midilib 2.0.2 → 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.
data/lib/midilib/event.rb CHANGED
@@ -1,10 +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
- # The abstract superclass of all MIDI events.
7
- class Event
5
+ # The abstract superclass of all MIDI events.
6
+ class Event
8
7
  # Modifying delta_time does not affect time_from_start. You need to call
9
8
  # the event's track's +recalc_time+ method.
10
9
  attr_accessor :delta_time
@@ -28,9 +27,12 @@ class Event
28
27
  attr_accessor :print_channel_numbers_from_one
29
28
 
30
29
  def initialize(status = 0, delta_time = 0)
31
- @status = status
32
- @delta_time = delta_time
33
- @time_from_start = 0 # maintained by tracks
30
+ @status = status
31
+ @delta_time = delta_time
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
34
36
  end
35
37
  protected :initialize
36
38
 
@@ -38,7 +40,7 @@ class Event
38
40
  # MIDI stream. In MIDI::EVENT this raises a "subclass responsibility"
39
41
  # exception.
40
42
  def data_as_bytes
41
- raise "subclass responsibility"
43
+ raise 'subclass responsibility'
42
44
  end
43
45
 
44
46
  # Quantize this event's time_from_start by moving it to the nearest
@@ -46,593 +48,620 @@ class Event
46
48
  # modify the event's delta_time, though MIDI::Track#quantize calls
47
49
  # recalc_delta_from_times after it asks each event to quantize itself.
48
50
  def quantize_to(boundary)
49
- diff = @time_from_start % boundary
50
- @time_from_start -= diff
51
- if diff >= boundary / 2
52
- @time_from_start += boundary
53
- end
51
+ diff = @time_from_start % boundary
52
+ @time_from_start -= diff
53
+ @time_from_start += boundary if diff >= boundary / 2
54
54
  end
55
55
 
56
56
  # For sorting. Uses @time_from_start, which is maintained by this event's
57
57
  # track. I'm not sure this is necessary, since each track has to
58
58
  # maintain its events' time-from-start values anyway.
59
- def <=>(an_event)
60
- return @time_from_start <=> an_event.time_from_start
59
+ def <=>(other)
60
+ @time_from_start <=> other.time_from_start
61
61
  end
62
62
 
63
63
  # Returns +val+ as a decimal or hex string, depending upon the value of
64
64
  # @print_decimal_numbers.
65
65
  def number_to_s(val)
66
- return @print_decimal_numbers ? val.to_s : ('%02x' % val)
66
+ @print_decimal_numbers ? val.to_s : ('%02x' % val)
67
67
  end
68
68
 
69
69
  # Returns +val+ as a decimal or hex string, depending upon the value of
70
70
  # @print_decimal_numbers.
71
71
  def channel_to_s(val)
72
- val += 1 if @print_channel_numbers_from_one
73
- return number_to_s(val)
72
+ val += 1 if @print_channel_numbers_from_one
73
+ number_to_s(val)
74
74
  end
75
75
 
76
76
  def to_s
77
- "#{@delta_time}: "
77
+ "#{@delta_time}: "
78
78
  end
79
- end
79
+ end
80
80
 
81
- # The abstract superclass of all channel events (events that have a MIDI
82
- # channel, like notes and program changes).
83
- class ChannelEvent < Event
81
+ # The abstract superclass of all channel events (events that have a MIDI
82
+ # channel, like notes and program changes).
83
+ class ChannelEvent < Event
84
84
  # MIDI channel, 0-15.
85
85
  attr_accessor :channel
86
86
 
87
87
  def initialize(status, channel, delta_time)
88
- super(status, delta_time)
89
- @channel = channel
88
+ super(status, delta_time)
89
+ @channel = channel
90
90
  end
91
91
  protected :initialize
92
92
 
93
93
  def to_s
94
- return super << "ch #{channel_to_s(@channel)} "
94
+ super << "ch #{channel_to_s(@channel)} "
95
95
  end
96
+ end
96
97
 
97
- end
98
-
99
- # The abstract superclass of all note on, and note off, and polyphonic
100
- # pressure events.
101
- class NoteEvent < ChannelEvent
98
+ # The abstract superclass of all note on, and note off, and polyphonic
99
+ # pressure events.
100
+ class NoteEvent < ChannelEvent
102
101
  attr_accessor :note, :velocity
102
+
103
103
  def initialize(status, channel, note, velocity, delta_time)
104
- super(status, channel, delta_time)
105
- @note = note
106
- @velocity = velocity
104
+ super(status, channel, delta_time)
105
+ @note = note
106
+ @velocity = velocity
107
107
  end
108
108
  protected :initialize
109
109
 
110
- 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]
111
111
 
112
112
  # Returns note name as a pitch/octave string like "C4" or "F#6".
113
- def pch_oct(val=@note)
114
- pch = val % 12
115
- oct = (val / 12) - 1
116
- "#{PITCHES[pch]}#{oct}"
113
+ def pch_oct(val = @note)
114
+ pch = val % 12
115
+ oct = (val / 12) - 1
116
+ "#{PITCHES[pch]}#{oct}"
117
117
  end
118
118
 
119
119
  # If @print_note_names is true, returns pch_oct(val) else returns value
120
120
  # as a number using number_to_s.
121
121
  def note_to_s
122
- return @print_note_names ? pch_oct(@note) : number_to_s(@note)
122
+ @print_note_names ? pch_oct(@note) : number_to_s(@note)
123
123
  end
124
124
 
125
125
  def data_as_bytes
126
- data = []
127
- data << (@status + @channel)
128
- data << @note
129
- data << @velocity
126
+ data = []
127
+ data << (@status + @channel)
128
+ data << @note
129
+ data << @velocity
130
130
  end
131
- end
131
+ end
132
132
 
133
- class NoteOn < NoteEvent
133
+ class NoteOn < NoteEvent
134
134
  attr_accessor :off
135
+
135
136
  def initialize(channel = 0, note = 64, velocity = 64, delta_time = 0)
136
- super(NOTE_ON, channel, note, velocity, delta_time)
137
+ super(NOTE_ON, channel, note, velocity, delta_time)
137
138
  end
138
139
 
139
140
  def to_s
140
- return super <<
141
- "on #{note_to_s} #{number_to_s(@velocity)}"
141
+ super <<
142
+ "on #{note_to_s} #{number_to_s(@velocity)}"
142
143
  end
143
- end
144
+ end
144
145
 
145
- # Old class name for compatability
146
- NoteOnEvent = NoteOn
146
+ # Old class name for compatability
147
+ NoteOnEvent = NoteOn
147
148
 
148
- class NoteOff < NoteEvent
149
+ class NoteOff < NoteEvent
149
150
  attr_accessor :on
151
+
150
152
  def initialize(channel = 0, note = 64, velocity = 64, delta_time = 0)
151
- super(NOTE_OFF, channel, note, velocity, delta_time)
153
+ super(NOTE_OFF, channel, note, velocity, delta_time)
152
154
  end
153
155
 
154
156
  def to_s
155
- return super <<
156
- "off #{note_to_s} #{number_to_s(@velocity)}"
157
+ super <<
158
+ "off #{note_to_s} #{number_to_s(@velocity)}"
157
159
  end
158
- end
160
+ end
159
161
 
160
- # Old class name for compatability
161
- NoteOffEvent = NoteOff
162
+ # Old class name for compatability
163
+ NoteOffEvent = NoteOff
162
164
 
163
- class PolyPressure < NoteEvent
165
+ class PolyPressure < NoteEvent
164
166
  def initialize(channel = 0, note = 64, value = 0, delta_time = 0)
165
- super(POLY_PRESSURE, channel, note, value, delta_time)
167
+ super(POLY_PRESSURE, channel, note, value, delta_time)
166
168
  end
167
169
 
168
170
  def pressure
169
- return @velocity
171
+ @velocity
170
172
  end
173
+
171
174
  def pressure=(val)
172
- @velocity = val
175
+ @velocity = val
173
176
  end
177
+
174
178
  def to_s
175
- return super <<
176
- "poly press #{channel_to_s(@channel)} #{note_to_s} #{number_to_s(@velocity)}"
179
+ super <<
180
+ "poly press #{channel_to_s(@channel)} #{note_to_s} #{number_to_s(@velocity)}"
177
181
  end
178
- end
182
+ end
179
183
 
180
- class Controller < ChannelEvent
184
+ class Controller < ChannelEvent
181
185
  attr_accessor :controller, :value
182
186
 
183
187
  def initialize(channel = 0, controller = 0, value = 0, delta_time = 0)
184
- super(CONTROLLER, channel, delta_time)
185
- @controller = controller
186
- @value = value
188
+ super(CONTROLLER, channel, delta_time)
189
+ @controller = controller
190
+ @value = value
187
191
  end
188
192
 
189
193
  def data_as_bytes
190
- data = []
191
- data << (@status + @channel)
192
- data << @controller
193
- data << @value
194
+ data = []
195
+ data << (@status + @channel)
196
+ data << @controller
197
+ data << @value
194
198
  end
195
199
 
196
200
  def to_s
197
- return super << "cntl #{number_to_s(@controller)} #{number_to_s(@value)}"
201
+ super << "cntl #{number_to_s(@controller)} #{number_to_s(@value)}"
198
202
  end
199
- end
203
+ end
200
204
 
201
- class ProgramChange < ChannelEvent
205
+ class ProgramChange < ChannelEvent
202
206
  attr_accessor :program
203
207
 
204
208
  def initialize(channel = 0, program = 0, delta_time = 0)
205
- super(PROGRAM_CHANGE, channel, delta_time)
206
- @program = program
209
+ super(PROGRAM_CHANGE, channel, delta_time)
210
+ @program = program
207
211
  end
208
212
 
209
213
  def data_as_bytes
210
- data = []
211
- data << (@status + @channel)
212
- data << @program
214
+ data = []
215
+ data << (@status + @channel)
216
+ data << @program
213
217
  end
214
218
 
215
219
  def to_s
216
- return super << "prog #{number_to_s(@program)}"
220
+ super << "prog #{number_to_s(@program)}"
217
221
  end
218
- end
222
+ end
219
223
 
220
- class ChannelPressure < ChannelEvent
224
+ class ChannelPressure < ChannelEvent
221
225
  attr_accessor :pressure
222
226
 
223
227
  def initialize(channel = 0, pressure = 0, delta_time = 0)
224
- super(CHANNEL_PRESSURE, channel, delta_time)
225
- @pressure = pressure
228
+ super(CHANNEL_PRESSURE, channel, delta_time)
229
+ @pressure = pressure
226
230
  end
227
231
 
228
232
  def data_as_bytes
229
- data = []
230
- data << (@status + @channel)
231
- data << @pressure
233
+ data = []
234
+ data << (@status + @channel)
235
+ data << @pressure
232
236
  end
233
237
 
234
238
  def to_s
235
- return super << "chan press #{number_to_s(@pressure)}"
239
+ super << "chan press #{number_to_s(@pressure)}"
236
240
  end
237
- end
241
+ end
238
242
 
239
- class PitchBend < ChannelEvent
243
+ class PitchBend < ChannelEvent
240
244
  attr_accessor :value
241
245
 
242
246
  def initialize(channel = 0, value = 0, delta_time = 0)
243
- super(PITCH_BEND, channel, delta_time)
244
- @value = value
247
+ super(PITCH_BEND, channel, delta_time)
248
+ @value = value
245
249
  end
246
250
 
247
251
  def data_as_bytes
248
- data = []
249
- data << (@status + @channel)
250
- data << (@value & 0x7f) # lsb
251
- data << ((@value >> 7) & 0x7f) # msb
252
+ data = []
253
+ data << (@status + @channel)
254
+ data << (@value & 0x7f) # lsb
255
+ data << ((@value >> 7) & 0x7f) # msb
252
256
  end
253
257
 
254
258
  def to_s
255
- return super << "pb #{number_to_s(@value)}"
259
+ super << "pb #{number_to_s(@value)}"
256
260
  end
257
- end
261
+ end
258
262
 
259
- class SystemCommon < Event
263
+ class SystemCommon < Event
260
264
  def initialize(status, delta_time)
261
- super(status, delta_time)
265
+ super(status, delta_time)
262
266
  end
263
- end
267
+ end
264
268
 
265
- class SystemExclusive < SystemCommon
269
+ class SystemExclusive < SystemCommon
266
270
  attr_accessor :data
267
271
 
268
272
  def initialize(data, delta_time = 0)
269
- super(SYSEX, delta_time)
270
- @data = data
273
+ super(SYSEX, delta_time)
274
+ @data = data
271
275
  end
272
276
 
273
277
  def data_as_bytes
274
- data = []
275
- data << @status
276
- data << Utils.as_var_len(@data.length)
277
- data << @data
278
- data << EOX
279
- data.flatten
278
+ data = []
279
+ data << @status
280
+ data << Utils.as_var_len(@data.length)
281
+ data << @data
282
+ data << EOX
283
+ data.flatten
280
284
  end
281
285
 
282
286
  def to_s
283
- return super << "sys ex"
287
+ super << 'sys ex'
284
288
  end
285
- end
289
+ end
286
290
 
287
- class SongPointer < SystemCommon
291
+ class SongPointer < SystemCommon
288
292
  attr_accessor :pointer
289
293
 
290
294
  def initialize(pointer = 0, delta_time = 0)
291
- super(SONG_POINTER, delta_time)
292
- @pointer = pointer
295
+ super(SONG_POINTER, delta_time)
296
+ @pointer = pointer
293
297
  end
294
298
 
295
299
  def data_as_bytes
296
- data = []
297
- data << @status
298
- data << ((@pointer >> 8) & 0xff)
299
- data << (@pointer & 0xff)
300
+ data = []
301
+ data << @status
302
+ data << ((@pointer >> 8) & 0xff)
303
+ data << (@pointer & 0xff)
300
304
  end
301
305
 
302
306
  def to_s
303
- return super << "song ptr #{number_to_s(@pointer)}"
307
+ super << "song ptr #{number_to_s(@pointer)}"
304
308
  end
305
- end
309
+ end
306
310
 
307
- class SongSelect < SystemCommon
311
+ class SongSelect < SystemCommon
308
312
  attr_accessor :song
309
313
 
310
314
  def initialize(song = 0, delta_time = 0)
311
- super(SONG_SELECT, delta_time)
312
- @song = song
315
+ super(SONG_SELECT, delta_time)
316
+ @song = song
313
317
  end
314
318
 
315
319
  def data_as_bytes
316
- data = []
317
- data << @status
318
- data << @song
320
+ data = []
321
+ data << @status
322
+ data << @song
319
323
  end
320
324
 
321
325
  def to_s
322
- return super << "song sel #{number_to_s(@song)}"
326
+ super << "song sel #{number_to_s(@song)}"
323
327
  end
324
- end
328
+ end
325
329
 
326
- class TuneRequest < SystemCommon
330
+ class TuneRequest < SystemCommon
327
331
  def initialize(delta_time = 0)
328
- super(TUNE_REQUEST, delta_time)
332
+ super(TUNE_REQUEST, delta_time)
329
333
  end
330
334
 
331
335
  def data_as_bytes
332
- data = []
333
- data << @status
336
+ data = []
337
+ data << @status
334
338
  end
335
339
 
336
340
  def to_s
337
- return super << "tune req"
341
+ super << 'tune req'
338
342
  end
339
- end
343
+ end
340
344
 
341
- class Realtime < Event
345
+ class Realtime < Event
342
346
  def initialize(status, delta_time)
343
- super(status, delta_time)
347
+ super(status, delta_time)
344
348
  end
345
349
 
346
350
  def data_as_bytes
347
- data = []
348
- data << @status
351
+ data = []
352
+ data << @status
349
353
  end
350
354
 
351
355
  def to_s
352
- return super << "realtime #{number_to_s(@status)}"
356
+ super << "realtime #{number_to_s(@status)}"
353
357
  end
354
- end
358
+ end
355
359
 
356
- class Clock < Realtime
360
+ class Clock < Realtime
357
361
  def initialize(delta_time = 0)
358
- super(CLOCK, delta_time)
362
+ super(CLOCK, delta_time)
359
363
  end
360
364
 
361
365
  def to_s
362
- return super << "clock"
366
+ super << 'clock'
363
367
  end
364
- end
368
+ end
365
369
 
366
- class Start < Realtime
370
+ class Start < Realtime
367
371
  def initialize(delta_time = 0)
368
- super(START, delta_time)
372
+ super(START, delta_time)
369
373
  end
374
+
370
375
  def to_s
371
- return super << "start"
376
+ super << 'start'
372
377
  end
373
- end
378
+ end
374
379
 
375
- class Continue < Realtime
380
+ class Continue < Realtime
376
381
  def initialize(delta_time = 0)
377
- super(CONTINUE, delta_time)
382
+ super(CONTINUE, delta_time)
378
383
  end
384
+
379
385
  def to_s
380
- return super << "continue"
386
+ super << 'continue'
381
387
  end
382
- end
388
+ end
383
389
 
384
- class Stop < Realtime
390
+ class Stop < Realtime
385
391
  def initialize(delta_time = 0)
386
- super(STOP, delta_time)
392
+ super(STOP, delta_time)
387
393
  end
394
+
388
395
  def to_s
389
- return super << "stop"
396
+ super << 'stop'
390
397
  end
391
- end
398
+ end
392
399
 
393
- class ActiveSense < Realtime
400
+ class ActiveSense < Realtime
394
401
  def initialize(delta_time = 0)
395
- super(ACTIVE_SENSE, delta_time)
402
+ super(ACTIVE_SENSE, delta_time)
396
403
  end
404
+
397
405
  def to_s
398
- return super << "act sens"
406
+ super << 'act sens'
399
407
  end
400
- end
408
+ end
401
409
 
402
- class SystemReset < Realtime
410
+ class SystemReset < Realtime
403
411
  def initialize(delta_time = 0)
404
- super(SYSTEM_RESET, delta_time)
412
+ super(SYSTEM_RESET, delta_time)
405
413
  end
414
+
406
415
  def to_s
407
- return super << "sys reset"
416
+ super << 'sys reset'
408
417
  end
409
- end
418
+ end
410
419
 
411
- class MetaEvent < Event
412
- attr_reader :meta_type
413
- attr_reader :data
420
+ class MetaEvent < Event
421
+ attr_reader :meta_type, :data
414
422
 
415
423
  def self.bytes_as_str(bytes)
416
- bytes ? bytes.collect { |byte| byte.chr }.join : nil
424
+ bytes ? bytes.collect { |byte| byte.chr }.join : nil
417
425
  end
418
426
 
419
- if RUBY_VERSION >= '1.9'
420
- def self.str_as_bytes(str)
421
- str.split(//).collect { |chr| chr.ord }
422
- end
423
- else
424
- def self.str_as_bytes(str)
425
- str.split(//).collect { |chr| chr[0] }
426
- end
427
+ def self.str_as_bytes(str)
428
+ str.split(//).collect { |chr| chr.ord }
427
429
  end
428
430
 
429
431
  def initialize(meta_type, data = nil, delta_time = 0)
430
- super(META_EVENT, delta_time)
431
- @meta_type = meta_type
432
- self.data=(data)
432
+ super(META_EVENT, delta_time)
433
+ @meta_type = meta_type
434
+ self.data = (data)
433
435
  end
434
436
 
435
437
  def data_as_bytes
436
- data = []
437
- data << @status
438
- data << @meta_type
439
- data << (@data ? Utils.as_var_len(@data.length) : 0)
440
- data << @data if @data
441
- data.flatten
438
+ data = []
439
+ data << @status
440
+ data << @meta_type
441
+ data << (@data ? Utils.as_var_len(@data.length) : 0)
442
+ data << @data if @data
443
+ data.flatten
442
444
  end
443
445
 
444
446
  def data_as_str
445
- MetaEvent.bytes_as_str(@data)
447
+ MetaEvent.bytes_as_str(@data)
446
448
  end
447
449
 
448
450
  # Stores bytes. If data is a string, splits it into an array of bytes.
449
451
  def data=(data)
450
- case data
451
- when String
452
- @data = MetaEvent.str_as_bytes(data)
453
- else
454
- @data = data
455
- end
452
+ @data = case data
453
+ when String
454
+ MetaEvent.str_as_bytes(data)
455
+ else
456
+ data
457
+ end
456
458
  end
457
459
 
458
460
  def to_s
459
- str = super()
460
- str << "meta #{number_to_s(@meta_type)} "
461
- # I know, I know...this isn't OO.
462
- case @meta_type
463
- when META_SEQ_NUM
464
- str << "sequence number"
465
- when META_TEXT
466
- str << "text: #{data_as_str}"
467
- when META_COPYRIGHT
468
- str << "copyright: #{data_as_str}"
469
- when META_SEQ_NAME
470
- str << "sequence or track name: #{data_as_str}"
471
- when META_INSTRUMENT
472
- str << "instrument name: #{data_as_str}"
473
- when META_LYRIC
474
- str << "lyric: #{data_as_str}"
475
- when META_MARKER
476
- str << "marker: #{data_as_str}"
477
- when META_CUE
478
- str << "cue point: #{@data}"
479
- when META_TRACK_END
480
- str << "track end"
481
- when META_SMPTE
482
- str << "smpte"
483
- when META_TIME_SIG
484
- str << "time signature"
485
- when META_KEY_SIG
486
- str << "key signature"
487
- when META_SEQ_SPECIF
488
- str << "sequence specific"
489
- else
490
- # Some other possible @meta_type values are handled by subclasses.
491
- str << "(other)"
492
- end
493
- return str
494
- end
495
- end
496
-
497
- class Marker < MetaEvent
461
+ str = super()
462
+ str << "meta #{number_to_s(@meta_type)} "
463
+ # I know, I know...this isn't OO.
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
496
+ end
497
+ end
498
+
499
+ class Marker < MetaEvent
498
500
  def initialize(msg, delta_time = 0)
499
- super(META_MARKER, msg, delta_time)
501
+ super(META_MARKER, msg, delta_time)
500
502
  end
501
- end
502
-
503
- class Tempo < MetaEvent
503
+ end
504
504
 
505
+ class Tempo < MetaEvent
505
506
  MICROSECS_PER_MINUTE = 1_000_000 * 60
506
507
 
507
508
  # Translates beats per minute to microseconds per quarter note (beat).
508
- def Tempo.bpm_to_mpq(bpm)
509
- return MICROSECS_PER_MINUTE / bpm
509
+ def self.bpm_to_mpq(bpm)
510
+ MICROSECS_PER_MINUTE / bpm
510
511
  end
511
512
 
512
513
  # Translates microseconds per quarter note (beat) to beats per minute.
513
- def Tempo.mpq_to_bpm(mpq)
514
- 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
515
516
  end
516
517
 
517
518
  def initialize(msecs_per_qnote, delta_time = 0)
518
- super(META_SET_TEMPO, msecs_per_qnote, delta_time)
519
+ super(META_SET_TEMPO, msecs_per_qnote, delta_time)
519
520
  end
520
521
 
521
522
  def tempo
522
- return @data
523
+ @data
523
524
  end
524
525
 
525
526
  def tempo=(val)
526
- @data = val
527
+ @data = val
527
528
  end
528
529
 
529
530
  def data_as_bytes
530
- data = []
531
- data << @status
532
- data << @meta_type
533
- data << 3
534
- data << ((@data >> 16) & 0xff)
535
- data << ((@data >> 8) & 0xff)
536
- data << (@data & 0xff)
531
+ data = []
532
+ data << @status
533
+ data << @meta_type
534
+ data << 3
535
+ data << ((@data >> 16) & 0xff)
536
+ data << ((@data >> 8) & 0xff)
537
+ data << (@data & 0xff)
537
538
  end
538
539
 
539
540
  def to_s
540
- "tempo #{@data} msecs per qnote (#{Tempo.mpq_to_bpm(@data)} bpm)"
541
+ "tempo #{@data} msecs per qnote (#{Tempo.mpq_to_bpm(@data)} bpm)"
541
542
  end
542
- end
543
+ end
543
544
 
544
- # Container for time signature events
545
- class TimeSig < MetaEvent
546
-
545
+ # Container for time signature events
546
+ class TimeSig < MetaEvent
547
547
  # Constructor
548
548
  def initialize(numer, denom, clocks, qnotes, delta_time = 0)
549
- super(META_TIME_SIG, [numer, denom, clocks, qnotes], delta_time)
549
+ super(META_TIME_SIG, [numer, denom, clocks, qnotes], delta_time)
550
550
  end
551
-
551
+
552
552
  # Returns the complete event as stored in the sequence
553
553
  def data_as_bytes
554
- data = []
555
- data << @status
556
- data << @meta_type
557
- data << 4
558
- data << @data[0]
559
- data << @data[1]
560
- data << @data[2]
561
- data << @data[3]
554
+ data = []
555
+ data << @status
556
+ data << @meta_type
557
+ data << 4
558
+ data << @data[0]
559
+ data << @data[1]
560
+ data << @data[2]
561
+ data << @data[3]
562
562
  end
563
563
 
564
- # Calculates the duration (in ticks) for a full measure
565
- def measure_duration(ppqn)
566
- (4 * ppqn * @data[0]) / (2**@data[1])
564
+ # Calculates the duration (in ticks) for a full measure
565
+ def measure_duration(ppqn)
566
+ (4 * ppqn * @data[0]) / (2**@data[1])
567
567
  end
568
-
568
+
569
569
  # Returns the numerator (the top digit) for the time signature
570
570
  def numerator
571
- @data[0]
571
+ @data[0]
572
572
  end
573
-
573
+
574
574
  # Returns the denominator of the time signature. Use it as a power of 2
575
575
  # to get the displayed (lower-part) digit of the time signature.
576
576
  def denominator
577
- @data[1]
577
+ @data[1]
578
578
  end
579
-
579
+
580
580
  # Returns the metronome tick duration for the time signature. On
581
581
  # each quarter note, there's 24 ticks.
582
582
  def metronome_ticks
583
- @data[2]
583
+ @data[2]
584
584
  end
585
-
585
+
586
586
  # Returns the time signature for the event as a string.
587
587
  # Example: "time sig 3/4"
588
588
  def to_s
589
- "time sig #{@data[0]}/#{2**@data[1]}"
589
+ "time sig #{@data[0]}/#{2**@data[1]}"
590
590
  end
591
- end
591
+ end
592
592
 
593
- # Container for key signature events
594
- class KeySig < MetaEvent
595
-
593
+ # Container for key signature events
594
+ class KeySig < MetaEvent
596
595
  # Constructor
597
596
  def initialize(sharpflat, is_minor, delta_time = 0)
598
- super(META_KEY_SIG, [sharpflat, is_minor], delta_time)
597
+ super(META_KEY_SIG, [sharpflat, is_minor], delta_time)
599
598
  end
600
-
599
+
601
600
  # Returns the complete event as stored in the sequence
602
601
  def data_as_bytes
603
- data = []
604
- data << @status
605
- data << @meta_type
606
- data << 2
607
- data << @data[0]
608
- data << (@data[1] ? 1 : 0)
609
- end
610
-
602
+ data = []
603
+ data << @status
604
+ data << @meta_type
605
+ data << 2
606
+ data << @data[0]
607
+ data << (@data[1] ? 1 : 0)
608
+ end
609
+
611
610
  # Returns true if it's a minor key, false if major key
612
611
  def minor_key?
613
- @data[1]
612
+ @data[1]
614
613
  end
615
-
614
+
616
615
  # Returns true if it's a major key, false if minor key
617
616
  def major_key?
618
- !@data[1]
617
+ !@data[1]
619
618
  end
620
-
619
+
621
620
  # Returns the number of sharps/flats in the key sig. Negative for flats.
622
621
  def sharpflat
623
- @data[0] > 7 ? @data[0] - 256 : @data[0]
622
+ @data[0] > 7 ? @data[0] - 256 : @data[0]
624
623
  end
625
-
624
+
626
625
  # Returns the key signature as a text string.
627
626
  # Example: "key sig A flat major"
628
627
  def to_s
629
- majorkeys = ['C flat', 'G flat', 'D flat', 'A flat', 'E flat', 'B flat', 'F',
630
- 'C', 'G', 'D', 'A', 'E', 'B', 'F#', 'C#']
631
- minorkeys = ['a flat', 'e flat', 'b flat', 'f', 'c', 'g', 'd',
628
+ if minor_key?
629
+ "key sig #{minorkeys[sharpflat + 7]} minor"
630
+ else
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
643
+ end
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',
632
654
  'a', 'e', 'b', 'f#', 'c#', 'g#', 'd#', 'a#']
633
- minor_key? ? "key sig #{minorkeys[sharpflat + 7]} minor" :
634
- "key sig #{majorkeys[sharpflat + 7]} major"
635
655
  end
636
- end
637
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
638
667
  end