/src/echonest/support/midi/MidiOutStream.py

http://echo-nest-remix.googlecode.com/ · Python · 471 lines · 134 code · 8 blank · 329 comment · 6 complexity · 4039d2767524f78e22adb5830e7fbbfc MD5 · raw file

  1. # -*- coding: ISO-8859-1 -*-
  2. class MidiOutStream:
  3. """
  4. MidiOutstream is Basically an eventhandler. It is the most central
  5. class in the Midi library. You use it both for writing events to
  6. an output stream, and as an event handler for an input stream.
  7. This makes it extremely easy to take input from one stream and
  8. send it to another. Ie. if you want to read a Midi file, do some
  9. processing, and send it to a midiport.
  10. All time values are in absolute values from the opening of a
  11. stream. To calculate time values, please use the MidiTime and
  12. MidiDeltaTime classes.
  13. """
  14. def __init__(self):
  15. # the time is rather global, so it needs to be stored
  16. # here. Otherwise there would be no really simple way to
  17. # calculate it. The alternative would be to have each event
  18. # handler do it. That sucks even worse!
  19. self._absolute_time = 0
  20. self._relative_time = 0
  21. self._current_track = 0
  22. self._running_status = None
  23. # time handling event handlers. They should be overwritten with care
  24. def update_time(self, new_time=0, relative=1):
  25. """
  26. Updates the time, if relative is true, new_time is relative,
  27. else it's absolute.
  28. """
  29. if relative:
  30. self._relative_time = new_time
  31. self._absolute_time += new_time
  32. else:
  33. self._relative_time = new_time - self._absolute_time
  34. self._absolute_time = new_time
  35. def reset_time(self):
  36. """
  37. reset time to 0
  38. """
  39. self._relative_time = 0
  40. self._absolute_time = 0
  41. def rel_time(self):
  42. "Returns the relative time"
  43. return self._relative_time
  44. def abs_time(self):
  45. "Returns the absolute time"
  46. return self._absolute_time
  47. # running status methods
  48. def reset_run_stat(self):
  49. "Invalidates the running status"
  50. self._running_status = None
  51. def set_run_stat(self, new_status):
  52. "Set the new running status"
  53. self._running_status = new_status
  54. def get_run_stat(self):
  55. "Set the new running status"
  56. return self._running_status
  57. # track handling event handlers
  58. def set_current_track(self, new_track):
  59. "Sets the current track number"
  60. self._current_track = new_track
  61. def get_current_track(self):
  62. "Returns the current track number"
  63. return self._current_track
  64. #####################
  65. ## Midi events
  66. def channel_message(self, message_type, channel, data):
  67. """The default event handler for channel messages"""
  68. pass
  69. def note_on(self, channel=0, note=0x40, velocity=0x40):
  70. """
  71. channel: 0-15
  72. note, velocity: 0-127
  73. """
  74. pass
  75. def note_off(self, channel=0, note=0x40, velocity=0x40):
  76. """
  77. channel: 0-15
  78. note, velocity: 0-127
  79. """
  80. pass
  81. def aftertouch(self, channel=0, note=0x40, velocity=0x40):
  82. """
  83. channel: 0-15
  84. note, velocity: 0-127
  85. """
  86. pass
  87. def continuous_controller(self, channel, controller, value):
  88. """
  89. channel: 0-15
  90. controller, value: 0-127
  91. """
  92. pass
  93. def patch_change(self, channel, patch):
  94. """
  95. channel: 0-15
  96. patch: 0-127
  97. """
  98. pass
  99. def channel_pressure(self, channel, pressure):
  100. """
  101. channel: 0-15
  102. pressure: 0-127
  103. """
  104. pass
  105. def pitch_bend(self, channel, value):
  106. """
  107. channel: 0-15
  108. value: 0-16383
  109. """
  110. pass
  111. #####################
  112. ## System Exclusive
  113. def system_exclusive(self, data):
  114. """
  115. data: list of values in range(128)
  116. """
  117. pass
  118. #####################
  119. ## Common events
  120. def song_position_pointer(self, value):
  121. """
  122. value: 0-16383
  123. """
  124. pass
  125. def song_select(self, songNumber):
  126. """
  127. songNumber: 0-127
  128. """
  129. pass
  130. def tuning_request(self):
  131. """
  132. No values passed
  133. """
  134. pass
  135. def midi_time_code(self, msg_type, values):
  136. """
  137. msg_type: 0-7
  138. values: 0-15
  139. """
  140. pass
  141. #########################
  142. # header does not really belong here. But anyhoo!!!
  143. def header(self, format=0, nTracks=1, division=96):
  144. """
  145. format: type of midi file in [1,2]
  146. nTracks: number of tracks
  147. division: timing division
  148. """
  149. pass
  150. def eof(self):
  151. """
  152. End of file. No more events to be processed.
  153. """
  154. pass
  155. #####################
  156. ## meta events
  157. def meta_event(self, meta_type, data):
  158. """
  159. Handles any undefined meta events
  160. """
  161. pass
  162. def start_of_track(self, n_track=0):
  163. """
  164. n_track: number of track
  165. """
  166. pass
  167. def end_of_track(self):
  168. """
  169. n_track: number of track
  170. """
  171. pass
  172. def sequence_number(self, value):
  173. """
  174. value: 0-16383
  175. """
  176. pass
  177. def text(self, text):
  178. """
  179. Text event
  180. text: string
  181. """
  182. pass
  183. def copyright(self, text):
  184. """
  185. Copyright notice
  186. text: string
  187. """
  188. pass
  189. def sequence_name(self, text):
  190. """
  191. Sequence/track name
  192. text: string
  193. """
  194. pass
  195. def instrument_name(self, text):
  196. """
  197. text: string
  198. """
  199. pass
  200. def lyric(self, text):
  201. """
  202. text: string
  203. """
  204. pass
  205. def marker(self, text):
  206. """
  207. text: string
  208. """
  209. pass
  210. def cuepoint(self, text):
  211. """
  212. text: string
  213. """
  214. pass
  215. def midi_ch_prefix(self, channel):
  216. """
  217. channel: midi channel for subsequent data (deprecated in the spec)
  218. """
  219. pass
  220. def midi_port(self, value):
  221. """
  222. value: Midi port (deprecated in the spec)
  223. """
  224. pass
  225. def tempo(self, value):
  226. """
  227. value: 0-2097151
  228. tempo in us/quarternote
  229. (to calculate value from bpm: int(60,000,000.00 / BPM))
  230. """
  231. pass
  232. def smtp_offset(self, hour, minute, second, frame, framePart):
  233. """
  234. hour,
  235. minute,
  236. second: 3 bytes specifying the hour (0-23), minutes (0-59) and
  237. seconds (0-59), respectively. The hour should be
  238. encoded with the SMPTE format, just as it is in MIDI
  239. Time Code.
  240. frame: A byte specifying the number of frames per second (one
  241. of : 24, 25, 29, 30).
  242. framePart: A byte specifying the number of fractional frames,
  243. in 100ths of a frame (even in SMPTE-based tracks
  244. using a different frame subdivision, defined in the
  245. MThd chunk).
  246. """
  247. pass
  248. def time_signature(self, nn, dd, cc, bb):
  249. """
  250. nn: Numerator of the signature as notated on sheet music
  251. dd: Denominator of the signature as notated on sheet music
  252. The denominator is a negative power of 2: 2 = quarter
  253. note, 3 = eighth, etc.
  254. cc: The number of MIDI clocks in a metronome click
  255. bb: The number of notated 32nd notes in a MIDI quarter note
  256. (24 MIDI clocks)
  257. """
  258. pass
  259. def key_signature(self, sf, mi):
  260. """
  261. sf: is a byte specifying the number of flats (-ve) or sharps
  262. (+ve) that identifies the key signature (-7 = 7 flats, -1
  263. = 1 flat, 0 = key of C, 1 = 1 sharp, etc).
  264. mi: is a byte specifying a major (0) or minor (1) key.
  265. """
  266. pass
  267. def sequencer_specific(self, data):
  268. """
  269. data: The data as byte values
  270. """
  271. pass
  272. #####################
  273. ## realtime events
  274. def timing_clock(self):
  275. """
  276. No values passed
  277. """
  278. pass
  279. def song_start(self):
  280. """
  281. No values passed
  282. """
  283. pass
  284. def song_stop(self):
  285. """
  286. No values passed
  287. """
  288. pass
  289. def song_continue(self):
  290. """
  291. No values passed
  292. """
  293. pass
  294. def active_sensing(self):
  295. """
  296. No values passed
  297. """
  298. pass
  299. def system_reset(self):
  300. """
  301. No values passed
  302. """
  303. pass
  304. if __name__ == '__main__':
  305. midiOut = MidiOutStream()
  306. midiOut.update_time(0,0)
  307. midiOut.note_on(0, 63, 127)
  308. midiOut.note_off(0, 63, 127)