midimessage.py 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880
  1. #!/usr/bin/python
  2. from .options import *
  3. import time
  4. import io
  5. class MIDIParserException(Exception):
  6. def __init__(self, message):
  7. super().__init__(message)
  8. def send_message(x, data):
  9. s="["
  10. for i in range(len(data)):
  11. if i>0: s+=", "
  12. s+=hex(data[i])
  13. MIDIDEBUG(s+"]")
  14. x.send_message(data)
  15. class MidiType:
  16. def __init__(self):
  17. MidiType.ERROR=0
  18. MidiType.NOTE_OFF=0x80
  19. MidiType.NOTE_ON=0x90
  20. MidiType.KEY_PRESSURE=0xA0
  21. MidiType.CONTROL_CHANGE=0xB0
  22. MidiType.PROGRAM_CHANGE=0xC0
  23. MidiType.CHANNEL_PRESSURE=0xD0
  24. MidiType.PITCH_WHEEL_CHANGE=0xE0
  25. MidiType.SYSTEM_EXCLUSIVE=0xF0
  26. MidiType.SONG_POSITION_POINTER=0xF2
  27. MidiType.SONG_SELECT=0xF2
  28. MidiType.TUNE_REQUEST=0xF6
  29. MidiType.END_OF_EXCUSIVE=0xF7 #not used
  30. MidiType.TIMING_CLOCK=0xF8 # a faire
  31. MidiType.START=0xFA
  32. MidiType.CONTINUE=0xFB
  33. MidiType.STOP=0xFC
  34. MidiType.ACTIVE_SENSING=0xFE
  35. MidiType.META=0xFF
  36. MidiType.RESET=0xFF
  37. MidiType.META_SEQ=0x00
  38. MidiType.META_TEXT=0x01
  39. MidiType.META_COPYRIGHT=0x02
  40. MidiType.META_TRACK_NAME=0x03
  41. MidiType.META_INSTRUMENT_NAME=0x04
  42. MidiType.META_LYRICS=0x05
  43. MidiType.META_TEXT_MARKER=0x06
  44. MidiType.META_CUE_POINT=0x07
  45. MidiType.META_CHANNEL_PREFIX=0x20
  46. MidiType.META_END_OF_TRACK=0x2F
  47. MidiType.META_SET_TEMPO=0x51
  48. MidiType.META_SMPTE_OFFSET=0x54
  49. MidiType.META_TIME_SIGNATURE=0x58
  50. MidiType.META_KEY_SIGNATURE=0x59
  51. MidiType.META_SPECIFIC=0x7F
  52. MidiType()
  53. class MidiMessage:
  54. def __init__(self, typ):
  55. self.type=typ
  56. self.__sleep=0.00001
  57. self.__doSleep=True
  58. self.key=-1
  59. def isEndTrack(self):
  60. return False
  61. def getType(self):
  62. if self.type>=0x80 and self.type<=0xE0:
  63. return self.type&0xf0
  64. return self.type
  65. def isTypeOf(self, x):
  66. return self.getType() == x
  67. def isMeta(self):
  68. return self.type>=0 and self.type<=0x58
  69. def isSysEx(self):
  70. return self.type>=0xF0 and self.type<=0xF7
  71. def write(self, oport):
  72. send_message(oport, self.bytes())
  73. #oport.send_message(self.bytes())
  74. if self.__doSleep:
  75. time.sleep(self.__sleep)
  76. def read(self, iport, n=1):
  77. if n>0:
  78. out=[]
  79. for i in range(n):
  80. out.append(self.byte())
  81. return out
  82. return iport.get_message()
  83. def syncRead(self, iport):
  84. x=None
  85. while True:
  86. x=self.read(iport)
  87. if x!=None:
  88. return x
  89. def __eq__(self, x):
  90. xx=x.bytes()
  91. ex=self.bytes()
  92. if len(xx) != len(ex): return False
  93. for i in len(xx):
  94. if xx[i] != ex[i]:
  95. return False
  96. return True
  97. def transpose(self, n):
  98. pass
  99. def copy(self):
  100. x=MidiMessage.parse(self.bytes())
  101. return x
  102. @staticmethod
  103. def byte(fd):
  104. vv=fd.read(1)
  105. if vv==None or len(vv)==0:
  106. raise MIDIParserException("End off file premature")
  107. return int(vv[0])
  108. @staticmethod
  109. def parse(fd):
  110. if isinstance(fd, (bytes, list)):
  111. b=bytes(fd)
  112. fd=io.BytesIO(b)
  113. return MidiMessage.parseStream(fd)
  114. @staticmethod
  115. def parseStream(fd):
  116. vv=fd.read(1)
  117. if vv==None:
  118. return MidiEndFile()
  119. first=int(vv[0])
  120. xa= first&0xf0
  121. xb= first&0x0f
  122. if xa==MidiType.NOTE_ON: return NoteOn(xb, fd)
  123. elif xa==MidiType.NOTE_OFF: return NoteOff(xb, fd)
  124. elif xa==MidiType.KEY_PRESSURE: return KeyPressure(xb, fd)
  125. elif xa==MidiType.CONTROL_CHANGE: return ControlChange(xb, fd)
  126. elif xa==MidiType.PROGRAM_CHANGE: return ProgramChange(xb, fd)
  127. elif xa==MidiType.CHANNEL_PRESSURE: return ChannelPressure(xb, fd)
  128. elif xa==MidiType.PITCH_WHEEL_CHANGE: return PitchWheelChange(xb, fd)
  129. elif first==MidiType.SYSTEM_EXCLUSIVE: return SystemExclusive(fd)
  130. elif first==MidiType.SONG_POSITION_POINTER: return SongPointerPosition(fd)
  131. elif first==MidiType.SONG_SELECT: return SongSelect(fd)
  132. elif first==MidiType.TUNE_REQUEST: return TuneRequest(fd)
  133. elif first==MidiType.TIMING_CLOCK: return TimingClock(fd)
  134. elif first==MidiType.START: return Start(fd)
  135. elif first==MidiType.CONTINUE: return Continue(fd)
  136. elif first==MidiType.STOP: return Stop(fd)
  137. elif first==MidiType.ACTIVE_SENSING: return ActiveSensing(fd)
  138. elif first==MidiType.META: return MidiMessage.parseMeta( fd)
  139. else: return MidiError(first)
  140. @staticmethod
  141. def parseMeta(fd):
  142. cmd=MidiMessage.byte(fd)
  143. if cmd==MidiType.META_SEQ: return SequenceNumber(fd)
  144. elif cmd==MidiType.META_TEXT: return TextEvent(fd)
  145. elif cmd==MidiType.META_COPYRIGHT: return Copyright(fd)
  146. elif cmd==MidiType.META_TRACK_NAME: return TrackName(fd)
  147. elif cmd==MidiType.META_INSTRUMENT_NAME: return InstrumentName(fd)
  148. elif cmd==MidiType.META_LYRICS: return TextLyrics(fd)
  149. elif cmd==MidiType.META_TEXT_MARKER: return TextMarker(fd)
  150. elif cmd==MidiType.META_CUE_POINT: return CuePoint(fd)
  151. elif cmd==MidiType.META_CHANNEL_PREFIX: return ChannelPrefix(fd)
  152. elif cmd==MidiType.META_END_OF_TRACK: return EndOfTrack(fd)
  153. elif cmd==MidiType.META_SET_TEMPO: return SetTempo(fd)
  154. elif cmd==MidiType.META_SMPTE_OFFSET: return SMPTEOffset(fd)
  155. elif cmd==MidiType.META_TIME_SIGNATURE: return TimeSignature(fd)
  156. elif cmd==MidiType.META_KEY_SIGNATURE: return KeySignature(fd)
  157. elif cmd==MidiType.META_SPECIFIC: return MetaSpecific(fd)
  158. else: return MidiError(cmd, fd.offset)
  159. """
  160. Voices Messages
  161. """
  162. class MidiVoiceMessage(MidiMessage):
  163. def __init__(self, typ, ch, fd=None):
  164. MidiMessage.__init__(self, typ)
  165. self.channel=ch+1
  166. class NoteOn(MidiVoiceMessage):
  167. def __init__(self, ch, fd=None):
  168. MidiVoiceMessage.__init__(self, MidiType.NOTE_ON, ch)
  169. if fd:
  170. self.key=self.byte(fd)
  171. self.velocity=self.byte(fd)
  172. else:
  173. self.key = 0
  174. self.velocity = 0
  175. def bytes(self):
  176. return [MidiType.NOTE_ON | (self.channel-1), self.key, self.velocity]
  177. @staticmethod
  178. def new(chan, key, vel):
  179. x=NoteOn(chan+-1)
  180. x.key=key
  181. x.velocity=vel
  182. return x
  183. def transpose(self, n):
  184. self.key+=n
  185. def __str__(self):
  186. return "NOTEON("+str(self.key)+", "+ str(self.channel) +")"
  187. class NoteOff(MidiVoiceMessage):
  188. def __init__(self, ch, fd=None):
  189. MidiVoiceMessage.__init__(self, MidiType.NOTE_OFF, ch)
  190. if fd:
  191. self.key=self.byte(fd)
  192. self.velocity=self.byte(fd)
  193. else:
  194. self.key = 0
  195. self.velocity = 0
  196. def bytes(self):
  197. return [MidiType.NOTE_OFF | (self.channel-1), self.key, self.velocity]
  198. @staticmethod
  199. def new( chan, key, vel):
  200. x=NoteOff(chan-1)
  201. x.key=key
  202. x.velocity=vel
  203. return x
  204. def transpose(self, n):
  205. self.key+=n
  206. def __str__(self):
  207. return "NOTEOFF("+str(self.key)+", "+ str(self.channel) +")"
  208. class KeyPressure(MidiVoiceMessage):
  209. def __init__(self, ch, fd=None):
  210. MidiVoiceMessage.__init__(self, MidiType.KEY_PRESSURE, ch)
  211. if fd:
  212. self.key=self.byte(fd)
  213. self.pressure=self.byte(fd)
  214. def bytes(self):
  215. return [MidiType.KEY_PRESSURE | (self.channel-1), self.key, self.value]
  216. def new(self, chan, key, pressure):
  217. x=KeyPressure(chan-1)
  218. x.key=key
  219. x.pressure=pressure
  220. return x
  221. class ControlChange(MidiVoiceMessage):
  222. def __init__(self, ch, fd=None):
  223. MidiVoiceMessage.__init__(self, MidiType.CONTROL_CHANGE, ch)
  224. if fd:
  225. self.key=self.byte(fd)
  226. self.value=self.byte(fd)
  227. def bytes(self):
  228. return [MidiType.CONTROL_CHANGE | (self.channel-1), self.key, self.value]
  229. def new(self, chan, key, value):
  230. x=ControlChange(chan-1)
  231. x.key=key
  232. x.value=value
  233. return x
  234. class ProgramChange(MidiVoiceMessage):
  235. def __init__(self, ch, fd=None):
  236. MidiVoiceMessage.__init__(self, MidiType.PROGRAM_CHANGE, ch)
  237. if fd:
  238. self.key=self.byte(fd)
  239. def bytes(self):
  240. return [MidiType.PROGRAM_CHANGE | (self.channel-1), self.key]
  241. def new(self, chan, key):
  242. x=ProgramChange(chan-1)
  243. x.key=key
  244. return x
  245. class ChannelPressure(MidiVoiceMessage):
  246. def __init__(self, ch, fd=None):
  247. MidiVoiceMessage.__init__(self, MidiType.CHANNEL_PRESSURE, ch)
  248. if fd:
  249. self.pressure=self.byte(fd)
  250. def bytes(self):
  251. return [MidiType.CHANNEL_PRESSURE | (self.channel-1), self.key, self.pressure]
  252. def new(self, chan, pressure):
  253. x=ChannelPressure(chan-1)
  254. x.pressure=pressure
  255. return x
  256. class PitchWheelChange(MidiVoiceMessage):
  257. def __init__(self, ch, fd=None):
  258. MidiVoiceMessage.__init__(self, MidiType.PITCH_WHEEL_CHANGE, ch)
  259. if fd:
  260. self.pressure=self.byte(fd)
  261. self.pressure+=(self.byte(fd)<<7)
  262. def bytes(self):
  263. return [MidiType.PITCH_WHEEL_CHANGE | (self.channel-1),
  264. self.pressure & 0x7f, (self.pressure & 0x3f8)>>7]
  265. def new(self, chan, pressure):
  266. x=PitchWheelChange(chan-1)
  267. x.pressure=pressure
  268. return x
  269. """
  270. System Common Messages
  271. """
  272. class SystemExclusive(MidiMessage):
  273. def __init__(self, fd=None):
  274. MidiMessage.__init__(self, MidiType.SYSTEM_EXCLUSIVE)
  275. if fd:
  276. self.data=[]
  277. while True:
  278. x=self.byte(fd)
  279. if x==MidiMessage.END_OF_EXCUSIVE:
  280. break
  281. else:
  282. self.data.append(x)
  283. def bytes(self):
  284. return [MidiType.SYSTEM_EXCLUSIVE]+self.data+[MidiType.END_OF_EXCUSIVE]
  285. def new(self, data):
  286. x=SystemExclusive(chan)
  287. x.data=data
  288. return x
  289. class SongPointerPosition(MidiMessage):
  290. def __init__(self, fd=None):
  291. MidiMessage.__init__(self, MidiType.SONG_POSITION_POINTER)
  292. if fd:
  293. self.beats=self.byte(fd)
  294. self.beats+=(self.byte(fd)<<7)
  295. def bytes(self):
  296. return [MidiType.SONG_POSITION_POINTER, self.beats & 0x7f, (self.beats & 0x3f8)>>7]
  297. def new(self, beats):
  298. x=SongPointerPosition(chan)
  299. x.beats=beats
  300. return x
  301. class SongSelect(MidiMessage):
  302. def __init__(self, fd=None):
  303. MidiMessage.__init__(self, MidiType.SONG_SELECT)
  304. if fd:
  305. self.song=fd.self.byte(fd)
  306. def bytes(self):
  307. return [MidiType.SONG_SELECT, self.song]
  308. def new(self, song):
  309. x=SongSelect(chan)
  310. x.song=song
  311. return x
  312. class TuneRequest(MidiMessage):
  313. def __init__(self, fd=None):
  314. MidiMessage.__init__(self, MidiType.TUNE_REQUEST)
  315. def bytes(self):
  316. return [MidiType.TUNE_REQUEST]
  317. def new(self):
  318. return TuneRequest()
  319. """
  320. System RT Messages
  321. """
  322. class TimingClock(MidiMessage):
  323. def __init__(self, fd=None):
  324. MidiMessage.__init__(self, MidiType.TimingClock)
  325. def bytes(self):
  326. return [MidiType.TIMING_CLOCK]
  327. def new(self):
  328. return TimingClock()
  329. class Start(MidiMessage):
  330. def __init__(self, fd=None):
  331. MidiMessage.__init__(self, MidiType.START)
  332. def bytes(self):
  333. return [MidiType.START]
  334. def new(self):
  335. return Start()
  336. class Continue(MidiMessage):
  337. def __init__(self, fd=None):
  338. MidiMessage.__init__(self, MidiType.CONTINUE)
  339. def bytes(self):
  340. return [MidiType.CONTINUE]
  341. def new(self):
  342. return Continue()
  343. class Stop(MidiMessage):
  344. def __init__(self, fd=None):
  345. MidiMessage.__init__(self, MidiType.STOP)
  346. def bytes(self):
  347. return [MidiType.STOP]
  348. def new(self):
  349. return Stop()
  350. class ActiveSensing(MidiMessage):
  351. def __init__(self, fd=None):
  352. MidiMessage.__init__(self, MidiType.ACTIVE_SENSING)
  353. def bytes(self):
  354. return [MidiType.ACTIVE_SENSING]
  355. def new(self):
  356. return ActiveSensing()
  357. """
  358. Meta
  359. """
  360. class Meta(MidiMessage):
  361. def __init__(self, cmd):
  362. MidiMessage.__init__(self, MidiType.META)
  363. self.command=cmd
  364. class EndOfTrack(Meta):
  365. def __init__(self, fd=None):
  366. Meta.__init__(self, MidiType.META_END_OF_TRACK)
  367. if fd:
  368. self.byte(fd)
  369. def isEndTrack(self):
  370. return True
  371. def bytes(self):
  372. return [MidiType.META, self.command, 0]
  373. def new(self):
  374. return EndOfTrack()
  375. class SequenceNumber(Meta):
  376. def __init__(self, fd=None):
  377. Meta.__init__(self, MidiType.META_SEQ)
  378. if fd:
  379. self.number=self.byte(fd)
  380. def bytes(self):
  381. return [MidiType.META, self.command, 0x2]
  382. def new(self):
  383. return SequenceNumber()
  384. class TextEvent(Meta):
  385. def __init__(self, fd=None):
  386. Meta.__init__(self, MidiType.META_TEXT)
  387. if fd:
  388. self.text=fd.read(self.byte(fd)).decode("utf-8")
  389. def bytes(self):
  390. return [MidiType.META, self.command,
  391. len(self.text)]+[e.encode("hex") for e in self.text]
  392. def new(self, text):
  393. x=TextEvent()
  394. self.text=text
  395. return x
  396. class Copyright(Meta):
  397. def __init__(self,cmd, fd=None):
  398. Meta.__init__(self, MidiType.META_COPYRIGHT)
  399. if fd:
  400. self.text=fd.read(self.byte(fd)).decode("utf-8")
  401. def bytes(self):
  402. return [MidiType.META, self.command,
  403. len(self.text)]+[e.encode("hex") for e in self.text]
  404. def new(self, text):
  405. x=Copyright()
  406. self.text=text
  407. return x
  408. class TrackName(Meta):
  409. def __init__(self, fd=None):
  410. Meta.__init__(self, MidiType.META_TRACK_NAME)
  411. if fd:
  412. self.text=fd.read(self.byte(fd)).decode("utf-8")
  413. def bytes(self):
  414. return [MidiType.META, self.command,
  415. len(self.text)]+[e.encode("hex") for e in self.text]
  416. def new(self, text):
  417. x=TrackName()
  418. self.text=text
  419. return x
  420. class InstrumentName(Meta):
  421. def __init__(self, fd=None):
  422. Meta.__init__(self, MidiType.META_INSTRUMENT_NAME)
  423. if fd:
  424. self.text=fd.read(self.byte(fd)).decode("utf-8")
  425. def bytes(self):
  426. return [MidiType.META, self.command,
  427. len(self.text)]+[e.encode("hex") for e in self.text]
  428. def new(self, text):
  429. x=InstrumentName()
  430. self.text=text
  431. return x
  432. class TextLyrics(Meta):
  433. def __init__(self, fd=None):
  434. Meta.__init__(self, MidiType.META_LYRICS)
  435. if fd:
  436. self.text=fd.read(self.byte(fd)).decode("utf-8")
  437. def bytes(self):
  438. return [MidiType.META, self.command,
  439. len(self.text)]+[e.encode("hex") for e in self.text]
  440. def new(self, text):
  441. x=TextLyrics()
  442. self.text=text
  443. return x
  444. class TextMarker(Meta):
  445. def __init__(self, fd=None):
  446. Meta.__init__(self, MidiType.META_TEXT_MARKER)
  447. if fd:
  448. self.text=fd.read(self.byte(fd)).decode("utf-8")
  449. def bytes(self):
  450. return [MidiType.META, self.command,
  451. len(self.text)]+[e.encode("hex") for e in self.text]
  452. def new(self, text):
  453. x=TextMarker()
  454. self.text=text
  455. return x
  456. class CuePoint(Meta):
  457. def __init__(self, fd=None):
  458. Meta.__init__(self, MidiType.META_CUE_POINT)
  459. if fd:
  460. self.text=fd.read(self.byte(fd)).decode("utf-8")
  461. def bytes(self):
  462. return [MidiType.META, self.command,
  463. len(self.text)]+[e.encode("hex") for e in self.text]
  464. def new(self, text):
  465. x=CuePoint()
  466. self.text=text
  467. return x
  468. class ChannelPrefix(Meta):
  469. def __init__(self, fd=None):
  470. Meta.__init__(self, MidiType.META_CHANNEL_PREFIX)
  471. if fd:
  472. self.byte(fd)
  473. self.channelPrefix=self.byte(fd)
  474. def bytes(self):
  475. return [MidiType.META, self.command, 1, self.channelPrefix]
  476. def new(self, channelPrefix):
  477. x=ChannelPrefix()
  478. self.channelPrefix=channelPrefix
  479. return x
  480. class SetTempo(Meta):
  481. def __init__(self, fd=None):
  482. Meta.__init__(self, MidiType.META_SET_TEMPO)
  483. if fd:
  484. self.byte(fd)
  485. self.tempo=self.byte(fd)<<16
  486. self.tempo+=self.byte(fd)<<8
  487. self.tempo+=self.byte(fd)
  488. def bytes(self):
  489. x=self.tempo
  490. return [MidiType.META, self.command, 3, (x&0xFF0000)>>16,
  491. (x&0xFF00)>>8, x&0xFF ]
  492. def new(self, tempo):
  493. x=SetTempo()
  494. self.tempo=tempo
  495. return x
  496. class SMPTEOffset(Meta):
  497. def __init__(self, fd=None):
  498. Meta.__init__(self, MidiType.META_SMPTE_OFFSET)
  499. if fd:
  500. self.byte(fd)
  501. self.hour=self.byte(fd)
  502. self.minutes=self.byte(fd)
  503. self.seconds=self.byte(fd)
  504. self.frame=self.byte(fd)
  505. self.fraction=self.byte(fd)
  506. def bytes(self):
  507. return [MidiType.META, self.command, 5, self.hour, self.minutes,
  508. self.seconds, self.frame, self.fraction]
  509. def new(self, hh, mm, ss, fr, ff):
  510. x=SMPTEOffset()
  511. x.hour=hh
  512. x.minutes=mm
  513. x.seconds=ss
  514. x.frame=fr
  515. x.fraction=ff
  516. return x
  517. class TimeSignature(Meta):
  518. def __init__(self, fd=None):
  519. Meta.__init__(self, MidiType.META_TIME_SIGNATURE)
  520. if fd:
  521. self.byte(fd)
  522. self.numerator=self.byte(fd)
  523. self.denominator=self.byte(fd)
  524. self.clic=self.byte(fd)
  525. self.notes=self.byte(fd)
  526. def bytes(self):
  527. return [MidiType.META, self.command, 4, self.numerator, self.denominator,
  528. self.clic, self.notes]
  529. def new(self, numerator, denominator, clic, notes):
  530. x=TimeSignature()
  531. x.numerator=numerator
  532. x.denominator=denominator
  533. x.clic=clic
  534. x.notes=notes
  535. return x
  536. class KeySignature(Meta):
  537. def __init__(self, fd=None):
  538. Meta.__init__(self, MidiType.META_KEY_SIGNATURE)
  539. if fd:
  540. self.byte(fd)
  541. self.sf=self.byte(fd)
  542. self.mi=self.byte(fd)
  543. def bytes(self):
  544. return [MidiType.META, self.command, 2, self.sf, self.mi]
  545. def new(self, sf, mi):
  546. x=KeySignature()
  547. self.sf=sf
  548. self.mi=mi
  549. return x
  550. class MetaSpecific(Meta):
  551. def __init__(self, fd=None):
  552. Meta.__init__(self, MidiType.META_SPECIFIC)
  553. if fd:
  554. self.length=self.byte(fd)
  555. self.data=self.read(fd, self.length)
  556. def bytes(self):
  557. return [MidiType.META, self.command, self.length, self.data]
  558. def new(self, data):
  559. x=KeySignature()
  560. self.data=data
  561. self.length=len(data)
  562. return x
  563. """
  564. Error
  565. """
  566. class MidiError(MidiMessage):
  567. def __init__(self, first, offset):
  568. MidiMessage.__init__(self, MidiType.ERROR)
  569. raise MIDIParserException("First Midi byte ("+hex(first)+") is unknown at: "+hex(offset))