musa-dsl 0.30.2 → 0.40.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 (123) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -1
  3. data/.version +6 -0
  4. data/.yardopts +7 -0
  5. data/README.md +227 -6
  6. data/docs/README.md +83 -0
  7. data/docs/api-reference.md +86 -0
  8. data/docs/getting-started/quick-start.md +93 -0
  9. data/docs/getting-started/tutorial.md +58 -0
  10. data/docs/subsystems/core-extensions.md +316 -0
  11. data/docs/subsystems/datasets.md +465 -0
  12. data/docs/subsystems/generative.md +290 -0
  13. data/docs/subsystems/matrix.md +63 -0
  14. data/docs/subsystems/midi.md +123 -0
  15. data/docs/subsystems/music.md +233 -0
  16. data/docs/subsystems/musicxml-builder.md +264 -0
  17. data/docs/subsystems/neumas.md +71 -0
  18. data/docs/subsystems/repl.md +135 -0
  19. data/docs/subsystems/sequencer.md +98 -0
  20. data/docs/subsystems/series.md +302 -0
  21. data/docs/subsystems/transcription.md +152 -0
  22. data/docs/subsystems/transport.md +177 -0
  23. data/lib/musa-dsl/core-ext/array-explode-ranges.rb +68 -0
  24. data/lib/musa-dsl/core-ext/arrayfy.rb +110 -0
  25. data/lib/musa-dsl/core-ext/attribute-builder.rb +91 -30
  26. data/lib/musa-dsl/core-ext/deep-copy.rb +125 -2
  27. data/lib/musa-dsl/core-ext/dynamic-proxy.rb +78 -0
  28. data/lib/musa-dsl/core-ext/extension.rb +53 -0
  29. data/lib/musa-dsl/core-ext/hashify.rb +162 -1
  30. data/lib/musa-dsl/core-ext/inspect-nice.rb +154 -0
  31. data/lib/musa-dsl/core-ext/smart-proc-binder.rb +117 -0
  32. data/lib/musa-dsl/core-ext/with.rb +114 -0
  33. data/lib/musa-dsl/datasets/dataset.rb +109 -0
  34. data/lib/musa-dsl/datasets/delta-d.rb +78 -0
  35. data/lib/musa-dsl/datasets/e.rb +186 -2
  36. data/lib/musa-dsl/datasets/gdv.rb +279 -2
  37. data/lib/musa-dsl/datasets/gdvd.rb +201 -0
  38. data/lib/musa-dsl/datasets/helper.rb +75 -0
  39. data/lib/musa-dsl/datasets/p.rb +177 -2
  40. data/lib/musa-dsl/datasets/packed-v.rb +91 -0
  41. data/lib/musa-dsl/datasets/pdv.rb +136 -1
  42. data/lib/musa-dsl/datasets/ps.rb +134 -4
  43. data/lib/musa-dsl/datasets/score/queriable.rb +143 -1
  44. data/lib/musa-dsl/datasets/score/render.rb +105 -1
  45. data/lib/musa-dsl/datasets/score/to-mxml/process-pdv.rb +138 -1
  46. data/lib/musa-dsl/datasets/score/to-mxml/process-ps.rb +111 -0
  47. data/lib/musa-dsl/datasets/score/to-mxml/process-time.rb +200 -1
  48. data/lib/musa-dsl/datasets/score/to-mxml/to-mxml.rb +145 -1
  49. data/lib/musa-dsl/datasets/score.rb +279 -0
  50. data/lib/musa-dsl/datasets/v.rb +88 -0
  51. data/lib/musa-dsl/generative/darwin.rb +180 -1
  52. data/lib/musa-dsl/generative/generative-grammar.rb +359 -0
  53. data/lib/musa-dsl/generative/markov.rb +133 -3
  54. data/lib/musa-dsl/generative/rules.rb +258 -4
  55. data/lib/musa-dsl/generative/variatio.rb +217 -2
  56. data/lib/musa-dsl/logger/logger.rb +267 -2
  57. data/lib/musa-dsl/matrix/matrix.rb +256 -10
  58. data/lib/musa-dsl/midi/midi-recorder.rb +108 -1
  59. data/lib/musa-dsl/midi/midi-voices.rb +265 -4
  60. data/lib/musa-dsl/music/chord-definition.rb +233 -1
  61. data/lib/musa-dsl/music/chord-definitions.rb +33 -6
  62. data/lib/musa-dsl/music/chords.rb +308 -2
  63. data/lib/musa-dsl/music/equally-tempered-12-tone-scale-system.rb +315 -0
  64. data/lib/musa-dsl/music/scales.rb +957 -40
  65. data/lib/musa-dsl/musicxml/builder/attributes.rb +483 -3
  66. data/lib/musa-dsl/musicxml/builder/backup-forward.rb +166 -1
  67. data/lib/musa-dsl/musicxml/builder/direction.rb +243 -0
  68. data/lib/musa-dsl/musicxml/builder/helper.rb +240 -0
  69. data/lib/musa-dsl/musicxml/builder/measure.rb +284 -0
  70. data/lib/musa-dsl/musicxml/builder/note-complexities.rb +324 -8
  71. data/lib/musa-dsl/musicxml/builder/note.rb +285 -0
  72. data/lib/musa-dsl/musicxml/builder/part-group.rb +108 -1
  73. data/lib/musa-dsl/musicxml/builder/part.rb +139 -0
  74. data/lib/musa-dsl/musicxml/builder/pitched-note.rb +124 -0
  75. data/lib/musa-dsl/musicxml/builder/rest.rb +93 -0
  76. data/lib/musa-dsl/musicxml/builder/score-partwise.rb +276 -0
  77. data/lib/musa-dsl/musicxml/builder/typed-text.rb +62 -1
  78. data/lib/musa-dsl/musicxml/builder/unpitched-note.rb +83 -0
  79. data/lib/musa-dsl/neumalang/neumalang.rb +675 -0
  80. data/lib/musa-dsl/neumas/array-to-neumas.rb +149 -0
  81. data/lib/musa-dsl/neumas/neuma-decoder.rb +253 -0
  82. data/lib/musa-dsl/neumas/neuma-gdv-decoder.rb +142 -2
  83. data/lib/musa-dsl/neumas/neuma-gdvd-decoder.rb +82 -0
  84. data/lib/musa-dsl/neumas/neumas.rb +67 -0
  85. data/lib/musa-dsl/neumas/string-to-neumas.rb +233 -1
  86. data/lib/musa-dsl/repl/repl.rb +550 -0
  87. data/lib/musa-dsl/sequencer/base-sequencer-implementation-every.rb +118 -2
  88. data/lib/musa-dsl/sequencer/base-sequencer-implementation-move.rb +149 -2
  89. data/lib/musa-dsl/sequencer/base-sequencer-implementation-play-helper.rb +296 -0
  90. data/lib/musa-dsl/sequencer/base-sequencer-implementation-play-timed.rb +88 -2
  91. data/lib/musa-dsl/sequencer/base-sequencer-implementation-play.rb +161 -0
  92. data/lib/musa-dsl/sequencer/base-sequencer-implementation.rb +263 -0
  93. data/lib/musa-dsl/sequencer/base-sequencer-tick-based.rb +173 -1
  94. data/lib/musa-dsl/sequencer/base-sequencer-tickless-based.rb +177 -0
  95. data/lib/musa-dsl/sequencer/base-sequencer.rb +710 -10
  96. data/lib/musa-dsl/sequencer/sequencer-dsl.rb +210 -0
  97. data/lib/musa-dsl/sequencer/timeslots.rb +79 -0
  98. data/lib/musa-dsl/series/array-to-serie.rb +37 -1
  99. data/lib/musa-dsl/series/base-series.rb +843 -5
  100. data/lib/musa-dsl/series/buffer-serie.rb +48 -0
  101. data/lib/musa-dsl/series/hash-or-array-serie-splitter.rb +41 -0
  102. data/lib/musa-dsl/series/main-serie-constructors.rb +398 -2
  103. data/lib/musa-dsl/series/main-serie-operations.rb +538 -16
  104. data/lib/musa-dsl/series/proxy-serie.rb +67 -0
  105. data/lib/musa-dsl/series/quantizer-serie.rb +45 -7
  106. data/lib/musa-dsl/series/queue-serie.rb +65 -0
  107. data/lib/musa-dsl/series/series-composer.rb +701 -0
  108. data/lib/musa-dsl/series/timed-serie.rb +473 -28
  109. data/lib/musa-dsl/transcription/from-gdv-to-midi.rb +404 -1
  110. data/lib/musa-dsl/transcription/from-gdv-to-musicxml.rb +118 -0
  111. data/lib/musa-dsl/transcription/from-gdv.rb +84 -1
  112. data/lib/musa-dsl/transcription/transcription.rb +265 -0
  113. data/lib/musa-dsl/transport/clock.rb +125 -0
  114. data/lib/musa-dsl/transport/dummy-clock.rb +89 -2
  115. data/lib/musa-dsl/transport/external-tick-clock.rb +91 -0
  116. data/lib/musa-dsl/transport/input-midi-clock.rb +133 -1
  117. data/lib/musa-dsl/transport/timer-clock.rb +183 -1
  118. data/lib/musa-dsl/transport/timer.rb +83 -0
  119. data/lib/musa-dsl/transport/transport.rb +318 -0
  120. data/lib/musa-dsl/version.rb +1 -1
  121. data/lib/musa-dsl.rb +132 -25
  122. data/musa-dsl.gemspec +12 -10
  123. metadata +87 -8
@@ -2,30 +2,126 @@ require_relative 'scales'
2
2
 
3
3
  module Musa
4
4
  module Scales
5
+ # Base class for 12-semitone scale systems.
6
+ #
7
+ # TwelveSemitonesScaleSystem provides the foundation for any scale system
8
+ # using 12 semitones per octave. It defines intervals and structure but
9
+ # doesn't specify tuning (frequency calculation).
10
+ #
11
+ # Concrete subclasses must implement frequency calculation:
12
+ #
13
+ # - {EquallyTempered12ToneScaleSystem}: Equal temperament (12-TET)
14
+ # - Other temperaments could be added (e.g., meantone, just intonation)
15
+ #
16
+ # ## Intervals
17
+ #
18
+ # Defines standard interval names using semitone distances:
19
+ #
20
+ # { P0: 0, m2: 1, M2: 2, m3: 3, M3: 4, P4: 5, TT: 6,
21
+ # P5: 7, m6: 8, M6: 9, m7: 10, M7: 11, P8: 12 }
22
+ #
23
+ # @abstract Subclasses must implement {frequency_of_pitch}
24
+ # @see EquallyTempered12ToneScaleSystem Concrete equal temperament implementation
5
25
  class TwelveSemitonesScaleSystem < ScaleSystem
6
26
  class << self
7
27
  @@intervals = { P0: 0, m2: 1, M2: 2, m3: 3, M3: 4, P4: 5, TT: 6, P5: 7, m6: 8, M6: 9, m7: 10, M7: 11, P8: 12 }
8
28
 
29
+ # System identifier.
30
+ # @return [Symbol] :et12
9
31
  def id
10
32
  :et12
11
33
  end
12
34
 
35
+ # Number of distinct notes per octave.
36
+ # @return [Integer] 12
13
37
  def notes_in_octave
14
38
  12
15
39
  end
16
40
 
41
+ # Size of smallest pitch division.
42
+ # @return [Integer] 1 (semitone)
17
43
  def part_of_tone_size
18
44
  1
19
45
  end
20
46
 
47
+ # Interval definitions.
48
+ #
49
+ # @return [Hash{Symbol => Integer}] interval name to semitones mapping
50
+ #
51
+ # @example
52
+ # intervals[:P5] # => 7 (perfect fifth)
53
+ # intervals[:M3] # => 4 (major third)
21
54
  def intervals
22
55
  @@intervals
23
56
  end
24
57
  end
25
58
  end
26
59
 
60
+ # Equal temperament 12-tone scale system.
61
+ #
62
+ # EquallyTempered12ToneScaleSystem implements the standard equal temperament
63
+ # tuning where each semitone has exactly the same frequency ratio: 2^(1/12).
64
+ # This is the most common tuning system in modern Western music.
65
+ #
66
+ # ## Frequency Calculation
67
+ #
68
+ # Uses the equal temperament formula based on A440 concert pitch:
69
+ #
70
+ # frequency = a_frequency × 2^((pitch - 69) / 12)
71
+ #
72
+ # Where:
73
+ #
74
+ # - **a_frequency**: Reference A frequency (typically 440 Hz)
75
+ # - **pitch**: MIDI pitch number (69 = A4)
76
+ #
77
+ # ## Historical Pitch Standards
78
+ #
79
+ # Different A frequencies represent different historical standards:
80
+ #
81
+ # - **440 Hz**: Modern concert pitch (ISO 16)
82
+ # - **442 Hz**: Used by some orchestras (brighter sound)
83
+ # - **415 Hz**: Baroque pitch (approximately A=415)
84
+ # - **432 Hz**: Alternative tuning (some claim harmonic benefits)
85
+ #
86
+ # ## Registration
87
+ #
88
+ # This system is registered as the default scale system, accessible via:
89
+ #
90
+ # Scales[:et12] # By ID
91
+ # Scales.default_system # As default
92
+ #
93
+ # ## Usage
94
+ #
95
+ # # Get system with standard A440 tuning
96
+ # system = Scales[:et12][440.0]
97
+ #
98
+ # # Get system with baroque tuning
99
+ # baroque = Scales[:et12][415.0]
100
+ #
101
+ # # Access scale kinds
102
+ # c_major = system[:major][60]
103
+ # a_minor = system[:minor][69]
104
+ #
105
+ # @see TwelveSemitonesScaleSystem Abstract base class
106
+ # @see ScaleSystem#frequency_of_pitch Abstract method implemented here
27
107
  class EquallyTempered12ToneScaleSystem < TwelveSemitonesScaleSystem
28
108
  class << self
109
+ # Calculates frequency for a pitch using equal temperament.
110
+ #
111
+ # Implements the equal temperament tuning formula where each semitone
112
+ # has a frequency ratio of 2^(1/12) ≈ 1.059463.
113
+ #
114
+ # @param pitch [Integer] MIDI pitch number
115
+ # @param _root_pitch [Integer] unused (required by interface)
116
+ # @param a_frequency [Numeric] reference A4 frequency in Hz
117
+ # @return [Float] frequency in Hz
118
+ #
119
+ # @example Standard A440 tuning
120
+ # frequency_of_pitch(69, nil, 440.0) # => 440.0 (A4)
121
+ # frequency_of_pitch(60, nil, 440.0) # => 261.63 (C4, middle C)
122
+ #
123
+ # @example Baroque tuning
124
+ # frequency_of_pitch(69, nil, 415.0) # => 415.0 (A4)
29
125
  def frequency_of_pitch(pitch, _root_pitch, a_frequency)
30
126
  (a_frequency * Rational(2)**Rational(pitch - 69, 12)).to_f
31
127
  end
@@ -35,6 +131,35 @@ module Musa
35
131
  end
36
132
 
37
133
 
134
+ # Chromatic scale kind (all 12 semitones).
135
+ #
136
+ # ChromaticScaleKind defines the chromatic scale containing all 12 semitones
137
+ # of the octave. It's used as a fallback for chromatic (non-diatonic) notes
138
+ # and for atonal or twelve-tone compositions.
139
+ #
140
+ # ## Pitch Structure
141
+ #
142
+ # Contains 12 pitch classes, one for each semitone:
143
+ #
144
+ # - Degrees: _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12
145
+ # - Pitches: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 (semitones from root)
146
+ #
147
+ # ## Special Properties
148
+ #
149
+ # - **chromatic?**: Returns true (only scale kind with this property)
150
+ # - Used automatically when accessing non-diatonic notes in diatonic scales
151
+ #
152
+ # ## Usage
153
+ #
154
+ # chromatic = Scales[:et12][440.0][:chromatic][60]
155
+ # chromatic._1 # C
156
+ # chromatic._2 # C#/Db
157
+ # chromatic._3 # D
158
+ # # ... all 12 semitones
159
+ #
160
+ # @see ScaleKind Abstract base class
161
+ # @see MajorScaleKind Major scale (7 notes)
162
+ # @see MinorNaturalScaleKind Minor scale (7 notes)
38
163
  class ChromaticScaleKind < ScaleKind
39
164
  class << self
40
165
  @@pitches =
@@ -51,14 +176,20 @@ module Musa
51
176
  { functions: [:_11], pitch: 10 },
52
177
  { functions: [:_12], pitch: 11 }].freeze
53
178
 
179
+ # Pitch structure.
180
+ # @return [Array<Hash>] pitch definitions with functions and offsets
54
181
  def pitches
55
182
  @@pitches
56
183
  end
57
184
 
185
+ # Scale kind identifier.
186
+ # @return [Symbol] :chromatic
58
187
  def id
59
188
  :chromatic
60
189
  end
61
190
 
191
+ # Indicates if this is a chromatic scale.
192
+ # @return [Boolean] true
62
193
  def chromatic?
63
194
  true
64
195
  end
@@ -67,6 +198,52 @@ module Musa
67
198
  EquallyTempered12ToneScaleSystem.register ChromaticScaleKind
68
199
  end
69
200
 
201
+ # Major scale kind (Ionian mode).
202
+ #
203
+ # MajorScaleKind defines the major scale, the fundamental scale of Western
204
+ # tonal music. It follows the pattern: W-W-H-W-W-W-H (whole-half steps)
205
+ # or intervals: M2-M2-m2-M2-M2-M2-m2 from the root.
206
+ #
207
+ # ## Pitch Structure
208
+ #
209
+ # 7 diatonic degrees plus extended harmony (8th-13th):
210
+ #
211
+ # **Scale Degrees** (Roman numerals, uppercase for major):
212
+ #
213
+ # - **I** (tonic): Root (0 semitones)
214
+ # - **II** (supertonic): Major second (2 semitones)
215
+ # - **III** (mediant): Major third (4 semitones)
216
+ # - **IV** (subdominant): Perfect fourth (5 semitones)
217
+ # - **V** (dominant): Perfect fifth (7 semitones)
218
+ # - **VI** (submediant): Major sixth (9 semitones, relative minor)
219
+ # - **VII** (leading): Major seventh (11 semitones)
220
+ #
221
+ # **Extended degrees** (for extended harmony):
222
+ #
223
+ # - VIII-XIII: Compound intervals (8th, 9th, 10th, 11th, 12th, 13th)
224
+ #
225
+ # ## Function Aliases
226
+ #
227
+ # Each degree has multiple function names:
228
+ #
229
+ # - **Numeric**: _1, _2, _3, _4, _5, _6, _7 (ordinal)
230
+ # - **Roman**: I, II, III, IV, V, VI, VII (harmonic analysis)
231
+ # - **Function**: tonic, supertonic, mediant, subdominant, dominant,
232
+ # submediant, leading
233
+ # - **Ordinal**: first, second, third, fourth, fifth, sixth, seventh
234
+ # - **Special**: relative/relative_minor for VI (relative minor root)
235
+ #
236
+ # ## Usage
237
+ #
238
+ # c_major = Scales[:et12][440.0][:major][60]
239
+ # c_major.tonic # C (60)
240
+ # c_major.dominant # G (67)
241
+ # c_major.VI # A (69) - relative minor root
242
+ # c_major.relative_minor.scale(:minor) # A minor scale
243
+ #
244
+ # @see ScaleKind Abstract base class
245
+ # @see MinorNaturalScaleKind Natural minor scale
246
+ # @see ChromaticScaleKind Chromatic scale
70
247
  class MajorScaleKind < ScaleKind
71
248
  class << self
72
249
  @@pitches =
@@ -97,14 +274,20 @@ module Musa
97
274
  { functions: %i[XIII _13 thirteenth],
98
275
  pitch: 12 + 9 }].freeze
99
276
 
277
+ # Pitch structure.
278
+ # @return [Array<Hash>] pitch definitions with functions and offsets
100
279
  def pitches
101
280
  @@pitches
102
281
  end
103
282
 
283
+ # Number of diatonic degrees.
284
+ # @return [Integer] 7
104
285
  def grades
105
286
  7
106
287
  end
107
288
 
289
+ # Scale kind identifier.
290
+ # @return [Symbol] :major
108
291
  def id
109
292
  :major
110
293
  end
@@ -113,6 +296,65 @@ module Musa
113
296
  EquallyTempered12ToneScaleSystem.register MajorScaleKind
114
297
  end
115
298
 
299
+ # Natural minor scale kind (Aeolian mode).
300
+ #
301
+ # MinorNaturalScaleKind defines the natural minor scale, parallel to the
302
+ # major scale but with a darker, melancholic character. It follows the
303
+ # pattern: W-H-W-W-H-W-W or intervals: M2-m2-M2-M2-m2-M2-M2 from the root.
304
+ #
305
+ # ## Pitch Structure
306
+ #
307
+ # 7 diatonic degrees plus extended harmony (8th-13th):
308
+ #
309
+ # **Scale Degrees** (Roman numerals, lowercase for minor):
310
+ #
311
+ # - **i** (tonic): Root (0 semitones)
312
+ # - **ii** (supertonic): Major second (2 semitones)
313
+ # - **iii** (mediant): Minor third (3 semitones, relative major)
314
+ # - **iv** (subdominant): Perfect fourth (5 semitones)
315
+ # - **v** (dominant): Perfect fifth (7 semitones)
316
+ # - **vi** (submediant): Minor sixth (8 semitones)
317
+ # - **vii** (subtonic): Minor seventh (10 semitones, NOT leading tone)
318
+ #
319
+ # **Extended degrees**: viii-xiii (compound intervals)
320
+ #
321
+ # ## Differences from Major
322
+ #
323
+ # Compared to major scale (same tonic):
324
+ #
325
+ # - **iii**: Flatted third (minor third instead of major)
326
+ # - **vi**: Flatted sixth (minor sixth instead of major)
327
+ # - **vii**: Flatted seventh (minor seventh instead of major)
328
+ #
329
+ # ## Relative Major
330
+ #
331
+ # The **iii** degree is the root of the relative major scale (shares same
332
+ # notes but different tonic). For example:
333
+ #
334
+ # - A minor (natural) relative major: C major
335
+ # - C major relative minor: A minor
336
+ #
337
+ # ## Function Aliases
338
+ #
339
+ # Similar to major but with lowercase Roman numerals:
340
+ #
341
+ # - **Numeric**: _1, _2, _3, _4, _5, _6, _7
342
+ # - **Roman**: i, ii, iii, iv, v, vi, vii
343
+ # - **Function**: tonic, supertonic, mediant, subdominant, dominant, submediant
344
+ # - **Ordinal**: first, second, third, fourth, fifth, sixth, seventh
345
+ # - **Special**: relative/relative_major for iii
346
+ #
347
+ # ## Usage
348
+ #
349
+ # a_minor = Scales[:et12][440.0][:minor][69]
350
+ # a_minor.tonic # A (69)
351
+ # a_minor.dominant # E (76)
352
+ # a_minor.iii # C (72) - relative major root
353
+ # a_minor.relative_major.scale(:major) # C major scale
354
+ #
355
+ # @see ScaleKind Abstract base class
356
+ # @see MajorScaleKind Major scale
357
+ # @see MinorHarmonicScaleKind Harmonic minor (with raised 7th)
116
358
  class MinorNaturalScaleKind < ScaleKind
117
359
  class << self
118
360
  @@pitches =
@@ -143,14 +385,20 @@ module Musa
143
385
  { functions: %i[xiii _13 thirteenth],
144
386
  pitch: 12 + 8 }].freeze
145
387
 
388
+ # Pitch structure.
389
+ # @return [Array<Hash>] pitch definitions with functions and offsets
146
390
  def pitches
147
391
  @@pitches
148
392
  end
149
393
 
394
+ # Number of diatonic degrees.
395
+ # @return [Integer] 7
150
396
  def grades
151
397
  7
152
398
  end
153
399
 
400
+ # Scale kind identifier.
401
+ # @return [Symbol] :minor
154
402
  def id
155
403
  :minor
156
404
  end
@@ -159,6 +407,67 @@ module Musa
159
407
  EquallyTempered12ToneScaleSystem.register MinorNaturalScaleKind
160
408
  end
161
409
 
410
+ # Harmonic minor scale kind.
411
+ #
412
+ # MinorHarmonicScaleKind defines the harmonic minor scale, a variation of
413
+ # the natural minor with a raised seventh degree. This creates a leading
414
+ # tone (major seventh) that resolves strongly to the tonic, giving the
415
+ # scale a more directed, dramatic character.
416
+ #
417
+ # ## Pitch Structure
418
+ #
419
+ # 7 diatonic degrees plus extended harmony (8th-13th):
420
+ #
421
+ # **Scale Degrees** (Roman numerals, lowercase for minor):
422
+ #
423
+ # - **i** (tonic): Root (0 semitones)
424
+ # - **ii** (supertonic): Major second (2 semitones)
425
+ # - **iii** (mediant): Minor third (3 semitones, relative major)
426
+ # - **iv** (subdominant): Perfect fourth (5 semitones)
427
+ # - **v** (dominant): Perfect fifth (7 semitones)
428
+ # - **vi** (submediant): Minor sixth (8 semitones)
429
+ # - **vii** (leading): **Major seventh** (11 semitones) ← RAISED from natural minor
430
+ #
431
+ # **Extended degrees**: viii-xiii (compound intervals)
432
+ #
433
+ # ## Key Difference from Natural Minor
434
+ #
435
+ # The **vii** degree is raised from 10 semitones (minor seventh) to
436
+ # 11 semitones (major seventh), creating:
437
+ #
438
+ # - A **leading tone** that resolves strongly upward to the tonic
439
+ # - An **augmented second** interval between vi and vii (3 semitones)
440
+ # - A **dominant seventh chord** (v7) with strong resolution to i
441
+ #
442
+ # ## Musical Character
443
+ #
444
+ # The harmonic minor scale:
445
+ #
446
+ # - Maintains minor quality (minor third)
447
+ # - Provides strong dominant-to-tonic resolution
448
+ # - Creates exotic sound due to augmented second (vi-vii)
449
+ # - Common in classical, jazz, and Middle Eastern music
450
+ #
451
+ # ## Function Aliases
452
+ #
453
+ # Same as natural minor:
454
+ #
455
+ # - **Numeric**: _1, _2, _3, _4, _5, _6, _7
456
+ # - **Roman**: i, ii, iii, iv, v, vi, vii
457
+ # - **Function**: tonic, supertonic, mediant, subdominant, dominant,
458
+ # submediant, leading
459
+ # - **Special**: relative/relative_major for iii
460
+ #
461
+ # ## Usage
462
+ #
463
+ # a_harmonic_minor = Scales[:et12][440.0][:minor_harmonic][69]
464
+ # a_harmonic_minor.vii # G# (80) - raised 7th, not G (79)
465
+ # a_harmonic_minor.vi # F (77)
466
+ # # Augmented second: F to G# = 3 semitones
467
+ #
468
+ # @see ScaleKind Abstract base class
469
+ # @see MinorNaturalScaleKind Natural minor (with minor 7th)
470
+ # @see MajorScaleKind Major scale
162
471
  class MinorHarmonicScaleKind < ScaleKind
163
472
  class << self
164
473
  @@pitches =
@@ -189,14 +498,20 @@ module Musa
189
498
  { functions: %i[xiii _13],
190
499
  pitch: 12 + 8 }].freeze
191
500
 
501
+ # Pitch structure.
502
+ # @return [Array<Hash>] pitch definitions with functions and offsets
192
503
  def pitches
193
504
  @@pitches
194
505
  end
195
506
 
507
+ # Number of diatonic degrees.
508
+ # @return [Integer] 7
196
509
  def grades
197
510
  7
198
511
  end
199
512
 
513
+ # Scale kind identifier.
514
+ # @return [Symbol] :minor_harmonic
200
515
  def id
201
516
  :minor_harmonic
202
517
  end