qq_25369263 2018-12-25 09:48 采纳率: 0%
浏览 1313
已采纳

pcm音频格式转换成ima_adpcm音频,有杂音,望各位大侠帮忙看看。

初次接触音频转换,希望各位帮忙看看。多谢了。
这个代码我找了好多大神的博客,改了改最终确定下来的版本。
项目使用的是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;
}
  • 写回答

2条回答 默认 最新

  • qq_25369263 2018-12-25 09:18
    关注

    已经解决了。。。。。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 js调用html页面需要隐藏某个按钮
  • ¥15 ads仿真结果在圆图上是怎么读数的
  • ¥20 Cotex M3的调试和程序执行方式是什么样的?
  • ¥15 一道python难题3
  • ¥15 牛顿斯科特系数表表示
  • ¥15 arduino 步进电机
  • ¥20 程序进入HardFault_Handler
  • ¥15 oracle集群安装出bug
  • ¥15 关于#python#的问题:自动化测试
  • ¥20 问题请教!vue项目关于Nginx配置nonce安全策略的问题