Files
2025-08-27 09:51:58 +01:00

1192 lines
40 KiB
C

#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <math.h>
#include "adpcm_code.h"
/* 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
};
static const int index_table_3bit[] = {
/* adpcm data size is 3 */
-1, -1, 1, 2
};
static const int index_table_5bit[] = {
/* adpcm data size is 5 */
-1, -1, -1, -1, -1, -1, -1, -1, 1, 2, 4, 6, 8, 10, 13, 16
};
//void adpcm_downsamlpe_2(int16_t *buf, uint32_t size)
//{
// int temp = 0;
// for(uint32_t i=0; i<(size/2); i++) {
// buf[i] = buf[2*i];
// }
//}
//void adpcm_upsamlpe_2(int16_t *buf, uint32_t size)
//{
// int temp = 0;
// memcpy(buf+size,buf,size*2);
// for(uint32_t i=0; i<size; i++) {
// buf[2*i] = buf[size+i];
// buf[2*i+1] = buf[2*i];
// }
//}
static inline int32_t noise_shape (struct adpcm_channel *pchan, int32_t sample)
{
int32_t temp = -((pchan->shaping_weight * pchan->error + 512) >> 10);
if (pchan->shaping_weight < 0 && temp) {
if (temp == pchan->error)
temp = (temp < 0) ? temp + 1 : temp - 1;
pchan->error = -sample;
sample += temp;
}
else
pchan->error = -(sample += temp);
return sample;
}
static rms_error_t min_error_4bit (const struct adpcm_channel *pchan, int nch, int32_t csample, const int16_t *psample, int flags, int *best_nibble, rms_error_t max_error)
{
int32_t delta = csample - pchan->pcmdata, csample2;
struct adpcm_channel chan = *pchan;
uint16_t step = step_table[chan.index];
uint16_t trial_delta = (step >> 3);
int nibble, testnbl;
rms_error_t min_error;
// this odd-looking code always generates the nibble value with the least error,
// regardless of step size (which was not true previously)
if (delta < 0) {
int mag = ((-delta << 2) + (step & 3) + ((step & 1) << 1)) / step;
nibble = 0x8 | (mag > 7 ? 7 : mag);
}
else {
int mag = ((delta << 2) + (step & 3) + ((step & 1) << 1)) / 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 = (rms_error_t) (chan.pcmdata - csample) * (chan.pcmdata - csample);
// if we're at a leaf, or we're not at a leaf but have already exceeded the error limit, return
if (!(flags & LOOKAHEAD_DEPTH) || min_error >= max_error)
return min_error;
// otherwise we execute that naively closest nibble and search deeper for improvement
chan.index += index_table[nibble & 0x07];
CLIP(chan.index, 0, 88);
if (flags & NOISE_SHAPING_ENABLED) {
chan.error += chan.pcmdata;
csample2 = noise_shape (&chan, psample [nch]);
}
else
csample2 = psample [nch];
min_error += min_error_4bit (&chan, nch, csample2, psample + nch, flags - 1, NULL, max_error - min_error);
// min_error is the error (from here to the leaf) for the naively closest nibble.
// Unless we've been told not to try, we may be able to improve on that by choosing
// an alternative (not closest) nibble.
if (flags & LOOKAHEAD_NO_BRANCHING)
return min_error;
for (testnbl = 0; testnbl <= 0xF; ++testnbl) {
rms_error_t error, threshold;
if (testnbl == nibble) // don't do the same value again
continue;
// we execute this branch if:
// 1. we're doing an exhaustive search, or
// 2. the test value is one of the maximum values (i.e., 0x7 or 0xf), or
// 3. the test value's delta is within three of the initial estimate's delta
if (flags & LOOKAHEAD_EXHAUSTIVE || !(~testnbl & 0x7) || abs (NIBBLE_TO_DELTA (4,nibble) - NIBBLE_TO_DELTA (4,testnbl)) <= 3) {
trial_delta = (step >> 3);
chan = *pchan;
if (testnbl & 1) trial_delta += (step >> 2);
if (testnbl & 2) trial_delta += (step >> 1);
if (testnbl & 4) trial_delta += step;
if (testnbl & 8)
chan.pcmdata -= trial_delta;
else
chan.pcmdata += trial_delta;
CLIP(chan.pcmdata, -32768, 32767);
error = (rms_error_t) (chan.pcmdata - csample) * (chan.pcmdata - csample);
threshold = max_error < min_error ? max_error : min_error;
if (error < threshold) {
chan.index += index_table[testnbl & 0x07];
CLIP(chan.index, 0, 88);
if (flags & NOISE_SHAPING_ENABLED) {
chan.error += chan.pcmdata;
csample2 = noise_shape (&chan, psample [nch]);
}
else
csample2 = psample [nch];
error += min_error_4bit (&chan, nch, csample2, psample + nch, flags - 1, NULL, threshold - error);
if (error < min_error) {
if (best_nibble) *best_nibble = testnbl;
min_error = error;
}
}
}
}
return min_error;
}
static rms_error_t min_error_2bit (const struct adpcm_channel *pchan, int nch, int32_t csample, const int16_t *psample, int flags, int *best_nibble, rms_error_t max_error)
{
int32_t delta = csample - pchan->pcmdata, csample2;
struct adpcm_channel chan = *pchan;
uint16_t step = step_table[chan.index];
int nibble, testnbl;
rms_error_t min_error;
if (delta < 0) {
if (-delta >= step) {
chan.pcmdata -= step + (step >> 1);
nibble = 3;
}
else {
chan.pcmdata -= step >> 1;
nibble = 2;
}
}
else
chan.pcmdata += step * ((nibble = delta >= step)) + (step >> 1);
CLIP(chan.pcmdata, -32768, 32767);
if (best_nibble) *best_nibble = nibble;
min_error = (rms_error_t) (chan.pcmdata - csample) * (chan.pcmdata - csample);
// if we're at a leaf, or we're not at a leaf but have already exceeded the error limit, return
if (!(flags & LOOKAHEAD_DEPTH) || min_error >= max_error)
return min_error;
// otherwise we execute that naively closest nibble and search deeper for improvement
chan.index += (nibble & 1) * 3 - 1;
CLIP(chan.index, 0, 88);
if (flags & NOISE_SHAPING_ENABLED) {
chan.error += chan.pcmdata;
csample2 = noise_shape (&chan, psample [nch]);
}
else
csample2 = psample [nch];
min_error += min_error_2bit (&chan, nch, csample2, psample + nch, flags - 1, NULL, max_error - min_error);
// min_error is the error (from here to the leaf) for the naively closest nibble.
// Unless we've been told not to try, we may be able to improve on that by choosing
// an alternative (not closest) nibble.
if (flags & LOOKAHEAD_NO_BRANCHING)
return min_error;
for (testnbl = 0; testnbl <= 0x3; ++testnbl) {
rms_error_t error, threshold;
if (testnbl == nibble) // don't do the same value again
continue;
chan = *pchan;
if (testnbl & 2)
chan.pcmdata -= step * (testnbl & 1) + (step >> 1);
else
chan.pcmdata += step * (testnbl & 1) + (step >> 1);
CLIP(chan.pcmdata, -32768, 32767);
error = (rms_error_t) (chan.pcmdata - csample) * (chan.pcmdata - csample);
threshold = max_error < min_error ? max_error : min_error;
if (error < threshold) {
chan.index += (testnbl & 1) * 3 - 1;
CLIP(chan.index, 0, 88);
if (flags & NOISE_SHAPING_ENABLED) {
chan.error += chan.pcmdata;
csample2 = noise_shape (&chan, psample [nch]);
}
else
csample2 = psample [nch];
error += min_error_2bit (&chan, nch, csample2, psample + nch, flags - 1, NULL, threshold - error);
if (error < min_error) {
if (best_nibble) *best_nibble = testnbl;
min_error = error;
}
}
}
return min_error;
}
static rms_error_t min_error_3bit (const struct adpcm_channel *pchan, int nch, int32_t csample, const int16_t *psample, int flags, int *best_nibble, rms_error_t max_error)
{
int32_t delta = csample - pchan->pcmdata, csample2;
struct adpcm_channel chan = *pchan;
uint16_t step = step_table[chan.index];
uint16_t trial_delta = (step >> 2);
int nibble, testnbl;
rms_error_t min_error;
if (delta < 0) {
int mag = ((-delta << 1) + (step & 1)) / step;
nibble = 0x4 | (mag > 3 ? 3 : mag);
}
else {
int mag = ((delta << 1) + (step & 1)) / step;
nibble = mag > 3 ? 3 : mag;
}
if (nibble & 1) trial_delta += (step >> 1);
if (nibble & 2) trial_delta += step;
if (nibble & 4)
chan.pcmdata -= trial_delta;
else
chan.pcmdata += trial_delta;
CLIP(chan.pcmdata, -32768, 32767);
if (best_nibble) *best_nibble = nibble;
min_error = (rms_error_t) (chan.pcmdata - csample) * (chan.pcmdata - csample);
// if we're at a leaf, or we're not at a leaf but have already exceeded the error limit, return
if (!(flags & LOOKAHEAD_DEPTH) || min_error >= max_error)
return min_error;
// otherwise we execute that naively closest nibble and search deeper for improvement
chan.index += index_table_3bit[nibble & 0x03];
CLIP(chan.index, 0, 88);
if (flags & NOISE_SHAPING_ENABLED) {
chan.error += chan.pcmdata;
csample2 = noise_shape (&chan, psample [nch]);
}
else
csample2 = psample [nch];
min_error += min_error_3bit (&chan, nch, csample2, psample + nch, flags - 1, NULL, max_error - min_error);
// min_error is the error (from here to the leaf) for the naively closest nibble.
// Unless we've been told not to try, we may be able to improve on that by choosing
// an alternative (not closest) nibble.
if (flags & LOOKAHEAD_NO_BRANCHING)
return min_error;
for (testnbl = 0; testnbl <= 0x7; ++testnbl) {
rms_error_t error, threshold;
if (testnbl == nibble) // don't do the same value again
continue;
// we execute this branch if:
// 1. we're doing an exhaustive search, or
// 2. the test value is one of the maximum values (i.e., 0x3 or 0x7), or
// 3. the test value's delta is within two of the initial estimate's delta
if (flags & LOOKAHEAD_EXHAUSTIVE || !(~testnbl & 0x3) || abs (NIBBLE_TO_DELTA (3,nibble) - NIBBLE_TO_DELTA (3,testnbl)) <= 2) {
trial_delta = (step >> 2);
chan = *pchan;
if (testnbl & 1) trial_delta += (step >> 1);
if (testnbl & 2) trial_delta += step;
if (testnbl & 4)
chan.pcmdata -= trial_delta;
else
chan.pcmdata += trial_delta;
CLIP(chan.pcmdata, -32768, 32767);
error = (rms_error_t) (chan.pcmdata - csample) * (chan.pcmdata - csample);
threshold = max_error < min_error ? max_error : min_error;
if (error < threshold) {
chan.index += index_table_3bit[testnbl & 0x03];
CLIP(chan.index, 0, 88);
if (flags & NOISE_SHAPING_ENABLED) {
chan.error += chan.pcmdata;
csample2 = noise_shape (&chan, psample [nch]);
}
else
csample2 = psample [nch];
error += min_error_3bit (&chan, nch, csample2, psample + nch, flags - 1, NULL, threshold - error);
if (error < min_error) {
if (best_nibble) *best_nibble = testnbl;
min_error = error;
}
}
}
}
return min_error;
}
static rms_error_t min_error_5bit (const struct adpcm_channel *pchan, int nch, int32_t csample, const int16_t *psample, int flags, int *best_nibble, rms_error_t max_error)
{
static char comp_table [16] = { 0, 0, 0, 5, 0, 6, 4, 10, 0, 7, 6, 10, 4, 11, 11, 13 };
int32_t delta = csample - pchan->pcmdata, csample2;
struct adpcm_channel chan = *pchan;
uint16_t step = step_table[chan.index];
uint16_t trial_delta = (step >> 4);
int nibble, testnbl;
rms_error_t min_error;
if (delta < 0) {
int mag = ((-delta << 3) + comp_table [step & 0xf]) / step;
nibble = 0x10 | (mag > 0xf ? 0xf : mag);
}
else {
int mag = ((delta << 3) + comp_table [step & 0xf]) / step;
nibble = mag > 0xf ? 0xf : mag;
}
if (nibble & 1) trial_delta += (step >> 3);
if (nibble & 2) trial_delta += (step >> 2);
if (nibble & 4) trial_delta += (step >> 1);
if (nibble & 8) trial_delta += step;
if (nibble & 0x10)
chan.pcmdata -= trial_delta;
else
chan.pcmdata += trial_delta;
CLIP(chan.pcmdata, -32768, 32767);
if (best_nibble) *best_nibble = nibble;
min_error = (rms_error_t) (chan.pcmdata - csample) * (chan.pcmdata - csample);
// if we're at a leaf, or we're not at a leaf but have already exceeded the error limit, return
if (!(flags & LOOKAHEAD_DEPTH) || min_error >= max_error)
return min_error;
// otherwise we execute that naively closest nibble and search deeper for improvement
chan.index += index_table_5bit[nibble & 0x0f];
CLIP(chan.index, 0, 88);
if (flags & NOISE_SHAPING_ENABLED) {
chan.error += chan.pcmdata;
csample2 = noise_shape (&chan, psample [nch]);
}
else
csample2 = psample [nch];
min_error += min_error_5bit (&chan, nch, csample2, psample + nch, flags - 1, NULL, max_error - min_error);
// min_error is the error (from here to the leaf) for the naively closest nibble.
// Unless we've been told not to try, we may be able to improve on that by choosing
// an alternative (not closest) nibble.
if (flags & LOOKAHEAD_NO_BRANCHING)
return min_error;
for (testnbl = 0; testnbl <= 0x1F; ++testnbl) {
rms_error_t error, threshold;
if (testnbl == nibble) // don't do the same value again
continue;
// we execute this trial if:
// 1. we're doing an exhaustive search, or
// 2. the trial value is one of the four maximum values for the sign, or
// 3. the test value's delta is within three of the initial estimate's delta
if (flags & LOOKAHEAD_EXHAUSTIVE || (testnbl | 3) == (nibble | 0xf) || abs (NIBBLE_TO_DELTA (5,nibble) - NIBBLE_TO_DELTA (5,testnbl)) <= 3) {
trial_delta = (step >> 4);
chan = *pchan;
if (testnbl & 1) trial_delta += (step >> 3);
if (testnbl & 2) trial_delta += (step >> 2);
if (testnbl & 4) trial_delta += (step >> 1);
if (testnbl & 8) trial_delta += step;
if (testnbl & 0x10)
chan.pcmdata -= trial_delta;
else
chan.pcmdata += trial_delta;
CLIP(chan.pcmdata, -32768, 32767);
error = (rms_error_t) (chan.pcmdata - csample) * (chan.pcmdata - csample);
threshold = max_error < min_error ? max_error : min_error;
if (error < threshold) {
chan.index += index_table_5bit [testnbl & 0x0f];
CLIP(chan.index, 0, 88);
if (flags & NOISE_SHAPING_ENABLED) {
chan.error += chan.pcmdata;
csample2 = noise_shape (&chan, psample [nch]);
}
else
csample2 = psample [nch];
error += min_error_5bit (&chan, nch, csample2, psample + nch, flags - 1, NULL, threshold - error);
if (error < min_error) {
if (best_nibble) *best_nibble = testnbl;
min_error = error;
}
}
}
}
return min_error;
}
static uint8_t encode_sample (struct adpcm_context *pcnxt, int ch, int bps, const int16_t *psample, int num_samples)
{
struct adpcm_channel *pchan = pcnxt->channels + ch;
uint16_t step = step_table[pchan->index];
int flags = pcnxt->config_flags, nibble;
int32_t csample = *psample;
uint16_t trial_delta;
if (flags & NOISE_SHAPING_ENABLED)
csample = noise_shape (pchan, csample);
if ((flags & LOOKAHEAD_DEPTH) > num_samples - 1)
flags = (flags & ~LOOKAHEAD_DEPTH) + num_samples - 1;
if (bps == 2) {
min_error_2bit (pchan, pcnxt->num_channels, csample, psample, flags, &nibble, MAX_RMS_ERROR);
if (nibble & 2)
pchan->pcmdata -= step * (nibble & 1) + (step >> 1);
else
pchan->pcmdata += step * (nibble & 1) + (step >> 1);
pchan->index += (nibble & 1) * 3 - 1;
}
else if (bps == 3) {
min_error_3bit (pchan, pcnxt->num_channels, csample, psample, flags, &nibble, MAX_RMS_ERROR);
trial_delta = (step >> 2);
if (nibble & 1) trial_delta += (step >> 1);
if (nibble & 2) trial_delta += step;
if (nibble & 4)
pchan->pcmdata -= trial_delta;
else
pchan->pcmdata += trial_delta;
pchan->index += index_table_3bit[nibble & 0x03];
}
else if (bps == 4) {
min_error_4bit (pchan, pcnxt->num_channels, csample, psample, flags, &nibble, MAX_RMS_ERROR);
trial_delta = (step >> 3);
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];
}
else { // bps == 5
min_error_5bit (pchan, pcnxt->num_channels, csample, psample, flags, &nibble, MAX_RMS_ERROR);
trial_delta = (step >> 4);
if (nibble & 1) trial_delta += (step >> 3);
if (nibble & 2) trial_delta += (step >> 2);
if (nibble & 4) trial_delta += (step >> 1);
if (nibble & 8) trial_delta += step;
if (nibble & 0x10)
pchan->pcmdata -= trial_delta;
else
pchan->pcmdata += trial_delta;
pchan->index += index_table_5bit[nibble & 0x0f];
}
CLIP(pchan->index, 0, 88);
CLIP(pchan->pcmdata, -32768, 32767);
if (flags & NOISE_SHAPING_ENABLED)
pchan->error += pchan->pcmdata;
return nibble;
}
static void encode_chunks (struct adpcm_context *pcnxt, uint8_t *outbuf, int *outbufsize, const int16_t *inbuf, int inbufcount, int bps)
{
const int16_t *pcmbuf;
int ch;
for (ch = 0; ch < pcnxt->num_channels; ++ch) {
int shiftbits = 0, numbits = 0, i, j;
if (pcnxt->config_flags & NOISE_SHAPING_STATIC)
pcnxt->channels [ch].shaping_weight = pcnxt->static_shaping_weight;
pcmbuf = inbuf + ch;
for (j = i = 0; i < inbufcount; ++i) {
if (pcnxt->config_flags & NOISE_SHAPING_DYNAMIC)
pcnxt->channels [ch].shaping_weight = pcnxt->dynamic_shaping_array [i];
shiftbits |= encode_sample (pcnxt, ch, bps, pcmbuf, inbufcount - i) << numbits;
pcmbuf += pcnxt->num_channels;
if ((numbits += bps) >= 8) {
outbuf [(j & ~3) * pcnxt->num_channels + (ch * 4) + (j & 3)] = shiftbits;
shiftbits >>= 8;
numbits -= 8;
j++;
}
}
if (numbits)
outbuf [(j & ~3) * pcnxt->num_channels + (ch * 4) + (j & 3)] = shiftbits;
}
*outbufsize += (inbufcount * bps + 31) / 32 * pcnxt->num_channels * 4;
}
int adpcm_encode_block(struct adpcm_context *adpcm_cnxt, uint8_t *outbuf, int *outbufsize, const int16_t *inbuf, int inbufcount, int bps)
{
struct adpcm_context *pcnxt = (struct adpcm_context *) adpcm_cnxt;
*outbufsize = 0;
int ch = 0;
if(bps < 2 || bps > 5)
return 0;
if(!inbufcount)
return 0;
for (ch = 0; ch < pcnxt->num_channels; ch++)
pcnxt->channels[ch].pcmdata = *inbuf++;
inbufcount--;
if (inbufcount && (pcnxt->channels [0].index < 0 || (pcnxt->config_flags & LOOKAHEAD_DEPTH) >= 3)) {
int flags = 16 | LOOKAHEAD_NO_BRANCHING;
if ((flags & LOOKAHEAD_DEPTH) > inbufcount - 1)
flags = (flags & ~LOOKAHEAD_DEPTH) + inbufcount - 1;
for (ch = 0; ch < pcnxt->num_channels; ch++) {
rms_error_t min_error = MAX_RMS_ERROR;
rms_error_t error_per_index [89];
int best_index = 0, tindex;
for (tindex = 0; tindex <= 88; tindex++) {
struct adpcm_channel chan = pcnxt->channels [ch];
chan.index = tindex;
chan.shaping_weight = 0;
if (bps == 2)
error_per_index [tindex] = min_error_2bit (&chan, pcnxt->num_channels, inbuf [ch], inbuf + ch, flags, NULL, MAX_RMS_ERROR);
else if (bps == 3)
error_per_index [tindex] = min_error_3bit (&chan, pcnxt->num_channels, inbuf [ch], inbuf + ch, flags, NULL, MAX_RMS_ERROR);
else if (bps == 5)
error_per_index [tindex] = min_error_5bit (&chan, pcnxt->num_channels, inbuf [ch], inbuf + ch, flags, NULL, MAX_RMS_ERROR);
else
error_per_index [tindex] = min_error_4bit (&chan, pcnxt->num_channels, inbuf [ch], inbuf + ch, flags, NULL, MAX_RMS_ERROR);
}
// we use a 3-wide average window because the min_error_nbit() results can be noisy
for (tindex = 0; tindex <= 87; tindex++) {
rms_error_t terror = error_per_index [tindex];
if (tindex)
terror = (error_per_index [tindex - 1] + terror + error_per_index [tindex + 1]) / 3;
if (terror < min_error) {
best_index = tindex;
min_error = terror;
}
}
pcnxt->channels [ch].index = best_index;
}
}
// write the block header, which includes the first PCM sample verbatim
for (ch = 0; ch < pcnxt->num_channels; ch++) {
outbuf[0] = pcnxt->channels[ch].pcmdata;
outbuf[1] = pcnxt->channels[ch].pcmdata >> 8;
outbuf[2] = pcnxt->channels[ch].index;
outbuf[3] = 0;
outbuf += 4;
*outbufsize += 4;
}
void generate_dns_values (const int16_t *samples, int sample_count, int num_chans, int sample_rate,
int16_t *values, int16_t min_value, int16_t last_value);
if (inbufcount && (pcnxt->config_flags & NOISE_SHAPING_DYNAMIC)) {
pcnxt->dynamic_shaping_array = malloc (inbufcount * sizeof (int16_t));
generate_dns_values (inbuf, inbufcount, pcnxt->num_channels, pcnxt->sample_rate, pcnxt->dynamic_shaping_array, -512, pcnxt->last_shaping_weight);
pcnxt->last_shaping_weight = pcnxt->dynamic_shaping_array [inbufcount - 1];
}
// encode the rest of the PCM samples, if any, into 32-bit, possibly interleaved, chunks
if (inbufcount)
encode_chunks(pcnxt, outbuf, outbufsize, inbuf, inbufcount, bps);
if (pcnxt->dynamic_shaping_array && (pcnxt->config_flags & NOISE_SHAPING_DYNAMIC)) {
free (pcnxt->dynamic_shaping_array);
pcnxt->dynamic_shaping_array = NULL;
}
return 1;
}
int adpcm_encode(AdpcmEncoder *adpcm_enc, uint8_t *outbuf, int *outbufsize, int16_t *inbuf, int inbufcount, int bps)
{
static uint8_t rddancy_encode_flag = 0;
if(adpcm_enc->rddancy_num>0) {
TYPE_RINGBUF *ringbuf_original = adpcm_enc->ringbuf_original;
TYPE_RINGBUF *ringbuf_encode = adpcm_enc->ringbuf_encode;
int original_encode_len = (inbufcount*bps/8+4);
int reddancy_encode_len = (inbufcount*4/8+4);
int reddancy_total_len = 0;
int rddancy_num = adpcm_enc->rddancy_num;
uint8_t encode_buf[inbufcount*4/8+4];
int16_t original_buf[inbufcount];
push_ringbuf(ringbuf_original, (uint8_t*)inbuf, inbufcount*2);
if(rddancy_encode_flag) {
reddancy_encode_len = 0;
if(adpcm_encode_block(adpcm_enc->rddancy_cnxt,encode_buf,&reddancy_encode_len,inbuf,inbufcount,4) != 1)
return 0;
if(reddancy_encode_len > 0) {
push_ringbuf(ringbuf_encode,encode_buf,reddancy_encode_len);
}
}
if(!rddancy_encode_flag)
rddancy_encode_flag = 1;
reddancy_total_len = reddancy_encode_len*rddancy_num;
if(ringbuf_pop_available(ringbuf_original) >= (rddancy_num+1)*inbufcount*2) {
pop_ringbuf(ringbuf_original,(uint8_t*)original_buf,inbufcount*2);
original_encode_len = 0;
if(adpcm_encode_block(adpcm_enc->normal_cnxt,outbuf+4,&original_encode_len,original_buf,inbufcount,bps) != 1)
return 0;
if(original_encode_len > 0) {
pop_ringbuf(ringbuf_encode,outbuf+4+original_encode_len,reddancy_encode_len);
if(rddancy_num>1)
pop_ringbuf_notmove(ringbuf_encode,outbuf+4+original_encode_len+reddancy_encode_len,
reddancy_total_len-reddancy_encode_len);
}
*outbufsize = original_encode_len+reddancy_total_len+4;
*((uint32_t*)outbuf) = 0x80008000;
*((uint16_t*)outbuf) |= original_encode_len;
*((uint16_t*)outbuf+1) |= reddancy_encode_len;
}
else {
*outbufsize = original_encode_len+reddancy_total_len+4;
memset(outbuf,0,*outbufsize);
*((uint16_t*)outbuf) |= original_encode_len;
*((uint16_t*)outbuf+1) |= reddancy_encode_len;
}
}
else {
if(adpcm_encode_block(adpcm_enc->normal_cnxt,outbuf+4,outbufsize,inbuf,inbufcount,bps) != 1)
return 0;
*((uint32_t*)outbuf) = 0x8000;
*((uint16_t*)outbuf) |= *outbufsize;
*outbufsize += 4;
}
return 1;
}
int adpcm_decode_4bps (int16_t *outbuf, const uint8_t *inbuf, uint32_t inbufsize, 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;
}
int adpcm_decode_block(int16_t *outbuf, const uint8_t *inbuf, uint32_t inbufsize, int channels, int bps)
{
int samples = 1, ch;
int32_t pcmdata[2];
int8_t index[2];
if (bps == 4)
return adpcm_decode_4bps (outbuf, inbuf, inbufsize, channels);
if (bps < 2 || bps > 5 || 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;
}
if (!inbufsize || (inbufsize % (channels * 4))) // extra clean
return samples;
samples += inbufsize / channels * 8 / bps;
switch (bps) {
case 2:
for (ch = 0; ch < channels; ++ch) {
int shiftbits = 0, numbits = 0, i, j;
for (j = i = 0; i < samples - 1; ++i) {
uint16_t step = step_table [index [ch]];
if (numbits < bps) {
shiftbits |= inbuf [(j & ~3) * channels + (ch * 4) + (j & 3)] << numbits;
numbits += 8;
j++;
}
if (shiftbits & 2)
pcmdata[ch] -= step * (shiftbits & 1) + (step >> 1);
else
pcmdata[ch] += step * (shiftbits & 1) + (step >> 1);
index[ch] += (shiftbits & 1) * 3 - 1;
shiftbits >>= bps;
numbits -= bps;
CLIP(index[ch], 0, 88);
CLIP(pcmdata[ch], -32768, 32767);
outbuf [i * channels + ch] = pcmdata[ch];
}
}
break;
case 3:
for (ch = 0; ch < channels; ++ch) {
int shiftbits = 0, numbits = 0, i, j;
for (j = i = 0; i < samples - 1; ++i) {
uint16_t step = step_table [index [ch]], delta = step >> 2;
if (numbits < bps) {
shiftbits |= inbuf [(j & ~3) * channels + (ch * 4) + (j & 3)] << numbits;
numbits += 8;
j++;
}
if (shiftbits & 1) delta += (step >> 1);
if (shiftbits & 2) delta += step;
if (shiftbits & 4)
pcmdata[ch] -= delta;
else
pcmdata[ch] += delta;
index[ch] += index_table_3bit [shiftbits & 0x3];
shiftbits >>= bps;
numbits -= bps;
CLIP(index[ch], 0, 88);
CLIP(pcmdata[ch], -32768, 32767);
outbuf [i * channels + ch] = pcmdata[ch];
}
}
break;
case 5:
for (ch = 0; ch < channels; ++ch) {
int shiftbits = 0, numbits = 0, i, j;
for (j = i = 0; i < samples - 1; ++i) {
uint16_t step = step_table [index [ch]], delta = step >> 4;
if (numbits < bps) {
shiftbits |= inbuf [(j & ~3) * channels + (ch * 4) + (j & 3)] << numbits;
numbits += 8;
j++;
}
if (shiftbits & 1) delta += (step >> 3);
if (shiftbits & 2) delta += (step >> 2);
if (shiftbits & 4) delta += (step >> 1);
if (shiftbits & 8) delta += step;
if (shiftbits & 0x10)
pcmdata[ch] -= delta;
else
pcmdata[ch] += delta;
index[ch] += index_table_5bit [shiftbits & 0xf];
shiftbits >>= bps;
numbits -= bps;
CLIP(index[ch], 0, 88);
CLIP(pcmdata[ch], -32768, 32767);
outbuf [i * channels + ch] = pcmdata[ch];
}
}
break;
default:
return 0;
}
return samples;
}
int adpcm_decode(AdpcmDecoder *adpcm_dec, int16_t *outbuf, const uint8_t *inbuf, uint32_t inbufsize, int bps)
{
int samples = 0;
int original_encode_len = 0;
int reddancy_encode_len = 0;
uint16_t inbuf_info[2];
memcpy(inbuf_info,inbuf,4);
original_encode_len = inbuf_info[0] & 0x7FFF;
reddancy_encode_len = inbuf_info[1] & 0x7FFF;
if((adpcm_dec->rddancy_num > 0)&&(inbuf_info[1]&0x8000)) {
adpcm_dec->rddancy_encode_len = reddancy_encode_len;
adpcm_dec->rddancy_encbuf_pos = 0;
adpcm_dec->rddancy_encbuf_num = (inbufsize-(4+original_encode_len))/reddancy_encode_len;
memcpy(adpcm_dec->rddancy_encbuf,inbuf+4+original_encode_len,inbufsize-(4+original_encode_len));
}
samples = adpcm_decode_block(adpcm_dec->decode_buf,inbuf+4,original_encode_len,1,bps);
samples -= 1;
adpcm_dec->plc_sta = 0;
for(uint32_t i=0; i<samples/FRAMESZ; i++)
g711plc_addtohistory(adpcm_dec->lowcfe, adpcm_dec->decode_buf+FRAMESZ*i);
memcpy(outbuf,adpcm_dec->decode_buf,samples*2);
return samples;
}
int adpcm_decode_plc(AdpcmDecoder *adpcm_dec, int16_t *outbuf)
{
int samples = 0;
if(adpcm_dec->rddancy_encbuf_num) {
adpcm_dec->rddancy_encbuf_num--;
samples = adpcm_decode_block(adpcm_dec->decode_buf,adpcm_dec->rddancy_encbuf+adpcm_dec->rddancy_encbuf_pos,
adpcm_dec->rddancy_encode_len,1,4);
samples -= 1;
adpcm_dec->plc_sta = 1;
for(uint32_t i=0; i<samples/FRAMESZ; i++)
g711plc_addtohistory(adpcm_dec->lowcfe, adpcm_dec->decode_buf+FRAMESZ*i);
memcpy(outbuf,adpcm_dec->decode_buf,samples*2);
adpcm_dec->rddancy_encbuf_pos += adpcm_dec->rddancy_encode_len;
return samples;
}
else {
adpcm_dec->plc_sta = 2;
for(uint32_t i=0; i<adpcm_dec->block_size/FRAMESZ; i++)
g711plc_dofe(adpcm_dec->lowcfe, adpcm_dec->decode_buf+FRAMESZ*i);
memcpy(outbuf,adpcm_dec->decode_buf,adpcm_dec->block_size*2);
return adpcm_dec->block_size;
}
}
struct adpcm_context *adpcm_create_context (int num_channels, int sample_rate, int lookahead, int noise_shaping)
{
struct adpcm_context *pcnxt = (struct adpcm_context *)adpcm_malloc(sizeof (struct adpcm_context));
int ch;
if(!pcnxt)
return 0;
memset (pcnxt, 0, sizeof (struct adpcm_context));
pcnxt->config_flags = noise_shaping | lookahead;
pcnxt->static_shaping_weight = 1024;
pcnxt->num_channels = num_channels;
pcnxt->sample_rate = sample_rate;
// we set the indicies to invalid values so that we always recalculate them
// on at least the first frame (and every frame if the depth is sufficient)
for (ch = 0; ch < num_channels; ++ch)
pcnxt->channels [ch].index = -1;
return pcnxt;
}
void adpcm_free_context(struct adpcm_context *p)
{
if(p) {
adpcm_free(p);
p = NULL;
}
}
TYPE_RINGBUF *adpcm_create_ringbuf(int num_channels, int bufsize, int redundancy_num)
{
TYPE_RINGBUF *ringbuf = NULL;
ringbuf = (TYPE_RINGBUF *)adpcm_malloc(sizeof(TYPE_RINGBUF));
if(ringbuf_Init(ringbuf,(bufsize*(redundancy_num+2)*num_channels)) == -1)
return 0;
ringbuf->data = (uint8_t*)adpcm_malloc(ringbuf->size);
if(!ringbuf->data) {
ringbuf_del(ringbuf);
return 0;
}
return ringbuf;
}
void adpcm_free_ringbuf(TYPE_RINGBUF *p)
{
if(p) {
if(p->data) {
adpcm_free(p->data);
p->data = NULL;
}
ringbuf_del(p);
}
}
AdpcmEncoder *adpcm_encoder_create(int sample_rate, int lookahead, int noise_shaping, int block_size, int redundancy_num)
{
struct adpcm_context *adpcm_normal_cnxt = NULL;
struct adpcm_context *adpcm_rddancy_cnxt = NULL;
TYPE_RINGBUF *ringbuf_original = NULL;
TYPE_RINGBUF *ringbuf_encode = NULL;
AdpcmEncoder *adpcm_enc = NULL;
adpcm_normal_cnxt = adpcm_create_context(1,sample_rate,lookahead,noise_shaping);
if(!adpcm_normal_cnxt)
goto adpcm_encoder_create_err;
if(redundancy_num) {
adpcm_rddancy_cnxt = adpcm_create_context(1,sample_rate,lookahead,noise_shaping);
if(!adpcm_rddancy_cnxt)
goto adpcm_encoder_create_err;
ringbuf_original = adpcm_create_ringbuf(1,block_size*2,redundancy_num);
if(!ringbuf_original)
goto adpcm_encoder_create_err;
ringbuf_encode = adpcm_create_ringbuf(1,block_size*4/8+4,redundancy_num); //bps2:block_size*2/8+4
if(!ringbuf_encode)
goto adpcm_encoder_create_err;
}
adpcm_enc = (AdpcmEncoder *)adpcm_malloc(sizeof(AdpcmEncoder));
if(!adpcm_enc)
goto adpcm_encoder_create_err;
adpcm_enc->normal_cnxt = adpcm_normal_cnxt;
adpcm_enc->rddancy_cnxt = adpcm_rddancy_cnxt;
adpcm_enc->ringbuf_original = ringbuf_original;
adpcm_enc->ringbuf_encode = ringbuf_encode;
adpcm_enc->rddancy_num = redundancy_num;
return adpcm_enc;
adpcm_encoder_create_err:
adpcm_free_context(adpcm_normal_cnxt);
adpcm_free_context(adpcm_rddancy_cnxt);
adpcm_free_ringbuf(ringbuf_original);
adpcm_free_ringbuf(ringbuf_encode);
return 0;
}
void adpcm_free_encoder(AdpcmEncoder *adpcm_enc)
{
if(adpcm_enc) {
adpcm_free_context(adpcm_enc->normal_cnxt);
adpcm_free_context(adpcm_enc->rddancy_cnxt);
adpcm_free_ringbuf(adpcm_enc->ringbuf_original);
adpcm_free_ringbuf(adpcm_enc->ringbuf_encode);
adpcm_free(adpcm_enc);
adpcm_enc = NULL;
}
}
AdpcmDecoder *adpcm_decoder_create(int block_size, int redundancy_num)
{
uint8_t *rddancy_encbuf = NULL;
AdpcmDecoder *adpcm_dec = NULL;
LowcFE_c *lc = NULL;
int16_t *decode_buf = NULL;
if(redundancy_num) {
rddancy_encbuf = (uint8_t*)adpcm_malloc(1*(block_size*4/8+4)*redundancy_num);
if(!rddancy_encbuf)
goto adpcm_decoder_create_err;
}
lc = (LowcFE_c *)adpcm_malloc(sizeof(LowcFE_c));
if(!lc)
goto adpcm_decoder_create_err;
adpcm_dec = (AdpcmDecoder *)adpcm_malloc(sizeof(AdpcmDecoder));
if(!adpcm_dec)
goto adpcm_decoder_create_err;
decode_buf = (int16_t *)adpcm_malloc(sizeof(short)*(block_size+1));
if(!decode_buf)
goto adpcm_decoder_create_err;
adpcm_dec->rddancy_encbuf = rddancy_encbuf;
adpcm_dec->lowcfe = lc;
adpcm_dec->rddancy_num = redundancy_num;
adpcm_dec->rddancy_encbuf_num = 0;
adpcm_dec->block_size = block_size;
adpcm_dec->decode_buf = decode_buf;
g711plc_construct(adpcm_dec->lowcfe);
return adpcm_dec;
adpcm_decoder_create_err:
if(rddancy_encbuf) {
adpcm_free(rddancy_encbuf);
rddancy_encbuf = NULL;
}
if(lc) {
adpcm_free(lc);
lc = NULL;
}
if(decode_buf) {
adpcm_free(decode_buf);
decode_buf = NULL;
}
return 0;
}
void adpcm_free_decoder(AdpcmDecoder *adpcm_dec)
{
if(adpcm_dec) {
if(adpcm_dec->rddancy_encbuf) {
adpcm_free(adpcm_dec->rddancy_encbuf);
adpcm_dec->rddancy_encbuf = NULL;
}
if(adpcm_dec->lowcfe) {
adpcm_free(adpcm_dec->lowcfe);
adpcm_dec->lowcfe = NULL;
}
if(adpcm_dec->decode_buf) {
adpcm_free(adpcm_dec->decode_buf);
adpcm_dec->decode_buf = NULL;
}
adpcm_free(adpcm_dec);
adpcm_dec = NULL;
}
}