音频处理
目前软件开发中所做的音频处理主要包括:
- 音频编解码
- 3A(回声消除AEC,降噪ANC,增益AGC)
- 混响,均衡器,压缩器等
对于音频编解码,使用成熟的编解码开源库即可。对于3A算法,基本上借鉴webRTC上的3A算法扩展即可。
但是对于混响,均衡器,压缩器等音效处理确是没有一种明确的处理方案,目前已知的比较靠谱的开源库就是(SOX,openAL)
SOX介绍
SOX:一款自称是音频处理界的瑞士军刀的一款开源库,SoX - Sound eXchange。SOX可以直接安装到PC上执行命令,用于各种格式的转换,播放,以及给音频加入特效。也可以通过交叉编译在移动端运行。
该软件的主页是http://sox.sourceforge.net/。
这两篇文章里面可以看到SOX的能力介绍:SOX能力介绍,SoX使用手册
SOX API使用
在使用SOX库之前,必须初始化整个库的全局参数,需要调用:
sox_init();
上述函数返回一个整数,如果返回的是SOX_SUCCESS这个枚举值,代码初始化成功;
退出SOX则需要调用如下代码
sox_quit();
需要注意的是,如果没有调用sox_quit方法,那么不可以再一次调用sox_init,否则会Crash。
接下来初始化输入文件,代码如下:
sox_format_t* in;
const char* in_path = "/sdcard/input.wav";
in = sox_open_read(in_path,NULL,NULL,NULL);
再来初始化输出文件,代码如下:
sox_format_t* out;
const char* out_path = "/sdcard/output.wav";
out = sox_open_write(out_path,&in->signal,NULL,NULL,NULL,NULL);
sox使用类似责任链设计模式的方式设计整个系统,所以使用时需要先构造一下效果器链,然后将使用的效果器一个一个加到这个效果链中。先来构造这个效果器链,代码如下:
sox_effects_chain_t* chain;
chain = sox_create_chain(&in->encoding , &out->encoding);
上述代码构造出了一个效果器链,重要的是里面的两个参数,这两个参数实际上就是确定输入,输出的数据格式,比如声道数,采样率,位宽等。这些数据已经从初始化sox_format_t的时候拿到了,会存进相应encoding属性中,有了效果器链,就可以构建效果器,然后添加进效果器链。
先来构建一下输入数据的效果器:(所有支持的效果器可以去effects.h这个头文件中查看)
sox_effect_t* inputEffect;
inputEffect = sox_create_cffect(sox_find_effect("input"));
上述代码构造了一个输入数据的效果器,但是数据从哪来呢,怎么将上面的输入文件配置到这个效果器中呢,代码如下:
char* args[10];
args[0] = (char*)in;
sox_effect_options(inputEffect,1,args) //参数含义:效果器,参数个数,具体参数
目前已经给inputEffect效果器配置好了需要的参数,然后要将这个效果器增加到效果器链中,并将这个效果器释放掉,代码如下:
sox_add_effect(chain,inputEffect,&in->signal,&in->signal);
free(inputEffect);
到此已经把这个输入效果器添加到了效果器链中,接下来在加入一个增加音量的效果器,添加代码如下:
sox_effect_t* volumeEffect;
volumeEffect = sox_create_cffect(sox_find_effect("vol"));
args[0] = "20db";
sox_effect_options(volumeEffect,1,args) ;
sox_add_effect(chain,volumeEffect,&in->signal,&in->signal);
free(volumeEffect);
到此一个增加20db增加音量效果器添加完成。
接下来添加一个输出数据的效果器,代码如下:
sox_effect_t* outputEffect;
outputEffect = sox_create_cffect(sox_find_effect("output"));
args[0] = (char*)out;
sox_effect_options(outputEffect,1,args) ;
sox_add_effect(chain,outputEffect,&in->signal,&in->signal);
free(outputEffect);
到此这个效果器链构建完好了:
input.wav—>inputEffect------>volumeEffect------->outputEffect------>output.wav
要让效果器链运行起来,要执行如下代码:
sox_flow_effects(chain,NULL,NULL);
这个方法执行结束,整个处理流程就结束了,增加音量后的音频数据已经全部被写入output.wav。
处理完后就要销毁这个效果器链了:
sox_delete_effects_chain(chain);
sox_close(out);
sox_close(in);
sox_quit();
到此结束。当然输入,输出也可以是data音频数据。修改输入,输出效果器即可实现实时处理。
混响器的实现
这里就不在解释混响是什么了,可以自行搜索。。。
混响音效重要的时配置参数 需要懂乐理进行参数调节,可调节出KTV,温暖,磁性,空灵,悠远,3D迷幻,等音效,当然和均衡器一起使用效果更好。
sox_effect_t* reverb;
reverb = sox_create_effect(sox_find_effect("reverb"));
//是否纯湿声
char* wetOnle = "-w";
//混响大小,高频阻尼,房间大小
char* reverbrance = "50";
char* hfDamping = "50";
char* roomScale = "80";
//立体声深度,早反射声,及湿声增益,代码如下:
char* stereoDepth = "90";
char* preDelay = "30";
char* wetGain = "0";
char* args = {wetOnle,reverbrance,hfDamping,roomScale,stereoDepth,preDelay,wetGain};
sox_effect_options(reverb,7,args);
将这个效果器添加进效果器链中,运行程序,可得出一个有音效的输出文件。
均衡器的实现
sox_effect_t* eq;
eq = sox_create_effect(sox_find_effect("equalizer"));
//中心频率,频宽,增益
char* frequency = "400";
char* bandWidth = "1.25q";
char* gain = "4db";
char* args = {frequency,bandWidth,gain};
sox_effect_options(eq,3,args);
一般情况下会创建多个均衡器作用到用一音频上。处理音频的时候一般还会加上高通,低通。效果器名称分别是highpass,lowpass。
压缩器等其他效果器就不在示范了,和上面这些套路基本一致。