声音处理是MATLAB的众多强大功能之一。我们可以使用audioread函数从文件读取声音,使用audiorwrite函数将向量保存为音频文件。MATLAB也自带了一些音频,以.mat格式的文件保存在系统目录。可以使用load函数来加载,然后进行播放,或者根据需要进行二次加工(例如滤波、小波变换实现变调/变速、二路音频合成等等)。
1.生成单一频率的声音
下列代码生成小字1组的a1(国际标准音高A4),并将其保存至文件:
t=1:1/5000:5;
y=cos(pi*2*440*t);
audiowrite('A4.wav',y,5000);
下列代码生成小字2组的a2:
t=1:1/5000:5;
y=cos(pi*2*880*t);
audiowrite('A5.wav',y,5000);
下列代码生成小字1组的c1(注意采用了平均律,其他音律的音高稍有差异):
t=1:1/5000:5;
f=220*2^(1/4);
y=cos(pi*2*f*t);
audiowrite('C4.wav',y,5000);
如果想要直接播放声音,只需把最后一行audiorwrite代码替换为:
sound(y,5000); %采样频率是5000
2.生成柱式和弦(注意下面均采用了平均律)
生成C和弦(即C大调主三和弦):
t=1:1/5000:5;
f1=220*2^(1/4);
f2=220*2^(7/12);
f3=220*2^(5/6);
y=0.3*cos(pi*2*f1*t)+0.3*cos(pi*2*f2*t)+0.3*cos(pi*2*f3*t);
audiowrite('C4_major_triad.wav',y,5000);
生成Cm和弦(即C小调主三和弦):
t=1:1/5000:5;
f1=220*2^(1/4);
f2=220*2^(1/2);
f3=220*2^(5/6);
y=0.3*cos(pi*2*f1*t)+0.3*cos(pi*2*f2*t)+0.3*cos(pi*2*f3*t);
audiowrite('C4_minor_triad.wav',y,5000);
生成C大调上行音阶:
%C大调上行音阶一个八度
rate=5000; %采样率5000 Hz
time=1; %每个音时长1 s
t=0:1/rate:time;
t(rate*time+1)=[];
f=[220*2^(1/4),220*2^(5/12),220*2^(7/12),220*2^(2/3),220*2^(5/6),440,440*2^(1/6),440*2^(1/4)];
for n=1:8
y((n-1)*rate*time+1:n*rate*time)=cos(pi*2*f(n)*t);
end
audiowrite('C4_major_scale.wav',y,5000);
3.周期性音频的合成
接下来,让我们尝试一些有难度、也是更刺激的音频合成项目。首先生成救护车的声音:
%频率周期性变化的声音(模仿救护车)
clear;
rate=5000; %采样率5000 Hz
f_high=950; f_low=750; %高低音频率
time_high=1; time_low=1; %高低音时长
repeat=8; %循环8次
t_high=0:1/rate:time_high/2; t_high(rate*time_high/2+1)=[];
y_high=cos(pi*2*f_high*t_high);
t_low=0:1/rate:time_low/2; t_low(rate*time_low/2+1)=[];
y_low=cos(pi*2*f_low*t_low);
y=[];
for n=1:repeat
y=[y y_high y_low];
end
audiowrite('ambulance.wav',y,rate);
生成救火车的声音。救火车jing笛声的合成要更难一些,因为它的音高(即频率)随时间是连续变化的,必须要用到调频的知识。
%频率周期性变化的声音(模仿救火车)
clear;
rate=5000; %采样率5000 Hz
fmax=1320; fmin=660;
period=2; repeat=8; %单次循环时长2 s,循环8次
%{
f(t)=(fmin-fmax)/2*cos(2*pi*t/period)+(fmin+fmax)/2; 频率随时间的变化
y=cos{[(fmin-fmax)/2*sin(2*pi*t/period)*period/2/pi+(fmin+fmax)/2*t]*2*pi}; 调频
以上是纯数学推导,t是真实的时间,与采样无关。下面是代码实现:
%}
t=0:1/rate:period; t(rate*period+1)=[];
part1=sin(2*pi*t/period); part2=(fmin+fmax)/2*t;
f_inte=(fmin-fmax)*period/4/pi*part1+part2;
omega_inte=f_inte*2*pi;
y_unit=cos(omega_inte);
y=[];
for n=1:repeat
y=[y y_unit];
end
audiowrite('fire engine.wav',y,rate);