初次接触音频转换,希望各位帮忙看看。多谢了。
这个代码我找了好多大神的博客,改了改最终确定下来的版本。
项目使用的是vs2017编译器,C语言和C++语言。
主要是采样位数为16位的pcm转换成采样位数为4位的ima_adpcm。
但是有挺大的杂音并且采样率越高,转换出来的ima_adpcm音频的杂音就越大。
望各位大侠帮忙看看,我写这个写了一个多月了。。。。。
如需可运行的整个项目,可联系我,若能帮我修改,我愿提供一定的报酬。多谢了。。。。
下面是将pcm源文件以1010个字节为一个数据块传给压缩函数
for (i = 0; i < len0 - 1010; i += 1010) {
// 以1010个字节截取
memcpy(data1, data + i, 1010);
len += adpcm_encode_block((uint8_t *)(data2 + j * 256), (uint8_t *)data1, 1010);
j++;
}
下面为pcm转换成ima_adpcm的具体代码
/* Private define ------------------------------------------------------------*/
/* Quantizer step size lookup table */
const uint16_t StepSizeTable[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 };
/* Table of index changes */
const int8_t IndexTable[16] = { 0xff,0xff,0xff,0xff,2,4,6,8,0xff,0xff,0xff,0xff,2,4,6,8 };
static int16_t index = 0; //willow add
static int32_t predsample = 0;
/*如果按分块处理,这也是电脑上通用的IMA_ADPCM保存的格式,就需要预置index & presample的值*/
void set_index(int16_t idx)
{
index = idx;
}
void set_presample(int32_t pcm_16)
{
predsample = pcm_16;
}
uint8_t ADPCM_Encode(int32_t sample)
{
// static int16_t index = 0;
// static int32_t predsample = 0;
uint8_t code = 0; //ima_adpcm值
uint16_t tmpstep = 0; //步长
int32_t diff = 0; // 预测输出值
int32_t diffq = 0; // 当前更改值
uint16_t step = 0; // 当前步长
step = StepSizeTable[index];
/* 1. compute diff and record sign and absolut value */
/* 计算差异,记录符号和绝对值 */
diff = sample - predsample;
if (diff < 0)
{
code = 8;
diff = (-diff);
}
/* Note:
** This code *approximately* computes:
** code = diff*4/step;
** diffq = (code+0.5)*step/4;
** but in shift step bits are dropped. The net result of this is
** that even if you have fast mul/div hardware you cannot put it to
** good use since the fixup would be too expensive.
*/
/* 3. quantize the diff into ADPCM code */
/* 4. inverse quantize the code into a predicted diff */
/* 将差异量化为ADPCM代码 */
/* 将代码反量化为预测的差异 */
tmpstep = step;
diffq = (step >> 3);
if (diff >= tmpstep)
{
//code += 0.5;
code |= 0x04;
diff -= tmpstep;
diffq += step;
}
tmpstep = tmpstep >> 1;
if (diff >= tmpstep)
{
//code += 0.5;
code |= 0x02;
diff -= tmpstep;
diffq += (step >> 1);
}
tmpstep = tmpstep >> 1;
if (diff >= tmpstep)
{
//code += 0.5;
code |= 0x01;
diffq += (step >> 2);
}
/* 5. fixed predictor to get new predicted sample*/
/* 固定的预测得到新的预测样本 */
if (code & 8)
{
predsample -= diffq;
}
else
{
predsample += diffq;
}
/* check for overflow*/
/* 溢出检查*/
if (predsample > 32767)
{
predsample = 32767;
}
else if (predsample < -32768)
{
predsample = -32768;
}
/* 6. find new stepsize index */
/* 找出新的下标索引 */
index += IndexTable[code];
/* check for overflow*/
/* 检查溢出 */
if (index <0)
{
index = 0;
}
else if (index > 88)
{
index = 88;
}
/* 8. return new ADPCM code*/
/* 返回adpcm 值*/
//return (code);
return (code & 0x0f);
}
int adpcm_encode_block(uint8_t *p_dst, uint8_t *p_src, uint32_t len)
{
int length = 0;
int16_t *p_pcm;
uint32_t i;
uint8_t tmp;
p_pcm = (int16_t*)p_src;
set_presample(*p_pcm); //第一个不压缩
*(int16_t*)p_dst = *p_pcm++; //保存第一个采样值
p_dst += 2;
len--;
*p_dst++ = index; //保存index
*p_dst++ = 0; //保留字节 =0
length += 8;
int jj = 0;
for (i = 0; i<(len >> 1); i++)
{
tmp = ADPCM_Encode(*p_pcm++);
jj++;
tmp |= ADPCM_Encode(*p_pcm++) << 4;
jj++;
*p_dst++ = tmp;
length++;
}
return length / 2;
}