无82云学习
MATLAB专题
音乐合成篇
【写在前面】
学过物理我们知道,声音的本质是波,任何声音都可以用波形来描述,而音乐,用电子工程中的术语解释,就是周期信号的幅频随时间节奏变化的一种表述。所以,只要研究清楚乐音的频谱规律,就可以通过软件编程来模拟乐器的声音,进而制作出“电子音乐”了。今天,我们就用简单的教程带大家使用MATLAB来弹奏有伴奏的立体环绕音效版《小星星》吧!
01
基本乐理
为了从原理上更容易理解代码
我们先来学习一些基础的乐理知识吧
如果不感兴趣也可以直接跳到第2节
♬..♩~ ♫. ♪ ~ ♬..♩..♩~ ♫. ♪ ~ ♬..♩..♩~ ♫. ♪ ~ ♬..♩..♩~ ♫. ♪ ~ ♬..♩♫. ♪ ~ ♬..♩~ ♫. ♪..♩~ ♫. ♪ ~ ♬..♩..♩~ ♫. ♪ ~ ♬..♩..♩~ ♫. ♪ ~ ♬..♩我们称物体振动规则,听起来音高十分明显的声音为“乐音”,乐音体系中的各音称作“音级”,其名称叫做“音名”。
音的性质可以用音高、音值、音量、音色来概括,下面分别解释:
◆音高(pitch):即音调的高低,用发声体的振动频率(frequency)来衡量。
◆音值(duration):即音的时值长短,用发声体振动的延续时间来衡量。
◆音量(volume):即音的强度大小,用发声体振动幅度(amplitude)来衡量。
◆音色(tone):由泛音频谱和包络波形等多因素决定。
下面首先来看看音高。
以钢琴为例。我们用大写字母C、D、E、F、G、A、B来表示“基本音级”的音名,它们对应到一个八度(C大调中的do到si)中的钢琴的白键,如图所示。
乐音体系中各音的绝对准确高度及其相互关系,称为“音律”。下面将黑键也考虑进去,我们用升号#或降号b表示黑键(比如A和B之间的黑键可记为A#或Bb),则一个八度共有12个音级(7个白键、5个黑键),每个音级的频率可由“十二平均律”计算导出,这里的平均是指数平均增长,相邻两个音级相差2^(1/12)倍。现在我们使用的大部分键盘乐器都是采用十二平均律定音的。
将主音设为第一国际高度440Hz,则对应的十二平均律如下表所示。易知相邻两个八度中对应音级的频率是2^(12/12)即两倍关系。取出7个基本音级(白键do到si,在C大调中即对应C、D、E、F、G、A、B),我们可以设音高数组h = [523.251, 587.330, 659.255, 698.456, 783.991, 880, 987.766]。那么将它整体依次乘或除2,可以直接推得相邻八度中各音级的频率。如果需要用到黑键,你可以自行查表修改音高数组。
然后再来看看音色。
我们在上面已经确定了一个乐音信号的基波频率,为了让它的音色有所变化,还应当考虑谐波分量(即“泛音”)以及波形包络。
不同乐器即使演奏相同的音高,发出乐音的音色也是千差万别,这主要是因为它们的谐波成分有所区别,比如单簧管的三次、五次谐波成分很强,所以我们应当通过调整谐波分量的强度来改变音色。
而音色的另一特质便是其波形包络形状,包络限制了波形的幅度变化,让声音听起来有强弱的起伏。两种乐器单个音符的波形如下图所示,可以直观地感受到钢琴的音符间将会更加界线分明听起来更清脆,而管乐则是连续过度更显悠长连绵。
在设置包络时要注意,波形的首尾应当连续地衔接!我们今天要模仿的是弹奏型乐器,它的波形振幅应当是先达到峰值再逐渐衰减的,为了不让两个音符衔接时出现“阶跃”从而导致毛刺产生(听起来就会有“啪”的杂音),应当让波形包络从0开始增长且最终衰减到0。
02
第一个音符
看完繁琐的乐理知识介绍
相信你已经急切地想演奏出第一个音符吧
来吧,开启电子音乐之旅~
♬..♩~ ♫. ♪ ~ ♬..♩..♩~ ♫. ♪ ~ ♬..♩..♩~ ♫. ♪ ~ ♬..♩..♩~ ♫. ♪ ~ ♬..♩♫. ♪ ~ ♬..♩~ ♫. ♪..♩~ ♫. ♪ ~ ♬..♩..♩~ ♫. ♪ ~ ♬..♩..♩~ ♫. ♪ ~ ♬..♩首先我们再补充一个小的知识点——采样率。采样率就是每秒从我们希望得到的连续信号中提取并组成离散信号的采样点个数,实际输出波形是由这些采样点连成的曲线,因此在一定范围内较高的采样率会有更好的音质。由于人能听到的声音频率范围约为20Hz~20kHz,因此由Nyquist采样定理,采样频率至少需要40kHz才能更精准地还原人耳能听到的大部分声音,下面我们采用音频的标准采样率44.1kHz。
然后,先来看看MATLAB的工作面板吧。如下图所示,各功能分区参考图中标注,这里不赘述。接下来我们将在脚本中编写代码正文,脚本运行后,工作区将会出现执行后的变量,这时可以在命令行中输入需要的临时操作进行调试与测试,比如中途用plot查看包络波形、用soundsc播放调参过程中的音乐、用clear sound停止播放音乐等,后面会详细展开。
注意,每一小节末尾会给完整代码汇总!
那么下面我们来定义一个音符吧。根据前面的乐理基础,我们通过音高、音值、音量、音色四个方面来确定一个音符的波形。
它的音高取C调的do(523.251Hz),音值与音量定义为1个单