class Music::Performance::NoteTimeConverter

Convert note duration to time duration.

Public Class Methods

new(tempo_computer, beat_duration_computer, sample_rate) click to toggle source
# File lib/music-performance/conversion/note_time_converter.rb, line 7
def initialize tempo_computer, beat_duration_computer, sample_rate
  @tempo_computer = tempo_computer
  @beat_duration_computer = beat_duration_computer
  @sample_period = Rational(1,sample_rate)
end
notes_per_second(tempo, beat_duration) click to toggle source
# File lib/music-performance/conversion/note_time_converter.rb, line 13
def self.notes_per_second tempo, beat_duration
  (tempo * beat_duration) * Rational(1,60)
end

Public Instance Methods

map_note_offsets_to_time_offsets(note_offsets) click to toggle source

map absolute note offsets to relative time offsets

# File lib/music-performance/conversion/note_time_converter.rb, line 60
def map_note_offsets_to_time_offsets note_offsets
  time_counter = 0.0
  sorted_offsets = note_offsets.sort
  note_time_map = { sorted_offsets.first => time_counter }
  
  for i in 1...sorted_offsets.count do
    time_counter += time_elapsed(sorted_offsets[i-1], sorted_offsets[i])
    note_time_map[sorted_offsets[i]] = time_counter
  end
  
  return note_time_map
end
notes_per_second_at(offset) click to toggle source
# File lib/music-performance/conversion/note_time_converter.rb, line 17
def notes_per_second_at offset
  tempo = @tempo_computer.value_at offset
  beat_duration = @beat_duration_computer.value_at offset
  return NoteTimeConverter.notes_per_second(tempo,beat_duration)
end
time_elapsed(note_begin, note_end) click to toggle source

Convert the given note duration to a time duration. Using the tempo computer and beat duration computer, figure the current notes-per-second relationship depending on the current note offset. Using this, note duration for each sample is known and accumulated as samples are taken. When accumulated note duration passes the given desired duration (note_end - note_begin), the number of samples take will indicated the corresponding time duration. There is adjustment for last sample taken, which likely goes past the desired note duration.

@param [Numeric] note_begin the starting note offset. @param [Numeric] note_end the ending note offset. @raise [ArgumentError] if note end is less than note begin.

# File lib/music-performance/conversion/note_time_converter.rb, line 35
def time_elapsed note_begin, note_end
  raise ArgumentError "note end is less than note begin" if note_end < note_begin
  
  time = 0.to_r
  note = note_begin
  
  while note < note_end
    notes_per_sec = notes_per_second_at note
    notes_per_sample = notes_per_sec * @sample_period
    
    if (note + notes_per_sample) > note_end
      #interpolate between note and note_end
      perc = (note_end - note) / notes_per_sample
      time += @sample_period * perc
      note = note_end
    else
      time += @sample_period
      note += notes_per_sample
    end
  end
  
  return time
end