我正在为嵌入式处理器(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
。
答案 0 :(得分:0)
我成功解决了这个问题。它是由一个愚蠢的错误引起的,一次读取一个字节的16位输入数据,然后使用相同的错误解压缩数据在Python中产生了正确的结果。但这显然对解码器的C实现没有好处。
事后看来,我不确定为什么我没有注意到音频文件的大小应该是原来的两倍。