音乐合成_matlab
- 格式:doc
- 大小:286.21 KB
- 文档页数:11
MATLAB音乐合成一、简单音乐合成1、根据音乐简谱和十二平均律计算出每个乐音的频率,在 MATLAB中生成幅度为 1,抽样频率为 8kHz 的正弦信号表示这些乐音,用 sound 播放合成的音乐A=[174.61 196 220 246.94 261.62 293.66 329.63 349.23 392 440493.88 523.25 587.33 659.25 698.45 739.99 783.99]; % 定义各调频率fs=8000; %修改频率pu=[1 1 1 3 5 5 5 5 6 6 6 8 5 4 4 6 6 3 3 3 3 2 2 2 2 5 5 1 1 1 3 5 5 5 5 6 6 6 8 5 4 4 4 6 3 3 3 3 3 2 2 2 3 1 ]; %在pu中只需输入乐谱数字,在下面B=A-什么什么那部分调整音调,省去了写频率的麻烦p=0.5;last_time=[p/2 p/2 p/2 p/2 p/2 p/2 p/2 p/2 p/2 p/2 p/2 p/2 p p/2 p/2 p/2 p/2 p/2 p/2 p/2 p/2 p/2 p/2 p/2 p/2 p p p/2 p/2 p/2 p/2 p/2 p/2 p/2 p/2 p/2 p/2 p/2 p/2 p p/2 p/2 p/2 p/2 p/2 p/2 p/2 p/2 p/2 p/2 p/2 p/2 p/2 p ];%各乐音持续时间为节省空间,用p代替N=length(pu);f=zeros(1,N);B=A-5;for i=1:Nf(i)=B(pu(i)); %f为各个乐音对应的频率,修改其它调endpoint=fs*last_time; %各个乐音的抽样点数total_point=sum(point); %这段音乐的总抽样点数store=zeros(1,total_point); %用store向量来储存抽样点m=1;for num=1:N %利用循环产生抽样数据,num表示乐音编号 t=1/fs:1/fs:point(num)/fs; %产生第num个乐音的抽样点store(m:m+point(num)-1)=sin(2*pi*f(num)*t); %抽样点对应的幅值m=m+point(num);endsound(store,8000); %播放出storeplot(store); %画出store图像2、除噪音,加包络在1.1中听到有“啪”的杂声,这是由于相位不连续产生了高频分量,下面通过加包络来消噪音。
比较科学的包络如下图所示,每个乐音都经过冲激、衰减、持续、消失四个阶段。
由上图可以看出这个包络是四段直线段构成的,因此只要确定了每段线段的端点,即可用端点数据写出直线方程,因为直线方程可以用通式写出(可以用斜截式),因此这段包络可以用简单的循环来完成。
例如认为包络线上的数据如下图所示:(1.2)A=[174.61 196 220 246.94 261.62 293.66 329.63 349.23 392 440 493.88 523.25 587.33 659.25 698.45 739.99 783.99]; % 定义各调频率fs=8000; %修改频率pu=[1 1 1 3 5 5 5 5 6 6 6 8 5 4 4 6 6 3 3 3 3 2 2 2 2 5 5 1 1 1 3 5 5 5 5 6 6 6 8 5 4 4 4 6 3 3 3 3 3 2 2 2 3 1 ];p=0.5;last_time=[p/2 p/2 p/2 p/2 p/2 p/2 p/2 p/2 p/2 p/2 p/2 p/2 p p/2 p/2 p/2 p/2 p/2 p/2 p/2 p/2 p/2 p/2 p/2 p/2 p p p/2 p/2 p/2 p/2 p/2 p/2 p/2 p/2 p/2 p/2 p/2 p/2 p p/2 p/2 p/2 p/2 p/2 p/2 p/2 p/2 p/2 p/2 p/2 p/2 p/2 p ];N=length(pu);f=zeros(1,N);B=A-5;for i=1:Nf(i)=B(pu(i)); %f为各个乐音对应的频率,修改其它调endpoint=fs*last_time; %各个乐音的抽样点数total_point=sum(point); %这段音乐的总抽样点数store=zeros(1,total_point); %用store向量来储存抽样点m=1;for num=1:N %利用循环产生抽样数据,num表示乐音编号t=1/fs:1/fs:point(num)/fs; %产生第num个乐音的抽样点baoluo=zeros(1,point(num)); %包络for j=1:point(num)if (j<0.2*point(num))y=7.5*j/point(num);elseif (j<0.333*point(num))y=-15/4*j/point(num)+9/4;elseif (j<0.666*point(num))y=1;elsey=-3*j/point(num)+3;endendendbaoluo(j)=y;endstore(m:m+point(num)-1)=sin(2*pi*f(num)*t).*baoluo(1:point(num)); %储存抽样点对应的幅值m=m+point(num);endsound(store,8000); %播放出storeplot(store);3、改变程序,实现 1.2 中的音乐升高和降低一个八度将此句f(i)=A(pu(i)); 改为 f(i)=A(pu(i))*2; 或f(i)=A(pu(i))/2;4、在1.2的音乐中加入谐波在1.2的音乐中加上二、三、四次谐波,基波幅度为1,高次谐波幅度分别为0.2、0.3、0.1。
(1.4)A=[174.61 196 220 246.94 261.62 293.66 329.63 349.23 392 440 493.88 523.25 587.33 659.25 698.45 739.99 783.99]; % 定义各调频率fs=8000; %修改频率pu=[1 1 1 3 5 5 5 5 6 6 6 8 5 4 4 6 6 3 3 3 3 2 2 2 2 5 5 1 1 1 3 5 5 5 5 6 6 6 8 5 4 4 4 6 3 3 3 3 3 2 2 2 3 1 ];p=0.5;last_time=[p/2 p/2 p/2 p/2 p/2 p/2 p/2 p/2 p/2 p/2 p/2 p/2 p p/2 p/2 p/2 p/2 p/2 p/2 p/2 p/2 p/2 p/2 p/2 p/2 p p p/2 p/2 p/2 p/2 p/2 p/2 p/2 p/2 p/2 p/2 p/2 p/2 p p/2 p/2 p/2 p/2 p/2 p/2 p/2 p/2 p/2 p/2 p/2 p/2 p/2 p ]; %在pu中只需输入乐谱数字,在下面B=A-什么什么那部分调整音调,省去了写频率的麻烦%在此处输入音谱%各乐音持续时间N=length(pu);f=zeros(1,N);B=A-5;for i=1:Nf(i)=B(pu(i)); %f为各个乐音对应的频率,修改其它调endpoint=fs*last_time; %各个乐音的抽样点数total_point=sum(point); %这段音乐的总抽样点数store=zeros(1,total_point); %用store向量来储存抽样点m=1;for num=1:N %利用循环产生抽样数据,num表示乐音编号 t=1/fs:1/fs:point(num)/fs; %产生第num个乐音的抽样点baoluo=zeros(1,point(num)); %包络for j=1:point(num)if (j<0.2*point(num))y=7.5*j/point(num);elseif (j<0.333*point(num))y=-15/4*j/point(num)+9/4;elseif (j<0.666*point(num))y=1;elsey=-3*j/point(num)+3;endendendbaoluo(j)=y;endh=[1 0.2 0.3 0.1]; %波形幅值矩阵xiebo=zeros(1,length(t));for i=1:length(m)xiebo=xiebo+h(i)*sin(2*i*pi*f(num)*t); %加谐波endstore(m:m+point(num)-1)=xiebo.*baoluo(1:point(num)); %储存抽样点对应的幅值m=m+point(num);endsound(store,8000); %播放出storeplot(store);二、用傅立叶变换分析音乐1、载入fmt.wav并播放利用wavread函数载入,用sound函数播放,这段音乐听起来比之前合成的音乐更加真实,因为里边含有丰富的谐波。
fmt_wave=wavread('fmt.wav');sound(fmt_wave)2、载入文件Guitar.mat,处理原始数据realwave载入文件Guitar.mat,分析wave2proc是怎么由realwave得到的。
利用load Guitar.mat;载入并用plot函数将realwave、wave2proc分别画出。
plot(realwave)plot(wave2proc)3、分析 wave2proc 的基波和谐波为了分析wave2proc的基波和谐波,可以对wave2proc进行傅里叶变换,得到wave2proc的幅值谱,在频谱图上的第一个突出的波峰对应的频率即为wave2proc基频,可以利用help fft学习 MATLAB中快速傅里叶变换函数fft的用法,然后写程序。
(程序运行后虽然从图上可以大概看出包络,但是非常不明显,这是因为wave2proc 是周期函数,但是现在的wave2proc只有243个数据点,并不能非常明显的体现出其周期性,因此它的幅值谱的离散化程度不高,虽然提高了频域的抽样频率,但是wave2proc数据点的周期性并没有增加,所以要显示出离散化程度高的幅值谱,就要增加wave2proc的周期性,即让wave2proc在时域重复多次后再进行傅里叶变换。
利用repmat函数可以将wave2proc在时域重复,可以编写程序试一下。