head_music 8.3.0 → 11.0.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 (138) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +9 -3
  3. data/CHANGELOG.md +71 -0
  4. data/CLAUDE.md +62 -25
  5. data/Gemfile +7 -1
  6. data/Gemfile.lock +91 -3
  7. data/MUSIC_THEORY.md +120 -0
  8. data/README.md +18 -0
  9. data/Rakefile +7 -2
  10. data/head_music.gemspec +1 -1
  11. data/lib/head_music/analysis/diatonic_interval.rb +29 -27
  12. data/lib/head_music/analysis/dyad.rb +229 -0
  13. data/lib/head_music/analysis/interval_consonance.rb +51 -0
  14. data/lib/head_music/analysis/melodic_interval.rb +1 -1
  15. data/lib/head_music/analysis/pitch_class_set.rb +111 -14
  16. data/lib/head_music/analysis/{pitch_set.rb → pitch_collection.rb} +11 -5
  17. data/lib/head_music/analysis/sonority.rb +50 -12
  18. data/lib/head_music/content/note.rb +1 -1
  19. data/lib/head_music/content/placement.rb +1 -1
  20. data/lib/head_music/content/position.rb +1 -1
  21. data/lib/head_music/content/voice.rb +1 -1
  22. data/lib/head_music/instruments/alternate_tuning.rb +102 -0
  23. data/lib/head_music/instruments/alternate_tunings.yml +78 -0
  24. data/lib/head_music/instruments/instrument.rb +231 -72
  25. data/lib/head_music/instruments/instrument_configuration.rb +66 -0
  26. data/lib/head_music/instruments/instrument_configuration_option.rb +38 -0
  27. data/lib/head_music/instruments/instrument_configurations.yml +288 -0
  28. data/lib/head_music/instruments/instrument_families.yml +77 -0
  29. data/lib/head_music/instruments/instrument_family.rb +15 -5
  30. data/lib/head_music/instruments/instruments.yml +795 -965
  31. data/lib/head_music/instruments/playing_technique.rb +75 -0
  32. data/lib/head_music/instruments/playing_techniques.yml +826 -0
  33. data/lib/head_music/instruments/score_order.rb +136 -0
  34. data/lib/head_music/instruments/score_orders.yml +130 -0
  35. data/lib/head_music/instruments/staff.rb +61 -1
  36. data/lib/head_music/instruments/staff_scheme.rb +6 -4
  37. data/lib/head_music/instruments/stringing.rb +115 -0
  38. data/lib/head_music/instruments/stringing_course.rb +58 -0
  39. data/lib/head_music/instruments/stringings.yml +168 -0
  40. data/lib/head_music/instruments/variant.rb +6 -1
  41. data/lib/head_music/locales/de.yml +29 -0
  42. data/lib/head_music/locales/en.yml +106 -0
  43. data/lib/head_music/locales/es.yml +29 -0
  44. data/lib/head_music/locales/fr.yml +29 -0
  45. data/lib/head_music/locales/it.yml +29 -0
  46. data/lib/head_music/locales/ru.yml +29 -0
  47. data/lib/head_music/{rudiment → notation}/musical_symbol.rb +3 -3
  48. data/lib/head_music/notation/staff_mapping.rb +70 -0
  49. data/lib/head_music/notation/staff_position.rb +62 -0
  50. data/lib/head_music/notation.rb +7 -0
  51. data/lib/head_music/rudiment/alteration.rb +34 -49
  52. data/lib/head_music/rudiment/alterations.yml +32 -0
  53. data/lib/head_music/rudiment/base.rb +9 -0
  54. data/lib/head_music/rudiment/chromatic_interval.rb +4 -7
  55. data/lib/head_music/rudiment/clef.rb +2 -2
  56. data/lib/head_music/rudiment/consonance.rb +39 -5
  57. data/lib/head_music/rudiment/diatonic_context.rb +25 -0
  58. data/lib/head_music/rudiment/key.rb +77 -0
  59. data/lib/head_music/rudiment/key_signature/enharmonic_equivalence.rb +1 -1
  60. data/lib/head_music/rudiment/key_signature.rb +21 -8
  61. data/lib/head_music/rudiment/letter_name.rb +3 -3
  62. data/lib/head_music/rudiment/meter.rb +19 -9
  63. data/lib/head_music/rudiment/mode.rb +92 -0
  64. data/lib/head_music/rudiment/note.rb +112 -0
  65. data/lib/head_music/rudiment/pitch/parser.rb +52 -0
  66. data/lib/head_music/rudiment/pitch.rb +5 -6
  67. data/lib/head_music/rudiment/pitch_class.rb +1 -1
  68. data/lib/head_music/rudiment/quality.rb +1 -1
  69. data/lib/head_music/rudiment/reference_pitch.rb +1 -1
  70. data/lib/head_music/rudiment/register.rb +4 -1
  71. data/lib/head_music/rudiment/rest.rb +36 -0
  72. data/lib/head_music/rudiment/rhythmic_element.rb +53 -0
  73. data/lib/head_music/rudiment/rhythmic_unit/parser.rb +86 -0
  74. data/lib/head_music/rudiment/rhythmic_unit.rb +13 -5
  75. data/lib/head_music/rudiment/rhythmic_units.yml +80 -0
  76. data/lib/head_music/rudiment/rhythmic_value/parser.rb +77 -0
  77. data/lib/head_music/{content → rudiment}/rhythmic_value.rb +23 -5
  78. data/lib/head_music/rudiment/scale.rb +4 -5
  79. data/lib/head_music/rudiment/scale_degree.rb +1 -1
  80. data/lib/head_music/rudiment/scale_type.rb +9 -3
  81. data/lib/head_music/rudiment/solmization.rb +1 -1
  82. data/lib/head_music/rudiment/spelling.rb +8 -4
  83. data/lib/head_music/rudiment/tempo.rb +85 -0
  84. data/lib/head_music/rudiment/tonal_context.rb +35 -0
  85. data/lib/head_music/rudiment/tuning/just_intonation.rb +0 -39
  86. data/lib/head_music/rudiment/tuning/meantone.rb +0 -39
  87. data/lib/head_music/rudiment/tuning/pythagorean.rb +0 -39
  88. data/lib/head_music/rudiment/tuning.rb +21 -1
  89. data/lib/head_music/rudiment/unpitched_note.rb +62 -0
  90. data/lib/head_music/style/guidelines/consonant_climax.rb +2 -2
  91. data/lib/head_music/style/medieval_tradition.rb +26 -0
  92. data/lib/head_music/style/modern_tradition.rb +31 -0
  93. data/lib/head_music/style/renaissance_tradition.rb +26 -0
  94. data/lib/head_music/style/tradition.rb +21 -0
  95. data/lib/head_music/time/clock_position.rb +84 -0
  96. data/lib/head_music/time/conductor.rb +264 -0
  97. data/lib/head_music/time/meter_event.rb +37 -0
  98. data/lib/head_music/time/meter_map.rb +173 -0
  99. data/lib/head_music/time/musical_position.rb +188 -0
  100. data/lib/head_music/time/smpte_timecode.rb +164 -0
  101. data/lib/head_music/time/tempo_event.rb +40 -0
  102. data/lib/head_music/time/tempo_map.rb +187 -0
  103. data/lib/head_music/time.rb +32 -0
  104. data/lib/head_music/utilities/case.rb +27 -0
  105. data/lib/head_music/utilities/hash_key.rb +34 -2
  106. data/lib/head_music/version.rb +1 -1
  107. data/lib/head_music.rb +71 -22
  108. data/user_stories/active/string-pitches.md +41 -0
  109. data/user_stories/backlog/notation-style.md +183 -0
  110. data/user_stories/backlog/organizing-content.md +80 -0
  111. data/user_stories/done/consonance-dissonance-classification.md +117 -0
  112. data/user_stories/{backlog → done}/dyad-analysis.md +6 -16
  113. data/user_stories/done/epic--score-order/PLAN.md +244 -0
  114. data/user_stories/done/expand-playing-techniques.md +38 -0
  115. data/user_stories/done/handle-time.md +7 -0
  116. data/user_stories/done/handle-time.rb +163 -0
  117. data/user_stories/done/instrument-architecture.md +238 -0
  118. data/user_stories/done/instrument-variant.md +65 -0
  119. data/user_stories/done/move-musical-symbol-to-notation.md +161 -0
  120. data/user_stories/done/move-staff-mapping-to-notation.md +158 -0
  121. data/user_stories/done/move-staff-position-to-notation.md +141 -0
  122. data/user_stories/done/notation-module-foundation.md +102 -0
  123. data/user_stories/done/percussion_set.md +260 -0
  124. data/user_stories/done/sonority-identification.md +37 -0
  125. data/user_stories/done/superclass-for-note.md +30 -0
  126. data/user_stories/epics/notation-module.md +135 -0
  127. data/user_stories/visioning/agentic-daw.md +2 -0
  128. metadata +84 -18
  129. data/TODO.md +0 -109
  130. data/check_instrument_consistency.rb +0 -0
  131. data/test_translations.rb +0 -15
  132. data/user_stories/backlog/consonance-dissonance-classification.md +0 -57
  133. data/user_stories/backlog/pitch-set-classification.md +0 -62
  134. data/user_stories/backlog/sonority-identification.md +0 -47
  135. /data/user_stories/{backlog → done/epic--score-order}/band-score-order.md +0 -0
  136. /data/user_stories/{backlog → done/epic--score-order}/chamber-ensemble-score-order.md +0 -0
  137. /data/user_stories/{backlog → done/epic--score-order}/orchestral-score-order.md +0 -0
  138. /data/user_stories/{backlog → done}/pitch-class-set-analysis.md +0 -0
@@ -0,0 +1,38 @@
1
+ module HeadMusic::Instruments; end
2
+
3
+ # An option for an instrument configuration.
4
+ #
5
+ # Examples:
6
+ # - Piccolo trumpet leadpipe: "a" option with transposition_semitones: -1
7
+ # - Bass trombone F attachment: "engaged" option with lowest_pitch_semitones: -6
8
+ # - Trumpet mute: "straight", "cup", "harmon" options (no pitch effects)
9
+ class HeadMusic::Instruments::InstrumentConfigurationOption
10
+ attr_reader :name_key, :default, :transposition_semitones, :lowest_pitch_semitones
11
+
12
+ def initialize(name_key:, default: false, transposition_semitones: nil, lowest_pitch_semitones: nil)
13
+ @name_key = name_key.to_sym
14
+ @default = default
15
+ @transposition_semitones = transposition_semitones
16
+ @lowest_pitch_semitones = lowest_pitch_semitones
17
+ end
18
+
19
+ def default?
20
+ @default == true
21
+ end
22
+
23
+ def affects_transposition?
24
+ !transposition_semitones.nil?
25
+ end
26
+
27
+ def affects_range?
28
+ !lowest_pitch_semitones.nil?
29
+ end
30
+
31
+ def ==(other)
32
+ to_s == other.to_s
33
+ end
34
+
35
+ def to_s
36
+ name_key.to_s
37
+ end
38
+ end
@@ -0,0 +1,288 @@
1
+ # Instrument configurations define optional equipment or settings
2
+ # that modify an instrument's characteristics.
3
+ #
4
+ # Structure:
5
+ # instrument_key:
6
+ # configuration_name:
7
+ # options:
8
+ # option_name:
9
+ # default: true/false
10
+ # transposition_semitones: integer (optional)
11
+ # lowest_pitch_semitones: integer (optional)
12
+
13
+ piccolo_trumpet:
14
+ leadpipe:
15
+ options:
16
+ b_flat:
17
+ default: true
18
+ a:
19
+ transposition_semitones: -1
20
+
21
+ trumpet:
22
+ mute:
23
+ options:
24
+ open:
25
+ default: true
26
+ straight:
27
+ cup:
28
+ harmon:
29
+ bucket:
30
+ plunger:
31
+
32
+ trombone:
33
+ mute:
34
+ options:
35
+ open:
36
+ default: true
37
+ straight:
38
+ cup:
39
+ harmon:
40
+ bucket:
41
+ plunger:
42
+
43
+ bass_trombone:
44
+ f_attachment:
45
+ options:
46
+ disengaged:
47
+ default: true
48
+ engaged:
49
+ lowest_pitch_semitones: -6
50
+ mute:
51
+ options:
52
+ open:
53
+ default: true
54
+ straight:
55
+ bucket:
56
+
57
+ cornet:
58
+ mute:
59
+ options:
60
+ open:
61
+ default: true
62
+ straight:
63
+ cup:
64
+ harmon:
65
+ bucket:
66
+ plunger:
67
+
68
+ flugelhorn:
69
+ mute:
70
+ options:
71
+ open:
72
+ default: true
73
+ straight:
74
+ cup:
75
+ bucket:
76
+
77
+ french_horn:
78
+ mute:
79
+ options:
80
+ open:
81
+ default: true
82
+ straight:
83
+ stopping:
84
+
85
+ euphonium:
86
+ mute:
87
+ options:
88
+ open:
89
+ default: true
90
+ straight:
91
+
92
+ baritone_horn:
93
+ mute:
94
+ options:
95
+ open:
96
+ default: true
97
+ straight:
98
+
99
+ tuba:
100
+ mute:
101
+ options:
102
+ open:
103
+ default: true
104
+ straight:
105
+
106
+ sousaphone:
107
+ mute:
108
+ options:
109
+ open:
110
+ default: true
111
+ straight:
112
+
113
+ violin:
114
+ mute:
115
+ options:
116
+ open:
117
+ default: true
118
+ orchestral:
119
+
120
+ viola:
121
+ mute:
122
+ options:
123
+ open:
124
+ default: true
125
+ orchestral:
126
+
127
+ cello:
128
+ mute:
129
+ options:
130
+ open:
131
+ default: true
132
+ orchestral:
133
+
134
+ double_bass:
135
+ c_extension:
136
+ options:
137
+ without:
138
+ default: true
139
+ with:
140
+ lowest_pitch_semitones: -4
141
+ mute:
142
+ options:
143
+ open:
144
+ default: true
145
+ orchestral:
146
+
147
+ natural_horn:
148
+ crook:
149
+ options:
150
+ f:
151
+ default: true
152
+ e_flat:
153
+ transposition_semitones: -1
154
+ e:
155
+ transposition_semitones: -2
156
+ d:
157
+ transposition_semitones: -3
158
+ c:
159
+ transposition_semitones: -5
160
+ b_flat_basso:
161
+ transposition_semitones: -7
162
+
163
+ guitar:
164
+ capo:
165
+ options:
166
+ none:
167
+ default: true
168
+ fret_1:
169
+ transposition_semitones: 1
170
+ fret_2:
171
+ transposition_semitones: 2
172
+ fret_3:
173
+ transposition_semitones: 3
174
+ fret_4:
175
+ transposition_semitones: 4
176
+ fret_5:
177
+ transposition_semitones: 5
178
+ fret_6:
179
+ transposition_semitones: 6
180
+ fret_7:
181
+ transposition_semitones: 7
182
+ fret_8:
183
+ transposition_semitones: 8
184
+ fret_9:
185
+ transposition_semitones: 9
186
+
187
+ banjo:
188
+ capo:
189
+ options:
190
+ none:
191
+ default: true
192
+ fret_1:
193
+ transposition_semitones: 1
194
+ fret_2:
195
+ transposition_semitones: 2
196
+ fret_3:
197
+ transposition_semitones: 3
198
+ fret_4:
199
+ transposition_semitones: 4
200
+ fret_5:
201
+ transposition_semitones: 5
202
+ fret_6:
203
+ transposition_semitones: 6
204
+ fret_7:
205
+ transposition_semitones: 7
206
+ fret_8:
207
+ transposition_semitones: 8
208
+ fret_9:
209
+ transposition_semitones: 9
210
+
211
+ ukulele:
212
+ capo:
213
+ options:
214
+ none:
215
+ default: true
216
+ fret_1:
217
+ transposition_semitones: 1
218
+ fret_2:
219
+ transposition_semitones: 2
220
+ fret_3:
221
+ transposition_semitones: 3
222
+ fret_4:
223
+ transposition_semitones: 4
224
+ fret_5:
225
+ transposition_semitones: 5
226
+ fret_6:
227
+ transposition_semitones: 6
228
+ fret_7:
229
+ transposition_semitones: 7
230
+ fret_8:
231
+ transposition_semitones: 8
232
+ fret_9:
233
+ transposition_semitones: 9
234
+ fret_10:
235
+ transposition_semitones: 10
236
+ fret_11:
237
+ transposition_semitones: 11
238
+ fret_12:
239
+ transposition_semitones: 12
240
+
241
+ mandolin:
242
+ capo:
243
+ options:
244
+ none:
245
+ default: true
246
+ fret_1:
247
+ transposition_semitones: 1
248
+ fret_2:
249
+ transposition_semitones: 2
250
+ fret_3:
251
+ transposition_semitones: 3
252
+ fret_4:
253
+ transposition_semitones: 4
254
+ fret_5:
255
+ transposition_semitones: 5
256
+ fret_6:
257
+ transposition_semitones: 6
258
+ fret_7:
259
+ transposition_semitones: 7
260
+ fret_8:
261
+ transposition_semitones: 8
262
+ fret_9:
263
+ transposition_semitones: 9
264
+
265
+
266
+ lute:
267
+ tied_fret:
268
+ options:
269
+ none:
270
+ default: true
271
+ fret_1:
272
+ transposition_semitones: 1
273
+ fret_2:
274
+ transposition_semitones: 2
275
+ fret_3:
276
+ transposition_semitones: 3
277
+ fret_4:
278
+ transposition_semitones: 4
279
+ fret_5:
280
+ transposition_semitones: 5
281
+ fret_6:
282
+ transposition_semitones: 6
283
+ fret_7:
284
+ transposition_semitones: 7
285
+ fret_8:
286
+ transposition_semitones: 8
287
+ fret_9:
288
+ transposition_semitones: 9
@@ -7,6 +7,12 @@ accordion:
7
7
  - keyboard
8
8
  - wind
9
9
  orchestra_section_key: keyboard
10
+ arpeggione:
11
+ classification_keys:
12
+ - bowed
13
+ - chordophone
14
+ - string
15
+ orchestra_section_key: string
10
16
  bagpipe:
11
17
  classification_keys:
12
18
  - aerophone
@@ -14,6 +20,12 @@ bagpipe:
14
20
  - wind
15
21
  - woodwind
16
22
  orchestra_section_key: woodwind
23
+ banjo:
24
+ classification_keys:
25
+ - plucked
26
+ - chordophone
27
+ - string
28
+ orchestra_section_key: string
17
29
  bass_drum:
18
30
  classification_keys:
19
31
  - percussion
@@ -28,6 +40,11 @@ bassoon:
28
40
  - wind
29
41
  - woodwind
30
42
  orchestra_section_key: woodwind
43
+ castanets:
44
+ classification_keys:
45
+ - percussion
46
+ - idiophone
47
+ orchestra_section_key: percussion
31
48
  celesta:
32
49
  classification_keys:
33
50
  - idiophone
@@ -51,6 +68,11 @@ clavichord:
51
68
  - keyboard
52
69
  - string
53
70
  orchestra_section_key: keyboard
71
+ chimes:
72
+ classification_keys:
73
+ - percussion
74
+ - idiophone
75
+ orchestra_section_key: percussion
54
76
  cornet:
55
77
  classification_keys:
56
78
  - aerophone
@@ -58,6 +80,16 @@ cornet:
58
80
  - valve
59
81
  - wind
60
82
  orchestra_section_key: brass
83
+ cowbell:
84
+ classification_keys:
85
+ - percussion
86
+ - idiophone
87
+ orchestra_section_key: percussion
88
+ crotales:
89
+ classification_keys:
90
+ - percussion
91
+ - idiophone
92
+ orchestra_section_key: percussion
61
93
  cymbal:
62
94
  classification_keys:
63
95
  - percussion
@@ -75,6 +107,13 @@ double_bass:
75
107
  - unfretted
76
108
  - string
77
109
  orchestra_section_key: string
110
+ drum_kit:
111
+ classification_keys:
112
+ - percussion
113
+ - membranophone
114
+ - idiophone
115
+ - unpitched
116
+ orchestra_section_key: percussion
78
117
  flute:
79
118
  classification_keys:
80
119
  - aerophone
@@ -105,6 +144,13 @@ guitar:
105
144
  - fretted
106
145
  - string
107
146
  orchestra_section_key: string
147
+ hammered_dulcimer:
148
+ classification_keys:
149
+ - percussion
150
+ - chordophone
151
+ - string
152
+ - struck
153
+ orchestra_section_key: percussion
108
154
  harmonica:
109
155
  classification_keys:
110
156
  - reed
@@ -124,6 +170,12 @@ harpsichord:
124
170
  - keyboard
125
171
  - string
126
172
  orchestra_section_key: keyboard
173
+ hi_hat:
174
+ classification_keys:
175
+ - percussion
176
+ - idiophone
177
+ - unpitched
178
+ orchestra_section_key: percussion
127
179
  horn:
128
180
  classification_keys:
129
181
  - aerophone
@@ -151,6 +203,12 @@ mandolin:
151
203
  - fretted
152
204
  - string
153
205
  orchestra_section_key: string
206
+ maracas:
207
+ classification_keys:
208
+ - percussion
209
+ - shaken
210
+ - idiophone
211
+ orchestra_section_key: percussion
154
212
  marimba:
155
213
  classification_keys:
156
214
  - idiophone
@@ -243,9 +301,28 @@ tambourine:
243
301
  - idiophone
244
302
  - unpitched
245
303
  orchestra_section_key: percussion
304
+ tenor_drum:
305
+ classification_keys:
306
+ - percussion
307
+ - struck
308
+ - membranophone
309
+ orchestra_section_key: percussion
246
310
  theremin:
247
311
  classification_keys:
248
312
  - electronic
313
+ tom_tom:
314
+ classification_keys:
315
+ - percussion
316
+ - membranophone
317
+ - struck
318
+ - unpitched
319
+ orchestra_section_key: percussion
320
+ triangle:
321
+ classification_keys:
322
+ - percussion
323
+ - struck
324
+ - idiophone
325
+ orchestra_section_key: percussion
249
326
  trombone:
250
327
  classification_keys:
251
328
  - aerophone
@@ -1,10 +1,20 @@
1
- # Namespace for instrument definitions, categorization, and configuration
2
1
  module HeadMusic::Instruments; end
3
2
 
4
3
  # An *InstrumentFamily* is a species of instrument
5
4
  # that may exist in a variety of keys or other variations.
6
- # For example, _saxophone_ is an instrument family, while
7
- # _alto saxophone_ and _baritone saxophone_ are specific instruments.
5
+ # For example:
6
+ # - _saxophone_ is an instrument family, while
7
+ # _alto saxophone_ and _baritone saxophone_ are specific instruments.
8
+ # - _oboe_ is an instrument family, while
9
+ # _oboe d'amore_ and _English horn_ are specific instruments.
10
+ #
11
+ # Instrument families are categorized by:
12
+ # - orchestra section (e.g. woodwind, brass, percussion, strings)
13
+ # - classification (e.g. bowed string, plucked string, double reed, single reed, brass, keyboard, electronic, percussion)
14
+ #
15
+ # Instrument families are defined in `lib/head_music/instruments/instrument_families.yml`.
16
+ #
17
+ # @see HeadMusic::Instruments::Instrument
8
18
  class HeadMusic::Instruments::InstrumentFamily
9
19
  include HeadMusic::Named
10
20
 
@@ -20,8 +30,8 @@ class HeadMusic::Instruments::InstrumentFamily
20
30
  end
21
31
 
22
32
  def self.all
23
- @all ||=
24
- INSTRUMENT_FAMILIES.map { |key, _data| get(key) }.sort_by(&:name)
33
+ INSTRUMENT_FAMILIES.map { |key, _data| get(key) }
34
+ @all ||= @instances.values.compact.sort_by(&:name)
25
35
  end
26
36
 
27
37
  private_class_method :new