class Musicality::NoteFIFO
Attributes
duration[R]
notes[R]
Public Class Methods
new(initial_notes = [])
click to toggle source
# File lib/musicality/composition/sequencing/note_fifo.rb, line 5 def initialize initial_notes = [] @notes = [] @duration = 0 add_notes(initial_notes) if initial_notes.any? end
Public Instance Methods
add_note(note)
click to toggle source
# File lib/musicality/composition/sequencing/note_fifo.rb, line 15 def add_note note if note.duration <= 0 raise ArgumentError, "note have non-positive duration: #{note}" end @notes.push note @duration += note.duration end
add_notes(notes)
click to toggle source
# File lib/musicality/composition/sequencing/note_fifo.rb, line 23 def add_notes notes nonpositive = notes.select {|x| x.duration <= 0} if nonpositive.any? raise ArgumentError, "one or more notes have non-positive duration: #{notes}" end @notes += notes @duration += notes.inject(0) {|sum, note| sum + note.duration } end
empty?()
click to toggle source
# File lib/musicality/composition/sequencing/note_fifo.rb, line 11 def empty? @notes.empty? end
remove_notes(target_duration)
click to toggle source
Return a sequence of notes with total duration equal to the given target duration, and remove the same notes from the accumulator. Any notes beyond the given target duration are left in the accumulator. Split a note into two tied notes if needed.
# File lib/musicality/composition/sequencing/note_fifo.rb, line 35 def remove_notes target_duration raise ArgumentError, "negative target duration #{target_duration}" if target_duration < 0 if target_duration > duration raise ArgumentError, "target duration #{target_duration} is greater than duration of accumulated notes #{duration}" end removed_notes = if target_duration == 0 [] elsif target_duration == duration notes.shift(notes.size) else dur_so_far = 0.to_r num_notes_taking = 0 @notes.each_with_index do |note, idx| dur_so_far += note.duration num_notes_taking += 1 break if dur_so_far >= target_duration end notes_taking = notes.shift(num_notes_taking) excess_dur = dur_so_far - target_duration if excess_dur > 0 @notes.unshift(notes_taking[-1].resize(excess_dur)) notes_taking[-1] = notes_taking[-1].resize(notes_taking[-1].duration - excess_dur) notes_taking[-1].pitches.each do |pitch| notes_taking[-1].links[pitch] = Link::Tie.new end end notes_taking end @duration = @duration - target_duration return removed_notes end