diff --git a/extern/adpcm-xq-s/adpcm-lib.c b/extern/adpcm-xq-s/adpcm-lib.c index 73f41f05e..bd2016e5b 100644 --- a/extern/adpcm-xq-s/adpcm-lib.c +++ b/extern/adpcm-xq-s/adpcm-lib.c @@ -1,415 +1,408 @@ -//////////////////////////////////////////////////////////////////////////// -// **** ADPCM-XQ **** // -// Xtreme Quality ADPCM Encoder/Decoder // -// Copyright (c) 2022 David Bryant. // -// All Rights Reserved. // -// Distributed under the BSD Software License (see license.txt) // -//////////////////////////////////////////////////////////////////////////// - -#include -#include - -#include "adpcm-lib.h" - -/* This module encodes and decodes 4-bit ADPCM (DVI/IMA varient). ADPCM data is divided - * into independently decodable blocks that can be relatively small. The most common - * configuration is to store 505 samples into a 256 byte block, although other sizes are - * permitted as long as the number of samples is one greater than a multiple of 8. When - * multiple channels are present, they are interleaved in the data with an 8-sample - * interval. - */ - -/********************************* 4-bit ADPCM encoder ********************************/ - -#define CLIP(data, min, max) \ -if ((data) > (max)) data = max; \ -else if ((data) < (min)) data = min; - -/* step table */ -static const uint16_t step_table[89] = { - 7, 8, 9, 10, 11, 12, 13, 14, - 16, 17, 19, 21, 23, 25, 28, 31, - 34, 37, 41, 45, 50, 55, 60, 66, - 73, 80, 88, 97, 107, 118, 130, 143, - 157, 173, 190, 209, 230, 253, 279, 307, - 337, 371, 408, 449, 494, 544, 598, 658, - 724, 796, 876, 963, 1060, 1166, 1282, 1411, - 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024, - 3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484, - 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, - 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, - 32767 -}; - -/* step index tables */ -static const int index_table[] = { - /* adpcm data size is 4 */ - -1, -1, -1, -1, 2, 4, 6, 8 -}; - -struct adpcm_channel { - int32_t pcmdata; // current PCM value - int32_t error, weight, history [2]; // for noise shaping - int8_t index; // current index into step size table -}; - -struct adpcm_context { - struct adpcm_channel channels [2]; - int num_channels, lookahead, noise_shaping; -}; - -/* Create ADPCM encoder context with given number of channels. - * The returned pointer is used for subsequent calls. Note that - * even though an ADPCM encoder could be set up to encode frames - * independently, we use a context so that we can use previous - * data to improve quality (this encoder might not be optimal - * for encoding independent frames). - */ - -void *adpcm_create_context (int num_channels, int lookahead, int noise_shaping, int32_t initial_deltas [2]) -{ - struct adpcm_context *pcnxt = malloc (sizeof (struct adpcm_context)); - int ch, i; - - memset (pcnxt, 0, sizeof (struct adpcm_context)); - pcnxt->noise_shaping = noise_shaping; - pcnxt->num_channels = num_channels; - pcnxt->lookahead = lookahead; - - // given the supplied initial deltas, search for and store the closest index - - for (ch = 0; ch < num_channels; ++ch) - for (i = 0; i <= 88; i++) - if (i == 88 || initial_deltas [ch] < ((int32_t) step_table [i] + step_table [i+1]) / 2) { - pcnxt->channels [ch].index = i; - break; - } - - return pcnxt; -} - -/* Free the ADPCM encoder context. - */ - -void adpcm_free_context (void *p) -{ - struct adpcm_context *pcnxt = (struct adpcm_context *) p; - - free (pcnxt); -} - -static void set_decode_parameters (struct adpcm_context *pcnxt, int32_t *init_pcmdata, int8_t *init_index) -{ - int ch; - - for (ch = 0; ch < pcnxt->num_channels; ch++) { - pcnxt->channels[ch].pcmdata = init_pcmdata[ch]; - pcnxt->channels[ch].index = init_index[ch]; - } -} - -static void get_decode_parameters (struct adpcm_context *pcnxt, int32_t *init_pcmdata, int8_t *init_index) -{ - int ch; - - for (ch = 0; ch < pcnxt->num_channels; ch++) { - init_pcmdata[ch] = pcnxt->channels[ch].pcmdata; - init_index[ch] = pcnxt->channels[ch].index; - } -} - -static double minimum_error (const struct adpcm_channel *pchan, int nch, int32_t csample, const int16_t *sample, int depth, int *best_nibble) -{ - int32_t delta = csample - pchan->pcmdata; - struct adpcm_channel chan = *pchan; - uint16_t step = step_table[chan.index]; - uint16_t trial_delta = (step >> 3); - int nibble, nibble2; - double min_error; - - if (delta < 0) { - int mag = (-delta << 2) / step; - nibble = 0x8 | (mag > 7 ? 7 : mag); - } - else { - int mag = (delta << 2) / step; - nibble = mag > 7 ? 7 : mag; - } - - if (nibble & 1) trial_delta += (step >> 2); - if (nibble & 2) trial_delta += (step >> 1); - if (nibble & 4) trial_delta += step; - - if (nibble & 8) - chan.pcmdata -= trial_delta; - else - chan.pcmdata += trial_delta; - - CLIP(chan.pcmdata, -32768, 32767); - if (best_nibble) *best_nibble = nibble; - min_error = (double) (chan.pcmdata - csample) * (chan.pcmdata - csample); - - if (depth) { - chan.index += index_table[nibble & 0x07]; - CLIP(chan.index, 0, 88); - min_error += minimum_error (&chan, nch, sample [nch], sample + nch, depth - 1, NULL); - } - else - return min_error; - - for (nibble2 = 0; nibble2 <= 0xF; ++nibble2) { - double error; - - if (nibble2 == nibble) - continue; - - chan = *pchan; - trial_delta = (step >> 3); - - if (nibble2 & 1) trial_delta += (step >> 2); - if (nibble2 & 2) trial_delta += (step >> 1); - if (nibble2 & 4) trial_delta += step; - - if (nibble2 & 8) - chan.pcmdata -= trial_delta; - else - chan.pcmdata += trial_delta; - - CLIP(chan.pcmdata, -32768, 32767); - - error = (double) (chan.pcmdata - csample) * (chan.pcmdata - csample); - - if (error < min_error) { - chan.index += index_table[nibble2 & 0x07]; - CLIP(chan.index, 0, 88); - error += minimum_error (&chan, nch, sample [nch], sample + nch, depth - 1, NULL); - - if (error < min_error) { - if (best_nibble) *best_nibble = nibble2; - min_error = error; - } - } - } - - return min_error; -} - -static uint8_t encode_sample (struct adpcm_context *pcnxt, int ch, const int16_t *sample, int num_samples) -{ - struct adpcm_channel *pchan = pcnxt->channels + ch; - int32_t csample = *sample; - int depth = num_samples - 1, nibble; - uint16_t step = step_table[pchan->index]; - uint16_t trial_delta = (step >> 3); - - if (pcnxt->noise_shaping == NOISE_SHAPING_DYNAMIC) { - int32_t sam = (3 * pchan->history [0] - pchan->history [1]) >> 1; - int32_t temp = csample - (((pchan->weight * sam) + 512) >> 10); - int32_t shaping_weight; - - if (sam && temp) pchan->weight -= (((sam ^ temp) >> 29) & 4) - 2; - pchan->history [1] = pchan->history [0]; - pchan->history [0] = csample; - - shaping_weight = (pchan->weight < 256) ? 1024 : 1536 - (pchan->weight * 2); - temp = -((shaping_weight * pchan->error + 512) >> 10); - - if (shaping_weight < 0 && temp) { - if (temp == pchan->error) - temp = (temp < 0) ? temp + 1 : temp - 1; - - pchan->error = -csample; - csample += temp; - } - else - pchan->error = -(csample += temp); - } - else if (pcnxt->noise_shaping == NOISE_SHAPING_STATIC) - pchan->error = -(csample -= pchan->error); - - if (depth > pcnxt->lookahead) - depth = pcnxt->lookahead; - - minimum_error (pchan, pcnxt->num_channels, csample, sample, depth, &nibble); - - if (nibble & 1) trial_delta += (step >> 2); - if (nibble & 2) trial_delta += (step >> 1); - if (nibble & 4) trial_delta += step; - - if (nibble & 8) - pchan->pcmdata -= trial_delta; - else - pchan->pcmdata += trial_delta; - - pchan->index += index_table[nibble & 0x07]; - CLIP(pchan->index, 0, 88); - CLIP(pchan->pcmdata, -32768, 32767); - - if (pcnxt->noise_shaping) - pchan->error += pchan->pcmdata; - - return nibble; -} - -static void encode_chunks (struct adpcm_context *pcnxt, uint8_t **outbuf, size_t *outbufsize, const int16_t **inbuf, int inbufcount) -{ - const int16_t *pcmbuf; - int chunks, ch, i; - - chunks = (inbufcount - 1) / 8; - *outbufsize += (chunks * 4) * pcnxt->num_channels; - - while (chunks--) - { - for (ch = 0; ch < pcnxt->num_channels; ch++) - { - pcmbuf = *inbuf + ch; - - for (i = 0; i < 4; i++) { - **outbuf = encode_sample (pcnxt, ch, pcmbuf, chunks * 8 + (3 - i) * 2 + 2); - pcmbuf += pcnxt->num_channels; - **outbuf |= encode_sample (pcnxt, ch, pcmbuf, chunks * 8 + (3 - i) * 2 + 1) << 4; - pcmbuf += pcnxt->num_channels; - (*outbuf)++; - } - } - - *inbuf += 8 * pcnxt->num_channels; - } -} - -/* Encode a block of 16-bit PCM data into 4-bit ADPCM. - * - * Parameters: - * p the context returned by adpcm_begin() - * outbuf destination buffer - * outbufsize pointer to variable where the number of bytes written - * will be stored - * inbuf source PCM samples - * inbufcount number of composite PCM samples provided (note: this is - * the total number of 16-bit samples divided by the number - * of channels) - * - * Returns 1 (for success as there is no error checking) - */ - -int adpcm_encode_block (void *p, uint8_t *outbuf, size_t *outbufsize, const int16_t *inbuf, int inbufcount) -{ - struct adpcm_context *pcnxt = (struct adpcm_context *) p; - int32_t init_pcmdata[2]; - int8_t init_index[2]; - int ch; - - *outbufsize = 0; - - if (!inbufcount) - return 1; - - get_decode_parameters(pcnxt, init_pcmdata, init_index); - - for (ch = 0; ch < pcnxt->num_channels; ch++) { - init_pcmdata[ch] = *inbuf++; - outbuf[0] = init_pcmdata[ch]; - outbuf[1] = init_pcmdata[ch] >> 8; - outbuf[2] = init_index[ch]; - outbuf[3] = 0; - - outbuf += 4; - *outbufsize += 4; - } - - set_decode_parameters(pcnxt, init_pcmdata, init_index); - encode_chunks (pcnxt, &outbuf, outbufsize, &inbuf, inbufcount); - - return 1; -} - -/********************************* 4-bit ADPCM decoder ********************************/ - -/* Decode the block of ADPCM data into PCM. This requires no context because ADPCM blocks - * are indeppendently decodable. This assumes that a single entire block is always decoded; - * it must be called multiple times for multiple blocks and cannot resume in the middle of a - * block. - * - * Parameters: - * outbuf destination for interleaved PCM samples - * inbuf source ADPCM block - * inbufsize size of source ADPCM block - * channels number of channels in block (must be determined from other context) - * - * Returns number of converted composite samples (total samples divided by number of channels) - */ - -int adpcm_decode_block (int16_t *outbuf, const uint8_t *inbuf, size_t inbufsize, size_t outbufsize, int channels) -{ - int ch, samples = 1, chunks; - int32_t pcmdata[2]; - int8_t index[2]; - - if (inbufsize < (uint32_t) channels * 4) - return 0; - - for (ch = 0; ch < channels; ch++) { - *outbuf++ = pcmdata[ch] = (int16_t) (inbuf [0] | (inbuf [1] << 8)); - index[ch] = inbuf [2]; - - if (index [ch] < 0 || index [ch] > 88 || inbuf [3]) // sanitize the input a little... - return 0; - - inbufsize -= 4; - inbuf += 4; - } - - chunks = inbufsize / (channels * 4); - samples += chunks * 8; - - while (chunks--) { - int ch, i; - - for (ch = 0; ch < channels; ++ch) { - - for (i = 0; i < 4; ++i) { - uint16_t step = step_table [index [ch]], delta = step >> 3; - - if (*inbuf & 1) delta += (step >> 2); - if (*inbuf & 2) delta += (step >> 1); - if (*inbuf & 4) delta += step; - - if (*inbuf & 8) - pcmdata[ch] -= delta; - else - pcmdata[ch] += delta; - - index[ch] += index_table [*inbuf & 0x7]; - CLIP(index[ch], 0, 88); - CLIP(pcmdata[ch], -32768, 32767); - outbuf [i * 2 * channels] = pcmdata[ch]; - - step = step_table [index [ch]]; delta = step >> 3; - - if (*inbuf & 0x10) delta += (step >> 2); - if (*inbuf & 0x20) delta += (step >> 1); - if (*inbuf & 0x40) delta += step; - - if (*inbuf & 0x80) - pcmdata[ch] -= delta; - else - pcmdata[ch] += delta; - - index[ch] += index_table [(*inbuf >> 4) & 0x7]; - CLIP(index[ch], 0, 88); - CLIP(pcmdata[ch], -32768, 32767); - outbuf [(i * 2 + 1) * channels] = pcmdata[ch]; - - inbuf++; - } - - outbuf++; - } - - outbuf += channels * 7; - } - - return samples; -} - +//////////////////////////////////////////////////////////////////////////// +// **** ADPCM-XQ **** // +// Xtreme Quality ADPCM Encoder/Decoder // +// Copyright (c) 2022 David Bryant. // +// All Rights Reserved. // +// Distributed under the BSD Software License (see license.txt) // +//////////////////////////////////////////////////////////////////////////// + +#include +#include + +#include "adpcm-lib.h" + +/* This module encodes and decodes 4-bit ADPCM (DVI/IMA varient). ADPCM data is divided + * into independently decodable blocks that can be relatively small. The most common + * configuration is to store 505 samples into a 256 byte block, although other sizes are + * permitted as long as the number of samples is one greater than a multiple of 8. When + * multiple channels are present, they are interleaved in the data with an 8-sample + * interval. + */ + +/********************************* 4-bit ADPCM encoder ********************************/ + +#define CLIP(data, min, max) \ +if ((data) > (max)) data = max; \ +else if ((data) < (min)) data = min; + +/* step table */ +static const uint16_t step_table[89] = { + 7, 8, 9, 10, 11, 12, 13, 14, + 16, 17, 19, 21, 23, 25, 28, 31, + 34, 37, 41, 45, 50, 55, 60, 66, + 73, 80, 88, 97, 107, 118, 130, 143, + 157, 173, 190, 209, 230, 253, 279, 307, + 337, 371, 408, 449, 494, 544, 598, 658, + 724, 796, 876, 963, 1060, 1166, 1282, 1411, + 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024, + 3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484, + 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, + 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, + 32767 +}; + +/* step index tables */ +static const int index_table[] = { + /* adpcm data size is 4 */ + -1, -1, -1, -1, 2, 4, 6, 8 +}; + +struct adpcm_channel { + int32_t pcmdata; // current PCM value + int32_t error, weight, history [2]; // for noise shaping + int8_t index; // current index into step size table +}; + +struct adpcm_context { + struct adpcm_channel channels [2]; + int num_channels, lookahead, noise_shaping; +}; + +/* Create ADPCM encoder context with given number of channels. + * The returned pointer is used for subsequent calls. Note that + * even though an ADPCM encoder could be set up to encode frames + * independently, we use a context so that we can use previous + * data to improve quality (this encoder might not be optimal + * for encoding independent frames). + */ + +void *adpcm_create_context (int num_channels, int lookahead, int noise_shaping, int32_t initial_deltas [2]) +{ + struct adpcm_context *pcnxt = malloc (sizeof (struct adpcm_context)); + int ch, i; + + memset (pcnxt, 0, sizeof (struct adpcm_context)); + pcnxt->noise_shaping = noise_shaping; + pcnxt->num_channels = num_channels; + pcnxt->lookahead = lookahead; + + // given the supplied initial deltas, search for and store the closest index + + for (ch = 0; ch < num_channels; ++ch) + for (i = 0; i <= 88; i++) + if (i == 88 || initial_deltas [ch] < ((int32_t) step_table [i] + step_table [i+1]) / 2) { + pcnxt->channels [ch].index = i; + break; + } + + return pcnxt; +} + +/* Free the ADPCM encoder context. + */ + +void adpcm_free_context (void *p) +{ + struct adpcm_context *pcnxt = (struct adpcm_context *) p; + + free (pcnxt); +} + +static void set_decode_parameters (struct adpcm_context *pcnxt, int32_t *init_pcmdata, int8_t *init_index) +{ + int ch; + + for (ch = 0; ch < pcnxt->num_channels; ch++) { + pcnxt->channels[ch].pcmdata = init_pcmdata[ch]; + pcnxt->channels[ch].index = init_index[ch]; + } +} + +static void get_decode_parameters (struct adpcm_context *pcnxt, int32_t *init_pcmdata, int8_t *init_index) +{ + int ch; + + for (ch = 0; ch < pcnxt->num_channels; ch++) { + init_pcmdata[ch] = pcnxt->channels[ch].pcmdata; + init_index[ch] = pcnxt->channels[ch].index; + } +} + +static double minimum_error (const struct adpcm_channel *pchan, int nch, int32_t csample, const int16_t *sample, int depth, int *best_nibble) +{ + int32_t delta = csample - pchan->pcmdata; + struct adpcm_channel chan = *pchan; + uint16_t step = step_table[chan.index]; + uint16_t trial_delta = (step >> 3); + int nibble, nibble2; + double min_error; + + if (delta < 0) { + int mag = (-delta << 2) / step; + nibble = 0x8 | (mag > 7 ? 7 : mag); + } + else { + int mag = (delta << 2) / step; + nibble = mag > 7 ? 7 : mag; + } + + if (nibble & 1) trial_delta += (step >> 2); + if (nibble & 2) trial_delta += (step >> 1); + if (nibble & 4) trial_delta += step; + + if (nibble & 8) + chan.pcmdata -= trial_delta; + else + chan.pcmdata += trial_delta; + + CLIP(chan.pcmdata, -32768, 32767); + if (best_nibble) *best_nibble = nibble; + min_error = (double) (chan.pcmdata - csample) * (chan.pcmdata - csample); + + if (depth) { + chan.index += index_table[nibble & 0x07]; + CLIP(chan.index, 0, 88); + min_error += minimum_error (&chan, nch, sample [nch], sample + nch, depth - 1, NULL); + } + else + return min_error; + + for (nibble2 = 0; nibble2 <= 0xF; ++nibble2) { + double error; + + if (nibble2 == nibble) + continue; + + chan = *pchan; + trial_delta = (step >> 3); + + if (nibble2 & 1) trial_delta += (step >> 2); + if (nibble2 & 2) trial_delta += (step >> 1); + if (nibble2 & 4) trial_delta += step; + + if (nibble2 & 8) + chan.pcmdata -= trial_delta; + else + chan.pcmdata += trial_delta; + + CLIP(chan.pcmdata, -32768, 32767); + + error = (double) (chan.pcmdata - csample) * (chan.pcmdata - csample); + + if (error < min_error) { + chan.index += index_table[nibble2 & 0x07]; + CLIP(chan.index, 0, 88); + error += minimum_error (&chan, nch, sample [nch], sample + nch, depth - 1, NULL); + + if (error < min_error) { + if (best_nibble) *best_nibble = nibble2; + min_error = error; + } + } + } + + return min_error; +} + +static uint8_t encode_sample (struct adpcm_context *pcnxt, int ch, const int16_t *sample, int num_samples) +{ + struct adpcm_channel *pchan = pcnxt->channels + ch; + int32_t csample = *sample; + int depth = num_samples - 1, nibble; + uint16_t step = step_table[pchan->index]; + uint16_t trial_delta = (step >> 3); + + if (pcnxt->noise_shaping == NOISE_SHAPING_DYNAMIC) { + int32_t sam = (3 * pchan->history [0] - pchan->history [1]) >> 1; + int32_t temp = csample - (((pchan->weight * sam) + 512) >> 10); + int32_t shaping_weight; + + if (sam && temp) pchan->weight -= (((sam ^ temp) >> 29) & 4) - 2; + pchan->history [1] = pchan->history [0]; + pchan->history [0] = csample; + + shaping_weight = (pchan->weight < 256) ? 1024 : 1536 - (pchan->weight * 2); + temp = -((shaping_weight * pchan->error + 512) >> 10); + + if (shaping_weight < 0 && temp) { + if (temp == pchan->error) + temp = (temp < 0) ? temp + 1 : temp - 1; + + pchan->error = -csample; + csample += temp; + } + else + pchan->error = -(csample += temp); + } + else if (pcnxt->noise_shaping == NOISE_SHAPING_STATIC) + pchan->error = -(csample -= pchan->error); + + if (depth > pcnxt->lookahead) + depth = pcnxt->lookahead; + + minimum_error (pchan, pcnxt->num_channels, csample, sample, depth, &nibble); + + if (nibble & 1) trial_delta += (step >> 2); + if (nibble & 2) trial_delta += (step >> 1); + if (nibble & 4) trial_delta += step; + + if (nibble & 8) + pchan->pcmdata -= trial_delta; + else + pchan->pcmdata += trial_delta; + + pchan->index += index_table[nibble & 0x07]; + CLIP(pchan->index, 0, 88); + CLIP(pchan->pcmdata, -32768, 32767); + + if (pcnxt->noise_shaping) + pchan->error += pchan->pcmdata; + + return nibble; +} + +static void encode_chunks (struct adpcm_context *pcnxt, uint8_t **outbuf, size_t *outbufsize, const int16_t **inbuf, int inbufcount) +{ + const int16_t *pcmbuf; + int chunks, ch, i; + + chunks = (inbufcount - 1) / 8; + *outbufsize += (chunks * 4) * pcnxt->num_channels; + + while (chunks--) + { + for (ch = 0; ch < pcnxt->num_channels; ch++) + { + pcmbuf = *inbuf + ch; + + for (i = 0; i < 4; i++) { + **outbuf = encode_sample (pcnxt, ch, pcmbuf, chunks * 8 + (3 - i) * 2 + 2); + pcmbuf += pcnxt->num_channels; + **outbuf |= encode_sample (pcnxt, ch, pcmbuf, chunks * 8 + (3 - i) * 2 + 1) << 4; + pcmbuf += pcnxt->num_channels; + (*outbuf)++; + } + } + + *inbuf += 8 * pcnxt->num_channels; + } +} + +/* Encode a block of 16-bit PCM data into 4-bit ADPCM. + * + * Parameters: + * p the context returned by adpcm_begin() + * outbuf destination buffer + * outbufsize pointer to variable where the number of bytes written + * will be stored + * inbuf source PCM samples + * inbufcount number of composite PCM samples provided (note: this is + * the total number of 16-bit samples divided by the number + * of channels) + * + * Returns 1 (for success as there is no error checking) + */ + +int adpcm_encode_block (void *p, uint8_t *outbuf, size_t *outbufsize, const int16_t *inbuf, int inbufcount) +{ + struct adpcm_context *pcnxt = (struct adpcm_context *) p; + int32_t init_pcmdata[2]; + int8_t init_index[2]; + int ch; + + *outbufsize = 0; + + if (!inbufcount) + return 1; + + get_decode_parameters(pcnxt, init_pcmdata, init_index); + + for (ch = 0; ch < pcnxt->num_channels; ch++) { + init_pcmdata[ch] = *inbuf++; + outbuf[0] = init_pcmdata[ch]; + outbuf[1] = init_pcmdata[ch] >> 8; + outbuf[2] = init_index[ch]; + outbuf[3] = 0; + + outbuf += 4; + *outbufsize += 4; + } + + set_decode_parameters(pcnxt, init_pcmdata, init_index); + encode_chunks (pcnxt, &outbuf, outbufsize, &inbuf, inbufcount); + + return 1; +} + +/********************************* 4-bit ADPCM decoder ********************************/ + +/* Decode the block of ADPCM data into PCM. This requires no context because ADPCM blocks + * are indeppendently decodable. This assumes that a single entire block is always decoded; + * it must be called multiple times for multiple blocks and cannot resume in the middle of a + * block. + * + * Parameters: + * outbuf destination for interleaved PCM samples + * inbuf source ADPCM block + * inbufsize size of source ADPCM block + * channels number of channels in block (must be determined from other context) + * + * Returns number of converted composite samples (total samples divided by number of channels) + */ + +int adpcm_decode_block (int16_t *outbuf, const uint8_t *inbuf, size_t inbufsize, size_t outbufsize) +{ + int samples = 1, chunks; + int32_t pcmdata[2]; + int8_t index[2]; + + if (inbufsize < 4) + return 0; + + *outbuf++ = pcmdata[0] = (int16_t) (inbuf [0] | (inbuf [1] << 8)); + index[0] = inbuf [2]; + + if (index [0] < 0 || index [0] > 88 || inbuf [3]) // sanitize the input a little... + return 0; + + inbufsize -= 4; + inbuf += 4; + + chunks = inbufsize / 4; + samples += chunks * 8; + + while (chunks--) { + int i; + + for (i = 0; i < 4; ++i) { + uint16_t step = step_table [index [0]], delta = step >> 3; + + if (*inbuf & 1) delta += (step >> 2); + if (*inbuf & 2) delta += (step >> 1); + if (*inbuf & 4) delta += step; + + if (*inbuf & 8) + pcmdata[0] -= delta; + else + pcmdata[0] += delta; + + index[0] += index_table [*inbuf & 0x7]; + CLIP(index[0], 0, 88); + CLIP(pcmdata[0], -32768, 32767); + outbuf [i * 2] = pcmdata[0]; + + step = step_table [index [0]]; delta = step >> 3; + + if (*inbuf & 0x10) delta += (step >> 2); + if (*inbuf & 0x20) delta += (step >> 1); + if (*inbuf & 0x40) delta += step; + + if (*inbuf & 0x80) + pcmdata[0] -= delta; + else + pcmdata[0] += delta; + + index[0] += index_table [(*inbuf >> 4) & 0x7]; + CLIP(index[0], 0, 88); + CLIP(pcmdata[0], -32768, 32767); + outbuf [(i * 2 + 1)] = pcmdata[0]; + + inbuf++; + } + + outbuf += 8; + } + + return samples; +} + diff --git a/extern/adpcm-xq-s/adpcm-lib.h b/extern/adpcm-xq-s/adpcm-lib.h index 0ef8547d3..4d7a1210a 100644 --- a/extern/adpcm-xq-s/adpcm-lib.h +++ b/extern/adpcm-xq-s/adpcm-lib.h @@ -1,44 +1,44 @@ -//////////////////////////////////////////////////////////////////////////// -// **** ADPCM-XQ **** // -// Xtreme Quality ADPCM Encoder/Decoder // -// Copyright (c) 2015 David Bryant. // -// All Rights Reserved. // -// Distributed under the BSD Software License (see license.txt) // -//////////////////////////////////////////////////////////////////////////// - -#ifndef ADPCMLIB_H_ -#define ADPCMLIB_H_ - -#define NOISE_SHAPING_OFF 0 // flat noise (no shaping) -#define NOISE_SHAPING_STATIC 1 // first-order highpass shaping -#define NOISE_SHAPING_DYNAMIC 2 // dynamically tilted noise based on signal - -#if defined(_MSC_VER) && _MSC_VER < 1600 -typedef unsigned __int64 uint64_t; -typedef unsigned __int32 uint32_t; -typedef unsigned __int16 uint16_t; -typedef unsigned __int8 uint8_t; -typedef __int64 int64_t; -typedef __int32 int32_t; -typedef __int16 int16_t; -typedef __int8 int8_t; -#else -#include -#endif - -#ifdef __cplusplus -extern "C" { -#endif - - -void *adpcm_create_context (int num_channels, int lookahead, int noise_shaping, int32_t initial_deltas [2]); -int adpcm_encode_block (void *p, uint8_t *outbuf, size_t *outbufsize, const int16_t *inbuf, int inbufcount); -int adpcm_decode_block (int16_t *outbuf, const uint8_t *inbuf, size_t inbufsize, size_t outbufsize, int channels); -void adpcm_free_context (void *p); - -#ifdef __cplusplus -} -#endif - - -#endif /* ADPCMLIB_H_ */ +//////////////////////////////////////////////////////////////////////////// +// **** ADPCM-XQ **** // +// Xtreme Quality ADPCM Encoder/Decoder // +// Copyright (c) 2015 David Bryant. // +// All Rights Reserved. // +// Distributed under the BSD Software License (see license.txt) // +//////////////////////////////////////////////////////////////////////////// + +#ifndef ADPCMLIB_H_ +#define ADPCMLIB_H_ + +#define NOISE_SHAPING_OFF 0 // flat noise (no shaping) +#define NOISE_SHAPING_STATIC 1 // first-order highpass shaping +#define NOISE_SHAPING_DYNAMIC 2 // dynamically tilted noise based on signal + +#if defined(_MSC_VER) && _MSC_VER < 1600 +typedef unsigned __int64 uint64_t; +typedef unsigned __int32 uint32_t; +typedef unsigned __int16 uint16_t; +typedef unsigned __int8 uint8_t; +typedef __int64 int64_t; +typedef __int32 int32_t; +typedef __int16 int16_t; +typedef __int8 int8_t; +#else +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + +void *adpcm_create_context (int num_channels, int lookahead, int noise_shaping, int32_t initial_deltas [2]); +int adpcm_encode_block (void *p, uint8_t *outbuf, size_t *outbufsize, const int16_t *inbuf, int inbufcount); +int adpcm_decode_block (int16_t *outbuf, const uint8_t *inbuf, size_t inbufsize, size_t outbufsize); +void adpcm_free_context (void *p); + +#ifdef __cplusplus +} +#endif + + +#endif /* ADPCMLIB_H_ */ diff --git a/src/engine/sample.cpp b/src/engine/sample.cpp index 6dfcf4f69..a7e542c86 100644 --- a/src/engine/sample.cpp +++ b/src/engine/sample.cpp @@ -1289,7 +1289,7 @@ void DivSample::render(unsigned int formatMask) { } break; case DIV_SAMPLE_DEPTH_IMA_ADPCM: // IMA ADPCM - if (adpcm_decode_block(data16,dataIMA,lengthIMA,samples,1)==0) logE("oh crap!"); + if (adpcm_decode_block(data16,dataIMA,lengthIMA,samples)==0) logE("oh crap!"); break; default: return;