midilib 1.0.0 → 1.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (273) hide show
  1. data/ChangeLog +23 -0
  2. data/Credits +6 -0
  3. data/README +33 -1
  4. data/Rakefile +1 -1
  5. data/examples/from_scratch.rb +0 -0
  6. data/examples/measures_mbt.rb +30 -0
  7. data/examples/print_program_changes.rb +28 -0
  8. data/examples/reader2text.rb +0 -0
  9. data/examples/seq2text.rb +0 -0
  10. data/examples/split.rb +0 -0
  11. data/examples/strings.rb +0 -0
  12. data/examples/transpose.rb +0 -0
  13. data/html/classes/MIDI/ActiveSense.html +156 -0
  14. data/html/classes/MIDI/ActiveSense.src/M000157.html +18 -0
  15. data/html/classes/MIDI/ActiveSense.src/M000158.html +18 -0
  16. data/html/classes/MIDI/ChannelEvent.html +179 -0
  17. data/html/classes/MIDI/ChannelEvent.src/M000129.html +20 -0
  18. data/html/classes/MIDI/ChannelEvent.src/M000130.html +18 -0
  19. data/html/classes/MIDI/ChannelPressure.html +184 -0
  20. data/html/classes/MIDI/ChannelPressure.src/M000089.html +19 -0
  21. data/html/classes/MIDI/ChannelPressure.src/M000090.html +21 -0
  22. data/html/classes/MIDI/ChannelPressure.src/M000091.html +18 -0
  23. data/html/classes/MIDI/Clock.html +156 -0
  24. data/html/classes/MIDI/Clock.src/M000145.html +18 -0
  25. data/html/classes/MIDI/Clock.src/M000146.html +18 -0
  26. data/html/classes/MIDI/Continue.html +156 -0
  27. data/html/classes/MIDI/Continue.src/M000143.html +18 -0
  28. data/html/classes/MIDI/Continue.src/M000144.html +18 -0
  29. data/html/classes/MIDI/Controller.html +189 -0
  30. data/html/classes/MIDI/Controller.src/M000134.html +21 -0
  31. data/html/classes/MIDI/Controller.src/M000135.html +22 -0
  32. data/html/classes/MIDI/Controller.src/M000136.html +18 -0
  33. data/html/classes/MIDI/Event.html +507 -0
  34. data/html/classes/MIDI/Event.src/M000166.html +30 -0
  35. data/html/classes/MIDI/Event.src/M000167.html +18 -0
  36. data/html/classes/MIDI/Event.src/M000168.html +18 -0
  37. data/html/classes/MIDI/Event.src/M000169.html +18 -0
  38. data/html/classes/MIDI/Event.src/M000170.html +18 -0
  39. data/html/classes/MIDI/Event.src/M000171.html +18 -0
  40. data/html/classes/MIDI/Event.src/M000172.html +18 -0
  41. data/html/classes/MIDI/Event.src/M000173.html +18 -0
  42. data/html/classes/MIDI/Event.src/M000174.html +18 -0
  43. data/html/classes/MIDI/Event.src/M000175.html +18 -0
  44. data/html/classes/MIDI/Event.src/M000176.html +18 -0
  45. data/html/classes/MIDI/Event.src/M000177.html +18 -0
  46. data/html/classes/MIDI/Event.src/M000178.html +22 -0
  47. data/html/classes/MIDI/Event.src/M000179.html +18 -0
  48. data/html/classes/MIDI/Event.src/M000180.html +18 -0
  49. data/html/classes/MIDI/Event.src/M000181.html +19 -0
  50. data/html/classes/MIDI/Event.src/M000182.html +18 -0
  51. data/html/classes/MIDI/IO/MIDIFile.html +931 -0
  52. data/html/classes/MIDI/IO/MIDIFile.src/M000029.html +22 -0
  53. data/html/classes/MIDI/IO/MIDIFile.src/M000030.html +24 -0
  54. data/html/classes/MIDI/IO/MIDIFile.src/M000031.html +20 -0
  55. data/html/classes/MIDI/IO/MIDIFile.src/M000032.html +19 -0
  56. data/html/classes/MIDI/IO/MIDIFile.src/M000033.html +17 -0
  57. data/html/classes/MIDI/IO/MIDIFile.src/M000034.html +17 -0
  58. data/html/classes/MIDI/IO/MIDIFile.src/M000035.html +17 -0
  59. data/html/classes/MIDI/IO/MIDIFile.src/M000036.html +17 -0
  60. data/html/classes/MIDI/IO/MIDIFile.src/M000037.html +17 -0
  61. data/html/classes/MIDI/IO/MIDIFile.src/M000038.html +17 -0
  62. data/html/classes/MIDI/IO/MIDIFile.src/M000039.html +17 -0
  63. data/html/classes/MIDI/IO/MIDIFile.src/M000040.html +17 -0
  64. data/html/classes/MIDI/IO/MIDIFile.src/M000041.html +17 -0
  65. data/html/classes/MIDI/IO/MIDIFile.src/M000042.html +17 -0
  66. data/html/classes/MIDI/IO/MIDIFile.src/M000043.html +17 -0
  67. data/html/classes/MIDI/IO/MIDIFile.src/M000044.html +17 -0
  68. data/html/classes/MIDI/IO/MIDIFile.src/M000045.html +17 -0
  69. data/html/classes/MIDI/IO/MIDIFile.src/M000046.html +17 -0
  70. data/html/classes/MIDI/IO/MIDIFile.src/M000047.html +17 -0
  71. data/html/classes/MIDI/IO/MIDIFile.src/M000048.html +17 -0
  72. data/html/classes/MIDI/IO/MIDIFile.src/M000049.html +17 -0
  73. data/html/classes/MIDI/IO/MIDIFile.src/M000050.html +17 -0
  74. data/html/classes/MIDI/IO/MIDIFile.src/M000051.html +17 -0
  75. data/html/classes/MIDI/IO/MIDIFile.src/M000052.html +17 -0
  76. data/html/classes/MIDI/IO/MIDIFile.src/M000053.html +17 -0
  77. data/html/classes/MIDI/IO/MIDIFile.src/M000054.html +43 -0
  78. data/html/classes/MIDI/IO/MIDIFile.src/M000055.html +34 -0
  79. data/html/classes/MIDI/IO/MIDIFile.src/M000056.html +96 -0
  80. data/html/classes/MIDI/IO/MIDIFile.src/M000057.html +18 -0
  81. data/html/classes/MIDI/IO/MIDIFile.src/M000058.html +48 -0
  82. data/html/classes/MIDI/IO/MIDIFile.src/M000059.html +42 -0
  83. data/html/classes/MIDI/IO/MIDIFile.src/M000060.html +19 -0
  84. data/html/classes/MIDI/IO/MIDIFile.src/M000061.html +19 -0
  85. data/html/classes/MIDI/IO/MIDIFile.src/M000062.html +20 -0
  86. data/html/classes/MIDI/IO/MIDIFile.src/M000063.html +21 -0
  87. data/html/classes/MIDI/IO/MIDIFile.src/M000064.html +31 -0
  88. data/html/classes/MIDI/IO/MIDIFile.src/M000065.html +20 -0
  89. data/html/classes/MIDI/IO/MIDIFile.src/M000066.html +22 -0
  90. data/html/classes/MIDI/IO/MIDIFile.src/M000067.html +30 -0
  91. data/html/classes/MIDI/IO/MIDIFile.src/M000068.html +18 -0
  92. data/html/classes/MIDI/IO/MIDIFile.src/M000069.html +20 -0
  93. data/html/classes/MIDI/IO/MIDIFile.src/M000070.html +18 -0
  94. data/html/classes/MIDI/IO/MIDIFile.src/M000071.html +18 -0
  95. data/html/classes/MIDI/IO/SeqReader.html +476 -0
  96. data/html/classes/MIDI/IO/SeqReader.src/M000001.html +22 -0
  97. data/html/classes/MIDI/IO/SeqReader.src/M000002.html +22 -0
  98. data/html/classes/MIDI/IO/SeqReader.src/M000003.html +21 -0
  99. data/html/classes/MIDI/IO/SeqReader.src/M000004.html +34 -0
  100. data/html/classes/MIDI/IO/SeqReader.src/M000005.html +26 -0
  101. data/html/classes/MIDI/IO/SeqReader.src/M000006.html +28 -0
  102. data/html/classes/MIDI/IO/SeqReader.src/M000007.html +21 -0
  103. data/html/classes/MIDI/IO/SeqReader.src/M000008.html +19 -0
  104. data/html/classes/MIDI/IO/SeqReader.src/M000009.html +19 -0
  105. data/html/classes/MIDI/IO/SeqReader.src/M000010.html +19 -0
  106. data/html/classes/MIDI/IO/SeqReader.src/M000011.html +19 -0
  107. data/html/classes/MIDI/IO/SeqReader.src/M000012.html +19 -0
  108. data/html/classes/MIDI/IO/SeqReader.src/M000013.html +18 -0
  109. data/html/classes/MIDI/IO/SeqReader.src/M000014.html +18 -0
  110. data/html/classes/MIDI/IO/SeqReader.src/M000015.html +29 -0
  111. data/html/classes/MIDI/IO/SeqReader.src/M000016.html +19 -0
  112. data/html/classes/MIDI/IO/SeqReader.src/M000017.html +18 -0
  113. data/html/classes/MIDI/IO/SeqReader.src/M000018.html +18 -0
  114. data/html/classes/MIDI/IO/SeqReader.src/M000019.html +18 -0
  115. data/html/classes/MIDI/IO/SeqWriter.html +267 -0
  116. data/html/classes/MIDI/IO/SeqWriter.src/M000020.html +19 -0
  117. data/html/classes/MIDI/IO/SeqWriter.src/M000021.html +25 -0
  118. data/html/classes/MIDI/IO/SeqWriter.src/M000022.html +22 -0
  119. data/html/classes/MIDI/IO/SeqWriter.src/M000023.html +54 -0
  120. data/html/classes/MIDI/IO/SeqWriter.src/M000024.html +49 -0
  121. data/html/classes/MIDI/IO/SeqWriter.src/M000025.html +21 -0
  122. data/html/classes/MIDI/IO/SeqWriter.src/M000026.html +19 -0
  123. data/html/classes/MIDI/IO/SeqWriter.src/M000027.html +24 -0
  124. data/html/classes/MIDI/IO/SeqWriter.src/M000028.html +26 -0
  125. data/html/classes/MIDI/IO.html +121 -0
  126. data/html/classes/MIDI/KeySig.html +241 -0
  127. data/html/classes/MIDI/KeySig.src/M000137.html +19 -0
  128. data/html/classes/MIDI/KeySig.src/M000138.html +23 -0
  129. data/html/classes/MIDI/KeySig.src/M000139.html +18 -0
  130. data/html/classes/MIDI/KeySig.src/M000140.html +18 -0
  131. data/html/classes/MIDI/KeySig.src/M000141.html +18 -0
  132. data/html/classes/MIDI/KeySig.src/M000142.html +23 -0
  133. data/html/classes/MIDI/Marker.html +139 -0
  134. data/html/classes/MIDI/Marker.src/M000111.html +18 -0
  135. data/html/classes/MIDI/Measure.html +242 -0
  136. data/html/classes/MIDI/Measure.src/M000147.html +23 -0
  137. data/html/classes/MIDI/Measure.src/M000148.html +20 -0
  138. data/html/classes/MIDI/Measure.src/M000149.html +18 -0
  139. data/html/classes/MIDI/Measures.html +217 -0
  140. data/html/classes/MIDI/Measures.src/M000105.html +20 -0
  141. data/html/classes/MIDI/Measures.src/M000106.html +18 -0
  142. data/html/classes/MIDI/Measures.src/M000107.html +21 -0
  143. data/html/classes/MIDI/MetaEvent.html +189 -0
  144. data/html/classes/MIDI/MetaEvent.src/M000192.html +21 -0
  145. data/html/classes/MIDI/MetaEvent.src/M000193.html +23 -0
  146. data/html/classes/MIDI/MetaEvent.src/M000194.html +53 -0
  147. data/html/classes/MIDI/NoteEvent.html +233 -0
  148. data/html/classes/MIDI/NoteEvent.src/M000092.html +21 -0
  149. data/html/classes/MIDI/NoteEvent.src/M000093.html +20 -0
  150. data/html/classes/MIDI/NoteEvent.src/M000094.html +18 -0
  151. data/html/classes/MIDI/NoteEvent.src/M000095.html +22 -0
  152. data/html/classes/MIDI/NoteOffEvent.html +169 -0
  153. data/html/classes/MIDI/NoteOffEvent.src/M000087.html +19 -0
  154. data/html/classes/MIDI/NoteOffEvent.src/M000088.html +19 -0
  155. data/html/classes/MIDI/NoteOnEvent.html +169 -0
  156. data/html/classes/MIDI/NoteOnEvent.src/M000103.html +19 -0
  157. data/html/classes/MIDI/NoteOnEvent.src/M000104.html +19 -0
  158. data/html/classes/MIDI/PitchBend.html +184 -0
  159. data/html/classes/MIDI/PitchBend.src/M000108.html +19 -0
  160. data/html/classes/MIDI/PitchBend.src/M000109.html +22 -0
  161. data/html/classes/MIDI/PitchBend.src/M000110.html +18 -0
  162. data/html/classes/MIDI/PolyPressure.html +186 -0
  163. data/html/classes/MIDI/PolyPressure.src/M000195.html +18 -0
  164. data/html/classes/MIDI/PolyPressure.src/M000196.html +18 -0
  165. data/html/classes/MIDI/PolyPressure.src/M000197.html +18 -0
  166. data/html/classes/MIDI/PolyPressure.src/M000198.html +19 -0
  167. data/html/classes/MIDI/ProgramChange.html +184 -0
  168. data/html/classes/MIDI/ProgramChange.src/M000100.html +20 -0
  169. data/html/classes/MIDI/ProgramChange.src/M000101.html +21 -0
  170. data/html/classes/MIDI/ProgramChange.src/M000102.html +18 -0
  171. data/html/classes/MIDI/Realtime.html +171 -0
  172. data/html/classes/MIDI/Realtime.src/M000084.html +19 -0
  173. data/html/classes/MIDI/Realtime.src/M000085.html +20 -0
  174. data/html/classes/MIDI/Realtime.src/M000086.html +18 -0
  175. data/html/classes/MIDI/Sequence.html +500 -0
  176. data/html/classes/MIDI/Sequence.src/M000112.html +28 -0
  177. data/html/classes/MIDI/Sequence.src/M000113.html +21 -0
  178. data/html/classes/MIDI/Sequence.src/M000114.html +22 -0
  179. data/html/classes/MIDI/Sequence.src/M000117.html +18 -0
  180. data/html/classes/MIDI/Sequence.src/M000118.html +27 -0
  181. data/html/classes/MIDI/Sequence.src/M000119.html +18 -0
  182. data/html/classes/MIDI/Sequence.src/M000120.html +19 -0
  183. data/html/classes/MIDI/Sequence.src/M000121.html +19 -0
  184. data/html/classes/MIDI/Sequence.src/M000122.html +19 -0
  185. data/html/classes/MIDI/Sequence.src/M000123.html +19 -0
  186. data/html/classes/MIDI/Sequence.src/M000124.html +18 -0
  187. data/html/classes/MIDI/Sequence.src/M000125.html +54 -0
  188. data/html/classes/MIDI/SongPointer.html +184 -0
  189. data/html/classes/MIDI/SongPointer.src/M000159.html +19 -0
  190. data/html/classes/MIDI/SongPointer.src/M000160.html +22 -0
  191. data/html/classes/MIDI/SongPointer.src/M000161.html +18 -0
  192. data/html/classes/MIDI/SongSelect.html +184 -0
  193. data/html/classes/MIDI/SongSelect.src/M000131.html +19 -0
  194. data/html/classes/MIDI/SongSelect.src/M000132.html +21 -0
  195. data/html/classes/MIDI/SongSelect.src/M000133.html +18 -0
  196. data/html/classes/MIDI/Start.html +156 -0
  197. data/html/classes/MIDI/Start.src/M000098.html +18 -0
  198. data/html/classes/MIDI/Start.src/M000099.html +18 -0
  199. data/html/classes/MIDI/Stop.html +156 -0
  200. data/html/classes/MIDI/Stop.src/M000096.html +18 -0
  201. data/html/classes/MIDI/Stop.src/M000097.html +18 -0
  202. data/html/classes/MIDI/SystemCommon.html +139 -0
  203. data/html/classes/MIDI/SystemCommon.src/M000165.html +19 -0
  204. data/html/classes/MIDI/SystemExclusive.html +184 -0
  205. data/html/classes/MIDI/SystemExclusive.src/M000162.html +19 -0
  206. data/html/classes/MIDI/SystemExclusive.src/M000163.html +23 -0
  207. data/html/classes/MIDI/SystemExclusive.src/M000164.html +18 -0
  208. data/html/classes/MIDI/SystemReset.html +156 -0
  209. data/html/classes/MIDI/SystemReset.src/M000082.html +18 -0
  210. data/html/classes/MIDI/SystemReset.src/M000083.html +18 -0
  211. data/html/classes/MIDI/Tempo.html +250 -0
  212. data/html/classes/MIDI/Tempo.src/M000183.html +18 -0
  213. data/html/classes/MIDI/Tempo.src/M000184.html +20 -0
  214. data/html/classes/MIDI/Tempo.src/M000185.html +18 -0
  215. data/html/classes/MIDI/Tempo.src/M000186.html +18 -0
  216. data/html/classes/MIDI/Tempo.src/M000187.html +18 -0
  217. data/html/classes/MIDI/Tempo.src/M000188.html +25 -0
  218. data/html/classes/MIDI/Tempo.src/M000189.html +18 -0
  219. data/html/classes/MIDI/TimeSig.html +263 -0
  220. data/html/classes/MIDI/TimeSig.src/M000150.html +19 -0
  221. data/html/classes/MIDI/TimeSig.src/M000151.html +25 -0
  222. data/html/classes/MIDI/TimeSig.src/M000152.html +18 -0
  223. data/html/classes/MIDI/TimeSig.src/M000153.html +18 -0
  224. data/html/classes/MIDI/TimeSig.src/M000154.html +18 -0
  225. data/html/classes/MIDI/TimeSig.src/M000155.html +18 -0
  226. data/html/classes/MIDI/TimeSig.src/M000156.html +18 -0
  227. data/html/classes/MIDI/Track.html +389 -0
  228. data/html/classes/MIDI/Track.src/M000072.html +23 -0
  229. data/html/classes/MIDI/Track.src/M000073.html +21 -0
  230. data/html/classes/MIDI/Track.src/M000074.html +26 -0
  231. data/html/classes/MIDI/Track.src/M000075.html +18 -0
  232. data/html/classes/MIDI/Track.src/M000076.html +22 -0
  233. data/html/classes/MIDI/Track.src/M000077.html +25 -0
  234. data/html/classes/MIDI/Track.src/M000078.html +22 -0
  235. data/html/classes/MIDI/Track.src/M000079.html +26 -0
  236. data/html/classes/MIDI/Track.src/M000080.html +18 -0
  237. data/html/classes/MIDI/Track.src/M000081.html +19 -0
  238. data/html/classes/MIDI/TuneRequest.html +171 -0
  239. data/html/classes/MIDI/TuneRequest.src/M000126.html +18 -0
  240. data/html/classes/MIDI/TuneRequest.src/M000127.html +20 -0
  241. data/html/classes/MIDI/TuneRequest.src/M000128.html +18 -0
  242. data/html/classes/MIDI/Utils.html +190 -0
  243. data/html/classes/MIDI/Utils.src/M000190.html +20 -0
  244. data/html/classes/MIDI/Utils.src/M000191.html +25 -0
  245. data/html/classes/MIDI.html +758 -0
  246. data/html/created.rid +1 -0
  247. data/html/files/README.html +681 -0
  248. data/html/files/TODO.html +142 -0
  249. data/html/files/lib/midilib/consts_rb.html +107 -0
  250. data/html/files/lib/midilib/event_rb.html +109 -0
  251. data/html/files/lib/midilib/info_rb.html +101 -0
  252. data/html/files/lib/midilib/io/midifile_rb.html +108 -0
  253. data/html/files/lib/midilib/io/seqreader_rb.html +110 -0
  254. data/html/files/lib/midilib/io/seqwriter_rb.html +115 -0
  255. data/html/files/lib/midilib/measure_rb.html +108 -0
  256. data/html/files/lib/midilib/sequence_rb.html +110 -0
  257. data/html/files/lib/midilib/track_rb.html +108 -0
  258. data/html/files/lib/midilib/utils_rb.html +101 -0
  259. data/html/files/lib/midilib_rb.html +124 -0
  260. data/html/fr_class_index.html +63 -0
  261. data/html/fr_file_index.html +39 -0
  262. data/html/fr_method_index.html +224 -0
  263. data/html/index.html +24 -0
  264. data/html/rdoc-style.css +208 -0
  265. data/lib/midilib/consts.rb +2 -1
  266. data/lib/midilib/event.rb +132 -4
  267. data/lib/midilib/info.rb +2 -2
  268. data/lib/midilib/io/midifile.rb +3 -2
  269. data/lib/midilib/io/seqreader.rb +10 -6
  270. data/lib/midilib/measure.rb +80 -0
  271. data/lib/midilib/sequence.rb +50 -3
  272. data/test/test.mid +0 -0
  273. metadata +343 -38
data/lib/midilib/event.rb CHANGED
@@ -23,6 +23,10 @@ class Event
23
23
  # decimal # (true). Delta times are always printed as decimal.
24
24
  attr_accessor :print_decimal_numbers
25
25
 
26
+ # Determines if to_s outputs MIDI channel numbers from 1-16 instead
27
+ # of the default 0-15.
28
+ attr_accessor :print_channel_numbers_from_one
29
+
26
30
  def initialize(status = 0, delta_time = 0)
27
31
  @status = status
28
32
  @delta_time = delta_time
@@ -33,6 +37,9 @@ class Event
33
37
  @is_meta = false
34
38
  @is_system = false
35
39
  @is_realtime = false
40
+ @is_timesig = false
41
+ @is_keysig = false
42
+ @is_program_change = false
36
43
  @time_from_start = 0 # maintained by tracks
37
44
  end
38
45
  protected :initialize
@@ -74,13 +81,27 @@ class Event
74
81
  def system?
75
82
  return @is_system
76
83
  end
84
+
85
+ # Returns +true+ if this is a time signature event.
86
+ def timesig?
87
+ return @is_timesig
88
+ end
89
+
90
+ # Returns +true+ if this is a key signature event.
91
+ def keysig?
92
+ return @is_keysig
93
+ end
77
94
 
78
95
  # Returns +true+ if this is a realtime status byte.
79
-
80
96
  def realtime?
81
97
  return @is_realtime
82
98
  end
83
99
 
100
+ # Returns +true+ if this is a program change.
101
+ def program_change?
102
+ return @is_program_change
103
+ end
104
+
84
105
  # Quantize this event's time_from_start by moving it to the nearest
85
106
  # multiple of +boundary+. See MIDI::Track#quantize. *Note*: does not
86
107
  # modify the event's delta_time, though MIDI::Track#quantize calls
@@ -106,6 +127,13 @@ class Event
106
127
  return @print_decimal_numbers ? val.to_s : ('%02x' % val)
107
128
  end
108
129
 
130
+ # Returns +val+ as a decimal or hex string, depending upon the value of
131
+ # @print_decimal_numbers.
132
+ def channel_to_s(val)
133
+ val += 1 if @print_channel_numbers_from_one
134
+ return number_to_s(val)
135
+ end
136
+
109
137
  def to_s
110
138
  "#{@delta_time}: "
111
139
  end
@@ -125,7 +153,7 @@ class ChannelEvent < Event
125
153
  protected :initialize
126
154
 
127
155
  def to_s
128
- return super << "ch #{number_to_s(@channel)} "
156
+ return super << "ch #{channel_to_s(@channel)} "
129
157
  end
130
158
 
131
159
  end
@@ -203,7 +231,7 @@ class PolyPressure < NoteEvent
203
231
  end
204
232
  def to_s
205
233
  return super <<
206
- "poly press #{number_to_s(@channel)} #{note_to_s} #{number_to_s(@velocity)}"
234
+ "poly press #{channel_to_s(@channel)} #{note_to_s} #{number_to_s(@velocity)}"
207
235
  end
208
236
  end
209
237
 
@@ -236,6 +264,7 @@ class ProgramChange < ChannelEvent
236
264
  def initialize(channel = 0, program = 0, delta_time = 0)
237
265
  super(PROGRAM_CHANGE, channel, delta_time)
238
266
  @program = program
267
+ @is_program_change = true
239
268
  end
240
269
 
241
270
  def data_as_bytes
@@ -526,7 +555,9 @@ class Tempo < MetaEvent
526
555
 
527
556
  # Translates microseconds per quarter note (beat) to beats per minute.
528
557
  def Tempo.mpq_to_bpm(mpq)
529
- return MICROSECS_PER_MINUTE / mpq
558
+ # Nov 17 2007: Fixed integer rounding error issue:
559
+ # 110 bpm (as 545455 msecs) becomes 109.999 (which became 109 bpm)
560
+ return Integer(MICROSECS_PER_MINUTE.to_f / mpq + 0.49)
530
561
  end
531
562
 
532
563
  def initialize(msecs_per_qnote, delta_time = 0)
@@ -556,4 +587,101 @@ class Tempo < MetaEvent
556
587
  "tempo #{@data} msecs per qnote (#{Tempo.mpq_to_bpm(@data)} bpm)"
557
588
  end
558
589
  end
590
+
591
+ # Container for time signature events
592
+ class TimeSig < MetaEvent
593
+
594
+ # Constructor
595
+ def initialize(numer, denom, clocks, qnotes, delta_time = 0)
596
+ super(META_TIME_SIG, [numer, denom, clocks, qnotes], delta_time)
597
+ @is_timesig = true
598
+ end
599
+
600
+ # Returns the complete event as stored in the sequence
601
+ def data_as_bytes
602
+ data = ''
603
+ data << @status
604
+ data << @meta_type
605
+ data << 4
606
+ data << @data[0]
607
+ data << @data[1]
608
+ data << @data[2]
609
+ data << @data[3]
610
+ end
611
+
612
+ # Calculates the duration (in ticks) for a full measure
613
+ def measure_duration(ppqn)
614
+ (4 * ppqn * @data[0]) / (2**@data[1])
615
+ end
616
+
617
+ # Returns the numerator (the top digit) for the time signature
618
+ def numerator
619
+ @data[0]
620
+ end
621
+
622
+ # Returns the denominator of the time signature. Use it as a power of 2
623
+ # to get the displayed (lower-part) digit of the time signature.
624
+ def denominator
625
+ @data[1]
626
+ end
627
+
628
+ # Returns the metronome tick duration for the time signature. On
629
+ # each quarter note, there's 24 ticks.
630
+ def metronome_ticks
631
+ @data[2]
632
+ end
633
+
634
+ # Returns the time signature for the event as a string.
635
+ # Example: "time sig 3/4"
636
+ def to_s
637
+ "time sig #{@data[0]}/#{2**@data[1]}"
638
+ end
639
+ end
640
+
641
+ # Container for key signature events
642
+ class KeySig < MetaEvent
643
+
644
+ # Constructor
645
+ def initialize(sharpflat, is_minor, delta_time = 0)
646
+ super(META_KEY_SIG, [sharpflat, is_minor], delta_time)
647
+ @is_keysig = true
648
+ end
649
+
650
+ # Returns the complete event as stored in the sequence
651
+ def data_as_bytes
652
+ data = ''
653
+ data << @status
654
+ data << @meta_type
655
+ data << 2
656
+ data << @data[0]
657
+ data << @data[1] ? 1 : 0
658
+ end
659
+
660
+ # Returns true if it's a minor key, false if major key
661
+ def minor_key?
662
+ @data[1]
663
+ end
664
+
665
+ # Returns true if it's a major key, false if minor key
666
+ def major_key?
667
+ !@data[1]
668
+ end
669
+
670
+ # Returns the number of sharps/flats in the key sig. Negative for flats.
671
+ def sharpflat
672
+ @data[0] > 7 ? @data[0] - 256 : @data[0]
673
+ end
674
+
675
+ # Returns the key signature as a text string.
676
+ # Example: "key sig A flat major"
677
+ def to_s
678
+ majorkeys = ['C flat', 'G flat', 'D flat', 'A flat', 'E flat', 'B flat', 'F',
679
+ 'C', 'G', 'D', 'A', 'E', 'B', 'F#', 'C#']
680
+ minorkeys = ['a flat', 'e flat', 'b flat', 'f', 'c', 'g', 'd',
681
+ 'a', 'e', 'b', 'f#', 'c#', 'g#', 'd#', 'a#']
682
+ minor_key? ? "key sig #{minorkeys[sharpflat + 7]} minor" :
683
+ "key sig #{majorkeys[sharpflat + 7]} major"
684
+ end
685
+ end
686
+
559
687
  end
data/lib/midilib/info.rb CHANGED
@@ -1,8 +1,8 @@
1
1
  module MIDI
2
2
 
3
3
  VERSION_MAJOR = 1
4
- VERSION_MINOR = 0
5
- VERSION_TWEAK = 0
4
+ VERSION_MINOR = 1
5
+ VERSION_TWEAK = 1
6
6
  Version = "#{VERSION_MAJOR}.#{VERSION_MINOR}.#{VERSION_TWEAK}"
7
7
  Copyright = 'Copyright (c) 2003-2007 by Jim Menard <jimm@io.com>'
8
8
 
@@ -54,10 +54,11 @@ class MIDIFile
54
54
  end
55
55
 
56
56
  # This default getc implementation tries to read a single character
57
- # from io.
57
+ # from io and returns it as an integer.
58
58
  def getc
59
59
  @bytes_to_be_read -= 1
60
- return @io.getc()
60
+ c = @io.getc()
61
+ c.respond_to?(:bytes) ? c.bytes.first : c
61
62
  end
62
63
 
63
64
  # The default error handler.
@@ -145,9 +145,11 @@ class SeqReader < MIDIFile
145
145
 
146
146
  def text(type, msg)
147
147
  case type
148
- when META_SEQ_NAME
149
- @track.events << MetaEvent.new(META_SEQ_NAME, msg, 0)
150
- when META_INSTRUMENT
148
+ when META_TEXT, META_LYRIC, META_CUE
149
+ @track.events << MetaEvent.new(type, msg, @curr_ticks)
150
+ when META_SEQ_NAME, META_COPYRIGHT
151
+ @track.events << MetaEvent.new(type, msg, 0)
152
+ when META_INSTRUMENT
151
153
  @track.instrument = msg
152
154
  when META_MARKER
153
155
  @track.events << Marker.new(msg, @curr_ticks)
@@ -168,6 +170,7 @@ class SeqReader < MIDIFile
168
170
 
169
171
  def time_signature(numer, denom, clocks, qnotes)
170
172
  @seq.time_signature(numer, denom, clocks, qnotes)
173
+ @track.events << TimeSig.new(numer, denom, clocks, qnotes, @curr_ticks)
171
174
  end
172
175
 
173
176
  # --
@@ -179,10 +182,11 @@ class SeqReader < MIDIFile
179
182
  @track.events << Tempo.new(microsecs, @curr_ticks)
180
183
  end
181
184
 
182
- # --
183
- # def key_signature(sharpflat, is_minor)
184
- # end
185
+ def key_signature(sharpflat, is_minor)
186
+ @track.events << KeySig.new(sharpflat, is_minor, @curr_ticks)
187
+ end
185
188
 
189
+ # --
186
190
  # def arbitrary(msg)
187
191
  # end
188
192
  # ++
@@ -0,0 +1,80 @@
1
+ require 'midilib/consts'
2
+
3
+ module MIDI
4
+
5
+ # The Measure class contains information about a measure from the sequence.
6
+ # The measure data is based on the time signature information from the sequence
7
+ # and is not stored in the sequence itself
8
+ class Measure
9
+ # The numerator (top digit) for the measure's time signature
10
+ attr_reader :numerator
11
+ # The denominator for the measure's time signature
12
+ attr_reader :denominator
13
+ # Start clock tick for the measure
14
+ attr_reader :start
15
+ # End clock tick for the measure (inclusive)
16
+ attr_reader :end
17
+ # The measure number (1-based)
18
+ attr_reader :measure_number
19
+ # The metronome tick for the measure
20
+ attr_reader :metronome_ticks
21
+
22
+ # Constructor
23
+ def initialize(meas_no, start_time, duration, numer, denom, met_ticks)
24
+ @measure_number = meas_no
25
+ @start = start_time
26
+ @end = start_time + duration - 1
27
+ @numerator = numer
28
+ @denominator = denom
29
+ @metronome_ticks = met_ticks
30
+ end
31
+
32
+ # Returns a detailed string with information about the measure
33
+ def to_s
34
+ t = "#{@numerator}/#{2**@denominator}"
35
+ m = @metronome_ticks.to_f / 24
36
+ "measure #{@measure_number} #{@start}-#{@end} #{t} #{m} qs metronome"
37
+ end
38
+
39
+ # Returns +true+ if the event is in the measure
40
+ def contains_event?(e)
41
+ (e.time_from_start >= @start) && (e.time_from_start <= @end)
42
+ end
43
+ end
44
+
45
+ # A specialized container for MIDI::Measure objects, which can be use to map
46
+ # event times to measure numbers. Please note that this object has to be remade
47
+ # when events are deleted/added in the sequence.
48
+ class Measures < Array
49
+ # The highest event time in the sequence (at the time when the
50
+ # object was created)
51
+ attr_reader :max_time
52
+
53
+ # The ppqd from the sequence
54
+ attr_reader :ppqd
55
+
56
+ # Constructor
57
+ def initialize(max_time, ppqd)
58
+ super(0)
59
+ @max_time = max_time
60
+ @ppqd = ppqd
61
+ end
62
+
63
+ # Returns the MIDI::Measure object where the event is located.
64
+ # Returns +nil+ if the event isn't found in the container (should
65
+ # never happen if the MIDI::Measures object is up to date).
66
+ def measure_for_event(e)
67
+ detect { | m | m.contains_event?(e) }
68
+ end
69
+
70
+ # Returns the event's time as a formatted MBT string (Measure:Beat:Ticks)
71
+ # as found in MIDI sequencers.
72
+ def to_mbt(e)
73
+ m = measure_for_event(e)
74
+ b = (e.time_from_start.to_f - m.start.to_f) / @ppqd
75
+ b *= 24 / m.metronome_ticks
76
+ sprintf("%d:%02d:%03d", m.measure_number, b.to_i + 1, (b - b.to_i) * @ppqd)
77
+ end
78
+ end
79
+
80
+ end
@@ -1,5 +1,6 @@
1
1
  require 'midilib/io/seqreader'
2
2
  require 'midilib/io/seqwriter'
3
+ require 'midilib/measure.rb'
3
4
 
4
5
  module MIDI
5
6
 
@@ -27,7 +28,12 @@ class Sequence
27
28
  '64th' => 0.0625
28
29
  }
29
30
 
30
- attr_accessor :tracks, :ppqn, :format
31
+ # Array with all tracks for the sequence
32
+ attr_accessor :tracks
33
+ # Pulses (i.e. clocks) Per Quarter Note resolution for the sequence
34
+ attr_accessor :ppqn
35
+ # The MIDI file format (0, 1, or 2)
36
+ attr_accessor :format
31
37
  attr_accessor :numer, :denom, :clocks, :qnotes
32
38
  # The class to use for reading MIDI from a stream. The default is
33
39
  # MIDI::IO::SeqReader. You can change this at any time.
@@ -43,7 +49,7 @@ class Sequence
43
49
  # Time signature
44
50
  @numer = 4 # Numer + denom = 4/4 time default
45
51
  @denom = 2
46
- @clocks = @ppqn
52
+ @clocks = 24 # Bug fix Nov 11, 2007 - this is not the same as ppqn!
47
53
  @qnotes = 8
48
54
 
49
55
  @reader_class = IO::SeqReader
@@ -124,7 +130,6 @@ class Sequence
124
130
 
125
131
  # Reads a MIDI stream.
126
132
  def read(io, proc = nil) # :yields: track, num_tracks, index
127
- @tracks = Array.new()
128
133
  reader = @reader_class.new(self, block_given?() ? Proc.new() : proc)
129
134
  reader.read_from(io)
130
135
  end
@@ -140,5 +145,47 @@ class Sequence
140
145
  @tracks.each { | track | yield track }
141
146
  end
142
147
 
148
+ # Returns a Measures object, which is an array container for all measures
149
+ # in the sequence
150
+ def get_measures
151
+ # Collect time sig events and scan for last event time
152
+ time_sigs = []
153
+ max_pos = 0
154
+ @tracks.each { |t|
155
+ t.each { |e|
156
+ time_sigs << e if e.timesig?
157
+ max_pos = e.time_from_start if e.time_from_start > max_pos
158
+ }
159
+ }
160
+ time_sigs.sort { |x,y| x.time_from_start <=> y.time_from_start }
161
+
162
+ # Add a "fake" time sig event at the very last position of the sequence,
163
+ # just to make sure the whole sequence is calculated.
164
+ t = MIDI::TimeSig.new(4, 2, 24, 8, 0)
165
+ t.time_from_start = max_pos
166
+ time_sigs << t
167
+
168
+ # Default to 4/4
169
+ measure_length = @ppqn * 4
170
+ oldnumer, olddenom, oldbeats = 4, 2, 24
171
+
172
+ measures = MIDI::Measures.new(max_pos, @ppqn)
173
+ curr_pos = 0
174
+ curr_meas_no = 1
175
+ time_sigs.each { |te|
176
+ meas_count = (te.time_from_start - curr_pos) / measure_length
177
+ meas_count += 1 if (te.time_from_start - curr_pos) % measure_length > 0
178
+ 1.upto(meas_count) { |i|
179
+ measures << MIDI::Measure.new(curr_meas_no,
180
+ curr_pos, measure_length, oldnumer, olddenom, oldbeats)
181
+ curr_meas_no += 1
182
+ curr_pos += measure_length
183
+ }
184
+ oldnumer, olddenom, oldbeats = te.numerator, te.denominator, te.metronome_ticks
185
+ measure_length = te.measure_duration(@ppqn)
186
+ }
187
+ measures
188
+ end
189
+
143
190
  end
144
191
  end
data/test/test.mid ADDED
Binary file