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.
Files changed (29) hide show
  1. checksums.yaml +4 -4
  2. data/lib/musa-dsl.rb +1 -1
  3. data/lib/musa-dsl/core-ext/inspect-nice.rb +1 -2
  4. data/lib/musa-dsl/datasets/p.rb +36 -15
  5. data/lib/musa-dsl/datasets/score/to-mxml/process-pdv.rb +14 -12
  6. data/lib/musa-dsl/datasets/score/to-mxml/process-ps.rb +32 -6
  7. data/lib/musa-dsl/datasets/score/to-mxml/to-mxml.rb +24 -10
  8. data/lib/musa-dsl/logger/logger.rb +6 -1
  9. data/lib/musa-dsl/matrix/matrix.rb +9 -7
  10. data/lib/musa-dsl/midi/midi-voices.rb +1 -0
  11. data/lib/musa-dsl/music/scales.rb +1 -1
  12. data/lib/musa-dsl/sequencer/base-sequencer-implementation-play-helper.rb +7 -2
  13. data/lib/musa-dsl/sequencer/base-sequencer-implementation-play-timed.rb +30 -129
  14. data/lib/musa-dsl/sequencer/base-sequencer-implementation.rb +10 -24
  15. data/lib/musa-dsl/sequencer/base-sequencer-tick-based.rb +9 -9
  16. data/lib/musa-dsl/sequencer/base-sequencer-tickless-based.rb +3 -5
  17. data/lib/musa-dsl/sequencer/{base-sequencer-public.rb → base-sequencer.rb} +15 -23
  18. data/lib/musa-dsl/sequencer/sequencer-dsl.rb +7 -4
  19. data/lib/musa-dsl/sequencer/sequencer.rb +8 -1
  20. data/lib/musa-dsl/series/base-series.rb +3 -3
  21. data/lib/musa-dsl/series/hash-or-array-serie-splitter.rb +90 -10
  22. data/lib/musa-dsl/series/main-serie-constructors.rb +8 -12
  23. data/lib/musa-dsl/series/main-serie-operations.rb +45 -5
  24. data/lib/musa-dsl/series/quantizer-serie.rb +25 -15
  25. data/lib/musa-dsl/series/series.rb +1 -1
  26. data/lib/musa-dsl/series/timed-serie.rb +356 -0
  27. data/musa-dsl.gemspec +3 -3
  28. metadata +6 -6
  29. 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, ticks_per_beat,
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, :size, :everying, :playing, :moving,
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-public'
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 accomodate to real subclass specificities.
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
- unless @_have_peeked_next_value
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
- protected def _instance!
33
- super
34
- restart
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 restart(restart_source: true)
38
- @source.restart if restart_source
39
- @values = nil
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.nil? || @values[key_or_index].nil? || @values[key_or_index].empty?
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.collect(&:clone)
215
- @key_parameters = @original_key_parameters.transform_values(&:clone)
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 == :_prototype!
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 == :_prototype!
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 == :_prototype!
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] } }.extend(AbsTimed).extend(AbsD)
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] } }.extend(AbsTimed).extend(AbsD)
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] += "; edited on a as start"
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: "added on a as start" }
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: "added on a as end stop" }
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] += "; edited on b"
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: "added on b" }
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, "time only can go forward" if @last_processed_time && time <= @last_processed_time
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 }.extend(AbsD).extend(AbsTimed)
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 }.extend(AbsD).extend(AbsTimed)
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] }.extend(AbsD).extend(AbsTimed)
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 }.extend(AbsD).extend(AbsTimed)
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