PCM的数据解析出音量信息首先要知道的一些基础常识:
采样频率,指每秒钟取得声音样本的次数,采样频率越高,包含的声音信息自然就越多,声音也就越好,频率越高,保存需要的空间也会高。
采样位宽,即采样值,一般分为8位和16位,可以表示的范围分别是2^8和2^16的区间,区间越大,分辨率也就越大,发出声音大能力也就越强,同样的,位宽越大,需要的空间也就越大。
声道数,分为单声道和双声道,双声道即立体声。
博主使用的是位宽为16位,采样频率为16KHz的单声道数据样本,所以代码十分简单,直接获得音量信息数据,代码如下:
int volume_output(short * in_buf, short * out_buf)
{
cout<<"原始数值:"<<*in_buf<<endl;
int temp;
temp = *in_buf; // 接受来自PCM文件中的音量数据
//temp*=10; //此行可用来调整获取的音量数据
// 下面的code主要是为了溢出判断,当数据溢出时取最大值或最小值
if(temp > 32767)
temp = 32767;
else if(temp < -32768)
temp = -32768;
*out_buf = temp; //输出解码PCM得到的数据
cout<<"获取的数值:"<<*out_buf<<endl;
return 0;
}
void pcm_read_write()
{
short pcm_In = 0;
short pcm_Out = 0;
int size = 0;
FILE *fp = fopen(OLD_FILE_PATH, "rb+"); //为读写打开一个二进制文件 即pcm文件
FILE *fp_new = fopen(NEW_FILE_PATH, "wb+"); //以二进制方式进行读写,可以对获取的数据写入一个新的pcm文件
while(!feof(fp))
{
size = fread(&pcm_In, 2, 1, fp); //pcm中每个数据大小为2字节,每次读取1个数据
if(size>0)
{
volume_output(&pcm_In, &pcm_Out); //从PCM中获取的数据经过处理后输出
fwrite(&pcm_Out, 2, 1, fp_new); //以同样的方式写入文件
}
}
fclose(fp);
fclose(fp_new);
}
为了使结果更为明显,我将获取的数据放大十倍后输出到新的PCM文件中,利用audacity软件打开,可以看到我们处理后的效果图:
代码运行结果:
完整的代码和其他参考资料可以从博主GitHub上获得:
https://github.com/xiaobooo/OpenGL/tree/master/%E4%BB%A3%E7%A0%81/Music-Visualization
参考资料:
【C语言】PCM音频数据处理---音量增大或减小:https://blog.csdn.net/timsley/article/details/50683084
PCM音频波形的绘制以及注意事项:https://blog.csdn.net/huangmindong/article/details/55513646