musa-dsl 0.22.6 → 0.23.4
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/smart-proc-binder.rb +13 -11
- data/lib/musa-dsl/datasets/p.rb +14 -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/midi/midi-voices.rb +7 -7
- 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 +2 -2
- data/lib/musa-dsl/sequencer/sequencer-dsl.rb +6 -6
- data/lib/musa-dsl/series/base-series.rb +293 -144
- data/lib/musa-dsl/series/buffer-serie.rb +236 -0
- data/lib/musa-dsl/series/hash-or-array-serie-splitter.rb +142 -128
- data/lib/musa-dsl/series/main-serie-constructors.rb +248 -155
- data/lib/musa-dsl/series/main-serie-operations.rb +324 -316
- data/lib/musa-dsl/series/proxy-serie.rb +25 -41
- data/lib/musa-dsl/series/quantizer-serie.rb +38 -38
- data/lib/musa-dsl/series/queue-serie.rb +39 -43
- data/lib/musa-dsl/series/series-composer.rb +316 -0
- data/lib/musa-dsl/series/series.rb +5 -1
- data/lib/musa-dsl/series/timed-serie.rb +106 -119
- data/musa-dsl.gemspec +12 -2
- metadata +7 -7
- data/.ruby-version +0 -1
- data/lib/musa-dsl/series/holder-serie.rb +0 -87
@@ -0,0 +1,236 @@
|
|
1
|
+
module Musa
|
2
|
+
module Series::Operations
|
3
|
+
def buffered(sync: false)
|
4
|
+
if sync
|
5
|
+
SyncBufferSerie.new(self)
|
6
|
+
else
|
7
|
+
BufferSerie.new(self)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class SyncBufferSerie
|
12
|
+
include Series::Serie.with(source: true)
|
13
|
+
|
14
|
+
def initialize(serie)
|
15
|
+
self.source = serie
|
16
|
+
@history = []
|
17
|
+
@buffers = Set[]
|
18
|
+
|
19
|
+
init
|
20
|
+
end
|
21
|
+
|
22
|
+
private def _restart
|
23
|
+
@source.restart
|
24
|
+
clear_old_history
|
25
|
+
end
|
26
|
+
|
27
|
+
private def _next_value
|
28
|
+
@source.next_value.tap { |value| @history << value unless value.nil? && !@history.empty? && @history.last.nil? }
|
29
|
+
end
|
30
|
+
|
31
|
+
def buffer
|
32
|
+
@buffer ||= Buffer.new(@history)
|
33
|
+
@buffer.send(@get).tap { |_| @buffers << _ }
|
34
|
+
end
|
35
|
+
|
36
|
+
private def clear_old_history
|
37
|
+
min_last_nil_index = @buffers.collect(&:last_nil_index).min
|
38
|
+
|
39
|
+
if min_last_nil_index && min_last_nil_index >=0
|
40
|
+
@history = @history.drop(min_last_nil_index)
|
41
|
+
|
42
|
+
@buffers.each do |b|
|
43
|
+
b._reindex(@history, min_last_nil_index)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
class Buffer
|
49
|
+
include Series::Serie.base
|
50
|
+
|
51
|
+
def initialize(history)
|
52
|
+
@history = history
|
53
|
+
@last_nil_index = -1
|
54
|
+
init
|
55
|
+
end
|
56
|
+
|
57
|
+
attr_reader :last_nil_index
|
58
|
+
|
59
|
+
def _reindex(history, offset)
|
60
|
+
@history = history
|
61
|
+
|
62
|
+
@last_nil_index -= offset
|
63
|
+
@index -= offset
|
64
|
+
end
|
65
|
+
|
66
|
+
private def _init
|
67
|
+
@index = @last_nil_index
|
68
|
+
@wait_restart = false
|
69
|
+
end
|
70
|
+
|
71
|
+
private def _next_value
|
72
|
+
@index += 1 if @index + 1 < @history.size && !@wait_restart
|
73
|
+
|
74
|
+
if @history[@index].nil? && @index < @history.size
|
75
|
+
|
76
|
+
@wait_restart = true
|
77
|
+
|
78
|
+
if @index + 1 < @history.size
|
79
|
+
@last_nil_index = @index
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
@history[@index]
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
private_constant :Buffer
|
88
|
+
end
|
89
|
+
|
90
|
+
private_constant :SyncBufferSerie
|
91
|
+
|
92
|
+
class BufferSerie
|
93
|
+
# modo fill_on_restart: cuando una serie hace restart, las demás no se ven afectadas porque siguen recibiendo
|
94
|
+
# todos los elementos de la serie original
|
95
|
+
|
96
|
+
include Series::Serie.with(source: true)
|
97
|
+
|
98
|
+
def initialize(serie)
|
99
|
+
self.source = serie
|
100
|
+
|
101
|
+
@history = [nil]
|
102
|
+
@nils = [0]
|
103
|
+
@buffers = Set[]
|
104
|
+
|
105
|
+
@singleton = nil
|
106
|
+
@buffer = nil
|
107
|
+
|
108
|
+
init
|
109
|
+
end
|
110
|
+
|
111
|
+
def instance
|
112
|
+
@singleton ||= super
|
113
|
+
end
|
114
|
+
|
115
|
+
def buffer
|
116
|
+
@buffer ||= Buffer.new(self)
|
117
|
+
@buffer
|
118
|
+
end
|
119
|
+
|
120
|
+
private def _restart(buffer)
|
121
|
+
raise ArgumentError, "Can't restart a BufferSerie directly. Should use a buffer instance instead." unless buffer
|
122
|
+
return if @source_just_restarted
|
123
|
+
|
124
|
+
next_nil = @nils.find { |_| _ > buffer.index }
|
125
|
+
|
126
|
+
if next_nil && buffer.index < next_nil
|
127
|
+
buffer.last_nil_index = buffer.index = next_nil
|
128
|
+
|
129
|
+
else
|
130
|
+
until _next_value.nil?; end
|
131
|
+
buffer.last_nil_index = buffer.index = @nils.last
|
132
|
+
end
|
133
|
+
|
134
|
+
clear_old_history
|
135
|
+
|
136
|
+
@source.restart
|
137
|
+
@source_just_restarted = true
|
138
|
+
end
|
139
|
+
|
140
|
+
private def _next_value
|
141
|
+
@source_just_restarted = false
|
142
|
+
value = @source.next_value
|
143
|
+
|
144
|
+
if value.nil?
|
145
|
+
unless @history.last.nil?
|
146
|
+
@history << nil
|
147
|
+
@nils << @history.size - 1
|
148
|
+
end
|
149
|
+
else
|
150
|
+
@history << value
|
151
|
+
end
|
152
|
+
|
153
|
+
value
|
154
|
+
end
|
155
|
+
|
156
|
+
def _register(buffer)
|
157
|
+
@buffers << buffer
|
158
|
+
|
159
|
+
buffer.history = @history
|
160
|
+
buffer.last_nil_index = 0
|
161
|
+
end
|
162
|
+
|
163
|
+
private def clear_old_history
|
164
|
+
min_last_nil_index = @buffers.collect(&:last_nil_index).min
|
165
|
+
|
166
|
+
if min_last_nil_index && min_last_nil_index >=0
|
167
|
+
|
168
|
+
pre_nils = @nils.clone
|
169
|
+
@history = @history.drop(min_last_nil_index)
|
170
|
+
|
171
|
+
@nils.collect! { |_| _ - min_last_nil_index }
|
172
|
+
@nils.delete_if(&:negative?)
|
173
|
+
|
174
|
+
@buffers.each do |b|
|
175
|
+
b._reindex(@history, min_last_nil_index)
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
class Buffer
|
181
|
+
include Series::Serie.with(source: true, private_source: true)
|
182
|
+
|
183
|
+
def initialize(base)
|
184
|
+
self.source = base
|
185
|
+
|
186
|
+
mark_as_prototype! # necesario para que se creen instancias diferentes cada vez que se ejecute BufferSerie.buffer()
|
187
|
+
|
188
|
+
init
|
189
|
+
end
|
190
|
+
|
191
|
+
attr_accessor :history
|
192
|
+
attr_accessor :last_nil_index
|
193
|
+
attr_accessor :index
|
194
|
+
|
195
|
+
def _reindex(history, offset)
|
196
|
+
@history = history
|
197
|
+
@last_nil_index -= offset
|
198
|
+
@index -= offset
|
199
|
+
end
|
200
|
+
|
201
|
+
private def _init
|
202
|
+
@source._register(self) if instance?
|
203
|
+
@index = @last_nil_index
|
204
|
+
end
|
205
|
+
|
206
|
+
private def _restart
|
207
|
+
@source.restart(self)
|
208
|
+
@needs_restart = false
|
209
|
+
end
|
210
|
+
|
211
|
+
private def _next_value
|
212
|
+
value = nil
|
213
|
+
|
214
|
+
unless @needs_restart
|
215
|
+
if @index + 1 < @history.size
|
216
|
+
@index += 1
|
217
|
+
value = @history[@index]
|
218
|
+
else
|
219
|
+
value = _next_value unless @source.next_value.nil?
|
220
|
+
end
|
221
|
+
|
222
|
+
if value.nil?
|
223
|
+
@needs_restart = true
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
value
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
private_constant :Buffer
|
232
|
+
end
|
233
|
+
|
234
|
+
private_constant :BufferSerie
|
235
|
+
end
|
236
|
+
end
|
@@ -1,175 +1,189 @@
|
|
1
1
|
module Musa
|
2
|
-
module Series
|
3
|
-
|
4
|
-
|
5
|
-
|
2
|
+
module Series::Operations
|
3
|
+
def split
|
4
|
+
Splitter.new(self)
|
5
|
+
end
|
6
|
+
|
7
|
+
class Splitter
|
8
|
+
include Enumerable
|
9
|
+
include Series::Serie::Prototyping
|
10
|
+
|
11
|
+
def initialize(source)
|
12
|
+
@source = source
|
13
|
+
@series = {}
|
6
14
|
end
|
7
15
|
|
8
|
-
|
9
|
-
|
16
|
+
def source=(serie)
|
17
|
+
@source = serie
|
18
|
+
@proxy.source = @source if @proxy
|
19
|
+
end
|
10
20
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
21
|
+
protected def _instance!
|
22
|
+
super
|
23
|
+
@proxy = SplitterProxy.new(@source)
|
24
|
+
end
|
15
25
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
26
|
+
def [](key_or_index)
|
27
|
+
raise "Can't get a component because Splitter is a prototype. To get a component you need a Splitter instance." unless @is_instance
|
28
|
+
|
29
|
+
if @series.key?(key_or_index)
|
30
|
+
@series[key_or_index]
|
31
|
+
else
|
32
|
+
@series[key_or_index] = Split.new(@proxy, key_or_index)
|
22
33
|
end
|
34
|
+
end
|
23
35
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
@proxy.components.each do |index|
|
32
|
-
yield self[index]
|
33
|
-
end
|
34
|
-
else
|
35
|
-
# do nothing
|
36
|
+
def each
|
37
|
+
raise "Can't iterate because Splitter is a prototype. To iterate you need a Splitter instance." unless @is_instance
|
38
|
+
|
39
|
+
if block_given?
|
40
|
+
if @proxy.hash_mode?
|
41
|
+
@proxy.components.each do |key|
|
42
|
+
yield [key, self[key]]
|
36
43
|
end
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
elsif @proxy.array_mode?
|
41
|
-
@proxy.components.collect { |index| self[index] }.each
|
42
|
-
else
|
43
|
-
[].each
|
44
|
+
elsif @proxy.array_mode?
|
45
|
+
@proxy.components.each do |index|
|
46
|
+
yield self[index]
|
44
47
|
end
|
48
|
+
else
|
49
|
+
# do nothing
|
45
50
|
end
|
46
|
-
|
47
|
-
|
48
|
-
def to_hash
|
51
|
+
else
|
49
52
|
if @proxy.hash_mode?
|
50
|
-
@proxy.components.collect { |key| [key, self[key]] }.
|
53
|
+
@proxy.components.collect { |key| [key, self[key]] }.each
|
54
|
+
elsif @proxy.array_mode?
|
55
|
+
@proxy.components.collect { |index| self[index] }.each
|
51
56
|
else
|
52
|
-
|
57
|
+
[].each
|
53
58
|
end
|
54
59
|
end
|
60
|
+
end
|
55
61
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
end
|
62
|
+
def to_hash
|
63
|
+
if @proxy.hash_mode?
|
64
|
+
@proxy.components.collect { |key| [key, self[key]] }.to_h
|
65
|
+
else
|
66
|
+
raise RuntimeError, 'Splitter is not based on Hash: can\'t convert to Hash'
|
62
67
|
end
|
68
|
+
end
|
63
69
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
70
|
+
def to_ary
|
71
|
+
if @proxy.array_mode?
|
72
|
+
[].tap { |_| @proxy.components.each { |i| _[i] = self[i] } }
|
73
|
+
else
|
74
|
+
raise RuntimeError, 'Splitter is not based on Array: can\'t convert to Array'
|
75
|
+
end
|
76
|
+
end
|
69
77
|
|
70
|
-
|
78
|
+
class SplitterProxy
|
79
|
+
def initialize(hash_or_array_serie)
|
80
|
+
@source = hash_or_array_serie
|
81
|
+
infer_components
|
82
|
+
end
|
71
83
|
|
72
|
-
|
84
|
+
attr_reader :source
|
73
85
|
|
74
|
-
|
75
|
-
|
86
|
+
def source=(hash_or_array_serie)
|
87
|
+
@source = hash_or_array_serie
|
88
|
+
infer_components
|
89
|
+
end
|
76
90
|
|
77
|
-
|
91
|
+
def hash_mode?; @hash_mode; end
|
78
92
|
|
79
|
-
|
80
|
-
def array_mode?; @array_mode; end
|
93
|
+
def array_mode?; @array_mode; end
|
81
94
|
|
82
|
-
|
83
|
-
if key_or_index
|
84
|
-
@asked_to_restart[key_or_index] = true
|
85
|
-
else
|
86
|
-
@components.each { |c| @asked_to_restart[c] = true }
|
87
|
-
end
|
95
|
+
attr_reader :components
|
88
96
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
97
|
+
def restart(key_or_index = nil)
|
98
|
+
if key_or_index
|
99
|
+
@asked_to_restart[key_or_index] = true
|
100
|
+
else
|
101
|
+
@components.each { |c| @asked_to_restart[c] = true }
|
93
102
|
end
|
94
103
|
|
95
|
-
|
96
|
-
|
97
|
-
|
104
|
+
if @asked_to_restart.values.all?
|
105
|
+
@source.restart
|
106
|
+
infer_components
|
107
|
+
end
|
108
|
+
end
|
98
109
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
110
|
+
private def infer_components
|
111
|
+
source = @source.instance
|
112
|
+
sample = source.current_value || source.peek_next_value
|
113
|
+
|
114
|
+
case sample
|
115
|
+
when Array
|
116
|
+
@components = (0..sample.size-1).to_a
|
117
|
+
@values = []
|
118
|
+
@array_mode = true
|
119
|
+
@hash_mode = false
|
120
|
+
when Hash
|
121
|
+
@components = sample.keys.clone
|
122
|
+
@values = {}
|
123
|
+
@array_mode = false
|
124
|
+
@hash_mode = true
|
125
|
+
else
|
126
|
+
@components = []
|
127
|
+
@values = nil
|
128
|
+
@array_mode = @hash_mode = false
|
129
|
+
end
|
115
130
|
|
116
|
-
|
131
|
+
@asked_to_restart = {}
|
117
132
|
|
118
|
-
|
119
|
-
|
120
|
-
end
|
133
|
+
@components.each do |component|
|
134
|
+
@asked_to_restart[component] = false
|
121
135
|
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def next_value(key_or_index)
|
139
|
+
if @values[key_or_index].nil? || @values[key_or_index].empty?
|
140
|
+
|
141
|
+
hash_or_array_value = @source.next_value
|
122
142
|
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
end
|
134
|
-
when Array
|
135
|
-
hash_or_array_value.each_index do |i|
|
136
|
-
@values[i] ||= []
|
137
|
-
@values[i] << hash_or_array_value[i]
|
138
|
-
end
|
143
|
+
case hash_or_array_value
|
144
|
+
when Hash
|
145
|
+
hash_or_array_value.each do |k, v|
|
146
|
+
@values[k] ||= []
|
147
|
+
@values[k] << v
|
148
|
+
end
|
149
|
+
when Array
|
150
|
+
hash_or_array_value.each_index do |i|
|
151
|
+
@values[i] ||= []
|
152
|
+
@values[i] << hash_or_array_value[i]
|
139
153
|
end
|
140
154
|
end
|
155
|
+
end
|
141
156
|
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
end
|
157
|
+
if @values && !@values[key_or_index].nil?
|
158
|
+
@values[key_or_index].shift
|
159
|
+
else
|
160
|
+
nil
|
147
161
|
end
|
148
162
|
end
|
163
|
+
end
|
149
164
|
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
def initialize(proxy, key_or_index)
|
154
|
-
@source = proxy
|
155
|
-
@key_or_index = key_or_index
|
165
|
+
class Split
|
166
|
+
include Series::Serie.base
|
156
167
|
|
157
|
-
|
158
|
-
|
168
|
+
def initialize(proxy, key_or_index)
|
169
|
+
@proxy = proxy
|
170
|
+
@key_or_index = key_or_index
|
159
171
|
|
160
|
-
|
161
|
-
|
162
|
-
end
|
172
|
+
mark_as_instance!
|
173
|
+
end
|
163
174
|
|
164
|
-
|
165
|
-
|
166
|
-
end
|
175
|
+
private def _restart
|
176
|
+
@proxy.restart(@key_or_index)
|
167
177
|
end
|
168
178
|
|
169
|
-
|
179
|
+
private def _next_value
|
180
|
+
@proxy.next_value(@key_or_index)
|
181
|
+
end
|
170
182
|
end
|
171
183
|
|
172
|
-
private_constant :
|
184
|
+
private_constant :Split
|
173
185
|
end
|
186
|
+
|
187
|
+
private_constant :Splitter
|
174
188
|
end
|
175
189
|
end
|