python编写的midi制作软件

更新时间:2024-01-25 13:56:01 阅读量: 教育文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

用Python编写的Mid音频制作软件

源代码如下:

#Midi.py:

#This file can be used to simply turn MidiTxt file to Mid file. #Author:loupen #Date:2010-7-20

#If you want to use it, you must write the MidiTxt file by some rules. #Read the document to learn more.

from struct import * #Three global variables TrackBegin=[] TrackEnd=[] ToneFore=1

#write the MidiHeader def MidiHeader(buffer):

buffer.write(pack('ccccBBBB','M','T','h','d',0,0,0,6)) def msg(buffer,tracks,deltatime): if deltatime>0xff:

buffer.write(pack('BBBBBB',0,1,0,tracks,deltatime>>8,deltatime&0xff)) else:

buffer.write(pack('BBBBBB',0,1,0,tracks,0,deltatime))

return buffer.tell()-3

#write the header and tail of tracks def TrackHeader(buffer,list):

buffer.write(pack('cccc','M','T','r','k')) list.append(buffer.tell()) buffer.write(pack('i',0))

def TrackTail(buffer,list):

buffer.write(pack('BBBB',0,0xff,0x2f,0)) list.append(buffer.tell())

#Set the pulse , instrument and controller def SetSpeed(buffer,time): time=60.0/int(time) time=int(time*(10**6))

buffer.write(pack('BBBBBBB',0,0xff,0x51,3,time>>16,(time&0xff00)>>8,time&0xff)) return 1

#The words , FenZi and FenMu , are from Chinese . ~O~

def SetPulse(buffer,FenZi,FenMu):

QQ: 750825502 E-mail: loupen@yeah.net

FenZi=int(FenZi) FenMu=int(FenMu) if FenMu==2: FenMu=1 elif FenMu==4: FenMu=2 elif FenMu==8: FenMu=3 else: return 0

buffer.write(pack('BBBBBBBB',0,0xff,0x58,4,int(FenZi),int(FenMu),0x18,0x08)) return 1

def SetTone(buffer):

buffer.write(pack('BBBBBB',0,0xff,0x59,2,0,0)) return 1

def SetNumOrder(buffer,time):

buffer.write(pack('BBBB',time>>24,(time&0xff0000)>>16,(time&0xff00)>>8,time&0xff))

def SetTrackNum(buffer,ad,n): buffer.seek(ad)

buffer.write(pack('B',n+1))

def SetInstrument(buffer,trackNum,ITNum): trackNum=int(trackNum) trackNum+=0xc0

buffer.write(pack('BBB',0,trackNum,ITNum))

def SetController(buffer,trackNum,CtrNum): trackNum=int(trackNum) trackNum+=0xb0

buffer.write(pack('BBBB',0,trackNum,11,CtrNum)) buffer.write(pack('BBB',0,0xa,0x40))

def SetVolume(buffer,trackNum,S): trackNum=int(trackNum) trackNum+=0xb0 if S=='H':

buffer.write(pack('BBBB',0,trackNum,7,0x7f)) buffer.write(pack('BBB',0,0xa,0x40)) if S=='L':

buffer.write(pack('BBBB',0,trackNum,7,80)) buffer.write(pack('BBB',0,0xa,0x40))

QQ: 750825502 E-mail: loupen@yeah.net

def SetChanYin(buffer,trackNum): trackNum=int(trackNum) trackNum+=0xb0

buffer.write(pack('BBBB',0,trackNum,1,127))

#imitate the function of buffer in C

def readNext(buffer): while True:

a=buffer.read(1) if a in [' ','\\n']: pass else: return a

#def seekFore(buffer,offset):

# buffer.seek(buffer.tell()-offset)

#Use the following two functions to deal with the events

def liftup(buffer,time,note): time=int(time) if time>=128:

buffer.write(pack('BBBB',0x80|(time>>7),0x7f&time,note,0)) else:

buffer.write(pack('BBB',time,note,0))

def pressdown(buffer,num,dict,mark,note,force): global ToneFore

a=dict[note]+(5+mark)*12 if ToneFore==1: num+=0x90

buffer.write(pack('BBBB',0,num,a,force)) else:

buffer.write(pack('BBB',0,a,force)) ToneFore=a

def main(lp):

track=1;deltatime=120 speed='';temp=0

begin=0;mark=0;time=deltatime

TrackNum=[0,1,2,3];ITNum=lp;CtrNum=0x7f dict={'0':0,'1':0,'2':2,'3':4,'4':5,'5':7,'6':9,'7':11} pTxt=open(r'.\\1.txt') s=\

QQ: 750825502 E-mail: loupen@yeah.net

pMid=open(s,'wb')

if pTxt.read(6)!=\

print \ pMid.close() pTxt.close() return 0 while True:

if pTxt.read(1)=='|':

FenMu=pTxt.read(1) pTxt.seek(pTxt.tell()-3) FenZi=pTxt.read(1) n=0

while n<8:

if readNext(pTxt)=='<':break n+=1 if n==8:

print \ pMid.close() pTxt.close() return 0 break n=0

a=readNext(pTxt) while a!='>': speed+=a

a=readNext(pTxt) MidiHeader(pMid)

track=msg(pMid,0,deltatime) TrackHeader(pMid,TrackBegin) SetPulse(pMid,FenZi,FenMu) SetTone(pMid)

SetSpeed(pMid,speed) TrackTail(pMid,TrackEnd) pMid.seek(TrackBegin[0])

SetNumOrder(pMid,TrackEnd[0]-TrackBegin[0]-4) pMid.seek(TrackEnd[0]) a=readNext(pTxt) while a=='[':

pTxt.readline()

TrackHeader(pMid,TrackBegin)

SetInstrument(pMid,TrackNum[n],ITNum[n]) SetController(pMid,TrackNum[n],CtrNum) a=readNext(pTxt) n+=1

QQ: 750825502 E-mail: loupen@yeah.net

while True: if a=='|':

a=readNext(pTxt) if a=='|':

a=readNext(pTxt) if a in ['[','']:

global ToneFore ToneFore=-1;break elif a=='\\'': mark+=1

a=readNext(pTxt) elif a=='.':

if begin==0: mark-=1 elif begin==1: time*=3.0/2

liftup(pMid,time,ToneFore) begin=0 elif begin==2:

a=pTxt.read(1) if a in [' ','|']: if a=='|':

print \ time*=3.0/2 time+=temp

liftup(pMid,time,ToneFore) begin=0;temp=0 mark=0 else:continue a=readNext(pTxt) elif a=='Y':

time=deltatime/2 a=pTxt.read(1) if a in [' ','|']: if a=='|':

print \ if begin==2:time+=temp liftup(pMid,time,ToneFore) begin=0;temp=0 mark=0

a=readNext(pTxt) elif a=='E':

time=deltatime/4 a=pTxt.read(1) if a in [' ','|']:

QQ: 750825502 E-mail: loupen@yeah.net

if a=='|':

print \ if begin==2:time+=temp liftup(pMid,time,ToneFore) begin=0;temp=0 mark=0

a=readNext(pTxt) elif a=='S':

time=deltatime/8 a=pTxt.read(1) if a in [' ','|']: if a=='|':

print \ if begin==2:time+=temp liftup(pMid,time,ToneFore) begin=0;temp=0 mark=0

a=readNext(pTxt) elif '7'>=a>='0': if begin==0:

if a=='0': force=0 else: force=100

pressdown(pMid,TrackNum[n-1],dict,mark,a,force) time=deltatime mark=0;begin=1 a=pTxt.read(1) if a in [' ','|']: if a=='|':

print \ liftup(pMid,time,ToneFore) begin=0

a=readNext(pTxt) elif begin==2:

time=deltatime a=pTxt.read(1) if a in [' ','|']: if a=='|':

print \ time+=temp

liftup(pMid,time,ToneFore) begin=0;temp=0 mark=0

a=readNext(pTxt) elif a=='^':

QQ: 750825502 E-mail: loupen@yeah.net

begin=2 temp+=time

a=readNext(pTxt) elif a=='-':

a=pTxt.read(1) if a in [' ','|']: if a=='|':

print \ time+=temp

liftup(pMid,time,ToneFore) begin=0;temp=0 mark=0

a=readNext(pTxt) elif a=='*':

SetVolume(pMid,TrackNum[n-1],'H') ToneFore=1

a=readNext(pTxt) elif a==',':

SetVolume(pMid,TrackNum[n-1],'L') ToneFore=1

a=readNext(pTxt) elif a=='W':

SetChanYin(pMid,TrackNum[n-1]) ToneFore=1

a=readNext(pTxt) else:

print \ pMid.close() pTxt.close() return 0

TrackTail(pMid,TrackEnd) pMid.seek(TrackBegin[n])

SetNumOrder(pMid,TrackEnd[n]-TrackBegin[n]-4) pMid.seek(TrackEnd[n]) SetTrackNum(pMid,track,n) pMid.close() pTxt.close()

print \以上文件存为midi.py。 #test.py: import midi i=1 z=[]

QQ: 750825502 E-mail: loupen@yeah.net

j=int(input(\while i<=j:

tmp=input(\ z.append(int(tmp)) i+=1 midi.main(z)

以上文件存为test.py。 以下为mid文本范例【赛马】:

<2|4> <120> [1]

|| 6. 3E 5E | 6. 3E 5E | 6. 3E 5E | 6. 3E 5E | 6E 5E 3E 5E 6E 5E 3E 5E | 6E 5E 3E 5E 6E 5E 3E 5E | 6Y 5E 6E 6Y 5E 6E |

6Y 5E 6E 6Y 5E 6E | .6Y 3Y 1Y .6Y | 3Y 6Y 5Y 3Y | 2E 3E 2E 1E 2E 3E 2E 1E | 2E 3E 2E 1E 2E 3E 2E 1E | .6Y 3Y 1Y .6Y | 3Y 6Y 5Y 3Y |

2E 3E 2E 1E 2E 3E 2E 1E | 2E 3E 2E 1E 2E 3E 2E 1E | 2. .6E 1E | 2. .6E 1E | 2. .6E 1E | 2. .6E 1E | 2E 3E 2E 1E 2E 3E 2E 1E |

2E 3E 2E 1E 2E 3E 2E 1E | 2Y 1E 2E 2Y 1E 2E | 2Y 1E 2E 2Y 1E 2E | .6 6 | 5 3 | 2 5 | 3 1 | .6 6 | 5 3 | 2 5 | 3 1 | .6. 1E 2E | .6. 1E 2E | .6. 1E 2E | .6. 1E 2E | .6E 2E 1E 2E .6E 2E 1E 2E | .6E 2E 1E 2E .6E 2E 1E 2E |

.6 .6Y .6Y | .6^ .6 | 3 6Y. '1E | 5. 3Y | 5Y 6Y '1Y. '3E | 6^ 6 | 3 6Y. '1E | 5 5Y 3Y | 2Y 3Y 6Y 5Y | 3^ 3 | 5 6Y. '1E |

1. .6Y | 2Y 3Y 6Y 5Y | 3 3Y 2Y | 1Y. 2E 3Y 5Y | 6 .6 | 2Y 3Y 1Y. 3E | .6^ .6 | 3Y 3E 3E 6Y '1Y | 5Y 5E 5E 5Y 3Y |

5Y 5E 6E '1Y '2E '1E | 6Y 6E 6E 6Y .6Y | 3Y 3E 3E 6Y '1Y | 5Y 5E 5E 5Y 3Y | 2Y 2E 3E 6Y 5Y | 3Y 3E 5E 3Y .6Y | 5Y 5E 5E 6Y '1Y |

1Y 1E 1E 1Y .6Y | 2Y 2E 3E 6Y 5Y | 3Y 3E 5E 3Y 2Y | 1E .6E 1E 2E 3E 2E 3E 5E | 6E 5E 6E '1E 5E 6E 5E 3E | 2E 3E 2E 1E 2E 1E .6E 1E | .6 6 |

0Y .6Y 1Y 3Y | 0Y .6Y 1Y 3Y | 0Y 2Y .7Y 2Y | .6Y 3Y 1Y 3Y | 0Y .6Y 1Y 3Y | 0Y .6Y 1Y 3Y | 0Y 2Y .7Y 2Y | .6Y 3Y 1Y 3Y | 0Y .6Y 1Y 3Y |

0Y .6Y 1Y 3Y | 0Y 2Y .7Y 2Y | .6Y 3Y 1Y 3Y | 0Y 5Y 3Y 2Y | 1Y 2Y 1Y .6 | 2Y 2Y 3Y 1Y | .6. 3E 5E | .6. 3E 5E | .6. 3E 5E |

.6. 3E 5E | .6. 1E 2E | 3E 2E 3E 5E 6E '1E 6E 5E | 3E 2E 3E 5E 6E '1E 6E 5E | 3E 5E 3E 2E 1Y 3Y | .6. 1E 2E | 3E 2E 3E 5E 6E '1E 6E 5E | 3E 2E 3E 5E 6E '1E 6E 5E |

3E 5E 3E 2E 1Y 3Y | .6. 3E 6E | '1Y 6Y 6Y '3Y | '1Y 6Y 6Y 3Y | '1Y 6Y 6Y '3Y | '1Y 6Y 6Y 3Y | 1Y .6E 1E 2Y 1E 2E | 3Y 2E 3E 5Y 3E 5E |

5Y 3E 5E 6Y 5E 6E | '1Y 6E '1E '2Y '1E '2E | '3E '2E '1E '2E '3E '2E '1E '2E | '3E '2E '1E '2E '3E '2E '1E '2E | '3E '2E '1E '2E '3E '2E '1E '2E | '3E '2E '1E '2E '3E '2E '3E '5E | '6^ '6^ | '6^ '6^ | '6^ '6 | '6 0 | 6 6 | .6^ .6 ||

上述文件存为1.txt,和midi.py , test.py放在同一个文件夹下,运行test.py Tracks为文本中[]的个数,instrument为乐器号取值范围为0-127. 注:后附mid文本编辑规范。

QQ: 750825502 E-mail: loupen@yeah.net

附录

Midi文本需按以下格式书写。 <3|8> <120>#每分钟的节拍数 [1] ||...|| [2] ||...||

////////////////////////////////////////////////////////////////////////////////////////////////////// ||1. ''2. ..3. 4^ -^ - #5 b6 7Y. ''1Y^ -^ -||

#1。'表示升高一个八度。[''1]表示比1高两个八度。

#2。.在音符前表示降低一个八度。如[..6]表示比6低两个八度。 #3。.在音符后表示付点音符。如[6.] #4。Y表示8分音符,即“一条横线”。如[6Y] #5。E表示16分音符,即“二条横线”。如[6E] #6。S表示32分音符,即“三条横线”。如[6S] #7。#表示升高半音 #8。b表示降低半音

#9。-表示延长一个四分音符。如[6^ -]

#10。^表示两个相同的音相连。如6 -表示为6^ - 注:

1。对于表示升降的符号['],[.]后需紧接音符。 2。附点音符[.],[^]需紧接在音符之后。 [^]前后两个音必须相同,即[6^ 6]或[6^ -] 3。[Y],[E],[S]需紧接在音符之后。 4。空格的作用非常重要,慎用。 音符后接空格表示此音符已结束。

5。其他功能,像控制器之类,还有待完善!对于升降音因为很少用就忽略了。编辑后的文本需以1.txt命名。

本人刚学python不足之处请高手指教。本文代码在wm5 sp手机上编辑和测试。

QQ: 750825502 E-mail: loupen@yeah.net

本文来源:https://www.bwwdw.com/article/1y9w.html

Top