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). 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
-
#consonant_with_cantus?(note) ⇒ Boolean
private
-
#dissonant_with_cantus?(note) ⇒ Boolean
private
-
#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
-
#stepwise_figure?(note, same_direction:) ⇒ Boolean
private
Instance Method Details
#all_consonant_with_cantus?(*checked_notes) ⇒ Boolean (private)
94 95 96 |
# File 'lib/head_music/style/guidelines/dissonance_figure_detection.rb', line 94 def all_consonant_with_cantus?(*checked_notes) checked_notes.all? { |note| consonant_with_cantus?(note) } end |
#cambiata_as_note_2?(index) ⇒ Boolean (private)
54 55 56 57 58 59 |
# File 'lib/head_music/style/guidelines/dissonance_figure_detection.rb', line 54 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.
40 41 42 43 44 45 |
# File 'lib/head_music/style/guidelines/dissonance_figure_detection.rb', line 40 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)
61 62 63 64 65 66 67 |
# File 'lib/head_music/style/guidelines/dissonance_figure_detection.rb', line 61 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)
14 15 16 |
# File 'lib/head_music/style/guidelines/dissonance_figure_detection.rb', line 14 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)
98 99 100 |
# File 'lib/head_music/style/guidelines/dissonance_figure_detection.rb', line 98 def consonant_with_cantus?(note) !dissonant_with_cantus?(note) end |
#dissonant_with_cantus?(note) ⇒ Boolean (private)
9 10 11 12 |
# File 'lib/head_music/style/guidelines/dissonance_figure_detection.rb', line 9 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.
78 79 80 81 82 83 84 85 86 |
# File 'lib/head_music/style/guidelines/dissonance_figure_detection.rb', line 78 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)
47 48 49 50 51 52 |
# File 'lib/head_music/style/guidelines/dissonance_figure_detection.rb', line 47 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)
88 89 90 91 92 |
# File 'lib/head_music/style/guidelines/dissonance_figure_detection.rb', line 88 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)
102 103 104 |
# File 'lib/head_music/style/guidelines/dissonance_figure_detection.rb', line 102 def melodic_interval_between(note1, note2) HeadMusic::Analysis::MelodicInterval.new(note1, note2) end |
#neighbor_tone?(note) ⇒ Boolean (private)
22 23 24 |
# File 'lib/head_music/style/guidelines/dissonance_figure_detection.rb', line 22 def neighbor_tone?(note) stepwise_figure?(note, same_direction: false) end |
#passing_tone?(note) ⇒ Boolean (private)
18 19 20 |
# File 'lib/head_music/style/guidelines/dissonance_figure_detection.rb', line 18 def passing_tone?(note) stepwise_figure?(note, same_direction: true) end |
#steps_back_from?(leap, step_back_1, step_back_2) ⇒ Boolean (private)
69 70 71 72 73 |
# File 'lib/head_music/style/guidelines/dissonance_figure_detection.rb', line 69 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)
26 27 28 29 30 31 32 33 34 |
# File 'lib/head_music/style/guidelines/dissonance_figure_detection.rb', line 26 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 |