Module: Lydown::Rendering::Accidentals

Defined in:
lib/lydown/rendering/notes.rb

Constant Summary collapse

KEY_CYCLE =
%w{c- g- d- a- e- b- f c g d a e b f+ c+ g+ d+ a+ e+ b+}
C_IDX =
KEY_CYCLE.index('c')
A_IDX =
KEY_CYCLE.index('a')
SHARPS_IDX =
KEY_CYCLE.index('f+')
FLATS_IDX =
KEY_CYCLE.index('b-')
KEY_ACCIDENTALS =
{}
SIGNATURE_ACCIDENTAL_TRANSLATION =
{
  '#' => '+',
  'ß' => '-'
}
ACCIDENTAL_VALUES =
{
  '+' => 1,
  '-' => -1,
  '#' => 1,
  'ß' => -1
}

Class Method Summary collapse

Class Method Details

.accidentals_for_key_signature(signature) ⇒ Object



12
13
14
# File 'lib/lydown/rendering/notes.rb', line 12

def self.accidentals_for_key_signature(signature)
  KEY_ACCIDENTALS[signature] ||= calc_accidentals_for_key_signature(signature)
end

.calc_accidentals_for_key_signature(signature) ⇒ Object



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/lydown/rendering/notes.rb', line 21

def self.calc_accidentals_for_key_signature(signature)
  signature = signature.gsub(/[#ß]/) {|c| SIGNATURE_ACCIDENTAL_TRANSLATION[c]}
  unless signature =~ /^([a-g][\+\-]*) (major|minor)$/
    raise "Invalid key signature #{signature.inspect}"
  end

  key = $1; mode = $2

  # calculate offset from c major / a minor
  base_idx = (mode == 'major') ? C_IDX : A_IDX
  offset = KEY_CYCLE.index(key) - base_idx

  if offset >= 0
    calc_accidentals_map(KEY_CYCLE[SHARPS_IDX, offset])
  else
    calc_accidentals_map(KEY_CYCLE[FLATS_IDX + offset + 1, -offset])
  end
end

.calc_accidentals_map(accidentals) ⇒ Object



40
41
42
# File 'lib/lydown/rendering/notes.rb', line 40

def self.calc_accidentals_map(accidentals)
  accidentals.inject({}) { |h, a| h[a[0]] = (a[1] == '+') ? 1 : -1; h}
end

.chromatic_to_diatonic(note, key_signature = 'c major') ⇒ Object



65
66
67
68
69
70
71
72
73
74
75
# File 'lib/lydown/rendering/notes.rb', line 65

def self.chromatic_to_diatonic(note, key_signature = 'c major')
  note =~ /([a-g])([\+\-]*)/
  diatonic_note = $1
  chromatic_value = $2.count('+') - $2.count('-')

  key_accidentals = accidentals_for_key_signature(key_signature)
  diatonic_value = key_accidentals[diatonic_note] || 0
  value = chromatic_value - diatonic_value

  "#{diatonic_note}#{value >= 0 ? '+' * value : '-' * -value}"
end

.lilypond_note_name(note, key_signature = 'c major') ⇒ Object



51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/lydown/rendering/notes.rb', line 51

def self.lilypond_note_name(note, key_signature = 'c major')
  # if the natural sign (h) is used, no need to calculate the note name
  return $1 if note =~ /([a-g])h/

  value = 0
  # accidental value from note
  note = note.gsub(/[\-\+#ß]/) { |c| value += ACCIDENTAL_VALUES[c]; '' }

  # add key signature value
  value += accidentals_for_key_signature(key_signature)[note] || 0

  note + (value >= 0 ? 'is' * value : 'es' * -value)
end

.translate_note_name(context, note) ⇒ Object

Takes into account the accidentals mode



78
79
80
81
82
83
84
85
# File 'lib/lydown/rendering/notes.rb', line 78

def self.translate_note_name(context, note)
  if context.get_current_setting(:accidentals) == 'manual'
    key = 'c major'
  else
    key = context.get_current_setting(:key)
  end
  lilypond_note_name(note, key)
end