还在为高数而烦恼吗?
还在为复杂的建模而不知所措吗?
还在为玄学编程而怀疑自己的智商吗?
还在为脑补实验而秃头吗?
假如你还在为这些而担忧
不如写首小曲子休闲娱乐一下吧~~
你没看错!
今天小编将为大家揭开MATLAB的一大隐藏功能
演 奏 歌 曲先来听听我们做出的《only my railgun》片段吧!
MED某咸鱼粉丝
哇!好好听!好神奇!
快教教我怎么用MATLAB写歌!
海团STA
来了来了!
首先我们发现
在matlab里有一个用于声音播放的函数为
sound(Y,Fs,bits)
注:其中Y是指定声音信号的向量,为重中之重
Fs为采样频率
bits为字节数
后两者涉及某些专业领域的探讨,在这里我们不过多深究
我们可以直接取用CD的标准,16bits,44.1Khz
一、表示音符要想用matlab写歌,第一步就是要将音符表示出来。
而matlab能表示出来最基本的则是函数。
音是物体振动,形成声波产生的,
最为基本的是正弦波周期,
于是我们想到了正弦函数。
如图 x=linspace(0,2*pi,Fs)
y=sin(x)
画出的图像周期太短,产生低频的次声波,是无法被人耳识别的,因此我们增加周期。
于是我们写出Y=sin440*x,
这是标准音的频率,即小字组的A,
这样,我们就可以听到电子音了!
二、音符输入现在,我们要将更多更丰富的音写入matlab中,
已知频率不同,音高不同,
现在我们需要的是每个音对应的频率,
于是我们翻出了十二平均律表。
注:十二平均律是西方音乐体系里最普遍的律制,也是当前最常用的律制。在十二平均律中,我们将八度的音程分为了十二个音,如下图,这也构成了当前最基本的乐理机制。
十二平均律的理论研究,也是巴赫最显著的成就。
在此推荐巴赫平均律组曲,整部曲子构造严密精巧,散发着数学的气质,聆听时,能感受到超越时空的神圣感与万物俱寂的平静,一切归于理性。
PS:写论文和做数学的时候有奇效哦!
十二平均律精确地反映了每个音的来源与定义,通过这一律制,我们也可以用数学方式定义我们的音符。
这里有两种方法定义音符(左右滑动查看代码):
第一,我们可以直接定义函数freq,即
Function f=freq(p)F=440*2^((p-69)/12)(音高和频率的满足的公式,p为音高)
第二,我们也可以直接找出十二平均律对照的频率表,然后直接根据对应频率来定义音。
此处以标准音A(即小字组的fa)举例:
X=linspace(0,2*pi,Fs) Y=sin(440*x)/y=sin(freq(p)*x)
此时我们发现每个音是没有相应停顿的,
但真实的音是有衰减过程(即音逐渐减弱)的,
因此我们需要乘上一个衰减的函数。
此处可以简单地乘上一个一次函数,
如Y=sin(freq(p)*x).*(1-x/2*pi),
注:y=1-x/2*pi为过(0,1)和(2*pi,0)的一次函数
构成了这样的形状。
此处,根据节奏的不同可以进行调整。
(如四分音符,八分音符,十六分音符结束处不一样,斜率也应相应变化)
于是,单个的音就构成了。
接下来,我们可以设置函数key,加入节奏。
Function y=key(p,r,fs)(p为pitch表示音高,r为rhythm表示节奏)X=linspace(0,2*pi*r,floor(fs*r));(此处加入floor为取整函数)Y=sin(freq(p)*x).*(1-x/r*2*pi)
由此我们就可以设置出所有的音了,
例如小字组的B:
b1_2=key(71,2,fs)(即两拍的长音)
当然我们也可以采用更简单的方式,
即一次性列出C大调的小字一组。
Function y=majorC1(tone,r) Fs=44100 Freqs=[523,587,659,698,783,880,987] X=linspace(0,2*pi*r,floor(fs*r));Y=sin(freqs(tone)*x).*(1-x/r*2*pi)
另外,我们还需要定义休止符:
Function z=pause(r,fs)X=linspace(0,2*pi*r,floor(fs*r));Y=0*sin(2*pi*r).*(1-x/r*2*pi)
三、快乐写曲
现在,所有的基础音定义完成后,
我们打开一份简谱,
此处以《only my railgun》为例:
此时我们需要利用一些乐理知识,
首先,我们发现这首歌是以B大调为主,中途转了bB和bA。(通俗易懂地讲,即是把B作为音阶的起始音do)
现在我们有两种解决方法:
我们复习一下前面提供的音程图,可以发现一个八度的音呈现出“全全半全全全半”的规律,梳理出对应的音阶:
bB C D bE F G A bB
bA bB C bD bE F G bA
如果采用函数key,则先将该谱转化为C大调的谱子,再对应码入。
如果采用第二种函数构成,
那么我们可以分别设置出bB、bA、B的三个音区的函数,
例如:
function y=majorB0(tone,rythm)Fs=44100; freqs=[246,261,293,329,349,391,440];x=linspace(0,2*pi*rythm,floor(Fs*rythm)); y=sin(freqs(tone)*x).*(1-x/(rythm*2*pi)); end
以前奏这一段旋律为例:
如果以第二种方法,可写出:
Fs=14400;y1=majorB0(6,1/2);y2=majorB0(6,1/2); y3=majorB0(5,1/4);y4=majorB0(6,1/2); y=[y1,y2,y3,y4]; sound(y)
但如果是第一个函数,则会写出:
(第一行简谱)part1=[zeroh d6_08 d6_08 c5_016 d6_016 zeroh d6_08 c5_08 c5_016 d6_016]; part2=[zeroh d6_08 d6_08 c5_016 d6_016 zeroh d6_08 c5_08 c5_016 d6_016]; part3=[zeroh d6_08 d6_08 c5_016 d6_016 zeroh d6_08 c5_08 c5_016 d6_016]; part4=[zeroh d6_08 d6_08 c5_016 d6_016 zeroh d6_08 c5_08 c5_016 d6_016]; line1=[part1 part2 part3 part4]; .......
在写完所有代码后还需进行合并:
vector=[line1 line2 line3 line4 line5 line6 line7 line8 line9... line10 line11 line12 line13 line14 line15 line16... line17 line18 line19 line20 line21 line22 line23... line24 line25 line26 line27 line28 line29 line30]; sound(vector,2.25*fs,16);
最后我们将文件储存为音频格式:
filename='only my railgun.wav'; y=vector; Fs=2.25*fs; audiowrite(filename,y,Fs)
我们的这首歌就这样写出来啦!
这两种方式各有优缺点,
对于熟悉乐理知识的朋友,
或者拿到以1=C的谱子,
那么逐个定义音符后,
写出曲子会更为简洁。
而对于需要多次转调,
且对乐理没有那么熟悉的朋友,
定义调性后会更为简单。
大家学到之后就可以尝试写出带有浓浓游戏音的沙雕音乐哦!
下附参考视频连接
感兴趣的小伙伴可以去看看资深up主的详细介绍
Up主:正月点灯笼https://b23.tv/BV1Kb411H7cM
相信本期分享为大家打开了MATLAB使用的新大门
欢迎大家一起来发现MATLAB更多的隐藏功能呀
往期回顾 ↓
简介、优势:干货:让MATLAB拯救芸芸众生中的你--第一弹
绘图功能:干货:让MATLAB拯救芸芸众生中的你——第二弹
仿真模拟实验:干货:让MATLAB拯救芸芸众生中的你——第三弹
作者:海团STA
排版:陈茜茜
SEA海团子
扫码收获精彩♪(´▽`)