Class: HeadMusic::Style::Guidelines::FloridDissonanceTreatment
Overview
Unified dissonance handling for mixed-species (florid) contexts.
- Strong beat dissonances must be properly prepared suspensions from a tie.
- Weak beat dissonances must be passing tones, neighbor tones, nota cambiata, or double neighbor figures.
- Tied notes dissonant at the new CF note must resolve by step to a consonance.
Constant Summary
collapse
- MESSAGE =
"Treat dissonances appropriately: passing tones, cambiata, or double neighbor " \
"on weak beats; proper suspension treatment for tied notes."
Instance Method Summary
collapse
Instance Method Details
#cambiata_dissonance?(note) ⇒ Boolean
Originally defined in module
DissonanceFigureDetection
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.
#cantus_firmus_positions ⇒ Object
59
60
61
|
# File 'lib/head_music/style/guidelines/florid_dissonance_treatment.rb', line 59
def cantus_firmus_positions
@cantus_firmus_positions ||= Set.new(cantus_firmus.notes.map { |note| note.position.to_s })
end
|
#current_cf_note_at(position) ⇒ Object
63
64
65
|
# File 'lib/head_music/style/guidelines/florid_dissonance_treatment.rb', line 63
def current_cf_note_at(position)
cantus_firmus.note_at(position)
end
|
#dissonant_with_cantus?(note) ⇒ Boolean
67
68
69
70
|
# File 'lib/head_music/style/guidelines/florid_dissonance_treatment.rb', line 67
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: 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.
#following_note(note) ⇒ Object
95
96
97
98
|
# File 'lib/head_music/style/guidelines/florid_dissonance_treatment.rb', line 95
def following_note(note)
index = notes.index(note)
notes[index + 1] if index && index < notes.length - 1
end
|
#improperly_treated_notes ⇒ Object
22
23
24
|
# File 'lib/head_music/style/guidelines/florid_dissonance_treatment.rb', line 22
def improperly_treated_notes
notes.select { |note| dissonant_with_cantus?(note) && !properly_treated?(note) }
end
|
#marks ⇒ Object
14
15
16
17
18
|
# File 'lib/head_music/style/guidelines/florid_dissonance_treatment.rb', line 14
def marks
return [] unless cantus_firmus&.notes&.any?
improperly_treated_notes.map { |note| HeadMusic::Style::Mark.for(note) }
end
|
#neighbor_tone?(note) ⇒ Boolean
76
77
78
|
# File 'lib/head_music/style/guidelines/florid_dissonance_treatment.rb', line 76
def neighbor_tone?(note)
stepwise_figure?(note, same_direction: false)
end
|
#on_strong_beat?(note) ⇒ Boolean
55
56
57
|
# File 'lib/head_music/style/guidelines/florid_dissonance_treatment.rb', line 55
def on_strong_beat?(note)
cantus_firmus_positions.include?(note.position.to_s)
end
|
#passing_tone?(note) ⇒ Boolean
72
73
74
|
# File 'lib/head_music/style/guidelines/florid_dissonance_treatment.rb', line 72
def passing_tone?(note)
stepwise_figure?(note, same_direction: true)
end
|
#preceding_note(note) ⇒ Object
90
91
92
93
|
# File 'lib/head_music/style/guidelines/florid_dissonance_treatment.rb', line 90
def preceding_note(note)
index = notes.index(note)
notes[index - 1] if index && index > 0
end
|
#properly_treated?(note) ⇒ Boolean
26
27
28
29
30
31
32
33
|
# File 'lib/head_music/style/guidelines/florid_dissonance_treatment.rb', line 26
def properly_treated?(note)
if on_strong_beat?(note)
properly_treated_suspension?(note)
else
passing_tone?(note) || neighbor_tone?(note) ||
cambiata_dissonance?(note) || double_neighbor_member?(note)
end
end
|
#properly_treated_suspension?(note) ⇒ Boolean
A note on a strong beat that is dissonant must be a tied suspension
(its position is before the CF note position, meaning it was held over).
37
38
39
40
41
42
43
|
# File 'lib/head_music/style/guidelines/florid_dissonance_treatment.rb', line 37
def properly_treated_suspension?(note)
cf_note = current_cf_note_at(note.position)
return false unless cf_note
note.position < cf_note.position && resolved_by_step?(note)
end
|
#resolved_by_step?(note) ⇒ Boolean
45
46
47
48
49
50
51
52
53
|
# File 'lib/head_music/style/guidelines/florid_dissonance_treatment.rb', line 45
def resolved_by_step?(note)
next_cp = following_note(note)
return false unless next_cp
melodic = melodic_interval_between(note, next_cp)
return false unless melodic.step?
consonant_with_cantus?(next_cp)
end
|
80
81
82
83
84
85
86
87
88
|
# File 'lib/head_music/style/guidelines/florid_dissonance_treatment.rb', line 80
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
|