musa-dsl 0.22.0 → 0.22.5
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/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
|