2024年3月11日发(作者:秘豪)
音乐合成大作业
实验报告
无84 王梦娣 2008011134
音乐合成大作业实验报告 无84 王梦娣 200811134
实验报告部分
一、 简单的音乐合成
1. 请根据《东方红》片断的简谱和“十二平均律”计算出该片断中各个乐音的频率,在
MATLAB 中生成幅度为1 、抽样频率为8kHz 的正弦信号表示这些乐音。请用sound 函
数播放每个乐音,听一听音调是否正确。最后用这一系列乐音信号拼出《东方红》片断,
注意控制每个乐音持续的时间要符合节拍,用sound 播放你合成的音乐,听起来感觉
如何?
问题解答:
《东方红》片段:
其中所用音符的唱名、音名及对应频率(由十二平均律和相应键数间隔即可导
出)如下:(单位是Hz)
5
523.25
5
523.25
6
587.33
2
392
1
349.23
1
349.23
6.
293.66
2
392
用sound播放单音,音调正确。以一拍0.5秒计,播出合成音乐。发现音乐听起来,
总体上音调、节拍正确,但乐音无声音强弱变化,两音之间有明显的“啪”的杂声。
2. 你一定注意到(1) 的乐曲中相邻乐音之间有“啪”的杂声,这是由于相位不连续产生了
高频分量。这种噪声严重影响合成音乐的质量,丧失真实感。为了消除它,我们可以用
图1.5 所示包络修正每个乐音,以保证在乐音的邻接处信号幅度为零。此外建议用指数
衰减的包络来表示。
问题解答:
这个问题,实际上我并没有完全理解题意,没有明白是需要乐音之间有重叠,还是
没有重叠,所以,我把两种方法都做了一遍,结果发现,用耳朵完全听不出区别。
2 / 24
音乐合成大作业实验报告 无84 王梦娣 200811134
对于无重叠的包络:
我对包络所做的处理是,对于上图折线部分用指数实现,因为题目中有说当主观感
受为线性变化时声音的概率实际上呈指数变化。做出的结果的图像如下:
包络
2
1.5
1
0.5
0
00.511.522.533.54
加包络后的音乐
2
1
0
-1
-2
00.511.522.533.54
3 / 24
音乐合成大作业实验报告 无84 王梦娣 200811134
未处理的一个音符
1
0
-1
00.050.10.150.20.25
加包络处理过的音符
1
0
-1
00.050.10.150.20.25
有重叠的包络:(处理后的音)
1.5
1
0.5
0
-0.5
-1
-1.5
00.511.522.533.5
x 10
4
从图像上可明显看出有重叠包络和无重叠包络的区别,但是听起来,基本听不出区别。
3. 请用最简单的方法将(2) 中的音乐分别升高和降低一个八度。(提示:音乐播放的时间
可以变化)再难一些,请用resample 函数(也可以用interp 和decimate 函数)将上
述音乐升高半个音阶。(提示:视计算复杂度,不必特别精确)
问题解答:
4 / 24
音乐合成大作业实验报告 无84 王梦娣 200811134
由于题目中已有提示“音乐播放的时间可以变化”,所以很容易就想到用Sample函
数实现音调的改变,用Sample函数也确实是最简单的方法。
对于升高半个音阶,通过“十二平均律”的方法可知,所谓提高半个音阶,即频率提
高2^12≈1.06 倍。这也就可以运用resample函数用这个比例重新抽样,这里的关键就是
resample函数的应用。
4. 试着在(2) 的音乐中增加一些谐波分量,听一听音乐是否更有“厚度”了?注意谐波分
量的能量要小,否则掩盖住基音反而听不清音调了。(如果选择基波幅度为1 ,二次谐
波幅度0:2 ,三次谐波幅度0:3 ,听起来像不像象风琴?)
问题解答:
这里只需要改变各个音的组成,加上各次谐波即可。
5. 自选其他音乐合成,例如《贝多芬第五交响乐》的开头两小节。
问题解答:
这里的方法与前面完全相同,只是改变乐谱,映射到技术问题上就是改变基频。
二、 用傅里叶级数分析音乐
现在我们开始要处理真实的音乐信号了!请用load 命令载入附件光盘中的数据文件
",工作区会出现两个新的变量realwave 和wave2proc (可以用who 查看变量名),
如图1.6 和1.7 所示。其中前者是从一段吉他乐曲(附件光盘上的")中截取下来的
真实信号,后者是用信号处理方法得到的这段信号的理论值,它们的抽样率都是8kHz。
5 / 24
音乐合成大作业实验报告 无84 王梦娣 200811134
1. 先用wavread 函数载入光盘中的 文件,播放出来听听效果如何?是否比刚才
的合成音乐真实多了。
这个只有一个操作,没有代码,直接在操作平台上完成。
主要操作如下:
>> FMT = wavread('');
>> figure;
>> plot(FMT);
>> sound(FMT/max(abs(FMT)),8000);
听起来这个声音确实比之前真实多了,有金属弹奏的感觉了。
画出图像如下:
0.6
0.4
0.2
0
-0.2
-0.4
-0.6
-0.8
x 10
4
2. 你知道待处理的wave2proc 是如何从真实值realwave 中得到的么?这个预处理过程可
以去除真实乐曲中的非线性谐波和噪声,对于正确分析音调是非常重要的。提示:从时
域做,可以继续使用resample 函数。
问题解答:
先直接画出两个信号的图像,观察二者区别:
6 / 24
音乐合成大作业实验报告 无84 王梦娣 200811134
realwave
0.2
r
e
a
l
w
a
v
e
0.1
0
-0.1
-0.2
00.0050.010.0150.02
t(8 kHz Sampled)
wave2proc
0.0250.030.035
0.2
w
a
v
e
2
p
r
o
c
0.1
0
-0.1
-0.2
00.0050.010.0150.02
t(8 kHz Sampled)
0.0250.030.035
可明显观察出二者的异同点主要为:
二者均近似为周期函数,周期约为整个时间轴的十分之一;但是其区别就是
wave2proc的周期性更强一些,realwave中的非线性谐波和噪声大一点。
所以,这里对realwave的处理的主要想法是尽可能的减小噪声的干扰,一个很有效
的方法就是对其做平均。由于所给信号极其接近十个周期,所以将其分为等长的十段再
做平均,同时这里还有一个处理,使用resample函数改变抽样频率,以提高处理精度。
处理后的信号与wave2proc的对比如下:(蓝色为我所处理得到的信号,红色为
wave2proc)
7 / 24
音乐合成大作业实验报告 无84 王梦娣 200811134
wave
0.2
0.1
w
a
v
e
0
-0.1
-0.2
050100150
t(8 kHz Sampled)
wave2proc
200250
0.2
w
a
v
e
2
p
r
o
c
0.1
0
-0.1
-0.2
050100150
t(8 kHz Sampled)
200250
3. 这段音乐的基频是多少?是哪个音调?请用傅里叶级数或者变换的方法分析它的谐波
分量分别是什么。提示:简单的方法是近似取出一个周期求傅里叶级数但这样明显不准
确,因为你应该已经发现基音周期不是整数(这里不允许使用resample 函数)。复杂些
的方法是对整个信号求傅里叶变换(回忆周期性信号的傅里叶变换),但你可能发现无
论你如何提高频域的分辨率,也得不到精确的包络(应该近似于冲激函数而不是sinc 函
数),可选的方法是增加时域的数据量,即再把时域信号重复若干次,看看这样是否效
果好多了?请解释之。
问题解答:
这里对信号直接做FFT,得到的图像如下图所示,得到的幅频特性如下图所示,可
见特性并不是特别理想,但如果对此图像进行近似处理,直接取各冲激的极值点也能得
到近似的基频值,但是,此处由于所给信号的特殊性,这里可以由较好的处理方法。
8 / 24
音乐合成大作业实验报告 无84 王梦娣 200811134
10
9
8
7
6
5
4
3
2
1
0
25004000
由于可以对realwave信号先做一个延拓,再对其进行FFT变换。(注:这里要说明一
下延拓的可行性,其实并不是所有的信号可以直接进行延拓,但是由于这里所给信号
realwave信号是极其近似的十个周期,所以进行延拓,对其频谱并没有太大的影响,唯
一的影响就是使频谱更接近于冲激,而如果说对一个非整数周期的函数进行延拓,则既
有可能导致不可想象的误差,更确切的说应该是“错误”。)
用此方法得到的频谱如下,可以直接得到基频及各次谐波的系数:
1
0.8
X: 329.2
Y: 0.6863
F
f
f
t
(
)
0.6
0.4
0.2
0
25004000
可得出基频约为:F0=329.2181,基波及各次谐波的系数为:
9 / 24
音乐合成大作业实验报告 无84 王梦娣 200811134
1.0000 1.4572 0.9587 1.0999 0.0523 0.1099 0.3589 0.1240
0 0
4. 再次载入 ,现在要求你写一段程序,自动分析出这段乐曲的音调和节拍!如果
你觉得太难就允许手工标定出每个音调的起止时间,再不行你就把每个音调的数据都单
独保存成一个文件,然后让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 ;
while id < lenN
10 / 24
音乐合成大作业实验报告 无84 王梦娣 200811134
Increase = 0 ;
while id < lenN && FMT_max(id) Increase = Increase + 1; id = id + 1; end if( FMT_max(id)-FMT_max(id-Increase)>dif_min && id - positionN(n) >= length_min ) n = n + 1 ; positionN(n) = id ; end id = id + 1 ; end position = 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是经多次测试得到的。由于在在做的过程中分 音的参数主要是针对这个信号的,所以此程序并不特别通用,还有很大的改进空间,但 由于能力加时间有限,所以此问题只做到一下这个程度(可能有的地方有一定的误差)。 分音结果如下: 11 / 24 音乐合成大作业实验报告 无84 王梦娣 200811134 1 0.8 0.6 0.4 0.2 0 x 10 4 分音之后对各段音求基频时,由于有和弦的影响,音的混杂导致某些段的频谱比较 乱,所以还需要进行一定的处理,我的主要想法就是找出各个可能的基频,求出基波以 及它的各次谐波的能量和,取能量最大的就认为它的基波,这样可能会有一定的误差, 但对于批处理来说,这个处理方法的误差还是比较小的。 分出的各段音及其对应的频谱画出如下: 0.2 0.1 0 -0.1 -0.2 05001000 1 1 15 0.4 0.2 0 -0.2 -0.4 0 2 1 80 0.5 0.5 0 0 2500 12 / 24 音乐合成大作业实验报告 无84 王梦娣 200811134 0.4 0.2 0 -0.2 -0.4 2000 3 1 2500 1 0.5 0 -0.5 -1 01000 4 1 12002000 0.5 0.5 0 20002500 0 25004000 0.4 0.2 0 -0.2 -0.4 05001000 5 1 15 0.5 0 -0.5 2000 6 2500 1 0.5 0.5 0 0 25004000 20002500 0.5 0.5 0 0 -0.5 2000 7 2500 -0.5 2000 8 2500 1 1 0.5 0.5 0 20002500 0 20002500 0.5 0.2 0.1 0 0 -0.1 -0.5 2000 9 2500 -0.2 2000 10 25004500 1 1 0.5 0.5 0 20002500 0 0 13 / 24 音乐合成大作业实验报告 无84 王梦娣 200811134 0.2 0.1 0 -0.1 -0.2 0 11 1 4000 0.4 0.2 0 -0.2 -0.4 05001000 12 1 15 0.5 0.5 0 0 0 25004000 0.6 0.4 0.2 0 0.2 0.1 0 -0.1 -0.2 04000 13 1 5000 -0.2 0 14 4000 1 0.5 0.5 0 010001200 0 0 1 0.5 0.5 0 0 -0.5 0 15 4 -0.5 2000 16 2500 1 1 0.5 0.5 0 0 20002500 0.2 0.1 0 -0.1 -0.2 2000 17 1 25004500 0.2 0.1 0 -0.1 -0.2 18 1 2500 0.5 0.5 0 0 0 20002500 14 / 24 音乐合成大作业实验报告 无84 王梦娣 200811134 0.4 0.2 0 -0.2 -0.4 05001000 19 1 15 0.6 0.4 0.2 0 -0.2 20 1 2500 0.5 0.5 0 25004000 0 20002500 0.4 0.2 0 -0.2 -0.4 05001000 21 1 15 0.5 0 -0.5 2000 22 2500 1 0.5 0.5 0 25004000 0 0.4 0.2 0 -0.2 -0.4 20002500 0.4 0.2 0 -0.2 -0.4 2000 23 1 2500 2000 24 25004500 1 0.5 0.5 0 20002500 0 0.4 0.2 0 -0.2 -0.4 0 0.2 0.1 0 -0.1 -0.2 2000 25 1 2500 2000 26 25004500 1 0.5 0.5 0 0 20002500 0 15 / 24 音乐合成大作业实验报告 无84 王梦娣 200811134 0.4 0.2 0 -0.2 -0.4 27 1 2 0.2 0.1 0 -0.1 -0.2 0 28 1 4 0.5 0.5 0 2 0 0.4 0.2 0 -0.2 -0.4 0 29 1 4 0.4 0.2 0 -0.2 -0.4 0 30 1 80 0.5 0.5 0 01600 0 0 然后,对于各音的系数的选择,由于要保留吉他声音的特点,而对于同一音这里可 能会出现多次,谐波系数的选择也是一个问题,这里,最基本的有两种方法,一种就是 做平均,一种是选择最好的一组系数。我这里想要实现的是要找一组最好的,但是所谓 “最好”是要有一个评价标准的,这里我认为这个标准就是“相对能量最大的”(即基 波和各次谐波的能量和用基波能量进行归一化)。(对于音乐我不太了解,并不知道此方 法是否合适,但是仅从信号上来说,我认为这是合理的。) 对于音调和节拍的分析输出结果如下: 音调(对于的正确的基频) 220.0026 220.0026 246.9445 220.0026 220.0026 293.6682 329.6314 196.0000 220.0026 293.6682 293.6682 207.6548 329.6314 329.6314 220.0026 329.6314 220.0026 220.0026 392.0000 349.2323 293.6682 329.6314 246.9445 293.6682 261.6286 246.9445 220.0026 220.0026 220.0026 207.6548 对应的节拍长度(n表示为n分音符) 3 1 2 4 4 2 2 2 2 2 1 4 1 1 1 2 2 2 4 2 3 1 2 1 其中3的出现,可能是分音的不准确所致。 16 / 24 4 2 2 2 2 2 音乐合成大作业实验报告 无84 王梦娣 200811134 最后所得各频率对应的谐波系数(即为吉他中各音的特点): (其中第一个为频率,之后依次为基波和各次谐波的系数,这里用最大值进行了归一化) coffecients = 196.0000 1.0000 0.8374 0.5694 0.1344 0.0892 0.0990 0.1724 0 0 0 207.6548 1.0000 0.5453 0.9237 0 0 0 0 220.0026 0.4343 1.0000 0.4531 0 0 0 0.0625 246.9445 1.0000 0.5699 0.2531 0.0682 0.1245 0.1634 0 261.6286 1.0000 0.4656 0.1676 0 0 0 0 293.6682 1.0000 0.9409 0.2148 0.1068 0 0.1575 0.2526 329.6314 0.7822 1.0000 0.9455 0.4609 0.1279 0.1288 0 349.2323 1.0000 0.2994 0.2224 0 0 0 0 392.0000 1.0000 0.6160 0.1155 0.0540 0 0.5185 0 0.6289 0.0532 0.0860 0 0.0787 0.0598 0.9754 0.0701 0.1944 0 0.0900 0.0650 0 0.6852 0.0700 0.0639 0.2936 0.0976 0 0 17 / 24 音乐合成大作业实验报告 无84 王梦娣 200811134 0 0 0 0 三、 基于傅里叶级数的合成音乐 现在进入了合成音乐的高级境界,我们要用演奏 的吉他合成出一段《东方红》 1. 用6.2.2节(2)计算出来的傅里叶级数再次完成第6.2.1节(4) 题,听一听是否像演奏 的吉他演奏出来的? 问题解答: 这里,实现比较简单,因为6.2.2节(2)计算出来的傅里叶级数即各次谐波的系数已 存储在文件中了,在此处只需要将此数据load进来即可,方法类似于第 6.2.1节(4) 题的方法。 但是合成出来的结果却与吉他音大相径庭,经分析,音色不仅与谐波有关,更与包 络有很大的关系,吉他音的包络应该类似于钢琴的包络,即指数衰减型,但是此处我不 并不想完全改变原来的包络,所以在这里对于之前的包络做了一定的修改,即将持续时 间减少,将衰减时间增长,这样会更接近于指数衰减型包络,听起来也更接近于吉他音。 画出声音信号的图像如下所示: 4 3 2 1 0 -1 -2 -3 -4 00.511.522.533.5 x 10 4 2. 也许(1) 还不是很像,因为对于一把泛音丰富的吉他而言,不可能每个音调对应的泛 音数量和幅度都相同。但是通过完成6.2.2节(4)题,你已经提取出 中的很多 音调,或者说,掌握了每个音调对应的傅里叶级数,大致了解了这把吉他的特征。现 在就来演奏一曲《东方红》吧。提示:如果还是音调信息不够,那就利用相邻音调的 18 / 24 音乐合成大作业实验报告 无84 王梦娣 200811134 信息近似好了,毕竟可以假设吉他的频响是连续变化的。 问题解答: 同第一问,这里只需要将谐波系数改变即可,而谐波系数在前面已经求出,这里只 需选择对应的即可。 注:由于《东方红》中的乐音的频率普遍偏高,所存储的吉他音中基本没有,所以我这 里将《东方红》中的乐音均降了八度,效果也还不错。 所合成的音乐的图像画出如下: 2 1.5 1 0.5 0 -0.5 -1 -1.5 -2 00.511.522.533.5 x 10 4 3. 现在只要你掌握了某乐器足够多的演奏资料,就可以合成出该乐器演奏的任何音 乐,在学完本书后面内容之后,试着做一个图形界面把上述功能封装起来。 问题解答: 这个是很好玩的一个问题,做起来比较轻松。这是这个好玩儿的东西让我感触很深, 下面要详细介绍一下。 首先,最终结果界面如下: 19 / 24 音乐合成大作业实验报告 无84 王梦娣 200811134 其功能主要是输入乐谱,选择一定的乐器,则能自动将音乐用对应的乐器演奏出来。 其中各部分的功能及相应的输入规则一一描述如下: 1. 曲调 这里在opupmenu框中有ABCDFFG七个选项可选,很明显,各个选项分别代表 ABCDEFG大调。 曲调选择 乐器选择 20 / 24 音乐合成大作业实验报告 无84 王梦娣 200811134 2. 唱名&音符长度&音调 这三部分即为乐谱的输入,由于乐谱本身表示的复杂性,所以这里将乐谱的性质分 为这三部分输入。其中: 唱名:输入乐谱对应的1234567即可;(输入时各唱名以空格分开) 音符长度:输入数字n对应是n分音符,如输入‘2’对应的即为二分音符,输入‘4’ 对应的是二分音符;(输入时各音符长度以空格分开) 音调:1为正常,0为降八度,2为升八度。(输入时各音调以空格分开) 3. 乐器 这里有Guitar、Piano、Organ、Flute四个选择,选择对应的乐器即为将乐谱用所选 的乐器演奏。 这里的实现即为选择不同的乐器时使用不同乐器的参数,如果有更多的乐器参数还 可以增加乐器的选择,由于这里材料有限,我将这四种乐器用的均为同一参数,即为前 面所得的吉他的参数(且参数值有限)。 4. Save按钮 此按钮的功能就是将当前所输入的乐谱存储。 5. Add按钮 此按钮的功能主要是将当前输入的乐谱加入到已有的乐谱中,加这个按钮的主要想 法就是防止乐谱过长无法一次同时输入所带来的问题。 6. Sound按钮 此按钮的功能很显然,就是将现在所存储的乐谱用对应的乐器播放出来。 个人对此界面的评价: 1. 外观 这个问题不涉及技术问题,所以在这里并不多说,且在我做的过程中也完全没有考 虑这个问题,做到结构清晰即可。 2. 界面的友好性 这里设置了两个popupmenu框,用于选择曲调和乐器,我自认为这样的设置还是 比较友好的。首先,曲调的选择,每个曲子都有对应的数据,这里设置这样一个选择框, 21 / 24 音乐合成大作业实验报告 无84 王梦娣 200811134 直接有限项选择,不用输入;其次,对于乐器的选择,只要有相应的乐器数据即可完成 对应的功能,避免了只能实现吉他演奏的功能单调性,同时,能够不需要对源程序进行 任何改动即可完成乐器的手动选择。 3. 异常情况的处理 这里主要有一点就是输入数据的不合理性,即输入的唱名&音符长度&音调的个数 不相符,我的主要想法就是以唱名个数为准,其他两个数据,如果数目少了,则在末尾 补足默认值,其中音符长度的默认值为二分音符,音调的默认值为正常,即为1;如果 数目多了的话,则从前到后截取正确数值的元素个数。虽然这样的处理可能对音乐有很 大的影响,或者说会导致很诡异的错误,但是至少这样能够解决程序因为遇到异常而直 接强制退出的不良后果。由于本人是个乐盲,对音乐相当的不了解,所以也没有想到更 好的对于这种情况的异常处理的方法。 4. 整体 由于刚刚接触GUI界面,对一些操作和处理还不是特别熟,所以,这个界面还是存 在一定的问题的,而且应该说存在着很大问题: 首先,乐谱的输入过于复杂,很容易就会导致上述问题,即输入的唱名&音符长度 &音调的个数不相符的问题,这个应该属于算法问题而非技术问题,但是由于乐谱本身 的复杂性,我确实没有想到什么好的方法; 其次,对于sound,输入数据后必须先进行保存才能sound,否则的话,sound出来 是音是系统之前所存储的音。 最后,还是界面友好性的问题,比如说应该按Add的时候按了Save,这就有可能会 导致很大的损失;另外,就是输入规则的问题,我本来的想法是在界面上加一个Help 按钮,点击即可在屏幕上出现一个窗口,显示数据的输入规则,而这个新的窗口也希望 用GUI界面实现,我觉得这样实现起来其实并不难,但是由于时间有限,最终还是没有 实现这个想法,我们只能默认使用我这个窗口的人已知所有的输入规则(„„很不现实)。 最后,其实,还有一个想法,就是在使用者得到一个新的乐器的数据时能够将此数据加 入到此程序中并且在乐器选择框中添加这一选项,或者说用户想删掉某一乐器时,也可 以在界面将其手动删除,而不需要修改源程序。但是由于能力有限加之时间有限,这个 想法就不实现了。 22 / 24 音乐合成大作业实验报告 无84 王梦娣 200811134 实验总结部分 这次作业较第一次作业难度上明显有增加,而且这次涉及到一定的音乐知识,所以我这 次做起来比较吃力,花费了相当长的时间。这次遇到的主要问题在前面大部分都已经提到。 在这个小结中我主要叙述一下我做这次作业的感受。 1. 关于MatLAB&Help 这次做作业我真正的感受到了help的益处。我完全无法想象,没有了help我的MatlAB还会 学到什么程度。实际上我在做作业之前只看了课件,基本了解了下老师课上所讲的一些 方法及函数,当然这些对于算法的设计以及实现上有很大的限制,而实际上对于MatlAB 中本身所提供的函数我一点都不了解,举个例子,某一次在跟同学交流的过程中说到, 我某一部分实现了一个功能,具体来说就是找到极值点,对于极值点的要求就是此极值 点要大于它周围的几个点一定的值,对于这个值我可以自己设定,而同学却告诉我,这 个在MatlAB中有提供findpeaks函数,很容易就实现了„„而我则是扫描加判断实现的, 循环和矩阵处理在效率上差别是很大的啊!这只是一个很简单的问题,还有很多其他的, 各种问题让我发现我对MatlAB有多么的不熟悉,虽然经过这一次作业有了很大的进步, 但是我的MatlAB水平亟待提高啊。 2. 关于音乐 不得不说,对于音乐,我实在很无语,由于我在之前一点都不了解乐理知识,虽然课本 上提供了一些讲解,但是这些远远不够,在做的过程中我遇到了各种诡异的乐音知识盲 区,甚至我都不知道所谓“和弦”是what,这也是导致我这次作业做起来比较吃力的一 个客观原因吧。 3. 感谢 如之前提到的,这次作业遇到了各种诡异的问题,所以在这里要特别感谢在技术上给予 我很大帮助的吴文昊同学,和在乐理知识上给予我极大支持的朱益萱同学! 23 / 24 音乐合成大作业实验报告 无84 王梦娣 200811134 附:代码清单 6.2.1节(1)题 6.2.1节(2)题 简单的合成音乐 (有重叠和无重叠) 6.2.1节(3)题 6.2.1节(4)题 6.2.2节(2)题 用傅里叶级数分析音乐 6.2.2节(3)题 6.2.2节(4)题 6.2.3节(1)题 基于傅里叶级数的合成音乐 6.2.3节(2)题 6.2.3节(3)题 pro1_1_1.m pro1_1_2_1.m pro1_1_2_2.m pro1_1_3.m pro1_1_4.m pro1_2_2.m pro1_2_3.m pro1_2_4.m pro1_3_1m pro1_3_2.m GUI.m 24 / 24
2024年3月11日发(作者:秘豪)
音乐合成大作业
实验报告
无84 王梦娣 2008011134
音乐合成大作业实验报告 无84 王梦娣 200811134
实验报告部分
一、 简单的音乐合成
1. 请根据《东方红》片断的简谱和“十二平均律”计算出该片断中各个乐音的频率,在
MATLAB 中生成幅度为1 、抽样频率为8kHz 的正弦信号表示这些乐音。请用sound 函
数播放每个乐音,听一听音调是否正确。最后用这一系列乐音信号拼出《东方红》片断,
注意控制每个乐音持续的时间要符合节拍,用sound 播放你合成的音乐,听起来感觉
如何?
问题解答:
《东方红》片段:
其中所用音符的唱名、音名及对应频率(由十二平均律和相应键数间隔即可导
出)如下:(单位是Hz)
5
523.25
5
523.25
6
587.33
2
392
1
349.23
1
349.23
6.
293.66
2
392
用sound播放单音,音调正确。以一拍0.5秒计,播出合成音乐。发现音乐听起来,
总体上音调、节拍正确,但乐音无声音强弱变化,两音之间有明显的“啪”的杂声。
2. 你一定注意到(1) 的乐曲中相邻乐音之间有“啪”的杂声,这是由于相位不连续产生了
高频分量。这种噪声严重影响合成音乐的质量,丧失真实感。为了消除它,我们可以用
图1.5 所示包络修正每个乐音,以保证在乐音的邻接处信号幅度为零。此外建议用指数
衰减的包络来表示。
问题解答:
这个问题,实际上我并没有完全理解题意,没有明白是需要乐音之间有重叠,还是
没有重叠,所以,我把两种方法都做了一遍,结果发现,用耳朵完全听不出区别。
2 / 24
音乐合成大作业实验报告 无84 王梦娣 200811134
对于无重叠的包络:
我对包络所做的处理是,对于上图折线部分用指数实现,因为题目中有说当主观感
受为线性变化时声音的概率实际上呈指数变化。做出的结果的图像如下:
包络
2
1.5
1
0.5
0
00.511.522.533.54
加包络后的音乐
2
1
0
-1
-2
00.511.522.533.54
3 / 24
音乐合成大作业实验报告 无84 王梦娣 200811134
未处理的一个音符
1
0
-1
00.050.10.150.20.25
加包络处理过的音符
1
0
-1
00.050.10.150.20.25
有重叠的包络:(处理后的音)
1.5
1
0.5
0
-0.5
-1
-1.5
00.511.522.533.5
x 10
4
从图像上可明显看出有重叠包络和无重叠包络的区别,但是听起来,基本听不出区别。
3. 请用最简单的方法将(2) 中的音乐分别升高和降低一个八度。(提示:音乐播放的时间
可以变化)再难一些,请用resample 函数(也可以用interp 和decimate 函数)将上
述音乐升高半个音阶。(提示:视计算复杂度,不必特别精确)
问题解答:
4 / 24
音乐合成大作业实验报告 无84 王梦娣 200811134
由于题目中已有提示“音乐播放的时间可以变化”,所以很容易就想到用Sample函
数实现音调的改变,用Sample函数也确实是最简单的方法。
对于升高半个音阶,通过“十二平均律”的方法可知,所谓提高半个音阶,即频率提
高2^12≈1.06 倍。这也就可以运用resample函数用这个比例重新抽样,这里的关键就是
resample函数的应用。
4. 试着在(2) 的音乐中增加一些谐波分量,听一听音乐是否更有“厚度”了?注意谐波分
量的能量要小,否则掩盖住基音反而听不清音调了。(如果选择基波幅度为1 ,二次谐
波幅度0:2 ,三次谐波幅度0:3 ,听起来像不像象风琴?)
问题解答:
这里只需要改变各个音的组成,加上各次谐波即可。
5. 自选其他音乐合成,例如《贝多芬第五交响乐》的开头两小节。
问题解答:
这里的方法与前面完全相同,只是改变乐谱,映射到技术问题上就是改变基频。
二、 用傅里叶级数分析音乐
现在我们开始要处理真实的音乐信号了!请用load 命令载入附件光盘中的数据文件
",工作区会出现两个新的变量realwave 和wave2proc (可以用who 查看变量名),
如图1.6 和1.7 所示。其中前者是从一段吉他乐曲(附件光盘上的")中截取下来的
真实信号,后者是用信号处理方法得到的这段信号的理论值,它们的抽样率都是8kHz。
5 / 24
音乐合成大作业实验报告 无84 王梦娣 200811134
1. 先用wavread 函数载入光盘中的 文件,播放出来听听效果如何?是否比刚才
的合成音乐真实多了。
这个只有一个操作,没有代码,直接在操作平台上完成。
主要操作如下:
>> FMT = wavread('');
>> figure;
>> plot(FMT);
>> sound(FMT/max(abs(FMT)),8000);
听起来这个声音确实比之前真实多了,有金属弹奏的感觉了。
画出图像如下:
0.6
0.4
0.2
0
-0.2
-0.4
-0.6
-0.8
x 10
4
2. 你知道待处理的wave2proc 是如何从真实值realwave 中得到的么?这个预处理过程可
以去除真实乐曲中的非线性谐波和噪声,对于正确分析音调是非常重要的。提示:从时
域做,可以继续使用resample 函数。
问题解答:
先直接画出两个信号的图像,观察二者区别:
6 / 24
音乐合成大作业实验报告 无84 王梦娣 200811134
realwave
0.2
r
e
a
l
w
a
v
e
0.1
0
-0.1
-0.2
00.0050.010.0150.02
t(8 kHz Sampled)
wave2proc
0.0250.030.035
0.2
w
a
v
e
2
p
r
o
c
0.1
0
-0.1
-0.2
00.0050.010.0150.02
t(8 kHz Sampled)
0.0250.030.035
可明显观察出二者的异同点主要为:
二者均近似为周期函数,周期约为整个时间轴的十分之一;但是其区别就是
wave2proc的周期性更强一些,realwave中的非线性谐波和噪声大一点。
所以,这里对realwave的处理的主要想法是尽可能的减小噪声的干扰,一个很有效
的方法就是对其做平均。由于所给信号极其接近十个周期,所以将其分为等长的十段再
做平均,同时这里还有一个处理,使用resample函数改变抽样频率,以提高处理精度。
处理后的信号与wave2proc的对比如下:(蓝色为我所处理得到的信号,红色为
wave2proc)
7 / 24
音乐合成大作业实验报告 无84 王梦娣 200811134
wave
0.2
0.1
w
a
v
e
0
-0.1
-0.2
050100150
t(8 kHz Sampled)
wave2proc
200250
0.2
w
a
v
e
2
p
r
o
c
0.1
0
-0.1
-0.2
050100150
t(8 kHz Sampled)
200250
3. 这段音乐的基频是多少?是哪个音调?请用傅里叶级数或者变换的方法分析它的谐波
分量分别是什么。提示:简单的方法是近似取出一个周期求傅里叶级数但这样明显不准
确,因为你应该已经发现基音周期不是整数(这里不允许使用resample 函数)。复杂些
的方法是对整个信号求傅里叶变换(回忆周期性信号的傅里叶变换),但你可能发现无
论你如何提高频域的分辨率,也得不到精确的包络(应该近似于冲激函数而不是sinc 函
数),可选的方法是增加时域的数据量,即再把时域信号重复若干次,看看这样是否效
果好多了?请解释之。
问题解答:
这里对信号直接做FFT,得到的图像如下图所示,得到的幅频特性如下图所示,可
见特性并不是特别理想,但如果对此图像进行近似处理,直接取各冲激的极值点也能得
到近似的基频值,但是,此处由于所给信号的特殊性,这里可以由较好的处理方法。
8 / 24
音乐合成大作业实验报告 无84 王梦娣 200811134
10
9
8
7
6
5
4
3
2
1
0
25004000
由于可以对realwave信号先做一个延拓,再对其进行FFT变换。(注:这里要说明一
下延拓的可行性,其实并不是所有的信号可以直接进行延拓,但是由于这里所给信号
realwave信号是极其近似的十个周期,所以进行延拓,对其频谱并没有太大的影响,唯
一的影响就是使频谱更接近于冲激,而如果说对一个非整数周期的函数进行延拓,则既
有可能导致不可想象的误差,更确切的说应该是“错误”。)
用此方法得到的频谱如下,可以直接得到基频及各次谐波的系数:
1
0.8
X: 329.2
Y: 0.6863
F
f
f
t
(
)
0.6
0.4
0.2
0
25004000
可得出基频约为:F0=329.2181,基波及各次谐波的系数为:
9 / 24
音乐合成大作业实验报告 无84 王梦娣 200811134
1.0000 1.4572 0.9587 1.0999 0.0523 0.1099 0.3589 0.1240
0 0
4. 再次载入 ,现在要求你写一段程序,自动分析出这段乐曲的音调和节拍!如果
你觉得太难就允许手工标定出每个音调的起止时间,再不行你就把每个音调的数据都单
独保存成一个文件,然后让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 ;
while id < lenN
10 / 24
音乐合成大作业实验报告 无84 王梦娣 200811134
Increase = 0 ;
while id < lenN && FMT_max(id) Increase = Increase + 1; id = id + 1; end if( FMT_max(id)-FMT_max(id-Increase)>dif_min && id - positionN(n) >= length_min ) n = n + 1 ; positionN(n) = id ; end id = id + 1 ; end position = 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是经多次测试得到的。由于在在做的过程中分 音的参数主要是针对这个信号的,所以此程序并不特别通用,还有很大的改进空间,但 由于能力加时间有限,所以此问题只做到一下这个程度(可能有的地方有一定的误差)。 分音结果如下: 11 / 24 音乐合成大作业实验报告 无84 王梦娣 200811134 1 0.8 0.6 0.4 0.2 0 x 10 4 分音之后对各段音求基频时,由于有和弦的影响,音的混杂导致某些段的频谱比较 乱,所以还需要进行一定的处理,我的主要想法就是找出各个可能的基频,求出基波以 及它的各次谐波的能量和,取能量最大的就认为它的基波,这样可能会有一定的误差, 但对于批处理来说,这个处理方法的误差还是比较小的。 分出的各段音及其对应的频谱画出如下: 0.2 0.1 0 -0.1 -0.2 05001000 1 1 15 0.4 0.2 0 -0.2 -0.4 0 2 1 80 0.5 0.5 0 0 2500 12 / 24 音乐合成大作业实验报告 无84 王梦娣 200811134 0.4 0.2 0 -0.2 -0.4 2000 3 1 2500 1 0.5 0 -0.5 -1 01000 4 1 12002000 0.5 0.5 0 20002500 0 25004000 0.4 0.2 0 -0.2 -0.4 05001000 5 1 15 0.5 0 -0.5 2000 6 2500 1 0.5 0.5 0 0 25004000 20002500 0.5 0.5 0 0 -0.5 2000 7 2500 -0.5 2000 8 2500 1 1 0.5 0.5 0 20002500 0 20002500 0.5 0.2 0.1 0 0 -0.1 -0.5 2000 9 2500 -0.2 2000 10 25004500 1 1 0.5 0.5 0 20002500 0 0 13 / 24 音乐合成大作业实验报告 无84 王梦娣 200811134 0.2 0.1 0 -0.1 -0.2 0 11 1 4000 0.4 0.2 0 -0.2 -0.4 05001000 12 1 15 0.5 0.5 0 0 0 25004000 0.6 0.4 0.2 0 0.2 0.1 0 -0.1 -0.2 04000 13 1 5000 -0.2 0 14 4000 1 0.5 0.5 0 010001200 0 0 1 0.5 0.5 0 0 -0.5 0 15 4 -0.5 2000 16 2500 1 1 0.5 0.5 0 0 20002500 0.2 0.1 0 -0.1 -0.2 2000 17 1 25004500 0.2 0.1 0 -0.1 -0.2 18 1 2500 0.5 0.5 0 0 0 20002500 14 / 24 音乐合成大作业实验报告 无84 王梦娣 200811134 0.4 0.2 0 -0.2 -0.4 05001000 19 1 15 0.6 0.4 0.2 0 -0.2 20 1 2500 0.5 0.5 0 25004000 0 20002500 0.4 0.2 0 -0.2 -0.4 05001000 21 1 15 0.5 0 -0.5 2000 22 2500 1 0.5 0.5 0 25004000 0 0.4 0.2 0 -0.2 -0.4 20002500 0.4 0.2 0 -0.2 -0.4 2000 23 1 2500 2000 24 25004500 1 0.5 0.5 0 20002500 0 0.4 0.2 0 -0.2 -0.4 0 0.2 0.1 0 -0.1 -0.2 2000 25 1 2500 2000 26 25004500 1 0.5 0.5 0 0 20002500 0 15 / 24 音乐合成大作业实验报告 无84 王梦娣 200811134 0.4 0.2 0 -0.2 -0.4 27 1 2 0.2 0.1 0 -0.1 -0.2 0 28 1 4 0.5 0.5 0 2 0 0.4 0.2 0 -0.2 -0.4 0 29 1 4 0.4 0.2 0 -0.2 -0.4 0 30 1 80 0.5 0.5 0 01600 0 0 然后,对于各音的系数的选择,由于要保留吉他声音的特点,而对于同一音这里可 能会出现多次,谐波系数的选择也是一个问题,这里,最基本的有两种方法,一种就是 做平均,一种是选择最好的一组系数。我这里想要实现的是要找一组最好的,但是所谓 “最好”是要有一个评价标准的,这里我认为这个标准就是“相对能量最大的”(即基 波和各次谐波的能量和用基波能量进行归一化)。(对于音乐我不太了解,并不知道此方 法是否合适,但是仅从信号上来说,我认为这是合理的。) 对于音调和节拍的分析输出结果如下: 音调(对于的正确的基频) 220.0026 220.0026 246.9445 220.0026 220.0026 293.6682 329.6314 196.0000 220.0026 293.6682 293.6682 207.6548 329.6314 329.6314 220.0026 329.6314 220.0026 220.0026 392.0000 349.2323 293.6682 329.6314 246.9445 293.6682 261.6286 246.9445 220.0026 220.0026 220.0026 207.6548 对应的节拍长度(n表示为n分音符) 3 1 2 4 4 2 2 2 2 2 1 4 1 1 1 2 2 2 4 2 3 1 2 1 其中3的出现,可能是分音的不准确所致。 16 / 24 4 2 2 2 2 2 音乐合成大作业实验报告 无84 王梦娣 200811134 最后所得各频率对应的谐波系数(即为吉他中各音的特点): (其中第一个为频率,之后依次为基波和各次谐波的系数,这里用最大值进行了归一化) coffecients = 196.0000 1.0000 0.8374 0.5694 0.1344 0.0892 0.0990 0.1724 0 0 0 207.6548 1.0000 0.5453 0.9237 0 0 0 0 220.0026 0.4343 1.0000 0.4531 0 0 0 0.0625 246.9445 1.0000 0.5699 0.2531 0.0682 0.1245 0.1634 0 261.6286 1.0000 0.4656 0.1676 0 0 0 0 293.6682 1.0000 0.9409 0.2148 0.1068 0 0.1575 0.2526 329.6314 0.7822 1.0000 0.9455 0.4609 0.1279 0.1288 0 349.2323 1.0000 0.2994 0.2224 0 0 0 0 392.0000 1.0000 0.6160 0.1155 0.0540 0 0.5185 0 0.6289 0.0532 0.0860 0 0.0787 0.0598 0.9754 0.0701 0.1944 0 0.0900 0.0650 0 0.6852 0.0700 0.0639 0.2936 0.0976 0 0 17 / 24 音乐合成大作业实验报告 无84 王梦娣 200811134 0 0 0 0 三、 基于傅里叶级数的合成音乐 现在进入了合成音乐的高级境界,我们要用演奏 的吉他合成出一段《东方红》 1. 用6.2.2节(2)计算出来的傅里叶级数再次完成第6.2.1节(4) 题,听一听是否像演奏 的吉他演奏出来的? 问题解答: 这里,实现比较简单,因为6.2.2节(2)计算出来的傅里叶级数即各次谐波的系数已 存储在文件中了,在此处只需要将此数据load进来即可,方法类似于第 6.2.1节(4) 题的方法。 但是合成出来的结果却与吉他音大相径庭,经分析,音色不仅与谐波有关,更与包 络有很大的关系,吉他音的包络应该类似于钢琴的包络,即指数衰减型,但是此处我不 并不想完全改变原来的包络,所以在这里对于之前的包络做了一定的修改,即将持续时 间减少,将衰减时间增长,这样会更接近于指数衰减型包络,听起来也更接近于吉他音。 画出声音信号的图像如下所示: 4 3 2 1 0 -1 -2 -3 -4 00.511.522.533.5 x 10 4 2. 也许(1) 还不是很像,因为对于一把泛音丰富的吉他而言,不可能每个音调对应的泛 音数量和幅度都相同。但是通过完成6.2.2节(4)题,你已经提取出 中的很多 音调,或者说,掌握了每个音调对应的傅里叶级数,大致了解了这把吉他的特征。现 在就来演奏一曲《东方红》吧。提示:如果还是音调信息不够,那就利用相邻音调的 18 / 24 音乐合成大作业实验报告 无84 王梦娣 200811134 信息近似好了,毕竟可以假设吉他的频响是连续变化的。 问题解答: 同第一问,这里只需要将谐波系数改变即可,而谐波系数在前面已经求出,这里只 需选择对应的即可。 注:由于《东方红》中的乐音的频率普遍偏高,所存储的吉他音中基本没有,所以我这 里将《东方红》中的乐音均降了八度,效果也还不错。 所合成的音乐的图像画出如下: 2 1.5 1 0.5 0 -0.5 -1 -1.5 -2 00.511.522.533.5 x 10 4 3. 现在只要你掌握了某乐器足够多的演奏资料,就可以合成出该乐器演奏的任何音 乐,在学完本书后面内容之后,试着做一个图形界面把上述功能封装起来。 问题解答: 这个是很好玩的一个问题,做起来比较轻松。这是这个好玩儿的东西让我感触很深, 下面要详细介绍一下。 首先,最终结果界面如下: 19 / 24 音乐合成大作业实验报告 无84 王梦娣 200811134 其功能主要是输入乐谱,选择一定的乐器,则能自动将音乐用对应的乐器演奏出来。 其中各部分的功能及相应的输入规则一一描述如下: 1. 曲调 这里在opupmenu框中有ABCDFFG七个选项可选,很明显,各个选项分别代表 ABCDEFG大调。 曲调选择 乐器选择 20 / 24 音乐合成大作业实验报告 无84 王梦娣 200811134 2. 唱名&音符长度&音调 这三部分即为乐谱的输入,由于乐谱本身表示的复杂性,所以这里将乐谱的性质分 为这三部分输入。其中: 唱名:输入乐谱对应的1234567即可;(输入时各唱名以空格分开) 音符长度:输入数字n对应是n分音符,如输入‘2’对应的即为二分音符,输入‘4’ 对应的是二分音符;(输入时各音符长度以空格分开) 音调:1为正常,0为降八度,2为升八度。(输入时各音调以空格分开) 3. 乐器 这里有Guitar、Piano、Organ、Flute四个选择,选择对应的乐器即为将乐谱用所选 的乐器演奏。 这里的实现即为选择不同的乐器时使用不同乐器的参数,如果有更多的乐器参数还 可以增加乐器的选择,由于这里材料有限,我将这四种乐器用的均为同一参数,即为前 面所得的吉他的参数(且参数值有限)。 4. Save按钮 此按钮的功能就是将当前所输入的乐谱存储。 5. Add按钮 此按钮的功能主要是将当前输入的乐谱加入到已有的乐谱中,加这个按钮的主要想 法就是防止乐谱过长无法一次同时输入所带来的问题。 6. Sound按钮 此按钮的功能很显然,就是将现在所存储的乐谱用对应的乐器播放出来。 个人对此界面的评价: 1. 外观 这个问题不涉及技术问题,所以在这里并不多说,且在我做的过程中也完全没有考 虑这个问题,做到结构清晰即可。 2. 界面的友好性 这里设置了两个popupmenu框,用于选择曲调和乐器,我自认为这样的设置还是 比较友好的。首先,曲调的选择,每个曲子都有对应的数据,这里设置这样一个选择框, 21 / 24 音乐合成大作业实验报告 无84 王梦娣 200811134 直接有限项选择,不用输入;其次,对于乐器的选择,只要有相应的乐器数据即可完成 对应的功能,避免了只能实现吉他演奏的功能单调性,同时,能够不需要对源程序进行 任何改动即可完成乐器的手动选择。 3. 异常情况的处理 这里主要有一点就是输入数据的不合理性,即输入的唱名&音符长度&音调的个数 不相符,我的主要想法就是以唱名个数为准,其他两个数据,如果数目少了,则在末尾 补足默认值,其中音符长度的默认值为二分音符,音调的默认值为正常,即为1;如果 数目多了的话,则从前到后截取正确数值的元素个数。虽然这样的处理可能对音乐有很 大的影响,或者说会导致很诡异的错误,但是至少这样能够解决程序因为遇到异常而直 接强制退出的不良后果。由于本人是个乐盲,对音乐相当的不了解,所以也没有想到更 好的对于这种情况的异常处理的方法。 4. 整体 由于刚刚接触GUI界面,对一些操作和处理还不是特别熟,所以,这个界面还是存 在一定的问题的,而且应该说存在着很大问题: 首先,乐谱的输入过于复杂,很容易就会导致上述问题,即输入的唱名&音符长度 &音调的个数不相符的问题,这个应该属于算法问题而非技术问题,但是由于乐谱本身 的复杂性,我确实没有想到什么好的方法; 其次,对于sound,输入数据后必须先进行保存才能sound,否则的话,sound出来 是音是系统之前所存储的音。 最后,还是界面友好性的问题,比如说应该按Add的时候按了Save,这就有可能会 导致很大的损失;另外,就是输入规则的问题,我本来的想法是在界面上加一个Help 按钮,点击即可在屏幕上出现一个窗口,显示数据的输入规则,而这个新的窗口也希望 用GUI界面实现,我觉得这样实现起来其实并不难,但是由于时间有限,最终还是没有 实现这个想法,我们只能默认使用我这个窗口的人已知所有的输入规则(„„很不现实)。 最后,其实,还有一个想法,就是在使用者得到一个新的乐器的数据时能够将此数据加 入到此程序中并且在乐器选择框中添加这一选项,或者说用户想删掉某一乐器时,也可 以在界面将其手动删除,而不需要修改源程序。但是由于能力有限加之时间有限,这个 想法就不实现了。 22 / 24 音乐合成大作业实验报告 无84 王梦娣 200811134 实验总结部分 这次作业较第一次作业难度上明显有增加,而且这次涉及到一定的音乐知识,所以我这 次做起来比较吃力,花费了相当长的时间。这次遇到的主要问题在前面大部分都已经提到。 在这个小结中我主要叙述一下我做这次作业的感受。 1. 关于MatLAB&Help 这次做作业我真正的感受到了help的益处。我完全无法想象,没有了help我的MatlAB还会 学到什么程度。实际上我在做作业之前只看了课件,基本了解了下老师课上所讲的一些 方法及函数,当然这些对于算法的设计以及实现上有很大的限制,而实际上对于MatlAB 中本身所提供的函数我一点都不了解,举个例子,某一次在跟同学交流的过程中说到, 我某一部分实现了一个功能,具体来说就是找到极值点,对于极值点的要求就是此极值 点要大于它周围的几个点一定的值,对于这个值我可以自己设定,而同学却告诉我,这 个在MatlAB中有提供findpeaks函数,很容易就实现了„„而我则是扫描加判断实现的, 循环和矩阵处理在效率上差别是很大的啊!这只是一个很简单的问题,还有很多其他的, 各种问题让我发现我对MatlAB有多么的不熟悉,虽然经过这一次作业有了很大的进步, 但是我的MatlAB水平亟待提高啊。 2. 关于音乐 不得不说,对于音乐,我实在很无语,由于我在之前一点都不了解乐理知识,虽然课本 上提供了一些讲解,但是这些远远不够,在做的过程中我遇到了各种诡异的乐音知识盲 区,甚至我都不知道所谓“和弦”是what,这也是导致我这次作业做起来比较吃力的一 个客观原因吧。 3. 感谢 如之前提到的,这次作业遇到了各种诡异的问题,所以在这里要特别感谢在技术上给予 我很大帮助的吴文昊同学,和在乐理知识上给予我极大支持的朱益萱同学! 23 / 24 音乐合成大作业实验报告 无84 王梦娣 200811134 附:代码清单 6.2.1节(1)题 6.2.1节(2)题 简单的合成音乐 (有重叠和无重叠) 6.2.1节(3)题 6.2.1节(4)题 6.2.2节(2)题 用傅里叶级数分析音乐 6.2.2节(3)题 6.2.2节(4)题 6.2.3节(1)题 基于傅里叶级数的合成音乐 6.2.3节(2)题 6.2.3节(3)题 pro1_1_1.m pro1_1_2_1.m pro1_1_2_2.m pro1_1_3.m pro1_1_4.m pro1_2_2.m pro1_2_3.m pro1_2_4.m pro1_3_1m pro1_3_2.m GUI.m 24 / 24