Class: Musicality::NoteTimeConverter

Inherits:
Object
  • Object
show all
Defined in:
lib/musicality/notation/conversion/note_time_converter.rb

Overview

Convert offsets in measured note time to just plain time.

Instance Method Summary collapse

Constructor Details

#initialize(tempo_computer, bdur_computer, sample_rate) ⇒ NoteTimeConverter

value in quarter-notes-per-minute in the conversion (samples/sec).

Parameters:

  • tempo_computer (ValueComputer)

    Given an offset, returns tempo

  • sample_rate (Numeric)

    Rate at which tempo values are sampled



9
10
11
12
13
# File 'lib/musicality/notation/conversion/note_time_converter.rb', line 9

def initialize tempo_computer, bdur_computer, sample_rate
  @tempo_computer = tempo_computer
  @bdur_computer = bdur_computer
  @sample_period = Rational(1,sample_rate)
end

Instance Method Details

#note_time_map(offsets) ⇒ Object

map absolute note offsets to relative time offsets



55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/musicality/notation/conversion/note_time_converter.rb', line 55

def note_time_map offsets
  time_counter = 0.0
  sorted_offsets = 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) ⇒ Object



15
16
17
# File 'lib/musicality/notation/conversion/note_time_converter.rb', line 15

def notes_per_second_at offset
  Tempo::BPM.to_nps(@tempo_computer.at(offset), @bdur_computer.at(offset))
end

#time_elapsed(start_offset, end_offset) ⇒ Object

Calculate the time elapsed between given start/end note offset. Using the notes-per-second values over this interval, note duration for each sample is known and accumulated as samples are taken. When accumulated note duration passes the given desired duration (end_offset - start_offset), the number of samples taken will indicated the corresponding time duration. Then there is adjustment for last sample taken, which likely goes past the desired note duration.

Parameters:

  • start_offset (Numeric)

    the starting note offset.

  • end_offset (Numeric)

    the ending note offset.

Raises:

  • (ArgumentError)

    if end offset is less than starting offset.



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/musicality/notation/conversion/note_time_converter.rb', line 30

def time_elapsed start_offset, end_offset
  raise ArgumentError "note end is less than note begin" if end_offset < start_offset
  
  time_samples = 0
  offset = start_offset
  
  while offset < end_offset
    notes_per_sec = notes_per_second_at offset
    notes_per_sample = notes_per_sec * @sample_period
    
    if (offset + notes_per_sample) > end_offset
      #interpolate between offset and end_offset
      perc = (end_offset - offset) / notes_per_sample
      time_samples += perc
      offset = end_offset
    else
      time_samples += 1
      offset += notes_per_sample
    end
  end
  
  return time_samples * @sample_period
end