midilib 2.0.2 → 2.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. data/Credits +5 -0
  2. data/README.rdoc +35 -30
  3. data/examples/reader2text.rb +1 -0
  4. data/html/IO.html +259 -0
  5. data/html/MIDI.html +665 -0
  6. data/html/MIDI/ActiveSense.html +295 -0
  7. data/html/MIDI/ChannelEvent.html +319 -0
  8. data/html/MIDI/ChannelPressure.html +350 -0
  9. data/html/MIDI/Clock.html +295 -0
  10. data/html/MIDI/Continue.html +295 -0
  11. data/html/MIDI/Controller.html +365 -0
  12. data/html/MIDI/Event.html +573 -0
  13. data/html/MIDI/IO.html +207 -0
  14. data/html/MIDI/IO/MIDIFile.html +1996 -0
  15. data/html/MIDI/IO/SeqReader.html +946 -0
  16. data/html/MIDI/IO/SeqWriter.html +648 -0
  17. data/html/MIDI/KeySig.html +435 -0
  18. data/html/MIDI/MIDI.html +204 -0
  19. data/html/MIDI/MIDI/MIDI.html +204 -0
  20. data/html/MIDI/MIDI/MIDI/Array.html +353 -0
  21. data/html/MIDI/Marker.html +257 -0
  22. data/html/MIDI/Measure.html +423 -0
  23. data/html/MIDI/Measures.html +375 -0
  24. data/html/MIDI/MetaEvent.html +534 -0
  25. data/html/MIDI/NoteEvent.html +417 -0
  26. data/html/MIDI/NoteOff.html +316 -0
  27. data/html/MIDI/NoteOn.html +316 -0
  28. data/html/MIDI/PitchBend.html +351 -0
  29. data/html/MIDI/PolyPressure.html +360 -0
  30. data/html/MIDI/ProgramChange.html +350 -0
  31. data/html/MIDI/Realtime.html +328 -0
  32. data/html/MIDI/Sequence.html +961 -0
  33. data/html/MIDI/SongPointer.html +351 -0
  34. data/html/MIDI/SongSelect.html +350 -0
  35. data/html/MIDI/Start.html +295 -0
  36. data/html/MIDI/Stop.html +295 -0
  37. data/html/MIDI/SystemCommon.html +257 -0
  38. data/html/MIDI/SystemExclusive.html +353 -0
  39. data/html/MIDI/SystemReset.html +295 -0
  40. data/html/MIDI/Tempo.html +474 -0
  41. data/html/MIDI/TimeSig.html +467 -0
  42. data/html/MIDI/Track.html +769 -0
  43. data/html/MIDI/TuneRequest.html +328 -0
  44. data/html/MIDI/Utils.html +320 -0
  45. data/html/README_rdoc.html +751 -0
  46. data/html/TODO_rdoc.html +200 -0
  47. data/html/created.rid +14 -0
  48. data/html/images/add.png +0 -0
  49. data/html/images/brick.png +0 -0
  50. data/html/images/brick_link.png +0 -0
  51. data/html/images/bug.png +0 -0
  52. data/html/images/bullet_black.png +0 -0
  53. data/html/images/bullet_toggle_minus.png +0 -0
  54. data/html/images/bullet_toggle_plus.png +0 -0
  55. data/html/images/date.png +0 -0
  56. data/html/images/delete.png +0 -0
  57. data/html/images/find.png +0 -0
  58. data/html/images/loadingAnimation.gif +0 -0
  59. data/html/images/macFFBgHack.png +0 -0
  60. data/html/images/package.png +0 -0
  61. data/html/images/page_green.png +0 -0
  62. data/html/images/page_white_text.png +0 -0
  63. data/html/images/page_white_width.png +0 -0
  64. data/html/images/plugin.png +0 -0
  65. data/html/images/ruby.png +0 -0
  66. data/html/images/tag_blue.png +0 -0
  67. data/html/images/tag_green.png +0 -0
  68. data/html/images/transparent.png +0 -0
  69. data/html/images/wrench.png +0 -0
  70. data/html/images/wrench_orange.png +0 -0
  71. data/html/images/zoom.png +0 -0
  72. data/html/index.html +750 -0
  73. data/html/js/darkfish.js +153 -0
  74. data/html/js/jquery.js +18 -0
  75. data/html/js/navigation.js +142 -0
  76. data/html/js/search.js +94 -0
  77. data/html/js/search_index.js +1 -0
  78. data/html/js/searcher.js +228 -0
  79. data/html/rdoc.css +543 -0
  80. data/html/table_of_contents.html +652 -0
  81. data/lib/midilib/info.rb +1 -1
  82. data/lib/midilib/io/seqreader.rb +1 -1
  83. data/lib/midilib/sequence.rb +7 -0
  84. data/test/test_sequence.rb +11 -0
  85. metadata +80 -3
@@ -0,0 +1,751 @@
1
+ <!DOCTYPE html>
2
+
3
+ <html>
4
+ <head>
5
+ <meta content="text/html; charset=US-ASCII" http-equiv="Content-Type">
6
+
7
+ <title>README - midilib</title>
8
+
9
+ <link type="text/css" media="screen" href="./rdoc.css" rel="stylesheet">
10
+
11
+ <script type="text/javascript">
12
+ var rdoc_rel_prefix = "./";
13
+ </script>
14
+
15
+ <script type="text/javascript" charset="utf-8" src="./js/jquery.js"></script>
16
+ <script type="text/javascript" charset="utf-8" src="./js/navigation.js"></script>
17
+ <script type="text/javascript" charset="utf-8" src="./js/search_index.js"></script>
18
+ <script type="text/javascript" charset="utf-8" src="./js/search.js"></script>
19
+ <script type="text/javascript" charset="utf-8" src="./js/searcher.js"></script>
20
+ <script type="text/javascript" charset="utf-8" src="./js/darkfish.js"></script>
21
+
22
+
23
+ <body class="file">
24
+ <nav id="metadata">
25
+ <nav id="home-section" class="section">
26
+ <h3 class="section-header">
27
+ <a href="./index.html">Home</a>
28
+ <a href="./table_of_contents.html#classes">Classes</a>
29
+ <a href="./table_of_contents.html#methods">Methods</a>
30
+ </h3>
31
+ </nav>
32
+
33
+
34
+ <nav id="search-section" class="section project-section" class="initially-hidden">
35
+ <form action="#" method="get" accept-charset="utf-8">
36
+ <h3 class="section-header">
37
+ <input type="text" name="search" placeholder="Search" id="search-field"
38
+ title="Type to search, Up and Down to navigate, Enter to load">
39
+ </h3>
40
+ </form>
41
+
42
+ <ul id="search-results" class="initially-hidden"></ul>
43
+ </nav>
44
+
45
+
46
+ <div id="project-metadata">
47
+ <nav id="fileindex-section" class="section project-section">
48
+ <h3 class="section-header">Pages</h3>
49
+
50
+ <ul>
51
+
52
+ <li class="file"><a href="./README_rdoc.html">README</a>
53
+
54
+ <li class="file"><a href="./TODO_rdoc.html">TODO</a>
55
+
56
+ </ul>
57
+ </nav>
58
+
59
+ <nav id="classindex-section" class="section project-section">
60
+ <h3 class="section-header">Class and Module Index</h3>
61
+
62
+ <ul class="link-list">
63
+
64
+ <li><a href="./MIDI.html">MIDI</a>
65
+
66
+ <li><a href="./MIDI/ActiveSense.html">MIDI::ActiveSense</a>
67
+
68
+ <li><a href="./MIDI/ChannelEvent.html">MIDI::ChannelEvent</a>
69
+
70
+ <li><a href="./MIDI/ChannelPressure.html">MIDI::ChannelPressure</a>
71
+
72
+ <li><a href="./MIDI/Clock.html">MIDI::Clock</a>
73
+
74
+ <li><a href="./MIDI/Continue.html">MIDI::Continue</a>
75
+
76
+ <li><a href="./MIDI/Controller.html">MIDI::Controller</a>
77
+
78
+ <li><a href="./MIDI/Event.html">MIDI::Event</a>
79
+
80
+ <li><a href="./MIDI/IO.html">MIDI::IO</a>
81
+
82
+ <li><a href="./MIDI/IO/MIDIFile.html">MIDI::IO::MIDIFile</a>
83
+
84
+ <li><a href="./MIDI/IO/SeqReader.html">MIDI::IO::SeqReader</a>
85
+
86
+ <li><a href="./MIDI/IO/SeqWriter.html">MIDI::IO::SeqWriter</a>
87
+
88
+ <li><a href="./MIDI/KeySig.html">MIDI::KeySig</a>
89
+
90
+ <li><a href="./MIDI/MIDI.html">MIDI::MIDI</a>
91
+
92
+ <li><a href="./MIDI/MIDI/MIDI.html">MIDI::MIDI::MIDI</a>
93
+
94
+ <li><a href="./MIDI/MIDI/MIDI/Array.html">MIDI::MIDI::MIDI::Array</a>
95
+
96
+ <li><a href="./MIDI/Marker.html">MIDI::Marker</a>
97
+
98
+ <li><a href="./MIDI/Measure.html">MIDI::Measure</a>
99
+
100
+ <li><a href="./MIDI/Measures.html">MIDI::Measures</a>
101
+
102
+ <li><a href="./MIDI/MetaEvent.html">MIDI::MetaEvent</a>
103
+
104
+ <li><a href="./MIDI/NoteEvent.html">MIDI::NoteEvent</a>
105
+
106
+ <li><a href="./MIDI/NoteOff.html">MIDI::NoteOff</a>
107
+
108
+ <li><a href="./MIDI/NoteOff.html">MIDI::NoteOffEvent</a>
109
+
110
+ <li><a href="./MIDI/NoteOn.html">MIDI::NoteOn</a>
111
+
112
+ <li><a href="./MIDI/NoteOn.html">MIDI::NoteOnEvent</a>
113
+
114
+ <li><a href="./MIDI/PitchBend.html">MIDI::PitchBend</a>
115
+
116
+ <li><a href="./MIDI/PolyPressure.html">MIDI::PolyPressure</a>
117
+
118
+ <li><a href="./MIDI/ProgramChange.html">MIDI::ProgramChange</a>
119
+
120
+ <li><a href="./MIDI/Realtime.html">MIDI::Realtime</a>
121
+
122
+ <li><a href="./MIDI/Sequence.html">MIDI::Sequence</a>
123
+
124
+ <li><a href="./MIDI/SongPointer.html">MIDI::SongPointer</a>
125
+
126
+ <li><a href="./MIDI/SongSelect.html">MIDI::SongSelect</a>
127
+
128
+ <li><a href="./MIDI/Start.html">MIDI::Start</a>
129
+
130
+ <li><a href="./MIDI/Stop.html">MIDI::Stop</a>
131
+
132
+ <li><a href="./MIDI/SystemCommon.html">MIDI::SystemCommon</a>
133
+
134
+ <li><a href="./MIDI/SystemExclusive.html">MIDI::SystemExclusive</a>
135
+
136
+ <li><a href="./MIDI/SystemReset.html">MIDI::SystemReset</a>
137
+
138
+ <li><a href="./MIDI/Tempo.html">MIDI::Tempo</a>
139
+
140
+ <li><a href="./MIDI/TimeSig.html">MIDI::TimeSig</a>
141
+
142
+ <li><a href="./MIDI/Track.html">MIDI::Track</a>
143
+
144
+ <li><a href="./MIDI/TuneRequest.html">MIDI::TuneRequest</a>
145
+
146
+ <li><a href="./MIDI/Utils.html">MIDI::Utils</a>
147
+
148
+ <li><a href="./IO.html">IO</a>
149
+
150
+ </ul>
151
+ </nav>
152
+
153
+ </div>
154
+ </nav>
155
+
156
+ <div id="documentation" class="description">
157
+
158
+ <h1 id="label-midilib">midilib</h1>
159
+
160
+ <p>midilib is a pure Ruby <a href="MIDI.html">MIDI</a> library useful for
161
+ reading and writing standard <a href="MIDI.html">MIDI</a> files and
162
+ manipulating <a href="MIDI.html">MIDI</a> event data.</p>
163
+
164
+ <p>The GitHub project page and Web site of midilib is <a
165
+ href="http://github.com/jimm/midilib">github.com/jimm/midilib</a> and the
166
+ RubyGems.org page is <a
167
+ href="http://rubygems.org/gems/midilib">rubygems.org/gems/midilib</a>,
168
+ where you can also find all the RDoc documentation.</p>
169
+
170
+ <p>midilib is compatible with both Ruby 1.8.x and 1.9.x.</p>
171
+
172
+ <h2 id="label-Dependencies">Dependencies</h2>
173
+
174
+ <p>midilib does not require any other packages. The test suite in the tests
175
+ directory requires the testing framework TestUnit, which comes with Ruby
176
+ 1.8 and later and can also be found in the Ruby Application Archive (<a
177
+ href="http://raa.ruby-lang.org">raa.ruby-lang.org</a>).</p>
178
+
179
+ <p>To rebuild the gem or RDocs or run the tests easily, you can use the
180
+ Rakefile which requires Rake (<a
181
+ href="http://rake.rubyforge.org">rake.rubyforge.org</a>).</p>
182
+
183
+ <h2 id="label-Installation">Installation</h2>
184
+
185
+ <h3 id="label-RubyGems+Installation">RubyGems Installation</h3>
186
+
187
+ <p>To install midilib as a gem, type</p>
188
+
189
+ <pre>% gem install midilib</pre>
190
+
191
+ <p>or, if you already have a previous version, use</p>
192
+
193
+ <pre>% gem update midilib</pre>
194
+
195
+ <p>You may need root privileges to install or update the gem.</p>
196
+
197
+ <h3 id="label-Manual+Installation">Manual Installation</h3>
198
+
199
+ <p>After downloading and expanding the archive, you can install midilib with
200
+ the command</p>
201
+
202
+ <pre>% ruby install.rb</pre>
203
+
204
+ <p>(or)</p>
205
+
206
+ <pre>% ruby install.rb --install-dir=my_directory</pre>
207
+
208
+ <p>You may need root privileges to install.</p>
209
+
210
+ <h2 id="label-Testing">Testing</h2>
211
+
212
+ <pre>% rake test</pre>
213
+
214
+ <p>runs all of the tests in the test directory.</p>
215
+
216
+ <h2 id="label-Overview">Overview</h2>
217
+
218
+ <p>The midilib <a href="MIDI.html">MIDI</a> file reader only understands <a
219
+ href="MIDI.html">MIDI</a> file format 1, where a sequence is made up of
220
+ multiple tracks. It doesn't yet understand format 0 (a single track
221
+ containing all events) or format 2 (a collection of format 0 files in one
222
+ file).</p>
223
+
224
+ <p>d=== <a href="MIDI/Sequence.html">MIDI::Sequence</a></p>
225
+
226
+ <p>A sequence contains a collection of tracks and global information like the
227
+ sequence's pulses per quarter note (ppqn) and time signature.</p>
228
+
229
+ <p>The first track in a sequence is special; it holds meta-events like tempo
230
+ and sequence name. Don't put any notes in this track.</p>
231
+
232
+ <p><a href="MIDI/Sequence.html">MIDI::Sequence</a> also contains some
233
+ convenience methods that let you set and retrieve the sequence's name, the
234
+ time signature, and to retrieve the first tempo event's beats-per-minute
235
+ value.</p>
236
+
237
+ <p>Normally instances of <a
238
+ href="MIDI/IO/SeqReader.html">MIDI::IO::SeqReader</a> and <a
239
+ href="MIDI/IO/SeqWriter.html">MIDI::IO::SeqWriter</a> are used when a
240
+ sequence reads itself from or writes itself to a <a
241
+ href="MIDI.html">MIDI</a> file. You can change that by setting a sequence's
242
+ reader_class or writer_class attributes. Instances of the classes contained
243
+ in those attributes are created and used whenever the sequence reads or
244
+ writes itself.</p>
245
+
246
+ <h3 id="label-MIDI%3A%3ATrack"><a href="MIDI/Track.html">MIDI::Track</a></h3>
247
+
248
+ <p>A track contains an array of events.</p>
249
+
250
+ <p>When you modify the <code>events</code> array, make sure to call
251
+ recalc_times so each event gets its <code>time_from_start</code>
252
+ recalculated. You don't have to do that after every event you add; just
253
+ remember to do so before using the track in a way that expects the list of
254
+ events to be ordered correctly.</p>
255
+
256
+ <p>A Track also holds a bit mask that specifies the channels used by the
257
+ track. This bit mask is set when the track is read from the <a
258
+ href="MIDI.html">MIDI</a> file by a SeqReader but is <em>not</em> kept up
259
+ to date by any other methods. Specifically, if you add events to a track at
260
+ any other time, the bit mask will not be updated.</p>
261
+
262
+ <h3 id="label-MIDI%3A%3AMeasure"><a href="MIDI/Measure.html">MIDI::Measure</a></h3>
263
+
264
+ <p>This class contains information about a measure from the sequence. Measure
265
+ data is based on the time signature information from the sequence and is
266
+ not stored in the sequence itself.</p>
267
+
268
+ <h3 id="label-MIDI%3A%3AMeasures"><a href="MIDI/Measures.html">MIDI::Measures</a></h3>
269
+
270
+ <p>The class <a href="MIDI/Sequence.html">MIDI::Sequence</a> method
271
+ get_measures returns a <a href="MIDI/Measures.html">MIDI::Measures</a>
272
+ object. <a href="MIDI/Measures.html">MIDI::Measures</a> is a subclass of
273
+ Array. It is a specialized container for <a
274
+ href="MIDI/Measure.html">MIDI::Measure</a> objects, which can be use to map
275
+ event times to measure numbers. Please note that this object has to be
276
+ remade when events are deleted/added in the sequence.</p>
277
+
278
+ <p><a href="MIDI/Measure.html">MIDI::Measure</a> and <a
279
+ href="MIDI/Measures.html">MIDI::Measures</a> are brought to us by Jari
280
+ Williamsson &lt;mailbox at jari.williamsson.swipnet.se&gt;, who also
281
+ contributed some improvements to the <a
282
+ href="MIDI/Event.html">MIDI::Event</a> and <a
283
+ href="MIDI/Track.html">MIDI::Track</a> classes.</p>
284
+
285
+ <h3 id="label-MIDI%3A%3AEvent"><a href="MIDI/Event.html">MIDI::Event</a></h3>
286
+
287
+ <p>Each event holds not only its delta time but also its time from the start
288
+ of the track. The track is responsible for recalculating its events' start
289
+ times. You can call <a
290
+ href="MIDI/Track.html#method-i-recalc_times">MIDI::Track#recalc_times</a>
291
+ to do so.</p>
292
+
293
+ <p>Subclasses of <a href="MIDI/Event.html">MIDI::Event</a> implement the
294
+ various <a href="MIDI.html">MIDI</a> messages such as note on and off,
295
+ controller values, system exclusive data, and realtime bytes.</p>
296
+
297
+ <p><a href="MIDI/Realtime.html">MIDI::Realtime</a> events have delta values
298
+ and start times, just like all the other midilib event types do. (<a
299
+ href="MIDI.html">MIDI</a> real time status bytes don't have delta times,
300
+ but this way we can record when in a track the realtime byte was received
301
+ and should be sent. This is useful for start/continue/stop events that
302
+ control other devices, for example.) Note that when a <a
303
+ href="MIDI/Realtime.html">MIDI::Realtime</a> event is written out to a <a
304
+ href="MIDI.html">MIDI</a> file, the delta time is not written.</p>
305
+
306
+ <p><a href="MIDI/MetaEvent.html">MIDI::MetaEvent</a> events hold an array of
307
+ bytes named 'data'. Many meta events are string holders (text, lyric,
308
+ marker, etc.) Though the 'data' value is always an array of bytes, <a
309
+ href="MIDI/MetaEvent.html">MIDI::MetaEvent</a> helps with saving and
310
+ accessing string. The <a
311
+ href="MIDI/MetaEvent.html#method-i-data_as_str">MIDI::MetaEvent#data_as_str</a>
312
+ method returns the data bytes as a string. When assigning to a meta event's
313
+ data, if you pass in a string it will get converted to an array of bytes.</p>
314
+
315
+ <h2 id="label-How+To+Use">How To Use</h2>
316
+
317
+ <p>The following examples show you how to use midilib to read, write, and
318
+ manipulate <a href="MIDI.html">MIDI</a> files and modify track events. See
319
+ also the files in the examples directory, which are described below.</p>
320
+
321
+ <h3 id="label-Reading+a+MIDI+File">Reading a <a href="MIDI.html">MIDI</a> File</h3>
322
+
323
+ <p>To read a <a href="MIDI.html">MIDI</a> file, create a <a
324
+ href="MIDI/Sequence.html">MIDI::Sequence</a> object and call its read
325
+ method, passing in an <a href="IO.html">IO</a> object.</p>
326
+
327
+ <p>The read method takes an optional block. If present, the block is called
328
+ once after each track has finished being read. Each time, it is passed the
329
+ track object, the total number of tracks and the number of the current
330
+ track that has just been read. This is useful for notifying the user of
331
+ progress, for example by updating a GUI progress bar.</p>
332
+
333
+ <pre class="ruby"><span class="ruby-identifier">require</span> <span class="ruby-string">'midilib/io/seqreader'</span>
334
+
335
+ <span class="ruby-comment"># Create a new, empty sequence.</span>
336
+ <span class="ruby-identifier">seq</span> = <span class="ruby-constant">MIDI</span><span class="ruby-operator">::</span><span class="ruby-constant">Sequence</span>.<span class="ruby-identifier">new</span>()
337
+
338
+ <span class="ruby-comment"># Read the contents of a MIDI file into the sequence.</span>
339
+ <span class="ruby-constant">File</span>.<span class="ruby-identifier">open</span>(<span class="ruby-string">'my_midi_file.mid'</span>, <span class="ruby-string">'rb'</span>) { <span class="ruby-operator">|</span> <span class="ruby-identifier">file</span> <span class="ruby-operator">|</span>
340
+ <span class="ruby-identifier">seq</span>.<span class="ruby-identifier">read</span>(<span class="ruby-identifier">file</span>) { <span class="ruby-operator">|</span> <span class="ruby-identifier">track</span>, <span class="ruby-identifier">num_tracks</span>, <span class="ruby-identifier">i</span> <span class="ruby-operator">|</span>
341
+ <span class="ruby-comment"># Print something when each track is read.</span>
342
+ <span class="ruby-identifier">puts</span> <span class="ruby-node">&quot;read track #{i} of #{num_tracks}&quot;</span>
343
+ }
344
+ }
345
+ </pre>
346
+
347
+ <h3 id="label-Writing+a+MIDI+File">Writing a <a href="MIDI.html">MIDI</a> File</h3>
348
+
349
+ <p>To write a <a href="MIDI.html">MIDI</a> file, call the write method,
350
+ passing in an <a href="IO.html">IO</a> object.</p>
351
+
352
+ <pre class="ruby"><span class="ruby-identifier">require</span> <span class="ruby-string">'midilib/io/seqwriter'</span>
353
+
354
+ <span class="ruby-comment"># Start with a sequence that has something worth saving.</span>
355
+ <span class="ruby-identifier">seq</span> = <span class="ruby-identifier">read_or_create_seq_we_care_not_how</span>()
356
+
357
+ <span class="ruby-comment"># Write the sequence to a MIDI file.</span>
358
+ <span class="ruby-constant">File</span>.<span class="ruby-identifier">open</span>(<span class="ruby-string">'my_output_file.mid'</span>, <span class="ruby-string">'wb'</span>) { <span class="ruby-operator">|</span> <span class="ruby-identifier">file</span> <span class="ruby-operator">|</span> <span class="ruby-identifier">seq</span>.<span class="ruby-identifier">write</span>(<span class="ruby-identifier">file</span>) }
359
+ </pre>
360
+
361
+ <h3 id="label-Editing+a+MIDI+File">Editing a <a href="MIDI.html">MIDI</a> File</h3>
362
+
363
+ <p>Combining the last two examples, here is a script that reads a <a
364
+ href="MIDI.html">MIDI</a> file, transposes some events, and writes the
365
+ sequence out to a different file. This is a useful template for
366
+ programatically manipulating <a href="MIDI.html">MIDI</a> data.</p>
367
+
368
+ <p>This code transposes all of the note events (note on, note off, and poly
369
+ pressure) on channel 5 down one octave.</p>
370
+
371
+ <h4 id="label-Transposing+One+Channel">Transposing One Channel</h4>
372
+
373
+ <pre class="ruby"><span class="ruby-identifier">require</span> <span class="ruby-string">'midilib/io/seqreader'</span>
374
+ <span class="ruby-identifier">require</span> <span class="ruby-string">'midilib/io/seqwriter'</span>
375
+
376
+ <span class="ruby-comment"># Create a new, empty sequence.</span>
377
+ <span class="ruby-identifier">seq</span> = <span class="ruby-constant">MIDI</span><span class="ruby-operator">::</span><span class="ruby-constant">Sequence</span>.<span class="ruby-identifier">new</span>()
378
+
379
+ <span class="ruby-comment"># Read the contents of a MIDI file into the sequence.</span>
380
+ <span class="ruby-constant">File</span>.<span class="ruby-identifier">open</span>(<span class="ruby-string">'my_input_file.mid'</span>, <span class="ruby-string">'rb'</span>) { <span class="ruby-operator">|</span> <span class="ruby-identifier">file</span> <span class="ruby-operator">|</span>
381
+ <span class="ruby-identifier">seq</span>.<span class="ruby-identifier">read</span>(<span class="ruby-identifier">file</span>) { <span class="ruby-operator">|</span> <span class="ruby-identifier">track</span>, <span class="ruby-identifier">num_tracks</span>, <span class="ruby-identifier">i</span> <span class="ruby-operator">|</span>
382
+ <span class="ruby-comment"># Print something when each track is read.</span>
383
+ <span class="ruby-identifier">puts</span> <span class="ruby-node">&quot;read track #{i} of #{num_tracks}&quot;</span>
384
+ }
385
+ }
386
+
387
+ <span class="ruby-comment"># Iterate over every event in every track.</span>
388
+ <span class="ruby-identifier">seq</span>.<span class="ruby-identifier">each</span> { <span class="ruby-operator">|</span> <span class="ruby-identifier">track</span> <span class="ruby-operator">|</span>
389
+ <span class="ruby-identifier">track</span>.<span class="ruby-identifier">each</span> { <span class="ruby-operator">|</span> <span class="ruby-identifier">event</span> <span class="ruby-operator">|</span>
390
+ <span class="ruby-comment"># If the event is a note event (note on, note off, or poly</span>
391
+ <span class="ruby-comment"># pressure) and it is on MIDI channel 5 (channels start at</span>
392
+ <span class="ruby-comment"># 0, so we use 4), then transpose the event down one octave.</span>
393
+ <span class="ruby-keyword">if</span> <span class="ruby-constant">MIDI</span><span class="ruby-operator">::</span><span class="ruby-constant">NoteEvent</span> <span class="ruby-operator">===</span> <span class="ruby-identifier">event</span> <span class="ruby-operator">&amp;&amp;</span> <span class="ruby-identifier">event</span>.<span class="ruby-identifier">channel</span> <span class="ruby-operator">==</span> <span class="ruby-value">4</span>
394
+ <span class="ruby-identifier">event</span>.<span class="ruby-identifier">note</span> <span class="ruby-operator">-=</span> <span class="ruby-value">12</span>
395
+ <span class="ruby-keyword">end</span>
396
+ }
397
+ }
398
+
399
+ <span class="ruby-comment"># Write the sequence to a MIDI file.</span>
400
+ <span class="ruby-constant">File</span>.<span class="ruby-identifier">open</span>(<span class="ruby-string">'my_output_file.mid'</span>, <span class="ruby-string">'wb'</span>) { <span class="ruby-operator">|</span> <span class="ruby-identifier">file</span> <span class="ruby-operator">|</span> <span class="ruby-identifier">seq</span>.<span class="ruby-identifier">write</span>(<span class="ruby-identifier">file</span>) }
401
+ </pre>
402
+
403
+ <h3 id="label-Manipulating+tracks">Manipulating tracks</h3>
404
+
405
+ <p>If you modify a track's list of events directly, don't forget to call <a
406
+ href="MIDI/Track.html#method-i-recalc_times">MIDI::Track#recalc_times</a>
407
+ when you are done.</p>
408
+
409
+ <pre>track.events[42, 1] = array_of_events
410
+ track.events &lt;&lt; an_event
411
+ track.merge(array_of_events)
412
+ track.recalc_times</pre>
413
+
414
+ <h3 id="label-Calculating+delta+times">Calculating delta times</h3>
415
+
416
+ <p>A few methods in <a href="MIDI/Sequence.html">MIDI::Sequence</a> make it
417
+ easier to calculate the delta times that represent note lengths. <a
418
+ href="MIDI/Sequence.html#method-i-length_to_delta">MIDI::Sequence#length_to_delta</a>
419
+ takes a note length (a multiple of a quarter note) and returns the delta
420
+ time given the sequence's current ppqn (pulses per quarter note) setting. 1
421
+ is a quarter note, 1.0/32.0 is a 32nd note (use floating-point numbers to
422
+ avoid integer rounding), 1.5 is a dotted quarter, etc. See the
423
+ documentation for that method for more information.</p>
424
+
425
+ <p><a
426
+ href="MIDI/Sequence.html#method-i-note_to_length">MIDI::Sequence#note_to_length</a>
427
+ takes a note name and returns a length value (again, as a multiple of a
428
+ quarter note). Legal note names are those found in
429
+ MIDI::Sequence::NOTE_TO_LENGTH, and may begin with "dotted" and/or end with
430
+ "triplet". For example, "whole", "sixteenth", "32nd", "quarter triplet",
431
+ "dotted 16th", and "dotted 8th triplet" are all legal note names.</p>
432
+
433
+ <p>Finally, <a
434
+ href="MIDI/Sequence.html#method-i-note_to_delta">MIDI::Sequence#note_to_delta</a>
435
+ takes a note name and returns a delta time. It does this by calling
436
+ note_to_length, then passing the result to length_to_delta.</p>
437
+
438
+ <h3 id="label-Example+Scripts">Example Scripts</h3>
439
+
440
+ <p>Here are short descriptions of each of the examples found in the examples
441
+ directory.</p>
442
+ <ul><li>
443
+ <p>examples/from_scratch.rb shows you how to create a new sequence from
444
+ scratch and save it to a <a href="MIDI.html">MIDI</a> file. It creates a
445
+ file called 'from_scratch.mid'.</p>
446
+ </li><li>
447
+ <p>examples/seq2text.rb dumps a <a href="MIDI.html">MIDI</a> file as text. It
448
+ reads in a sequence and uses the to_s method of each event.</p>
449
+ </li><li>
450
+ <p>examples/reader2text.rb dumps a <a href="MIDI.html">MIDI</a> file as text.
451
+ It subclasses MIDI::SeqReader instead of creating a sequence containing
452
+ tracks and events.</p>
453
+ </li><li>
454
+ <p>examples/transpose.rb transposes all note events (note on, note off, poly
455
+ pressure) on a specified channel by a specified amount.</p>
456
+ </li><li>
457
+ <p>There is also one <a href="MIDI.html">MIDI</a> file, examples/NoFences.mid.
458
+ It is a little pop ditty I wrote. The instruments in this file use General
459
+ <a href="MIDI.html">MIDI</a> patch numbers and drum note assignments. Since
460
+ I don't normally use GM patches, the sounds used here are at best
461
+ approximations of the sounds I use.</p>
462
+ </li></ul>
463
+
464
+ <h2 id="label-Resources">Resources</h2>
465
+
466
+ <p>The Ruby Web site (<a
467
+ href="http://www.ruby-lang.org/en/index.html">www.ruby-lang.org/en/index.html</a>)
468
+ contains an introduction to Ruby, the Ruby Application Archive (RAA) at <a
469
+ href="http://raa.ruby-lang.org">raa.ruby-lang.org</a>, and pointers to more
470
+ information.</p>
471
+
472
+ <p>&lt;cite&gt;Programming Ruby, The Pragmatic Programmer's
473
+ Guide&lt;/cite&gt;, by David Thomas and Andrew Hunt, is a well-written and
474
+ practical introduction to Ruby. Its Web page at <a
475
+ href="http://www.rubycentral.com/book">www.rubycentral.com/book</a> also
476
+ contains a wealth of Ruby information. Though the first edition book is
477
+ available online, I encourage you to purchase a copy of the latest edition.</p>
478
+
479
+ <p>A description of the <a href="MIDI.html">MIDI</a> file format can be found
480
+ in a few places such as <a
481
+ href="http://www.borg.com/~jglatt/tech/midifile.htm.">www.borg.com/~jglatt/tech/midifile.htm.</a></p>
482
+
483
+ <p>The <a href="MIDI.html">MIDI</a> message reference at <a
484
+ href="http://www.jimmenard.com/midi_ref.html">www.jimmenard.com/midi_ref.html</a>
485
+ describes the format of <a href="MIDI.html">MIDI</a> commands.</p>
486
+
487
+ <h1 id="label-To+Do">To Do</h1>
488
+
489
+ <h2 id="label-Bugs">Bugs</h2>
490
+
491
+ <p>No known bugs. (If that's not a challenge, I don't know what is.)</p>
492
+
493
+ <h2 id="label-Features">Features</h2>
494
+ <ul><li>
495
+ <p><code>print_decimal_numbers</code> and
496
+ <code>print_channel_numbers_from_one</code> should be associated with
497
+ sequence, or perhaps track, not event.</p>
498
+ </li><li>
499
+ <p>Method to translate event's time_from_start to number of milliseconds from
500
+ start.</p>
501
+ </li><li>
502
+ <p>Swing quantizing. (Implied by list email from Carl Youngblood &lt;gmail at
503
+ carl.youngblood.com&gt;)</p>
504
+ </li><li>
505
+ <p>Implement key signature in SeqReader.</p>
506
+ </li><li>
507
+ <p>Format 0 files.</p>
508
+ </li><li>
509
+ <p>Format 2 files(?).</p>
510
+ </li></ul>
511
+
512
+ <h2 id="label-Documentation">Documentation</h2>
513
+ <ul><li>
514
+ <p>Write better docs.</p>
515
+ </li></ul>
516
+
517
+ <h2 id="label-Tests">Tests</h2>
518
+ <ul><li>
519
+ <p>Tests for Noah Thorp's midilib bug fixes.</p>
520
+ </li></ul>
521
+
522
+ <h1 id="label-Support">Support</h1>
523
+ <ul><li>
524
+ <p>Visit the forums, bug list, and mailing list pages at <a
525
+ href="http://rubyforge.org/projects/midilib">rubyforge.org/projects/midilib</a></p>
526
+ </li><li>
527
+ <p>Send email to Jim Menard at <a
528
+ href="mailto:jim@jimmenard.com">jim@jimmenard.com</a></p>
529
+ </li><li>
530
+ <p>Ask on the ruby-talk mailing list</p>
531
+ </li></ul>
532
+
533
+ <h1 id="label-Administrivia">Administrivia</h1>
534
+ <dl class="rdoc-list note-list"><dt>Author
535
+ <dd>
536
+ <p>Jim Menard (<a href="mailto:jim@jimmenard.com">jim@jimmenard.com</a>)</p>
537
+ </dd><dt>Copyright
538
+ <dd>
539
+ <p>Copyright (c) 2003-2012 Jim Menard</p>
540
+ </dd><dt>License
541
+ <dd>
542
+ <p>Distributed under the same license as Ruby.</p>
543
+ </dd></dl>
544
+
545
+ <h2 id="label-Copying">Copying</h2>
546
+
547
+ <p>midilib is copyrighted free software by Jim Menard and is released under
548
+ the same license as Ruby. See the Ruby license at <a
549
+ href="http://www.ruby-lang.org/en/LICENSE.txt.">www.ruby-lang.org/en/LICENSE.txt.</a></p>
550
+
551
+ <p>midilib may be freely copied in its entirety providing this notice, all
552
+ source code, all documentation, and all other files are included.</p>
553
+
554
+ <p>midilib is Copyright (c) 2003-2012 by Jim Menard.</p>
555
+
556
+ <p>The song "No Fences" contained in the <a href="MIDI.html">MIDI</a> file
557
+ examples/NoFences.mid is Copyright (c) 1992 by Jim Menard
558
+ (jim@jimmenard.com). It may be freely used for non-commercial purposes as
559
+ long as the author is given credit.</p>
560
+
561
+ <h2 id="label-Recent+Changes">Recent Changes</h2>
562
+
563
+ <h3 id="label-Changes+for+2.0.3%3A">Changes for 2.0.3:</h3>
564
+
565
+ <p>New <a
566
+ href="MIDI/Sequence.html#method-i-pulses_to_seconds">MIDI::Sequence#pulses_to_seconds</a>
567
+ method.</p>
568
+
569
+ <h3 id="label-Changes+for+2.0.2%3A">Changes for 2.0.2:</h3>
570
+
571
+ <p>Stop monkeypatching Array in <a href="MIDI/Track.html">MIDI::Track</a>.</p>
572
+
573
+ <h3 id="label-Changes+for+2.0.0%3A">Changes for 2.0.0:</h3>
574
+
575
+ <p><a href="MIDI/NoteOn.html">MIDI::NoteOnEvent</a> and <a
576
+ href="MIDI/NoteOff.html">MIDI::NoteOffEvent</a> renamed to <a
577
+ href="MIDI/NoteOn.html">MIDI::NoteOn</a> and <a
578
+ href="MIDI/NoteOff.html">MIDI::NoteOff</a>. The old names will still work
579
+ for a while.</p>
580
+
581
+ <p>The <a href="MIDI/Event.html">MIDI::Event</a> boolean methods like meta?
582
+ and note? have been removed. Use the event classes themselves (for example,
583
+ <a href="MIDI/MetaEvent.html">MIDI::MetaEvent</a> === my_event or
584
+ my_event.kind_of?(<a href="MIDI/MetaEvent.html">MIDI::MetaEvent</a>)). Case
585
+ statements that use classes work, too:</p>
586
+
587
+ <pre>case my_event
588
+ when MIDI::NoteEvent # superclass of note on, note off, poly press
589
+ do_this()
590
+ when MIDI::Controller
591
+ do_that()
592
+ end</pre>
593
+
594
+ <p>Introduced Adam Murray's stable sorting code for <a
595
+ href="MIDI/Track.html#method-i-recalc_delta_from_times">MIDI::Track#recalc_delta_from_times</a>.
596
+ See <a
597
+ href="http://wiki.github.com/adamjmurray/cosy/midilib-notes">wiki.github.com/adamjmurray/cosy/midilib-notes</a>
598
+ and <a
599
+ href="http://github.com/adamjmurray/cosy/blob/master/lib/cosy/helper/midi_file_renderer_helper.rb">github.com/adamjmurray/cosy/blob/master/lib/cosy/helper/midi_file_renderer_helper.rb</a>
600
+ for details.</p>
601
+
602
+ <p>Aliased <a href="MIDI/Track.html#method-i-sort">MIDI::Track#sort</a> to <a
603
+ href="MIDI/Track.html#method-i-recalc_delta_from_times">MIDI::Track#recalc_delta_from_times</a>,
604
+ since all sort did was sort the events then call recalc_delta_from_times,
605
+ and recalc_delta_from_times sorts the events before doing anything else.</p>
606
+
607
+ <p>MIDI::Tempo#mpq_to_bpm now returns a float.</p>
608
+
609
+ <h3 id="label-Changes+for+1.2.0%3A">Changes for 1.2.0:</h3>
610
+
611
+ <p>Use byte arrays instead of strings for passing around data. All tests now
612
+ pass for both Ruby 1.8.X and 1.9.X.</p>
613
+
614
+ <h3 id="label-New+code+repository">New code repository</h3>
615
+
616
+ <p>The midilib code is now hosted at Github (<a
617
+ href="http://github.com/jimm/midilib">github.com/jimm/midilib</a>).</p>
618
+
619
+ <h3 id="label-Changes+for+1.1.4%3A">Changes for 1.1.4:</h3>
620
+ <ul><li>
621
+ <p>Fixed a bug in KeySig.data_as_bytes. Thanks to Noah Thorp for finding this
622
+ and the bug fixed in 1.1.3.</p>
623
+ </li></ul>
624
+
625
+ <h3 id="label-Changes+for+1.1.3%3A">Changes for 1.1.3:</h3>
626
+ <ul><li>
627
+ <p>Fixed the way midilib detects the behavior of IO.getc.</p>
628
+ </li></ul>
629
+
630
+ <h3 id="label-Changes+for+1.1.2%3A">Changes for 1.1.2:</h3>
631
+ <ul><li>
632
+ <p>Define <a
633
+ href="MIDI/IO/MIDIFile.html#method-i-getc">MIDI::IO::MIDIFile#getc</a>
634
+ differently for different Ruby versions, instead of checking for
635
+ String.bytes every time we read a byte.</p>
636
+ </li></ul>
637
+
638
+ <h3 id="label-Changes+for+1.1.1%3A">Changes for 1.1.1:</h3>
639
+ <ul><li>
640
+ <p>Make <a
641
+ href="MIDI/IO/MIDIFile.html#method-i-getc">MIDI::IO::MIDIFile#getc</a> do
642
+ the right thing for both Ruby 1.8 and 1.9.</p>
643
+ </li></ul>
644
+
645
+ <h3 id="label-Changes+for+1.1.0%3A">Changes for 1.1.0:</h3>
646
+ <ul><li>
647
+ <p>Added test/test.mid to list of files to be included when packaging midifile
648
+ for distribution.</p>
649
+ </li></ul>
650
+
651
+ <h3 id="label-Changes+for+1.0.0%3A">Changes for 1.0.0:</h3>
652
+ <ul><li>
653
+ <p>Fixed the bug in Track#recalc_delta_from_times found by Christopher Rose.</p>
654
+ </li></ul>
655
+
656
+ <h3 id="label-Changes+for+0.8.7%3A">Changes for 0.8.7:</h3>
657
+ <ul><li>
658
+ <p>Fixed the misspelled POLY_PRESSURE constant, thanks to Mario Pehle.</p>
659
+ </li></ul>
660
+
661
+ <h3 id="label-Changes+for+0.8.6%3A">Changes for 0.8.6:</h3>
662
+ <ul><li>
663
+ <p>Added missing test/test.mid.</p>
664
+ </li></ul>
665
+
666
+ <h3 id="label-Changes+for+0.8.5%3A">Changes for 0.8.5:</h3>
667
+ <ul><li>
668
+ <p>Fixed bugs in <a href="MIDI/PitchBend.html">MIDI::PitchBend</a> reading and
669
+ writing, thanks to Emanuel Borsboom.</p>
670
+ </li><li>
671
+ <p>Fixed a bug in <a
672
+ href="MIDI/Track.html#method-i-quantize">MIDI::Track#quantize</a>.</p>
673
+ </li><li>
674
+ <p>The argument to <a
675
+ href="MIDI/Track.html#method-i-quantize">MIDI::Track#quantize</a> has
676
+ changed: it is now either a note name ("sixteenth", "32nd", "8th triplet")
677
+ or a length (1 = quarter, 0.25 = sixteenth). This is a drastic change that
678
+ will break all previous calls to quantize. However, since that method was
679
+ broken already, I don't feel it's a burden to anybody to change the
680
+ arguments.</p>
681
+ </li></ul>
682
+
683
+ <h3 id="label-Changes+for+0.8.4%3A">Changes for 0.8.4:</h3>
684
+ <ul><li>
685
+ <p>Realtime status bytes now set @is_realtime to true and return true when
686
+ realtime? is called.</p>
687
+ </li><li>
688
+ <p>All system common events now set @is_system to true and return true when
689
+ system? is called, not just system exclusive events.</p>
690
+ </li><li>
691
+ <p>Added examples/from_scratch.rb, which shows how to create a sequence
692
+ manually.</p>
693
+ </li><li>
694
+ <p>New <a href="MIDI/Sequence.html">MIDI::Sequence</a> methods that turn note
695
+ length names like "32nd", "dotted quarter", and "16th triplet" into delta
696
+ times. See the docs below and MIDI::Sequence::length_to_delta,
697
+ MIDI::Sequence::note_to_length, and MIDI::Sequence::note_to_delta.</p>
698
+ </li></ul>
699
+
700
+ <h3 id="label-Changes+for+0.8.3%3A">Changes for 0.8.3:</h3>
701
+ <ul><li>
702
+ <p>Added <a
703
+ href="MIDI/NoteEvent.html#method-i-note_to_s">MIDI::NoteEvent#note_to_s</a>,
704
+ which returns note name as a string like "C4" or "F#6".</p>
705
+ </li><li>
706
+ <p>Added new boolean attributes to MIDI::Event: @print_decimal_numbers and
707
+ @print_note_names. These are used by all Event to_s methods. See
708
+ examples/seq2text.rb for an example.</p>
709
+ </li></ul>
710
+
711
+ <h3 id="label-Changes+for+0.8.2%3A">Changes for 0.8.2:</h3>
712
+ <ul><li>
713
+ <p>Changed MIDI::MetaEvent.type to MIDI::MetaEvent.event_type to avoid runtime
714
+ complaints about Object#type calls.</p>
715
+ </li><li>
716
+ <p>Added 'b' binary flag to file open modes for Windows.</p>
717
+ </li><li>
718
+ <p>Fixed $LOAD_PATH in example files.</p>
719
+ </li><li>
720
+ <p>Fixed read and write block arguments.</p>
721
+ </li><li>
722
+ <p>Fixed other example script bugs.</p>
723
+ </li></ul>
724
+
725
+ <h3 id="label-Changes+for+0.8.1%3A">Changes for 0.8.1:</h3>
726
+ <ul><li>
727
+ <p>Fixed track sorting.</p>
728
+ </li><li>
729
+ <p>Fixed track's recalc_delta_from_times method.</p>
730
+ </li><li>
731
+ <p>Fixed event quantization.</p>
732
+ </li><li>
733
+ <p>More tests and documentation.</p>
734
+ </li></ul>
735
+
736
+ <h2 id="label-Warranty">Warranty</h2>
737
+
738
+ <p>This software is provided "as is" and without any express or implied
739
+ warranties, including, without limitation, the implied warranties of
740
+ merchantability and fitness for a particular purpose.</p>
741
+
742
+ </div>
743
+
744
+
745
+
746
+ <footer id="validator-badges">
747
+ <p><a href="http://validator.w3.org/check/referer">[Validate]</a>
748
+ <p>Generated by <a href="https://github.com/rdoc/rdoc">RDoc</a> 3.12.
749
+ <p>Generated with the <a href="http://deveiate.org/projects/Darkfish-Rdoc/">Darkfish Rdoc Generator</a> 3.
750
+ </footer>
751
+