Module: HeadMusic::Style::Guidelines::DissonanceFigureDetection
- Included in:
- FloridDissonanceTreatment, WeakBeatDissonanceTreatment
- Defined in:
- lib/head_music/style/guidelines/dissonance_figure_detection.rb
Overview
Shared detection of ornamental dissonance figures (nota cambiata, double neighbor) plus the melodic helpers those figures and their surrounding guidelines rely on. Include in any dissonance treatment guideline that recognizes these figures. Expects the including class to provide: #notes, #cantus_firmus, #voice.
Instance Method Summary collapse
-
#all_consonant_with_cantus?(*checked_notes) ⇒ Boolean
private
-
#cambiata_as_note_2?(index) ⇒ Boolean
private
-
#cambiata_dissonance?(note) ⇒ Boolean
private
Nota cambiata: a five-note figure where note 2 is dissonant, approached by step from note 1, leaps a third in the same direction to note 3, then notes 3-4-5 proceed stepwise in the opposite direction.
-
#cambiata_shape?(n1, n2, n3, n4, n5) ⇒ Boolean
private
-
#cantus_firmus_positions ⇒ Object
private
Positions where the cantus firmus sounds a note (the strong beats).
-
#consonant_with_cantus?(note) ⇒ Boolean
private
-
#dissonant_with_cantus?(note) ⇒ Boolean
private
A note whose pitch clashes with the cantus firmus in two-part harmony.
-
#double_neighbor_figure?(index, offset:) ⇒ Boolean
private
Double neighbor: a four-note figure within one bar.
-
#double_neighbor_member?(note) ⇒ Boolean
private
-
#double_neighbor_shape?(n1, n2, n3, n4) ⇒ Boolean
private
-
#melodic_interval_between(note1, note2) ⇒ Object
private
-
#neighbor_tone?(note) ⇒ Boolean
private
-
#passing_tone?(note) ⇒ Boolean
private
-
#steps_back_from?(leap, step_back_1, step_back_2) ⇒ Boolean
private
Notes 3-4-5 must both step in the direction opposite the leap.
-
#stepwise_figure?(note, same_direction:) ⇒ Boolean
private
Instance Method Details
#all_consonant_with_cantus?(*checked_notes) ⇒ Boolean (private)
99 100 101 |
# File 'lib/head_music/style/guidelines/dissonance_figure_detection.rb', line 99 def all_consonant_with_cantus?(*checked_notes) checked_notes.all? { |note| consonant_with_cantus?(note) } end |
#cambiata_as_note_2?(index) ⇒ Boolean (private)
58 59 60 61 62 63 |
# File 'lib/head_music/style/guidelines/dissonance_figure_detection.rb', line 58 def cambiata_as_note_2?(index) return false if index < 1 || index + 3 > notes.length - 1 n1, n2, n3, n4, n5 = notes[index - 1, 5] cambiata_shape?(n1, n2, n3, n4, n5) && all_consonant_with_cantus?(n1, n3, n5) end |
#cambiata_dissonance?(note) ⇒ Boolean (private)
Nota cambiata: a five-note figure where note 2 is dissonant, approached by step from note 1, leaps a third in the same direction to note 3, then notes 3-4-5 proceed stepwise in the opposite direction. Notes 1, 3, and 5 must be consonant with the CF.
44 45 46 47 48 49 |
# File 'lib/head_music/style/guidelines/dissonance_figure_detection.rb', line 44 def cambiata_dissonance?(note) index = notes.index(note) return false unless index cambiata_as_note_2?(index) end |
#cambiata_shape?(n1, n2, n3, n4, n5) ⇒ Boolean (private)
65 66 67 68 69 70 71 |
# File 'lib/head_music/style/guidelines/dissonance_figure_detection.rb', line 65 def cambiata_shape?(n1, n2, n3, n4, n5) approach = melodic_interval_between(n1, n2) leap = melodic_interval_between(n2, n3) return false unless approach.step? && leap.number == 3 && approach.direction == leap.direction steps_back_from?(leap, melodic_interval_between(n3, n4), melodic_interval_between(n4, n5)) end |
#cantus_firmus_positions ⇒ Object (private)
Positions where the cantus firmus sounds a note (the strong beats).
18 19 20 |
# File 'lib/head_music/style/guidelines/dissonance_figure_detection.rb', line 18 def cantus_firmus_positions @cantus_firmus_positions ||= Set.new(cantus_firmus.notes.map { |note| note.position.to_s }) end |
#consonant_with_cantus?(note) ⇒ Boolean (private)
103 104 105 |
# File 'lib/head_music/style/guidelines/dissonance_figure_detection.rb', line 103 def consonant_with_cantus?(note) !dissonant_with_cantus?(note) end |
#dissonant_with_cantus?(note) ⇒ Boolean (private)
A note whose pitch clashes with the cantus firmus in two-part harmony.
12 13 14 15 |
# File 'lib/head_music/style/guidelines/dissonance_figure_detection.rb', line 12 def dissonant_with_cantus?(note) interval = HeadMusic::Analysis::HarmonicInterval.new(cantus_firmus, voice, note.position) interval.notes.length == 2 && interval.dissonance?(:two_part_harmony) end |
#double_neighbor_figure?(index, offset:) ⇒ Boolean (private)
Double neighbor: a four-note figure within one bar. Beats 1 and 4 are the same pitch (consonant), beats 2 and 3 are upper and lower neighbors connected by a leap of a third.
83 84 85 86 87 88 89 90 91 |
# File 'lib/head_music/style/guidelines/dissonance_figure_detection.rb', line 83 def double_neighbor_figure?(index, offset:) start = index - offset return false if start < 0 || start + 3 > notes.length - 1 n1, n2, n3, n4 = notes[start, 4] double_neighbor_shape?(n1, n2, n3, n4) && n1.pitch == n4.pitch && all_consonant_with_cantus?(n1, n4) end |
#double_neighbor_member?(note) ⇒ Boolean (private)
51 52 53 54 55 56 |
# File 'lib/head_music/style/guidelines/dissonance_figure_detection.rb', line 51 def double_neighbor_member?(note) index = notes.index(note) return false unless index double_neighbor_figure?(index, offset: 1) || double_neighbor_figure?(index, offset: 2) end |
#double_neighbor_shape?(n1, n2, n3, n4) ⇒ Boolean (private)
93 94 95 96 97 |
# File 'lib/head_music/style/guidelines/dissonance_figure_detection.rb', line 93 def double_neighbor_shape?(n1, n2, n3, n4) melodic_interval_between(n1, n2).step? && melodic_interval_between(n2, n3).number == 3 && melodic_interval_between(n3, n4).step? end |
#melodic_interval_between(note1, note2) ⇒ Object (private)
107 108 109 |
# File 'lib/head_music/style/guidelines/dissonance_figure_detection.rb', line 107 def melodic_interval_between(note1, note2) HeadMusic::Analysis::MelodicInterval.new(note1, note2) end |
#neighbor_tone?(note) ⇒ Boolean (private)
26 27 28 |
# File 'lib/head_music/style/guidelines/dissonance_figure_detection.rb', line 26 def neighbor_tone?(note) stepwise_figure?(note, same_direction: false) end |
#passing_tone?(note) ⇒ Boolean (private)
22 23 24 |
# File 'lib/head_music/style/guidelines/dissonance_figure_detection.rb', line 22 def passing_tone?(note) stepwise_figure?(note, same_direction: true) end |
#steps_back_from?(leap, step_back_1, step_back_2) ⇒ Boolean (private)
Notes 3-4-5 must both step in the direction opposite the leap.
74 75 76 77 78 |
# File 'lib/head_music/style/guidelines/dissonance_figure_detection.rb', line 74 def steps_back_from?(leap, step_back_1, step_back_2) step_back_1.step? && step_back_2.step? && step_back_1.direction != leap.direction && step_back_2.direction != leap.direction end |
#stepwise_figure?(note, same_direction:) ⇒ Boolean (private)
30 31 32 33 34 35 36 37 38 |
# File 'lib/head_music/style/guidelines/dissonance_figure_detection.rb', line 30 def stepwise_figure?(note, same_direction:) prev_note = preceding_note(note) next_note = following_note(note) return false unless prev_note && next_note approach = melodic_interval_between(prev_note, note) departure = melodic_interval_between(note, next_note) approach.step? && departure.step? && (approach.direction == departure.direction) == same_direction end |