musa-dsl 0.22.5 → 0.23.3
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 +38 -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/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/midi/midi-voices.rb +8 -7
- 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 +2 -2
- data/lib/musa-dsl/sequencer/base-sequencer-implementation-play-timed.rb +2 -1
- data/lib/musa-dsl/sequencer/base-sequencer-implementation.rb +2 -0
- data/lib/musa-dsl/sequencer/base-sequencer-tick-based.rb +4 -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 +145 -115
- data/lib/musa-dsl/series/main-serie-constructors.rb +249 -156
- data/lib/musa-dsl/series/main-serie-operations.rb +331 -318
- 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 +119 -130
- data/musa-dsl.gemspec +13 -3
- metadata +9 -9
- 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,159 +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
|
-
|
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
|
66
77
|
|
67
|
-
|
68
|
-
|
69
|
-
|
78
|
+
class SplitterProxy
|
79
|
+
def initialize(hash_or_array_serie)
|
80
|
+
@source = hash_or_array_serie
|
81
|
+
infer_components
|
82
|
+
end
|
70
83
|
|
71
|
-
|
72
|
-
end
|
84
|
+
attr_reader :source
|
73
85
|
|
74
|
-
|
86
|
+
def source=(hash_or_array_serie)
|
87
|
+
@source = hash_or_array_serie
|
88
|
+
infer_components
|
89
|
+
end
|
75
90
|
|
76
|
-
|
77
|
-
def array_mode?; @array_mode; end
|
91
|
+
def hash_mode?; @hash_mode; end
|
78
92
|
|
79
|
-
|
80
|
-
super
|
81
|
-
restart
|
82
|
-
end
|
93
|
+
def array_mode?; @array_mode; end
|
83
94
|
|
84
|
-
|
85
|
-
@source.restart if restart_source
|
95
|
+
attr_reader :components
|
86
96
|
|
87
|
-
|
88
|
-
|
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 }
|
102
|
+
end
|
89
103
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
@values = []
|
94
|
-
@array_mode = true
|
95
|
-
@hash_mode = false
|
96
|
-
when Hash
|
97
|
-
@components = sample.keys.clone
|
98
|
-
@values = {}
|
99
|
-
@array_mode = false
|
100
|
-
@hash_mode = true
|
101
|
-
else
|
102
|
-
@components = []
|
103
|
-
@values = nil
|
104
|
-
@array_mode = @hash_mode = false
|
105
|
-
end
|
104
|
+
if @asked_to_restart.values.all?
|
105
|
+
@source.restart
|
106
|
+
infer_components
|
106
107
|
end
|
108
|
+
end
|
107
109
|
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
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
|
125
130
|
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
end
|
131
|
+
@asked_to_restart = {}
|
132
|
+
|
133
|
+
@components.each do |component|
|
134
|
+
@asked_to_restart[component] = false
|
131
135
|
end
|
132
136
|
end
|
133
137
|
|
134
|
-
|
135
|
-
|
138
|
+
def next_value(key_or_index)
|
139
|
+
if @values[key_or_index].nil? || @values[key_or_index].empty?
|
136
140
|
|
137
|
-
|
138
|
-
@source = proxy
|
139
|
-
@key_or_index = key_or_index
|
141
|
+
hash_or_array_value = @source.next_value
|
140
142
|
|
141
|
-
|
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]
|
153
|
+
end
|
154
|
+
end
|
142
155
|
end
|
143
156
|
|
144
|
-
|
145
|
-
@
|
157
|
+
if @values && !@values[key_or_index].nil?
|
158
|
+
@values[key_or_index].shift
|
159
|
+
else
|
160
|
+
nil
|
146
161
|
end
|
162
|
+
end
|
163
|
+
end
|
147
164
|
|
148
|
-
|
149
|
-
|
150
|
-
|
165
|
+
class Split
|
166
|
+
include Series::Serie.base
|
167
|
+
|
168
|
+
def initialize(proxy, key_or_index)
|
169
|
+
@proxy = proxy
|
170
|
+
@key_or_index = key_or_index
|
171
|
+
|
172
|
+
mark_as_instance!
|
151
173
|
end
|
152
174
|
|
153
|
-
|
175
|
+
private def _restart
|
176
|
+
@proxy.restart(@key_or_index)
|
177
|
+
end
|
178
|
+
|
179
|
+
private def _next_value
|
180
|
+
@proxy.next_value(@key_or_index)
|
181
|
+
end
|
154
182
|
end
|
155
183
|
|
156
|
-
private_constant :
|
184
|
+
private_constant :Split
|
157
185
|
end
|
186
|
+
|
187
|
+
private_constant :Splitter
|
158
188
|
end
|
159
189
|
end
|