Class: Musicality::PartEngraver
- Inherits:
-
Object
- Object
- Musicality::PartEngraver
- Defined in:
- lib/musicality/printing/lilypond/part_engraver.rb
Constant Summary collapse
- MAX_LINE_LEN =
76
- INDENT =
" "
- CLEF_RANGES =
{ Clef::TREBLE => Pitches::C4..Pitches::A5, Clef::ALTO => Pitches::D3..Pitches::B4, Clef::TENOR => Pitches::B2..Pitches::G4, Clef::BASS => Pitches::E2..Pitches::C4, }
Class Method Summary collapse
Instance Method Summary collapse
- #decrease_indent ⇒ Object
- #increase_indent ⇒ Object
-
#initialize(part, title) ⇒ PartEngraver
constructor
A new instance of PartEngraver.
- #make_body(sharpit) ⇒ Object
- #make_final ⇒ Object
- #make_lilypond(start_key, start_meter, key_changes: {}, meter_changes: {}, master: false) ⇒ Object
- #make_preliminary(start_meter, start_key, master) ⇒ Object
Constructor Details
#initialize(part, title) ⇒ PartEngraver
Returns a new instance of PartEngraver.
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
# File 'lib/musicality/printing/lilypond/part_engraver.rb', line 7 def initialize part, title if part.invalid? raise ArgumentError, "given part contains errors: #{part.errors}" end @transpose_interval = part.lilypond_settings.transpose_interval @clefs = part.lilypond_settings.clefs @part = (@transpose_interval == 0) ? part : part.transpose(@transpose_interval) @title = title @indent = INDENT @triplet_flags = @part.notes.map do |note| note.duration.to_r.denominator % 3 == 0 end end |
Class Method Details
.best_clef(notes, allowed_clefs) ⇒ Object
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
# File 'lib/musicality/printing/lilypond/part_engraver.rb', line 93 def self.best_clef notes, allowed_clefs raise ArgumentError unless notes.any? raise ArgumentError unless allowed_clefs.any? ranges = CLEF_RANGES.select {|clef,range| allowed_clefs.include?(clef) } range_scores = Hash.new(0) notes.each do |note| note.pitches.each do |p| ranges.each do |name,range| if p >= range.min && p <= range.max range_scores[name] += note.duration end end end end range_score = range_scores.max_by {|range,score| score} range_score.nil? ? allowed_clefs.first : range_score[0] end |
Instance Method Details
#decrease_indent ⇒ Object
27 28 29 |
# File 'lib/musicality/printing/lilypond/part_engraver.rb', line 27 def decrease_indent @indent = @indent[0...-INDENT.size] end |
#increase_indent ⇒ Object
23 24 25 |
# File 'lib/musicality/printing/lilypond/part_engraver.rb', line 23 def increase_indent @indent += INDENT end |
#make_body(sharpit) ⇒ Object
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
# File 'lib/musicality/printing/lilypond/part_engraver.rb', line 56 def make_body sharpit i = 0 pieces = @part.notes.map do |n| str = if @triplet_flags[i] n.resize(n.duration * Rational(3,2)).to_lilypond(sharpit, begins_triplet: i == 0 || !@triplet_flags[i-1], ends_triplet: i == (@triplet_flags.size-1) || !@triplet_flags[i+1]) else n.to_lilypond(sharpit) end i += 1 str end output = "" while pieces.any? line = @indent + pieces.shift until pieces.empty? || (line.size + 1 + pieces.first.size) > MAX_LINE_LEN line += " " + pieces.shift end output += line + "\n" end return output end |
#make_final ⇒ Object
81 82 83 84 |
# File 'lib/musicality/printing/lilypond/part_engraver.rb', line 81 def make_final decrease_indent return @indent + "}\n" end |
#make_lilypond(start_key, start_meter, key_changes: {}, meter_changes: {}, master: false) ⇒ Object
31 32 33 34 35 36 37 38 39 40 |
# File 'lib/musicality/printing/lilypond/part_engraver.rb', line 31 def make_lilypond start_key, start_meter, key_changes: {}, meter_changes: {}, master: false if @transpose_interval != 0 start_key = transpose_start_key(start_key) key_changes = transpose_key_changes(key_changes) end sharpit = start_key.sharp? return make_preliminary(start_meter, start_key, master) + make_body(sharpit) + make_final() end |
#make_preliminary(start_meter, start_key, master) ⇒ Object
42 43 44 45 46 47 48 49 50 51 52 53 54 |
# File 'lib/musicality/printing/lilypond/part_engraver.rb', line 42 def make_preliminary start_meter, start_key, master clef = self.class.best_clef(@part.notes, @clefs) output = @indent + "\\new Staff {\n" increase_indent output += @indent + "\\set Staff.instrumentName = \\markup { \"#{@title}\" }\n" output += @indent + "\\clef #{clef}\n" if master output += @indent + start_meter.to_lilypond + "\n" end output += @indent + start_key.to_lilypond + "\n" return output end |