pcm 32bit float 双声道转换16bit单声道
多通道音频转单通道
音频多通道是按照采样点进行交叉排列,比如双声道的16bit音频,16bit为一个采样点,那就是按照
通道1(16bit) | 通道2(16bit) | 通道1(16bit) | 通道2(16bit) |
---|
进行交叉排列,如果是32bit,那每个采样点是32bit数据,c语言demo双声道转单声道
int ReSample2CTo1C(char* in, char* out, int nInputLen, int bit) {
int count = 0;
if (bit == 16) {
count = nInputLen / 2 / 2; //16bit 一个采样点可以转成short 2个字节
}
else if (bit == 32) {
count = nInputLen / 2 / 4; // 32bit 一个采样点是float 4个字节
}
for (int i = 0; i < count; i++) {
if (bit == 16) {
((short*)out)[i] = ((short*)in)[2 * i]; //交叉排列取第一路数据
}
else if (bit == 32) {
((float*)out)[i] = ((float*)in)[2 * i]; //交叉排列取第一路数据
}
}
return nInputLen / 2;
}
32bit float 数据转16bit
音频每个采样点里记录的数据是有上限的,如果是16bit数据 ,一个short能表示最大32767,最小-32766
,而32bit的float能表示的范围远比short大,我们要做的就是让float的数据范围落到short的区间,如下
int ReSample32bitTo16(char* in, char* out, int nInputLen) {
int count = nInputLen / 4;
for (int i = 0; i < count; i++) {
float tmp = ((float*)in)[i];
//printf("tmp = %f\n", tmp);
short reout;
if (tmp < -0.999999f) {
reout = -32766;
}
else if (tmp >= 0.999999f) {
reout = 32767;
}
else
reout = (short)(tmp * (32767.0f));
((short*)out)[i] = reout;
}
return nInputLen / 2;
}
经过上述的转换,可以让音频从32bit双声道转到16bit的单声道
采样率转换
采样率就是1秒中采集了多少个采样点,48000hz采样转16000hz的话就是正好三分之一的采样点,所以我们可以每3个采样点取一个
int ReSample(char* in, char* out, int nInputLen) {
int count = nInputLen / 3;
for (int i = 0; i < count; i++) {
((short*)out)[i] = ((short*)in)[3 * i]; //交叉排列取第一路数据
}
return nInputLen / 3;
}
但其实采样率转换还是比较复杂,上述采样方法辉出现混叠(需要被采样的数字信号频率高于采样频率1/2的频率,高出来的频率将被重采样成低于采样率的1/2频率的信号,高频信号被低频信号代替,两种波形完全重叠在一起,形成严重失真,这种频谱的重叠导致的失真称为混叠),要解决这种问题我们再重采样时就需要滤波器来重采样,滤波器的好坏也决定了音频的质量(或者针对不同的使用场景而做了不同的修改)