Matlab音乐合成实验报告.docx_第1页
Matlab音乐合成实验报告.docx_第2页
Matlab音乐合成实验报告.docx_第3页
Matlab音乐合成实验报告.docx_第4页
Matlab音乐合成实验报告.docx_第5页
已阅读5页,还剩17页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

音乐合成实验目录音乐合成实验1摘要:2第一部分 简单的合成音乐21.1合成东方红21.2 除噪音,加包络31.3改变程序,实现1.2中的音乐升高和降低一个八度91.4 在1.2的音乐中加入谐波101.5 自选音乐合成两只老虎11第二部分 用傅里叶变换分析音乐122.1 载入fmt.wav并播放122.2 载入文件Guitar.mat,处理原始数据realwave122.3 分析wave2proc的基波和谐波142.4 自动分析fmt.wav的音调和节拍17第三部分基于傅里叶级数的音乐合成203.1 用2.3分析出来的结果重新加谐波203.2 通过2.4提取的吉他音调信息弹奏东方红20实验收获22摘要:本文共有三大部分:第一部分,简单的音乐合成;第二部分,用傅里叶变换分析音乐;第三部分,基于傅里叶级数的音乐合成。由潜入深,一步一步分析了用MATLAB进行音乐合成的过程。通过本实验达到了加深对傅里叶级数和傅里叶分析的理解,熟悉对MATLAB基本使用的目标。第一部分简单的合成音乐1.1合成东方红根据东方红第一小节的简谱和十二平均律计算出该小节每个乐音的频率,在MATLAB中生成幅度为1,抽样频率为8kHz的正弦信号表示这些乐音,用sound播放合成的音乐由图可知东方红的曲调定为F,即1=F,对应的频率为349.23Hz,据此可以计算出其他乐音的频率,例如5对应的频率为,一次类推计算出第一小节各乐音对应的频率为:乐音55621162频率523.25523.25587.33392349.23349.23293.66392在确定了各乐音的频率之后需要确定每个乐音的持续时间。每小节有两拍,一拍的时间是0.5s,因此各乐音的持续时间为:乐音55621162时间0.50.250.2510.50.250.251而在MATLAB中表示乐音所用的抽样频率为fs=8000Hz,也就是所1s钟内有8000个点,抽样点数的多少就可表示出每个乐音的持续时间的长短。用一个行向量来存储这段音乐对应的抽样点,在用sound函数播放即可。根据以上分析在MATLAB中编写如下程序:sound_1_1.mclear;clc;fs=8000;%抽样频率f=523.25 523.25 587.33 392 349.23 349.23 293.66 392; %各个乐音对应的频率time=fs*1/2,1/4,1/4,1,1/2,1/4,1/4,1;%各个乐音的抽样点数N=length(time);%这段音乐的总抽样点数east=zeros(1,N);%用east向量来储存抽样点n=1;for num=1:N%利用循环产生抽样数据,num表示乐音编号 t=1/fs:1/fs:time(num)/fs;%产生第num个乐音的抽样点east(n:n+time(num)-1)=sin(2*pi*f(num)*t);%抽样点对应的幅值 n=n+time(num);endsound(east,8000);%播放音乐在MATLAB中运行sound_1_1.m,播放出了东方红的第一段,但是可以听出效果很不好,只能听出具有东方红的调子而已。1.2 除噪音,加包络在1.1中听到有“啪”的杂声,下面通过加包络来消噪音。最简单的包络为指数衰减。最简单的指数衰减是对每个音乘以因子,在实验中首先加的是的衰减,这种衰减方法使用的是相同速度的衰减,但是发现噪音并没有完全消除,播放的音乐效果不是很好,感觉音乐起伏性不强。于是采用不同速度的衰减,根据乐音持续时间的长短来确定衰减的快慢,乐音持续时间越长,衰减的越慢,持续时间越短,衰减的越快。在1.1程序的基础上加上包络,编写如下程序:sound_1_21.mclear;clc;fs=8000;%抽样频率f=523.25 523.25 587.33 392 349.23 349.23 293.66 392; %各个乐音对应的频率time=fs*1/2,1/4,1/4,1,1/2,1/4,1/4,1;%各个乐音的抽样点数N=length(time);%这段音乐的总抽样点数east=zeros(1,N);%用east向量来储存抽样点n=1;for num=1:N%利用循环产生抽样数据,num表示乐音编号 t=1/fs:1/fs:time(num)/fs;%产生第num个乐音的抽样点 G=zeros(1,time(num); %G为存储包络数据的向量G(1:time(num)=exp(1:(-1/time(num):1/8000);%产生包络点 east(n:n+time(num)-1)=sin(2*pi*f(num)*t).*G(1:time(num); %给第num个乐音加上包络 n=n+time(num);endsound(east,8000);%播放plot(east);播放后可以听出噪音已经消除,同时因为不同时长的乐音衰减的快慢不一样,音乐听起来更有起伏感,下图是加包络后的east图像。更科学的包络如下图所示,每个乐音都经过冲激、衰减、持续、消失四个阶段。由上图可以看出这个包络是四段直线段构成的,因此只要确定了每段线段的端点,即可用端点数据写出直线方程,因为直线方程可以用通式写出(我用的是斜截式),因此这段包络可以用简单的循环来完成。例如认为包络线上的数据如下图所示:据此在MATLAB中编写如下程序:sound_1_22.mclear;clc;fs=8000;%抽样频率f=523.25 523.25 587.33 392 349.23 349.23 293.66 392; %各个乐音对应的频率time=fs*1/2,1/4,1/4,1,1/2,1/4,1/4,1;%各个乐音的抽样点数N=length(time);%这段音乐的总抽样点数east=zeros(1,N);%用east向量来储存抽样点n=1;for num=1:N%利用循环产生抽样数据,num表示乐音编号 t=1/fs:1/fs:(time(num)/fs;%产生第num个乐音的抽样点 P=zeros(1,time(num);%P为存储包络数据的向量L=(time(num)*0 1/5 333/1000 333/500 1;%包络线端点对应的横坐标 T=0 1.5 1 1 0;%包络线端点对应的纵坐标 s=1; b=1:1:time(num);%产生包络线抽样点 for k=1:4 P(s:L(k+1)-1)=(T(k+1)-T(k)/(L(k+1)-L(k)*(b(s:L(k+1)-1)-L(k+1)*ones(1,L(k+1)-s)+T(k+1)*ones(1,L(k+1)-s);%包络线直线方程通式 s=L(k+1);end east(n:n+time(num)-1)=sin(2*pi*f(num)*t).*P(1:time(num);%给第num个乐音加上包络 n=n+time(num);endsound(east,8000);plot(east);运行得到的图像为:下图是两个乐音交接处的局部放大图,可以看到前一个乐音一直衰减到0,后一个乐音从0开始增加,因此消除了噪音。若不需要每个音都衰减到0,例如只需衰减到持续阶段幅值的20%,对程序做简单的修改即可,将T=0 1.5 1 1 0改为T=0.2 1.5 1 1 0.2运行得到的结果为:由图可见,每个乐音都是衰减到一较小值而不是0,也能消除噪音,同时音乐听起来更加连续。1.3改变程序,实现1.2中的音乐升高和降低一个八度升高一个八度即每个乐音的频率都提高一倍,变为原来的2被;降低一个八度即每个乐音的频率都减小一倍,变为原来的1/2。因此最简单的办法是将存储乐音频率的向量每个元素改变为2或1/2倍。即将程序中的f=523.25 523.25 587.33 392 349.23 349.23 293.66 392;改为f=523.25 523.25 587.33 392 349.23 349.23 293.66 392*2;或f=523.25 523.25 587.33 392 349.23 349.23 293.66 392/2;将上述音乐上高半个音阶,即将频率变为原来的(1.06)倍,可以利用resamlpe函数对原来的数据点进行重采样来实现east=resample(east,100,106);因为resample进行重新采样后会使每个乐音的持续时间改变,但是因为升高半个音阶,频率改变不大,所以每个音的持续时间是基本不变的。1.4 在1.2的音乐中加入谐波在1.2的音乐中加上二、三、四次谐波,基波幅度为1,高次谐波幅度分别为0.2、0.3、0.1。只需将1.2程序改为sound_1_4.mclear;clc;fs=8000;%抽样频率f=523.25 523.25 587.33 392 349.23 349.23 293.66 392; %各个乐音对应的频率time=fs*1/2,1/4,1/4,1,1/2,1/4,1/4,1;%各个乐音的抽样点数N=length(time);%这段音乐的总抽样点数east=zeros(1,N);%用east向量来储存抽样点n=1;for num=1:N%利用循环产生抽样数据,num表示乐音编号 t=1/fs:1/fs:(time(num)/fs;%产生第num个乐音的抽样点 P=zeros(1,time(num);%P为存储包络数据的向量L=(time(num)*0 1/5 333/1000 333/500 1;%包络线端点对应的横坐标 T=0 1.5 1 1 0;%包络线端点对应的纵坐标 s=1; b=1:1:time(num);%产生包络线抽样点 for k=1:4 P(s:L(k+1)-1)=(T(k+1)-T(k)/(L(k+1)-L(k)*(b(s:L(k+1)-1)-L(k+1)*ones(1,L(k+1)-s)+T(k+1)*ones(1,L(k+1)-s);%包络线直线方程通式 s=L(k+1); end m=1 0.3 0.2;%波形幅值矩阵 ss=zeros(1,length(t); for i=1:length(m) ss=ss+m(i)*sin(2*i*pi*f(num)*t);%加谐波 endeast(n:n+time(num)-1)=ss.*P(1:time(num); %给第num个乐音加上包络 n=n+time(num);endsound(2*east,8000);plot(east);即可,加颜色部分为修改的部分,加上谐波后音乐效果变得更好了。1.5自选音乐合成两只老虎两只老虎曲调为C,因此可以得到每个乐音对应的频率分别为:12345262.63293.66329.63349.23392每小节有四拍,一拍的时间是0.5s,因此各乐音的持续时间为:乐音12311231时间0.50.50.50.50.50.50.50.5乐音345345时间0.50.510.50.510.25sound_1_5.mclear;clc;fs=8000;%抽样频率f=262.63 293.66 329.63 262.63 262.63 293.66 329.63 262.63 329.63 349.23 392; %各个乐音对应的频率time=fs*1/2,1/2,1/2,1/2,1/2,1/2,1/2,1/2,1/2,1/2,1,1/2,1/2,1;%各个乐音的抽样点数N=length(time);%这段音乐的总抽样点数east=zeros(1,N);%用east向量来储存抽样点n=1;for num=1:N%利用循环产生抽样数据,num表示乐音编号 t=1/fs:1/fs:time(num)/fs;%产生第num个乐音的抽样点 G=zeros(1,time(num); %G为存储包络数据的向量G(1:time(num)=exp(1:(-1/time(num):1/8000);%产生包络点 east(n:n+time(num)-1)=sin(2*pi*f(num)*t).*G(1:time(num); %给第num个乐音加上包络 n=n+time(num);endsound(east,8000);%播放plot(east);第二部分用傅里叶变换分析音乐2.1载入fmt.wav并播放利用wavread函数载入,用sound函数播放,程序如下:sound_2_1.mwave=wavread(fmt.wav);sound(wave)这段音乐听起来比之前合成的音乐更加真实,因为里边含有丰富的谐波。2.2 载入文件Guitar.mat,处理原始数据realwave载入文件Guitar.mat,分析wave2proc是怎么由realwave得到的。利用load Guitar.mat;载入并用plot函数将realwave、wave2proc分别画出,得到以下两幅图可以看到,wave2proc比realwave的周期性好得多,去掉了非线性谐波和噪声。在时域做,从图上可以看到,realwave的数据大约是10个周期的共243个数据,因此可以用resample函数对realwave进行重新采样,将采样点提高到250个,那么重采样后每个周期有25个点,将这25个点对应相加求平均值后得到一个周期的值,因为进行了平均,减小了非线性谐波和噪音,然后将这25个数据延托成十个周期即250个点,在利用resample函数对得到的函数重新采样将采样点数恢复到243个。根据以上分析,编写实现这个思路的程序如下:sound_2_2.mclear;clc;load Guitar.mat;wave=resample(realwave,250,243); %重采样,将点数变为250w=zeros(1,25);for i=1:25 for k=0:9 w(i)=w(i)+wave(25*k+i);%10个周期的对应点分别求和 endendw=w/10; %取平均值wave2=repmat(w,1,10); %将1个周期的10个点延拓至250个点wave2=resample(wave2,243,250); %重采样,将点数变回243hold on,plot(wave2,r),hold off; %将处理后的数据绘出,红色hold on,plot(wave2proc); %将所给的数据绘出,蓝色运行后的结果为:由图可见,两组数据重合的很好,说明这种方法是很不错的方法。2.3分析wave2proc的基波和谐波为了分析wave2proc的基波和谐波,可以对wave2proc进行傅里叶变换,得到wave2proc的幅值谱,在频谱图上的第一个突出的波峰对应的频率即为wave2proc基频,利用help fft学习了MATLAB中快速傅里叶变换函数fft的用法,编写了如下程序:clear;clc;load Guitar.mat;fs=8000; NFFT = 2nextpow2(length(wave2proc); Y = fft(wave2proc,NFFT)/length(wave2proc);g = fs/2*linspace(0,1,NFFT/2+1);plot(g,2*abs(Y(1:NFFT/2+1)运行后得到的结果为虽然从图上可以大概看出包络,但是非常不明显,假如提高频域的抽样频率,例如将抽样频率由NFFT = 2nextpow2(length(wave2proc)改为NFFT = 8nextpow2(length(wave2proc)得到的结果如下;由图可见虽然频域的抽样频率提高了很多,但是得到的包络依然不精确,这是因为wave2proc是周期函数,但是现在的wave2proc只有243个数据点,并不能非常明显的体现出其周期性,因此它的幅值谱的离散化程度不高,虽然提高了频域的抽样频率,但是wave2proc数据点的周期性并没有增加,所以要显示出离散化程度高的幅值谱,就要增加wave2proc的周期性,即让wave2proc在时域重复多次后在进行傅里叶变换。利用repmat函数可以将wave2proc在时域重复。将程序修改为sound_2_3.mclear;clc;load Guitar.mat;fs=8000; wave2proc =repmat(wave2proc,20,1);%将wave2proc重复20次NFFT = 2nextpow2(length(wave2proc); Y = fft(wave2proc,NFFT)/length(wave2proc);g = fs/2*linspace(0,1,NFFT/2+1);plot(g,2*abs(Y(1:NFFT/2+1)运行后得到的幅值谱为可以看出幅值谱的离散化程度已经非常高了。由图读出wave2proc的基频为329.1Hz,幅值为0.05401,高次谐波幅值分别为:谐波23456789幅值0.076760.048410.051900.0057090.019230.0067410.0073262.4自动分析fmt.wav的音调和节拍思路分析:将fmt.wav导入后得到的是一个向量,它包含了这段音乐的所有信息,要自动分析这段音乐的音调就需要将每个音调对应的点进行傅里叶变换得到其幅值谱,在幅值谱上找到第一个幅值较大的极大值点,该点对应的就是该音调的基频,得到基频后就可以得到高次谐波的幅值。为了使对每个音调进行傅里叶变换后得到的幅值谱离散程度高,应该将每个音调的数据在时域上重复多次,由于这些点都是直接采集的为做处理的点,因此其重复次数应该足够大才能体现出较强周期性,本实验采用重复1000次,虽然重复次数越多越好,但是次数太大,程序运行的速度会大大降低。这里边还有两个关键点:第一,在从幅值谱上找基频时,因为图上的极大值点很多,怎么能让程序自动确定出准确的基频。第二,在程序找到了基频之后,再由基频去获取高次谐波的幅值时需要有一定的容错能力,例如若基频为200Hz,幅值为1,那么对应的二次谐波的频率为400Hz,但是很可能恰好幅值谱上400Hz处的幅值为0.01,但是401Hz处的幅值为0.2,这时实际上的二次谐波应该为401Hz,但是若没有给基频一个容错范围,显然找到的二次谐波的幅值是不正确的。针对以上提出的两个关键点,我找到了两条有针对性的解决办法。对于第一点,因为幅值谱上极大值点的幅值足够大才能将其定位基频,因此在分析了几个音调后发现基频处的幅值都在0.025以上,因此将基频处的限定条件改为幅值大于0.025的,但是在运行后发现,有几个音调没有分析出来,说明它们的基频幅值小于0.025,其实可以观察一下fmt.wav的波形就会发现,有几段的整体幅值很小,因此基频幅值小,于是又在加上限定条件,若所有点的幅值都小于0.02,那么再用0.015作为幅值的限定条件继续找,这样就将剩下的音调基频也确定出来了。对于上述的第二点,可以将确定出的基频的误差设为+-1Hz,例如程序确定的基频为200Hz,实际的基频应该在(200-1)到(200+1)之间,那么k次谐波对应的频率范围是k*(200-1)到k*(200+1),在这个区间中继续找幅值的极大值点就是k次谐波对应点。根据以上思路,下面开始编写用于分析一个音调频率的函数analysis。在取谐波幅值时,幅值小于基波幅值5%的谐波认为其幅值为0,最终谐波的幅值用归一化后的数据表示。每一步的详细思路见注释。analysis.mfunction y1 y2=analysis(w,a)%设有两个返回值,y1返回频率,y2返回幅值,两个变量,w为待分析数组,a为数据的抽样频率fs=a; %傅里叶变换的抽样频率y1=zeros(1,7);%求最大7次谐波,因此定义1*7矩阵y2=zeros(1,7);NFFT = 2nextpow2(length(w); Y = fft(w,NFFT)/length(w);g = fs/2*linspace(0,1,NFFT/2+1);p=2*abs(Y(1:NFFT/2+1);plot(g,p)%以上为傅里叶变换部分d=floor(NFFT/fs);%将误差1Hz化成对应的点数for k=2:length(p)-1 if (p(k)0.02)&(p(k)p(k-1)&(p(k)p(k+1) %寻找基频的条件 y1(1)=g(k);%存储基频 y2(1)=p(k);%存储基波幅值 breakelseif (p(k)0.015)&(p(k)p(k-1)&(p(k)p(k+1)%若未找到基频,将幅值限制改为0.015,继续寻找 y1(1)=g(k); y2(1)=p(k); endendfor t=2:7 for i=t*(k-d):t*(k+d)%在误差允许的范围内寻找t次谐波点 if (p(k)0.02)&(p(i)0.05*p(k)&(p(i)p(i-1)&(p(i)p(i+1) y2(t)=p(i)/y2(1);%谐波幅值归一化 y1(t)=g(i); break elseif (p(k)0.015)&(p(i)0.05*p(k)&(p(i)p(i-1)&(p(i)p(i+1) y2(t)=p(i)/y2(1); y1(t)=g(i);%这一段循环是与找基频条件相对应的获取高次谐波幅值 end endend在编写完分析函数analysis后即可编写自动分析的主程序。首先在Coool Edit中手动标定音调交界处的时间节点,得到了time向量time=floor(0.096 0.267 1.767 2.234 2.706 3.146 3.606. 4.056 4.520 5.030 5.749 5.978 7.015 7.709 7.923. 8.028 8.490 8.959 9.454 9.852 10.125 10.356. 10.565 10.822 11.292 11.741 12.284 12.741.13.269 13.758 14.315 14.939 15.432/16.384*N);/16.384*N中16.384是fmt.wav的总长度,N为fmt.wav数据点的总数,这一项是为了将时间转换成对应的数据点数,由于点的个数必须是整数,因此用floor函数进行取整。在得到了对应音调交接处的点后就可以进行编程了,用循环一个一个音调分析。程序如下:sound_2_4.mclear;clc;wave=wavread(fmt.wav);%读入文件N=length(wave);%确定数据总数time=floor(0.096 0.267 1.767 2.234 2.706 3.146 3.606. 4.056 4.520 5.030 5.749 5.978 7.015 7.709 7.923. 8.028 8.490 8.959 9.454 9.852 10.125 10.356. 10.565 10.822 11.292 11.741 12.284 12.741. 13.269 13.758 14.315 14.939 15.432/16.384*N); %节点向量fs=N/16.384;%确定数据的抽样频率n=length(time);for k=1:n; if k=1 temp=wave(1:time(k)-1); else temp=wave(time(k-1):time(k)-1);%将第k个音调数据存入temp矩阵 end temp=repmat(temp,1000,1);%将数据重复1000次F(k,1:7) U(k,1:7)=analysis(temp,fs); %将每个音调的处理结果分别保存,F保存频率,U保存幅值end运行后的结果见Excel文件“自动分析结果”。第三部分基于傅里叶级数的音乐合成3.1 用2.3分析出来的结果重新加谐波基频329.1Hz 幅值为0.05401谐波23456789幅值0.076760.048410.051900.0057090.019230.0067410.007326再次完成1.4只需将1.4程序中的波形幅度矩阵m=1 0.3 0.2改为m=0.05401 0.07676 0.04841 0.0519 0.005709 0.01923 0.006791 0.007326;即可3.2 通过2.4提取的吉他音调信息弹奏东方红根据2.4分析的结果可以提取出吉他的音调信息,在“自动分析结果”Excel文件中用黄色标出了出来,一下所用的音调信息用最接近的频率来近似。而所给信息中缺少523.25和587.33的数据,因此用它们的一般来近似频率293.66349.23392523.25587.33近似频率291.97350.65391.942*261.632*295.4511111120.520305440.2757865390.1086165950.3071496930.205838324300.1758122440.06907235600.15708081340000.057298602050.052802710.05603520200.0753863870.08891702260.095940260000700000.065977510将1.4中的程序改为sound_3_2.mfs=8000;%抽样频率f=523.25 523.25 587.33 392 349.23 349.23 293.66 392; %各个乐音对应的频率time=fs*1/2,1/4,1/4,1,1/2,1/4,1/4,1;%各个乐音的抽样点数N=length(time);%这段音乐的总抽样点数east=zeros(1,N);%用east向量来储存抽样点n=1;for num=1:N%利用循环产生抽样数据

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论