pcmu音频文件 —— 声音调节
前言(pcmu音频基础知识):
声音的本质是一种能量波,由振动而产生的能量波,通过传输介质传输出去。声音有三个属性:
音调:声音频率的高低叫做音调(Pitch),是声音的三个主要的主观属性,即音量(响度)、音调、音色(也称音品) 之一。表示人的听觉分辨一个声音的调子高低的程度。音调主要由声音的频率决定,同时也与声音强度有关
音量:人主观上感觉声音的大小(俗称音量),由“振幅”(amplitude)和人离声源的距离决定,振幅越大响度越大,人和声源的距离越小,响度越大。(单位:分贝dB)
音色:又称声音的品质,波形决定了声音的音色。声音因不同物体材料的特性而具有不同特性,音色本身是一种抽象的东西,但波形是把这个抽象直观的表现。音色不同,波形则不同。典型的音色波形有方波,锯齿波,正弦波,脉冲波等。不同的音色,通过波形,完全可以分辨的。
波长是决定音调高低;振幅是决定音量高低;波纹是决定音色
即:调节pcmu音频的声音大小 —— 调节其振幅。
原文链接:https://blog.csdn.net/qq_28581781/article/details/108569819
另外,可参考:https://blog.csdn.net/yinshipin007/article/details/124044344 —— 音视频开发系列(2)PCM音量控制(高级篇)
以及同系列:https://blog.csdn.net/yinshipin007/article/details/124040585?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522166233887616782414980199%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=166233887616782414980199&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~first_rank_ecpm_v1~rank_v31_ecpm-25-124040585-null-null.nonecase&utm_term=%E9%9F%B3%E8%A7%86%E9%A2%91%E5%BC%80%E5%8F%91%E7%B3%BB%E5%88%97&spm=1018.2226.3001.4450 —— 音视频开发系列(1)开发什么是PCM
(作者:音视频开发老马 --- 音频开发系列 ---https://so.csdn.net/so/search?q=%E9%9F%B3%E8%A7%86%E9%A2%91%E5%BC%80%E5%8F%91%E7%B3%BB%E5%88%97&t=blog&u=yinshipin007)
方法1(使用):
原文链接:https://blog.csdn.net/Ivy9808/article/details/123669609 —— 基于C的PCM音频数据的读取、处理与写入(一)
通过更改volume_adjust实现音量的调节,调节后的数据写入到另一PCM中,通过ocenaudio,可查看其幅值,以作验证。
//PCM音频文件,采样率16KHZ,分辨率16位,读取文件并调节音量即幅值后另存到另一PCM文件中。
代码如下:
//PCM音频文件,采样率16KHZ,分辨率16位,读取文件并调节音量即幅值后另存到另一PCM文件中。 #include<stdio.h> #include<stdlib.h> int main() { const short MAX_VOL_S16_N = 32768; //16Bit满量程转换 const short MAX_VOL_S16_P = 32767; //打开文件,读取,操作,并存入另一文件 short in_data; short out_data; float in_data_f; float out_data_f; float volume_adjust=0; FILE *fp_in = fopen("file.pcm","rb"); //r是打开文本文件,rb是打开二进制文件 FILE *fp_out=fopen("out.pcm","wb+"); //pcm文件是模拟音频信号经过数模转换后直接形成的二进制序列。这是一种十分罕见的音频文件格式。 printf("请输入音量调节系数:"); scanf("%f",&volume_adjust); while(!feof(fp_in)) //当文件不是文件尾时均执行后续代码 { fread(&in_data,2,1,fp_in); if(in_data>=0) { in_data_f=(float)in_data/MAX_VOL_S16_P; } else { in_data_f=(float)-1*in_data/MAX_VOL_S16_N; } // printf("%f\n",in_data_f); out_data_f= in_data_f*volume_adjust; if(out_data_f>=0) { out_data=(short)(out_data_f*MAX_VOL_S16_P); } else { out_data=(short)(-1*out_data_f*MAX_VOL_S16_N); } if(out_data>32767) { out_data = 32767; } else if(out_data<-32768) { out_data = -32768; } else { out_data = out_data; } //printf("%d",out_data); fwrite(&out_data,2,1,fp_out); printf("%d\t%f\t%d\t%f\t%f\n",in_data,in_data_f,out_data,out_data_f,volume_adjust); } fclose(fp_in); fclose(fp_out); return 0; }
分为生成了sound、sound_80%、sound_60%、sound_40%、sound_20%、sound_10%五个文件进行了对比。
结果:
借助工具audacity,可以看出,的确实现了振幅对应的调节,并且声音渐弱。
以上可基本实现要求的功能,有几个问题还需继续探究:
1、后续使用fopen_s替代fopen
2、由short-float转换式中出现的是否添加括号引申出的运算符的优先级的问题
3、传入指针参数时的保护
4、结构体的用法
5、左移右移操作
以上几个问题,将会结合下一篇代码进行分析。
即:参考:https://blog.csdn.net/Ivy9808/article/details/123671062?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1-123671062-blog-123669609.pc_relevant_multi_platform_whitelistv6&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1-123671062-blog-123669609.pc_relevant_multi_platform_whitelistv6&utm_relevant_index=2 —— 基于C的PCM音频数据的读取、处理与写入(二)
方法2:
原文链接:https://blog.csdn.net/Timsley/article/details/50683084?spm=1001.2101.3001.6661.1&utm_medium=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1-50683084-blog-108569819.pc_relevant_aa_2&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1-50683084-blog-108569819.pc_relevant_aa_2&utm_relevant_index=1 —— 【C语言】PCM音频数据处理---音量增大或减小
PCM音频数据增大或减小的原理主要是,将采样的数据乘上一个数字或者是除以一个数字,但要注意溢出处理。具体实现如下(C语言):
#define OLD_FILE_PATH "file.pcm" #define VOL_FILE_PATH "vol.pcm" int volume_adjust(short * in_buf, short * out_buf, float in_vol) { int i, tmp; // in_vol[0, 100] float vol = in_vol - 98; if(-98<vol && vol<0) vol = 1/(vol*(-1)); else if(0<=vol && vol<=1) vol = 1; /* else if(1<=vol && vol<=2) vol = vol; */ else if(vol<=-98) vol = 0; else if(vol>=2) vol = 40; //这个值可以根据你的实际情况去调整 tmp = (*in_buf)*vol; // 上面所有关于vol的判断,其实都是为了此处*in_buf乘以一个倍数,你可以根据自己的需要去修改 // 下面的code主要是为了溢出判断 if(tmp > 32767) tmp = 32767; else if(tmp < -32768) tmp = -32768; *out_buf = tmp; return 0; } void pcm_volume_control(int volume) { short s16In = 0; short s16Out = 0; int size = 0; FILE *fp = fopen(OLD_FILE_PATH, "rb+"); FILE *fp_vol = fopen(VOL_FILE_PATH, "wb+"); while(!feof(fp)) { size = fread(&s16In, 2, 1, fp); if(size>0) { volume_adjust(&s16In, &s16Out, volume); fwrite(&s16Out, 2, 1, fp_vol); } } fclose(fp); fclose(fp_vol); } int main(void) { pcm_volume_control(100); return 0; }
上面程序中,main函数中pcm_volume_control(100),这里设置为100主要是为了让其走入volume_adjust函数中的最后一个else语句,而最终放大的数据,是将其乘上一个40,这个值可以根据你自己的需求去调整。
vol = 40;
tmp = (*in_buf)*vol;
经过上面的算法放大后,可以用Audacity工具去查看,放大后的PCM数据,如下图所示,上面的波形是原始数据,下面的波形是经过音量放大后的数据。
附属链接参考:
PCM 音量调节 —— https://blog.csdn.net/qinqqfirst/article/details/5985736
结果分析:
3.其他(参考):
1)C语言解析WAV音频文件
参考:https://www.cnblogs.com/LexMoon/p/wave-c.html
2)C++实现音频播放时音量调节功能 (代码下载 - - 6_GetSetVolume.cpp)
参考:https://download.csdn.net/download/xym352860763/12023116
(更改系统的声音 - 比较 lm )