问题描述
前几天在学习matlab的时候,发现了一篇用matlab演奏音乐的文章,不禁感叹matlab居然还能这么玩!于是我就学着用matlab演奏我最喜欢听的一首歌——周杰伦的《七里香》。最后成果我已经发到B站,链接为:用matlab演奏周杰伦的《七里香》。
matlab播放音乐的原理
matlab播放音乐是由sound(Y,fs,bits)函数完成的,该函数的3个参数代表输入信号、采样率、比特率。先说采样率fs的设置,人耳能够听到的声音范围是20~20000Hz。根据采样定理fs只需要大于40000即可。此处采样率的设置采用了MP3的标准,即fs=44.1k.再说输入信号Y,Y一般是一个正弦波,如A* sin(2* pi* w* t)。其中A控制着声音的大小,w控制着声音的高低,t的范围控制着声音的长短,所以理论上利用这个公式可以发出任何声音,只是不能控制音色和音质(音色音质很难用参数量化,我问了一下学语音的同学,这个东西跟音频谱重心,音频扩展度和音频谱平坦度有关系,这里不作讨论)。比特率采用默认值即可,该参数省略。
于是用下面的公式就可以播放出标准音la:(座机电话提示音就是la,可以用来调吉他)
fs=44100;
t=0: 1/fs: 0.5;
la = sin(2* pi* 440* t); (下文介绍440是怎么来的)
sound(la, fs)
下面介绍一下简单乐理:
看过柯南的同学都知道,音高和频率是指数的关系,它们满足下面的公式,其中p是音高,f是频率
f=440*2^((p-69)/12)
标准音la,即钢琴的A4键,定义为p=69。音高每上升一个半音,p加1。
如上图所示,从C4到B4分别对应着do re mi fa sol la xi,它们的p值分别为 60 62 64 65 67 69 71,注意中间有黑键,你也可以根据下表来查询某个音的频率。
Frequency in hertz (semitones above or below middle C) | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
Octave→ Note↓ | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
C | 16.352 (−48) | 32.703 (−36) | 65.406 (−24) | 130.81 (−12) | 261.63 (0) | 523.25 (+12) | 1046.5 (+24) | 2093.0 (+36) | 4186.0 (+48) | 8372.0 (+60) |
C♯/D♭ | 17.324 (−47) | 34.648 (−35) | 69.296 (−23) | 138.59 (−11) | 277.18 (+1) | 554.37 (+13) | 1108.7 (+25) | 2217.5 (+37) | 4434.9 (+49) | 8869.8 (+61) |
D | 18.354 (−46) | 36.708 (−34) | 73.416 (−22) | 146.83 (−10) | 293.66 (+2) | 587.33 (+14) | 1174.7 (+26) | 2349.3 (+38) | 4698.6 (+50) | 9397.3 (+62) |
D♯/E♭ | 19.445 (−45) | 38.891 (−33) | 77.782 (−21) | 155.56 (−9) | 311.13 (+3) | 622.25 (+15) | 1244.5 (+27) | 2489.0 (+39) | 4978.0 (+51) | 9956.1 (+63) |
E | 20.602 (−44) | 41.203 (−32) | 82.407 (−20) | 164.81 (−8) | 329.63 (+4) | 659.26 (+16) | 1318.5 (+28) | 2637.0 (+40) | 5274.0 (+52) | 10548 (+64) |
F | 21.827 (−43) | 43.654 (−31) | 87.307 (−19) | 174.61 (−7) | 349.23 (+5) | 698.46 (+17) | 1396.9 (+29) | 2793.8 (+41) | 5587.7 (+53) | 11175 (+65) |
F♯/G♭ | 23.125 (−42) | 46.249 (−30) | 92.499 (−18) | 185.00 (−6) | 369.99 (+6) | 739.99 (+18) | 1480.0 (+30) | 2960.0 (+42) | 5919.9 (+54) | 11840 (+66) |
G | 24.500 (−41) | 48.999 (−29) | 97.999 (−17) | 196.00 (−5) | 392.00 (+7) | 783.99 (+19) | 1568.0 (+31) | 3136.0 (+43) | 6271.9 (+55) | 12544 (+67) |
G♯/A♭ | 25.957 (−40) | 51.913 (−28) | 103.83 (−16) | 207.65 (−4) | 415.30 (+8) | 830.61 (+20) | 1661.2 (+32) | 3322.4 (+44) | 6644.9 (+56) | 13290 (+68) |
A | 27.500 (−39) | 55.000 (−27) | 110.00 (−15) | 220.00 (−3) | 440.00 (+9) | 880.00 (+21) | 1760.0 (+33) | 3520.0 (+45) | 7040.0 (+57) | 14080 (+69) |
A♯/B♭ | 29.135 (−38) | 58.270 (−26) | 116.54 (−14) | 233.08 (−2) | 466.16 (+10) | 932.33 (+22) | 1864.7 (+34) | 3729.3 (+46) | 7458.6 (+58) | 14917 (+70) |
B | 30.868 (−37) | 61.735 (−25) | 123.47 (−13) | 246.94 (−1) | 493.88 (+11) | 987.77 (+23) | 1975.5 (+35) | 3951.1 (+47) | 7902.1 (+59) | 15804 (+71) |
有了上面的基础,下面就可以用matlab创作歌曲了。
用matlab演奏的过程
目标音乐的简谱
首先需要搜索目标音乐的简谱。以本文创作的“七里香”为例,在“百度图片”上就能够找到相应的简谱。
对音符的定义
在这个过程中,需要对节拍稍作注意,最常见的像四分之一拍,八分之一拍,以及十六分之一拍。
以四分之一拍的do为例:
do1f= mod4.* cos(2* pi* ScaleTable(5)* f0* t4);
其中涉及节拍,音调以及频率。mod4,ScaleTable及t4的定义,可参见帖子最后的源码。
分享几点我在编程过程中绕的弯路:
像图中所示的这种情况,最初我也是分别做两个do音符数据输出,但是整体听下来的效果比较奇怪,也因为我在乐理基础上的欠缺。
最终,我处理的方式是,这两个个音符作为一个5/16拍的do输出,这样听起来的效果会相对连续些,不知道从音乐方面来看,这么处理的方式是否正确。
类似的情况,这幅图中的mi,可作为3/16拍的mi输出。
那么针对这些情况,需要在节拍以及时间间隔定义上,额外再定义5/16拍,3/16拍等情况的数据。
还有这种情况,两个不同的音符连成一个音节。如果分别用1/16拍的fa和1/8拍的mi输出的话,中间会有所停顿,听起来不够连贯。所以我直接用3/16拍的fa输出,这样听起来只是略微和原曲不同,而不会让人感觉不连贯。
乐谱的定义
在最基本的音符定义完之后,就可以着手通过音符来定义乐谱了。根据简谱依次用所定义的音符定义一个声音矩阵:
violin = [mi1e fa1e so1e mi1f fa1e so1e ti1e];
如果出现有和弦的情况,以同样的方式定义和弦的曲子,并与violin的声音矩阵做加法处理。
之后通过sound函数就能够听到整首歌的效果:
sound(s,fs);
同时,如果你想保存这首歌的话,可以通过audiowrite函数来实现:
audiowrite(‘Qilixiang.wav’,violin,fs)
另外,如果已经有一个音频文件想通过Matlab处理,可以通过audioread函数来读取该音频文件:
audioread(‘Qilixiang.wav’)
以上就是实现Matlab演奏歌曲的整个过程,接下来附上我的源代码,如果你有兴趣想用该代码实现别的歌曲的演奏,只需要将violin矩阵中的乐谱矩阵稍作修改,就能实现你所需的效果。
源代码:
fs = 44100;
dt = 1/fs;
T16 = 0.2;
t16 = [0:dt:T16];
[temp k] = size(t16);
t2 = linspace(0,8*T16,8*k);
t3 = linspace(0,7*T16,7*k);%7/16拍
t4_25=linspace(0,5*T16,5*k);%5/16拍
t4 = linspace(0,4*T16,4*k);
t6 = linspace(0,3*T16,3*k);%3/16拍
t8 = linspace(0,2*T16,2*k);
[temp i] = size(t4);
[temp j] = size(t8);mod2 = sin(pi*t2/t2(end));
mod3= sin(pi*t3/t3(end));
mod4 = sin(pi*t4/t4(end));
mod4_25= sin(pi*t4_25/t4_25(end));
mod6 = sin(pi*t6/t6(end));
mod8 = sin(pi*t8/t8(end));
mod16 = sin(pi*t16/t16(end));
f0 = 2*146.8;
ScaleTable = [2/3 3/4 5/6 15/16 ...
1 9/8 5/4 4/3 3/2 5/3 9/5 15/8 ...
2 9/4 5/2 8/3 3 10/3 15/4 4 ...
1/2 9/16 5/8];% 1/4 notes
do0f = mod4.*cos(2*pi*ScaleTable(21)*f0*t4);
re0f = mod4.*cos(2*pi*ScaleTable(22)*f0*t4);
mi0f = mod4.*cos(2*pi*ScaleTable(23)*f0*t4);
fa0f = mod4.*cos(2*pi*ScaleTable(1)*f0*t4);
so0f = mod4.*cos(2*pi*ScaleTable(2)*f0*t4);
la0f = mod4.*cos(2*pi*ScaleTable(3)*f0*t4);
ti0f = mod4.*cos(2*pi*ScaleTable(4)*f0*t4);
do1f = mod4.*cos(2*pi*ScaleTable(5)*f0*t4);
re1f = mod4.*cos(2*pi*ScaleTable(6)*f0*t4);
mi1f = mod4.*cos(2*pi*ScaleTable(7)*f0*t4);
fa1f = mod4.*cos(2*pi*ScaleTable(8)*f0*t4);
so1f = mod4.*cos(2*pi*ScaleTable(9)*f0*t4);
la1f = mod4.*cos(2*pi*ScaleTable(10)*f0*t4);
tb1f = mod4.*cos(2*pi*ScaleTable(11)*f0*t4);
ti1f = mod4.*cos(2*pi*ScaleTable(12)*f0*t4);
do2f = mod4.*cos(2*pi*ScaleTable(13)*f0*t4);
re2f = mod4.*cos(2*pi*ScaleTable(14)*f0*t4);
mi2f = mod4.*cos(2*pi*ScaleTable(15)*f0*t4);
fa2f = mod4.*cos(2*pi*ScaleTable(16)*f0*t4);
so2f = mod4.*cos(2*pi*ScaleTable(17)*f0*t4);
la2f = mod4.*cos(2*pi*ScaleTable(18)*f0*t4);
ti2f = mod4.*cos(2*pi*ScaleTable(19)*f0*t4);
do3f = mod4.*cos(2*pi*ScaleTable(20)*f0*t4);
blkf = zeros(1,i);% 1/8 notes
do0e = mod8.*cos(2*pi*ScaleTable(21)*f0*t8);
fa0e = mod8.*cos(2*pi*ScaleTable(1)*f0*t8);
so0e = mod8.*cos(2*pi*ScaleTable(2)*f0*t8);
la0e = mod8.*cos(2*pi*ScaleTable(3)*f0*t8);
ti0e = mod8.*cos(2*pi*ScaleTable(4)*f0*t8);
do1e = mod8.*cos(2*pi*ScaleTable(5)*f0*t8);
do1_6 = mod6.*cos(2*pi*ScaleTable(5)*f0*t6);
re1e = mod8.*cos(2*pi*ScaleTable(6)*f0*t8);
mi1e = mod8.*cos(2*pi*ScaleTable(7)*f0*t8);
mi1_6= mod6.*cos(2*pi*ScaleTable(7)*f0*t6);
fa1e = mod8.*cos(2*pi*ScaleTable(8)*f0*t8);
fa1_6=mod6.*cos(2*pi*ScaleTable(8)*f0*t6);
so1e = mod8.*cos(2*pi*ScaleTable(9)*f0*t8);
so1_2= mod2.*cos(2*pi*ScaleTable(9)*f0*t2);
so1_3= mod3.*cos(2*pi*ScaleTable(9)*f0*t3);
la1e = mod8.*cos(2*pi*ScaleTable(10)*f0*t8);
la1_6 = mod6.*cos(2*pi*ScaleTable(10)*f0*t6);
tb1e = mod8.*cos(2*pi*ScaleTable(11)*f0*t8);
ti1e = mod8.*cos(2*pi*ScaleTable(12)*f0*t8);
do2e = mod8.*cos(2*pi*ScaleTable(13)*f0*t8);
do2_4_25= mod4_25.*cos(2*pi*ScaleTable(13)*f0*t4_25);
do2_6=mod6.*cos(2*pi*ScaleTable(13)*f0*t6);
re2e = mod8.*cos(2*pi*ScaleTable(14)*f0*t8);
re2_6 = mod6.*cos(2*pi*ScaleTable(14)*f0*t6);
mi2e = mod8.*cos(2*pi*ScaleTable(15)*f0*t8);
mi2_6 = mod6.*cos(2*pi*ScaleTable(15)*f0*t6);
fa2e = mod8.*cos(2*pi*ScaleTable(16)*f0*t8);
fa2_6 = mod6.*cos(2*pi*ScaleTable(16)*f0*t6);
so2e = mod8.*cos(2*pi*ScaleTable(17)*f0*t8);
la2e = mod8.*cos(2*pi*ScaleTable(18)*f0*t8);
ti2e = mod8.*cos(2*pi*ScaleTable(19)*f0*t8);
do3e = mod8.*cos(2*pi*ScaleTable(20)*f0*t8);
blke = zeros(1,j);% 1/16 notes
fa0s = mod16.*cos(2*pi*ScaleTable(1)*f0*t16);
so0s = mod16.*cos(2*pi*ScaleTable(2)*f0*t16);
la0s = mod16.*cos(2*pi*ScaleTable(3)*f0*t16);
ti0s = mod16.*cos(2*pi*ScaleTable(4)*f0*t16);
do1s = mod16.*cos(2*pi*ScaleTable(5)*f0*t16);
re1s = mod16.*cos(2*pi*ScaleTable(6)*f0*t16);
mi1s = mod16.*cos(2*pi*ScaleTable(7)*f0*t16);
fa1s = mod16.*cos(2*pi*ScaleTable(8)*f0*t16);
so1s = mod16.*cos(2*pi*ScaleTable(9)*f0*t16);
la1s = mod16.*cos(2*pi*ScaleTable(10)*f0*t16);
tb1s = mod16.*cos(2*pi*ScaleTable(11)*f0*t16);
ti1s = mod16.*cos(2*pi*ScaleTable(12)*f0*t16);
do2s = mod16.*cos(2*pi*ScaleTable(13)*f0*t16);
re2s = mod16.*cos(2*pi*ScaleTable(14)*f0*t16);
mi2s = mod16.*cos(2*pi*ScaleTable(15)*f0*t16);
fa2s = mod16.*cos(2*pi*ScaleTable(16)*f0*t16);
so2s = mod16.*cos(2*pi*ScaleTable(17)*f0*t16);
la2s = mod16.*cos(2*pi*ScaleTable(18)*f0*t16);
ti2s = mod16.*cos(2*pi*ScaleTable(19)*f0*t16);
do3s = mod16.*cos(2*pi*ScaleTable(20)*f0*t16);
blks = zeros(1,k);violin = [blke so1e...
do2f ti1e do2s do2_4_25 blke do2e...
do2e ti1e la1e ti1s la1_6 so1f so1e...
so1f fa1e mi1s so1_3 so1e...
so1e la1_6 re1e fa1s fa1_6 mi1f so1e...
do2f ti1e do2s do2_4_25 blke do2e...
do2e ti1e do2e re2s re2_6 do2e do2e ti1e...
do2e do2s do2_6 ti1e ti1e la1e la1e ti1s la1s...
so1_2 blkf so1e do2e...
do2f mi1e la1e la1f so1e re2e...
re2f re1e fa1s fa1_6 mi1e blke so1e...
so1e fa1e fa1e mi1s mi1_6 re1e re1e do1e...
mi1e re1f fa1e mi1f so1e do2e...
do2f mi1e la1e la1e so1e so1e re2e...
re2e re1e re1e fa1e mi1e so1e so1e mi2e...
mi2e re2e re2e do2e do2e re2e do2e mi2e...
mi2_6 re2_6 blke so1e ti1e do2s do2_4_25...
blke do2e do2e la1e la1e so1e...
ti1e do2e re2_6 do2_6 so1e ti1e do2s do2_4_25...
blke do2e do2e la1e la1e so1e...
re2e mi2e fa2_6 mi2_6 so1e ti1e do2s do2_4_25...
blke do2e do2e la1e la1e so1e...
re2e do2e ti1e do2s do2_6 blke do2e...
do2e re2e re2e do2e do2e ti1e re2e do2s do2_6
];s = violin;
s = s/max(s);sound(s,fs);
audiowrite('Qilixiang.wav',violin,fs)
参考文献
.
[1]:https://mp.weixin.qq.com/s?__biz=MzU5NTAyMTIzOQ==&mid=2247483839&idx=1&sn=e8f6a92ed8dcbdaaa4cb43facf58bccf&chksm=fe791d67c90e94719e12fd30247afe352d03395d626b8d9e9ab674420994de6f5a96c7022b27&scene=21#wechat_redirect
[2]:https://www.zhihu.com/question/27780598/answer/666803900
[3]:http://www.qupu123.com/tongsu/sanzi/qilixiang
[4]:https://blog.csdn.net/leonliu070602/article/details/76254153