musa-dsl 0.22.0 → 0.22.5
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/datasets/p.rb +3 -1
- data/lib/musa-dsl/matrix/matrix.rb +9 -7
- data/lib/musa-dsl/sequencer/base-sequencer-implementation-play-helper.rb +7 -2
- data/lib/musa-dsl/sequencer/base-sequencer-implementation-play-timed.rb +28 -128
- data/lib/musa-dsl/sequencer/base-sequencer-implementation.rb +8 -24
- data/lib/musa-dsl/sequencer/base-sequencer-tick-based.rb +5 -7
- 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 +2 -2
- data/lib/musa-dsl/series/hash-or-array-serie-splitter.rb +68 -4
- data/lib/musa-dsl/series/main-serie-constructors.rb +7 -11
- data/lib/musa-dsl/series/main-serie-operations.rb +39 -4
- 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 +354 -0
- data/musa-dsl.gemspec +2 -2
- metadata +4 -4
- data/lib/musa-dsl/series/flattener-timed-serie.rb +0 -61
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 77d95cd844364ae8dce08779712a34fdb0e8e349336717ffc7e49580c293b647
|
4
|
+
data.tar.gz: 16b7d33203bdd273acd5f235189025fa15797e7d09a1bee498151d521c0109d3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bad2f753e7c62c93276dd5a019f57ff8eb2b5c23c38a20989e4dcc5f7a3a4365dfdd1532750da0cbb8dbe0a08c459fb02f8f62b0fd1246f1a5f8da8c755c49c5
|
7
|
+
data.tar.gz: a7a7e3d32b7a723c206ec098585cbbad76d2ef377ad55007a722537ef0b1070a9a43a4a18740758db82167193b55e1b524e7bb7f3bdf5251e7beba1c2effd6d5
|
data/lib/musa-dsl.rb
CHANGED
data/lib/musa-dsl/datasets/p.rb
CHANGED
@@ -22,8 +22,10 @@ module Musa::Datasets
|
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
|
-
def to_timed_serie(time_start
|
25
|
+
def to_timed_serie(time_start: nil, time_start_component: nil, base_duration: nil)
|
26
26
|
time_start ||= 0r
|
27
|
+
time_start += self.first[time_start_component] if time_start_component
|
28
|
+
|
27
29
|
base_duration ||= 1/4r # TODO review incoherence between neumalang 1/4r base duration for quarter notes and general 1r size of bar
|
28
30
|
|
29
31
|
# TODO if instead of using clone (needed because of p.shift) we use index counter the P elements would be evaluated on the last moment
|
@@ -22,8 +22,8 @@ module Musa
|
|
22
22
|
indexes
|
23
23
|
end
|
24
24
|
|
25
|
-
def to_p(time_dimension
|
26
|
-
condensed_matrices.collect { |m| m.to_p(time_dimension, keep_time: keep_time) }
|
25
|
+
def to_p(time_dimension:, keep_time: nil)
|
26
|
+
condensed_matrices.collect { |m| m.to_p(time_dimension: time_dimension, keep_time: keep_time) }
|
27
27
|
end
|
28
28
|
|
29
29
|
def condensed_matrices
|
@@ -69,14 +69,14 @@ module Musa
|
|
69
69
|
refine ::Matrix do
|
70
70
|
include Musa::Datasets
|
71
71
|
|
72
|
-
def to_p(time_dimension
|
72
|
+
def to_p(time_dimension:, keep_time: nil)
|
73
73
|
decompose(self.to_a, time_dimension).collect do |points|
|
74
74
|
line = []
|
75
75
|
|
76
76
|
start_point = points[0]
|
77
77
|
start_time = start_point[time_dimension]
|
78
78
|
|
79
|
-
line << start_point.tap { |_| _.delete_at(time_dimension) unless keep_time; _ }.extend(Datasets::V)
|
79
|
+
line << start_point.clone.tap { |_| _.delete_at(time_dimension) unless keep_time; _ }.extend(Datasets::V)
|
80
80
|
|
81
81
|
(1..points.size-1).each do |i|
|
82
82
|
end_point = points[i]
|
@@ -84,7 +84,7 @@ module Musa
|
|
84
84
|
end_time = end_point[time_dimension]
|
85
85
|
|
86
86
|
line << end_time - start_time
|
87
|
-
line << end_point.tap { |_| _.delete_at(time_dimension) unless keep_time; _ }.extend(Datasets::V)
|
87
|
+
line << end_point.clone.tap { |_| _.delete_at(time_dimension) unless keep_time; _ }.extend(Datasets::V)
|
88
88
|
|
89
89
|
start_time = end_time
|
90
90
|
end
|
@@ -107,8 +107,9 @@ module Musa
|
|
107
107
|
|
108
108
|
x_dim_values_indexes.keys.sort.each do |value|
|
109
109
|
x_dim_values_indexes[value].each do |index|
|
110
|
+
#
|
110
111
|
# hacia un lado
|
111
|
-
|
112
|
+
#
|
112
113
|
unless used_indexes.include?(index)
|
113
114
|
i = index
|
114
115
|
xx = array[i][time_dimension]
|
@@ -125,8 +126,9 @@ module Musa
|
|
125
126
|
|
126
127
|
directional_segments << a if a.size > 1
|
127
128
|
|
129
|
+
#
|
128
130
|
# y hacia el otro
|
129
|
-
|
131
|
+
#
|
130
132
|
i = index
|
131
133
|
xx = array[i][time_dimension]
|
132
134
|
|
@@ -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,98 +7,59 @@ 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
|
@@ -106,82 +67,21 @@ module Musa; module Sequencer
|
|
106
67
|
end
|
107
68
|
|
108
69
|
_numeric_at start_position + _quantize_position(time, warn: false), control do
|
109
|
-
|
110
|
-
|
111
|
-
duration: durations,
|
112
|
-
quantized_duration: q_durations,
|
70
|
+
binder.call(values,
|
71
|
+
**extra_attributes,
|
113
72
|
started_ago: started_ago,
|
114
73
|
control: control)
|
115
74
|
|
116
|
-
_play_timed_step(hash_mode,
|
75
|
+
_play_timed_step(hash_mode,
|
76
|
+
component_ids, extra_attribute_names,
|
77
|
+
timed_serie,
|
78
|
+
start_position,
|
79
|
+
last_positions,
|
117
80
|
binder, control)
|
118
81
|
end
|
119
82
|
end
|
120
83
|
end
|
121
84
|
|
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
85
|
class PlayTimedControl < EventHandler
|
186
86
|
attr_reader :do_on_stop, :do_after
|
187
87
|
|
@@ -63,21 +63,16 @@ module Musa; module Sequencer
|
|
63
63
|
nil
|
64
64
|
end
|
65
65
|
|
66
|
-
private def _numeric_at(at_position, control,
|
66
|
+
private def _numeric_at(at_position, control, debug: nil, &block)
|
67
67
|
raise ArgumentError, "'at_position' parameter cannot be nil" if at_position.nil?
|
68
68
|
raise ArgumentError, 'Yield block is mandatory' unless block
|
69
69
|
|
70
70
|
at_position = _quantize_position(at_position)
|
71
71
|
|
72
|
-
value_parameters = []
|
73
|
-
value_parameters << with if !with.nil? && !with.is_a?(Hash)
|
74
|
-
|
75
72
|
block_key_parameters_binder =
|
76
73
|
SmartProcBinder.new block, on_rescue: proc { |e| _rescue_error(e) }
|
77
74
|
|
78
75
|
key_parameters = {}
|
79
|
-
key_parameters.merge! block_key_parameters_binder._apply(nil, with).last if with.is_a?(Hash)
|
80
|
-
|
81
76
|
key_parameters[:control] = control if block_key_parameters_binder.key?(:control)
|
82
77
|
|
83
78
|
if at_position == @position
|
@@ -85,7 +80,7 @@ module Musa; module Sequencer
|
|
85
80
|
|
86
81
|
begin
|
87
82
|
locked = @tick_mutex.try_lock
|
88
|
-
block_key_parameters_binder._call(
|
83
|
+
block_key_parameters_binder._call(nil, key_parameters)
|
89
84
|
ensure
|
90
85
|
@tick_mutex.unlock if locked
|
91
86
|
end
|
@@ -100,8 +95,8 @@ module Musa; module Sequencer
|
|
100
95
|
end
|
101
96
|
end
|
102
97
|
|
103
|
-
@timeslots[at_position] << { parent_control: control,
|
104
|
-
|
98
|
+
@timeslots[at_position] << { parent_control: control,
|
99
|
+
block: block_key_parameters_binder,
|
105
100
|
key_parameters: key_parameters }
|
106
101
|
else
|
107
102
|
@logger.warn('BaseSequencer') { "._numeric_at: ignoring past 'at' command for #{at_position}" }
|
@@ -110,20 +105,14 @@ module Musa; module Sequencer
|
|
110
105
|
nil
|
111
106
|
end
|
112
107
|
|
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
|
108
|
+
private def _serie_at(position_or_serie, control, debug: nil, &block)
|
109
|
+
bar_position = position_or_serie.next_value
|
121
110
|
|
122
111
|
if bar_position
|
123
|
-
_numeric_at bar_position, control,
|
112
|
+
_numeric_at bar_position, control, debug: debug, &block
|
124
113
|
|
125
114
|
_numeric_at bar_position, control, debug: false do
|
126
|
-
_serie_at
|
115
|
+
_serie_at position_or_serie, control, debug: debug, &block
|
127
116
|
end
|
128
117
|
else
|
129
118
|
# serie finalizada
|
@@ -224,8 +213,3 @@ module Musa; module Sequencer
|
|
224
213
|
private_constant :EventHandler
|
225
214
|
end
|
226
215
|
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'
|
@@ -27,9 +27,7 @@ module Musa
|
|
27
27
|
_release_public_ticks
|
28
28
|
end
|
29
29
|
|
30
|
-
private
|
31
|
-
|
32
|
-
def _init_timing
|
30
|
+
private def _init_timing
|
33
31
|
@ticks_per_bar = Rational(beats_per_bar * ticks_per_beat)
|
34
32
|
@tick_duration = Rational(1, @ticks_per_bar)
|
35
33
|
|
@@ -37,11 +35,11 @@ module Musa
|
|
37
35
|
@hold_ticks = 0
|
38
36
|
end
|
39
37
|
|
40
|
-
def _reset_timing
|
38
|
+
private def _reset_timing
|
41
39
|
@position = @position_mutex.synchronize { 1r - @tick_duration }
|
42
40
|
end
|
43
41
|
|
44
|
-
def _quantize_position(position, warn: true)
|
42
|
+
private def _quantize_position(position, warn: true)
|
45
43
|
ticks_position = position / @tick_duration
|
46
44
|
|
47
45
|
if ticks_position.round != ticks_position
|
@@ -58,11 +56,11 @@ module Musa
|
|
58
56
|
position
|
59
57
|
end
|
60
58
|
|
61
|
-
def _hold_public_ticks
|
59
|
+
private def _hold_public_ticks
|
62
60
|
@hold_public_ticks = true
|
63
61
|
end
|
64
62
|
|
65
|
-
def _release_public_ticks
|
63
|
+
private def _release_public_ticks
|
66
64
|
@hold_ticks.times { _tick(@position_mutex.synchronize { @position += @tick_duration }) }
|
67
65
|
@hold_ticks = 0
|
68
66
|
@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
|