class Musicality::Score::Tempo
Tempo-based score with meter, bar lines, and a fixed pulse (beat).
Offsets and durations are based on note duration, but note duration is determined by the tempo, which can change.
Tempo
values are in beats-per-minute.
Attributes
meter_changes[RW]
start_meter[RW]
start_tempo[RW]
tempo_changes[RW]
Public Class Methods
new(start_tempo, tempo_changes: {})
click to toggle source
See Score#initialize for remaining kwargs
Calls superclass method
Musicality::Score::new
# File lib/musicality/notation/model/score.rb, line 82 def initialize start_tempo, tempo_changes: {}, start_meter: Meters::FOUR_FOUR, meter_changes: {}, parts: {}, program: [], title: nil, composer: nil, sections: {}, start_key: Keys::C_MAJOR, key_changes: {}, auditions: [] @start_tempo = start_tempo @tempo_changes = tempo_changes @start_meter = start_meter @meter_changes = meter_changes super(parts: parts, program: program, title: title, composer: composer, sections: sections, start_key: start_key, key_changes: key_changes, auditions: auditions) end
Public Instance Methods
==(other)
click to toggle source
Calls superclass method
Musicality::Score#==
# File lib/musicality/notation/model/score.rb, line 99 def ==(other) return super(other) && @start_tempo == other.start_tempo && @tempo_changes == other.tempo_changes @start_meter == other.start_meter && @meter_changes == other.meter_changes end
beat_durations()
click to toggle source
# File lib/musicality/notation/conversion/score_conversion.rb, line 11 def beat_durations bdurs = @meter_changes.map do |offset,change_or_meter| if change_or_meter.is_a? Meter [ offset, change_or_meter.beat_duration ] else [ offset, change_or_meter.end_value.beat_duration ] end end.sort if bdurs.empty? || bdurs[0][0] != 0 bdurs.unshift([0.to_r,@start_meter.beat_duration]) end return Hash[ bdurs ] end
check_methods()
click to toggle source
Calls superclass method
Musicality::Score#check_methods
# File lib/musicality/notation/model/score.rb, line 91 def check_methods super() + [:check_start_tempo, :check_tempo_changes, :check_start_meter, :check_meter_changes] end
key_change(new_key, offset: 0)
click to toggle source
# File lib/musicality/composition/dsl/score_methods.rb, line 79 def key_change new_key, offset: 0 key_changes[self.duration + offset] = Change::Immediate.new(new_key) end
measure_duration(note_offset = self.duration)
click to toggle source
Returns the measure duration of the most recent meter duration since the given note offset, or of the start meter if there are no meter changes.
# File lib/musicality/notation/model/score.rb, line 109 def measure_duration note_offset = self.duration if meter_changes.any? candidates = meter_changes.select {|noff,change| noff <= note_offset } candidates.max[1].end_value.measure_duration else start_meter.measure_duration end end
meter_change(new_meter, offset: 0)
click to toggle source
# File lib/musicality/composition/dsl/score_methods.rb, line 75 def meter_change new_meter, offset: 0 meter_changes[self.duration + offset] = Change::Immediate.new(new_meter) end
tempo_change(new_tempo, transition_dur: 0, offset: 0)
click to toggle source
# File lib/musicality/composition/dsl/score_methods.rb, line 67 def tempo_change new_tempo, transition_dur: 0, offset: 0 if transition_dur == 0 tempo_changes[self.duration + offset] = Change::Immediate.new(new_tempo) else tempo_changes[self.duration + offset] = Change::Gradual.linear(new_tempo, transition_dur) end end
to_lilypond(selected_parts = @parts.keys)
click to toggle source
See ScoreEngraver#make_lilypond
for details on supported keyword args
# File lib/musicality/printing/lilypond/score_engraving.rb, line 6 def to_lilypond selected_parts = @parts.keys ScoreEngraver.new(self).make_lilypond(selected_parts) end
to_midi_seq(tempo_sample_rate, **kwargs)
click to toggle source
# File lib/musicality/performance/midi/score_sequencing.rb, line 11 def to_midi_seq tempo_sample_rate, **kwargs to_timed(tempo_sample_rate).to_midi_seq(**kwargs) end
to_osc(tempo_sample_rate, base_fpath, **kwargs)
click to toggle source
# File lib/musicality/performance/supercollider/score_conducting.rb, line 11 def to_osc tempo_sample_rate, base_fpath, **kwargs to_timed(tempo_sample_rate).to_osc(base_fpath, **kwargs) end
to_timed(tempo_sample_rate)
click to toggle source
Convert to timed score by converting note-based offsets and durations to time-based. This eliminates the use of meters and tempos.
# File lib/musicality/notation/conversion/score_conversion.rb, line 7 def to_timed tempo_sample_rate ScoreConverter.new(self, tempo_sample_rate).convert_score end
validatables()
click to toggle source
Calls superclass method
Musicality::Score#validatables
# File lib/musicality/notation/model/score.rb, line 95 def validatables super() + [ @start_meter ] + @meter_changes.values.map {|v| v.end_value} end
Private Instance Methods
check_meter_changes()
click to toggle source
# File lib/musicality/notation/model/score.rb, line 144 def check_meter_changes badtypes = @meter_changes.select {|k,v| !v.end_value.is_a?(Meter) } if badtypes.any? raise TypeError, "Found meter change values that are not Meter objects: #{badtypes}" end nonzero_duration = @meter_changes.select {|k,v| !v.is_a?(Change::Immediate) } if nonzero_duration.any? raise NonZeroError, "Found meter changes that are not immediate: #{nonzero_duration}" end end
check_start_meter()
click to toggle source
# File lib/musicality/notation/model/score.rb, line 138 def check_start_meter unless @start_meter.is_a? Meter raise TypeError, "Start meter #{@start_meter} is not a Meter object" end end
check_start_tempo()
click to toggle source
# File lib/musicality/notation/model/score.rb, line 120 def check_start_tempo if @start_tempo <= 0 raise NonPositiveError, "Start tempo (#{@start_tempo}) is not positive" end end
check_tempo_changes()
click to toggle source
# File lib/musicality/notation/model/score.rb, line 126 def check_tempo_changes badtypes = @tempo_changes.select {|k,v| !v.end_value.is_a?(Numeric) } if badtypes.any? raise TypeError, "Found non-numeric tempo change values: #{badtypes}" end badvalues = @tempo_changes.select {|k,v| v.end_value <= 0 } if badvalues.any? raise NonPositiveError, "Found non-positive tempo changes values: #{badvalues}" end end