PCM调整音量
最近接到一个客诉,说是摄像头的音量比较小,需要手机端增强音频信号,经查找研究,解决方案就是:对于PCM数据,乘以一个放大系数,并对放大后的数据进行溢出处理。
对于16位,单声道
的音频,采样点幅值为2^15-1
和-2^15
,即32767
和-32768
,当乘以放大倍数后,需要对超出此范围的数据进行溢出处理,但是如果一个音频帧中溢出数据过多,就会造成音频失真,故要合理的动态的选择放大倍数。
流程如下:
- 获取一个音频帧中的最大值
max
和最小值min
- 根据获取到的最大值和最小值分别计算出在不失真的情况下,允许的放大倍数
maxfactor
和minfactor
,取其最小值为允许的最大放大倍数allowfactor
- 根据给定的经验系数
factor
,选择合适的系数,对PCM数据放大即可
源码如下:
- (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;
}
}
网友评论