给不懂音乐的程序员和不懂代码的音乐人01-Sonic Pi理解MIDI之一

感谢支持,感谢催更!

应该有不少读者是从R语言声音音乐分析系列来的,相信大家也能猜到下一篇系列会更新什么。但是再我们继续往前冲之前,请一定要在这一篇掌握一点计算机音乐基本概念,因为它很简单,而且会非常有帮助,不管是对理解音乐分析系列的博客,还是对音乐和声音本身的理解。欢迎评论区一起交流学习!

这一篇我们接触一点点live coding,这是一种用代码敲音乐(是不是又崩溃又好奇)的音乐创作方式和现场演奏方式。这里我用的是Sonic Pi而不是“更加Professional”而且大多数live coder用的ixi langOvertone,因为它最重要的应用是提供更直观易懂的计算机教育,当然反过来也可以用来做音乐教育。

每个人都可以创造音乐。




MIDI

在正式开始live coding之前,我们还是看看书上那些话都是怎么说的看完了你就知道有一些行话在讲什么了。我搬一下我之前看《现代音乐人编曲手册——传统管弦乐配器和MIDI音序制作必备指南》的笔记,外加一点点解释。

MIDI全称是Music Instrument Digital Interface乐器数字接口,也可以理解成是一种音频数字化的标准,它不包含任何音频内容或片段,但是用数字信息去储存音频的信息。怎么用数字表示音频就是MIDI解决的问题。

一般会用MIDI控制器来给电脑输入MIDI,很多DJ用的都是MIDI控制器,通常是键盘或者打击垫,弹几个音,但是输入到电脑里,可以通过改参数来改变声音的方方面面。

MIDI信息主要分两类:通道信息系统信息

系统信息

系统信息基本上是于计算机本身相关的信息,包括系统实时信息、系统通用信息、系统专有信息。这里不是我们的重点,就直接略过了。

通道信息——关于演奏的信息

通道声音信息,是关乎演奏的信息。一共分为6类:

音符开 Note On

涉及到音高,编码范围是0-127,也就是C2-G8,这是一个音域范围
【图,MIDI和键盘对应】

音符关 Note Off

离键速度参数,几乎不用。

触后 Aftertouch / 压力

击键以后再稍使劲向下按一下,常用来做颤音效果。

弯音 Pitch Bend

一般由键盘的弯音轮控制,数值范围不是128级,而是0-16,因为弯音就是一个音往高或往低有轻微光滑变化,类似于吉他的推弦。

程序改变 Program Change

改变分配给某一MIDI通道的音色:
synthesizer内存中储存了一系列程序,也叫音色、预置、乐器/声音。对每个MIDI通道,分配一个音色,用来回放发送给通道的所有MIDI数据。可以通过面板进行音色改变,也可以通过控制器或音序器发送程序改变。
数值范围同样是0-127。
音色程序用库是一种组织形式,每个库最多存放128个音色。

控制改变 Control Change (CC)

对某一MIDI通道的特定参数进行控制。MIDI标准中一共有128个控制改变信息,即CC#0到CC#127。每个CC信息的数值范围也都是0-127。

最常用的是这几个:CC#1调制,CC#7音量(击键强度),CC#10声像,CC#64延音踏板。

有MIDI音频音序器以及合成器,你一个人就可以制作出又相当完整度的音乐了。

如果感觉还是没太懂,没关系,不要担心,继续往后走你会逐渐get the feeling。


Sonic Pi

Sonic Pi
一款免费的音乐编码软件,诞生于剑桥计算机实验室,Sam Aaron是它的创造者。Sam在各种论坛上有过诸多讲座,介绍Sonic Pi和它的潜能,影响特别深刻的一次,是在他简单示范如何使用这个软件,让电脑发出了声响,说:

……我们现在可以调整音高,可以控制时间,这就是大半个西方音乐系统!

Sonic Pi官网里有很多介绍,也有现成的代码示例和教程。in_thread社区里也有很多有趣的例子,如果觉得这里给你的例子还不够,欢迎到社区里去逛逛!

首先我们安装Sonic Pi,直接去官网http://sonic-pi.net/上找到你对应系统的版本下载安装就好了。安装程序不大,而且Sonic Pi的界面很好看:

Sonic Pi界面
还可以调整界面的透明度。

不推荐直接用Python的IDE来写,尽管可以这样做:Pypi的python-sonic网站里给的pip install python-sonic,我从来没试过,也不知道里面跑出来是什么样子。而且用python的话,有的代码可能会和我这里写的不太一样。

这一篇很多例子参考于官方文档和教程。

play 演奏起来玩起来

play和sleep

演奏第一个beep音:

play 60

然后Alt+R跑它。
这就是中央C。“60”你可以认为是钢琴上第60个键(包括黑键)。所以你的数值越低,它的音越低。现在我们换一个音:

play 70

再试试别的,比如75。
那如果我们写很多个play:

play 60
play 72

你听到的是两个音,middleC和C4,就是中间的中音do和高八度的高音do。数值上每隔12就是一个八度

play 72
play 75
play 79 

你听到的是一个和弦!没错!是C和弦CEG,或者说是C大调的do mi sol。音和音之间的数值上距离其实和音乐上的“音数”的概念相似。你也可以用音名也就是CEG去表示,证明你的数值是对的。它相当于:

play :C5
play :E5
play :G5

60相当于C4中央C,相当于小字一组C。60+12=72。72相当于C5,C5是指第五组的C,相当于小字二组的C:

大谱表与钢琴键盘对照表
图片来源于https://power.baidu.com/question/118836572.html?qbl=relate_question_7

你可能发现了,那我们升降号怎么办?在数字也就是MIDI音高表示方法里,直接加整数就行了。如果用音名的话,就用b表示降号(flat),用s表示升号(sharp),加在音名的后面,比如:Eb3就是第三个音组的(也就是大字组)降E,:Fs3就是第三个音组(大字组)升F。

你也可以一个一个分别演奏这些音,加上sleep让它停一会再接着跑就行了:

play 72
sleep 1
play 75
sleep 1
play 79 

sleep后面的数值是时间,以秒为单位,可以改一下sleep的时间试试看~

而有一些音你可能根本就想不到。
更有趣的在这里:

play 61.3333333

我第一次看到官方文档上有这个我第一反应是“这是什么玩意?”这个音是某种不能用通常的标准的乐器理解方式来理解,因为我们通常的乐器都是按照十二平均律来的,音序都是十二音序列,我们的MIDI的整数就是这12音。和这些音律相关的是对声音频率的研究、对声波的研究。那,如果是非十二平均律的音乐呢?可以参考一下知乎这里的回答,虽然不是很完整,但是可以帮助理解:有什么优秀的非十二平均律音乐?或者说我们通俗点讲,如果听过lo-fi或是迷幻音乐,肯定能轻易从众多音乐里分辨出来哪些是有lo-fi元素的,很简单——那种有一点点音不准的离调的感觉,低保真的音效。有一些lo-fi音乐在非十二平均律的探索上很大胆,直接使用十平均律、七平均律等等,人耳很难听出它们具体的差异,只是知道有点“跑调”,但是经过精心的编排,也可以听起来很“迷幻”、很吸引人的。这下面的并不算是严格的非十二平均律,但是和十二平均律的音对比一下,听起来还是有一定差别:

play 72 
sleep 0.25 
play 74.6666 
sleep 0.25 
play 78.6656
sleep 0.5
play 72
sleep 0.25
play 75
sleep 0.25
play 79

演奏一个简单音序sequence

既然音符可以用数字表示,那么音序也可以用一个列表list表示:

play choose([50, 55, 62])

choose是随机选列表里的一个音演奏出来,但如果仅仅这么写,run多少次都只是同一个音。用通常思维,我们加一个loop可能这种随机就能出来了,这里你可以知道,音的list也是可以遍历的(iterable),可以用一般普遍理解的数据结构来理解(但这里具体的代码先不讲,后面有新的博介绍这部分的时候,会把链接贴过来)。

如果演奏一个音的列表list,它也是在演奏和弦:

play [52, 55, 59]   # play [:E3, :G3, :B3] 

你甚至可以在右边的console输出列表第一个数值,第一个index是0。

puts [52, 55, 59][1] 

弹和弦play chord

和声演奏/一次弹一个完整和弦

play chord(:E3, :minor)  ## 小三和弦

或者我们还可以用这些和弦替换上面那个和弦,下面的也只是举例子,你可以在sonic pi的自动补全里看到更多的选项:
chord(:E3, :m7) 【小七和弦】
chord(:E3, :dim7) 【减七和弦】
chord(:E3, :dom7) 【属七和弦】 等等等等各种想得到想不到的和弦名称……

琶音Arppegio/和弦分解(一个音一个音弹)

(英国摇滚乐队Muse最擅长各种琶音)
在音乐里,什么和弦,叫什么,有什么音,一般都是固定的,所以说,这种一一对应的准确性,可以帮助我们理解大部分音乐,用更少的语言描述最多的内容。就比如和弦进行,基本上只用告诉用哪几个和弦,我们就能大致想象出音乐的调调,而不需要告诉你具体你得弹哪几个音。

基于这种对音乐的压缩性的描述,你可以猜测一下这些直接播放和弦的函数都是怎么实现的。

play_pattern chord(:E3, :m7)    ## E3的小七和弦 E minor7,相当于E G B D

或者手动设定分解的和弦音chord tone之间的间隔时间:

play_pattern_timed chord(:E3, :m13), [0.25, 0.5]     ## E3的小十三和弦

相当于

play 52
sleep 0.25
play 55
sleep 0.5
play 59
sleep 0.25
play 62
sleep 0.5
play 66
sleep 0.25
play 69
sleep 0.5
play 73 

只要提前确定好哪个和弦要哪几个音,封装在函数里,你就可以演奏对应的和弦。再有其他的参数控制也是可以加的。

数据结构之列表list

既然音符可以用数字表示,那么音序也可以用一个列表list表示:

play choose([50, 55, 62])

choose是随机选列表里的一个音演奏出来,但如果仅仅这么写,run多少次都只是同一个音。用通常思维,我们加一个loop可能这种随机就能出来了,这里你可以知道,音的list也是可以遍历的(iterable),可以用一般普遍理解的数据结构来理解(但这里具体的代码先不讲,后面有新的博介绍这部分的时候,会把链接贴过来)。

如果演奏一个列表list,它也是在演奏和弦,因为列表包含了所有音:

play [52, 55, 59]   # play [:E3, :G3, :B3]

不难理解,如果要分解和弦,必须遍历。


披一层外套的play——合成音synthesizer

试试这个:

use_synth :saw
play 38
sleep 0.25
play 50
sleep 0.25
play 62
sleep 0.25 

开始电音!
也可以中途一个转向立马换一个音色:

use_synth :saw
play 38
sleep 0.25
play 50
sleep 0.25
use_synth :prophet  # another synth 换合成器
play 57
sleep 0.25

就如开始我们讲到的MIDI标准,音高是一个参数,音色是另一个参数。这里就是选定了音色和音高,然后我们就做出了合成器的雏形了。


一些影响声音的参数——MIDI控制

语言解释反而不清楚,直接听比较好懂:

amp(amplitude 响度)

*请注意耳机音量

play 60, amp: 0.5 
sleep 1
play 60, amp: 0.5 
sleep 1
play 60, amp: 2

pan (panning 环绕声)

play 60, pan: -1 
sleep 1
play 60, pan: 0
sleep 1
play 60, pan: 1
sleep 0.25
play 60, pan: 0 
sleep 0.25
play 60, pan: -1 
sleep 0.25

cutoff (不知道怎么翻译)

有一种越来越近、越来越清楚的感觉。

use_random_seed 0
use_synth :prophet
5.times do
  play chord(:C4,:M), cutoff: (ring 60,70,80,90,100).tick
  sleep 0.5
end

# compared to the original one
sleep 1
play chord(:C4,:M)

res (resonance 反响)

可以理解为空间感,因为反响越大,感觉回声来的越远,空间越大。
这里我可没有找到合适的例子,我也可以在DAW上做一个小视频录一下不同resonance的区别,但是时间有限,而且也不知道怎么post上来。到下一篇碰到声音样本Sample的时候也会用这个参数。

波封ADSR envelope

ADSR是指attack, decay, sustain, release,ADSR envelope就是用这四个值简单定义的波封。

我把官方文档的代码放过来,可以试试,一听你就明白为什么讲到音频就会讲到波封。不要直接复制整个block,一行一行来,听完一行删掉换下一行,因为设置以后每个声音片段的时间长度不太一致,我也懒得写函数去适应这个时间值。:

play 70 
play 70, release: 1 
play 60, release: 2
play 60, release: 0.2 

play 60, attack: 2
play 65, attack: 0.5 
play 60, attack: 0.7, release: 4
play 60, attack: 4, release: 0.7 
play 60, attack: 0.5, release: 0.5 

play 60, attack: 0.3, sustain: 1, release: 1 

play 60, attack: 0.1, attack_level: 1, decay: 0.2, sustain_level: 0.4, sustain: 1, release: 0.5 

如果对声音有特别的要求,我们可以更完整地设置ADSR envelope:

play 60, attack: 0.1, attack_level: 0.1, decay: 0.2, decay_level: 1, sustain: 0.5, sustain_level: 0.8, release: 1.5 

借用官方文档的图:
ADSR Envelope
或者再举个例子:

play 60, attack: 0.1, attack_level: 1, decay: 0.2, decay_level: 0.3, sustain: 1, sustain_level: 0.4, release: 0.5

ADSR Envelope

  1. attack - time from 0 amplitude to the attack_level,
  2. decay - time to move amplitude from attack_level to decay_level,
  3. sustain - time to move the amplitude from decay_level to sustain_level,
  4. release - time to move amplitude from sustain_level to 0

It’s important to note that the duration of a sound is the summation of the times of each of these phases. Therefore the following sound will have a duration of 0.5 + 1 + 2 + 0.5 = 4 beats: play 60, attack:
0.5, attack_level: 1, decay: 1, sustain_level: 0.4, sustain: 2, release: 0.5

就是说,如果要设置,一定要注意ADSR这四个时段加起来要符合样本长度,样本播放的长度应该和ADSR占用时间之和相同。


下一篇我们会继续用Sonic Pi介绍一些基本的音乐制作知识(甚至都还不算音乐制作),包括声音取样(声音取样的开始点、结束点)、音频压缩和拉伸(调整速率)、切片(slicing)、变量及函数定义、如何演奏一小段旋律(do do sol sol la la so这种)。如果存在一些问题请一定在评论区提出来,我们一起沟通学习!

这一系列很快就会有更新,后面除了继续介绍R语言的音频处理方法,还会介绍声学相关、基本乐理、音乐制作等有助于音乐分析的干货。如果对数据分析、声音硬件、live-coding等等有兴趣也可以关注一下,后续也会有相关文章发布~

(P.S. DDL还没肝完,写博十分艰难,尽情谅解@-@)
(但是催更还是可以的)

发布了3 篇原创文章 · 获赞 12 · 访问量 521

猜你喜欢

转载自blog.csdn.net/dsager/article/details/104959239