midilib 2.0.5 → 3.0.1

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 (124) hide show
  1. checksums.yaml +5 -5
  2. data/ChangeLog +2 -1
  3. data/Credits +39 -2
  4. data/README.rdoc +5 -6
  5. data/Rakefile +36 -49
  6. data/TODO.rdoc +13 -2
  7. data/examples/from_scratch.rb +1 -1
  8. data/examples/measures_mbt.rb +11 -11
  9. data/examples/print_program_changes.rb +2 -2
  10. data/examples/reader2text.rb +47 -47
  11. data/examples/seq2text.rb +1 -1
  12. data/examples/split.rb +4 -3
  13. data/examples/strings.rb +4 -4
  14. data/examples/transpose.rb +19 -20
  15. data/install.rb +21 -13
  16. data/lib/midilib/consts.rb +237 -239
  17. data/lib/midilib/event.rb +128 -100
  18. data/lib/midilib/info.rb +3 -5
  19. data/lib/midilib/io/midifile.rb +155 -182
  20. data/lib/midilib/io/seqreader.rb +80 -85
  21. data/lib/midilib/io/seqwriter.rb +93 -88
  22. data/lib/midilib/measure.rb +78 -80
  23. data/lib/midilib/mergesort.rb +39 -0
  24. data/lib/midilib/sequence.rb +40 -32
  25. data/lib/midilib/track.rb +16 -57
  26. data/lib/midilib/utils.rb +4 -7
  27. data/lib/midilib.rb +5 -5
  28. data/test/event_equality.rb +28 -30
  29. data/test/test_event.rb +9 -11
  30. data/test/test_io.rb +83 -3
  31. data/test/test_mergesort.rb +37 -0
  32. data/test/test_midifile.rb +6 -19
  33. data/test/test_sequence.rb +5 -4
  34. data/test/test_track.rb +9 -38
  35. data/test/test_varlen.rb +1 -3
  36. metadata +8 -95
  37. data/html/IO.html +0 -155
  38. data/html/MIDI/ActiveSense.html +0 -206
  39. data/html/MIDI/ChannelEvent.html +0 -231
  40. data/html/MIDI/ChannelPressure.html +0 -265
  41. data/html/MIDI/Clock.html +0 -206
  42. data/html/MIDI/Continue.html +0 -206
  43. data/html/MIDI/Controller.html +0 -280
  44. data/html/MIDI/Event.html +0 -489
  45. data/html/MIDI/IO/MIDIFile.html +0 -2024
  46. data/html/MIDI/IO/SeqReader.html +0 -904
  47. data/html/MIDI/IO/SeqWriter.html +0 -572
  48. data/html/MIDI/IO.html +0 -95
  49. data/html/MIDI/KeySig.html +0 -353
  50. data/html/MIDI/MIDI/MIDI/Array.html +0 -255
  51. data/html/MIDI/MIDI/MIDI.html +0 -95
  52. data/html/MIDI/MIDI.html +0 -95
  53. data/html/MIDI/Marker.html +0 -158
  54. data/html/MIDI/Measure.html +0 -328
  55. data/html/MIDI/Measures.html +0 -285
  56. data/html/MIDI/MetaEvent.html +0 -461
  57. data/html/MIDI/NoteEvent.html +0 -331
  58. data/html/MIDI/NoteOff.html +0 -228
  59. data/html/MIDI/NoteOn.html +0 -228
  60. data/html/MIDI/PitchBend.html +0 -266
  61. data/html/MIDI/PolyPressure.html +0 -277
  62. data/html/MIDI/ProgramChange.html +0 -265
  63. data/html/MIDI/Realtime.html +0 -242
  64. data/html/MIDI/Sequence.html +0 -896
  65. data/html/MIDI/SongPointer.html +0 -266
  66. data/html/MIDI/SongSelect.html +0 -265
  67. data/html/MIDI/Start.html +0 -206
  68. data/html/MIDI/Stop.html +0 -206
  69. data/html/MIDI/SystemCommon.html +0 -158
  70. data/html/MIDI/SystemExclusive.html +0 -268
  71. data/html/MIDI/SystemReset.html +0 -206
  72. data/html/MIDI/Tempo.html +0 -396
  73. data/html/MIDI/TimeSig.html +0 -388
  74. data/html/MIDI/Track.html +0 -695
  75. data/html/MIDI/TuneRequest.html +0 -242
  76. data/html/MIDI/Utils.html +0 -220
  77. data/html/MIDI.html +0 -547
  78. data/html/README_rdoc.html +0 -731
  79. data/html/TODO_rdoc.html +0 -125
  80. data/html/created.rid +0 -14
  81. data/html/css/fonts.css +0 -167
  82. data/html/css/rdoc.css +0 -590
  83. data/html/fonts/Lato-Light.ttf +0 -0
  84. data/html/fonts/Lato-LightItalic.ttf +0 -0
  85. data/html/fonts/Lato-Regular.ttf +0 -0
  86. data/html/fonts/Lato-RegularItalic.ttf +0 -0
  87. data/html/fonts/SourceCodePro-Bold.ttf +0 -0
  88. data/html/fonts/SourceCodePro-Regular.ttf +0 -0
  89. data/html/images/add.png +0 -0
  90. data/html/images/arrow_up.png +0 -0
  91. data/html/images/brick.png +0 -0
  92. data/html/images/brick_link.png +0 -0
  93. data/html/images/bug.png +0 -0
  94. data/html/images/bullet_black.png +0 -0
  95. data/html/images/bullet_toggle_minus.png +0 -0
  96. data/html/images/bullet_toggle_plus.png +0 -0
  97. data/html/images/date.png +0 -0
  98. data/html/images/delete.png +0 -0
  99. data/html/images/find.png +0 -0
  100. data/html/images/loadingAnimation.gif +0 -0
  101. data/html/images/macFFBgHack.png +0 -0
  102. data/html/images/package.png +0 -0
  103. data/html/images/page_green.png +0 -0
  104. data/html/images/page_white_text.png +0 -0
  105. data/html/images/page_white_width.png +0 -0
  106. data/html/images/plugin.png +0 -0
  107. data/html/images/ruby.png +0 -0
  108. data/html/images/tag_blue.png +0 -0
  109. data/html/images/tag_green.png +0 -0
  110. data/html/images/transparent.png +0 -0
  111. data/html/images/wrench.png +0 -0
  112. data/html/images/wrench_orange.png +0 -0
  113. data/html/images/zoom.png +0 -0
  114. data/html/index.html +0 -768
  115. data/html/js/darkfish.js +0 -161
  116. data/html/js/jquery.js +0 -4
  117. data/html/js/navigation.js +0 -142
  118. data/html/js/navigation.js.gz +0 -0
  119. data/html/js/search.js +0 -109
  120. data/html/js/search_index.js +0 -1
  121. data/html/js/search_index.js.gz +0 -0
  122. data/html/js/searcher.js +0 -228
  123. data/html/js/searcher.js.gz +0 -0
  124. data/html/table_of_contents.html +0 -1265
data/lib/midilib/event.rb CHANGED
@@ -1,11 +1,9 @@
1
- require 'midilib/consts'
2
- require 'midilib/utils'
1
+ require_relative 'consts'
2
+ require_relative 'utils'
3
3
 
4
4
  module MIDI
5
-
6
5
  # The abstract superclass of all MIDI events.
7
6
  class Event
8
-
9
7
  # Modifying delta_time does not affect time_from_start. You need to call
10
8
  # the event's track's +recalc_time+ method.
11
9
  attr_accessor :delta_time
@@ -31,7 +29,10 @@ module MIDI
31
29
  def initialize(status = 0, delta_time = 0)
32
30
  @status = status
33
31
  @delta_time = delta_time
34
- @time_from_start = 0 # maintained by tracks
32
+ @time_from_start = 0 # maintained by tracks
33
+ @print_note_names = false
34
+ @print_decimal_numbers = false
35
+ @print_channel_numbers_from_one = false
35
36
  end
36
37
  protected :initialize
37
38
 
@@ -39,7 +40,7 @@ module MIDI
39
40
  # MIDI stream. In MIDI::EVENT this raises a "subclass responsibility"
40
41
  # exception.
41
42
  def data_as_bytes
42
- raise "subclass responsibility"
43
+ raise 'subclass responsibility'
43
44
  end
44
45
 
45
46
  # Quantize this event's time_from_start by moving it to the nearest
@@ -49,29 +50,27 @@ module MIDI
49
50
  def quantize_to(boundary)
50
51
  diff = @time_from_start % boundary
51
52
  @time_from_start -= diff
52
- if diff >= boundary / 2
53
- @time_from_start += boundary
54
- end
53
+ @time_from_start += boundary if diff >= boundary / 2
55
54
  end
56
55
 
57
56
  # For sorting. Uses @time_from_start, which is maintained by this event's
58
57
  # track. I'm not sure this is necessary, since each track has to
59
58
  # maintain its events' time-from-start values anyway.
60
- def <=>(an_event)
61
- return @time_from_start <=> an_event.time_from_start
59
+ def <=>(other)
60
+ @time_from_start <=> other.time_from_start
62
61
  end
63
62
 
64
63
  # Returns +val+ as a decimal or hex string, depending upon the value of
65
64
  # @print_decimal_numbers.
66
65
  def number_to_s(val)
67
- return @print_decimal_numbers ? val.to_s : ('%02x' % val)
66
+ @print_decimal_numbers ? val.to_s : ('%02x' % val)
68
67
  end
69
68
 
70
69
  # Returns +val+ as a decimal or hex string, depending upon the value of
71
70
  # @print_decimal_numbers.
72
71
  def channel_to_s(val)
73
72
  val += 1 if @print_channel_numbers_from_one
74
- return number_to_s(val)
73
+ number_to_s(val)
75
74
  end
76
75
 
77
76
  def to_s
@@ -92,15 +91,15 @@ module MIDI
92
91
  protected :initialize
93
92
 
94
93
  def to_s
95
- return super << "ch #{channel_to_s(@channel)} "
94
+ super << "ch #{channel_to_s(@channel)} "
96
95
  end
97
-
98
96
  end
99
97
 
100
98
  # The abstract superclass of all note on, and note off, and polyphonic
101
99
  # pressure events.
102
100
  class NoteEvent < ChannelEvent
103
101
  attr_accessor :note, :velocity
102
+
104
103
  def initialize(status, channel, note, velocity, delta_time)
105
104
  super(status, channel, delta_time)
106
105
  @note = note
@@ -108,10 +107,10 @@ module MIDI
108
107
  end
109
108
  protected :initialize
110
109
 
111
- PITCHES = %w(C C# D D# E F F# G G# A A# B)
110
+ PITCHES = %w[C C# D D# E F F# G G# A A# B]
112
111
 
113
112
  # Returns note name as a pitch/octave string like "C4" or "F#6".
114
- def pch_oct(val=@note)
113
+ def pch_oct(val = @note)
115
114
  pch = val % 12
116
115
  oct = (val / 12) - 1
117
116
  "#{PITCHES[pch]}#{oct}"
@@ -120,7 +119,7 @@ module MIDI
120
119
  # If @print_note_names is true, returns pch_oct(val) else returns value
121
120
  # as a number using number_to_s.
122
121
  def note_to_s
123
- return @print_note_names ? pch_oct(@note) : number_to_s(@note)
122
+ @print_note_names ? pch_oct(@note) : number_to_s(@note)
124
123
  end
125
124
 
126
125
  def data_as_bytes
@@ -133,12 +132,13 @@ module MIDI
133
132
 
134
133
  class NoteOn < NoteEvent
135
134
  attr_accessor :off
135
+
136
136
  def initialize(channel = 0, note = 64, velocity = 64, delta_time = 0)
137
137
  super(NOTE_ON, channel, note, velocity, delta_time)
138
138
  end
139
139
 
140
140
  def to_s
141
- return super <<
141
+ super <<
142
142
  "on #{note_to_s} #{number_to_s(@velocity)}"
143
143
  end
144
144
  end
@@ -148,12 +148,13 @@ module MIDI
148
148
 
149
149
  class NoteOff < NoteEvent
150
150
  attr_accessor :on
151
+
151
152
  def initialize(channel = 0, note = 64, velocity = 64, delta_time = 0)
152
153
  super(NOTE_OFF, channel, note, velocity, delta_time)
153
154
  end
154
155
 
155
156
  def to_s
156
- return super <<
157
+ super <<
157
158
  "off #{note_to_s} #{number_to_s(@velocity)}"
158
159
  end
159
160
  end
@@ -167,13 +168,15 @@ module MIDI
167
168
  end
168
169
 
169
170
  def pressure
170
- return @velocity
171
+ @velocity
171
172
  end
173
+
172
174
  def pressure=(val)
173
175
  @velocity = val
174
176
  end
177
+
175
178
  def to_s
176
- return super <<
179
+ super <<
177
180
  "poly press #{channel_to_s(@channel)} #{note_to_s} #{number_to_s(@velocity)}"
178
181
  end
179
182
  end
@@ -195,7 +198,7 @@ module MIDI
195
198
  end
196
199
 
197
200
  def to_s
198
- return super << "cntl #{number_to_s(@controller)} #{number_to_s(@value)}"
201
+ super << "cntl #{number_to_s(@controller)} #{number_to_s(@value)}"
199
202
  end
200
203
  end
201
204
 
@@ -214,7 +217,7 @@ module MIDI
214
217
  end
215
218
 
216
219
  def to_s
217
- return super << "prog #{number_to_s(@program)}"
220
+ super << "prog #{number_to_s(@program)}"
218
221
  end
219
222
  end
220
223
 
@@ -233,7 +236,7 @@ module MIDI
233
236
  end
234
237
 
235
238
  def to_s
236
- return super << "chan press #{number_to_s(@pressure)}"
239
+ super << "chan press #{number_to_s(@pressure)}"
237
240
  end
238
241
  end
239
242
 
@@ -253,7 +256,7 @@ module MIDI
253
256
  end
254
257
 
255
258
  def to_s
256
- return super << "pb #{number_to_s(@value)}"
259
+ super << "pb #{number_to_s(@value)}"
257
260
  end
258
261
  end
259
262
 
@@ -281,7 +284,7 @@ module MIDI
281
284
  end
282
285
 
283
286
  def to_s
284
- return super << "sys ex"
287
+ super << 'sys ex'
285
288
  end
286
289
  end
287
290
 
@@ -301,7 +304,7 @@ module MIDI
301
304
  end
302
305
 
303
306
  def to_s
304
- return super << "song ptr #{number_to_s(@pointer)}"
307
+ super << "song ptr #{number_to_s(@pointer)}"
305
308
  end
306
309
  end
307
310
 
@@ -320,7 +323,7 @@ module MIDI
320
323
  end
321
324
 
322
325
  def to_s
323
- return super << "song sel #{number_to_s(@song)}"
326
+ super << "song sel #{number_to_s(@song)}"
324
327
  end
325
328
  end
326
329
 
@@ -335,7 +338,7 @@ module MIDI
335
338
  end
336
339
 
337
340
  def to_s
338
- return super << "tune req"
341
+ super << 'tune req'
339
342
  end
340
343
  end
341
344
 
@@ -350,7 +353,7 @@ module MIDI
350
353
  end
351
354
 
352
355
  def to_s
353
- return super << "realtime #{number_to_s(@status)}"
356
+ super << "realtime #{number_to_s(@status)}"
354
357
  end
355
358
  end
356
359
 
@@ -360,7 +363,7 @@ module MIDI
360
363
  end
361
364
 
362
365
  def to_s
363
- return super << "clock"
366
+ super << 'clock'
364
367
  end
365
368
  end
366
369
 
@@ -368,8 +371,9 @@ module MIDI
368
371
  def initialize(delta_time = 0)
369
372
  super(START, delta_time)
370
373
  end
374
+
371
375
  def to_s
372
- return super << "start"
376
+ super << 'start'
373
377
  end
374
378
  end
375
379
 
@@ -377,8 +381,9 @@ module MIDI
377
381
  def initialize(delta_time = 0)
378
382
  super(CONTINUE, delta_time)
379
383
  end
384
+
380
385
  def to_s
381
- return super << "continue"
386
+ super << 'continue'
382
387
  end
383
388
  end
384
389
 
@@ -386,8 +391,9 @@ module MIDI
386
391
  def initialize(delta_time = 0)
387
392
  super(STOP, delta_time)
388
393
  end
394
+
389
395
  def to_s
390
- return super << "stop"
396
+ super << 'stop'
391
397
  end
392
398
  end
393
399
 
@@ -395,8 +401,9 @@ module MIDI
395
401
  def initialize(delta_time = 0)
396
402
  super(ACTIVE_SENSE, delta_time)
397
403
  end
404
+
398
405
  def to_s
399
- return super << "act sens"
406
+ super << 'act sens'
400
407
  end
401
408
  end
402
409
 
@@ -404,33 +411,27 @@ module MIDI
404
411
  def initialize(delta_time = 0)
405
412
  super(SYSTEM_RESET, delta_time)
406
413
  end
414
+
407
415
  def to_s
408
- return super << "sys reset"
416
+ super << 'sys reset'
409
417
  end
410
418
  end
411
419
 
412
420
  class MetaEvent < Event
413
- attr_reader :meta_type
414
- attr_reader :data
421
+ attr_reader :meta_type, :data
415
422
 
416
423
  def self.bytes_as_str(bytes)
417
424
  bytes ? bytes.collect { |byte| byte.chr }.join : nil
418
425
  end
419
426
 
420
- if RUBY_VERSION >= '1.9'
421
- def self.str_as_bytes(str)
422
- str.split(//).collect { |chr| chr.ord }
423
- end
424
- else
425
- def self.str_as_bytes(str)
426
- str.split(//).collect { |chr| chr[0] }
427
- end
427
+ def self.str_as_bytes(str)
428
+ str.split(//).collect { |chr| chr.ord }
428
429
  end
429
430
 
430
431
  def initialize(meta_type, data = nil, delta_time = 0)
431
432
  super(META_EVENT, delta_time)
432
433
  @meta_type = meta_type
433
- self.data=(data)
434
+ self.data = (data)
434
435
  end
435
436
 
436
437
  def data_as_bytes
@@ -448,50 +449,50 @@ module MIDI
448
449
 
449
450
  # Stores bytes. If data is a string, splits it into an array of bytes.
450
451
  def data=(data)
451
- case data
452
- when String
453
- @data = MetaEvent.str_as_bytes(data)
454
- else
455
- @data = data
456
- end
452
+ @data = case data
453
+ when String
454
+ MetaEvent.str_as_bytes(data)
455
+ else
456
+ data
457
+ end
457
458
  end
458
459
 
459
460
  def to_s
460
461
  str = super()
461
462
  str << "meta #{number_to_s(@meta_type)} "
462
463
  # I know, I know...this isn't OO.
463
- case @meta_type
464
- when META_SEQ_NUM
465
- str << "sequence number"
466
- when META_TEXT
467
- str << "text: #{data_as_str}"
468
- when META_COPYRIGHT
469
- str << "copyright: #{data_as_str}"
470
- when META_SEQ_NAME
471
- str << "sequence or track name: #{data_as_str}"
472
- when META_INSTRUMENT
473
- str << "instrument name: #{data_as_str}"
474
- when META_LYRIC
475
- str << "lyric: #{data_as_str}"
476
- when META_MARKER
477
- str << "marker: #{data_as_str}"
478
- when META_CUE
479
- str << "cue point: #{@data}"
480
- when META_TRACK_END
481
- str << "track end"
482
- when META_SMPTE
483
- str << "smpte"
484
- when META_TIME_SIG
485
- str << "time signature"
486
- when META_KEY_SIG
487
- str << "key signature"
488
- when META_SEQ_SPECIF
489
- str << "sequence specific"
490
- else
491
- # Some other possible @meta_type values are handled by subclasses.
492
- str << "(other)"
493
- end
494
- return str
464
+ str << case @meta_type
465
+ when META_SEQ_NUM
466
+ 'sequence number'
467
+ when META_TEXT
468
+ "text: #{data_as_str}"
469
+ when META_COPYRIGHT
470
+ "copyright: #{data_as_str}"
471
+ when META_SEQ_NAME
472
+ "sequence or track name: #{data_as_str}"
473
+ when META_INSTRUMENT
474
+ "instrument name: #{data_as_str}"
475
+ when META_LYRIC
476
+ "lyric: #{data_as_str}"
477
+ when META_MARKER
478
+ "marker: #{data_as_str}"
479
+ when META_CUE
480
+ "cue point: #{@data}"
481
+ when META_TRACK_END
482
+ 'track end'
483
+ when META_SMPTE
484
+ 'smpte'
485
+ when META_TIME_SIG
486
+ 'time signature'
487
+ when META_KEY_SIG
488
+ 'key signature'
489
+ when META_SEQ_SPECIF
490
+ 'sequence specific'
491
+ else
492
+ # Some other possible @meta_type values are handled by subclasses.
493
+ '(other)'
494
+ end
495
+ str
495
496
  end
496
497
  end
497
498
 
@@ -502,17 +503,16 @@ module MIDI
502
503
  end
503
504
 
504
505
  class Tempo < MetaEvent
505
-
506
506
  MICROSECS_PER_MINUTE = 1_000_000 * 60
507
507
 
508
508
  # Translates beats per minute to microseconds per quarter note (beat).
509
- def Tempo.bpm_to_mpq(bpm)
510
- return MICROSECS_PER_MINUTE / bpm
509
+ def self.bpm_to_mpq(bpm)
510
+ MICROSECS_PER_MINUTE / bpm
511
511
  end
512
512
 
513
513
  # Translates microseconds per quarter note (beat) to beats per minute.
514
- def Tempo.mpq_to_bpm(mpq)
515
- return MICROSECS_PER_MINUTE.to_f / mpq.to_f
514
+ def self.mpq_to_bpm(mpq)
515
+ MICROSECS_PER_MINUTE.to_f / mpq.to_f
516
516
  end
517
517
 
518
518
  def initialize(msecs_per_qnote, delta_time = 0)
@@ -520,7 +520,7 @@ module MIDI
520
520
  end
521
521
 
522
522
  def tempo
523
- return @data
523
+ @data
524
524
  end
525
525
 
526
526
  def tempo=(val)
@@ -544,7 +544,6 @@ module MIDI
544
544
 
545
545
  # Container for time signature events
546
546
  class TimeSig < MetaEvent
547
-
548
547
  # Constructor
549
548
  def initialize(numer, denom, clocks, qnotes, delta_time = 0)
550
549
  super(META_TIME_SIG, [numer, denom, clocks, qnotes], delta_time)
@@ -593,7 +592,6 @@ module MIDI
593
592
 
594
593
  # Container for key signature events
595
594
  class KeySig < MetaEvent
596
-
597
595
  # Constructor
598
596
  def initialize(sharpflat, is_minor, delta_time = 0)
599
597
  super(META_KEY_SIG, [sharpflat, is_minor], delta_time)
@@ -627,13 +625,43 @@ module MIDI
627
625
  # Returns the key signature as a text string.
628
626
  # Example: "key sig A flat major"
629
627
  def to_s
630
- majorkeys = ['C flat', 'G flat', 'D flat', 'A flat', 'E flat', 'B flat', 'F',
631
- 'C', 'G', 'D', 'A', 'E', 'B', 'F#', 'C#']
632
- minorkeys = ['a flat', 'e flat', 'b flat', 'f', 'c', 'g', 'd',
633
- 'a', 'e', 'b', 'f#', 'c#', 'g#', 'd#', 'a#']
634
- minor_key? ? "key sig #{minorkeys[sharpflat + 7]} minor" :
628
+ if minor_key?
629
+ "key sig #{minorkeys[sharpflat + 7]} minor"
630
+ else
635
631
  "key sig #{majorkeys[sharpflat + 7]} major"
632
+ end
633
+ end
634
+
635
+ # Returns the key signature as a code.
636
+ # Example: "Ab" for "key sig A flat major"
637
+ def to_code
638
+ if minor_key?
639
+ minorkey_codes[sharpflat + 7]
640
+ else
641
+ majorkey_codes[sharpflat + 7]
642
+ end
636
643
  end
637
- end
638
644
 
645
+ private
646
+
647
+ def majorkeys
648
+ @majorkeys ||= ['C flat', 'G flat', 'D flat', 'A flat', 'E flat', 'B flat', 'F',
649
+ 'C', 'G', 'D', 'A', 'E', 'B', 'F#', 'C#']
650
+ end
651
+
652
+ def minorkeys
653
+ @minorkeys ||= ['a flat', 'e flat', 'b flat', 'f', 'c', 'g', 'd',
654
+ 'a', 'e', 'b', 'f#', 'c#', 'g#', 'd#', 'a#']
655
+ end
656
+
657
+ def majorkey_codes
658
+ @majorkeys_codes ||= ['Cb', 'Gb', 'Db', 'Ab', 'Eb', 'Bb', 'F',
659
+ 'C', 'G', 'D', 'A', 'E', 'B', 'F#', 'C#']
660
+ end
661
+
662
+ def minorkey_codes
663
+ @minorkeys_codes ||= ['Abm', 'Ebm', 'Bbm', 'Fm', 'Cm', 'Gm', 'Dm',
664
+ 'Am', 'Em', 'Bm', 'F#m', 'C#m', 'G#m', 'D#m', 'A#m']
665
+ end
666
+ end
639
667
  end
data/lib/midilib/info.rb CHANGED
@@ -1,9 +1,7 @@
1
1
  module MIDI
2
-
3
- VERSION_MAJOR = 2
2
+ VERSION_MAJOR = 3
4
3
  VERSION_MINOR = 0
5
- VERSION_TWEAK = 5
4
+ VERSION_TWEAK = 1
6
5
  Version = "#{VERSION_MAJOR}.#{VERSION_MINOR}.#{VERSION_TWEAK}"
7
- Copyright = 'Copyright (c) 2003-2015 by Jim Menard <jim@jimmenard.com>'
8
-
6
+ Copyright = 'Copyright (c) 2003-2022 by Jim Menard <jim@jimmenard.com>'
9
7
  end