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
@@ -1,11 +1,78 @@
1
+ #
2
+ # @api public
1
3
  require_relative 'base-series'
2
4
 
3
5
  module Musa
4
6
  module Series::Constructors
7
+ # Creates a proxy serie with optional initial source.
8
+ #
9
+ # Proxy series enable late binding - creating a serie placeholder that will
10
+ # be resolved later. Useful for:
11
+ #
12
+ # ## Use Cases
13
+ #
14
+ # - **Forward references**: Reference series before definition
15
+ # - **Circular structures**: Self-referential or mutually referential series
16
+ # - **Dependency injection**: Define structure, inject source later
17
+ # - **Dynamic routing**: Change source serie at runtime
18
+ #
19
+ # ## Method Delegation
20
+ #
21
+ # Proxy delegates all methods to underlying source via method_missing,
22
+ # making it transparent proxy for most operations.
23
+ #
24
+ # ## State Resolution
25
+ #
26
+ # Proxy starts in :undefined state, becomes :prototype/:instance when
27
+ # source is set and resolved.
28
+ #
29
+ # @param serie [Serie, nil] initial source serie (default: nil)
30
+ #
31
+ # @return [ProxySerie] proxy serie
32
+ #
33
+ # @example Forward reference
34
+ # proxy = PROXY()
35
+ # proxy.undefined? # => true
36
+ #
37
+ # # Define later
38
+ # proxy.proxy_source = S(1, 2, 3)
39
+ # proxy.prototype? # => true
40
+ #
41
+ # @example Circular structure
42
+ # loop_serie = PROXY()
43
+ # sequence = S(1, 2, 3).after(loop_serie)
44
+ # loop_serie.proxy_source = sequence
45
+ # # Creates infinite loop: 1, 2, 3, 1, 2, 3, ...
46
+ #
47
+ # @example With initial source
48
+ # proxy = PROXY(S(1, 2, 3))
49
+ #
50
+ # @api public
5
51
  def PROXY(serie = nil)
6
52
  ProxySerie.new(serie)
7
53
  end
8
54
 
55
+ # Proxy/wrapper serie that delegates to another serie.
56
+ #
57
+ # Acts as transparent proxy forwarding all method calls to the wrapped
58
+ # serie. Useful for lazy evaluation, conditional serie switching, or
59
+ # adding indirection layer.
60
+ #
61
+ # The proxy can be reassigned to a different serie dynamically by
62
+ # changing the `proxy_source` attribute.
63
+ #
64
+ # @example Basic proxy
65
+ # original = FromArray.new([1, 2, 3])
66
+ # proxy = ProxySerie.new(original)
67
+ # proxy.next_value # => 1 (delegates to original)
68
+ #
69
+ # @example Dynamic serie switching
70
+ # proxy = ProxySerie.new(serie_a)
71
+ # proxy.next_value # Uses serie_a
72
+ # proxy.proxy_source = serie_b
73
+ # proxy.next_value # Now uses serie_b
74
+ #
75
+ # @api private
9
76
  class ProxySerie
10
77
  include Series::Serie.with(source: true, source_as: :proxy_source)
11
78
 
@@ -3,16 +3,54 @@ require_relative '../core-ext/inspect-nice'
3
3
 
4
4
  require_relative 'base-series'
5
5
 
6
- # TODO remove debugging puts, intermediate hash comments on :info and InspectNice
7
6
  module Musa
8
7
  module Series::Operations
8
+ # Quantizes time-value serie to discrete steps.
9
+ #
10
+ # ## Quantization Modes
11
+ #
12
+ # - **Raw**: Rounds values to nearest step, interpolates between points
13
+ # - **Predictive**: Predicts crossings of quantization boundaries
14
+ #
15
+ # ## Applications
16
+ #
17
+ # - Quantize MIDI controller data to discrete values
18
+ # - Convert continuous pitch bends to semitones
19
+ # - Snap timing to grid
20
+ # - Generate stepped automation curves
21
+ # - Convert analog input to digital steps
22
+ #
23
+ # @param reference [Numeric, nil] quantization reference (default: 0)
24
+ # @param step [Numeric, nil] step size (default: 1)
25
+ # @param value_attribute [Symbol, nil] attribute to quantize (default: :value)
26
+ # @param stops [Boolean, nil] include stop points (default: false)
27
+ # @param predictive [Boolean, nil] use predictive mode (default: false)
28
+ # @param left_open [Boolean, nil] left boundary open (raw mode)
29
+ # @param right_open [Boolean, nil] right boundary open (raw mode)
30
+ #
31
+ # @return [RawQuantizer, PredictiveQuantizer] quantized serie
32
+ #
33
+ # @example Basic quantization
34
+ # # Quantize to semitones (12 steps per octave)
35
+ # pitch_bend = S({time: 0r, value: 60.3}, {time: 1r, value: 61.8})
36
+ # quantized = pitch_bend.quantize(step: 1)
37
+ # quantized.i.to_a # => [{time: 0, value: 60, duration: 1}, ...]
38
+ #
39
+ # @example Predictive quantization
40
+ # continuous = S({time: 0r, value: 0}, {time: 4r, value: 10})
41
+ # pred = continuous.quantize(step: 2, predictive: true)
42
+ # # Generates crossing points at values 0, 2, 4, 6, 8, 10
43
+ #
44
+ # @api public
9
45
  def quantize(reference: nil, step: nil,
10
- value_attribute: nil,
11
- stops: nil,
12
- predictive: nil,
13
- left_open: nil,
14
- right_open: nil)
15
-
46
+ value_attribute: nil,
47
+ stops: nil,
48
+ predictive: nil,
49
+ left_open: nil,
50
+ right_open: nil)
51
+
52
+ # TODO remove debugging puts, intermediate hash comments on :info and InspectNice
53
+
16
54
  Series::Constructors.QUANTIZE(self,
17
55
  reference: reference,
18
56
  step: step,
@@ -1,11 +1,76 @@
1
+ # Queue serie for dynamic series concatenation.
2
+ #
3
+ #
4
+ # @api public
1
5
  require_relative 'base-series'
2
6
 
3
7
  module Musa
4
8
  module Series::Constructors
9
+ # Creates queue serie from initial series.
10
+ #
11
+ # Queue allows adding series dynamically during playback, creating flexible
12
+ # sequential playback with runtime modification.
13
+ #
14
+ # ## Features
15
+ #
16
+ # - **Dynamic addition**: Add series with `<<` during playback
17
+ # - **Sequential playback**: Plays series in queue order
18
+ # - **Method delegation**: Delegates methods to current serie
19
+ # - **Clear**: Can clear queue and reset
20
+ #
21
+ # ## Use Cases
22
+ #
23
+ # - Interactive sequencing with user input
24
+ # - Dynamic phrase assembly
25
+ # - Playlist-style serie management
26
+ # - Reactive composition systems
27
+ # - Live coding pattern queuing
28
+ #
29
+ # @param series [Array<Serie>] initial series in queue
30
+ #
31
+ # @return [QueueSerie] queue serie
32
+ #
33
+ # @example Basic queue
34
+ # queue = QUEUE(S(1, 2, 3)).i
35
+ # queue.next_value # => 1
36
+ # queue << S(4, 5, 6).i # Add dynamically
37
+ # queue.to_a # => [2, 3, 4, 5, 6]
38
+ #
39
+ # @example Dynamic playlist
40
+ # queue = QUEUE().i
41
+ # queue << melody1.i
42
+ # queue << melody2.i
43
+ # # Plays melody1 then melody2
44
+ #
45
+ # @api public
5
46
  def QUEUE(*series)
6
47
  QueueSerie.new(series)
7
48
  end
8
49
 
50
+ # Serie that processes multiple source series in queue/sequence fashion.
51
+ #
52
+ # Combines multiple series by playing them sequentially - when one
53
+ # series exhausts, moves to the next. New series can be added dynamically
54
+ # with `<<` operator.
55
+ #
56
+ # All queued series must be instances (not prototypes). The queue can
57
+ # be cleared with `clear` method.
58
+ #
59
+ # @example Sequential series playback
60
+ # serie_a = FromArray.new([1, 2, 3]).instance
61
+ # serie_b = FromArray.new([4, 5, 6]).instance
62
+ # queue = QueueSerie.new([serie_a, serie_b])
63
+ # queue.next_value # => 1
64
+ # queue.next_value # => 2
65
+ # queue.next_value # => 3
66
+ # queue.next_value # => 4 (switches to serie_b)
67
+ #
68
+ # @example Dynamic queueing
69
+ # queue = QueueSerie.new([serie_a]).instance
70
+ # queue << serie_b # Add series on the fly
71
+ # queue.clear # Empty the queue
72
+ #
73
+ # @api private
9
74
  class QueueSerie
10
75
  include Series::Serie.with(sources: true)
11
76