
Matlab音乐合成实验报告(重大通院).pdf
21页重庆大学 Matlab 音乐合成实验报告班级:实验班指导老师:印勇学生: 覃继良学号: 20114909 重庆大学通信工程学院音乐合成实验介绍本文共有三大部分:第一部分,简单的音乐合成;第二部分,用傅里叶变换分析音乐;第三部分,基于傅里叶级数的音乐合成由潜入深,一步一步分析了用MATLAB 进行音乐合成的过程通过本实验达到了加深对傅里叶级数和傅里叶分析的理解,熟悉对MATLAB 基本使用的目标第一部分简单的合成音乐1.1 合成《东方红》根据《东方红》第一小节的简谱和十二平均律计算出该小节每个乐音的频率,在MATLAB中生成幅度为 1,抽样频率为 8kHz的正弦信号表示这些乐音,用sound播放合成的音乐由图可知《东方红》的曲调定为F,即 1=F,对应的频率为 349.23Hz,据此可以计算出其他乐音的频率,例如5 对应的频率为7/12 5349.232523.25f,一次类推计算出第一小节各乐音对应的频率为:乐音5 5 6 2 1 1 6 2 频率523.25 523.25 587.33 392 349.23 349.23 293.66 392 在确定了各乐音的频率之后需要确定每个乐音的持续时间。
每小节有两拍,一拍的时间是0.5s ,因此各乐音的持续时间为:乐音5 5 6 2 1 1 6 2 时间0.5 0.25 0.25 1 0.5 0.25 0.25 1 而在MATLAB 中表示乐音所用的抽样频率为fs=8000Hz,也就是所 1s钟内有 8000个点,抽样点数的多少就可表示出每个乐音的持续时间的长短用一个行向量来存储这段音乐对应的抽样点,在用sound函数播放即可根据以上分析在 MATLAB 中编写如下程序:east1.m clear;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); end sound(east,8000); %播放音乐在MATLAB 中运行 east1.m,播放出了《东方红》的第一段,但是可以听出效很不好,只能听出具有《东方红》的调子而已。
图1-1 由图1-1我们可以看到,每一个调子并没有能够区分出来,就是连续一片的幅度也是相当的,都是 11.2 除噪音,加包络在east1 中,连接的音符产生了一个杂音,下面通过加包络来消噪音最简单的包络为指数衰减最简单的指数衰减是对每个音乘以te因子,在实验中首先加的是1.5te的衰减,这种衰减方法使用的是相同速度的衰减,但是发现噪音并没有完全消除,播放的音乐效果不是很好, 感觉音乐起伏性不强 于是采用不同速度的衰减, 根据乐音持续时间的长短来确定衰减的快慢,乐音持续时间越长,衰减的越慢,持续时间越短,衰减的越快在1.1 程序的基础上加上包络,编写如下程序:East2.m clear;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 图像。
更科学的包络如下图所示,每个乐音都经过冲激、衰减、持续、消失四个阶段由上图可以看出这个包络是四段直线段构成的,因此只要确定了每段线段的端点,即可用端点数据写出直线方程, 因此这段包络可以用简单的循环来完成例如认为包络线上的数据如下图所示:包络的通式可以这样表示21 11 21()yyyxxyxx据此在 MATLAB 中编写如下程序:East3.m clear;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); n=1; for num=1:N t=1/fs:1/fs:(time(num))/fs; P=zeros(1,time(num)); X=(time(num))*[0 1/5 333/1000 333/500 1]; Y=[0 1.5 1 1 0]; s=1; b=1:1:time(num); for k=1:4 P(s:X(k+1)-1)=(Y(k+1)-Y(k))/(X(k+1)-X(k))*(b(s:X(k+1)-1)-X(k+1)*ones(1,X(k+1)-s))+Y(k+1)*ones(1,X(k+1)-s); s=X(k+1); endeast(n:n+time(num)-1)=sin(2*pi*f(num)*t).*P(1:time(num)); n=n+time(num); endsound(east,8000); plot(east); 运行得到的图像为:下图是两个乐音交接处的局部放大图,可以清楚地看到前一个乐音一直衰减到0,后一个乐音从 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/122(1.06 )倍,可以利用 resamlpe函数对原来的数据点进行重采样来实现east=resample(east,100,106); 因为resample 进行重新采样后会使每个乐音的持续时间改变,但是因为升高半个音阶,频率改变不大,所以每个音的持续时间是基本不变的1.4 在 1.2 的音乐中加入谐波在1.2 的音乐中加上二、 三、四次谐波,基波幅度为 1, 高次谐波幅度分别为 0.2、 0.3 、 0.1 。
只需将 east3.m 程序改为即可,加颜色部分为修改的部分,加上谐波后音乐效果变得更好了1.5 自选音乐合成——《》曲调为 C,因此可以得到每个乐音对应的频率分别为:561 2 3 5 220 233.08 262.63 293.66 329.63 392 各个乐音对应的持续时间为(单位s)5 5 3 2 3 3 5 1 6550.5 0.25 0.25 0.5 0.5 0.25 0.25 0.25 0.25 0.5 0.5 因此,可以得到如下的程序Music1.m clear;clc; fs=8000; % 抽样频率f=[392 392 329.63 293.66 329.63 329.63 392 262.63 233.08 220 220]; %各个乐音对应的频率time=fs*[0.5,0.25,0.25,0.5,0.5,0.25,0.25,0.25,0.25,0.5,0.5]; % 各个乐音的抽样点数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); %加谐波end east(n:n+time(num)-1)=ss.*P(1:time(num)); n=n+time(num); end sound(2*east,8000); plot(east); 第二部分用傅里叶变换分析音乐2.1 载入 FMT.WAV 并播放利用wavread函数载入,用 sound函数播放,程序如下 : test.m wave=wavread('fmt.wav'); sound(wave) 这段音乐听起来比之前合成的音乐更加真实,因为里边含有丰富的谐波。
2.2 载入文件GUITAR.MAT ,处理原始数据REALWAVE 载入文件 Guitar.mat ,分析 wave2proc是怎么由 realwave 得到的利用load Guitar.mat;载入并用 plot 函数将 realwave 、wave2proc分别画出,得到以下两幅图图2.2-1图2.2-2 可以看到,wave2proc比realwave 的周期性好得多, 去掉了非线性谐波和噪声 在时域做,从图上可以看到, realwave 的数据大约是 10个周期的共 243个数据,因此可以用 resample函数对realwave 进行重新采样,将采样点提高到250个,那么重采样后每个周期有25个点,将这 25个点对应相加求平均值后得到一个周期的值,因为进行了平均, 减小了非线性谐波和噪音, 然后将这 25个数据延托成十个周期即 250个点,在利用 resample函数对得到的函数重新采样将采050100。
