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.
- checksums.yaml +4 -4
- data/.gitignore +3 -1
- data/.version +6 -0
- data/.yardopts +7 -0
- data/README.md +227 -6
- data/docs/README.md +83 -0
- data/docs/api-reference.md +86 -0
- data/docs/getting-started/quick-start.md +93 -0
- data/docs/getting-started/tutorial.md +58 -0
- data/docs/subsystems/core-extensions.md +316 -0
- data/docs/subsystems/datasets.md +465 -0
- data/docs/subsystems/generative.md +290 -0
- data/docs/subsystems/matrix.md +63 -0
- data/docs/subsystems/midi.md +123 -0
- data/docs/subsystems/music.md +233 -0
- data/docs/subsystems/musicxml-builder.md +264 -0
- data/docs/subsystems/neumas.md +71 -0
- data/docs/subsystems/repl.md +135 -0
- data/docs/subsystems/sequencer.md +98 -0
- data/docs/subsystems/series.md +302 -0
- data/docs/subsystems/transcription.md +152 -0
- data/docs/subsystems/transport.md +177 -0
- data/lib/musa-dsl/core-ext/array-explode-ranges.rb +68 -0
- data/lib/musa-dsl/core-ext/arrayfy.rb +110 -0
- data/lib/musa-dsl/core-ext/attribute-builder.rb +91 -30
- data/lib/musa-dsl/core-ext/deep-copy.rb +125 -2
- data/lib/musa-dsl/core-ext/dynamic-proxy.rb +78 -0
- data/lib/musa-dsl/core-ext/extension.rb +53 -0
- data/lib/musa-dsl/core-ext/hashify.rb +162 -1
- data/lib/musa-dsl/core-ext/inspect-nice.rb +154 -0
- data/lib/musa-dsl/core-ext/smart-proc-binder.rb +117 -0
- data/lib/musa-dsl/core-ext/with.rb +114 -0
- data/lib/musa-dsl/datasets/dataset.rb +109 -0
- data/lib/musa-dsl/datasets/delta-d.rb +78 -0
- data/lib/musa-dsl/datasets/e.rb +186 -2
- data/lib/musa-dsl/datasets/gdv.rb +279 -2
- data/lib/musa-dsl/datasets/gdvd.rb +201 -0
- data/lib/musa-dsl/datasets/helper.rb +75 -0
- data/lib/musa-dsl/datasets/p.rb +177 -2
- data/lib/musa-dsl/datasets/packed-v.rb +91 -0
- data/lib/musa-dsl/datasets/pdv.rb +136 -1
- data/lib/musa-dsl/datasets/ps.rb +134 -4
- data/lib/musa-dsl/datasets/score/queriable.rb +143 -1
- data/lib/musa-dsl/datasets/score/render.rb +105 -1
- data/lib/musa-dsl/datasets/score/to-mxml/process-pdv.rb +138 -1
- data/lib/musa-dsl/datasets/score/to-mxml/process-ps.rb +111 -0
- data/lib/musa-dsl/datasets/score/to-mxml/process-time.rb +200 -1
- data/lib/musa-dsl/datasets/score/to-mxml/to-mxml.rb +145 -1
- data/lib/musa-dsl/datasets/score.rb +279 -0
- data/lib/musa-dsl/datasets/v.rb +88 -0
- data/lib/musa-dsl/generative/darwin.rb +180 -1
- data/lib/musa-dsl/generative/generative-grammar.rb +359 -0
- data/lib/musa-dsl/generative/markov.rb +133 -3
- data/lib/musa-dsl/generative/rules.rb +258 -4
- data/lib/musa-dsl/generative/variatio.rb +217 -2
- data/lib/musa-dsl/logger/logger.rb +267 -2
- data/lib/musa-dsl/matrix/matrix.rb +256 -10
- data/lib/musa-dsl/midi/midi-recorder.rb +108 -1
- data/lib/musa-dsl/midi/midi-voices.rb +265 -4
- data/lib/musa-dsl/music/chord-definition.rb +233 -1
- data/lib/musa-dsl/music/chord-definitions.rb +33 -6
- data/lib/musa-dsl/music/chords.rb +308 -2
- data/lib/musa-dsl/music/equally-tempered-12-tone-scale-system.rb +315 -0
- data/lib/musa-dsl/music/scales.rb +957 -40
- data/lib/musa-dsl/musicxml/builder/attributes.rb +483 -3
- data/lib/musa-dsl/musicxml/builder/backup-forward.rb +166 -1
- data/lib/musa-dsl/musicxml/builder/direction.rb +243 -0
- data/lib/musa-dsl/musicxml/builder/helper.rb +240 -0
- data/lib/musa-dsl/musicxml/builder/measure.rb +284 -0
- data/lib/musa-dsl/musicxml/builder/note-complexities.rb +324 -8
- data/lib/musa-dsl/musicxml/builder/note.rb +285 -0
- data/lib/musa-dsl/musicxml/builder/part-group.rb +108 -1
- data/lib/musa-dsl/musicxml/builder/part.rb +139 -0
- data/lib/musa-dsl/musicxml/builder/pitched-note.rb +124 -0
- data/lib/musa-dsl/musicxml/builder/rest.rb +93 -0
- data/lib/musa-dsl/musicxml/builder/score-partwise.rb +276 -0
- data/lib/musa-dsl/musicxml/builder/typed-text.rb +62 -1
- data/lib/musa-dsl/musicxml/builder/unpitched-note.rb +83 -0
- data/lib/musa-dsl/neumalang/neumalang.rb +675 -0
- data/lib/musa-dsl/neumas/array-to-neumas.rb +149 -0
- data/lib/musa-dsl/neumas/neuma-decoder.rb +253 -0
- data/lib/musa-dsl/neumas/neuma-gdv-decoder.rb +142 -2
- data/lib/musa-dsl/neumas/neuma-gdvd-decoder.rb +82 -0
- data/lib/musa-dsl/neumas/neumas.rb +67 -0
- data/lib/musa-dsl/neumas/string-to-neumas.rb +233 -1
- data/lib/musa-dsl/repl/repl.rb +550 -0
- data/lib/musa-dsl/sequencer/base-sequencer-implementation-every.rb +118 -2
- data/lib/musa-dsl/sequencer/base-sequencer-implementation-move.rb +149 -2
- data/lib/musa-dsl/sequencer/base-sequencer-implementation-play-helper.rb +296 -0
- data/lib/musa-dsl/sequencer/base-sequencer-implementation-play-timed.rb +88 -2
- data/lib/musa-dsl/sequencer/base-sequencer-implementation-play.rb +161 -0
- data/lib/musa-dsl/sequencer/base-sequencer-implementation.rb +263 -0
- data/lib/musa-dsl/sequencer/base-sequencer-tick-based.rb +173 -1
- data/lib/musa-dsl/sequencer/base-sequencer-tickless-based.rb +177 -0
- data/lib/musa-dsl/sequencer/base-sequencer.rb +710 -10
- data/lib/musa-dsl/sequencer/sequencer-dsl.rb +210 -0
- data/lib/musa-dsl/sequencer/timeslots.rb +79 -0
- data/lib/musa-dsl/series/array-to-serie.rb +37 -1
- data/lib/musa-dsl/series/base-series.rb +843 -5
- data/lib/musa-dsl/series/buffer-serie.rb +48 -0
- data/lib/musa-dsl/series/hash-or-array-serie-splitter.rb +41 -0
- data/lib/musa-dsl/series/main-serie-constructors.rb +398 -2
- data/lib/musa-dsl/series/main-serie-operations.rb +538 -16
- data/lib/musa-dsl/series/proxy-serie.rb +67 -0
- data/lib/musa-dsl/series/quantizer-serie.rb +45 -7
- data/lib/musa-dsl/series/queue-serie.rb +65 -0
- data/lib/musa-dsl/series/series-composer.rb +701 -0
- data/lib/musa-dsl/series/timed-serie.rb +473 -28
- data/lib/musa-dsl/transcription/from-gdv-to-midi.rb +404 -1
- data/lib/musa-dsl/transcription/from-gdv-to-musicxml.rb +118 -0
- data/lib/musa-dsl/transcription/from-gdv.rb +84 -1
- data/lib/musa-dsl/transcription/transcription.rb +265 -0
- data/lib/musa-dsl/transport/clock.rb +125 -0
- data/lib/musa-dsl/transport/dummy-clock.rb +89 -2
- data/lib/musa-dsl/transport/external-tick-clock.rb +91 -0
- data/lib/musa-dsl/transport/input-midi-clock.rb +133 -1
- data/lib/musa-dsl/transport/timer-clock.rb +183 -1
- data/lib/musa-dsl/transport/timer.rb +83 -0
- data/lib/musa-dsl/transport/transport.rb +318 -0
- data/lib/musa-dsl/version.rb +1 -1
- data/lib/musa-dsl.rb +132 -25
- data/musa-dsl.gemspec +12 -10
- metadata +87 -8
|
@@ -4,10 +4,74 @@ module Musa
|
|
|
4
4
|
module MusicXML
|
|
5
5
|
module Builder
|
|
6
6
|
module Internal
|
|
7
|
+
# Tuplet time modification (ratio).
|
|
8
|
+
#
|
|
9
|
+
# TimeModification defines the rhythmic ratio for tuplets, indicating how
|
|
10
|
+
# many notes of one type fit in the time normally occupied by notes of
|
|
11
|
+
# another type. This modifies the playback duration without changing the
|
|
12
|
+
# visual note type.
|
|
13
|
+
#
|
|
14
|
+
# ## Tuplet Ratios
|
|
15
|
+
#
|
|
16
|
+
# Tuplets are expressed as **actual_notes : normal_notes**:
|
|
17
|
+
#
|
|
18
|
+
# ### Common Tuplets
|
|
19
|
+
# - **Triplet** (3:2): 3 notes in the time of 2
|
|
20
|
+
# - Quarter note triplet: 3 quarters in time of 2 quarters (half note)
|
|
21
|
+
# - Eighth note triplet: 3 eighths in time of 2 eighths (quarter note)
|
|
22
|
+
#
|
|
23
|
+
# - **Quintuplet** (5:4): 5 notes in the time of 4
|
|
24
|
+
#
|
|
25
|
+
# - **Sextuplet** (6:4): 6 notes in the time of 4
|
|
26
|
+
#
|
|
27
|
+
# - **Septuplet** (7:4 or 7:8): 7 notes in time of 4 or 8
|
|
28
|
+
#
|
|
29
|
+
# - **Duplet** (2:3): 2 notes in the time of 3 (in compound meter)
|
|
30
|
+
#
|
|
31
|
+
# ## Components
|
|
32
|
+
#
|
|
33
|
+
# - **actual_notes**: Number of notes actually played
|
|
34
|
+
# - **normal_notes**: Number of notes normally played in that duration
|
|
35
|
+
# - **normal_type**: Note type for normal notes (optional)
|
|
36
|
+
# - **normal_dots**: Augmentation dots on normal notes (optional)
|
|
37
|
+
#
|
|
38
|
+
# ## Relationship with Tuplet
|
|
39
|
+
#
|
|
40
|
+
# TimeModification affects playback timing, while {Tuplet} controls
|
|
41
|
+
# visual display (bracket, number). Both are typically used together.
|
|
42
|
+
#
|
|
43
|
+
# @example Triplet (3:2)
|
|
44
|
+
# TimeModification.new(actual_notes: 3, normal_notes: 2)
|
|
45
|
+
#
|
|
46
|
+
# @example Quintuplet (5:4)
|
|
47
|
+
# TimeModification.new(actual_notes: 5, normal_notes: 4)
|
|
48
|
+
#
|
|
49
|
+
# @example Triplet with explicit normal type
|
|
50
|
+
# TimeModification.new(actual_notes: 3, normal_notes: 2,
|
|
51
|
+
# normal_type: 'eighth')
|
|
52
|
+
#
|
|
53
|
+
# @example Duplet in compound meter (2:3)
|
|
54
|
+
# TimeModification.new(actual_notes: 2, normal_notes: 3)
|
|
55
|
+
#
|
|
56
|
+
# @see Tuplet Visual tuplet bracket notation
|
|
57
|
+
# @see Note Note class using time modifications
|
|
7
58
|
class TimeModification
|
|
8
59
|
include Helper
|
|
9
60
|
include ToXML
|
|
10
61
|
|
|
62
|
+
# Creates a time modification.
|
|
63
|
+
#
|
|
64
|
+
# @param actual_notes [Integer] number of notes in the tuplet group
|
|
65
|
+
# @param normal_notes [Integer] number of normal notes in same duration
|
|
66
|
+
# @param normal_type [String, nil] note type of normal notes ('quarter', 'eighth', etc.)
|
|
67
|
+
# @param normal_dots [Integer, nil] augmentation dots on normal notes
|
|
68
|
+
#
|
|
69
|
+
# @example Quarter note triplet (3 in time of 2)
|
|
70
|
+
# TimeModification.new(actual_notes: 3, normal_notes: 2)
|
|
71
|
+
#
|
|
72
|
+
# @example Quintuplet with explicit normal type
|
|
73
|
+
# TimeModification.new(actual_notes: 5, normal_notes: 4,
|
|
74
|
+
# normal_type: 'quarter')
|
|
11
75
|
def initialize(actual_notes:, # number
|
|
12
76
|
normal_notes:, # number
|
|
13
77
|
normal_type: nil, # quarter / ...
|
|
@@ -19,8 +83,30 @@ module Musa
|
|
|
19
83
|
@normal_dots = normal_dots
|
|
20
84
|
end
|
|
21
85
|
|
|
22
|
-
|
|
23
|
-
|
|
86
|
+
# Number of actual notes in the tuplet.
|
|
87
|
+
# @return [Integer]
|
|
88
|
+
attr_accessor :actual_notes
|
|
89
|
+
|
|
90
|
+
# Number of normal notes in the same duration.
|
|
91
|
+
# @return [Integer]
|
|
92
|
+
attr_accessor :normal_notes
|
|
93
|
+
|
|
94
|
+
# Note type of normal notes.
|
|
95
|
+
# @return [String, nil]
|
|
96
|
+
attr_accessor :normal_type
|
|
97
|
+
|
|
98
|
+
# Augmentation dots on normal notes.
|
|
99
|
+
# @return [Integer, nil]
|
|
100
|
+
attr_accessor :normal_dots
|
|
101
|
+
|
|
102
|
+
# Generates the time-modification XML element.
|
|
103
|
+
#
|
|
104
|
+
# @param io [IO] output stream
|
|
105
|
+
# @param indent [Integer] indentation level
|
|
106
|
+
# @param tabs [String] tab string
|
|
107
|
+
# @return [void]
|
|
108
|
+
#
|
|
109
|
+
# @api private
|
|
24
110
|
def _to_xml(io, indent:, tabs:)
|
|
25
111
|
io.puts "#{tabs}<time-modification>"
|
|
26
112
|
|
|
@@ -35,10 +121,98 @@ module Musa
|
|
|
35
121
|
end
|
|
36
122
|
end
|
|
37
123
|
|
|
124
|
+
# Visual tuplet bracket and number notation.
|
|
125
|
+
#
|
|
126
|
+
# Tuplet controls the visual appearance of tuplet markings: brackets,
|
|
127
|
+
# numbers, and note type indications. Unlike {TimeModification}, which
|
|
128
|
+
# affects playback timing, Tuplet is purely visual.
|
|
129
|
+
#
|
|
130
|
+
# ## Components
|
|
131
|
+
#
|
|
132
|
+
# ### Type
|
|
133
|
+
# - **start**: Begin tuplet bracket/number
|
|
134
|
+
# - **stop**: End tuplet bracket/number
|
|
135
|
+
#
|
|
136
|
+
# Multiple tuplets can overlap using different `number` attributes.
|
|
137
|
+
#
|
|
138
|
+
# ### Bracket
|
|
139
|
+
# - **true**: Show bracket
|
|
140
|
+
# - **false/nil**: Hide bracket (use number only)
|
|
141
|
+
#
|
|
142
|
+
# Common practice: show brackets for beam-breaking tuplets, hide for beamed.
|
|
143
|
+
#
|
|
144
|
+
# ### Number Display
|
|
145
|
+
# - **show_number**:
|
|
146
|
+
# - 'actual': Show only actual number (e.g., "3")
|
|
147
|
+
# - 'both': Show ratio (e.g., "3:2")
|
|
148
|
+
# - 'none': Hide number
|
|
149
|
+
#
|
|
150
|
+
# - **show_type**:
|
|
151
|
+
# - 'actual': Show note type for actual notes
|
|
152
|
+
# - 'both': Show note types for both
|
|
153
|
+
# - 'none': Hide note types
|
|
154
|
+
#
|
|
155
|
+
# ### Actual/Normal Specification
|
|
156
|
+
#
|
|
157
|
+
# Optional detailed specification of tuplet appearance:
|
|
158
|
+
# - **actual_number/actual_type/actual_dots**: Actual notes representation
|
|
159
|
+
# - **normal_number/normal_type/normal_dots**: Normal notes representation
|
|
160
|
+
#
|
|
161
|
+
# Typically inferred from {TimeModification} and note properties.
|
|
162
|
+
#
|
|
163
|
+
# ## Typical Usage
|
|
164
|
+
#
|
|
165
|
+
# Most tuplets only need `type` (start/stop) and optionally `bracket`:
|
|
166
|
+
#
|
|
167
|
+
# Tuplet.new(type: 'start', bracket: true) # First note of triplet
|
|
168
|
+
# Tuplet.new(type: 'stop') # Last note of triplet
|
|
169
|
+
#
|
|
170
|
+
# @example Simple triplet bracket (start)
|
|
171
|
+
# Tuplet.new(type: 'start', bracket: true)
|
|
172
|
+
#
|
|
173
|
+
# @example Triplet end
|
|
174
|
+
# Tuplet.new(type: 'stop')
|
|
175
|
+
#
|
|
176
|
+
# @example Tuplet without bracket
|
|
177
|
+
# Tuplet.new(type: 'start', bracket: false)
|
|
178
|
+
#
|
|
179
|
+
# @example Nested tuplets with numbers
|
|
180
|
+
# Tuplet.new(type: 'start', number: 1, bracket: true) # Outer
|
|
181
|
+
# Tuplet.new(type: 'start', number: 2, bracket: true) # Inner
|
|
182
|
+
# Tuplet.new(type: 'stop', number: 2) # End inner
|
|
183
|
+
# Tuplet.new(type: 'stop', number: 1) # End outer
|
|
184
|
+
#
|
|
185
|
+
# @example Custom display (show ratio)
|
|
186
|
+
# Tuplet.new(type: 'start', show_number: 'both') # Shows "3:2"
|
|
187
|
+
#
|
|
188
|
+
# @see TimeModification Tuplet timing ratio
|
|
189
|
+
# @see Note Note class with tuplet support
|
|
38
190
|
class Tuplet
|
|
39
191
|
include Helper
|
|
40
192
|
include ToXML
|
|
41
193
|
|
|
194
|
+
# Creates a tuplet notation.
|
|
195
|
+
#
|
|
196
|
+
# @param type [String] 'start' or 'stop'
|
|
197
|
+
# @param number [Integer, nil] tuplet number for nesting (default 1)
|
|
198
|
+
# @param bracket [Boolean, nil] show bracket
|
|
199
|
+
# @param show_number [String, nil] number display: 'actual', 'both', 'none'
|
|
200
|
+
# @param show_type [String, nil] note type display: 'actual', 'both', 'none'
|
|
201
|
+
# @param actual_number [Integer, nil] actual number for display
|
|
202
|
+
# @param actual_type [String, nil] actual note type for display
|
|
203
|
+
# @param actual_dots [Integer, nil] actual dots for display
|
|
204
|
+
# @param normal_number [Integer, nil] normal number for display
|
|
205
|
+
# @param normal_type [String, nil] normal note type for display
|
|
206
|
+
# @param normal_dots [Integer, nil] normal dots for display
|
|
207
|
+
#
|
|
208
|
+
# @example Start a triplet bracket
|
|
209
|
+
# Tuplet.new(type: 'start', bracket: true)
|
|
210
|
+
#
|
|
211
|
+
# @example End a tuplet
|
|
212
|
+
# Tuplet.new(type: 'stop')
|
|
213
|
+
#
|
|
214
|
+
# @example Quintuplet with ratio display
|
|
215
|
+
# Tuplet.new(type: 'start', bracket: true, show_number: 'both')
|
|
42
216
|
def initialize(type:, # start / stop
|
|
43
217
|
number: nil, # number
|
|
44
218
|
bracket: nil, # true
|
|
@@ -64,10 +238,58 @@ module Musa
|
|
|
64
238
|
@normal_dots = normal_dots
|
|
65
239
|
end
|
|
66
240
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
attr_accessor :
|
|
70
|
-
|
|
241
|
+
# Tuplet type ('start' or 'stop').
|
|
242
|
+
# @return [String]
|
|
243
|
+
attr_accessor :type
|
|
244
|
+
|
|
245
|
+
# Tuplet number for nesting.
|
|
246
|
+
# @return [Integer, nil]
|
|
247
|
+
attr_accessor :number
|
|
248
|
+
|
|
249
|
+
# Show bracket.
|
|
250
|
+
# @return [Boolean, nil]
|
|
251
|
+
attr_accessor :bracket
|
|
252
|
+
|
|
253
|
+
# Number display mode.
|
|
254
|
+
# @return [String, nil]
|
|
255
|
+
attr_accessor :show_number
|
|
256
|
+
|
|
257
|
+
# Note type display mode.
|
|
258
|
+
# @return [String, nil]
|
|
259
|
+
attr_accessor :show_type
|
|
260
|
+
|
|
261
|
+
# Actual number for display.
|
|
262
|
+
# @return [Integer, nil]
|
|
263
|
+
attr_accessor :actual_number
|
|
264
|
+
|
|
265
|
+
# Actual note type for display.
|
|
266
|
+
# @return [String, nil]
|
|
267
|
+
attr_accessor :actual_type
|
|
268
|
+
|
|
269
|
+
# Actual augmentation dots for display.
|
|
270
|
+
# @return [Integer, nil]
|
|
271
|
+
attr_accessor :actual_dots
|
|
272
|
+
|
|
273
|
+
# Normal number for display.
|
|
274
|
+
# @return [Integer, nil]
|
|
275
|
+
attr_accessor :normal_number
|
|
276
|
+
|
|
277
|
+
# Normal note type for display.
|
|
278
|
+
# @return [String, nil]
|
|
279
|
+
attr_accessor :normal_type
|
|
280
|
+
|
|
281
|
+
# Normal augmentation dots for display.
|
|
282
|
+
# @return [Integer, nil]
|
|
283
|
+
attr_accessor :normal_dots
|
|
284
|
+
|
|
285
|
+
# Generates the tuplet XML element.
|
|
286
|
+
#
|
|
287
|
+
# @param io [IO] output stream
|
|
288
|
+
# @param indent [Integer] indentation level
|
|
289
|
+
# @param tabs [String] tab string
|
|
290
|
+
# @return [void]
|
|
291
|
+
#
|
|
292
|
+
# @api private
|
|
71
293
|
def _to_xml(io, indent:, tabs:)
|
|
72
294
|
io.puts "#{tabs}<tuplet type=\"#{@type}\"" \
|
|
73
295
|
"#{decode_bool_or_string_attribute(@number&.to_i, 'number')}" \
|
|
@@ -106,9 +328,64 @@ module Musa
|
|
|
106
328
|
end
|
|
107
329
|
end
|
|
108
330
|
|
|
331
|
+
# String harmonic technique.
|
|
332
|
+
#
|
|
333
|
+
# Harmonic represents natural and artificial harmonics for string instruments
|
|
334
|
+
# (violin, cello, guitar, etc.). Harmonics produce ethereal, whistle-like tones
|
|
335
|
+
# by lightly touching the string at specific node points.
|
|
336
|
+
#
|
|
337
|
+
# ## Harmonic Types
|
|
338
|
+
#
|
|
339
|
+
# ### Natural Harmonics
|
|
340
|
+
# Produced by lightly touching the string at natural node points (1/2, 1/3, 1/4, etc.):
|
|
341
|
+
# - **kind**: 'natural'
|
|
342
|
+
# - Common on open strings
|
|
343
|
+
# - Easier to execute
|
|
344
|
+
#
|
|
345
|
+
# ### Artificial Harmonics
|
|
346
|
+
# Produced by stopping the string at one point and lightly touching at another:
|
|
347
|
+
# - **kind**: 'artificial'
|
|
348
|
+
# - Requires two fingers
|
|
349
|
+
# - More versatile for chromaticism
|
|
350
|
+
#
|
|
351
|
+
# ## Pitch Specification
|
|
352
|
+
#
|
|
353
|
+
# Harmonics notation can indicate different pitches:
|
|
354
|
+
#
|
|
355
|
+
# - **base-pitch**: The stopped pitch (where finger presses firmly)
|
|
356
|
+
# - **touching-pitch**: Where finger lightly touches
|
|
357
|
+
# - **sounding-pitch**: The actual pitch that sounds (octave or more higher)
|
|
358
|
+
#
|
|
359
|
+
# Different notation conventions exist; MusicXML allows specifying which
|
|
360
|
+
# pitch the written note represents.
|
|
361
|
+
#
|
|
362
|
+
# @example Natural harmonic
|
|
363
|
+
# Harmonic.new(kind: 'natural')
|
|
364
|
+
#
|
|
365
|
+
# @example Artificial harmonic
|
|
366
|
+
# Harmonic.new(kind: 'artificial')
|
|
367
|
+
#
|
|
368
|
+
# @example Harmonic with sounding pitch notation
|
|
369
|
+
# Harmonic.new(kind: 'natural', pitch: 'sounding-pitch')
|
|
370
|
+
#
|
|
371
|
+
# @example Harmonic with touching pitch notation
|
|
372
|
+
# Harmonic.new(kind: 'artificial', pitch: 'touching-pitch')
|
|
373
|
+
#
|
|
374
|
+
# @see Note Note class with harmonic support
|
|
109
375
|
class Harmonic
|
|
110
376
|
include Helper::ToXML
|
|
111
377
|
|
|
378
|
+
# Creates a harmonic.
|
|
379
|
+
#
|
|
380
|
+
# @param kind [String, nil] 'natural' or 'artificial'
|
|
381
|
+
# @param pitch [String, nil] which pitch the note represents:
|
|
382
|
+
# 'base-pitch', 'sounding-pitch', or 'touching-pitch'
|
|
383
|
+
#
|
|
384
|
+
# @example Natural harmonic
|
|
385
|
+
# Harmonic.new(kind: 'natural')
|
|
386
|
+
#
|
|
387
|
+
# @example Artificial harmonic with sounding pitch
|
|
388
|
+
# Harmonic.new(kind: 'artificial', pitch: 'sounding-pitch')
|
|
112
389
|
def initialize(kind: nil, # natural / artificial
|
|
113
390
|
pitch: nil) # base-pitch / sounding-pitch / touching-pitch
|
|
114
391
|
|
|
@@ -116,8 +393,22 @@ module Musa
|
|
|
116
393
|
@pitch = pitch
|
|
117
394
|
end
|
|
118
395
|
|
|
119
|
-
|
|
120
|
-
|
|
396
|
+
# Harmonic type ('natural' or 'artificial').
|
|
397
|
+
# @return [String, nil]
|
|
398
|
+
attr_accessor :kind
|
|
399
|
+
|
|
400
|
+
# Which pitch the written note represents.
|
|
401
|
+
# @return [String, nil]
|
|
402
|
+
attr_accessor :pitch
|
|
403
|
+
|
|
404
|
+
# Generates the harmonic XML element.
|
|
405
|
+
#
|
|
406
|
+
# @param io [IO] output stream
|
|
407
|
+
# @param indent [Integer] indentation level
|
|
408
|
+
# @param tabs [String] tab string
|
|
409
|
+
# @return [void]
|
|
410
|
+
#
|
|
411
|
+
# @api private
|
|
121
412
|
def _to_xml(io, indent:, tabs:)
|
|
122
413
|
io.puts "#{tabs}<harmonic>"
|
|
123
414
|
io.puts "#{tabs}\t<#{@kind} />" if @kind
|
|
@@ -126,22 +417,47 @@ module Musa
|
|
|
126
417
|
end
|
|
127
418
|
end
|
|
128
419
|
|
|
420
|
+
# Notehead style and properties (not yet implemented).
|
|
421
|
+
#
|
|
422
|
+
# Placeholder for notehead customization (shape, color, filled/hollow, etc.).
|
|
423
|
+
#
|
|
424
|
+
# @api private
|
|
129
425
|
class Notehead
|
|
130
426
|
include Helper::NotImplemented
|
|
131
427
|
end
|
|
132
428
|
|
|
429
|
+
# Directional arrow notation (not yet implemented).
|
|
430
|
+
#
|
|
431
|
+
# Placeholder for arrow technical markings.
|
|
432
|
+
#
|
|
433
|
+
# @api private
|
|
133
434
|
class Arrow
|
|
134
435
|
include Helper::NotImplemented
|
|
135
436
|
end
|
|
136
437
|
|
|
438
|
+
# String bend notation (not yet implemented).
|
|
439
|
+
#
|
|
440
|
+
# Placeholder for guitar/bass string bending.
|
|
441
|
+
#
|
|
442
|
+
# @api private
|
|
137
443
|
class Bend
|
|
138
444
|
include Helper::NotImplemented
|
|
139
445
|
end
|
|
140
446
|
|
|
447
|
+
# Fingering indication (not yet implemented).
|
|
448
|
+
#
|
|
449
|
+
# Placeholder for finger numbers and substitution.
|
|
450
|
+
#
|
|
451
|
+
# @api private
|
|
141
452
|
class Fingering
|
|
142
453
|
include Helper::NotImplemented
|
|
143
454
|
end
|
|
144
455
|
|
|
456
|
+
# Woodwind fingering hole (not yet implemented).
|
|
457
|
+
#
|
|
458
|
+
# Placeholder for woodwind fingering charts.
|
|
459
|
+
#
|
|
460
|
+
# @api private
|
|
145
461
|
class Hole
|
|
146
462
|
include Helper::NotImplemented
|
|
147
463
|
end
|