midimessage.py 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873
  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. def bytes(self):
  173. return [MidiType.NOTE_ON | (self.channel-1), self.key, self.velocity]
  174. @staticmethod
  175. def new(chan, key, vel):
  176. x=NoteOn(chan+-1)
  177. x.key=key
  178. x.velocity=vel
  179. return x
  180. def transpose(self, n):
  181. self.key+=n
  182. def __str__(self):
  183. return "NOTEON("+str(self.key)+", "+ str(self.channel) +")"
  184. class NoteOff(MidiVoiceMessage):
  185. def __init__(self, ch, fd=None):
  186. MidiVoiceMessage.__init__(self, MidiType.NOTE_OFF, ch)
  187. if fd:
  188. self.key=self.byte(fd)
  189. self.velocity=self.byte(fd)
  190. def bytes(self):
  191. return [MidiType.NOTE_OFF | (self.channel-1), self.key, self.velocity]
  192. @staticmethod
  193. def new( chan, key, vel):
  194. x=NoteOff(chan-1)
  195. x.key=key
  196. x.velocity=vel
  197. return x
  198. def transpose(self, n):
  199. self.key+=n
  200. class KeyPressure(MidiVoiceMessage):
  201. def __init__(self, ch, fd=None):
  202. MidiVoiceMessage.__init__(self, MidiType.KEY_PRESSURE, ch)
  203. if fd:
  204. self.key=self.byte(fd)
  205. self.pressure=self.byte(fd)
  206. def bytes(self):
  207. return [MidiType.KEY_PRESSURE | (self.channel-1), self.key, self.value]
  208. def new(self, chan, key, pressure):
  209. x=KeyPressure(chan-1)
  210. x.key=key
  211. x.pressure=pressure
  212. return x
  213. class ControlChange(MidiVoiceMessage):
  214. def __init__(self, ch, fd=None):
  215. MidiVoiceMessage.__init__(self, MidiType.CONTROL_CHANGE, ch)
  216. if fd:
  217. self.key=self.byte(fd)
  218. self.value=self.byte(fd)
  219. def bytes(self):
  220. return [MidiType.CONTROL_CHANGE | (self.channel-1), self.key, self.value]
  221. def new(self, chan, key, value):
  222. x=ControlChange(chan-1)
  223. x.key=key
  224. x.value=value
  225. return x
  226. class ProgramChange(MidiVoiceMessage):
  227. def __init__(self, ch, fd=None):
  228. MidiVoiceMessage.__init__(self, MidiType.PROGRAM_CHANGE, ch)
  229. if fd:
  230. self.key=self.byte(fd)
  231. def bytes(self):
  232. return [MidiType.PROGRAM_CHANGE | (self.channel-1), self.key]
  233. def new(self, chan, key):
  234. x=ProgramChange(chan-1)
  235. x.key=key
  236. return x
  237. class ChannelPressure(MidiVoiceMessage):
  238. def __init__(self, ch, fd=None):
  239. MidiVoiceMessage.__init__(self, MidiType.CHANNEL_PRESSURE, ch)
  240. if fd:
  241. self.pressure=self.byte(fd)
  242. def bytes(self):
  243. return [MidiType.CHANNEL_PRESSURE | (self.channel-1), self.key, self.pressure]
  244. def new(self, chan, pressure):
  245. x=ChannelPressure(chan-1)
  246. x.pressure=pressure
  247. return x
  248. class PitchWheelChange(MidiVoiceMessage):
  249. def __init__(self, ch, fd=None):
  250. MidiVoiceMessage.__init__(self, MidiType.PITCH_WHEEL_CHANGE, ch)
  251. if fd:
  252. self.pressure=self.byte(fd)
  253. self.pressure+=(self.byte(fd)<<7)
  254. def bytes(self):
  255. return [MidiType.PITCH_WHEEL_CHANGE | (self.channel-1),
  256. self.pressure & 0x7f, (self.pressure & 0x3f8)>>7]
  257. def new(self, chan, pressure):
  258. x=PitchWheelChange(chan-1)
  259. x.pressure=pressure
  260. return x
  261. """
  262. System Common Messages
  263. """
  264. class SystemExclusive(MidiMessage):
  265. def __init__(self, fd=None):
  266. MidiMessage.__init__(self, MidiType.SYSTEM_EXCLUSIVE)
  267. if fd:
  268. self.data=[]
  269. while True:
  270. x=self.byte(fd)
  271. if x==MidiMessage.END_OF_EXCUSIVE:
  272. break
  273. else:
  274. self.data.append(x)
  275. def bytes(self):
  276. return [MidiType.SYSTEM_EXCLUSIVE]+self.data+[MidiType.END_OF_EXCUSIVE]
  277. def new(self, data):
  278. x=SystemExclusive(chan)
  279. x.data=data
  280. return x
  281. class SongPointerPosition(MidiMessage):
  282. def __init__(self, fd=None):
  283. MidiMessage.__init__(self, MidiType.SONG_POSITION_POINTER)
  284. if fd:
  285. self.beats=self.byte(fd)
  286. self.beats+=(self.byte(fd)<<7)
  287. def bytes(self):
  288. return [MidiType.SONG_POSITION_POINTER, self.beats & 0x7f, (self.beats & 0x3f8)>>7]
  289. def new(self, beats):
  290. x=SongPointerPosition(chan)
  291. x.beats=beats
  292. return x
  293. class SongSelect(MidiMessage):
  294. def __init__(self, fd=None):
  295. MidiMessage.__init__(self, MidiType.SONG_SELECT)
  296. if fd:
  297. self.song=fd.self.byte(fd)
  298. def bytes(self):
  299. return [MidiType.SONG_SELECT, self.song]
  300. def new(self, song):
  301. x=SongSelect(chan)
  302. x.song=song
  303. return x
  304. class TuneRequest(MidiMessage):
  305. def __init__(self, fd=None):
  306. MidiMessage.__init__(self, MidiType.TUNE_REQUEST)
  307. def bytes(self):
  308. return [MidiType.TUNE_REQUEST]
  309. def new(self):
  310. return TuneRequest()
  311. """
  312. System RT Messages
  313. """
  314. class TimingClock(MidiMessage):
  315. def __init__(self, fd=None):
  316. MidiMessage.__init__(self, MidiType.TimingClock)
  317. def bytes(self):
  318. return [MidiType.TIMING_CLOCK]
  319. def new(self):
  320. return TimingClock()
  321. class Start(MidiMessage):
  322. def __init__(self, fd=None):
  323. MidiMessage.__init__(self, MidiType.START)
  324. def bytes(self):
  325. return [MidiType.START]
  326. def new(self):
  327. return Start()
  328. class Continue(MidiMessage):
  329. def __init__(self, fd=None):
  330. MidiMessage.__init__(self, MidiType.CONTINUE)
  331. def bytes(self):
  332. return [MidiType.CONTINUE]
  333. def new(self):
  334. return Continue()
  335. class Stop(MidiMessage):
  336. def __init__(self, fd=None):
  337. MidiMessage.__init__(self, MidiType.STOP)
  338. def bytes(self):
  339. return [MidiType.STOP]
  340. def new(self):
  341. return Stop()
  342. class ActiveSensing(MidiMessage):
  343. def __init__(self, fd=None):
  344. MidiMessage.__init__(self, MidiType.ACTIVE_SENSING)
  345. def bytes(self):
  346. return [MidiType.ACTIVE_SENSING]
  347. def new(self):
  348. return ActiveSensing()
  349. """
  350. Meta
  351. """
  352. class Meta(MidiMessage):
  353. def __init__(self, cmd):
  354. MidiMessage.__init__(self, MidiType.META)
  355. self.command=cmd
  356. class EndOfTrack(Meta):
  357. def __init__(self, fd=None):
  358. Meta.__init__(self, MidiType.META_END_OF_TRACK)
  359. if fd:
  360. self.byte(fd)
  361. def isEndTrack(self):
  362. return True
  363. def bytes(self):
  364. return [MidiType.META, self.command, 0]
  365. def new(self):
  366. return EndOfTrack()
  367. class SequenceNumber(Meta):
  368. def __init__(self, fd=None):
  369. Meta.__init__(self, MidiType.META_SEQ)
  370. if fd:
  371. self.number=self.byte(fd)
  372. def bytes(self):
  373. return [MidiType.META, self.command, 0x2]
  374. def new(self):
  375. return SequenceNumber()
  376. class TextEvent(Meta):
  377. def __init__(self, fd=None):
  378. Meta.__init__(self, MidiType.META_TEXT)
  379. if fd:
  380. self.text=fd.read(self.byte(fd)).decode("utf-8")
  381. def bytes(self):
  382. return [MidiType.META, self.command,
  383. len(self.text)]+[e.encode("hex") for e in self.text]
  384. def new(self, text):
  385. x=TextEvent()
  386. self.text=text
  387. return x
  388. class Copyright(Meta):
  389. def __init__(self,cmd, fd=None):
  390. Meta.__init__(self, MidiType.META_COPYRIGHT)
  391. if fd:
  392. self.text=fd.read(self.byte(fd)).decode("utf-8")
  393. def bytes(self):
  394. return [MidiType.META, self.command,
  395. len(self.text)]+[e.encode("hex") for e in self.text]
  396. def new(self, text):
  397. x=Copyright()
  398. self.text=text
  399. return x
  400. class TrackName(Meta):
  401. def __init__(self, fd=None):
  402. Meta.__init__(self, MidiType.META_TRACK_NAME)
  403. if fd:
  404. self.text=fd.read(self.byte(fd)).decode("utf-8")
  405. def bytes(self):
  406. return [MidiType.META, self.command,
  407. len(self.text)]+[e.encode("hex") for e in self.text]
  408. def new(self, text):
  409. x=TrackName()
  410. self.text=text
  411. return x
  412. class InstrumentName(Meta):
  413. def __init__(self, fd=None):
  414. Meta.__init__(self, MidiType.META_INSTRUMENT_NAME)
  415. if fd:
  416. self.text=fd.read(self.byte(fd)).decode("utf-8")
  417. def bytes(self):
  418. return [MidiType.META, self.command,
  419. len(self.text)]+[e.encode("hex") for e in self.text]
  420. def new(self, text):
  421. x=InstrumentName()
  422. self.text=text
  423. return x
  424. class TextLyrics(Meta):
  425. def __init__(self, fd=None):
  426. Meta.__init__(self, MidiType.META_LYRICS)
  427. if fd:
  428. self.text=fd.read(self.byte(fd)).decode("utf-8")
  429. def bytes(self):
  430. return [MidiType.META, self.command,
  431. len(self.text)]+[e.encode("hex") for e in self.text]
  432. def new(self, text):
  433. x=TextLyrics()
  434. self.text=text
  435. return x
  436. class TextMarker(Meta):
  437. def __init__(self, fd=None):
  438. Meta.__init__(self, MidiType.META_TEXT_MARKER)
  439. if fd:
  440. self.text=fd.read(self.byte(fd)).decode("utf-8")
  441. def bytes(self):
  442. return [MidiType.META, self.command,
  443. len(self.text)]+[e.encode("hex") for e in self.text]
  444. def new(self, text):
  445. x=TextMarker()
  446. self.text=text
  447. return x
  448. class CuePoint(Meta):
  449. def __init__(self, fd=None):
  450. Meta.__init__(self, MidiType.META_CUE_POINT)
  451. if fd:
  452. self.text=fd.read(self.byte(fd)).decode("utf-8")
  453. def bytes(self):
  454. return [MidiType.META, self.command,
  455. len(self.text)]+[e.encode("hex") for e in self.text]
  456. def new(self, text):
  457. x=CuePoint()
  458. self.text=text
  459. return x
  460. class ChannelPrefix(Meta):
  461. def __init__(self, fd=None):
  462. Meta.__init__(self, MidiType.META_CHANNEL_PREFIX)
  463. if fd:
  464. self.byte(fd)
  465. self.channelPrefix=self.byte(fd)
  466. def bytes(self):
  467. return [MidiType.META, self.command, 1, self.channelPrefix]
  468. def new(self, channelPrefix):
  469. x=ChannelPrefix()
  470. self.channelPrefix=channelPrefix
  471. return x
  472. class SetTempo(Meta):
  473. def __init__(self, fd=None):
  474. Meta.__init__(self, MidiType.META_SET_TEMPO)
  475. if fd:
  476. self.byte(fd)
  477. self.tempo=self.byte(fd)<<16
  478. self.tempo+=self.byte(fd)<<8
  479. self.tempo+=self.byte(fd)
  480. def bytes(self):
  481. x=self.tempo
  482. return [MidiType.META, self.command, 3, (x&0xFF0000)>>16,
  483. (x&0xFF00)>>8, x&0xFF ]
  484. def new(self, tempo):
  485. x=SetTempo()
  486. self.tempo=tempo
  487. return x
  488. class SMPTEOffset(Meta):
  489. def __init__(self, fd=None):
  490. Meta.__init__(self, MidiType.META_SMPTE_OFFSET)
  491. if fd:
  492. self.byte(fd)
  493. self.hour=self.byte(fd)
  494. self.minutes=self.byte(fd)
  495. self.seconds=self.byte(fd)
  496. self.frame=self.byte(fd)
  497. self.fraction=self.byte(fd)
  498. def bytes(self):
  499. return [MidiType.META, self.command, 5, self.hour, self.minutes,
  500. self.seconds, self.frame, self.fraction]
  501. def new(self, hh, mm, ss, fr, ff):
  502. x=SMPTEOffset()
  503. x.hour=hh
  504. x.minutes=mm
  505. x.seconds=ss
  506. x.frame=fr
  507. x.fraction=ff
  508. return x
  509. class TimeSignature(Meta):
  510. def __init__(self, fd=None):
  511. Meta.__init__(self, MidiType.META_TIME_SIGNATURE)
  512. if fd:
  513. self.byte(fd)
  514. self.numerator=self.byte(fd)
  515. self.denominator=self.byte(fd)
  516. self.clic=self.byte(fd)
  517. self.notes=self.byte(fd)
  518. def bytes(self):
  519. return [MidiType.META, self.command, 4, self.numerator, self.denominator,
  520. self.clic, self.notes]
  521. def new(self, numerator, denominator, clic, notes):
  522. x=TimeSignature()
  523. x.numerator=numerator
  524. x.denominator=denominator
  525. x.clic=clic
  526. x.notes=notes
  527. return x
  528. class KeySignature(Meta):
  529. def __init__(self, fd=None):
  530. Meta.__init__(self, MidiType.META_KEY_SIGNATURE)
  531. if fd:
  532. self.byte(fd)
  533. self.sf=self.byte(fd)
  534. self.mi=self.byte(fd)
  535. def bytes(self):
  536. return [MidiType.META, self.command, 2, self.sf, self.mi]
  537. def new(self, sf, mi):
  538. x=KeySignature()
  539. self.sf=sf
  540. self.mi=mi
  541. return x
  542. class MetaSpecific(Meta):
  543. def __init__(self, fd=None):
  544. Meta.__init__(self, MidiType.META_SPECIFIC)
  545. if fd:
  546. self.length=self.byte(fd)
  547. self.data=self.read(fd, self.length)
  548. def bytes(self):
  549. return [MidiType.META, self.command, self.length, self.data]
  550. def new(self, data):
  551. x=KeySignature()
  552. self.data=data
  553. self.length=len(data)
  554. return x
  555. """
  556. Error
  557. """
  558. class MidiError(MidiMessage):
  559. def __init__(self, first, offset):
  560. MidiMessage.__init__(self, MidiType.ERROR)
  561. raise MIDIParserException("First Midi byte ("+hex(first)+") is unknown at: "+hex(offset))