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
@@ -324,8 +324,13 @@ module Musa
324
324
  run_operation eval_use_variable(element[:use_variable])
325
325
 
326
326
  when :event
327
- value_parameters = element[:value_parameters] ? element[:value_parameters].collect { |e| subcontext.eval_element(e) } : []
328
- key_parameters = element[:key_parameters] ? element[:key_parameters].collect { |k, e| [k, subcontext.eval_element(e)] }.to_h : {}
327
+ value_parameters = element[:value_parameters] ?
328
+ element[:value_parameters].collect { |e| subcontext.eval_element(e) } :
329
+ []
330
+
331
+ key_parameters = element[:key_parameters] ?
332
+ element[:key_parameters].collect { |k, e| [k, subcontext.eval_element(e)] }.to_h :
333
+ {}
329
334
 
330
335
  { current_operation: :event,
331
336
  current_event: element[:event],
@@ -7,181 +7,82 @@ module Musa; module Sequencer
7
7
  class BaseSequencer
8
8
  private def _play_timed(timed_serie,
9
9
  control,
10
- reference: nil,
11
- step: nil,
12
- right_open: nil,
13
10
  &block)
14
11
 
15
- reference ||= 0r
16
- step ||= 1r
17
-
18
12
  if first_value_sample = timed_serie.peek_next_value
19
-
20
13
  debug "_play_timed: first_value_sample #{first_value_sample}"
21
14
 
22
15
  hash_mode = first_value_sample[:value].is_a?(Hash)
23
16
 
24
17
  if hash_mode
25
- components = first_value_sample[:value].keys
26
-
27
- reference = reference.hashify(keys: components)
28
- step = step.hashify(keys: components)
29
- right_open = right_open.hashify(keys:components)
18
+ component_ids = first_value_sample[:value].keys
30
19
  else
31
20
  size = first_value_sample[:value].size
32
- components = (0 .. size-1).to_a
33
-
34
- reference = reference.arrayfy(size: size)
35
- step = step.arrayfy(size: size)
36
- right_open = right_open.arrayfy(size: size)
37
- end
38
-
39
- split = timed_serie.flatten_timed.split
40
- quantized_series = hash_mode ? {} : []
41
-
42
- components.each do |component|
43
- quantized_series[component] =
44
- QUANTIZE(split[component],
45
- reference: reference[component],
46
- step: step[component],
47
- right_open: right_open[component],
48
- stops: true).instance
21
+ component_ids = (0 .. size-1).to_a
49
22
  end
23
+ extra_attribute_names = Set[*(first_value_sample.keys - [:time, :value])]
50
24
 
51
25
  last_positions = hash_mode ? {} : []
52
26
  end
53
27
 
54
28
  binder = SmartProcBinder.new(block)
55
29
 
56
- _play_timed_step(hash_mode, components, quantized_series, position, last_positions, binder, control)
30
+ _play_timed_step(hash_mode, component_ids, extra_attribute_names, timed_serie,
31
+ position, last_positions, binder, control)
57
32
  end
58
33
 
59
-
60
- private def _play_timed_step(hash_mode, components, quantized_series, start_position, last_positions,
34
+ private def _play_timed_step(hash_mode,
35
+ component_ids, extra_attribute_names,
36
+ timed_serie,
37
+ start_position,
38
+ last_positions,
61
39
  binder, control)
62
40
 
63
- affected_components_by_time = {}
64
-
65
- components.each do |component|
66
- if v = quantized_series[component].peek_next_value
41
+ source_next_value = timed_serie.next_value
67
42
 
68
- debug "_play_timed_step: quantized_series[#{component}].peek_next_value #{v}"
69
- time = v[:time]
70
-
71
- affected_components_by_time[time] ||= []
72
- affected_components_by_time[time] << component
73
- end
74
- end
43
+ affected_components = component_ids.select { |_| !source_next_value[:value][_].nil? } if source_next_value
75
44
 
76
- if affected_components_by_time.any?
77
- time = affected_components_by_time.keys.sort.first
45
+ if affected_components && affected_components.any?
46
+ time = source_next_value[:time]
78
47
 
79
48
  values = hash_mode ? {} : []
80
- next_values = hash_mode ? {} : []
81
- durations = hash_mode ? {} : []
82
- q_durations = hash_mode ? {} : []
49
+ extra_attributes = extra_attribute_names.collect { |_| [_, hash_mode ? {} : []] }.to_h
83
50
  started_ago = hash_mode ? {} : []
84
51
 
85
- affected_components_by_time[time].each do |component|
86
- value = quantized_series[component].next_value
87
-
88
- values[component] = value[:value]
89
- durations[component] = value[:duration]
90
-
91
- q_durations[component] =
92
- _quantize_position(time + durations[component], warn: false) -
93
- _quantize_position(time, warn: false)
52
+ affected_components.each do |component|
53
+ values[component] = source_next_value[:value][component]
94
54
 
95
- nv = quantized_series[component].peek_next_value
96
- next_values[component] = (nv && nv[:value] != values[component]) ? nv[:value] : nil
55
+ extra_attribute_names.each do |attribute_name|
56
+ extra_attributes[attribute_name][component] = source_next_value[attribute_name][component]
57
+ end
97
58
 
98
59
  last_positions[component] = _quantize_position(time, warn: false)
99
60
  end
100
61
 
101
- components.each do |component|
62
+ component_ids.each do |component|
102
63
  if last_positions[component] && last_positions[component] != time
103
64
  sa = _quantize_position(time, warn: false) - last_positions[component]
104
65
  started_ago[component] = (sa == 0) ? nil : sa
105
66
  end
106
67
  end
107
68
 
108
- _numeric_at start_position + _quantize_position(time, warn: false), control do
109
- debug "_play_timed_step: before binder.call: durations #{durations} q_durations #{q_durations}"
110
- binder.call(values, next_values,
111
- duration: durations,
112
- quantized_duration: q_durations,
69
+ _numeric_at _quantize_position(start_position + time, warn: true), control do
70
+ binder.call(values,
71
+ **extra_attributes,
72
+ time: start_position + time,
113
73
  started_ago: started_ago,
114
74
  control: control)
115
75
 
116
- _play_timed_step(hash_mode, components, quantized_series, start_position, last_positions,
76
+ _play_timed_step(hash_mode,
77
+ component_ids, extra_attribute_names,
78
+ timed_serie,
79
+ start_position,
80
+ last_positions,
117
81
  binder, control)
118
82
  end
119
83
  end
120
84
  end
121
85
 
122
- # TODO implement this alternative play method as another mode
123
- # Este es un modo muy interesante pero que implica un procesamiento diferente en el yield_block que no me
124
- # sirve para el código de samples/multidim_sample, puesto que en este el next_values es literal,
125
- # mientras que samples/multidim_sample necesita que el next_value sea nil si el valor no cambia durante el periodo.
126
- #
127
- private def _play_timed_step_b(hash_mode, components, quantized_series, start_position, last_positions,
128
- binder, control)
129
-
130
- affected_components_by_time = {}
131
-
132
- components.each do |component|
133
- if v = quantized_series[component].peek_next_value
134
- time = v[:time]
135
-
136
- affected_components_by_time[time] ||= []
137
- affected_components_by_time[time] << component
138
- end
139
- end
140
-
141
- if !affected_components_by_time.empty?
142
- time = affected_components_by_time.keys.sort.first
143
-
144
- values = hash_mode ? {} : []
145
- next_values = hash_mode ? {} : []
146
- durations = hash_mode ? {} : []
147
- q_durations = hash_mode ? {} : []
148
- started_ago = hash_mode ? {} : []
149
-
150
- affected_components_by_time[time].each do |component|
151
- value = quantized_series[component].next_value
152
-
153
- values[component] = value[:value]
154
- durations[component] = value[:duration]
155
-
156
- q_durations[component] =
157
- _quantize_position(time + durations[component], warn: false) -
158
- _quantize_position(time, warn: false)
159
-
160
- last_positions[component] = _quantize_position(time, warn: false)
161
- end
162
-
163
- components.each do |component|
164
- nv = quantized_series[component].peek_next_value
165
- next_values[component] = nv[:value] if nv
166
-
167
- if last_positions[component] && last_positions[component] != time
168
- started_ago[component] = _quantize_position(time, warn: false) - last_positions[component]
169
- end
170
- end
171
-
172
- _numeric_at start_position + _quantize_position(time, warn: false), control do
173
- binder.call(values, next_values,
174
- duration: durations,
175
- quantized_duration: q_durations,
176
- started_ago: started_ago,
177
- control: control)
178
-
179
- _play_timed_step_b(hash_mode, components, quantized_series, start_position, last_positions,
180
- binder, control)
181
- end
182
- end
183
- end
184
-
185
86
  class PlayTimedControl < EventHandler
186
87
  attr_reader :do_on_stop, :do_after
187
88
 
@@ -9,6 +9,8 @@ module Musa; module Sequencer
9
9
  include Musa::Extension::SmartProcBinder
10
10
  include Musa::Extension::DeepCopy
11
11
 
12
+ using Musa::Extension::InspectNice
13
+
12
14
  private def _tick(position_to_run)
13
15
  @before_tick.each { |block| block.call position_to_run }
14
16
  queue = @timeslots[position_to_run]
@@ -63,21 +65,16 @@ module Musa; module Sequencer
63
65
  nil
64
66
  end
65
67
 
66
- private def _numeric_at(at_position, control, with: nil, debug: nil, &block)
68
+ private def _numeric_at(at_position, control, debug: nil, &block)
67
69
  raise ArgumentError, "'at_position' parameter cannot be nil" if at_position.nil?
68
70
  raise ArgumentError, 'Yield block is mandatory' unless block
69
71
 
70
72
  at_position = _quantize_position(at_position)
71
73
 
72
- value_parameters = []
73
- value_parameters << with if !with.nil? && !with.is_a?(Hash)
74
-
75
74
  block_key_parameters_binder =
76
75
  SmartProcBinder.new block, on_rescue: proc { |e| _rescue_error(e) }
77
76
 
78
77
  key_parameters = {}
79
- key_parameters.merge! block_key_parameters_binder._apply(nil, with).last if with.is_a?(Hash)
80
-
81
78
  key_parameters[:control] = control if block_key_parameters_binder.key?(:control)
82
79
 
83
80
  if at_position == @position
@@ -85,7 +82,7 @@ module Musa; module Sequencer
85
82
 
86
83
  begin
87
84
  locked = @tick_mutex.try_lock
88
- block_key_parameters_binder._call(value_parameters, key_parameters)
85
+ block_key_parameters_binder._call(nil, key_parameters)
89
86
  ensure
90
87
  @tick_mutex.unlock if locked
91
88
  end
@@ -100,8 +97,8 @@ module Musa; module Sequencer
100
97
  end
101
98
  end
102
99
 
103
- @timeslots[at_position] << { parent_control: control, block: block_key_parameters_binder,
104
- value_parameters: value_parameters,
100
+ @timeslots[at_position] << { parent_control: control,
101
+ block: block_key_parameters_binder,
105
102
  key_parameters: key_parameters }
106
103
  else
107
104
  @logger.warn('BaseSequencer') { "._numeric_at: ignoring past 'at' command for #{at_position}" }
@@ -110,20 +107,14 @@ module Musa; module Sequencer
110
107
  nil
111
108
  end
112
109
 
113
- private def _serie_at(bar_position_serie, control, with: nil, debug: nil, &block)
114
- bar_position = bar_position_serie.next_value
115
-
116
- with_value = if with.respond_to? :next_value
117
- with.next_value
118
- else
119
- with
120
- end
110
+ private def _serie_at(position_or_serie, control, debug: nil, &block)
111
+ bar_position = position_or_serie.next_value
121
112
 
122
113
  if bar_position
123
- _numeric_at bar_position, control, with: with_value, debug: debug, &block
114
+ _numeric_at bar_position, control, debug: debug, &block
124
115
 
125
116
  _numeric_at bar_position, control, debug: false do
126
- _serie_at bar_position_serie, control, with: with, debug: debug, &block
117
+ _serie_at position_or_serie, control, debug: debug, &block
127
118
  end
128
119
  else
129
120
  # serie finalizada
@@ -224,8 +215,3 @@ module Musa; module Sequencer
224
215
  private_constant :EventHandler
225
216
  end
226
217
  end; end
227
-
228
- require_relative 'base-sequencer-implementation-every'
229
- require_relative 'base-sequencer-implementation-move'
230
- require_relative 'base-sequencer-implementation-play'
231
- require_relative 'base-sequencer-implementation-play-timed'
@@ -3,6 +3,8 @@ module Musa
3
3
  class BaseSequencer
4
4
  module TickBasedTiming
5
5
 
6
+ using Musa::Extension::InspectNice
7
+
6
8
  attr_reader :position, :ticks_per_bar, :tick_duration
7
9
 
8
10
  def tick
@@ -27,9 +29,7 @@ module Musa
27
29
  _release_public_ticks
28
30
  end
29
31
 
30
- private
31
-
32
- def _init_timing
32
+ private def _init_timing
33
33
  @ticks_per_bar = Rational(beats_per_bar * ticks_per_beat)
34
34
  @tick_duration = Rational(1, @ticks_per_bar)
35
35
 
@@ -37,11 +37,11 @@ module Musa
37
37
  @hold_ticks = 0
38
38
  end
39
39
 
40
- def _reset_timing
40
+ private def _reset_timing
41
41
  @position = @position_mutex.synchronize { 1r - @tick_duration }
42
42
  end
43
43
 
44
- def _quantize_position(position, warn: true)
44
+ private def _quantize_position(position, warn: true)
45
45
  ticks_position = position / @tick_duration
46
46
 
47
47
  if ticks_position.round != ticks_position
@@ -50,19 +50,19 @@ module Musa
50
50
 
51
51
  if warn
52
52
  @logger.warn('BaseSequencer') { "_check_position: rounding "\
53
- "position #{original_position} (#{original_position.to_f.round(5)}) "\
54
- "to tick precision: #{position} (#{position.to_f.round(5)})" }
53
+ "position #{original_position.inspect} (#{original_position.to_f.round(5)}) "\
54
+ "to tick precision: #{position.inspect} (#{position.to_f.round(5)})" }
55
55
  end
56
56
  end
57
57
 
58
58
  position
59
59
  end
60
60
 
61
- def _hold_public_ticks
61
+ private def _hold_public_ticks
62
62
  @hold_public_ticks = true
63
63
  end
64
64
 
65
- def _release_public_ticks
65
+ private def _release_public_ticks
66
66
  @hold_ticks.times { _tick(@position_mutex.synchronize { @position += @tick_duration }) }
67
67
  @hold_ticks = 0
68
68
  @hold_public_ticks = false
@@ -53,16 +53,14 @@ module Musa
53
53
  @on_fast_forward.each { |block| block.call(false) }
54
54
  end
55
55
 
56
- private
57
-
58
- def _init_timing
56
+ private def _init_timing
59
57
  end
60
58
 
61
- def _reset_timing
59
+ private def _reset_timing
62
60
  @position = nil
63
61
  end
64
62
 
65
- def _quantize_position(position, warn: false)
63
+ private def _quantize_position(position, warn: false)
66
64
  position
67
65
  end
68
66
  end
@@ -30,6 +30,7 @@ module Musa
30
30
  else
31
31
  @logger = Musa::Logger::Logger.new(sequencer: self, position_format: log_position_format)
32
32
 
33
+ @logger.fatal!
33
34
  @logger.error! if do_error_log || do_error_log.nil?
34
35
  @logger.debug! if do_log
35
36
  end
@@ -82,6 +83,11 @@ module Musa
82
83
  @timeslots.empty?
83
84
  end
84
85
 
86
+ def quantize_position(position, warn: nil)
87
+ warn ||= false
88
+ _quantize_position(position, warn: warn)
89
+ end
90
+
85
91
  def run
86
92
  tick until empty?
87
93
  end
@@ -114,22 +120,19 @@ module Musa
114
120
  @event_handlers.last.launch event, *value_parameters, **key_parameters
115
121
  end
116
122
 
117
- def wait(bars_delay, with: nil, debug: nil, &block)
123
+ def wait(bars_delay, debug: nil, &block)
118
124
  debug ||= false
119
125
 
120
126
  control = EventHandler.new @event_handlers.last
121
127
  @event_handlers.push control
122
128
 
123
129
  if bars_delay.is_a? Numeric
124
- _numeric_at position + bars_delay.rationalize, control, with: with, debug: debug, &block
130
+ _numeric_at position + bars_delay.rationalize, control, debug: debug, &block
125
131
  else
126
132
  bars_delay = Series::S(*bars_delay) if bars_delay.is_a?(Array)
127
133
  bars_delay = bars_delay.instance if bars_delay
128
134
 
129
- with = Series::S(*with).repeat if with.is_a?(Array)
130
- with = with.instance if with
131
-
132
- _serie_at bars_delay.eval { |delay| position + delay }, control, with: with, debug: debug, &block
135
+ _serie_at bars_delay.eval { |delay| position + delay }, control, debug: debug, &block
133
136
  end
134
137
 
135
138
  @event_handlers.pop
@@ -137,11 +140,11 @@ module Musa
137
140
  control
138
141
  end
139
142
 
140
- def now(with: nil, &block)
143
+ def now(&block)
141
144
  control = EventHandler.new @event_handlers.last
142
145
  @event_handlers.push control
143
146
 
144
- _numeric_at position, control, with: with, &block
147
+ _numeric_at position, control, &block
145
148
 
146
149
  @event_handlers.pop
147
150
 
@@ -154,22 +157,19 @@ module Musa
154
157
  nil
155
158
  end
156
159
 
157
- def at(bar_position, with: nil, debug: nil, &block)
160
+ def at(bar_position, debug: nil, &block)
158
161
  debug ||= false
159
162
 
160
163
  control = EventHandler.new @event_handlers.last
161
164
  @event_handlers.push control
162
165
 
163
166
  if bar_position.is_a? Numeric
164
- _numeric_at bar_position.rationalize, control, with: with, debug: debug, &block
167
+ _numeric_at bar_position.rationalize, control, debug: debug, &block
165
168
  else
166
169
  bar_position = Series::S(*bar_position) if bar_position.is_a? Array
167
170
  bar_position = bar_position.instance if bar_position
168
171
 
169
- with = Series::S(*with).repeat if with.is_a? Array
170
- with = with.instance if with
171
-
172
- _serie_at bar_position, control, with: with, debug: debug, &block
172
+ _serie_at bar_position, control, debug: debug, &block
173
173
  end
174
174
 
175
175
  @event_handlers.pop
@@ -215,9 +215,6 @@ module Musa
215
215
  end
216
216
 
217
217
  def play_timed(timed_serie,
218
- reference: nil,
219
- step: nil,
220
- right_open: nil,
221
218
  on_stop: nil,
222
219
  after_bars: nil, after: nil,
223
220
  &block)
@@ -233,12 +230,7 @@ module Musa
233
230
 
234
231
  @event_handlers.push control
235
232
 
236
- _play_timed(timed_serie.instance,
237
- control,
238
- reference: reference,
239
- step: step,
240
- right_open: right_open,
241
- &block)
233
+ _play_timed(timed_serie.instance, control, &block)
242
234
 
243
235
  @event_handlers.pop
244
236