一、原理
我们都知道声音其实是一种波,所以要使用Matlab生成一段音乐其重点就是生成该声音的波
。首先我们来看最基本的波是怎么使用Matlab画出来的。使用Matlab画出最简单的正弦波。
1 2 3 4 5
| x = linspace(0, 2*pi, 100); y = sin(x);
plot(x, y)
|
可以看到,该波的波形十分的平滑,这是因为我们在x = linspace(0, 2*pi, 100)
中选择取100个点。其中点的个数100
在一段完整的声音中,叫做采样率
(在一秒钟的声音中,一共取了多少个点)。在Matlab中默认的采样率是8192
,采样范围是1000Hz≤FS≤384000Hz,也就是说采样率必须在此范围内,Matlab才能播放声音。
1 2 3 4 5 6
| % 默认采样率 Fs = 8192; x = linspace(0, 2*pi, Fs); y = sin(x); plot(x, y); title('采样率为8192Hz')
|
该代码表示播放一个周期的声音,之后我们使用sound()
函数,播放其声音。戴上耳机,仔细听会有两声哼
响。(据说这应该听不到,是次声波来着,但我确实听到了/(ㄒoㄒ)/~~)
1 2 3 4 5 6 7
| % 默认采样率 Fs = 8192; x = linspace(0, 2*pi, Fs); y = sin(x); plot(x, y); title('采样率为8192Hz') sound(y, Fs);
|
我们根据乐理知识,有一个标准音高A=440
,所以我们改变代码使其发出标准音高声。可以看到这时候的周期特别的多。
1 2 3 4 5 6 7
| Fs = 8192; x = linspace(0, 2*pi, Fs); y = sin(440*x); plot(x, y); title('采样率为8192Hz') sound(y, Fs);
|
二、探究音高的影响因素
上述,我们已经成功使用Matlab发声,那么影响音高的因素有哪些呢?我们从两个因素考虑:一个是声音的采样率,另一个是声音的频率。使用控制变量法研究以上两个因素。
1 2 3 4 5 6 7 8 9 10 11 12 13
| % 影响音高的因素 % 控制声音频率不变,只改变采样率 Fs1 = 8192; Fs2 = 20000;
x1 = linspace(0, 2*pi, Fs1); x2 = linspace(0, 2*pi, Fs2); y1 = sin(440 * x1); y2 = sin(440 * x2);
sound(y1, Fs1); %请先听完第一个声音再打开y2的注释,并注释y1。 %sound(y2, Fs2);
|
经过测试,两个声音没有任何区别
,如此可以说明,声音的采样率不会对音高产生影响。
1 2 3 4 5 6 7 8 9 10
|
Fz = 8192; x = linspace(0, 2 * pi, Fz); y1 = sin(440 * x); y2 = sin(880 * x);
sound(y1, Fz);
|
经过测试,y2的音高较y1有明显提高
,综上所述,影响声音音高的只有频率
因素。
三、十二平均律
已知声音的音高只与其频率
有关,那么如何才能通过调节频率产生一段优美的音乐呢?下面是来自wiki上的十二平均律表,该表计算的是一个八度的频率表,对于一个八度里的声音我们将其分成12份,这里采用以440Hz为主音
乘以212x,依次得到下个一个音。会发现从440-880
正好跨越一个八度。
下面的十二平均律表最左侧音程名称
中带有#1的表示升,带有b1的表示降。不带升号和降号的可以看作是钢琴的白键,带升号和降号的可以看作是钢琴的黑键。这张表我们不需要全部记下来,我们只需要从小三度(C)
开始记即可(跳过黑键#
),因为C
就是八度中的第一个dou
音。
1 2 3 4 5 6 7 8
| 常用频率 C: 523.2511 D: 587.3295 E: 659.2551 F: 698.4564 G: 783.9908 A: 880 B: 987.7666
|
如此我们就可以得到一个八度了
1 2 3 4 5 6 7 8 9 10 11 12 13
| Fz = 8192; x = linspace(0, 2 * pi, Fz); freqs = [523.2511, 587.3295, 659.2551, 698.4564, 783.9908, 880, 987.7666]; y1 = sin(freqs(1) * x); y2 = sin(freqs(2) * x); y3 = sin(freqs(3) * x); y4 = sin(freqs(4) * x); y5 = sin(freqs(5) * x); y6 = sin(freqs(6) * x); y7 = sin(freqs(7) * x); y = [y1, y2, y3, y4, y5, y6, y7] sound(y, Fz);
|
四、小星星
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| Fs = 8192; x = linspace(0, 2 * pi, Fs);
freqs = [523.2511, 587.3295, 659.2551, 698.4564, 783.9908, 880, 987.7666]; y1 = sin(freqs(1) * x); y2 = sin(freqs(1) * x); y3 = sin(freqs(5) * x); y4 = sin(freqs(5) * x); y5 = sin(freqs(6) * x); y6 = sin(freqs(6) * x); y7 = sin(freqs(5) * x); y8 = sin(freqs(5) * x);
y = [y1, y2, y3, y4, y5, y6, y7, y8]; sound(y, Fs);
|
播放完成后会发现,声音的间隔不是很清楚,我们先看一下y的波形。
如何解决这一问题呢?我们可以通过压缩正弦波解决
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| % 解决声音连在一起的现象 Fz = 8192; x1 = linspace(0, 2*pi, 8192); y1 = sin(x1);
x2 = [0 2 * pi]; y2 = [1, 0];
subplot(1, 2, 1) plot(x1, y1);
subplot(1, 2, 2) plot(x2, y2); % y = 1- x / (2*pi)
|
我们对以上小星星的程序进行改写所有正弦波都乘以1−2πx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| Fs = 8192; x = linspace(0, 2 * pi, Fs); x2 =linspace(0, 2 * pi * 2, Fs * 2); freqs = [523.2511, 587.3295, 659.2551, 698.4564, 783.9908, 880, 987.7666]; y1 = sin(freqs(1) * x) .* (1 - x / ( 2 * pi)); y2 = sin(freqs(1) * x) .* (1 - x / ( 2 * pi)); y3 = sin(freqs(5) * x) .* (1 - x / ( 2 * pi)); y4 = sin(freqs(5) * x) .* (1 - x / ( 2 * pi)); y5 = sin(freqs(6) * x) .* (1 - x / ( 2 * pi)); y6 = sin(freqs(6) * x) .* (1 - x / ( 2 * pi)); y7 = sin(freqs(5) * x2);
y = [y1, y2, y3, y4, y5, y6, y7]; plot(y); sound(y, Fs);
|
最后一个音听着有些不合群
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| Fs = 8192; x = linspace(0, 2 * pi, Fs); x2 =linspace(0, 2 * pi * 2, Fs * 2); freqs = [523.2511, 587.3295, 659.2551, 698.4564, 783.9908, 880, 987.7666]; y1 = sin(freqs(1) * x) .* (1 - x / ( 2 * pi)); y2 = sin(freqs(1) * x) .* (1 - x / ( 2 * pi)); y3 = sin(freqs(5) * x) .* (1 - x / ( 2 * pi)); y4 = sin(freqs(5) * x) .* (1 - x / ( 2 * pi)); y5 = sin(freqs(6) * x) .* (1 - x / ( 2 * pi)); y6 = sin(freqs(6) * x) .* (1 - x / ( 2 * pi)); y7 = sin(freqs(5) * x2) .* (1 - x2 / ( 4 * pi));
y = [y1, y2, y3, y4, y5, y6, y7]; plot(y);
|
五、封装函数
为了简便我们以后完成更长的音乐,可以选择将主要部分封装成函数以便调用。
1 2 3 4 5 6 7 8
| function y = music(tone, rythm)
Fs = 8192; freqs = [523.2511, 587.3295, 659.2551, 698.4564, 783.9908, 880, 987.7666]; x = linspace(0, 2 * pi *rythm, floor(Fs * rythm)); y = sin(freqs(tone) * x) .* (1 - x / (rythm * 2 * pi)); end
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| Fs = 8192;
y1 = music(1, 0.5); y2 = music(1, 0.5); y3 = music(5, 0.5); y4 = music(5, 0.5); y5 = music(6, 0.5); y6 = music(6, 0.5); y7 = music(5, 1); y = [y1, y2, y3, y4, y5, y6, y7];
y1 = music(4, 0.5); y2 = music(4, 0.5); y3 = music(3, 0.5); y4 = music(3, 0.5); y5 = music(2, 0.5); y6 = music(2, 0.5); y7 = music(1, 1); y = [y, y1, y2, y3, y4, y5, y6, y7]; sound(y, Fs)
|