内容简介:携您一起进入这美妙而又复杂的音乐世界
携您一起进入这美妙而又复杂的音乐世界
隋顺意,公众号:萝卜大杂烩 Python 播放音乐:使用 mido 编写,播放多声轨 MIDI 文件音乐
“
原文地址:
https://blog.csdn.net/Sui_da_xia/article/details/104495111
”
人人 都喜爱音乐,音乐丰富了我们的情感。 在历史上,不乏有伟大的作曲家、钢琴家: 巴赫、海顿、莫扎特、贝多芬、李斯特、勃拉姆斯……
我们可以在剧院里,音乐厅里听到美妙动听的音乐。当我看到钢琴家修长的手指在钢琴上飞快地舞动,奏出婉转的音乐,十分羡慕,相信你们也是一样。那怎样才能让电脑,手机播放出美妙的音乐呢?
今天,就让我,携您一起进入这美妙而又复杂的音乐世界吧。
安装:
从前有个库,名字叫 mido. 其他不会做,就会发声音。
pip install mido
如果报错,试试用pip3。
Mido使用:
使用 mido 库说来简单,但是特别的麻烦是,它有许许多多的功能,这里仅介绍几种最常用的。贴个代码:
import mido #不用说
from mido import Message, MidiFile, MidiTrack #懒得说
mid = MidiFile() #给自己的文件定的.mid后缀
track = MidiTrack() #定义声部,一个MidoTrack()就是一个声部
track.append(Message('program_change',channel=0,program= X,time=0))
track.append(Message('note_on', note=XX, velocity=64, time=XX,channel=0))
track.append(Message('note_off', note=XX, velocity=64, time=XX,channel=0))
mido 的 Message 有可以放很多种不同的参数,每种参数都有不同的用途,接下来,我将会一一介绍以下参数:
program_change:
track.append(Message('program_change',channel=0,program= X,time=0))
‘ program_change ’参数可以理解成是个起始,用于确定乐器的类型。其中,channel 和 time 不可改变,只能是0,(不信的可以自己去试)。
Program 用于确定乐器, mido 有个专门的对应表,用数字命名,从0到16,17种不同的乐器。接下来,我会使用 2(钢琴) 作为参数
note_on:
track.append(Message('note_on', note=XX, velocity=64, time=XX,channel=0))
‘ note_on ’ 参数是一个音的开端。用于确定音,与前个音之间的间隔,音量。
参数not*代表“ 音 ”,和 program 一样,都是用数字命名,从21到108, 以半音作为最小单位 ,它有张表格,记录了所有的对应。但,不见得每次都要查表。
为此,我花费两天时间,写了 巨大的 函数“ num ”,把音转换成对应的数字。因为太长,这不放了,如有需要,请到我的github:
https://github.com/duoduo666/mido-Barock/blob/master/translate(number%2Cnote)/note%20to%20number.py
"velocity "参数代表音量,具体换算分贝我没研究,有兴趣可以自己研究。建议使用 64 作为(官网是这样写的)
“ time ” 参数代表与 前个音间隔 时间,具体换算会在下面讲到
“ channel ”参数很奇特,到现在,还没研究出有何用,就写0吧。
Note off:
track.append(Message('note_off', note=XX, velocity=64, time=XX,channel=0))
“ note off ”为一音结束, 音(note)须和note on 一样 ,反之就报错。
“ velocity ” 是个很特别的参数, 可以和note on的不一样 。如:note on 音量是 64,这写 100,那会在发声时从64慢慢增加至100。但,建议 不要再钢琴频道(2)更改 ,学过钢琴都知道,钢琴不能变音量的。
这里的“ time ”代表着该音持续多少。但,这里是个 时间单位 ,而音乐节拍,如快板为120,是 速度单位 。而且,这的时间 不是一个基本单位 (如秒、微秒)time 参数的1都不知是多少秒!这如何是好?先贴代码:
def beat(time): #与mido的拍子互换
time /= 60 * 1000
time = 1/time
return time
这是个算式,请注意, 这是我自己做的运算,官网都没写 。当 time = 1000 时,那播放120个音就是一分钟, 每分120拍 (音乐节拍就是用120表示)。晕…
"channel”参数也没弄清,如有大佬明白,请到我的 github
https://github.com/duoduo666/mido-Barock
的 issue 模块评论
集合函数
稍稍动动脑筋,就可以很容易把刚刚说的三种参数放在一起
def yin(yin,pai,qian=0,liang=64,qi=2): #yin是音,pai是指时间(节拍),
if type(yin)== str: #qian是音前多少拍
yin = num(yin) #liang是音量
track.append(Message('program_change',channel=0,program=qi,time=0)
track.append(Message('note_on',note=yin,velocity=liang,time=qian,channel=0))
track.append(Message('note_off',note=yin,velocity=liang,time=pai,channel=0))
但是,怎样才能 同时播放两个,至多个 呢?接下来,我们就要加声部。
还记得刚刚写过的一行代码
track = MidiTrack() mid.tracks.append(track)
这就是增加一个声部,这个声部的名字为 track。所以,我们就可以增加声部,并做个 list,方便调用:
track = MidiTrack() track2 = MidiTrack() track3 = MidiTrack() track4 = MidiTrack() mid.tracks.append(track) mid.tracks.append(track2) mid.tracks.append(track3) mid.tracks.append(track4) tra = [track,track2,track3,track4]
我这里先做四声部,有空的朋友可以多加几个( 除巴赫写过首五部曲外,其他曲子,最多只有四声部 )再动动脑筋,让 yin 支持多声部:
def yin(yin,pai,qian=0,unit=track,liang=64,qi=2):
······· #转换
unit.append(Message('program_change',channel=0,program=qi,time=0))
unit.append(Message('note_on',note=yin,velocity=liang,time=qian,channel=0))
unit.append(Message('note_off',note=yin,velocity=liang,time=pai,channel=0))
多音单声部函数
一首曲子,定不止一音,动动脑筋,得出:
def myin(fu,pai,time,qian=None,yue=2): #单声部
pig = int(beat(time))
if qian == None:
for i in range(len(pai):
yin(fu[i],pai[i]*pig,qi=yue)
else:
for i in range(len(pai)):
yin(fu[i],pai[i]*pig,qian[i],qi=yue)
pig的beat刚在 note off 里time参数 里专门讲过,这不再多说。
多声部函数实现:
一首钢琴曲里,总会有好几个声部,何况我们后面讲的算法是巴洛克时期的曲子,当然要着重讲多声部啦。
在刚刚写的函数(myin)的基础上,我们稍稍改进一下:
1. def myin(fu,pai,time=120,bef=None,shenbu=track,yue=2): #多声部版 2. pig = int(beat(time)) 3. for i in range(len(pai)): 4. if type(pai[i]) == list: 5. for j in range(len(pai[i])): 6. if bef == None: 7. yin(fu[i][j],pai[i][j]*pig,unit=tra[j],qi=yue) 8. else: 9. yin(fu[i][j],pai[i][j]*pig,bef[i][j],unit=tra[j],qi=yue) 10. else: 11. if bef == None: 12. yin(fu[i],pai[i]*pig,unit=shenbu,qi=yue) 13. else: 14. yin(fu[i],pai[i]*pig,bef[i],unit=shenbu,qi=yue)
第四行 if type(pai[i]) == list 为了把多声部和单声部分开来,比如说输入:[64,[64,65,66]]那[64]就是单声部,[64,65,66]是多声部的。
至于bef,这其实没什么用,不想写的就不写吧。
结语:
现在,您就可以实现播放音乐了,无论多复杂,多绕的音乐,您都可以动动脑筋实现。完整代码请去我的 github。
https://github.com/duoduo666/mido-Barock
但完了么?文章是结束。但,你有没有想过,电脑,手机,可以播放音乐。但,它们可不可以 通过计算 ,来“ 写 ”曲子呢?
为了弄清这些问题,我们需要了解许多令人发指的乐理,及计算令人发指的公式。你准备好了么?
近期文章
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Spring Into HTML and CSS
Molly E. Holzschlag / Addison-Wesley Professional / 2005-5-2 / USD 34.99
The fastest route to true HTML/CSS mastery! Need to build a web site? Or update one? Or just create some effective new web content? Maybe you just need to update your skills, do the job better. Welco......一起来看看 《Spring Into HTML and CSS》 这本书的介绍吧!