PCM音频数据调整音量

2018-01-30  本文已影响887人  ibingewin

PCM调整音量

最近接到一个客诉,说是摄像头的音量比较小,需要手机端增强音频信号,经查找研究,解决方案就是:对于PCM数据,乘以一个放大系数,并对放大后的数据进行溢出处理。

对于16位,单声道的音频,采样点幅值为2^15-1-2^15,即32767-32768,当乘以放大倍数后,需要对超出此范围的数据进行溢出处理,但是如果一个音频帧中溢出数据过多,就会造成音频失真,故要合理的动态的选择放大倍数。

流程如下:

源码如下:

- (void)raiseVolume:(unsigned char *)buffer length:(UInt32)length factor:(int)factor{
    signed short MIN = -0x8000;
    signed short MAX = 0x7FFF;
    signed short low = 0, high = 0, data = 0, maxData = 0, minData = 0;
    //获取一个音频帧中的最大值`max`和最小值`min`
    for (int i = 0; i < length; i+=2) {
        low = buffer[i];
        high = buffer[i+1];
        data = low+(high<<8);
        maxData = maxData > data ? maxData : data;
        minData = minData < data ? minData : data;
    }
  //根据获取到的最大值和最小值分别计算出在不失真的情况下,允许的放大倍数`maxfactor`和`minfactor`
    signed short maxfactor =  maxData != 0 ? MAX/maxData : 1;
    signed short minfactor =  minData != 0 ? MIN/minData : 1;
    if (minfactor == 1 || maxfactor == 1) {
        return;
    }
    //取其最小值为允许的放大倍数`allowfactor`
    signed short allowfactor = MIN(maxfactor, minfactor);
    //根据经验系数`factor`,选择合适的系数
    factor = factor > allowfactor ? allowfactor : factor;
    if (factor <= 1) {
        return;
    }
    //对PCM数据放大
    signed long newData = 0;
    for (int i = 0; i < length; i+=2) {
        low = buffer[i];
        high = buffer[i+1];
        data = low+(high<<8);
        newData = data*factor;
        //边界值溢出处理
        if (newData < MIN) {
            newData = MIN;
        }else if (newData > MAX) {
            newData = MAX;
        }
        data = newData&0xffff;
        buffer[i] = data&0x00ff;
        buffer[i+1] = (data&0xff00)>>8;
    }
}
上一篇下一篇

猜你喜欢

热点阅读