Class: Musicality::ScoreConverter

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

Overview

Converts tempo-based score to timed score, by converting note-based offsets and durations to time-based, and eliminating the use of tempo and meters.

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(score, tempo_sample_rate) ⇒ ScoreConverter

Returns a new instance of ScoreConverter.



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/musicality/notation/conversion/score_converter.rb', line 35

def initialize score, tempo_sample_rate
  if score.invalid?
    raise NotValidError, "Errors detected given score: #{score.errors}"
  end
  beat_duration_changes = Hash[ score.beat_durations.map do |noff,bdur|
    [noff, Change::Immediate.new(bdur) ]
  end]
  tempo_computer = ValueComputer.new(score.start_tempo, score.tempo_changes)
  bdur_computer = ValueComputer.new(score.start_meter.beat_duration, beat_duration_changes)
  ntc = NoteTimeConverter.new(tempo_computer, bdur_computer, tempo_sample_rate)

  @parts = Hash[ score.parts.map {|name,part| [name, part.clone] }]
  @program = score.program.clone
  @note_time_map = ntc.note_time_map(note_offsets)
end

Class Method Details

.convert_changes(changes, offset_map) ⇒ Object



6
7
8
9
10
# File 'lib/musicality/notation/conversion/score_converter.rb', line 6

def self.convert_changes changes, offset_map
  Hash[ changes.map do |off,change|
    [ offset_map[off], change.remap(off,offset_map) ]
  end ]    
end

.convert_parts(parts, offset_map) ⇒ Object



12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/musicality/notation/conversion/score_converter.rb', line 12

def self.convert_parts parts, offset_map
  Hash[ parts.map do |name,part|
    offset = 0.to_r
    new_notes = part.notes.map do |note|
      starttime = offset_map[offset]
      endtime = offset_map[offset + note.duration]
      offset += note.duration
      note.resize(endtime - starttime)
    end
    new_dcs = convert_changes(part.dynamic_changes, offset_map)
    new_part = part.clone
    new_part.notes = new_notes
    new_part.dynamic_changes = new_dcs
    [name, new_part]
  end]
end

.convert_program(program, offset_map) ⇒ Object



29
30
31
32
33
# File 'lib/musicality/notation/conversion/score_converter.rb', line 29

def self.convert_program program, offset_map
  program.map do |segment|
    offset_map[segment.first]...offset_map[segment.last]
  end
end

Instance Method Details

#convert_partsObject

Convert note-based offsets & durations to time-based.



67
68
69
# File 'lib/musicality/notation/conversion/score_converter.rb', line 67

def convert_parts
  ScoreConverter.convert_parts(@parts, @note_time_map)
end

#convert_programObject

Convert note-based offsets & durations to time-based.



72
73
74
# File 'lib/musicality/notation/conversion/score_converter.rb', line 72

def convert_program
  ScoreConverter.convert_program(@program, @note_time_map)
end

#convert_scoreObject



62
63
64
# File 'lib/musicality/notation/conversion/score_converter.rb', line 62

def convert_score
  Score::Timed.new(parts: convert_parts, program: convert_program)
end

#note_offsetsObject



51
52
53
54
55
56
57
58
59
60
# File 'lib/musicality/notation/conversion/score_converter.rb', line 51

def note_offsets
  noffs = Set.new([0.to_r])
  @parts.values.each do |part|
    noff = 0.to_r
    part.notes.each {|note| noffs.add(noff += note.duration) }
    part.dynamic_changes.each {|noff2,change| noffs += change.offsets(noff2) }
  end
  noffs += @program.map {|seg| [seg.first, seg.last] }.flatten
  return noffs.sort
end