Class: HeadMusic::Style::Guidelines::ThirdSpeciesDissonanceTreatment

Inherits:
WeakBeatDissonanceTreatment show all
Defined in:
lib/head_music/style/guidelines/third_species_dissonance_treatment.rb

Overview

A counterpoint guideline for third-species dissonance treatment. Every dissonant note on beats 2, 3, or 4 must be treated as a passing tone, neighbor tone, nota cambiata, or double neighbor figure.

Constant Summary collapse

MESSAGE =
"Treat dissonances as passing tones, neighbor tones, cambiata, or double neighbor figures."

Instance Method Summary collapse

Constructor Details

This class inherits a constructor from HeadMusic::Style::Annotation

Instance Method Details

#cambiata_as_note_2?(index) ⇒ Boolean (private)

Returns:

  • (Boolean)


39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/head_music/style/guidelines/third_species_dissonance_treatment.rb', line 39

def cambiata_as_note_2?(index)
  return false if index < 1 || index + 3 > notes.length - 1

  n1 = notes[index - 1]
  n2 = notes[index]
  n3 = notes[index + 1]
  n4 = notes[index + 2]
  n5 = notes[index + 3]

  approach = melodic_interval_between(n1, n2)
  leap = melodic_interval_between(n2, n3)
  step_back_1 = melodic_interval_between(n3, n4)
  step_back_2 = melodic_interval_between(n4, n5)

  approach.step? &&
    leap.number == 3 && approach.direction == leap.direction &&
    step_back_1.step? && step_back_2.step? &&
    step_back_1.direction != leap.direction &&
    step_back_2.direction != leap.direction &&
    consonant_with_cantus?(n1) && consonant_with_cantus?(n3) && consonant_with_cantus?(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.

Returns:

  • (Boolean)


32
33
34
35
36
37
# File 'lib/head_music/style/guidelines/third_species_dissonance_treatment.rb', line 32

def cambiata_dissonance?(note)
  index = notes.index(note)
  return false unless index

  cambiata_as_note_2?(index)
end

#consonant_with_cantus?(note) ⇒ Boolean (private)

Returns:

  • (Boolean)


89
90
91
# File 'lib/head_music/style/guidelines/third_species_dissonance_treatment.rb', line 89

def consonant_with_cantus?(note)
  !dissonant_with_cantus?(note)
end

#double_neighbor_figure?(index, offset:) ⇒ Boolean (private)

Check for a double-neighbor four-note figure where the given index is note number (offset + 1) in the figure. offset=1 means note 2, offset=2 means note 3.

Returns:

  • (Boolean)


74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/head_music/style/guidelines/third_species_dissonance_treatment.rb', line 74

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]

  approach = melodic_interval_between(n1, n2)
  middle = melodic_interval_between(n2, n3)
  departure = melodic_interval_between(n3, n4)

  approach.step? && middle.number == 3 && departure.step? &&
    n1.pitch == n4.pitch &&
    consonant_with_cantus?(n1) && consonant_with_cantus?(n4)
end

#double_neighbor_member?(note) ⇒ 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.

Returns:

  • (Boolean)


64
65
66
67
68
69
# File 'lib/head_music/style/guidelines/third_species_dissonance_treatment.rb', line 64

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

#neighbor_tone?(note) ⇒ Boolean (private)

Neighbor tone: approached by step, left by step in the opposite direction.

Returns:

  • (Boolean)


17
18
19
20
21
22
23
24
25
26
# File 'lib/head_music/style/guidelines/third_species_dissonance_treatment.rb', line 17

def neighbor_tone?(note)
  prev = preceding_note(note)
  foll = following_note(note)
  return false unless prev && foll

  approach = melodic_interval_between(prev, note)
  departure = melodic_interval_between(note, foll)

  approach.step? && departure.step? && approach.direction != departure.direction
end

#recognized_figure?(note) ⇒ Boolean (private)

Returns:

  • (Boolean)


12
13
14
# File 'lib/head_music/style/guidelines/third_species_dissonance_treatment.rb', line 12

def recognized_figure?(note)
  super || neighbor_tone?(note) || cambiata_dissonance?(note) || double_neighbor_member?(note)
end