musa-dsl 0.14.16

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 (72) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +10 -0
  3. data/Gemfile +20 -0
  4. data/LICENSE.md +157 -0
  5. data/README.md +8 -0
  6. data/lib/musa-dsl/core-ext/array-apply-get.rb +18 -0
  7. data/lib/musa-dsl/core-ext/array-explode-ranges.rb +29 -0
  8. data/lib/musa-dsl/core-ext/array-to-neumas.rb +28 -0
  9. data/lib/musa-dsl/core-ext/array-to-serie.rb +20 -0
  10. data/lib/musa-dsl/core-ext/arrayfy.rb +15 -0
  11. data/lib/musa-dsl/core-ext/as-context-run.rb +44 -0
  12. data/lib/musa-dsl/core-ext/duplicate.rb +134 -0
  13. data/lib/musa-dsl/core-ext/dynamic-proxy.rb +55 -0
  14. data/lib/musa-dsl/core-ext/inspect-nice.rb +28 -0
  15. data/lib/musa-dsl/core-ext/key-parameters-procedure-binder.rb +85 -0
  16. data/lib/musa-dsl/core-ext/proc-nice.rb +13 -0
  17. data/lib/musa-dsl/core-ext/send-nice.rb +21 -0
  18. data/lib/musa-dsl/core-ext/string-to-neumas.rb +27 -0
  19. data/lib/musa-dsl/core-ext.rb +13 -0
  20. data/lib/musa-dsl/datasets/gdv-decorators.rb +221 -0
  21. data/lib/musa-dsl/datasets/gdv.rb +499 -0
  22. data/lib/musa-dsl/datasets/pdv.rb +44 -0
  23. data/lib/musa-dsl/datasets.rb +5 -0
  24. data/lib/musa-dsl/generative/darwin.rb +145 -0
  25. data/lib/musa-dsl/generative/generative-grammar.rb +294 -0
  26. data/lib/musa-dsl/generative/markov.rb +78 -0
  27. data/lib/musa-dsl/generative/rules.rb +282 -0
  28. data/lib/musa-dsl/generative/variatio.rb +331 -0
  29. data/lib/musa-dsl/generative.rb +5 -0
  30. data/lib/musa-dsl/midi/midi-recorder.rb +83 -0
  31. data/lib/musa-dsl/midi/midi-voices.rb +274 -0
  32. data/lib/musa-dsl/midi.rb +2 -0
  33. data/lib/musa-dsl/music/chord-definition.rb +99 -0
  34. data/lib/musa-dsl/music/chord-definitions.rb +13 -0
  35. data/lib/musa-dsl/music/chords.rb +326 -0
  36. data/lib/musa-dsl/music/equally-tempered-12-tone-scale-system.rb +204 -0
  37. data/lib/musa-dsl/music/scales.rb +584 -0
  38. data/lib/musa-dsl/music.rb +6 -0
  39. data/lib/musa-dsl/neuma/neuma.rb +181 -0
  40. data/lib/musa-dsl/neuma.rb +1 -0
  41. data/lib/musa-dsl/neumalang/neumalang.citrus +294 -0
  42. data/lib/musa-dsl/neumalang/neumalang.rb +179 -0
  43. data/lib/musa-dsl/neumalang.rb +3 -0
  44. data/lib/musa-dsl/repl/repl.rb +143 -0
  45. data/lib/musa-dsl/repl.rb +1 -0
  46. data/lib/musa-dsl/sequencer/base-sequencer-implementation-control.rb +189 -0
  47. data/lib/musa-dsl/sequencer/base-sequencer-implementation-play-helper.rb +354 -0
  48. data/lib/musa-dsl/sequencer/base-sequencer-implementation.rb +382 -0
  49. data/lib/musa-dsl/sequencer/base-sequencer-public.rb +261 -0
  50. data/lib/musa-dsl/sequencer/sequencer-dsl.rb +94 -0
  51. data/lib/musa-dsl/sequencer/sequencer.rb +3 -0
  52. data/lib/musa-dsl/sequencer.rb +1 -0
  53. data/lib/musa-dsl/series/base-series.rb +245 -0
  54. data/lib/musa-dsl/series/hash-serie-splitter.rb +194 -0
  55. data/lib/musa-dsl/series/holder-serie.rb +87 -0
  56. data/lib/musa-dsl/series/main-serie-constructors.rb +726 -0
  57. data/lib/musa-dsl/series/main-serie-operations.rb +1151 -0
  58. data/lib/musa-dsl/series/proxy-serie.rb +69 -0
  59. data/lib/musa-dsl/series/queue-serie.rb +94 -0
  60. data/lib/musa-dsl/series/series.rb +8 -0
  61. data/lib/musa-dsl/series.rb +1 -0
  62. data/lib/musa-dsl/transport/clock.rb +36 -0
  63. data/lib/musa-dsl/transport/dummy-clock.rb +47 -0
  64. data/lib/musa-dsl/transport/external-tick-clock.rb +31 -0
  65. data/lib/musa-dsl/transport/input-midi-clock.rb +124 -0
  66. data/lib/musa-dsl/transport/timer-clock.rb +102 -0
  67. data/lib/musa-dsl/transport/timer.rb +40 -0
  68. data/lib/musa-dsl/transport/transport.rb +137 -0
  69. data/lib/musa-dsl/transport.rb +9 -0
  70. data/lib/musa-dsl.rb +17 -0
  71. data/musa-dsl.gemspec +17 -0
  72. metadata +174 -0
@@ -0,0 +1,94 @@
1
+ require 'forwardable'
2
+
3
+ class Musa::Sequencer
4
+ extend Forwardable
5
+
6
+ def_delegators :@sequencer, :raw_at, :tick, :on_debug_at, :on_block_error
7
+ def_delegators :@sequencer, :on_fast_forward, :ticks_per_bar, :round, :position=, :size, :event_handler, :empty?
8
+
9
+ def_delegators :@context, :position, :log
10
+ def_delegators :@context, :with, :now, :at, :wait, :play, :every, :move
11
+ def_delegators :@context, :everying, :playing, :moving
12
+ def_delegators :@context, :launch, :on
13
+
14
+ def initialize(beats_per_bar, ticks_per_beat, sequencer: nil, do_log: nil, &block)
15
+ @sequencer ||= Musa::BaseSequencer.new beats_per_bar, ticks_per_beat, do_log: do_log
16
+ @context = DSLContext.new @sequencer
17
+
18
+ with &block if block
19
+ end
20
+
21
+ def reset
22
+ @sequencer.reset
23
+ end
24
+
25
+ class DSLContext
26
+ extend Forwardable
27
+
28
+ attr_reader :sequencer
29
+
30
+ def_delegators :@sequencer, :launch, :on,
31
+ :position, :everying, :playing, :moving,
32
+ :ticks_per_bar, :round, :log, :inspect
33
+
34
+ def initialize(sequencer)
35
+ @sequencer = sequencer
36
+ end
37
+
38
+ def with(*value_parameters, **key_parameters, &block)
39
+ block ||= proc {}
40
+
41
+ _as_context_run block, value_parameters, key_parameters
42
+ end
43
+
44
+ def now(*value_parameters, **key_parameters, &block)
45
+ block ||= proc {}
46
+
47
+ @sequencer.now *value_parameters, **key_parameters do |*value_args, **key_args|
48
+ _as_context_run block, value_args, key_args
49
+ end
50
+ end
51
+
52
+ def at(*value_parameters, **key_parameters, &block)
53
+ block ||= proc {}
54
+
55
+ @sequencer.at *value_parameters, **key_parameters do |*value_args, **key_args|
56
+ _as_context_run block, value_args, key_args
57
+ end
58
+ end
59
+
60
+ def wait(*value_parameters, **key_parameters, &block)
61
+ block ||= proc {}
62
+
63
+ @sequencer.wait *value_parameters, **key_parameters do | *values, **key_values |
64
+ _as_context_run block, values, key_values
65
+ end
66
+ end
67
+
68
+ def play(*value_parameters, **key_parameters, &block)
69
+ block ||= proc {}
70
+
71
+ @sequencer.play *value_parameters, **key_parameters do |*value_args, **key_args|
72
+ _as_context_run block, value_args, key_args
73
+ end
74
+ end
75
+
76
+ def every(*value_parameters, **key_parameters, &block)
77
+ block ||= proc {}
78
+
79
+ @sequencer.every *value_parameters, **key_parameters do |*value_args, **key_args|
80
+ _as_context_run block, value_args, KeyParametersProcedureBinder.new(block).apply(key_args)
81
+ end
82
+ end
83
+
84
+ def move(*value_parameters, **key_parameters, &block)
85
+ block ||= proc {}
86
+
87
+ @sequencer.move *value_parameters, **key_parameters do |*value_args, **key_args|
88
+ _as_context_run block, value_args, key_args
89
+ end
90
+ end
91
+ end
92
+
93
+ private_constant :DSLContext
94
+ end
@@ -0,0 +1,3 @@
1
+ require_relative 'base-sequencer-public'
2
+ require_relative 'base-sequencer-implementation'
3
+ require_relative 'sequencer-dsl'
@@ -0,0 +1 @@
1
+ require 'musa-dsl/sequencer/sequencer'
@@ -0,0 +1,245 @@
1
+ require 'musa-dsl/core-ext/duplicate'
2
+ require 'musa-dsl/generative/generative-grammar'
3
+
4
+ module Musa
5
+ module SerieOperations end
6
+
7
+ module SeriePrototyping
8
+ def prototype?
9
+ @is_instance ? false : true
10
+ end
11
+
12
+ def instance?
13
+ @is_instance ? true : false
14
+ end
15
+
16
+ def prototype
17
+ if @is_instance
18
+ @instance_of || (@instance_of = clone.tap(&:_prototype).mark_as_prototype!)
19
+ else
20
+ self
21
+ end
22
+ end
23
+
24
+ def _prototype
25
+ nil
26
+ end
27
+
28
+ alias_method :p, :prototype
29
+
30
+ def mark_as_prototype!
31
+ @is_instance = nil
32
+ freeze
33
+ end
34
+
35
+ protected :_prototype, :mark_as_prototype!
36
+
37
+ def mark_regarding!(source)
38
+ if source.prototype?
39
+ mark_as_prototype!
40
+ else
41
+ mark_as_instance!
42
+ end
43
+ end
44
+
45
+ protected :mark_regarding!
46
+
47
+ def instance
48
+ if @is_instance
49
+ self
50
+ else
51
+ clone(freeze: false).tap(&:_instance).mark_as_instance!(self)
52
+ end
53
+ end
54
+
55
+ alias_method :i, :instance
56
+
57
+ def _instance
58
+ nil
59
+ end
60
+
61
+ def mark_as_instance!(prototype = nil)
62
+ @instance_of = prototype
63
+ @is_instance = true
64
+ self
65
+ end
66
+
67
+ protected :_instance, :mark_as_instance!
68
+
69
+ class PrototypingSerieError < RuntimeError
70
+ def initialize(message = nil)
71
+ message ||= 'This serie is a prototype serie: cannot be consumed. To consume the serie use an instance serie via .instance method'
72
+ super message
73
+ end
74
+ end
75
+ end
76
+
77
+ module Serie
78
+ include SeriePrototyping
79
+ include SerieOperations
80
+
81
+ def restart
82
+ raise PrototypingSerieError unless @is_instance
83
+
84
+ @_have_peeked_next_value = false
85
+ @_peeked_next_value = nil
86
+ @_have_current_value = false
87
+ @_current_value = nil
88
+
89
+ _restart if respond_to? :_restart
90
+
91
+ self
92
+ end
93
+
94
+ def next_value
95
+ raise PrototypingSerieError unless @is_instance
96
+
97
+ unless @_have_current_value && @_current_value.nil?
98
+ if @_have_peeked_next_value
99
+ @_have_peeked_next_value = false
100
+ @_current_value = @_peeked_next_value
101
+ else
102
+ @_current_value = _next_value
103
+ end
104
+ end
105
+
106
+ propagate_value @_current_value
107
+
108
+ @_current_value
109
+ end
110
+
111
+ alias_method :v, :next_value
112
+
113
+ def peek_next_value
114
+ raise PrototypingSerieError unless @is_instance
115
+
116
+ unless @_have_peeked_next_value
117
+ @_have_peeked_next_value = true
118
+ @_peeked_next_value = _next_value
119
+ end
120
+
121
+ @_peeked_next_value
122
+ end
123
+
124
+ def current_value
125
+ raise PrototypingSerieError unless @is_instance
126
+
127
+ @_current_value
128
+ end
129
+
130
+ def infinite?
131
+ false
132
+ end
133
+
134
+ def to_a(recursive: nil, duplicate: nil, restart: nil, dr: nil)
135
+ recursive ||= false
136
+
137
+ dr ||= instance?
138
+
139
+ duplicate = dr if duplicate.nil?
140
+ restart = dr if restart.nil?
141
+
142
+ raise 'Cannot convert to array an infinite serie' if infinite?
143
+
144
+ array = []
145
+
146
+ serie = instance
147
+
148
+ serie = serie.duplicate if duplicate
149
+ serie = serie.restart if restart
150
+
151
+ while value = serie.next_value
152
+ array << if recursive
153
+ process_for_to_a(value)
154
+ else
155
+ value
156
+ end
157
+ end
158
+
159
+ array
160
+ end
161
+
162
+ alias_method :a, :to_a
163
+
164
+ def to_node(**attributes)
165
+ Nodificator.to_node(self, **attributes)
166
+ end
167
+
168
+ alias_method :node, :to_node
169
+
170
+ class Nodificator
171
+ extend Musa::GenerativeGrammar
172
+
173
+ def self.to_node(serie, **attributes)
174
+ N(serie, **attributes)
175
+ end
176
+ end
177
+
178
+ private_constant :Nodificator
179
+
180
+ protected
181
+
182
+ def propagate_value(value)
183
+ @_slaves.each { |s| s.push_next_value value } if @_slaves
184
+ end
185
+
186
+ private
187
+
188
+ def process_for_to_a(value)
189
+ case value
190
+ when Serie
191
+ value.to_a(recursive: true, restart: false, duplicate: false)
192
+ when Array
193
+ a = value.clone
194
+ a.collect! { |v| v.is_a?(Serie) ? v.to_a(recursive: true, restart: false, duplicate: false) : process_for_to_a(v) }
195
+ when Hash
196
+ h = value.clone
197
+ h.transform_values! { |v| v.is_a?(Serie) ? v.to_a(recursive: true, restart: false, duplicate: false) : process_for_to_a(v) }
198
+ else
199
+ value
200
+ end
201
+ end
202
+
203
+ end
204
+
205
+ class Slave
206
+ include Serie
207
+
208
+ attr_reader :master
209
+
210
+ def initialize(master)
211
+ @master = master
212
+ @next_value = []
213
+ end
214
+
215
+ def _restart
216
+ throw OperationNotAllowedError, "SlaveSerie #{self}: slave series cannot be restarted"
217
+ end
218
+
219
+ def next_value
220
+ value = @next_value.shift
221
+
222
+ raise "Warning: slave serie #{self} has lost sync with his master serie #{@master}" if value.nil? && !@master.peek_next_value.nil?
223
+
224
+ propagate_value value
225
+
226
+ value
227
+ end
228
+
229
+ def peek_next_value
230
+ value = @next_value.first
231
+
232
+ raise "Warning: slave serie #{self} has lost sync with his master serie #{@master}" if value.nil? && !@master.peek_next_value.nil?
233
+
234
+ value
235
+ end
236
+
237
+ def infinite?
238
+ @master.infinite?
239
+ end
240
+
241
+ def push_next_value(value)
242
+ @next_value << value
243
+ end
244
+ end
245
+ end
@@ -0,0 +1,194 @@
1
+ module Musa
2
+ # TODO: adapt to series prototyping
3
+ # TODO: full test cases
4
+
5
+ module SerieOperations
6
+ def split(buffered: nil, master: nil)
7
+ buffered ||= false
8
+
9
+ return HashSplitter.new HashSplitter::KeyProxy.new(self) if master.nil? && !buffered
10
+ return HashSplitter.new HashSplitter::MasterSlaveKeyProxy.new(self, master) if !master.nil? && !buffered
11
+ return HashSplitter.new HashSplitter::BufferedKeyProxy.new(self) if buffered
12
+ end
13
+
14
+ class HashSplitter
15
+ def initialize(proxy)
16
+ @proxy = proxy
17
+ @series = {}
18
+ end
19
+
20
+ def [](key)
21
+ serie = if @series.key? key
22
+ @series[key]
23
+ else
24
+ @series[key] = Splitted.new(@proxy, key: key)
25
+ end
26
+ end
27
+
28
+ class KeyProxy
29
+ def initialize(hash_serie)
30
+ @serie = hash_serie.instance
31
+ @values = {}
32
+ end
33
+
34
+ def restart
35
+ @serie.restart
36
+ @values = {}
37
+ end
38
+
39
+ def next_value(key)
40
+ return nil unless @values
41
+
42
+ value = @values[key]
43
+
44
+ if value.nil?
45
+ before_values = @values.collect { |k, v| [k, v] unless v.nil? }.compact.to_h
46
+
47
+ @values = @serie.next_value
48
+ value = @values[key] if @values
49
+
50
+ warn "Warning: splitted serie #{@serie} values #{before_values} are being lost" if !value.nil? && !before_values.empty?
51
+ end
52
+
53
+ @values[key] = nil if @values
54
+
55
+ value
56
+ end
57
+
58
+ def peek_next_value(key)
59
+ value = @values[key]
60
+
61
+ if value.nil?
62
+ peek_values = @serie.peek_next_value
63
+ value = peek_values[key] if peek_values
64
+ end
65
+
66
+ value
67
+ end
68
+ end
69
+
70
+ class BufferedKeyProxy
71
+ def initialize(hash_serie)
72
+ @serie = hash_serie.instance
73
+ @values = {}
74
+ end
75
+
76
+ def restart
77
+ @serie.restart
78
+ @values = {}
79
+ end
80
+
81
+ def next_value(key)
82
+ value = nil
83
+
84
+ if @values[key].nil? || @values[key].empty?
85
+ hash_value = @serie.next_value
86
+
87
+ if hash_value
88
+ hash_value.each do |k, v|
89
+ @values[k] = [] if @values[k].nil?
90
+ @values[k] << v
91
+ end
92
+ end
93
+ end
94
+
95
+ value = @values[key].shift if @values[key]
96
+
97
+ value
98
+ end
99
+
100
+ def peek_next_value(key)
101
+ value = nil
102
+
103
+ if @values[key] && !@values[key].empty?
104
+ value = @values[key].first
105
+ else
106
+ peek_values = @serie.peek_next_value
107
+ value = peek_values[key] if peek_values
108
+ end
109
+
110
+ value
111
+ end
112
+ end
113
+
114
+ class MasterSlaveKeyProxy
115
+ def initialize(hash_serie, master)
116
+ @serie = hash_serie.instance
117
+ @master = master
118
+ @values = {}
119
+ @values_counter = {}
120
+ end
121
+
122
+ def restart
123
+ @serie.restart
124
+ @values = {}
125
+ @values_counter = {}
126
+ end
127
+
128
+ def next_value(key)
129
+ return nil unless @values
130
+
131
+ value = @values[key]
132
+
133
+ if value.nil?
134
+ @values = @serie.next_value
135
+
136
+ value = @values[key] if @values
137
+
138
+ # warn "Info: splitted serie #{@serie} use count on next_value: #{@values_counter}"
139
+ @values_counter = {}
140
+ end
141
+
142
+ @values_counter[key] ||= 0
143
+ @values_counter[key] += 1
144
+
145
+ @values[key] = nil if key == @master && @values
146
+
147
+ value
148
+ end
149
+
150
+ def peek_next_value(key)
151
+ return nil unless @values
152
+
153
+ value = @values[key]
154
+
155
+ if value.nil?
156
+ peek_values = @serie.peek_next_value
157
+ value = peek_values[key] if peek_values
158
+ end
159
+
160
+ value
161
+ end
162
+ end
163
+
164
+ class Splitted
165
+ include Serie
166
+
167
+ def initialize(proxy, key:)
168
+ @proxy = proxy
169
+ @key = key
170
+
171
+ mark_as_instance!
172
+ end
173
+
174
+ def _prototype
175
+ raise PrototypingSerieError, 'Cannot get prototype of a splitted serie'
176
+ end
177
+
178
+ def _restart
179
+ @proxy.restart
180
+ end
181
+
182
+ def next_value
183
+ @proxy.next_value(@key)
184
+ end
185
+
186
+ def peek_next_value
187
+ @proxy.peek_next_value(@key)
188
+ end
189
+ end
190
+ end
191
+
192
+ private_constant :HashSplitter
193
+ end
194
+ end
@@ -0,0 +1,87 @@
1
+ module Musa
2
+ module Series
3
+ # TODO: adapt to series prototyping
4
+
5
+ def HOLDER(serie = nil)
6
+ Holder.new(serie)
7
+ end
8
+
9
+ class Holder
10
+ include Serie
11
+
12
+ attr_reader :hold, :next
13
+
14
+ def initialize(serie)
15
+ @hold = serie.instance if serie
16
+ @next = []
17
+
18
+ mark_as_instance!
19
+ end
20
+
21
+ def hold=(serie)
22
+ @hold = serie.instance
23
+ end
24
+
25
+ def <<(serie)
26
+ if @hold.nil?
27
+ @hold = serie.instance
28
+ else
29
+ @next << serie.instance
30
+ end
31
+
32
+ self
33
+ end
34
+
35
+ def _prototype
36
+ raise PrototypingSerieError, 'Cannot get prototype of a proxy serie'
37
+ end
38
+
39
+ def restart
40
+ if @next.empty? && @hold
41
+ @hold.restart
42
+ else
43
+ @hold = @next.shift
44
+ end
45
+
46
+ self
47
+ end
48
+
49
+ def current_value
50
+ @hold.current_value if @hold
51
+ end
52
+
53
+ def next_value
54
+ @hold.next_value if @hold
55
+ end
56
+
57
+ def peek_next_value
58
+ @hold.peek_next_value if @hold
59
+ end
60
+
61
+ def infinite?
62
+ @hold.infinite? if @hold
63
+ end
64
+
65
+ private
66
+
67
+ def method_missing(method_name, *args, **key_args, &block)
68
+ if @hold && @hold.respond_to?(method_name)
69
+ @hold.send_nice method_name, *args, **key_args, &block
70
+ else
71
+ super
72
+ end
73
+ end
74
+
75
+ def respond_to_missing?(method_name, include_private)
76
+ @hold && @hold.respond_to?(method_name, include_private) || super
77
+ end
78
+ end
79
+ end
80
+
81
+ module SerieOperations
82
+ # TODO add test case
83
+ def hold
84
+ Series::Holder.new self
85
+ end
86
+ end
87
+ end