为什么我的ADPCM解码器似乎在振荡?

时间:2018-03-13 11:03:46

标签: c audio adpcm

我正在为嵌入式处理器(ARM Cortex-M4)编写代码

此代码的目的是解码Intel / DVI格式的4位ADPCM(也称为IMA格式)。我使用Python的audioop模块编码了一个方波的ADPCM样本。然后,我使用相同的audioop模块成功解码了此示例,并且它非常适合输入。

但是,我无法在嵌入式处理器上正确解码输入数据。表示输出的valpred值似乎在大的正值和大的负值之间失控并振荡。这似乎是由sign值的行为驱动的。我遇到的问题是,这段代码实际上是audioop的C实现代码的副本,删除了Python部分。据我所知,该算法是相同的。然而,对于几乎每个输入数据值,它似乎仍然处于振荡状态。这显然是由sign翻转vpdiff值驱动的,但我看不出如何避免这种情况,因为量化步骤非常高(通常在最大步骤88)并且数据似乎确实如此有交替的迹象。

这是我现在正在使用的实现。 adpcm_step_size数组包含量化步骤(例如7,8,9 ... 29794,32767),而adpcm_step_size_adapt包含步长增量(-1,-1,-1,-1,2) ,4,6,8,重复)。

void audio_adpcm_play(uint8_t *sample_data, uint16_t sample_size)
{
    int sign, delta, step, vpdiff, valpred, index, half;
    uint32_t debug_data;
    uint32_t result;
    uint8_t data = 0x00;

    // Initial state
    half = 0;
    valpred = 0;
    index = 0;
    step = adpcm_step_size[index];

    while(sample_size > 0) {
        // Extract the appropriate word
        if(half) {
            delta = data & 0x0f;
        } else {
            data = *sample_data++;
            delta = (data >> 4) & 0x0f;
            sample_size--;
        }

        half = !half;
        debug_data = delta;

        // Find new index value
        index += adpcm_step_size_adapt[delta];
        if(index < 0)
            index = 0;
        if(index > 88)
            index = 88;

        // Separate sign and magnitude
        sign = delta & 8;
        delta = delta & 7;

        // Compute difference and the new predicted value
        vpdiff = step >> 3;

        if(delta & 4)
            vpdiff += step;
        if(delta & 2)
            vpdiff += step >> 1;
        if(delta & 1)
            vpdiff += step >> 2;

        if(sign)
            valpred -= vpdiff;
        else
            valpred += vpdiff;

        // Clamp values that exceed the valid range
        if(valpred > 32767)
            valpred = 32767;
        else if(valpred < -32768)
            valpred = -32768;

        step = adpcm_step_size[index];

        result = (valpred + 32767) >> AUDIO_CODE_SHIFT;
        uart_printf(DBG_LVL_INFO, \
                "data=%02x,  source_byte=%02x,  samples_rem=%5d,  valpred=%7d,  vpdiff=%5d,  sign=%02x,  delta=%02x,  index=%3d,  step=%3d,  adapt=%3d,  res=%5d/%5d\r\n", \
                debug_data, data, sample_size, valpred, vpdiff, sign, delta, index, step, \
                adpcm_step_size_adapt[delta], result, AUDIO_CODE_DUTY_MAX);
    }
}

这是输入方波输入的输出;可以看出,当它应该稳定在给定值时,valpred会在两个值之间快速振荡。

data=07,  source_byte=f7,  samples_rem= 7999,  valpred=     19,  vpdiff=   30,  sign=00,  delta=07,  index= 16,  step= 34,  adapt=  8,  res=  128/  256
data=0f,  source_byte=f7,  samples_rem= 7998,  valpred=    -44,  vpdiff=   63,  sign=08,  delta=07,  index= 24,  step= 73,  adapt=  8,  res=  127/  256
data=07,  source_byte=f7,  samples_rem= 7998,  valpred=     92,  vpdiff=  136,  sign=00,  delta=07,  index= 32,  step=157,  adapt=  8,  res=  128/  256
data=0f,  source_byte=f7,  samples_rem= 7997,  valpred=   -201,  vpdiff=  293,  sign=08,  delta=07,  index= 40,  step=337,  adapt=  8,  res=  127/  256
data=07,  source_byte=f7,  samples_rem= 7997,  valpred=    430,  vpdiff=  631,  sign=00,  delta=07,  index= 48,  step=724,  adapt=  8,  res=  129/  256
data=0f,  source_byte=f7,  samples_rem= 7996,  valpred=   -927,  vpdiff= 1357,  sign=08,  delta=07,  index= 56,  step=1552,  adapt=  8,  res=  124/  256
data=07,  source_byte=f7,  samples_rem= 7996,  valpred=   1983,  vpdiff= 2910,  sign=00,  delta=07,  index= 64,  step=3327,  adapt=  8,  res=  135/  256
data=0f,  source_byte=f7,  samples_rem= 7995,  valpred=  -4253,  vpdiff= 6236,  sign=08,  delta=07,  index= 72,  step=7132,  adapt=  8,  res=  111/  256
data=07,  source_byte=f7,  samples_rem= 7995,  valpred=   9119,  vpdiff=13372,  sign=00,  delta=07,  index= 80,  step=15289,  adapt=  8,  res=  163/  256
data=0d,  source_byte=d5,  samples_rem= 7994,  valpred= -11903,  vpdiff=21022,  sign=08,  delta=05,  index= 84,  step=22385,  adapt=  4,  res=   81/  256
data=05,  source_byte=d5,  samples_rem= 7994,  valpred=  18876,  vpdiff=30779,  sign=00,  delta=05,  index= 88,  step=32767,  adapt=  4,  res=  201/  256
data=0b,  source_byte=b3,  samples_rem= 7993,  valpred=  -9793,  vpdiff=28669,  sign=08,  delta=03,  index= 87,  step=29794,  adapt= -1,  res=   89/  256
data=03,  source_byte=b3,  samples_rem= 7993,  valpred=  16276,  vpdiff=26069,  sign=00,  delta=03,  index= 86,  step=27086,  adapt= -1,  res=  191/  256
data=0c,  source_byte=c4,  samples_rem= 7992,  valpred= -14195,  vpdiff=30471,  sign=08,  delta=04,  index= 88,  step=32767,  adapt=  2,  res=   72/  256
data=04,  source_byte=c4,  samples_rem= 7992,  valpred=  22667,  vpdiff=36862,  sign=00,  delta=04,  index= 88,  step=32767,  adapt=  2,  res=  216/  256
data=09,  source_byte=9c,  samples_rem= 7991,  valpred=  10381,  vpdiff=12286,  sign=08,  delta=01,  index= 87,  step=29794,  adapt= -1,  res=  168/  256
data=0c,  source_byte=9c,  samples_rem= 7991,  valpred= -23137,  vpdiff=33518,  sign=08,  delta=04,  index= 88,  step=32767,  adapt=  2,  res=   37/  256
data=04,  source_byte=4c,  samples_rem= 7990,  valpred=  13725,  vpdiff=36862,  sign=00,  delta=04,  index= 88,  step=32767,  adapt=  2,  res=  181/  256
data=0c,  source_byte=4c,  samples_rem= 7990,  valpred= -23137,  vpdiff=36862,  sign=08,  delta=04,  index= 88,  step=32767,  adapt=  2,  res=   37/  256
data=04,  source_byte=4c,  samples_rem= 7989,  valpred=  13725,  vpdiff=36862,  sign=00,  delta=04,  index= 88,  step=32767,  adapt=  2,  res=  181/  256
data=0c,  source_byte=4c,  samples_rem= 7989,  valpred= -23137,  vpdiff=36862,  sign=08,  delta=04,  index= 88,  step=32767,  adapt=  2,  res=   37/  256
data=04,  source_byte=4c,  samples_rem= 7988,  valpred=  13725,  vpdiff=36862,  sign=00,  delta=04,  index= 88,  step=32767,  adapt=  2,  res=  181/  256
data=0c,  source_byte=4c,  samples_rem= 7988,  valpred= -23137,  vpdiff=36862,  sign=08,  delta=04,  index= 88,  step=32767,  adapt=  2,  res=   37/  256
data=04,  source_byte=4c,  samples_rem= 7987,  valpred=  13725,  vpdiff=36862,  sign=00,  delta=04,  index= 88,  step=32767,  adapt=  2,  res=  181/  256
data=0c,  source_byte=4c,  samples_rem= 7987,  valpred= -23137,  vpdiff=36862,  sign=08,  delta=04,  index= 88,  step=32767,  adapt=  2,  res=   37/  256
data=04,  source_byte=4c,  samples_rem= 7986,  valpred=  13725,  vpdiff=36862,  sign=00,  delta=04,  index= 88,  step=32767,  adapt=  2,  res=  181/  256
data=0c,  source_byte=4c,  samples_rem= 7986,  valpred= -23137,  vpdiff=36862,  sign=08,  delta=04,  index= 88,  step=32767,  adapt=  2,  res=   37/  256
data=04,  source_byte=4c,  samples_rem= 7985,  valpred=  13725,  vpdiff=36862,  sign=00,  delta=04,  index= 88,  step=32767,  adapt=  2,  res=  181/  256
data=0c,  source_byte=4c,  samples_rem= 7985,  valpred= -23137,  vpdiff=36862,  sign=08,  delta=04,  index= 88,  step=32767,  adapt=  2,  res=   37/  256
data=04,  source_byte=4c,  samples_rem= 7984,  valpred=  13725,  vpdiff=36862,  sign=00,  delta=04,  index= 88,  step=32767,  adapt=  2,  res=  181/  256
data=0c,  source_byte=4c,  samples_rem= 7984,  valpred= -23137,  vpdiff=36862,  sign=08,  delta=04,  index= 88,  step=32767,  adapt=  2,  res=   37/  256
data=01,  source_byte=14,  samples_rem= 7983,  valpred= -10851,  vpdiff=12286,  sign=00,  delta=01,  index= 87,  step=29794,  adapt= -1,  res=   85/  256
data=04,  source_byte=14,  samples_rem= 7983,  valpred=  22667,  vpdiff=33518,  sign=00,  delta=04,  index= 88,  step=32767,  adapt=  2,  res=  216/  256
data=0c,  source_byte=c4,  samples_rem= 7982,  valpred= -14195,  vpdiff=36862,  sign=08,  delta=04,  index= 88,  step=32767,  adapt=  2,  res=   72/  256
data=04,  source_byte=c4,  samples_rem= 7982,  valpred=  22667,  vpdiff=36862,  sign=00,  delta=04,  index= 88,  step=32767,  adapt=  2,  res=  216/  256
data=0c,  source_byte=c4,  samples_rem= 7981,  valpred= -14195,  vpdiff=36862,  sign=08,  delta=04,  index= 88,  step=32767,  adapt=  2,  res=   72/  256
data=04,  source_byte=c4,  samples_rem= 7981,  valpred=  22667,  vpdiff=36862,  sign=00,  delta=04,  index= 88,  step=32767,  adapt=  2,  res=  216/  256
data=0c,  source_byte=c4,  samples_rem= 7980,  valpred= -14195,  vpdiff=36862,  sign=08,  delta=04,  index= 88,  step=32767,  adapt=  2,  res=   72/  256
data=04,  source_byte=c4,  samples_rem= 7980,  valpred=  22667,  vpdiff=36862,  sign=00,  delta=04,  index= 88,  step=32767,  adapt=  2,  res=  216/  256
data=0c,  source_byte=c4,  samples_rem= 7979,  valpred= -14195,  vpdiff=36862,  sign=08,  delta=04,  index= 88,  step=32767,  adapt=  2,  res=   72/  256
data=04,  source_byte=c4,  samples_rem= 7979,  valpred=  22667,  vpdiff=36862,  sign=00,  delta=04,  index= 88,  step=32767,  adapt=  2,  res=  216/  256
data=0c,  source_byte=c4,  samples_rem= 7978,  valpred= -14195,  vpdiff=36862,  sign=08,  delta=04,  index= 88,  step=32767,  adapt=  2,  res=   72/  256
data=04,  source_byte=c4,  samples_rem= 7978,  valpred=  22667,  vpdiff=36862,  sign=00,  delta=04,  index= 88,  step=32767,  adapt=  2,  res=  216/  256
data=0c,  source_byte=c4,  samples_rem= 7977,  valpred= -14195,  vpdiff=36862,  sign=08,  delta=04,  index= 88,  step=32767,  adapt=  2,  res=   72/  256
data=04,  source_byte=c4,  samples_rem= 7977,  valpred=  22667,  vpdiff=36862,  sign=00,  delta=04,  index= 88,  step=32767,  adapt=  2,  res=  216/  256
data=0c,  source_byte=c4,  samples_rem= 7976,  valpred= -14195,  vpdiff=36862,  sign=08,  delta=04,  index= 88,  step=32767,  adapt=  2,  res=   72/  256
data=04,  source_byte=c4,  samples_rem= 7976,  valpred=  22667,  vpdiff=36862,  sign=00,  delta=04,  index= 88,  step=32767,  adapt=  2,  res=  216/  256
data=09,  source_byte=9c,  samples_rem= 7975,  valpred=  10381,  vpdiff=12286,  sign=08,  delta=01,  index= 87,  step=29794,  adapt= -1,  res=  168/  256
data=0c,  source_byte=9c,  samples_rem= 7975,  valpred= -23137,  vpdiff=33518,  sign=08,  delta=04,  index= 88,  step=32767,  adapt=  2,  res=   37/  256
data=04,  source_byte=4c,  samples_rem= 7974,  valpred=  13725,  vpdiff=36862,  sign=00,  delta=04,  index= 88,  step=32767,  adapt=  2,  res=  181/  256

如果我只拍摄每一个样本,它对于方波几乎可以接受,但其他波形会出现问题。这仍然不是一个可接受的解决方案,但也许这是问题原因的线索。

如果有人有任何想法,我会很感激。我已经在这里擦了几天头发。

编辑:audioop模块的来源可在https://github.com/python/cpython/blob/master/Modules/audioop.c找到,ADPCM解码器为audioop_adpcm2lin_impl

1 个答案:

答案 0 :(得分:0)

我成功解决了这个问题。它是由一个愚蠢的错误引起的,一次读取一个字节的16位输入数据,然后使用相同的错误解压缩数据在Python中产生了正确的结果。但这显然对解码器的C实现没有好处。

事后看来,我不确定为什么我没有注意到音频文件的大小应该是原来的两倍。