音乐合成大作业实验报告无84王梦娣2008011134音乐合成大作业实验报告无84王梦娣2008111342/24实验报告部分一、简单的音乐合成1.请根据《东方红》片断的简谱和“十二平均律”计算出该片断中各个乐音的频率,在MATLAB中生成幅度为1、抽样频率为8kHz的正弦信号表示这些乐音。请用sound函数播放每个乐音,听一听音调是否正确。最后用这一系列乐音信号拼出《东方红》片断,注意控制每个乐音持续的时间要符合节拍,用sound播放你合成的音乐,听起来感觉如何?问题解答:《东方红》片段:其中所用音符的唱名、音名及对应频率(由十二平均律和相应键数间隔即可导出)如下:(单位是Hz)5562116.2523.25523.25587.33392349.23349.23293.66392用sound播放单音,音调正确。以一拍0.5秒计,播出合成音乐。发现音乐听起来,总体上音调、节拍正确,但乐音无声音强弱变化,两音之间有明显的“啪”的杂声。2.你一定注意到(1)的乐曲中相邻乐音之间有“啪”的杂声,这是由于相位不连续产生了高频分量。这种噪声严重影响合成音乐的质量,丧失真实感。为了消除它,我们可以用图1.5所示包络修正每个乐音,以保证在乐音的邻接处信号幅度为零。此外建议用指数衰减的包络来表示。问题解答:这个问题,实际上我并没有完全理解题意,没有明白是需要乐音之间有重叠,还是没有重叠,所以,我把两种方法都做了一遍,结果发现,用耳朵完全听不出区别。音乐合成大作业实验报告无84王梦娣2008111343/24对于无重叠的包络:我对包络所做的处理是,对于上图折线部分用指数实现,因为题目中有说当主观感受为线性变化时声音的概率实际上呈指数变化。做出的结果的图像如下:00.511.522.533.5400.511.52包络00.511.522.533.54-2-1012加包络后的音乐音乐合成大作业实验报告无84王梦娣2008111344/24有重叠的包络:(处理后的音)从图像上可明显看出有重叠包络和无重叠包络的区别,但是听起来,基本听不出区别。3.请用最简单的方法将(2)中的音乐分别升高和降低一个八度。(提示:音乐播放的时间可以变化)再难一些,请用resample函数(也可以用interp和decimate函数)将上述音乐升高半个音阶。(提示:视计算复杂度,不必特别精确)问题解答:00.050.10.150.20.25-101未处理的一个音符00.050.10.150.20.25-101加包络处理过的音符00.511.522.533.5x104-1.5-1-0.500.511.5音乐合成大作业实验报告无84王梦娣2008111345/24由于题目中已有提示“音乐播放的时间可以变化”,所以很容易就想到用Sample函数实现音调的改变,用Sample函数也确实是最简单的方法。对于升高半个音阶,通过“十二平均律”的方法可知,所谓提高半个音阶,即频率提高2^12≈1.06倍。这也就可以运用resample函数用这个比例重新抽样,这里的关键就是resample函数的应用。4.试着在(2)的音乐中增加一些谐波分量,听一听音乐是否更有“厚度”了?注意谐波分量的能量要小,否则掩盖住基音反而听不清音调了。(如果选择基波幅度为1,二次谐波幅度0:2,三次谐波幅度0:3,听起来像不像象风琴?)问题解答:这里只需要改变各个音的组成,加上各次谐波即可。5.自选其他音乐合成,例如《贝多芬第五交响乐》的开头两小节。问题解答:这里的方法与前面完全相同,只是改变乐谱,映射到技术问题上就是改变基频。二、用傅里叶级数分析音乐现在我们开始要处理真实的音乐信号了!请用load命令载入附件光盘中的数据文件\guitar.mat,工作区会出现两个新的变量realwave和wave2proc(可以用who查看变量名),如图1.6和1.7所示。其中前者是从一段吉他乐曲(附件光盘上的\fmt.wav)中截取下来的真实信号,后者是用信号处理方法得到的这段信号的理论值,它们的抽样率都是8kHz。音乐合成大作业实验报告无84王梦娣2008111346/241.先用wavread函数载入光盘中的fmt.wav文件,播放出来听听效果如何?是否比刚才的合成音乐真实多了。这个只有一个操作,没有代码,直接在操作平台上完成。主要操作如下:FMT=wavread('fmt.wav');figure;plot(FMT);sound(FMT/max(abs(FMT)),8000);听起来这个声音确实比之前真实多了,有金属弹奏的感觉了。画出图像如下:2.你知道待处理的wave2proc是如何从真实值realwave中得到的么?这个预处理过程可以去除真实乐曲中的非线性谐波和噪声,对于正确分析音调是非常重要的。提示:从时域做,可以继续使用resample函数。问题解答:先直接画出两个信号的图像,观察二者区别:02468101214x104-0.8-0.6-0.4-0.200.20.40.6音乐合成大作业实验报告无84王梦娣2008111347/24可明显观察出二者的异同点主要为:二者均近似为周期函数,周期约为整个时间轴的十分之一;但是其区别就是wave2proc的周期性更强一些,realwave中的非线性谐波和噪声大一点。所以,这里对realwave的处理的主要想法是尽可能的减小噪声的干扰,一个很有效的方法就是对其做平均。由于所给信号极其接近十个周期,所以将其分为等长的十段再做平均,同时这里还有一个处理,使用resample函数改变抽样频率,以提高处理精度。处理后的信号与wave2proc的对比如下:(蓝色为我所处理得到的信号,红色为wave2proc)00.0050.010.0150.020.0250.030.035-0.2-0.100.10.2realwavet(8kHzSampled)realwave00.0050.010.0150.020.0250.030.035-0.2-0.100.10.2wave2proct(8kHzSampled)wave2proc音乐合成大作业实验报告无84王梦娣2008111348/243.这段音乐的基频是多少?是哪个音调?请用傅里叶级数或者变换的方法分析它的谐波分量分别是什么。提示:简单的方法是近似取出一个周期求傅里叶级数但这样明显不准确,因为你应该已经发现基音周期不是整数(这里不允许使用resample函数)。复杂些的方法是对整个信号求傅里叶变换(回忆周期性信号的傅里叶变换),但你可能发现无论你如何提高频域的分辨率,也得不到精确的包络(应该近似于冲激函数而不是sinc函数),可选的方法是增加时域的数据量,即再把时域信号重复若干次,看看这样是否效果好多了?请解释之。问题解答:这里对信号直接做FFT,得到的图像如下图所示,得到的幅频特性如下图所示,可见特性并不是特别理想,但如果对此图像进行近似处理,直接取各冲激的极值点也能得到近似的基频值,但是,此处由于所给信号的特殊性,这里可以由较好的处理方法。050100150200250-0.2-0.100.10.2wavet(8kHzSampled)wave050100150200250-0.2-0.100.10.2wave2proct(8kHzSampled)wave2proc音乐合成大作业实验报告无84王梦娣2008111349/24由于可以对realwave信号先做一个延拓,再对其进行FFT变换。(注:这里要说明一下延拓的可行性,其实并不是所有的信号可以直接进行延拓,但是由于这里所给信号realwave信号是极其近似的十个周期,所以进行延拓,对其频谱并没有太大的影响,唯一的影响就是使频谱更接近于冲激,而如果说对一个非整数周期的函数进行延拓,则既有可能导致不可想象的误差,更确切的说应该是“错误”。)用此方法得到的频谱如下,可以直接得到基频及各次谐波的系数:可得出基频约为:F0=329.2181,基波及各次谐波的系数为:050010001500200025003000350040000123456789100500100015002000250030003500400000.20.40.60.81X:329.2Y:0.6863Ffft()音乐合成大作业实验报告无84王梦娣20081113410/241.00001.45720.95871.09990.05230.10990.35890.1240004.再次载入fmt.wav,现在要求你写一段程序,自动分析出这段乐曲的音调和节拍!如果你觉得太难就允许手工标定出每个音调的起止时间,再不行你就把每个音调的数据都单独保存成一个文件,然后让MATLAB对这些文件进行批处理。注意:不允许逐一地手工分析音调。编辑音乐文件,推荐使用”CoolEdit编辑软件。问题解答:这一问我花费的时间最长。开始时是想不到很好的分音方法,经过多次尝试之后,找到了一种比较好的方法,回来又经过多次实验,找到了一组比较好的参数。这之间我主要尝试了对图像进行平滑处理,然后取其包络,进行差值得到一个比较平滑的图像,可是这样做的结果用了好几种方法进行分音,效果都不是很好;然后我返回去直接用原信号进行分音,用了我最后选择的这种方法,效果相当好。其实,我特别不明白这一点,从理论上分析,这一种情况不应该存在啊。后经仔细思考了整个处理过程并与同学讨论之后,觉得出现这种诡异情况的原因可能是一方面由于包络提取的不够好,另一方面就是由于我对包络进行分音处理的方法可能不太好。考虑到对于此音乐的较好的处理,我选择了对原信号进行处理。由于我自己觉得本问比较难,所以这里特别将分音代码具体说明一下:gap=100;dif_min=0.06;length_min=19;lenN=ceil(len/gap);FMT_temp1=[FMT;zeros(gap*lenN-len,1)];FMT_temp2=reshape(FMT_temp1,gap,lenN);FMT_max=(max(FMT_temp2))';positionN=zeros(size(FMT_max));id=1;n=1;positionN(1)=1;whileidlenN音乐合成大作业实验报告无84王梦娣20081113411/24Increase=0;whileidlenN&&FMT_max(id)FMT_max(id+1)Increase=Increase+1;id=id+1;endif(FMT_max(id)-FMT_max(id-Increase)dif_min&&id-positionN(n)=length_min)n=n+1;positionN(n)=id;endid=id+1;endposition=zeros(n+1,1);position(1:n)=(positionN(1:n)-1)*gap+1;position(n+1)=len;cut=0*FMT;cut(position)=1;先把信号拆成长度为100的若干等长段(若总长度不为100的整数倍,则补足0),找出各段的最大值,再从这些点中找出分割点。主要想法就是找突增的点,找到递增沿,其中判断条件FMT_max(id)-FMT_max(id-Increase)dif_min是指增量要大于底限值dif_min,同时id-positionN(n)=length_min的判断条件是要求此处要与上一个分割点的距离大于最小音符的长度,这里我默认最短音符为四分音符(故设置length_min=19(*100),抽样频率为8000),结果验证是正确的,而dif_min是经多次测试得到的。由于在在做的过程中分音的参数主要是针对这个信号的,所以此程序并不特别通用,还有很大的改进空间,但由于能力加时间有限,所以此问题只做到一下这个程度(可能有的地方有一定的误差)。分音结果如下:音乐合成大作业实验报告无84王梦娣20081113412/24分音之后对各段音求基频时,由于有和弦的影响,音的混杂导致某些段的频谱比