midilib 0.8.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (252) hide show
  1. data/ChangeLog +87 -0
  2. data/Credits +8 -0
  3. data/README +361 -0
  4. data/Rakefile +68 -0
  5. data/TODO +25 -0
  6. data/examples/NoFences.mid +0 -0
  7. data/examples/from_scratch.mid +0 -0
  8. data/examples/from_scratch.rb +56 -0
  9. data/examples/reader2text.rb +220 -0
  10. data/examples/seq2text.rb +41 -0
  11. data/examples/strings.rb +34 -0
  12. data/examples/transpose.rb +75 -0
  13. data/html/classes/MIDI.html +738 -0
  14. data/html/classes/MIDI/ActiveSense.html +156 -0
  15. data/html/classes/MIDI/ActiveSense.src/M000136.html +18 -0
  16. data/html/classes/MIDI/ActiveSense.src/M000137.html +18 -0
  17. data/html/classes/MIDI/ChannelEvent.html +179 -0
  18. data/html/classes/MIDI/ChannelEvent.src/M000124.html +20 -0
  19. data/html/classes/MIDI/ChannelEvent.src/M000125.html +18 -0
  20. data/html/classes/MIDI/ChannelPressure.html +184 -0
  21. data/html/classes/MIDI/ChannelPressure.src/M000088.html +19 -0
  22. data/html/classes/MIDI/ChannelPressure.src/M000089.html +21 -0
  23. data/html/classes/MIDI/ChannelPressure.src/M000090.html +18 -0
  24. data/html/classes/MIDI/Clock.html +156 -0
  25. data/html/classes/MIDI/Clock.src/M000134.html +18 -0
  26. data/html/classes/MIDI/Clock.src/M000135.html +18 -0
  27. data/html/classes/MIDI/Continue.html +156 -0
  28. data/html/classes/MIDI/Continue.src/M000132.html +18 -0
  29. data/html/classes/MIDI/Continue.src/M000133.html +18 -0
  30. data/html/classes/MIDI/Controller.html +189 -0
  31. data/html/classes/MIDI/Controller.src/M000129.html +21 -0
  32. data/html/classes/MIDI/Controller.src/M000130.html +22 -0
  33. data/html/classes/MIDI/Controller.src/M000131.html +18 -0
  34. data/html/classes/MIDI/Event.html +424 -0
  35. data/html/classes/MIDI/Event.src/M000145.html +27 -0
  36. data/html/classes/MIDI/Event.src/M000146.html +18 -0
  37. data/html/classes/MIDI/Event.src/M000147.html +18 -0
  38. data/html/classes/MIDI/Event.src/M000148.html +18 -0
  39. data/html/classes/MIDI/Event.src/M000149.html +18 -0
  40. data/html/classes/MIDI/Event.src/M000150.html +18 -0
  41. data/html/classes/MIDI/Event.src/M000151.html +18 -0
  42. data/html/classes/MIDI/Event.src/M000152.html +18 -0
  43. data/html/classes/MIDI/Event.src/M000153.html +18 -0
  44. data/html/classes/MIDI/Event.src/M000154.html +22 -0
  45. data/html/classes/MIDI/Event.src/M000155.html +18 -0
  46. data/html/classes/MIDI/Event.src/M000156.html +18 -0
  47. data/html/classes/MIDI/Event.src/M000157.html +18 -0
  48. data/html/classes/MIDI/IO.html +121 -0
  49. data/html/classes/MIDI/IO/MIDIFile.html +925 -0
  50. data/html/classes/MIDI/IO/MIDIFile.src/M000028.html +22 -0
  51. data/html/classes/MIDI/IO/MIDIFile.src/M000029.html +24 -0
  52. data/html/classes/MIDI/IO/MIDIFile.src/M000030.html +19 -0
  53. data/html/classes/MIDI/IO/MIDIFile.src/M000031.html +19 -0
  54. data/html/classes/MIDI/IO/MIDIFile.src/M000032.html +17 -0
  55. data/html/classes/MIDI/IO/MIDIFile.src/M000033.html +17 -0
  56. data/html/classes/MIDI/IO/MIDIFile.src/M000034.html +17 -0
  57. data/html/classes/MIDI/IO/MIDIFile.src/M000035.html +17 -0
  58. data/html/classes/MIDI/IO/MIDIFile.src/M000036.html +17 -0
  59. data/html/classes/MIDI/IO/MIDIFile.src/M000037.html +17 -0
  60. data/html/classes/MIDI/IO/MIDIFile.src/M000038.html +17 -0
  61. data/html/classes/MIDI/IO/MIDIFile.src/M000039.html +17 -0
  62. data/html/classes/MIDI/IO/MIDIFile.src/M000040.html +17 -0
  63. data/html/classes/MIDI/IO/MIDIFile.src/M000041.html +17 -0
  64. data/html/classes/MIDI/IO/MIDIFile.src/M000042.html +17 -0
  65. data/html/classes/MIDI/IO/MIDIFile.src/M000043.html +17 -0
  66. data/html/classes/MIDI/IO/MIDIFile.src/M000044.html +17 -0
  67. data/html/classes/MIDI/IO/MIDIFile.src/M000045.html +17 -0
  68. data/html/classes/MIDI/IO/MIDIFile.src/M000046.html +17 -0
  69. data/html/classes/MIDI/IO/MIDIFile.src/M000047.html +17 -0
  70. data/html/classes/MIDI/IO/MIDIFile.src/M000048.html +17 -0
  71. data/html/classes/MIDI/IO/MIDIFile.src/M000049.html +17 -0
  72. data/html/classes/MIDI/IO/MIDIFile.src/M000050.html +17 -0
  73. data/html/classes/MIDI/IO/MIDIFile.src/M000051.html +17 -0
  74. data/html/classes/MIDI/IO/MIDIFile.src/M000052.html +17 -0
  75. data/html/classes/MIDI/IO/MIDIFile.src/M000053.html +43 -0
  76. data/html/classes/MIDI/IO/MIDIFile.src/M000054.html +34 -0
  77. data/html/classes/MIDI/IO/MIDIFile.src/M000055.html +96 -0
  78. data/html/classes/MIDI/IO/MIDIFile.src/M000056.html +18 -0
  79. data/html/classes/MIDI/IO/MIDIFile.src/M000057.html +48 -0
  80. data/html/classes/MIDI/IO/MIDIFile.src/M000058.html +42 -0
  81. data/html/classes/MIDI/IO/MIDIFile.src/M000059.html +19 -0
  82. data/html/classes/MIDI/IO/MIDIFile.src/M000060.html +19 -0
  83. data/html/classes/MIDI/IO/MIDIFile.src/M000061.html +20 -0
  84. data/html/classes/MIDI/IO/MIDIFile.src/M000062.html +21 -0
  85. data/html/classes/MIDI/IO/MIDIFile.src/M000063.html +31 -0
  86. data/html/classes/MIDI/IO/MIDIFile.src/M000064.html +20 -0
  87. data/html/classes/MIDI/IO/MIDIFile.src/M000065.html +22 -0
  88. data/html/classes/MIDI/IO/MIDIFile.src/M000066.html +30 -0
  89. data/html/classes/MIDI/IO/MIDIFile.src/M000067.html +18 -0
  90. data/html/classes/MIDI/IO/MIDIFile.src/M000068.html +20 -0
  91. data/html/classes/MIDI/IO/MIDIFile.src/M000069.html +18 -0
  92. data/html/classes/MIDI/IO/MIDIFile.src/M000070.html +18 -0
  93. data/html/classes/MIDI/IO/SeqReader.html +460 -0
  94. data/html/classes/MIDI/IO/SeqReader.src/M000001.html +22 -0
  95. data/html/classes/MIDI/IO/SeqReader.src/M000002.html +22 -0
  96. data/html/classes/MIDI/IO/SeqReader.src/M000003.html +21 -0
  97. data/html/classes/MIDI/IO/SeqReader.src/M000004.html +34 -0
  98. data/html/classes/MIDI/IO/SeqReader.src/M000005.html +26 -0
  99. data/html/classes/MIDI/IO/SeqReader.src/M000006.html +28 -0
  100. data/html/classes/MIDI/IO/SeqReader.src/M000007.html +21 -0
  101. data/html/classes/MIDI/IO/SeqReader.src/M000008.html +19 -0
  102. data/html/classes/MIDI/IO/SeqReader.src/M000009.html +19 -0
  103. data/html/classes/MIDI/IO/SeqReader.src/M000010.html +19 -0
  104. data/html/classes/MIDI/IO/SeqReader.src/M000011.html +19 -0
  105. data/html/classes/MIDI/IO/SeqReader.src/M000012.html +19 -0
  106. data/html/classes/MIDI/IO/SeqReader.src/M000013.html +18 -0
  107. data/html/classes/MIDI/IO/SeqReader.src/M000014.html +18 -0
  108. data/html/classes/MIDI/IO/SeqReader.src/M000015.html +27 -0
  109. data/html/classes/MIDI/IO/SeqReader.src/M000016.html +18 -0
  110. data/html/classes/MIDI/IO/SeqReader.src/M000017.html +18 -0
  111. data/html/classes/MIDI/IO/SeqReader.src/M000018.html +18 -0
  112. data/html/classes/MIDI/IO/SeqWriter.html +267 -0
  113. data/html/classes/MIDI/IO/SeqWriter.src/M000019.html +19 -0
  114. data/html/classes/MIDI/IO/SeqWriter.src/M000020.html +25 -0
  115. data/html/classes/MIDI/IO/SeqWriter.src/M000021.html +22 -0
  116. data/html/classes/MIDI/IO/SeqWriter.src/M000022.html +54 -0
  117. data/html/classes/MIDI/IO/SeqWriter.src/M000023.html +49 -0
  118. data/html/classes/MIDI/IO/SeqWriter.src/M000024.html +21 -0
  119. data/html/classes/MIDI/IO/SeqWriter.src/M000025.html +19 -0
  120. data/html/classes/MIDI/IO/SeqWriter.src/M000026.html +24 -0
  121. data/html/classes/MIDI/IO/SeqWriter.src/M000027.html +26 -0
  122. data/html/classes/MIDI/Marker.html +139 -0
  123. data/html/classes/MIDI/Marker.src/M000107.html +18 -0
  124. data/html/classes/MIDI/MetaEvent.html +189 -0
  125. data/html/classes/MIDI/MetaEvent.src/M000167.html +21 -0
  126. data/html/classes/MIDI/MetaEvent.src/M000168.html +23 -0
  127. data/html/classes/MIDI/MetaEvent.src/M000169.html +53 -0
  128. data/html/classes/MIDI/NoteEvent.html +233 -0
  129. data/html/classes/MIDI/NoteEvent.src/M000091.html +21 -0
  130. data/html/classes/MIDI/NoteEvent.src/M000092.html +20 -0
  131. data/html/classes/MIDI/NoteEvent.src/M000093.html +18 -0
  132. data/html/classes/MIDI/NoteEvent.src/M000094.html +22 -0
  133. data/html/classes/MIDI/NoteOffEvent.html +169 -0
  134. data/html/classes/MIDI/NoteOffEvent.src/M000086.html +19 -0
  135. data/html/classes/MIDI/NoteOffEvent.src/M000087.html +19 -0
  136. data/html/classes/MIDI/NoteOnEvent.html +169 -0
  137. data/html/classes/MIDI/NoteOnEvent.src/M000102.html +19 -0
  138. data/html/classes/MIDI/NoteOnEvent.src/M000103.html +19 -0
  139. data/html/classes/MIDI/PitchBend.html +184 -0
  140. data/html/classes/MIDI/PitchBend.src/M000104.html +19 -0
  141. data/html/classes/MIDI/PitchBend.src/M000105.html +22 -0
  142. data/html/classes/MIDI/PitchBend.src/M000106.html +18 -0
  143. data/html/classes/MIDI/PolyPressure.html +186 -0
  144. data/html/classes/MIDI/PolyPressure.src/M000170.html +18 -0
  145. data/html/classes/MIDI/PolyPressure.src/M000171.html +18 -0
  146. data/html/classes/MIDI/PolyPressure.src/M000172.html +18 -0
  147. data/html/classes/MIDI/PolyPressure.src/M000173.html +19 -0
  148. data/html/classes/MIDI/ProgramChange.html +184 -0
  149. data/html/classes/MIDI/ProgramChange.src/M000099.html +19 -0
  150. data/html/classes/MIDI/ProgramChange.src/M000100.html +21 -0
  151. data/html/classes/MIDI/ProgramChange.src/M000101.html +18 -0
  152. data/html/classes/MIDI/Realtime.html +171 -0
  153. data/html/classes/MIDI/Realtime.src/M000083.html +19 -0
  154. data/html/classes/MIDI/Realtime.src/M000084.html +20 -0
  155. data/html/classes/MIDI/Realtime.src/M000085.html +18 -0
  156. data/html/classes/MIDI/Sequence.html +469 -0
  157. data/html/classes/MIDI/Sequence.src/M000108.html +28 -0
  158. data/html/classes/MIDI/Sequence.src/M000109.html +21 -0
  159. data/html/classes/MIDI/Sequence.src/M000110.html +22 -0
  160. data/html/classes/MIDI/Sequence.src/M000113.html +18 -0
  161. data/html/classes/MIDI/Sequence.src/M000114.html +27 -0
  162. data/html/classes/MIDI/Sequence.src/M000115.html +18 -0
  163. data/html/classes/MIDI/Sequence.src/M000116.html +19 -0
  164. data/html/classes/MIDI/Sequence.src/M000117.html +19 -0
  165. data/html/classes/MIDI/Sequence.src/M000118.html +20 -0
  166. data/html/classes/MIDI/Sequence.src/M000119.html +19 -0
  167. data/html/classes/MIDI/Sequence.src/M000120.html +18 -0
  168. data/html/classes/MIDI/SongPointer.html +184 -0
  169. data/html/classes/MIDI/SongPointer.src/M000138.html +19 -0
  170. data/html/classes/MIDI/SongPointer.src/M000139.html +22 -0
  171. data/html/classes/MIDI/SongPointer.src/M000140.html +18 -0
  172. data/html/classes/MIDI/SongSelect.html +184 -0
  173. data/html/classes/MIDI/SongSelect.src/M000126.html +19 -0
  174. data/html/classes/MIDI/SongSelect.src/M000127.html +21 -0
  175. data/html/classes/MIDI/SongSelect.src/M000128.html +18 -0
  176. data/html/classes/MIDI/Start.html +156 -0
  177. data/html/classes/MIDI/Start.src/M000097.html +18 -0
  178. data/html/classes/MIDI/Start.src/M000098.html +18 -0
  179. data/html/classes/MIDI/Stop.html +156 -0
  180. data/html/classes/MIDI/Stop.src/M000095.html +18 -0
  181. data/html/classes/MIDI/Stop.src/M000096.html +18 -0
  182. data/html/classes/MIDI/SystemCommon.html +139 -0
  183. data/html/classes/MIDI/SystemCommon.src/M000144.html +19 -0
  184. data/html/classes/MIDI/SystemExclusive.html +184 -0
  185. data/html/classes/MIDI/SystemExclusive.src/M000141.html +19 -0
  186. data/html/classes/MIDI/SystemExclusive.src/M000142.html +23 -0
  187. data/html/classes/MIDI/SystemExclusive.src/M000143.html +18 -0
  188. data/html/classes/MIDI/SystemReset.html +156 -0
  189. data/html/classes/MIDI/SystemReset.src/M000081.html +18 -0
  190. data/html/classes/MIDI/SystemReset.src/M000082.html +18 -0
  191. data/html/classes/MIDI/Tempo.html +250 -0
  192. data/html/classes/MIDI/Tempo.src/M000158.html +18 -0
  193. data/html/classes/MIDI/Tempo.src/M000159.html +18 -0
  194. data/html/classes/MIDI/Tempo.src/M000160.html +18 -0
  195. data/html/classes/MIDI/Tempo.src/M000161.html +18 -0
  196. data/html/classes/MIDI/Tempo.src/M000162.html +18 -0
  197. data/html/classes/MIDI/Tempo.src/M000163.html +25 -0
  198. data/html/classes/MIDI/Tempo.src/M000164.html +18 -0
  199. data/html/classes/MIDI/Track.html +380 -0
  200. data/html/classes/MIDI/Track.src/M000071.html +23 -0
  201. data/html/classes/MIDI/Track.src/M000072.html +21 -0
  202. data/html/classes/MIDI/Track.src/M000073.html +26 -0
  203. data/html/classes/MIDI/Track.src/M000074.html +18 -0
  204. data/html/classes/MIDI/Track.src/M000075.html +22 -0
  205. data/html/classes/MIDI/Track.src/M000076.html +20 -0
  206. data/html/classes/MIDI/Track.src/M000077.html +22 -0
  207. data/html/classes/MIDI/Track.src/M000078.html +22 -0
  208. data/html/classes/MIDI/Track.src/M000079.html +18 -0
  209. data/html/classes/MIDI/Track.src/M000080.html +19 -0
  210. data/html/classes/MIDI/TuneRequest.html +171 -0
  211. data/html/classes/MIDI/TuneRequest.src/M000121.html +18 -0
  212. data/html/classes/MIDI/TuneRequest.src/M000122.html +20 -0
  213. data/html/classes/MIDI/TuneRequest.src/M000123.html +18 -0
  214. data/html/classes/MIDI/Utils.html +190 -0
  215. data/html/classes/MIDI/Utils.src/M000165.html +20 -0
  216. data/html/classes/MIDI/Utils.src/M000166.html +25 -0
  217. data/html/created.rid +1 -0
  218. data/html/files/README.html +599 -0
  219. data/html/files/TODO.html +142 -0
  220. data/html/files/lib/midilib/consts_rb.html +107 -0
  221. data/html/files/lib/midilib/event_rb.html +109 -0
  222. data/html/files/lib/midilib/info_rb.html +101 -0
  223. data/html/files/lib/midilib/io/midifile_rb.html +108 -0
  224. data/html/files/lib/midilib/io/seqreader_rb.html +110 -0
  225. data/html/files/lib/midilib/io/seqwriter_rb.html +115 -0
  226. data/html/files/lib/midilib/sequence_rb.html +109 -0
  227. data/html/files/lib/midilib/track_rb.html +108 -0
  228. data/html/files/lib/midilib/utils_rb.html +101 -0
  229. data/html/files/lib/midilib_rb.html +124 -0
  230. data/html/fr_class_index.html +59 -0
  231. data/html/fr_file_index.html +38 -0
  232. data/html/fr_method_index.html +199 -0
  233. data/html/index.html +24 -0
  234. data/html/rdoc-style.css +208 -0
  235. data/install.rb +57 -0
  236. data/lib/midilib.rb +16 -0
  237. data/lib/midilib/consts.rb +422 -0
  238. data/lib/midilib/event.rb +559 -0
  239. data/lib/midilib/info.rb +9 -0
  240. data/lib/midilib/io/midifile.rb +446 -0
  241. data/lib/midilib/io/seqreader.rb +198 -0
  242. data/lib/midilib/io/seqwriter.rb +151 -0
  243. data/lib/midilib/sequence.rb +144 -0
  244. data/lib/midilib/track.rb +115 -0
  245. data/lib/midilib/utils.rb +36 -0
  246. data/test/event_equality.rb +81 -0
  247. data/test/test_event.rb +116 -0
  248. data/test/test_io.rb +55 -0
  249. data/test/test_sequence.rb +68 -0
  250. data/test/test_track.rb +111 -0
  251. data/test/test_varlen.rb +40 -0
  252. metadata +330 -0
@@ -0,0 +1,115 @@
1
+ require 'midilib/event'
2
+
3
+ module MIDI
4
+
5
+ # A Track is a list of events.
6
+ #
7
+ # When you modify the +events+ array, make sure to call recalc_times so
8
+ # each Event gets its +time_from_start+ recalculated.
9
+ #
10
+ # A Track also holds a bitmask that specifies the channels used by the track.
11
+ # This bitmask is set when the track is read from the MIDI file by an
12
+ # IO::SeqReader but is _not_ kept up to date by any other methods.
13
+
14
+ class Track
15
+
16
+ include Enumerable
17
+
18
+ UNNAMED = 'Unnamed'
19
+
20
+ attr_accessor :instrument, :events, :channels_used
21
+ attr_reader :sequence
22
+
23
+ def initialize(sequence)
24
+ @sequence = sequence
25
+ @events = Array.new()
26
+
27
+ # Bitmask of all channels used. Set when track is read in from
28
+ # a MIDI file.
29
+ @channels_used = 0
30
+ end
31
+
32
+ # Return track name. If there is no name, return UNNAMED.
33
+ def name
34
+ event = @events.detect { | e |
35
+ e.meta? && e.meta_type == META_SEQ_NAME
36
+ }
37
+ return event ? event.data : UNNAMED
38
+ end
39
+
40
+ # Set track name. Replaces or creates a name meta-event.
41
+ def name=(name)
42
+ event = @events.detect { | e |
43
+ e.meta? && e.meta_type == META_SEQ_NAME
44
+ }
45
+ if event
46
+ event.data = name
47
+ else
48
+ event = MetaEvent.new(META_SEQ_NAME, name, 0)
49
+ @events[0, 0] = event
50
+ end
51
+ end
52
+
53
+ # Merges an array of events into our event list. After merging, the
54
+ # events' time_from_start values are correct so you don't need to worry
55
+ # about calling recalc_times.
56
+ def merge(event_list)
57
+ @events = merge_event_lists(@events, event_list)
58
+ end
59
+
60
+ # Merges two event arrays together. Does not modify this track.
61
+ def merge_event_lists(list1, list2)
62
+ recalc_times(0, list1)
63
+ recalc_times(0, list2)
64
+ list = (list1 + list2).sort_by { | e | e.time_from_start }
65
+ recalc_delta_from_times(0, list)
66
+ return list
67
+ end
68
+
69
+ # Quantize every event. +denom+ is the beat denominator. To quantize to
70
+ # sixteenths pass in a +denom+ of 16.
71
+ #
72
+ # Since each event's time_from_start is modified, we call
73
+ # recalc_delta_from_times after each event quantizes itself.
74
+ def quantize(denom)
75
+ boundary = @sequence.ppqn / denom
76
+ @events.each { | event | event.quantize_to(boundary) }
77
+ recalc_delta_from_times
78
+ end
79
+
80
+ # Recalculate start times for all events in +list+ from starting_at to
81
+ # end.
82
+ def recalc_times(starting_at=0, list=@events)
83
+ t = (starting_at == 0) ? 0 : list[starting_at - 1].time_from_start
84
+ list[starting_at .. -1].each { | e |
85
+ t += e.delta_time
86
+ e.time_from_start = t
87
+ }
88
+ end
89
+
90
+ # The opposite of recalc_times: recalculates delta_time for each event
91
+ # from each event's time_from_start. This is useful, for example, when
92
+ # merging two event lists.
93
+ def recalc_delta_from_times(starting_at=0, list=@events)
94
+ prev_time_from_start = 0
95
+ list[starting_at .. -1].each { | e |
96
+ e.delta_time = e.time_from_start - prev_time_from_start
97
+ prev_time_from_start = e.time_from_start
98
+ }
99
+ end
100
+
101
+ # Iterate over events.
102
+ def each # :yields: event
103
+ @events.each { | event | yield event }
104
+ end
105
+
106
+ # Sort events by their time_from_start. After sorting,
107
+ # recalc_delta_from_times is called to make sure that the delta times
108
+ # reflect the possibly new event order.
109
+ def sort
110
+ @events = @events.sort_by { | e | e.time_from_start }
111
+ recalc_delta_from_times()
112
+ end
113
+ end
114
+
115
+ end
@@ -0,0 +1,36 @@
1
+ module MIDI
2
+
3
+ # Utility methods.
4
+ class Utils
5
+
6
+ # MIDI note names. NOTE_NAMES[0] is 'C', NOTE_NAMES[1] is 'C#', etc.
7
+ NOTE_NAMES = [
8
+ 'C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B'
9
+ ]
10
+
11
+ # Given a MIDI note number, return the name and octave as a string.
12
+ def Utils.note_to_s(num)
13
+ note = num % 12
14
+ octave = num / 12
15
+ return "#{NOTE_NAMES[note]}#{octave - 1}"
16
+ end
17
+
18
+ # Given an integer, returns it as a variable length array of bytes (the
19
+ # format used by MIDI files).
20
+ #
21
+ # The converse operation--converting a var len into a number--requires
22
+ # input from a stream of bytes. Therefore we don't supply it here. That is
23
+ # a part of the MIDIFile class.
24
+ def Utils.as_var_len(val)
25
+ buffer = ''
26
+ buffer << (val & 0x7f)
27
+ val = (val >> 7)
28
+ while val > 0
29
+ buffer << (0x80 + (val & 0x7f))
30
+ val = (val >> 7)
31
+ end
32
+ return buffer.reverse!
33
+ end
34
+
35
+ end
36
+ end
@@ -0,0 +1,81 @@
1
+ # This code defines equality operators for all of the event classes. It's
2
+ # used by SeqTester.
3
+ #
4
+ # I don't think it is necessary to include these methods in the base Event
5
+ # classes. If someone disagrees, it would be trivial to move them there.
6
+
7
+ module MIDI
8
+
9
+ class Event
10
+ def ==(an_obj)
11
+ return an_obj.instance_of?(self.class) &&
12
+ @status == an_obj.status &&
13
+ @delta_time == an_obj.delta_time &&
14
+ @time_from_start == an_obj.time_from_start
15
+ end
16
+ end
17
+
18
+ class ChannelEvent
19
+ def ==(an_obj)
20
+ return super(an_obj) && @channel == an_obj.channel
21
+ end
22
+ end
23
+
24
+ class NoteEvent < ChannelEvent
25
+ def ==(an_obj)
26
+ return super(an_obj) &&
27
+ @note == an_obj.note && @velocity == an_obj.velocity
28
+ end
29
+ end
30
+
31
+ class Controller < ChannelEvent
32
+ def ==(an_obj)
33
+ return super(an_obj) &&
34
+ @controller == an_obj.controller && @value == an_obj.value
35
+ end
36
+ end
37
+
38
+ class ProgramChange < ChannelEvent
39
+ def ==(an_obj)
40
+ return super(an_obj) && @program == an_obj.program
41
+ end
42
+ end
43
+
44
+ class ChannelPressure < ChannelEvent
45
+ def ==(an_obj)
46
+ return super(an_obj) && @pressure == an_obj.pressure
47
+ end
48
+ end
49
+
50
+ class PitchBend < ChannelEvent
51
+ def ==(an_obj)
52
+ return super(an_obj) && @value == an_obj.value
53
+ end
54
+ end
55
+
56
+ class SystemExclusive < SystemCommon
57
+ def ==(an_obj)
58
+ return super(an_obj) && @data == an_obj.data
59
+ end
60
+ end
61
+
62
+ class SongPointer < SystemCommon
63
+ def ==(an_obj)
64
+ return super(an_obj) && @pointer == an_obj.pointer
65
+ end
66
+ end
67
+
68
+ class SongSelect < SystemCommon
69
+ def ==(an_obj)
70
+ return super(an_obj) && @song == an_obj.song
71
+ end
72
+ end
73
+
74
+ class MetaEvent < Event
75
+ def ==(an_obj)
76
+ return super(an_obj) && @meta_type == an_obj.meta_type &&
77
+ @data == an_obj.data
78
+ end
79
+ end
80
+
81
+ end
@@ -0,0 +1,116 @@
1
+ # Start looking for MIDI classes in the directory above this one.
2
+ # This forces us to use the local copy of MIDI, even if there is
3
+ # a previously installed version out there somewhere.
4
+ $LOAD_PATH[0, 0] = File.join(File.dirname(__FILE__), '..', 'lib')
5
+
6
+ require 'test/unit'
7
+ require 'midilib'
8
+
9
+ class EventTester < Test::Unit::TestCase
10
+
11
+ def test_note_on
12
+ e = MIDI::NoteOnEvent.new
13
+ assert_equal(MIDI::NOTE_ON, e.status)
14
+ assert_equal(0, e.channel)
15
+ assert_equal(64, e.note)
16
+ assert_equal(64, e.velocity)
17
+ assert_equal(0, e.delta_time)
18
+ assert_equal(0, e.time_from_start)
19
+ end
20
+
21
+ def test_quantize
22
+ e = MIDI::NoteOnEvent.new
23
+ e.quantize_to(4)
24
+ assert_equal(0, e.time_from_start)
25
+
26
+ # Each value in this array is the expected quantized value of
27
+ # its index in the array.
28
+
29
+ # Test with quantize_to(4)
30
+ [0, 0, 4, 4, 4, 4, 8, 8, 8, 8, 12, 12, 12, 12, 16].each_with_index {
31
+ | after, before |
32
+ e.time_from_start = before
33
+ e.quantize_to(4)
34
+ assert_equal(after, e.time_from_start)
35
+ }
36
+
37
+ # Test with quantize_to(6)
38
+ [0, 0, 0, 6, 6, 6, 6, 6, 6, 12, 12, 12, 12, 12, 12,
39
+ 18, 18, 18, 18, 18, 18, 24].each_with_index {
40
+ | after, before |
41
+ e.time_from_start = before
42
+ e.quantize_to(6)
43
+ assert_equal(after, e.time_from_start)
44
+ }
45
+ end
46
+
47
+ def test_to_s
48
+ e = MIDI::NoteOnEvent.new
49
+ assert_equal("0: ch 00 on 40 40", e.to_s)
50
+ e.print_decimal_numbers = true
51
+ assert_equal("0: ch 0 on 64 64", e.to_s)
52
+ e.print_note_names = true
53
+ assert_equal("0: ch 0 on E4 64", e.to_s)
54
+ e.print_decimal_numbers = false
55
+ assert_equal("0: ch 00 on E4 40", e.to_s)
56
+ end
57
+
58
+ def test_bools_note_on
59
+ e = MIDI::NoteOnEvent.new
60
+ assert(e.channel?)
61
+ assert(e.note?)
62
+ assert(e.note_on?)
63
+ assert(!e.note_off?)
64
+ assert(!e.meta?)
65
+ assert(!e.system?)
66
+ assert(!e.realtime?)
67
+ end
68
+
69
+ def test_bools_note_off
70
+ e = MIDI::NoteOffEvent.new
71
+ assert(e.channel?)
72
+ assert(e.note?)
73
+ assert(!e.note_on?)
74
+ assert(e.note_off?)
75
+ assert(!e.meta?)
76
+ assert(!e.system?)
77
+ assert(!e.realtime?)
78
+ end
79
+
80
+ def test_bools_realtime
81
+ e = MIDI::Clock.new
82
+ assert(!e.channel?)
83
+ assert(!e.note?)
84
+ assert(!e.meta?)
85
+ assert(!e.system?)
86
+ assert(e.realtime?)
87
+ end
88
+
89
+ def test_bools_controller
90
+ e = MIDI::Controller.new
91
+ assert(e.channel?)
92
+ assert(!e.note?)
93
+ assert(!e.meta?)
94
+ assert(!e.system?)
95
+ assert(!e.realtime?)
96
+ end
97
+
98
+ def test_bools_meta
99
+ e = MIDI::MetaEvent.new(MIDI::META_SEQ_NUM)
100
+ assert(!e.channel?)
101
+ assert(!e.note?)
102
+ assert(e.meta?)
103
+ assert(!e.system?)
104
+ assert(!e.realtime?)
105
+ end
106
+
107
+ def test_bools_system
108
+ e = MIDI::TuneRequest.new
109
+ assert(!e.channel?)
110
+ assert(!e.note?)
111
+ assert(!e.meta?)
112
+ assert(e.system?)
113
+ assert(!e.realtime?)
114
+ end
115
+
116
+ end
data/test/test_io.rb ADDED
@@ -0,0 +1,55 @@
1
+ # Start looking for MIDI classes in the directory above this one.
2
+ # This forces us to use the local copy of MIDI, even if there is
3
+ # a previously installed version out there somewhere.
4
+ $LOAD_PATH[0, 0] = File.join(File.dirname(__FILE__), '..', 'lib')
5
+ # Add current directory so we can find event_equality
6
+ $LOAD_PATH[0, 0] = File.dirname(__FILE__)
7
+
8
+ require 'test/unit'
9
+ require 'midilib'
10
+ require 'event_equality'
11
+
12
+ class IOTester < Test::Unit::TestCase
13
+
14
+ SEQ_TEST_FILE = File.join(File.dirname(__FILE__), 'test.mid')
15
+ OUTPUT_FILE = 'testout.mid'
16
+
17
+ def compare_tracks(t0, t1)
18
+ assert_equal(t0.name, t1.name, 'track names differ')
19
+ assert_equal(t0.events.length, t1.events.length,
20
+ 'number of track events differ')
21
+ t0.each_with_index { | ev0, i |
22
+ assert_equal(ev0, t1.events[i], 'events differ')
23
+ }
24
+ assert_equal(t0.instrument, t1.instrument)
25
+ end
26
+
27
+ def compare_sequences(s0, s1)
28
+ assert_equal(s0.name, s1.name, 'sequence names differ')
29
+ assert_equal(s0.tracks.length, s1.tracks.length,
30
+ 'number of tracks differ')
31
+ s0.each_with_index { | track0, i |
32
+ compare_tracks(track0, s1.tracks[i])
33
+ }
34
+ end
35
+
36
+ def test_read_and_write
37
+ seq0 = MIDI::Sequence.new()
38
+
39
+ puts if $DEBUG
40
+ puts ' reading file' if $DEBUG
41
+ File.open(SEQ_TEST_FILE, 'rb') { | f | seq0.read(f) }
42
+
43
+ puts ' writing file' if $DEBUG
44
+ File.open(OUTPUT_FILE, 'wb') { | f | seq0.write(f) }
45
+
46
+ puts ' reading file' if $DEBUG
47
+ seq1 = MIDI::Sequence.new()
48
+ File.open(OUTPUT_FILE, 'rb') { | f | seq1.read(f) }
49
+
50
+ puts ' comparing sequences' if $DEBUG
51
+ compare_sequences(seq0, seq1)
52
+ File.delete(OUTPUT_FILE)
53
+ end
54
+
55
+ end
@@ -0,0 +1,68 @@
1
+ # Start looking for MIDI classes in the directory above this one.
2
+ # This forces us to use the local copy of MIDI, even if there is
3
+ # a previously installed version out there somewhere.
4
+ $LOAD_PATH[0, 0] = File.join(File.dirname(__FILE__), '..', 'lib')
5
+
6
+ require 'test/unit'
7
+ require 'midilib'
8
+
9
+ class SequenceTester < Test::Unit::TestCase
10
+
11
+ def setup
12
+ @seq = MIDI::Sequence.new
13
+ @track = MIDI::Track.new(@seq)
14
+ @seq.tracks << @track
15
+ 3.times { @track.events << MIDI::NoteOnEvent.new(0, 64, 64, 100) }
16
+ @track.recalc_times
17
+ end
18
+
19
+ def test_basics
20
+ assert_equal(120, @seq.beats_per_minute)
21
+ assert_equal(1, @seq.tracks.length)
22
+ assert_equal(MIDI::Track::UNNAMED, @seq.name)
23
+ assert_equal(MIDI::Sequence::DEFAULT_TEMPO, @seq.bpm)
24
+ end
25
+
26
+ def test_length_to_delta
27
+ assert_equal(480, @seq.ppqn)
28
+ assert_equal(480, @seq.length_to_delta(1))
29
+ assert_equal(240, @seq.length_to_delta(0.5))
30
+
31
+ @seq.ppqn = 12
32
+ assert_equal(12, @seq.ppqn)
33
+ assert_equal(12, @seq.length_to_delta(1))
34
+ assert_equal(6, @seq.length_to_delta(0.5))
35
+ assert_equal(5, @seq.length_to_delta(0.49))
36
+ end
37
+
38
+ def test_note_to_length
39
+ assert_equal(1, @seq.note_to_length('quarter'))
40
+ assert_equal(4, @seq.note_to_length('whole'))
41
+ assert_equal(1.5, @seq.note_to_length('dotted quarter'))
42
+ assert_equal(1.0 / 3.0, @seq.note_to_length('quarter triplet'))
43
+ assert_equal(0.5, @seq.note_to_length('dotted quarter triplet'))
44
+ assert_equal(1.0 / 4, @seq.note_to_length('sixteenth'))
45
+ assert_equal(1.0 / 4, @seq.note_to_length('16th'))
46
+ assert_equal(1.0 / 8, @seq.note_to_length('thirty second'))
47
+ assert_equal(1.0 / 8, @seq.note_to_length('32nd'))
48
+ assert_equal(1.0 / 16, @seq.note_to_length('sixty fourth'))
49
+ assert_equal(1.0 / 16, @seq.note_to_length('sixtyfourth'))
50
+ assert_equal(1.0 / 16, @seq.note_to_length('64th'))
51
+ end
52
+
53
+ def test_note_to_delta
54
+ assert_equal(480, @seq.note_to_delta('quarter'))
55
+ assert_equal(480 * 4, @seq.note_to_delta('whole'))
56
+ assert_equal(720, @seq.note_to_delta('dotted quarter'))
57
+ assert_equal(480 / 3.0, @seq.note_to_delta('quarter triplet'))
58
+ assert_equal((480 / 3.0) * 1.5,
59
+ @seq.note_to_delta('dotted quarter triplet'))
60
+ assert_equal(480 / 4, @seq.note_to_delta('sixteenth'))
61
+ assert_equal(480 / 4, @seq.note_to_delta('16th'))
62
+ assert_equal(480 / 8, @seq.note_to_delta('thirty second'))
63
+ assert_equal(480 / 8, @seq.note_to_delta('32nd'))
64
+ assert_equal(480 / 16, @seq.note_to_delta('sixty fourth'))
65
+ assert_equal(480 / 16, @seq.note_to_delta('sixtyfourth'))
66
+ assert_equal(480 / 16, @seq.note_to_delta('64th'))
67
+ end
68
+ end