musa-dsl 0.22.1 → 0.22.6

Sign up to get free protection for your applications and to get access to all the features.
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