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
|
@@ -2,11 +2,93 @@ require_relative 'neuma-decoder'
|
|
|
2
2
|
|
|
3
3
|
module Musa::Neumas
|
|
4
4
|
module Decoders
|
|
5
|
+
# GDVD neuma decoder for preserving differential format.
|
|
6
|
+
#
|
|
7
|
+
# Simple decoder that processes GDVD (Grade-Duration-Velocity-Differential) neumas
|
|
8
|
+
# without converting to absolute GDV format. Useful when you need to work with
|
|
9
|
+
# differential values directly or perform intermediate processing.
|
|
10
|
+
#
|
|
11
|
+
# ## GDVD Format
|
|
12
|
+
#
|
|
13
|
+
# GDVD maintains relative/differential values:
|
|
14
|
+
# ```ruby
|
|
15
|
+
# {
|
|
16
|
+
# grade_diff: +2, # Relative grade change
|
|
17
|
+
# duration_factor: 2, # Duration multiplier
|
|
18
|
+
# velocity_factor: 1.2, # Velocity multiplier
|
|
19
|
+
# modifiers: {...} # Ornaments, articulations
|
|
20
|
+
# }
|
|
21
|
+
# ```
|
|
22
|
+
#
|
|
23
|
+
# ## Use Cases
|
|
24
|
+
#
|
|
25
|
+
# - **Intermediate processing**: Transform neumas before converting to GDV
|
|
26
|
+
# - **Pattern analysis**: Analyze melodic intervals without absolute pitch
|
|
27
|
+
# - **Transposition**: Work with relative values for easy transposition
|
|
28
|
+
#
|
|
29
|
+
# ## vs NeumaDecoder
|
|
30
|
+
#
|
|
31
|
+
# - **NeumaDifferentialDecoder**: Keeps differential format (GDVD)
|
|
32
|
+
# - **NeumaDecoder**: Converts to absolute format (GDV) using scale
|
|
33
|
+
#
|
|
34
|
+
# @example Process GDVD
|
|
35
|
+
# decoder = Musa::Neumas::Decoders::NeumaDifferentialDecoder.new(
|
|
36
|
+
# base_duration: 1/4r
|
|
37
|
+
# )
|
|
38
|
+
#
|
|
39
|
+
# gdvd = decoder.decode({ grade_diff: +2, duration_factor: 2 })
|
|
40
|
+
# # => { grade_diff: +2, duration_factor: 2, base_duration: 1/4r }
|
|
41
|
+
# # Still differential, not converted to absolute
|
|
42
|
+
#
|
|
43
|
+
# @example Intermediate processing workflow
|
|
44
|
+
# # Process neumas in differential format before final conversion
|
|
45
|
+
# using Musa::Extension::Neumas
|
|
46
|
+
#
|
|
47
|
+
# neumas = "0 +2 +2 -1 0".to_neumas
|
|
48
|
+
# differential_decoder = Musa::Neumas::Decoders::NeumaDifferentialDecoder.new
|
|
49
|
+
#
|
|
50
|
+
# # Process each neuma (keeping differential format)
|
|
51
|
+
# gdvds = []
|
|
52
|
+
# neumas.i.each do |neuma|
|
|
53
|
+
# gdvd = differential_decoder.decode(neuma[:gdvd])
|
|
54
|
+
# gdvds << gdvd
|
|
55
|
+
# end
|
|
56
|
+
#
|
|
57
|
+
# # GDVD objects still have differential values
|
|
58
|
+
# # Can transform them before converting to absolute GDV
|
|
59
|
+
#
|
|
60
|
+
# @see Musa::Neumas::Decoders::NeumaDecoder
|
|
61
|
+
# @see Musa::Neumas::Decoders::DifferentialDecoder
|
|
62
|
+
#
|
|
63
|
+
# @api public
|
|
5
64
|
class NeumaDifferentialDecoder < DifferentialDecoder # to get a GDVd
|
|
65
|
+
# Creates differential GDVD decoder.
|
|
66
|
+
#
|
|
67
|
+
# @param base_duration [Rational, nil] base duration unit (default: 1/4)
|
|
68
|
+
#
|
|
69
|
+
# @example Create decoder with eighth note base
|
|
70
|
+
# decoder = NeumaDifferentialDecoder.new(base_duration: 1/8r)
|
|
71
|
+
#
|
|
72
|
+
# @api public
|
|
6
73
|
def initialize(base_duration: nil)
|
|
7
74
|
@base_duration = base_duration || Rational(1,4)
|
|
8
75
|
end
|
|
9
76
|
|
|
77
|
+
# Processes GDVD by setting base_duration.
|
|
78
|
+
#
|
|
79
|
+
# Clones GDVD and sets base_duration for duration calculations.
|
|
80
|
+
# Does not convert to absolute values.
|
|
81
|
+
#
|
|
82
|
+
# @param gdvd [Hash] GDVD attributes
|
|
83
|
+
#
|
|
84
|
+
# @return [Hash] GDVD with base_duration set
|
|
85
|
+
#
|
|
86
|
+
# @example Process differential neuma
|
|
87
|
+
# gdvd = { grade_diff: +2, duration_factor: 2 }
|
|
88
|
+
# result = decoder.process(gdvd)
|
|
89
|
+
# # => { grade_diff: +2, duration_factor: 2, base_duration: 1/4r }
|
|
90
|
+
#
|
|
91
|
+
# @api public
|
|
10
92
|
def process(gdvd)
|
|
11
93
|
gdvd.clone.tap { |_| _.base_duration = @base_duration }
|
|
12
94
|
end
|
|
@@ -3,16 +3,74 @@ require_relative 'string-to-neumas'
|
|
|
3
3
|
using Musa::Extension::Neumas
|
|
4
4
|
|
|
5
5
|
module Musa
|
|
6
|
+
# Neuma notation system namespace.
|
|
7
|
+
#
|
|
8
|
+
# Contains all neuma-related modules, classes, and functionality.
|
|
9
|
+
#
|
|
10
|
+
# @api public
|
|
6
11
|
module Neumas
|
|
12
|
+
# Base neuma module for serie and parallel structures.
|
|
13
|
+
#
|
|
14
|
+
# Mixed into neuma hashes to provide structure-specific methods.
|
|
15
|
+
# Neumas are extended with either `Neuma::Serie` or `Neuma::Parallel`.
|
|
16
|
+
#
|
|
17
|
+
# @api public
|
|
7
18
|
module Neuma
|
|
19
|
+
# Parallel neuma structure (polyphonic).
|
|
20
|
+
#
|
|
21
|
+
# Represents simultaneous musical events (multiple voices, chords).
|
|
22
|
+
# Contains array of neuma series in `:parallel` key.
|
|
23
|
+
#
|
|
24
|
+
# @example Parallel structure
|
|
25
|
+
# {
|
|
26
|
+
# kind: :parallel,
|
|
27
|
+
# parallel: [
|
|
28
|
+
# { kind: :serie, serie: melody_neumas },
|
|
29
|
+
# { kind: :serie, serie: bass_neumas }
|
|
30
|
+
# ]
|
|
31
|
+
# }.extend(Musa::Neumas::Neuma::Parallel)
|
|
32
|
+
#
|
|
33
|
+
# @api public
|
|
8
34
|
module Parallel
|
|
9
35
|
include Neuma
|
|
10
36
|
end
|
|
11
37
|
|
|
38
|
+
# Serie neuma structure (monophonic).
|
|
39
|
+
#
|
|
40
|
+
# Represents sequential musical events (single voice melody).
|
|
41
|
+
# Contains array of neuma objects in `:serie` key.
|
|
42
|
+
#
|
|
43
|
+
# @example Serie structure
|
|
44
|
+
# {
|
|
45
|
+
# kind: :serie,
|
|
46
|
+
# serie: [neuma1, neuma2, neuma3]
|
|
47
|
+
# }.extend(Musa::Neumas::Neuma::Serie)
|
|
48
|
+
#
|
|
49
|
+
# @api public
|
|
12
50
|
module Serie
|
|
13
51
|
include Neuma
|
|
14
52
|
end
|
|
15
53
|
|
|
54
|
+
# Creates parallel structure with another neuma.
|
|
55
|
+
#
|
|
56
|
+
# Combines this neuma with another into parallel (polyphonic) structure.
|
|
57
|
+
# If already parallel, adds to existing parallel array.
|
|
58
|
+
#
|
|
59
|
+
# @param other [String, Neuma] neuma to parallelize with
|
|
60
|
+
#
|
|
61
|
+
# @return [Parallel] parallel neuma structure
|
|
62
|
+
#
|
|
63
|
+
# @raise [ArgumentError] if other cannot be converted
|
|
64
|
+
#
|
|
65
|
+
# @example Create parallel from neumas
|
|
66
|
+
# melody = "0 +2 +4".to_neumas
|
|
67
|
+
# bass = "-7 -5 -3".to_neumas
|
|
68
|
+
# harmony = melody | bass
|
|
69
|
+
#
|
|
70
|
+
# @example Chain multiple parallels
|
|
71
|
+
# satb = soprano | alto | tenor | bass
|
|
72
|
+
#
|
|
73
|
+
# @api public
|
|
16
74
|
def |(other)
|
|
17
75
|
if is_a?(Parallel)
|
|
18
76
|
clone.tap { |_| _[:parallel] << convert_to_parallel_element(other) }.extend(Parallel)
|
|
@@ -25,6 +83,15 @@ module Musa
|
|
|
25
83
|
|
|
26
84
|
private
|
|
27
85
|
|
|
86
|
+
# Converts element to parallel-compatible format.
|
|
87
|
+
#
|
|
88
|
+
# @param e [String, Neuma] element to convert
|
|
89
|
+
#
|
|
90
|
+
# @return [Hash] neuma serie structure
|
|
91
|
+
#
|
|
92
|
+
# @raise [ArgumentError] if cannot convert
|
|
93
|
+
#
|
|
94
|
+
# @api private
|
|
28
95
|
def convert_to_parallel_element(e)
|
|
29
96
|
case e
|
|
30
97
|
when String then { kind: :serie, serie: e.to_neumas }.extend(Neuma)
|
|
@@ -1,9 +1,240 @@
|
|
|
1
|
+
# String refinement for parsing neuma notation.
|
|
2
|
+
#
|
|
3
|
+
# Adds methods to String class for converting text-based neuma notation into
|
|
4
|
+
# structured neuma objects. Uses Neumalang parser to process the notation.
|
|
5
|
+
#
|
|
6
|
+
# ## Neuma Notation Syntax
|
|
7
|
+
#
|
|
8
|
+
# Neuma notation is a compact text format for musical sequences:
|
|
9
|
+
#
|
|
10
|
+
# ### Grade (Pitch)
|
|
11
|
+
# ```ruby
|
|
12
|
+
# "0" # Absolute grade 0
|
|
13
|
+
# "+2" # Up 2 scale steps
|
|
14
|
+
# "-1" # Down 1 scale step
|
|
15
|
+
# "^3" # Up 3 octaves
|
|
16
|
+
# "v1" # Down 1 octave
|
|
17
|
+
# ```
|
|
18
|
+
#
|
|
19
|
+
# ### Duration
|
|
20
|
+
# ```ruby
|
|
21
|
+
# "_" # Base duration
|
|
22
|
+
# "_2" # Double duration (half note if base is quarter)
|
|
23
|
+
# "_/2" # Half duration (eighth note if base is quarter)
|
|
24
|
+
# "_3/2" # 1.5x duration (dotted)
|
|
25
|
+
# ```
|
|
26
|
+
#
|
|
27
|
+
# ### Ornaments & Articulations
|
|
28
|
+
# ```ruby
|
|
29
|
+
# ".tr" # Trill
|
|
30
|
+
# ".mor" # Mordent
|
|
31
|
+
# ".turn" # Turn
|
|
32
|
+
# ".st" # Staccato
|
|
33
|
+
# ```
|
|
34
|
+
#
|
|
35
|
+
# ### Grace Notes (Appogiatura)
|
|
36
|
+
# ```ruby
|
|
37
|
+
# "(+1_/4)+2_" # Grace note +1 (1/4 duration) before main note +2
|
|
38
|
+
# ```
|
|
39
|
+
#
|
|
40
|
+
# ### Complete Examples
|
|
41
|
+
# ```ruby
|
|
42
|
+
# "0 +2 +2 -1 0" # Simple melodic sequence
|
|
43
|
+
# "+2_ +2_2 +1_/2" # With duration variations
|
|
44
|
+
# "+2.tr +3.mor -1.st" # With ornaments
|
|
45
|
+
# "(+1_/4)+2_ +2_" # With appogiatura
|
|
46
|
+
# ```
|
|
47
|
+
#
|
|
48
|
+
# ## Parallel Notation
|
|
49
|
+
#
|
|
50
|
+
# Use `|` operator to create parallel (polyphonic) structures:
|
|
51
|
+
# ```ruby
|
|
52
|
+
# "0 +2 +4" | "+7 +5 +7" # Two voices in parallel
|
|
53
|
+
# ```
|
|
54
|
+
#
|
|
55
|
+
# ## Usage with Refinement
|
|
56
|
+
#
|
|
57
|
+
# This is a refinement - must be activated with `using`:
|
|
58
|
+
# ```ruby
|
|
59
|
+
# using Musa::Extension::Neumas
|
|
60
|
+
#
|
|
61
|
+
# melody = "0 +2 +2 -1 0".to_neumas
|
|
62
|
+
# # or shorter:
|
|
63
|
+
# melody = "0 +2 +2 -1 0".n
|
|
64
|
+
# ```
|
|
65
|
+
#
|
|
66
|
+
# ## Integration with Decoders
|
|
67
|
+
#
|
|
68
|
+
# Parsed neumas contain GDVD (differential) data:
|
|
69
|
+
# ```ruby
|
|
70
|
+
# using Musa::Extension::Neumas
|
|
71
|
+
#
|
|
72
|
+
# neumas = "0 +2 +2 -1 0".to_neumas
|
|
73
|
+
#
|
|
74
|
+
# # Access parsed differential values
|
|
75
|
+
# neumas.i.each do |neuma|
|
|
76
|
+
# puts "GDVD: #{neuma[:gdvd].inspect}"
|
|
77
|
+
# end
|
|
78
|
+
# ```
|
|
79
|
+
#
|
|
80
|
+
# @example Basic parsing
|
|
81
|
+
# using Musa::Extension::Neumas
|
|
82
|
+
#
|
|
83
|
+
# melody = "0 +2 +2 -1 0".to_neumas
|
|
84
|
+
# # Returns series of GDVD hashes
|
|
85
|
+
#
|
|
86
|
+
# @example With ornaments
|
|
87
|
+
# using Musa::Extension::Neumas
|
|
88
|
+
#
|
|
89
|
+
# ornate = "+2.tr +3.mor -1.st".to_neumas
|
|
90
|
+
#
|
|
91
|
+
# @example Parallel voices
|
|
92
|
+
# using Musa::Extension::Neumas
|
|
93
|
+
#
|
|
94
|
+
# harmony = "0 +2 +4" | "+7 +5 +7"
|
|
95
|
+
#
|
|
96
|
+
# @example Convert to generative node
|
|
97
|
+
# using Musa::Extension::Neumas
|
|
98
|
+
#
|
|
99
|
+
# node = "0 +2 +2 -1 0".nn # to_neumas_to_node
|
|
100
|
+
#
|
|
101
|
+
# @see Musa::Neumalang
|
|
102
|
+
# @see Musa::Neumas::Decoders::NeumaDecoder
|
|
103
|
+
# @see Musa::Generative
|
|
104
|
+
#
|
|
105
|
+
# @api public
|
|
1
106
|
require_relative '../neumalang'
|
|
2
107
|
require_relative '../generative/generative-grammar'
|
|
3
108
|
|
|
4
109
|
module Musa
|
|
5
110
|
module Extension
|
|
111
|
+
# Namespace for neuma-related refinements.
|
|
112
|
+
#
|
|
113
|
+
# Contains refinements for String and Array to support neuma notation.
|
|
114
|
+
#
|
|
115
|
+
# ## Methods Added
|
|
116
|
+
#
|
|
117
|
+
# ### String
|
|
118
|
+
# - {String#to_neumas} - Parses neuma notation string to structured neumas
|
|
119
|
+
# - {String#to_neumas_to_node} - Parses neuma notation and converts to generative node
|
|
120
|
+
# - {String#|} - Creates parallel neuma structure
|
|
121
|
+
# - {String#neumas} - Alias for to_neumas
|
|
122
|
+
# - {String#n} - Short alias for to_neumas
|
|
123
|
+
# - {String#nn} - Short alias for to_neumas_to_node
|
|
124
|
+
#
|
|
125
|
+
# @api public
|
|
6
126
|
module Neumas
|
|
127
|
+
# String refinement adding neuma parsing methods.
|
|
128
|
+
#
|
|
129
|
+
# Must be activated with `using Musa::Extension::Neumas`.
|
|
130
|
+
#
|
|
131
|
+
# @api public
|
|
132
|
+
#
|
|
133
|
+
# @!method to_neumas(decode_with: nil, debug: nil)
|
|
134
|
+
# Parses neuma notation string to structured neumas.
|
|
135
|
+
#
|
|
136
|
+
# Uses Neumalang parser to convert text notation into GDVD (differential)
|
|
137
|
+
# neuma objects that can be decoded to GDV events.
|
|
138
|
+
#
|
|
139
|
+
# @note This method is added to String via refinement. Requires `using Musa::Extension::Neumas`.
|
|
140
|
+
#
|
|
141
|
+
# @param decode_with [Decoder, nil] optional decoder to apply immediately
|
|
142
|
+
# @param debug [Boolean, nil] enable debug output from parser
|
|
143
|
+
#
|
|
144
|
+
# @return [Serie, Array] parsed neuma series or array
|
|
145
|
+
#
|
|
146
|
+
# @example Parse simple melody
|
|
147
|
+
# using Musa::Extension::Neumas
|
|
148
|
+
# neumas = "0 +2 +2 -1 0".to_neumas
|
|
149
|
+
#
|
|
150
|
+
# @example Parse with immediate decoding
|
|
151
|
+
# using Musa::Extension::Neumas
|
|
152
|
+
# # Create a simple decoder
|
|
153
|
+
# decoder = Musa::Neumas::Decoders::NeumaDifferentialDecoder.new
|
|
154
|
+
# result = "0 +2 +2 -1 0".to_neumas(decode_with: decoder)
|
|
155
|
+
#
|
|
156
|
+
# @example Parse with debug
|
|
157
|
+
# using Musa::Extension::Neumas
|
|
158
|
+
# neumas = "0 +2 +2".to_neumas(debug: true)
|
|
159
|
+
#
|
|
160
|
+
# @api public
|
|
161
|
+
class ::String; end
|
|
162
|
+
|
|
163
|
+
# @!method to_neumas_to_node(decode_with: nil, debug: nil)
|
|
164
|
+
# Parses neuma notation and converts to generative node.
|
|
165
|
+
#
|
|
166
|
+
# Combines parsing with node conversion for use in generative grammars.
|
|
167
|
+
#
|
|
168
|
+
# @note This method is added to String via refinement. Requires `using Musa::Extension::Neumas`.
|
|
169
|
+
#
|
|
170
|
+
# @param decode_with [Decoder, nil] optional decoder to apply
|
|
171
|
+
# @param debug [Boolean, nil] enable debug output
|
|
172
|
+
#
|
|
173
|
+
# @return [Node] generative node structure
|
|
174
|
+
#
|
|
175
|
+
# @example Convert to node for generative grammar
|
|
176
|
+
# using Musa::Extension::Neumas
|
|
177
|
+
# node = "0 +2 +2 -1 0".to_neumas_to_node
|
|
178
|
+
#
|
|
179
|
+
# @see Musa::Generative
|
|
180
|
+
#
|
|
181
|
+
# @api public
|
|
182
|
+
class ::String; end
|
|
183
|
+
|
|
184
|
+
# @!method |(other)
|
|
185
|
+
# Creates parallel neuma structure.
|
|
186
|
+
#
|
|
187
|
+
# Combines two neuma strings into parallel (polyphonic) structure.
|
|
188
|
+
# Both voices are parsed and wrapped in parallel container.
|
|
189
|
+
#
|
|
190
|
+
# @note This method is added to String via refinement. Requires `using Musa::Extension::Neumas`.
|
|
191
|
+
#
|
|
192
|
+
# @param other [String] second neuma string to parallelize
|
|
193
|
+
#
|
|
194
|
+
# @return [Hash] parallel neuma structure with two series
|
|
195
|
+
#
|
|
196
|
+
# @raise [ArgumentError] if other is not a String
|
|
197
|
+
#
|
|
198
|
+
# @example Two-voice harmony
|
|
199
|
+
# using Musa::Extension::Neumas
|
|
200
|
+
#
|
|
201
|
+
# melody = "0 +2 +4 +5"
|
|
202
|
+
# bass = "-7 -5 -3 -1"
|
|
203
|
+
# harmony = melody | bass
|
|
204
|
+
#
|
|
205
|
+
# @api public
|
|
206
|
+
class ::String; end
|
|
207
|
+
|
|
208
|
+
# @!method neumas(decode_with: nil, debug: nil)
|
|
209
|
+
# Alias for `to_neumas`.
|
|
210
|
+
#
|
|
211
|
+
# @note This method is added to String via refinement. Requires `using Musa::Extension::Neumas`.
|
|
212
|
+
#
|
|
213
|
+
# @see String#to_neumas
|
|
214
|
+
#
|
|
215
|
+
# @api public
|
|
216
|
+
class ::String; end
|
|
217
|
+
|
|
218
|
+
# @!method n(decode_with: nil, debug: nil)
|
|
219
|
+
# Short alias for `to_neumas`.
|
|
220
|
+
#
|
|
221
|
+
# @note This method is added to String via refinement. Requires `using Musa::Extension::Neumas`.
|
|
222
|
+
#
|
|
223
|
+
# @see String#to_neumas
|
|
224
|
+
#
|
|
225
|
+
# @api public
|
|
226
|
+
class ::String; end
|
|
227
|
+
|
|
228
|
+
# @!method nn(decode_with: nil, debug: nil)
|
|
229
|
+
# Short alias for `to_neumas_to_node`.
|
|
230
|
+
#
|
|
231
|
+
# @note This method is added to String via refinement. Requires `using Musa::Extension::Neumas`.
|
|
232
|
+
#
|
|
233
|
+
# @see String#to_neumas_to_node
|
|
234
|
+
#
|
|
235
|
+
# @api public
|
|
236
|
+
class ::String; end
|
|
237
|
+
|
|
7
238
|
refine String do
|
|
8
239
|
def to_neumas(decode_with: nil, debug: nil)
|
|
9
240
|
Musa::Neumalang::Neumalang.parse(self, decode_with: decode_with, debug: debug)
|
|
@@ -24,9 +255,10 @@ module Musa
|
|
|
24
255
|
end
|
|
25
256
|
end
|
|
26
257
|
|
|
27
|
-
|
|
28
258
|
alias_method :neumas, :to_neumas
|
|
259
|
+
|
|
29
260
|
alias_method :n, :to_neumas
|
|
261
|
+
|
|
30
262
|
alias_method :nn, :to_neumas_to_node
|
|
31
263
|
end
|
|
32
264
|
end
|