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