Class: Musicality::ScoreSequencer

Inherits:
Object
  • Object
show all
Defined in:
lib/musicality/performance/midi/score_sequencer.rb

Constant Summary collapse

USEC_PER_QUARTER_SEC =
250000

Instance Method Summary collapse

Constructor Details

#initialize(score) ⇒ ScoreSequencer

Returns a new instance of ScoreSequencer.



4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# File 'lib/musicality/performance/midi/score_sequencer.rb', line 4

def initialize score
  unless score.is_a?(Score::Timed)
    raise ArgumentError, "The given score is not a Score::Timed. \
    Convert it first using ScoreConverter."
  end
  
  @parts = score.collated? ? score.parts : ScoreCollator.new(score).collate_parts

  # parts should all have MIDI settings, defaults if necessary
  @parts.each do |part_name, part|
    unless part.midi_settings
      part.settings.push MidiSettings.new(1)
    end
  end

  # part names should all be strings, because 1) a midi track name needs to
  # be a string and 2) the instrument map used to map part names to MIDI
  # program numbers will use part name strings as keys.
  @parts = Hash[ @parts.map {|k,v| [k.to_s,v] } ]
end

Instance Method Details

#make_midi_seq(selected_parts = @parts.keys) ⇒ Object



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/musicality/performance/midi/score_sequencer.rb', line 27

def make_midi_seq selected_parts = @parts.keys
  seq = MIDI::Sequence.new()
  
  # first track for the sequence holds time sig and tempo events
  track0 = MIDI::Track.new(seq)
  seq.tracks << track0
  track0.events << MIDI::Tempo.new(USEC_PER_QUARTER_SEC)
  track0.events << MIDI::MetaEvent.new(MIDI::META_SEQ_NAME, 'Sequence Name')
  
  channel = 0
  selected_parts.each do |part_name|
    part = @parts.fetch(part_name)
    program = part.midi_settings.program
    pseq = PartSequencer.new(part)
    seq.tracks << pseq.make_midi_track(seq, part_name, channel, seq.ppqn, program)
    channel += 1
  end
  
  return seq
end