musa-dsl 0.22.1 → 0.22.6
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/lib/musa-dsl.rb +1 -1
- data/lib/musa-dsl/core-ext/inspect-nice.rb +1 -2
- data/lib/musa-dsl/datasets/p.rb +36 -15
- data/lib/musa-dsl/datasets/score/to-mxml/process-pdv.rb +14 -12
- data/lib/musa-dsl/datasets/score/to-mxml/process-ps.rb +32 -6
- data/lib/musa-dsl/datasets/score/to-mxml/to-mxml.rb +24 -10
- data/lib/musa-dsl/logger/logger.rb +6 -1
- data/lib/musa-dsl/matrix/matrix.rb +9 -7
- data/lib/musa-dsl/midi/midi-voices.rb +1 -0
- data/lib/musa-dsl/music/scales.rb +1 -1
- data/lib/musa-dsl/sequencer/base-sequencer-implementation-play-helper.rb +7 -2
- data/lib/musa-dsl/sequencer/base-sequencer-implementation-play-timed.rb +30 -129
- data/lib/musa-dsl/sequencer/base-sequencer-implementation.rb +10 -24
- data/lib/musa-dsl/sequencer/base-sequencer-tick-based.rb +9 -9
- data/lib/musa-dsl/sequencer/base-sequencer-tickless-based.rb +3 -5
- data/lib/musa-dsl/sequencer/{base-sequencer-public.rb → base-sequencer.rb} +15 -23
- data/lib/musa-dsl/sequencer/sequencer-dsl.rb +7 -4
- data/lib/musa-dsl/sequencer/sequencer.rb +8 -1
- data/lib/musa-dsl/series/base-series.rb +3 -3
- data/lib/musa-dsl/series/hash-or-array-serie-splitter.rb +90 -10
- data/lib/musa-dsl/series/main-serie-constructors.rb +8 -12
- data/lib/musa-dsl/series/main-serie-operations.rb +45 -5
- data/lib/musa-dsl/series/quantizer-serie.rb +25 -15
- data/lib/musa-dsl/series/series.rb +1 -1
- data/lib/musa-dsl/series/timed-serie.rb +356 -0
- data/musa-dsl.gemspec +3 -3
- metadata +6 -6
- data/lib/musa-dsl/series/flattener-timed-serie.rb +0 -61
@@ -17,13 +17,14 @@ module Musa
|
|
17
17
|
:position=,
|
18
18
|
:event_handler
|
19
19
|
|
20
|
-
def_delegators :@context, :position, :logger, :debug
|
21
|
-
def_delegators :@context, :with, :now, :at, :wait, :play, :every, :move
|
20
|
+
def_delegators :@context, :position, :quantize_position, :logger, :debug
|
21
|
+
def_delegators :@context, :with, :now, :at, :wait, :play, :play_timed, :every, :move
|
22
22
|
def_delegators :@context, :everying, :playing, :moving
|
23
23
|
def_delegators :@context, :launch, :on
|
24
24
|
def_delegators :@context, :run
|
25
25
|
|
26
|
-
def initialize(beats_per_bar
|
26
|
+
def initialize(beats_per_bar = nil,
|
27
|
+
ticks_per_beat = nil,
|
27
28
|
sequencer: nil,
|
28
29
|
logger: nil,
|
29
30
|
do_log: nil, do_error_log: nil, log_position_format: nil,
|
@@ -50,7 +51,9 @@ module Musa
|
|
50
51
|
|
51
52
|
def_delegators :@sequencer,
|
52
53
|
:launch, :on,
|
53
|
-
:position, :
|
54
|
+
:position, :quantize_position,
|
55
|
+
:size,
|
56
|
+
:everying, :playing, :moving,
|
54
57
|
:ticks_per_bar, :logger, :debug, :inspect,
|
55
58
|
:run
|
56
59
|
|
@@ -1,3 +1,10 @@
|
|
1
|
-
require_relative 'base-sequencer
|
1
|
+
require_relative 'base-sequencer'
|
2
|
+
|
2
3
|
require_relative 'base-sequencer-implementation'
|
4
|
+
|
5
|
+
require_relative 'base-sequencer-implementation-every'
|
6
|
+
require_relative 'base-sequencer-implementation-move'
|
7
|
+
require_relative 'base-sequencer-implementation-play'
|
8
|
+
require_relative 'base-sequencer-implementation-play-timed'
|
9
|
+
|
3
10
|
require_relative 'sequencer-dsl'
|
@@ -30,7 +30,7 @@ module Musa
|
|
30
30
|
if @is_instance
|
31
31
|
self
|
32
32
|
else
|
33
|
-
clone(freeze: false).tap(&:_instance!).mark_as_instance!(self)
|
33
|
+
clone(freeze: false).tap(&:_instance!).mark_as_instance!(self).tap(&:restart)
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
@@ -40,7 +40,7 @@ module Musa
|
|
40
40
|
# handle prototyping/instancing automatically.
|
41
41
|
# If there is a @sources attribute with the eventual several sources, SeriePrototyping will handle them by
|
42
42
|
# default.
|
43
|
-
# If needed the subclasses can override this behaviour to
|
43
|
+
# If needed the subclasses can override this behaviour to accommodate to real subclass specificities.
|
44
44
|
#
|
45
45
|
protected def _prototype!
|
46
46
|
@source = @source.prototype if @source
|
@@ -130,7 +130,7 @@ module Musa
|
|
130
130
|
def peek_next_value
|
131
131
|
raise PrototypingSerieError unless @is_instance
|
132
132
|
|
133
|
-
|
133
|
+
if !@_have_peeked_next_value
|
134
134
|
@_have_peeked_next_value = true
|
135
135
|
@_peeked_next_value = _next_value
|
136
136
|
end
|
@@ -6,6 +6,8 @@ module Musa
|
|
6
6
|
end
|
7
7
|
|
8
8
|
class Splitter
|
9
|
+
include Enumerable
|
10
|
+
|
9
11
|
def initialize(proxy)
|
10
12
|
@proxy = proxy
|
11
13
|
@series = {}
|
@@ -19,39 +21,117 @@ module Musa
|
|
19
21
|
end
|
20
22
|
end
|
21
23
|
|
24
|
+
def each
|
25
|
+
if block_given?
|
26
|
+
if @proxy.hash_mode?
|
27
|
+
@proxy.components.each do |key|
|
28
|
+
yield [key, self[key]]
|
29
|
+
end
|
30
|
+
elsif @proxy.array_mode?
|
31
|
+
@proxy.components.each do |index|
|
32
|
+
yield self[index]
|
33
|
+
end
|
34
|
+
else
|
35
|
+
# do nothing
|
36
|
+
end
|
37
|
+
else
|
38
|
+
if @proxy.hash_mode?
|
39
|
+
@proxy.components.collect { |key| [key, self[key]] }.each
|
40
|
+
elsif @proxy.array_mode?
|
41
|
+
@proxy.components.collect { |index| self[index] }.each
|
42
|
+
else
|
43
|
+
[].each
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def to_hash
|
49
|
+
if @proxy.hash_mode?
|
50
|
+
@proxy.components.collect { |key| [key, self[key]] }.to_h
|
51
|
+
else
|
52
|
+
raise RuntimeError, 'Splitter is not based on Hash: can\'t convert to Hash'
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def to_ary
|
57
|
+
if @proxy.array_mode?
|
58
|
+
[].tap { |_| @proxy.components.each { |i| _[i] = self[i] } }
|
59
|
+
else
|
60
|
+
raise RuntimeError, 'Splitter is not based on Array: can\'t convert to Array'
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
22
64
|
class BufferedProxy
|
23
65
|
include SeriePrototyping
|
24
66
|
|
25
67
|
def initialize(hash_or_array_serie)
|
26
68
|
@source = hash_or_array_serie
|
69
|
+
|
70
|
+
infer_components
|
71
|
+
|
27
72
|
restart restart_source: false
|
28
73
|
|
29
74
|
mark_regarding! @source
|
30
75
|
end
|
31
76
|
|
32
|
-
|
33
|
-
|
34
|
-
|
77
|
+
attr_reader :components
|
78
|
+
|
79
|
+
def hash_mode?; @hash_mode; end
|
80
|
+
def array_mode?; @array_mode; end
|
81
|
+
|
82
|
+
def restart(key_or_index = nil, restart_source: true)
|
83
|
+
if key_or_index
|
84
|
+
@asked_to_restart[key_or_index] = true
|
85
|
+
else
|
86
|
+
@components.each { |c| @asked_to_restart[c] = true }
|
87
|
+
end
|
88
|
+
|
89
|
+
if @asked_to_restart.values.all?
|
90
|
+
@source.restart if restart_source
|
91
|
+
infer_components
|
92
|
+
end
|
35
93
|
end
|
36
94
|
|
37
|
-
def
|
38
|
-
@source.
|
39
|
-
|
95
|
+
private def infer_components
|
96
|
+
source = @source.instance
|
97
|
+
sample = source.current_value || source.peek_next_value
|
98
|
+
|
99
|
+
case sample
|
100
|
+
when Array
|
101
|
+
@components = (0..sample.size-1).to_a
|
102
|
+
@values = []
|
103
|
+
@array_mode = true
|
104
|
+
@hash_mode = false
|
105
|
+
when Hash
|
106
|
+
@components = sample.keys.clone
|
107
|
+
@values = {}
|
108
|
+
@array_mode = false
|
109
|
+
@hash_mode = true
|
110
|
+
else
|
111
|
+
@components = []
|
112
|
+
@values = nil
|
113
|
+
@array_mode = @hash_mode = false
|
114
|
+
end
|
115
|
+
|
116
|
+
@asked_to_restart = {}
|
117
|
+
|
118
|
+
@components.each do |component|
|
119
|
+
@asked_to_restart[component] = false
|
120
|
+
end
|
40
121
|
end
|
41
122
|
|
42
123
|
def next_value(key_or_index)
|
43
|
-
if @values
|
124
|
+
if @values[key_or_index].nil? || @values[key_or_index].empty?
|
125
|
+
|
44
126
|
hash_or_array_value = @source.next_value
|
45
127
|
|
46
128
|
case hash_or_array_value
|
47
129
|
when Hash
|
48
|
-
@values ||= {}
|
49
130
|
hash_or_array_value.each do |k, v|
|
50
131
|
@values[k] ||= []
|
51
132
|
@values[k] << v
|
52
133
|
end
|
53
134
|
when Array
|
54
|
-
@values ||= []
|
55
135
|
hash_or_array_value.each_index do |i|
|
56
136
|
@values[i] ||= []
|
57
137
|
@values[i] << hash_or_array_value[i]
|
@@ -78,7 +158,7 @@ module Musa
|
|
78
158
|
end
|
79
159
|
|
80
160
|
def _restart
|
81
|
-
@source.restart
|
161
|
+
@source.restart @key_or_index
|
82
162
|
end
|
83
163
|
|
84
164
|
def _next_value
|
@@ -195,6 +195,8 @@ module Musa
|
|
195
195
|
include Serie
|
196
196
|
include Musa::Extension::SmartProcBinder
|
197
197
|
|
198
|
+
using Musa::Extension::DeepCopy
|
199
|
+
|
198
200
|
attr_reader :block
|
199
201
|
|
200
202
|
def initialize(*values, **key_values, &block)
|
@@ -211,8 +213,8 @@ module Musa
|
|
211
213
|
end
|
212
214
|
|
213
215
|
def _restart
|
214
|
-
@value_parameters = @original_value_parameters.
|
215
|
-
@key_parameters = @original_key_parameters.
|
216
|
+
@value_parameters = @original_value_parameters.clone(deep: true)
|
217
|
+
@key_parameters = @original_key_parameters.clone(deep: true)
|
216
218
|
|
217
219
|
@first = true
|
218
220
|
@value = nil
|
@@ -220,7 +222,7 @@ module Musa
|
|
220
222
|
|
221
223
|
def _next_value
|
222
224
|
@value = if !@value.nil? || @value.nil? && @first
|
223
|
-
@value = @block.call(*@value_parameters, last_value: @value, **@key_parameters)
|
225
|
+
@value = @block.call(*@value_parameters, last_value: @value, caller: self, **@key_parameters)
|
224
226
|
else
|
225
227
|
nil
|
226
228
|
end
|
@@ -268,9 +270,7 @@ module Musa
|
|
268
270
|
@to.nil?
|
269
271
|
end
|
270
272
|
|
271
|
-
private
|
272
|
-
|
273
|
-
def sign_adjust_step
|
273
|
+
private def sign_adjust_step
|
274
274
|
@step = (-@step if @to && (@from < @to && @step < 0 || @from > @to && @step > 0)) || @step
|
275
275
|
end
|
276
276
|
end
|
@@ -337,9 +337,7 @@ module Musa
|
|
337
337
|
end
|
338
338
|
end
|
339
339
|
|
340
|
-
private
|
341
|
-
|
342
|
-
def adjust_step
|
340
|
+
private def adjust_step
|
343
341
|
@step = (-@step if @from < @to && @step < 0 || @from > @to && @step > 0) || @step
|
344
342
|
@step_count = ((@to - @from) / @step).to_i
|
345
343
|
end
|
@@ -411,9 +409,7 @@ module Musa
|
|
411
409
|
value
|
412
410
|
end
|
413
411
|
|
414
|
-
private
|
415
|
-
|
416
|
-
def adjust_step
|
412
|
+
private def adjust_step
|
417
413
|
@step = (-@step if @from < @to && @step < 0 || @from > @to && @step > 0) || @step
|
418
414
|
@step_count = ((@to - @from) / @step).to_i
|
419
415
|
end
|
@@ -112,6 +112,10 @@ module Musa
|
|
112
112
|
ProcessWith.new self, &yield_block
|
113
113
|
end
|
114
114
|
|
115
|
+
def anticipate(&yield_block)
|
116
|
+
Anticipate.new self, &yield_block
|
117
|
+
end
|
118
|
+
|
115
119
|
###
|
116
120
|
### Implementation
|
117
121
|
###
|
@@ -130,7 +134,7 @@ module Musa
|
|
130
134
|
@block = SmartProcBinder.new(block) if block_given?
|
131
135
|
|
132
136
|
if @source.prototype?
|
133
|
-
@sources = @sources.transform_values { |s| s.prototype }
|
137
|
+
@sources = @sources.transform_values { |s| s.prototype }.freeze
|
134
138
|
else
|
135
139
|
@sources = @sources.transform_values { |s| s.instance }
|
136
140
|
end
|
@@ -168,6 +172,42 @@ module Musa
|
|
168
172
|
|
169
173
|
private_constant :ProcessWith
|
170
174
|
|
175
|
+
class Anticipate
|
176
|
+
include Musa::Extension::SmartProcBinder
|
177
|
+
include Serie
|
178
|
+
|
179
|
+
attr_reader :source, :block
|
180
|
+
|
181
|
+
def initialize(serie, &block)
|
182
|
+
@source = serie
|
183
|
+
@block = block
|
184
|
+
|
185
|
+
mark_regarding! @source
|
186
|
+
end
|
187
|
+
|
188
|
+
def _restart
|
189
|
+
@source.restart
|
190
|
+
end
|
191
|
+
|
192
|
+
def _next_value
|
193
|
+
previous_value = @source.current_value
|
194
|
+
value = @source.next_value
|
195
|
+
peek_next_value = @source.peek_next_value
|
196
|
+
|
197
|
+
if value.nil?
|
198
|
+
nil
|
199
|
+
else
|
200
|
+
@block.call(previous_value, value, peek_next_value)
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
def infinite?
|
205
|
+
@source.infinite?
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
private_constant :Anticipate
|
210
|
+
|
171
211
|
class Switcher
|
172
212
|
include Serie
|
173
213
|
|
@@ -185,7 +225,7 @@ module Musa
|
|
185
225
|
@sources = hash_series.clone.transform_values(&get)
|
186
226
|
end
|
187
227
|
|
188
|
-
if get == :
|
228
|
+
if get == :prototype!
|
189
229
|
@sources.freeze
|
190
230
|
end
|
191
231
|
|
@@ -236,7 +276,7 @@ module Musa
|
|
236
276
|
|
237
277
|
_restart false
|
238
278
|
|
239
|
-
if get == :
|
279
|
+
if get == :prototype
|
240
280
|
@sources.freeze
|
241
281
|
end
|
242
282
|
|
@@ -293,7 +333,7 @@ module Musa
|
|
293
333
|
@sources = hash_series.clone.transform_values(&get)
|
294
334
|
end
|
295
335
|
|
296
|
-
if get == :
|
336
|
+
if get == :prototype
|
297
337
|
@sources.freeze
|
298
338
|
end
|
299
339
|
|
@@ -927,7 +967,7 @@ module Musa
|
|
927
967
|
|
928
968
|
def _next_value
|
929
969
|
if value = @source.next_value
|
930
|
-
while @block.call(value, @history)
|
970
|
+
while value && @block.call(value, @history)
|
931
971
|
@history << value
|
932
972
|
value = @source.next_value
|
933
973
|
end
|
@@ -65,7 +65,7 @@ module Musa
|
|
65
65
|
case n
|
66
66
|
when nil
|
67
67
|
time = value = nil
|
68
|
-
when AbsTimed
|
68
|
+
when Musa::Datasets::AbsTimed
|
69
69
|
time = n[:time].rationalize
|
70
70
|
value = n[@value_attribute].rationalize
|
71
71
|
when Array
|
@@ -87,8 +87,6 @@ module Musa
|
|
87
87
|
|
88
88
|
attr_reader :source
|
89
89
|
|
90
|
-
attr_reader :points_history
|
91
|
-
|
92
90
|
def initialize(reference, step, source, value_attribute, stops, left_open, right_open)
|
93
91
|
@reference = reference
|
94
92
|
@step_size = step.abs
|
@@ -144,7 +142,9 @@ module Musa
|
|
144
142
|
|
145
143
|
return { time: first[:time],
|
146
144
|
@value_attribute => first[:value],
|
147
|
-
duration: durations_to_sum.sum { |_| _[:duration] } }
|
145
|
+
duration: durations_to_sum.sum { |_| _[:duration] } }
|
146
|
+
.extend(Musa::Datasets::AbsTimed)
|
147
|
+
.extend(Musa::Datasets::AbsD)
|
148
148
|
else
|
149
149
|
i += 1
|
150
150
|
end
|
@@ -179,7 +179,9 @@ module Musa
|
|
179
179
|
|
180
180
|
return { time: first[:time],
|
181
181
|
@value_attribute => first[:value],
|
182
|
-
duration: durations_to_sum.sum { |_| _[:duration] } }
|
182
|
+
duration: durations_to_sum.sum { |_| _[:duration] } }
|
183
|
+
.extend(Musa::Datasets::AbsTimed)
|
184
|
+
.extend(Musa::Datasets::AbsD)
|
183
185
|
else
|
184
186
|
i += 1
|
185
187
|
end
|
@@ -214,13 +216,13 @@ module Musa
|
|
214
216
|
if @segments.last && @segments.last[:time] == from_time
|
215
217
|
|
216
218
|
@segments.last[:duration] = to_time - from_time
|
217
|
-
@segments.last[:info] +=
|
219
|
+
@segments.last[:info] += '; edited on a as start'
|
218
220
|
|
219
221
|
else
|
220
222
|
@segments << { time: from_time,
|
221
223
|
value: from_value,
|
222
224
|
duration: to_time - from_time,
|
223
|
-
info:
|
225
|
+
info: 'added on a as start' }
|
224
226
|
|
225
227
|
end
|
226
228
|
|
@@ -229,7 +231,7 @@ module Musa
|
|
229
231
|
value: from_value,
|
230
232
|
duration: 0,
|
231
233
|
stop: true,
|
232
|
-
info:
|
234
|
+
info: 'added on a as end stop' }
|
233
235
|
end
|
234
236
|
else
|
235
237
|
time_increment = to_time - from_time
|
@@ -264,7 +266,7 @@ module Musa
|
|
264
266
|
@segments.last[:value] == value
|
265
267
|
|
266
268
|
@segments.last[:duration] = step_time_increment
|
267
|
-
@segments.last[:info] +=
|
269
|
+
@segments.last[:info] += '; edited on b'
|
268
270
|
|
269
271
|
# puts "process2: editing #{@segments.last}"
|
270
272
|
|
@@ -272,7 +274,7 @@ module Musa
|
|
272
274
|
@segments << v = { time: intermediate_point_time,
|
273
275
|
value: value,
|
274
276
|
duration: step_time_increment,
|
275
|
-
info:
|
277
|
+
info: 'added on b' }
|
276
278
|
|
277
279
|
# puts "process2: adding #{v.inspect}"
|
278
280
|
end
|
@@ -293,7 +295,7 @@ module Musa
|
|
293
295
|
|
294
296
|
private def process(time, value, last_time_value)
|
295
297
|
if time && value
|
296
|
-
raise RuntimeError,
|
298
|
+
raise RuntimeError, 'time only can go forward' if @last_processed_time && time <= @last_processed_time
|
297
299
|
|
298
300
|
q_value = round_quantize(value)
|
299
301
|
|
@@ -400,7 +402,9 @@ module Musa
|
|
400
402
|
if time > first_time
|
401
403
|
result = { time: first_time,
|
402
404
|
@value_attribute => round_to_nearest_quantize(first_value, value),
|
403
|
-
duration: time - first_time }
|
405
|
+
duration: time - first_time }
|
406
|
+
.extend(Musa::Datasets::AbsD)
|
407
|
+
.extend(Musa::Datasets::AbsTimed)
|
404
408
|
else
|
405
409
|
result = _next_value
|
406
410
|
end
|
@@ -409,7 +413,9 @@ module Musa
|
|
409
413
|
next_time = @crossings[1][:time]
|
410
414
|
result = { time: time,
|
411
415
|
@value_attribute => value,
|
412
|
-
duration: next_time - time }
|
416
|
+
duration: next_time - time }
|
417
|
+
.extend(Musa::Datasets::AbsD)
|
418
|
+
.extend(Musa::Datasets::AbsTimed)
|
413
419
|
|
414
420
|
@crossings.shift
|
415
421
|
|
@@ -417,7 +423,9 @@ module Musa
|
|
417
423
|
if @last_time && @last_time > @crossings[0][:time]
|
418
424
|
result = { time: @crossings[0][:time],
|
419
425
|
@value_attribute => @crossings[0][@value_attribute],
|
420
|
-
duration: @last_time - @crossings[0][:time] }
|
426
|
+
duration: @last_time - @crossings[0][:time] }
|
427
|
+
.extend(Musa::Datasets::AbsD)
|
428
|
+
.extend(Musa::Datasets::AbsTimed)
|
421
429
|
|
422
430
|
@last_time = nil
|
423
431
|
end
|
@@ -427,7 +435,9 @@ module Musa
|
|
427
435
|
if @first && @last_time && @last_time > first_time
|
428
436
|
result = { time: first_time,
|
429
437
|
value: round_to_nearest_quantize(first_value),
|
430
|
-
duration: @last_time - first_time }
|
438
|
+
duration: @last_time - first_time }
|
439
|
+
.extend(Musa::Datasets::AbsD)
|
440
|
+
.extend(Musa::Datasets::AbsTimed)
|
431
441
|
|
432
442
|
@first = false
|
433
443
|
@last_time = false
|