From 46c78c24e1e7ba1f3bdae300b7b8f5bcea35b414 Mon Sep 17 00:00:00 2001 From: a dinosaur Date: Sun, 10 Dec 2023 11:28:52 +1100 Subject: [PATCH] neotools: adpcm-a partial rewrite --- neotools/CMakeLists.txt | 2 +- neotools/adpcm.c | 142 +++++++++++++++++----------------------- neotools/adpcm.h | 14 ++++ 3 files changed, 74 insertions(+), 84 deletions(-) create mode 100644 neotools/adpcm.h diff --git a/neotools/CMakeLists.txt b/neotools/CMakeLists.txt index a87d829..6d3c22a 100644 --- a/neotools/CMakeLists.txt +++ b/neotools/CMakeLists.txt @@ -4,7 +4,7 @@ if (USE_ZLIB AND NOT ZLIB_FOUND) message(FATAL_ERROR "USE_ZLIB specified but Zlib was not found") endif() -add_executable(adpcm adpcm.c) +add_executable(adpcm adpcm.h adpcm.c) set_property(TARGET adpcm PROPERTY C_STANDARD 99) target_compile_options(adpcm PRIVATE ${WARNINGS}) target_link_libraries(adpcm Common::wave $<$:m>) diff --git a/neotools/adpcm.c b/neotools/adpcm.c index 449420f..a11bcc1 100644 --- a/neotools/adpcm.c +++ b/neotools/adpcm.c @@ -2,11 +2,12 @@ * original ADPCM to PCM converter v 1.01 By MARTINEZ Fabrice aka SNK of SUPREMACY */ +#include "adpcm.h" +#include "util.h" +#include "wave.h" #include #include #include -#include "util.h" -#include "wave.h" #define BUFFER_SIZE (1024 * 256) #define ADPCMA_VOLUME_RATE 1 @@ -14,66 +15,56 @@ #define ADPCMA_DECODE_MIN (-(ADPCMA_DECODE_RANGE * ADPCMA_VOLUME_RATE)) #define ADPCMA_DECODE_MAX ((ADPCMA_DECODE_RANGE * ADPCMA_VOLUME_RATE) - 1) -static int decode_tableA1[16] = + +static const int decodeTableA1[16] = { -1 * 16, -1 * 16, -1 * 16, -1 * 16, 2 * 16, 5 * 16, 7 * 16, 9 * 16, -1 * 16, -1 * 16, -1 * 16, -1 * 16, 2 * 16, 5 * 16, 7 * 16, 9 * 16 }; -static int jedi_table[49 * 16]; -static int cursignal; -static int delta; - -void adpcm_init(void); -void adpcm_decode(void *, void *, int); - -int main(int argc, char *argv[]) +int main(int argc, char* argv[]) { - FILE *InputFile, *OutputFile; - void *InputBuffer, *OutputBuffer; - int bytesRead; - unsigned int Filelen; - - puts("**** ADPCM to PCM converter v 1.01\n"); + fprintf(stderr, "**** ADPCM to PCM converter v 1.01\n\n"); if (argc != 3) { - puts("USAGE: adpcm "); - exit(-1); + fprintf(stderr, "USAGE: adpcm \n"); + return -1; } - InputFile = fopen(argv[1], "rb"); - if (!InputFile) + FILE* inFile = fopen(argv[1], "rb"); + if (!inFile) { - printf("Could not open inputfile %s\n", argv[1]); - exit(-2); + fprintf(stderr, "Could not open inputfile %s\n", argv[1]); + return -2; } - OutputFile = fopen(argv[2], "wb"); - if (!OutputFile) + FILE* outFile = fopen(argv[2], "wb"); + if (!outFile) { - printf("Could not open outputfile %s\n", argv[2]); - exit(-3); + fprintf(stderr, "Could not open outputfile %s\n", argv[2]); + return -3; } - InputBuffer = malloc(BUFFER_SIZE); + char* InputBuffer = malloc(BUFFER_SIZE); if (InputBuffer == NULL) { - printf("Could not allocate input buffer. (%d bytes)\n", BUFFER_SIZE); - exit(-4); + fprintf(stderr, "Could not allocate input buffer. (%d bytes)\n", BUFFER_SIZE); + return -4; } - OutputBuffer = malloc(BUFFER_SIZE * 10); + short* OutputBuffer = malloc(BUFFER_SIZE * 4); if (OutputBuffer == NULL) { - printf("Could not allocate output buffer. (%d bytes)\n", BUFFER_SIZE * 4); - exit(-5); + fprintf(stderr, "Could not allocate output buffer. (%d bytes)\n", BUFFER_SIZE * 4); + return -5; } - adpcm_init(); + AdpcmADecoderState decoder; + adpcmAInit(&decoder); - fseek(InputFile, 0, SEEK_END); - Filelen = ftell(InputFile); - fseek(InputFile, 0, SEEK_SET); + fseek(inFile, 0, SEEK_END); + unsigned int Filelen = ftell(inFile); + fseek(inFile, 0, SEEK_SET); // Write wave header waveWrite(&(const WaveSpec) @@ -83,79 +74,64 @@ int main(int argc, char *argv[]) .rate = 18500, .bytedepth = 2 }, - NULL, Filelen * 4, &waveStreamDefaultCb, OutputFile); + NULL, Filelen * 4, &waveStreamDefaultCb, outFile); // Convert ADPCM to PCM and write to wave + int bytesRead; do { - bytesRead = fread(InputBuffer, 1, BUFFER_SIZE, InputFile); + bytesRead = fread(InputBuffer, 1, BUFFER_SIZE, inFile); if (bytesRead > 0) { - adpcm_decode(InputBuffer, OutputBuffer, bytesRead); - fwrite(OutputBuffer, bytesRead * 4, 1, OutputFile); + adpcmADecode(&decoder, InputBuffer, OutputBuffer, bytesRead); + fwrite(OutputBuffer, bytesRead * 4, 1, outFile); } - } while (bytesRead == BUFFER_SIZE); + } + while (bytesRead == BUFFER_SIZE); - free(InputBuffer); free(OutputBuffer); - fclose(InputFile); - fclose(OutputFile); + free(InputBuffer); + fclose(outFile); + fclose(inFile); - puts("Done..."); + fprintf(stderr, "Done...\n"); return 0; } -void adpcm_init(void) +void adpcmAInit(AdpcmADecoderState* decoder) { - int step, nib; - - for (step = 0; step <= 48; step++) + for (int step = 0; step <= 48; step++) { - int stepval = floor(16.0 * pow (11.0 / 10.0, (double)step) * ADPCMA_VOLUME_RATE); + int stepval = floor(16.0 * pow(11.0 / 10.0, step) * ADPCMA_VOLUME_RATE); // Loop over all nibbles and compute the difference - for (nib = 0; nib < 16; nib++) + for (int nib = 0; nib < 16; nib++) { int value = stepval * ((nib & 0x07) * 2 + 1) / 8; - jedi_table[step * 16 + nib] = (nib & 0x08) ? -value : value; + decoder->jediTable[step * 16 + nib] = (nib & 0x08) ? -value : value; } } - delta = 0; - cursignal = 0; + decoder->delta = 0; + decoder->cursignal = 0; } -void adpcm_decode(void *InputBuffer, void *OutputBuffer, int Length) +void adpcmADecode(AdpcmADecoderState* restrict decoder, char* restrict in, short* restrict out, int len) { - char *in; - short *out; - int i, data, oldsignal; - - in = (char *)InputBuffer; - out = (short *)OutputBuffer; - - for (i = 0; i < Length; i++) + for (int i = 0; i < len * 2; ++i) { - data = ((*in) >> 4) & 0x0F; - oldsignal = cursignal; - cursignal = CLAMP(cursignal + (jedi_table[data + delta]), ADPCMA_DECODE_MIN, ADPCMA_DECODE_MAX); - delta = CLAMP(delta + decode_tableA1[data], 0 * 16, 48 * 16); - if (abs(oldsignal - cursignal) > 2500) + int data = (!(i & 0x1) ? ((*in) >> 4) : (*in++)) & 0x0F; + int oldsignal = decoder->cursignal; + decoder->cursignal = CLAMP(decoder->cursignal + decoder->jediTable[data + decoder->delta], + ADPCMA_DECODE_MIN, ADPCMA_DECODE_MAX); + decoder->delta = CLAMP(decoder->delta + decodeTableA1[data], 0 * 16, 48 * 16); + if (abs(oldsignal - decoder->cursignal) > 2500) { - fprintf(stderr, "WARNING: Suspicious signal evolution %06x,%06x pos:%06x delta:%06x\n", oldsignal, cursignal, i, delta); - fprintf(stderr, "data:%02x dx:%08x\n", data, jedi_table[data + delta]); + fprintf(stderr, "WARNING: Suspicious signal evolution %06x,%06x pos:%06x delta:%06x\n", + oldsignal, decoder->cursignal, i % len, decoder->delta); + fprintf(stderr, "data:%02x dx:%08x\n", + data, decoder->jediTable[data + decoder->delta]); } - *(out++) = (cursignal & 0xffff) * 32; - - data = (*in++) & 0x0F; - oldsignal = cursignal; - cursignal = CLAMP(cursignal + (jedi_table[data + delta]), ADPCMA_DECODE_MIN, ADPCMA_DECODE_MAX); - delta = CLAMP(delta + decode_tableA1[data], 0 * 16, 48 * 16); - if (abs(oldsignal - cursignal) > 2500) - { - fprintf(stderr, "WARNING: Suspicious signal evolution %06x,%06x pos:%06x delta:%06x\n", oldsignal, cursignal, i, delta); - fprintf(stderr, "data:%02x dx:%08x\n", data, jedi_table[data + delta]); - } - *(out++) = (cursignal & 0xffff) * 32; + *(out++) = (decoder->cursignal & 0xffff) * 32; } } diff --git a/neotools/adpcm.h b/neotools/adpcm.h new file mode 100644 index 0000000..75b80ac --- /dev/null +++ b/neotools/adpcm.h @@ -0,0 +1,14 @@ +#ifndef ADPCM_H +#define ADPCM_H + +typedef struct AdpcmADecoderState +{ + int jediTable[49 * 16]; + int cursignal; + int delta; +} AdpcmADecoderState; + +void adpcmAInit(AdpcmADecoderState* decoder); +void adpcmADecode(AdpcmADecoderState* restrict decoder, char* restrict in, short* restrict out, int len); + +#endif//ADPCM_H