musa-dsl 0.22.2 → 0.23.0
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/Gemfile +3 -1
- data/lib/musa-dsl.rb +14 -8
- data/lib/musa-dsl/core-ext/deep-copy.rb +12 -1
- data/lib/musa-dsl/core-ext/inspect-nice.rb +1 -2
- data/lib/musa-dsl/core-ext/smart-proc-binder.rb +13 -11
- data/lib/musa-dsl/datasets/p.rb +41 -16
- 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/generative/backboner.rb +6 -11
- data/lib/musa-dsl/generative/generative-grammar.rb +1 -3
- data/lib/musa-dsl/generative/markov.rb +10 -6
- 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/neumalang/neumalang.rb +1 -1
- data/lib/musa-dsl/neumas/array-to-neumas.rb +1 -1
- data/lib/musa-dsl/sequencer/base-sequencer-implementation-play-helper.rb +9 -4
- 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 +9 -7
- data/lib/musa-dsl/sequencer/sequencer.rb +8 -1
- data/lib/musa-dsl/series/base-series.rb +293 -144
- data/lib/musa-dsl/series/buffer-serie.rb +237 -0
- data/lib/musa-dsl/series/hash-or-array-serie-splitter.rb +139 -60
- data/lib/musa-dsl/series/main-serie-constructors.rb +254 -165
- data/lib/musa-dsl/series/main-serie-operations.rb +308 -303
- data/lib/musa-dsl/series/proxy-serie.rb +21 -41
- data/lib/musa-dsl/series/quantizer-serie.rb +44 -46
- data/lib/musa-dsl/series/queue-serie.rb +39 -43
- data/lib/musa-dsl/series/series-composer.rb +149 -0
- data/lib/musa-dsl/series/series.rb +6 -2
- data/lib/musa-dsl/series/timed-serie.rb +343 -0
- data/musa-dsl.gemspec +13 -3
- metadata +11 -11
- data/lib/musa-dsl/series/flattener-timed-serie.rb +0 -61
- data/lib/musa-dsl/series/holder-serie.rb +0 -87
@@ -3,13 +3,8 @@ require_relative '../core-ext/with'
|
|
3
3
|
|
4
4
|
using Musa::Extension::Arrayfy
|
5
5
|
|
6
|
-
#
|
7
|
-
#
|
8
|
-
# crear rama tb debe recibir la serie de la history -> ya lo hace
|
9
|
-
# crear rama puede repetirse (hasta terminar según ended_when) -> no
|
10
|
-
#
|
11
|
-
# hacer que pueda funcionar en tiempo real? le vas suministrando seeds y le vas diciendo qué opción has elegido (p.ej. para hacer un armonizador en tiempo real)
|
12
|
-
# esto mismo sería aplicable en otros generadores? variatio/darwin? generative-grammar? markov?
|
6
|
+
# TODO hacer que pueda funcionar en tiempo real? le vas suministrando seeds y le vas diciendo qué opción has elegido (p.ej. para hacer un armonizador en tiempo real)
|
7
|
+
# TODO esto mismo sería aplicable en otros generadores? variatio/darwin? generative-grammar? markov?
|
13
8
|
|
14
9
|
module Musa
|
15
10
|
module Backboner
|
@@ -17,12 +12,12 @@ module Musa
|
|
17
12
|
include Musa::Extension::With
|
18
13
|
|
19
14
|
def initialize(&block)
|
20
|
-
@
|
15
|
+
@dsl = RulesEvalContext.new(&block)
|
21
16
|
end
|
22
17
|
|
23
18
|
def generate_possibilities(object, confirmed_node = nil, node = nil, grow_rules = nil)
|
24
19
|
node ||= Node.new
|
25
|
-
grow_rules ||= @
|
20
|
+
grow_rules ||= @dsl._grow_rules
|
26
21
|
|
27
22
|
history = confirmed_node.history if confirmed_node
|
28
23
|
history ||= []
|
@@ -33,9 +28,9 @@ module Musa
|
|
33
28
|
if grow_rule
|
34
29
|
grow_rule.generate_possibilities(object, history).each do |new_object|
|
35
30
|
new_node = Node.new new_object, node
|
36
|
-
new_node.mark_as_ended! if @
|
31
|
+
new_node.mark_as_ended! if @dsl._ended? new_object
|
37
32
|
|
38
|
-
rejection = @
|
33
|
+
rejection = @dsl._cut_rules.find { |cut_rule| cut_rule.rejects?(new_object, history) }
|
39
34
|
# TODO: include rejection secondary reasons in rejection message
|
40
35
|
|
41
36
|
new_node.reject! rejection if rejection
|
@@ -100,9 +100,7 @@ module Musa
|
|
100
100
|
options[index].to_serie.to_node
|
101
101
|
end
|
102
102
|
|
103
|
-
def to_serie(flatten:
|
104
|
-
flatten ||= true
|
105
|
-
|
103
|
+
def to_serie(flatten: true, &condition)
|
106
104
|
serie = _options(&condition).collect { |o| o.collect(&:content) }.to_serie(of_series: true).merge
|
107
105
|
serie = serie.flatten if flatten
|
108
106
|
|
@@ -7,9 +7,8 @@ module Musa
|
|
7
7
|
module Markov
|
8
8
|
class Markov
|
9
9
|
include Musa::Extension::SmartProcBinder
|
10
|
-
include Musa::Series::Serie
|
10
|
+
include Musa::Series::Serie.base
|
11
11
|
|
12
|
-
attr_accessor :start, :finish, :random, :transitions
|
13
12
|
|
14
13
|
def initialize(transitions:, start:, finish: nil, random: nil)
|
15
14
|
@transitions = transitions.clone.freeze
|
@@ -22,23 +21,28 @@ module Musa
|
|
22
21
|
|
23
22
|
@procedure_binders = {}
|
24
23
|
|
25
|
-
|
24
|
+
init
|
26
25
|
end
|
27
26
|
|
28
|
-
|
27
|
+
attr_accessor :start
|
28
|
+
attr_accessor :finish
|
29
|
+
attr_accessor :random
|
30
|
+
attr_accessor :transitions
|
31
|
+
|
32
|
+
private def _init
|
29
33
|
@current = nil
|
30
34
|
@finished = false
|
31
35
|
@history = []
|
32
36
|
end
|
33
37
|
|
34
|
-
def _next_value
|
38
|
+
private def _next_value
|
35
39
|
if @finished
|
36
40
|
@current = nil
|
37
41
|
else
|
38
42
|
if @current.nil?
|
39
43
|
@current = @start
|
40
44
|
else
|
41
|
-
if @transitions.has_key?
|
45
|
+
if @transitions.has_key?(@current)
|
42
46
|
options = @transitions[@current]
|
43
47
|
|
44
48
|
case options
|
@@ -1,7 +1,12 @@
|
|
1
1
|
require 'logger'
|
2
2
|
|
3
|
+
require_relative '../core-ext/inspect-nice'
|
4
|
+
|
5
|
+
|
3
6
|
module Musa; module Logger
|
4
7
|
class Logger < ::Logger
|
8
|
+
using Musa::Extension::InspectNice
|
9
|
+
|
5
10
|
def initialize(sequencer: nil, position_format: nil)
|
6
11
|
super STDERR, level: WARN
|
7
12
|
|
@@ -22,7 +27,7 @@ module Musa; module Logger
|
|
22
27
|
|
23
28
|
progname = "[#{progname}]" if progname
|
24
29
|
|
25
|
-
"#{position}#{level}#{progname} #{msg}\n"
|
30
|
+
"#{position}#{level}#{progname}#{' ' if position || level || progname}#{msg}\n"
|
26
31
|
else
|
27
32
|
"\n"
|
28
33
|
end
|
@@ -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
|
|
@@ -169,6 +169,7 @@ module Musa
|
|
169
169
|
private_constant :ControllersControl
|
170
170
|
|
171
171
|
class NoteControl
|
172
|
+
attr_reader :voice, :pitch, :velocity, :velocity_off, :duration
|
172
173
|
attr_reader :start_position, :end_position
|
173
174
|
|
174
175
|
def initialize(voice, pitch:, velocity: nil, duration: nil, velocity_off: nil)
|
@@ -303,7 +303,7 @@ module Musa
|
|
303
303
|
|
304
304
|
def [](grade_or_symbol)
|
305
305
|
|
306
|
-
raise ArgumentError, "grade_or_symbol '#{grade_or_symbol}' should be a
|
306
|
+
raise ArgumentError, "grade_or_symbol '#{grade_or_symbol}' should be a Integer, String or Symbol" unless grade_or_symbol.is_a?(Symbol) || grade_or_symbol.is_a?(String) || grade_or_symbol.is_a?(Integer)
|
307
307
|
|
308
308
|
wide_grade, sharps = grade_of(grade_or_symbol)
|
309
309
|
|
@@ -21,7 +21,7 @@ module Musa
|
|
21
21
|
def convert_to_neumas(e)
|
22
22
|
case e
|
23
23
|
when Musa::Neumas::Neuma::Serie then e
|
24
|
-
when Musa::Neumas::Neuma::Parallel then
|
24
|
+
when Musa::Neumas::Neuma::Parallel then S(e).extend(Musa::Neumas::Neuma::Serie)
|
25
25
|
when String then e.to_neumas
|
26
26
|
else
|
27
27
|
raise ArgumentError, "Don't know how to convert to neumas #{e}"
|
@@ -262,11 +262,11 @@ module Musa
|
|
262
262
|
|
263
263
|
when Musa::Series::Serie
|
264
264
|
{ current_operation: :play,
|
265
|
-
current_parameter: element.restart }
|
265
|
+
current_parameter: element.instance.restart }
|
266
266
|
|
267
267
|
when Parallel
|
268
268
|
{ current_operation: :parallel_play,
|
269
|
-
current_parameter: element.tap { |e| e.each(&:restart) } }
|
269
|
+
current_parameter: element.instance.tap { |e| e.each(&:restart) } }
|
270
270
|
|
271
271
|
when Array
|
272
272
|
{ current_operation: :no_eval_play,
|
@@ -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
|
|