midilib 2.0.2 → 3.0.1

Sign up to get free protection for your applications and to get access to all the features.
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