head_music 12.3.0 → 12.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (24) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +1 -1
  3. data/lib/head_music/instruments/alternate_tunings.yml +22 -0
  4. data/lib/head_music/instruments/instruments.yml +1 -2
  5. data/lib/head_music/instruments/stringings.yml +23 -0
  6. data/lib/head_music/style/guidelines/allowed_rhythmic_values_for_combined123.rb +20 -0
  7. data/lib/head_music/style/guidelines/allowed_rhythmic_values_for_combined234.rb +23 -0
  8. data/lib/head_music/style/guidelines/allowed_rhythmic_values_for_fifth_species.rb +12 -0
  9. data/lib/head_music/style/guidelines/florid_dissonance_treatment.rb +96 -0
  10. data/lib/head_music/style/guidelines/mixed_rhythmic_values.rb +21 -0
  11. data/lib/head_music/style/guidelines/no_rests_after_note.rb +20 -0
  12. data/lib/head_music/style/guides/combined_first_second_third_species_harmony.rb +16 -0
  13. data/lib/head_music/style/guides/combined_first_second_third_species_melody.rb +22 -0
  14. data/lib/head_music/style/guides/combined_second_third_fourth_species_harmony.rb +18 -0
  15. data/lib/head_music/style/guides/combined_second_third_fourth_species_melody.rb +22 -0
  16. data/lib/head_music/style/guides/fifth_species_harmony.rb +18 -0
  17. data/lib/head_music/style/guides/fifth_species_melody.rb +23 -0
  18. data/lib/head_music/style/guides/fourth_species_melody.rb +2 -1
  19. data/lib/head_music/style/guides/second_species_melody.rb +2 -1
  20. data/lib/head_music/style/guides/third_species_melody.rb +2 -1
  21. data/lib/head_music/style/guides/third_species_triple_meter_melody.rb +2 -1
  22. data/lib/head_music/version.rb +1 -1
  23. data/lib/head_music.rb +12 -0
  24. metadata +14 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 20155b40b92a030588ea4b1c791efcc37c70aa40e5e2008b0d3a282cb72391a1
4
- data.tar.gz: e717940c964c2859dcf7181a5ae7997f99cabaf741f6d5ab73dc374977ae2f3f
3
+ metadata.gz: fc52f4684dac9eebefdc696f1d7f74094c98b26994905f7436cd757800880764
4
+ data.tar.gz: 3087c3c68254f16768f875538d54028db26498b8f7dfb8e543e7d402582a4581
5
5
  SHA512:
6
- metadata.gz: 9b97712e65e7ecb1df4dc400854aedfb1ed9fbf0654fdda348dc72d552c6e3f061eaa1dec9b02034d867c7279fe1ad5a6305dd9724cf4c47f8389463486f1f4b
7
- data.tar.gz: c3bd7b7c5bc5ea85790a7e15998eb25f9a32e6a249ffcbea26b4e420fdde5fad236e8e2ebf7a844405414e97a1104792f8ad0aae85862ed11712aa1103794490
6
+ metadata.gz: 6344e623f21eaad3c5c1dab093980062701d33ebca7f73050e211a7665afc2f81e49ef0de69e99f6a5c14d0d7797608cf35a88ca2c54c94590bbf404e575db9f
7
+ data.tar.gz: d28d37afdaae4bb89cbe3de6e1b9957fc5d19d3e54a03f1d9145092e7e7727545751365bad050b96a2f26a5b8f56972ebcbd99f9ad985c11a27e6e95636c174b
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- head_music (12.3.0)
4
+ head_music (12.4.0)
5
5
  activesupport (>= 7.0, < 10)
6
6
  humanize (~> 2.0)
7
7
  i18n (~> 1.8)
@@ -60,11 +60,33 @@ banjo:
60
60
  ukulele:
61
61
  low_g:
62
62
  semitones: [-12, 0, 0, 0]
63
+ d_tuning:
64
+ semitones: [2, 2, 2, 2]
63
65
  baritone:
64
66
  semitones: [-5, -5, -5, -5]
65
67
  slack_key:
66
68
  semitones: [0, 0, -1, 0]
67
69
 
70
+ baritone_ukulele:
71
+ high_d:
72
+ semitones: [12, 0, 0, 0]
73
+
74
+ double_bass:
75
+ solo_tuning:
76
+ semitones: [1, 1, 1, 1]
77
+ drop_d:
78
+ semitones: [-2, 0, 0, 0]
79
+ orchestral_c_extension:
80
+ semitones: [-4, 0, 0, 0]
81
+
82
+ mandolin:
83
+ gdgd:
84
+ semitones: [0, 0, -2, -2]
85
+ open_d:
86
+ semitones: [-1, 0, 0, -2]
87
+ cross_tuning:
88
+ semitones: [2, 2, 0, 0]
89
+
68
90
  violin:
69
91
  solo_tuning:
70
92
  semitones: [1, 1, 1, 1]
@@ -218,9 +218,8 @@ bass_tuba_in_e_flat:
218
218
  bass_ukulele:
219
219
  family_key: ukulele
220
220
  range_categories:
221
+ - contrabass
221
222
  - bass
222
- - baritone
223
- - tenor
224
223
  staff_schemes:
225
224
  default:
226
225
  - clef: bass_clef
@@ -70,6 +70,29 @@ baritone_ukulele:
70
70
  - pitch: B3
71
71
  - pitch: E4
72
72
 
73
+ bass_ukulele:
74
+ courses:
75
+ - pitch: E1
76
+ - pitch: A1
77
+ - pitch: D2
78
+ - pitch: G2
79
+
80
+ pocket_ukulele:
81
+ courses:
82
+ - pitch: D5
83
+ - pitch: G4
84
+ - pitch: B4
85
+ - pitch: E5
86
+
87
+ arpeggione:
88
+ courses:
89
+ - pitch: E2
90
+ - pitch: A2
91
+ - pitch: D3
92
+ - pitch: G3
93
+ - pitch: B3
94
+ - pitch: E4
95
+
73
96
  mandolin:
74
97
  courses:
75
98
  - pitch: G3
@@ -0,0 +1,20 @@
1
+ # Module for style guidelines.
2
+ module HeadMusic::Style::Guidelines; end
3
+
4
+ # Validates that counterpoint notes use only whole, half, or quarter note rhythmic values.
5
+ # Appropriate for combined first, second, and third species counterpoint.
6
+ class HeadMusic::Style::Guidelines::AllowedRhythmicValuesForCombined123 < HeadMusic::Style::Annotation
7
+ MESSAGE = "Use only whole notes, half notes, and quarter notes."
8
+
9
+ ALLOWED_TOTAL_VALUES = [1.0, 0.5, 0.25].freeze
10
+
11
+ def marks
12
+ violating_notes.map { |note| HeadMusic::Style::Mark.for(note) }
13
+ end
14
+
15
+ private
16
+
17
+ def violating_notes
18
+ notes.reject { |note| ALLOWED_TOTAL_VALUES.include?(note.rhythmic_value.total_value) }
19
+ end
20
+ end
@@ -0,0 +1,23 @@
1
+ # Module for style guidelines.
2
+ module HeadMusic::Style::Guidelines; end
3
+
4
+ # Validates that counterpoint notes use only half notes, quarter notes, and tied notes.
5
+ # No whole notes filling an entire bar from beat 1.
6
+ # Appropriate for combined second, third, and fourth species counterpoint.
7
+ class HeadMusic::Style::Guidelines::AllowedRhythmicValuesForCombined234 < HeadMusic::Style::Annotation
8
+ MESSAGE = "Use only half notes, quarter notes, and tied notes. Avoid whole notes on beat 1."
9
+
10
+ def marks
11
+ violating_notes.map { |note| HeadMusic::Style::Mark.for(note) }
12
+ end
13
+
14
+ private
15
+
16
+ def violating_notes
17
+ notes.select { |note| whole_note_on_downbeat?(note) }
18
+ end
19
+
20
+ def whole_note_on_downbeat?(note)
21
+ note.rhythmic_value.total_value >= 1.0 && note.position.count == 1
22
+ end
23
+ end
@@ -0,0 +1,12 @@
1
+ # Module for style guidelines.
2
+ module HeadMusic::Style::Guidelines; end
3
+
4
+ # All rhythmic values are allowed in fifth species counterpoint.
5
+ # This guideline is always adherent.
6
+ class HeadMusic::Style::Guidelines::AllowedRhythmicValuesForFifthSpecies < HeadMusic::Style::Annotation
7
+ MESSAGE = "All rhythmic values are allowed in fifth species."
8
+
9
+ def marks
10
+ []
11
+ end
12
+ end
@@ -0,0 +1,96 @@
1
+ # Module for style guidelines.
2
+ module HeadMusic::Style::Guidelines; end
3
+
4
+ # Unified dissonance handling for mixed-species (florid) contexts.
5
+ # - Strong beat dissonances must be properly prepared suspensions from a tie.
6
+ # - Weak beat dissonances must be passing tones or neighbor tones.
7
+ # - Tied notes dissonant at the new CF note must resolve by step to a consonance.
8
+ class HeadMusic::Style::Guidelines::FloridDissonanceTreatment < HeadMusic::Style::Annotation
9
+ MESSAGE = "Treat dissonances appropriately: passing tones on weak beats, proper suspension treatment for tied notes."
10
+
11
+ def marks
12
+ return [] unless cantus_firmus&.notes&.any?
13
+
14
+ improperly_treated_notes.map { |note| HeadMusic::Style::Mark.for(note) }
15
+ end
16
+
17
+ private
18
+
19
+ def improperly_treated_notes
20
+ notes.select { |note| dissonant_with_cantus?(note) && !properly_treated?(note) }
21
+ end
22
+
23
+ def properly_treated?(note)
24
+ if on_strong_beat?(note)
25
+ properly_treated_suspension?(note)
26
+ else
27
+ passing_tone?(note) || neighbor_tone?(note)
28
+ end
29
+ end
30
+
31
+ # A note on a strong beat that is dissonant must be a tied suspension
32
+ # (its position is before the CF note position, meaning it was held over).
33
+ def properly_treated_suspension?(note)
34
+ cf_note = current_cf_note_at(note.position)
35
+ return false unless cf_note
36
+
37
+ # The CP note must have started before the CF note (tied over)
38
+ note.position < cf_note.position && resolved_by_step?(note)
39
+ end
40
+
41
+ def resolved_by_step?(note)
42
+ next_cp = following_note(note)
43
+ return false unless next_cp
44
+
45
+ melodic = HeadMusic::Analysis::MelodicInterval.new(note, next_cp)
46
+ return false unless melodic.step?
47
+
48
+ # Resolution must be consonant
49
+ !dissonant_with_cantus?(next_cp)
50
+ end
51
+
52
+ def on_strong_beat?(note)
53
+ cantus_firmus_positions.include?(note.position.to_s)
54
+ end
55
+
56
+ def cantus_firmus_positions
57
+ @cantus_firmus_positions ||= Set.new(cantus_firmus.notes.map { |note| note.position.to_s })
58
+ end
59
+
60
+ def current_cf_note_at(position)
61
+ cantus_firmus.note_at(position)
62
+ end
63
+
64
+ def dissonant_with_cantus?(note)
65
+ interval = HeadMusic::Analysis::HarmonicInterval.new(cantus_firmus, voice, note.position)
66
+ interval.notes.length == 2 && interval.dissonance?(:two_part_harmony)
67
+ end
68
+
69
+ def passing_tone?(note)
70
+ stepwise_figure?(note, same_direction: true)
71
+ end
72
+
73
+ def neighbor_tone?(note)
74
+ stepwise_figure?(note, same_direction: false)
75
+ end
76
+
77
+ def stepwise_figure?(note, same_direction:)
78
+ prev_note = preceding_note(note)
79
+ next_note = following_note(note)
80
+ return false unless prev_note && next_note
81
+
82
+ approach = HeadMusic::Analysis::MelodicInterval.new(prev_note, note)
83
+ departure = HeadMusic::Analysis::MelodicInterval.new(note, next_note)
84
+ approach.step? && departure.step? && (approach.direction == departure.direction) == same_direction
85
+ end
86
+
87
+ def preceding_note(note)
88
+ index = notes.index(note)
89
+ notes[index - 1] if index && index > 0
90
+ end
91
+
92
+ def following_note(note)
93
+ index = notes.index(note)
94
+ notes[index + 1] if index && index < notes.length - 1
95
+ end
96
+ end
@@ -0,0 +1,21 @@
1
+ # Module for style guidelines.
2
+ module HeadMusic::Style::Guidelines; end
3
+
4
+ # Checks that the voice uses at least 2 different rhythmic value durations.
5
+ # For full fifth species counterpoint.
6
+ class HeadMusic::Style::Guidelines::MixedRhythmicValues < HeadMusic::Style::Annotation
7
+ MESSAGE = "Use a variety of rhythmic values for an expressive florid line."
8
+
9
+ def marks
10
+ return [] if notes.length < 2
11
+ return [] if distinct_durations_count >= 2
12
+
13
+ [HeadMusic::Style::Mark.for(notes.first)]
14
+ end
15
+
16
+ private
17
+
18
+ def distinct_durations_count
19
+ notes.map { |note| note.rhythmic_value.total_value }.uniq.length
20
+ end
21
+ end
@@ -0,0 +1,20 @@
1
+ # Module for style guidelines.
2
+ module HeadMusic::Style::Guidelines; end
3
+
4
+ # Once the first note has sounded, no rests are permitted for the remainder
5
+ # of the voice. Rests before the first note (a leading rest) are allowed.
6
+ class HeadMusic::Style::Guidelines::NoRestsAfterNote < HeadMusic::Style::Annotation
7
+ MESSAGE = "Do not rest after the first note has sounded."
8
+
9
+ def marks
10
+ return [] if rests.empty? || notes.empty?
11
+
12
+ HeadMusic::Style::Mark.for_each(rests_after_first_note)
13
+ end
14
+
15
+ private
16
+
17
+ def rests_after_first_note
18
+ rests.select { |rest| rest.position >= first_note.position }
19
+ end
20
+ end
@@ -0,0 +1,16 @@
1
+ # Module for guides
2
+ module HeadMusic::Style::Guides; end
3
+
4
+ # Rules for combined first, second, and third species harmony
5
+ class HeadMusic::Style::Guides::CombinedFirstSecondThirdSpeciesHarmony < HeadMusic::Style::Guides::SpeciesHarmony
6
+ RULESET = [
7
+ HeadMusic::Style::Guidelines::ApproachPerfectionContrarily,
8
+ HeadMusic::Style::Guidelines::AvoidCrossingVoices,
9
+ HeadMusic::Style::Guidelines::AvoidOverlappingVoices,
10
+ HeadMusic::Style::Guidelines::ConsonantDownbeats,
11
+ HeadMusic::Style::Guidelines::NoParallelPerfectOnDownbeats,
12
+ HeadMusic::Style::Guidelines::PreferContraryMotion,
13
+ HeadMusic::Style::Guidelines::PreferImperfect,
14
+ HeadMusic::Style::Guidelines::FloridDissonanceTreatment
15
+ ].freeze
16
+ end
@@ -0,0 +1,22 @@
1
+ # Module for guides
2
+ module HeadMusic::Style::Guides; end
3
+
4
+ # Rules for combined first, second, and third species melodies
5
+ class HeadMusic::Style::Guides::CombinedFirstSecondThirdSpeciesMelody < HeadMusic::Style::Guides::SpeciesMelody
6
+ RULESET = [
7
+ HeadMusic::Style::Guidelines::AlwaysMove,
8
+ HeadMusic::Style::Guidelines::ConsonantClimax,
9
+ HeadMusic::Style::Guidelines::Diatonic,
10
+ HeadMusic::Style::Guidelines::EndOnTonic,
11
+ HeadMusic::Style::Guidelines::FrequentDirectionChanges,
12
+ HeadMusic::Style::Guidelines::LimitOctaveLeaps,
13
+ HeadMusic::Style::Guidelines::MostlyConjunct,
14
+ HeadMusic::Style::Guidelines::PrepareOctaveLeaps,
15
+ HeadMusic::Style::Guidelines::SingableIntervals,
16
+ HeadMusic::Style::Guidelines::SingableRange,
17
+ HeadMusic::Style::Guidelines::StartOnPerfectConsonance,
18
+ HeadMusic::Style::Guidelines::StepUpToFinalNote,
19
+ HeadMusic::Style::Guidelines::AllowedRhythmicValuesForCombined123,
20
+ HeadMusic::Style::Guidelines::NoRestsAfterNote
21
+ ].freeze
22
+ end
@@ -0,0 +1,18 @@
1
+ # Module for guides
2
+ module HeadMusic::Style::Guides; end
3
+
4
+ # Rules for combined second, third, and fourth species harmony
5
+ class HeadMusic::Style::Guides::CombinedSecondThirdFourthSpeciesHarmony < HeadMusic::Style::Guides::SpeciesHarmony
6
+ RULESET = [
7
+ HeadMusic::Style::Guidelines::ApproachPerfectionContrarily,
8
+ HeadMusic::Style::Guidelines::AvoidCrossingVoices,
9
+ HeadMusic::Style::Guidelines::AvoidOverlappingVoices,
10
+ HeadMusic::Style::Guidelines::ConsonantDownbeats,
11
+ HeadMusic::Style::Guidelines::NoParallelPerfectOnDownbeats,
12
+ HeadMusic::Style::Guidelines::NoParallelPerfectWithSyncopation,
13
+ HeadMusic::Style::Guidelines::PreferContraryMotion,
14
+ HeadMusic::Style::Guidelines::PreferImperfect,
15
+ HeadMusic::Style::Guidelines::FloridDissonanceTreatment,
16
+ HeadMusic::Style::Guidelines::SuspensionTreatment
17
+ ].freeze
18
+ end
@@ -0,0 +1,22 @@
1
+ # Module for guides
2
+ module HeadMusic::Style::Guides; end
3
+
4
+ # Rules for combined second, third, and fourth species melodies
5
+ class HeadMusic::Style::Guides::CombinedSecondThirdFourthSpeciesMelody < HeadMusic::Style::Guides::SpeciesMelody
6
+ RULESET = [
7
+ HeadMusic::Style::Guidelines::AlwaysMove,
8
+ HeadMusic::Style::Guidelines::ConsonantClimax,
9
+ HeadMusic::Style::Guidelines::Diatonic,
10
+ HeadMusic::Style::Guidelines::EndOnTonic,
11
+ HeadMusic::Style::Guidelines::FrequentDirectionChanges,
12
+ HeadMusic::Style::Guidelines::LimitOctaveLeaps,
13
+ HeadMusic::Style::Guidelines::MostlyConjunct,
14
+ HeadMusic::Style::Guidelines::PrepareOctaveLeaps,
15
+ HeadMusic::Style::Guidelines::SingableIntervals,
16
+ HeadMusic::Style::Guidelines::SingableRange,
17
+ HeadMusic::Style::Guidelines::StartOnPerfectConsonance,
18
+ HeadMusic::Style::Guidelines::StepUpToFinalNote,
19
+ HeadMusic::Style::Guidelines::AllowedRhythmicValuesForCombined234,
20
+ HeadMusic::Style::Guidelines::NoRestsAfterNote
21
+ ].freeze
22
+ end
@@ -0,0 +1,18 @@
1
+ # Module for guides
2
+ module HeadMusic::Style::Guides; end
3
+
4
+ # Rules for fifth species (florid) harmony
5
+ class HeadMusic::Style::Guides::FifthSpeciesHarmony < HeadMusic::Style::Guides::SpeciesHarmony
6
+ RULESET = [
7
+ HeadMusic::Style::Guidelines::ApproachPerfectionContrarily,
8
+ HeadMusic::Style::Guidelines::AvoidCrossingVoices,
9
+ HeadMusic::Style::Guidelines::AvoidOverlappingVoices,
10
+ HeadMusic::Style::Guidelines::ConsonantDownbeats,
11
+ HeadMusic::Style::Guidelines::NoParallelPerfectOnDownbeats,
12
+ HeadMusic::Style::Guidelines::NoParallelPerfectWithSyncopation,
13
+ HeadMusic::Style::Guidelines::PreferContraryMotion,
14
+ HeadMusic::Style::Guidelines::PreferImperfect,
15
+ HeadMusic::Style::Guidelines::FloridDissonanceTreatment,
16
+ HeadMusic::Style::Guidelines::SuspensionTreatment
17
+ ].freeze
18
+ end
@@ -0,0 +1,23 @@
1
+ # Module for guides
2
+ module HeadMusic::Style::Guides; end
3
+
4
+ # Rules for fifth species (florid) melodies
5
+ class HeadMusic::Style::Guides::FifthSpeciesMelody < HeadMusic::Style::Guides::SpeciesMelody
6
+ RULESET = [
7
+ HeadMusic::Style::Guidelines::AlwaysMove,
8
+ HeadMusic::Style::Guidelines::ConsonantClimax,
9
+ HeadMusic::Style::Guidelines::Diatonic,
10
+ HeadMusic::Style::Guidelines::EndOnTonic,
11
+ HeadMusic::Style::Guidelines::FrequentDirectionChanges,
12
+ HeadMusic::Style::Guidelines::LimitOctaveLeaps,
13
+ HeadMusic::Style::Guidelines::MostlyConjunct,
14
+ HeadMusic::Style::Guidelines::PrepareOctaveLeaps,
15
+ HeadMusic::Style::Guidelines::SingableIntervals,
16
+ HeadMusic::Style::Guidelines::SingableRange,
17
+ HeadMusic::Style::Guidelines::StartOnPerfectConsonance,
18
+ HeadMusic::Style::Guidelines::StepUpToFinalNote,
19
+ HeadMusic::Style::Guidelines::AllowedRhythmicValuesForFifthSpecies,
20
+ HeadMusic::Style::Guidelines::MixedRhythmicValues,
21
+ HeadMusic::Style::Guidelines::NoRestsAfterNote
22
+ ].freeze
23
+ end
@@ -18,6 +18,7 @@ class HeadMusic::Style::Guides::FourthSpeciesMelody < HeadMusic::Style::Guides::
18
18
  HeadMusic::Style::Guidelines::SingableRange,
19
19
  HeadMusic::Style::Guidelines::StartOnPerfectConsonance,
20
20
  HeadMusic::Style::Guidelines::StepOutOfUnison,
21
- HeadMusic::Style::Guidelines::StepUpToFinalNote
21
+ HeadMusic::Style::Guidelines::StepUpToFinalNote,
22
+ HeadMusic::Style::Guidelines::NoRestsAfterNote
22
23
  ].freeze
23
24
  end
@@ -19,6 +19,7 @@ class HeadMusic::Style::Guides::SecondSpeciesMelody < HeadMusic::Style::Guides::
19
19
  HeadMusic::Style::Guidelines::StartOnPerfectConsonance,
20
20
  HeadMusic::Style::Guidelines::StepOutOfUnison,
21
21
  HeadMusic::Style::Guidelines::StepUpToFinalNote,
22
- HeadMusic::Style::Guidelines::TwoPerBar
22
+ HeadMusic::Style::Guidelines::TwoPerBar,
23
+ HeadMusic::Style::Guidelines::NoRestsAfterNote
23
24
  ].freeze
24
25
  end
@@ -19,6 +19,7 @@ class HeadMusic::Style::Guides::ThirdSpeciesMelody < HeadMusic::Style::Guides::S
19
19
  HeadMusic::Style::Guidelines::SingableRange,
20
20
  HeadMusic::Style::Guidelines::StartOnPerfectConsonance,
21
21
  HeadMusic::Style::Guidelines::StepOutOfUnison,
22
- HeadMusic::Style::Guidelines::StepUpToFinalNote
22
+ HeadMusic::Style::Guidelines::StepUpToFinalNote,
23
+ HeadMusic::Style::Guidelines::NoRestsAfterNote
23
24
  ].freeze
24
25
  end
@@ -19,6 +19,7 @@ class HeadMusic::Style::Guides::ThirdSpeciesTripleMeterMelody < HeadMusic::Style
19
19
  HeadMusic::Style::Guidelines::StartOnPerfectConsonance,
20
20
  HeadMusic::Style::Guidelines::StepOutOfUnison,
21
21
  HeadMusic::Style::Guidelines::StepUpToFinalNote,
22
- HeadMusic::Style::Guidelines::ThreePerBar
22
+ HeadMusic::Style::Guidelines::ThreePerBar,
23
+ HeadMusic::Style::Guidelines::NoRestsAfterNote
23
24
  ].freeze
24
25
  end
@@ -1,3 +1,3 @@
1
1
  module HeadMusic
2
- VERSION = "12.3.0"
2
+ VERSION = "12.4.0"
3
3
  end
data/lib/head_music.rb CHANGED
@@ -178,6 +178,7 @@ require "head_music/style/guidelines/no_parallel_perfect_across_barline"
178
178
  require "head_music/style/guidelines/no_parallel_perfect_on_downbeats"
179
179
  require "head_music/style/guidelines/no_parallel_perfect_with_syncopation"
180
180
  require "head_music/style/guidelines/no_rests"
181
+ require "head_music/style/guidelines/no_rests_after_note"
181
182
  require "head_music/style/guidelines/no_strong_beat_unisons"
182
183
  require "head_music/style/guidelines/no_unisons_in_middle"
183
184
  require "head_music/style/guidelines/one_to_one"
@@ -204,6 +205,11 @@ require "head_music/style/guidelines/weak_beat_dissonance_treatment"
204
205
  require "head_music/style/guidelines/third_species_dissonance_treatment"
205
206
  require "head_music/style/guidelines/triple_meter_dissonance_treatment"
206
207
  require "head_music/style/guidelines/second_species_break"
208
+ require "head_music/style/guidelines/allowed_rhythmic_values_for_combined123"
209
+ require "head_music/style/guidelines/allowed_rhythmic_values_for_combined234"
210
+ require "head_music/style/guidelines/allowed_rhythmic_values_for_fifth_species"
211
+ require "head_music/style/guidelines/florid_dissonance_treatment"
212
+ require "head_music/style/guidelines/mixed_rhythmic_values"
207
213
 
208
214
  # style guides
209
215
  require "head_music/style/guides/species_melody"
@@ -220,3 +226,9 @@ require "head_music/style/guides/third_species_melody"
220
226
  require "head_music/style/guides/third_species_harmony"
221
227
  require "head_music/style/guides/fourth_species_melody"
222
228
  require "head_music/style/guides/fourth_species_harmony"
229
+ require "head_music/style/guides/combined_first_second_third_species_melody"
230
+ require "head_music/style/guides/combined_first_second_third_species_harmony"
231
+ require "head_music/style/guides/combined_second_third_fourth_species_melody"
232
+ require "head_music/style/guides/combined_second_third_fourth_species_harmony"
233
+ require "head_music/style/guides/fifth_species_melody"
234
+ require "head_music/style/guides/fifth_species_harmony"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: head_music
3
3
  version: !ruby/object:Gem::Version
4
- version: 12.3.0
4
+ version: 12.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rob Head
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-02-25 00:00:00.000000000 Z
11
+ date: 2026-04-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -268,6 +268,9 @@ files:
268
268
  - lib/head_music/rudiment/unpitched_note.rb
269
269
  - lib/head_music/style/analysis.rb
270
270
  - lib/head_music/style/annotation.rb
271
+ - lib/head_music/style/guidelines/allowed_rhythmic_values_for_combined123.rb
272
+ - lib/head_music/style/guidelines/allowed_rhythmic_values_for_combined234.rb
273
+ - lib/head_music/style/guidelines/allowed_rhythmic_values_for_fifth_species.rb
271
274
  - lib/head_music/style/guidelines/always_move.rb
272
275
  - lib/head_music/style/guidelines/approach_perfection_contrarily.rb
273
276
  - lib/head_music/style/guidelines/at_least_eight_notes.rb
@@ -284,15 +287,18 @@ files:
284
287
  - lib/head_music/style/guidelines/first_bar_half_notes.rb
285
288
  - lib/head_music/style/guidelines/first_bar_quarter_notes.rb
286
289
  - lib/head_music/style/guidelines/first_bar_whole_note.rb
290
+ - lib/head_music/style/guidelines/florid_dissonance_treatment.rb
287
291
  - lib/head_music/style/guidelines/four_per_bar.rb
288
292
  - lib/head_music/style/guidelines/frequent_direction_changes.rb
289
293
  - lib/head_music/style/guidelines/limit_octave_leaps.rb
294
+ - lib/head_music/style/guidelines/mixed_rhythmic_values.rb
290
295
  - lib/head_music/style/guidelines/moderate_direction_changes.rb
291
296
  - lib/head_music/style/guidelines/mostly_conjunct.rb
292
297
  - lib/head_music/style/guidelines/no_parallel_perfect_across_barline.rb
293
298
  - lib/head_music/style/guidelines/no_parallel_perfect_on_downbeats.rb
294
299
  - lib/head_music/style/guidelines/no_parallel_perfect_with_syncopation.rb
295
300
  - lib/head_music/style/guidelines/no_rests.rb
301
+ - lib/head_music/style/guidelines/no_rests_after_note.rb
296
302
  - lib/head_music/style/guidelines/no_strong_beat_unisons.rb
297
303
  - lib/head_music/style/guidelines/no_unisons_in_middle.rb
298
304
  - lib/head_music/style/guidelines/note_count_per_bar.rb
@@ -322,6 +328,12 @@ files:
322
328
  - lib/head_music/style/guidelines/two_per_bar.rb
323
329
  - lib/head_music/style/guidelines/up_to_fourteen_notes.rb
324
330
  - lib/head_music/style/guidelines/weak_beat_dissonance_treatment.rb
331
+ - lib/head_music/style/guides/combined_first_second_third_species_harmony.rb
332
+ - lib/head_music/style/guides/combined_first_second_third_species_melody.rb
333
+ - lib/head_music/style/guides/combined_second_third_fourth_species_harmony.rb
334
+ - lib/head_music/style/guides/combined_second_third_fourth_species_melody.rb
335
+ - lib/head_music/style/guides/fifth_species_harmony.rb
336
+ - lib/head_music/style/guides/fifth_species_melody.rb
325
337
  - lib/head_music/style/guides/first_species_harmony.rb
326
338
  - lib/head_music/style/guides/first_species_melody.rb
327
339
  - lib/head_music/style/guides/fourth_species_harmony.rb