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
@@ -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