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
@@ -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] ?
|
328
|
-
|
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
|
-
|
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
|
-
|
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,
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
77
|
-
time =
|
45
|
+
if affected_components && affected_components.any?
|
46
|
+
time = source_next_value[:time]
|
78
47
|
|
79
48
|
values = hash_mode ? {} : []
|
80
|
-
|
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
|
-
|
86
|
-
|
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
|
-
|
96
|
-
|
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
|
-
|
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 +
|
109
|
-
|
110
|
-
|
111
|
-
|
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,
|
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,
|
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(
|
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,
|
104
|
-
|
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(
|
114
|
-
bar_position =
|
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,
|
114
|
+
_numeric_at bar_position, control, debug: debug, &block
|
124
115
|
|
125
116
|
_numeric_at bar_position, control, debug: false do
|
126
|
-
_serie_at
|
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,
|
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,
|
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
|
-
|
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(
|
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,
|
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,
|
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,
|
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
|
-
|
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
|
|