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.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +3 -1
  3. data/lib/musa-dsl.rb +14 -8
  4. data/lib/musa-dsl/core-ext/deep-copy.rb +12 -1
  5. data/lib/musa-dsl/core-ext/inspect-nice.rb +1 -2
  6. data/lib/musa-dsl/core-ext/smart-proc-binder.rb +13 -11
  7. data/lib/musa-dsl/datasets/p.rb +41 -16
  8. data/lib/musa-dsl/datasets/score/to-mxml/process-pdv.rb +14 -12
  9. data/lib/musa-dsl/datasets/score/to-mxml/process-ps.rb +32 -6
  10. data/lib/musa-dsl/datasets/score/to-mxml/to-mxml.rb +24 -10
  11. data/lib/musa-dsl/generative/backboner.rb +6 -11
  12. data/lib/musa-dsl/generative/generative-grammar.rb +1 -3
  13. data/lib/musa-dsl/generative/markov.rb +10 -6
  14. data/lib/musa-dsl/logger/logger.rb +6 -1
  15. data/lib/musa-dsl/matrix/matrix.rb +9 -7
  16. data/lib/musa-dsl/midi/midi-voices.rb +1 -0
  17. data/lib/musa-dsl/music/scales.rb +1 -1
  18. data/lib/musa-dsl/neumalang/neumalang.rb +1 -1
  19. data/lib/musa-dsl/neumas/array-to-neumas.rb +1 -1
  20. data/lib/musa-dsl/sequencer/base-sequencer-implementation-play-helper.rb +9 -4
  21. data/lib/musa-dsl/sequencer/base-sequencer-implementation-play-timed.rb +30 -129
  22. data/lib/musa-dsl/sequencer/base-sequencer-implementation.rb +10 -24
  23. data/lib/musa-dsl/sequencer/base-sequencer-tick-based.rb +9 -9
  24. data/lib/musa-dsl/sequencer/base-sequencer-tickless-based.rb +3 -5
  25. data/lib/musa-dsl/sequencer/{base-sequencer-public.rb → base-sequencer.rb} +15 -23
  26. data/lib/musa-dsl/sequencer/sequencer-dsl.rb +9 -7
  27. data/lib/musa-dsl/sequencer/sequencer.rb +8 -1
  28. data/lib/musa-dsl/series/base-series.rb +293 -144
  29. data/lib/musa-dsl/series/buffer-serie.rb +237 -0
  30. data/lib/musa-dsl/series/hash-or-array-serie-splitter.rb +139 -60
  31. data/lib/musa-dsl/series/main-serie-constructors.rb +254 -165
  32. data/lib/musa-dsl/series/main-serie-operations.rb +308 -303
  33. data/lib/musa-dsl/series/proxy-serie.rb +21 -41
  34. data/lib/musa-dsl/series/quantizer-serie.rb +44 -46
  35. data/lib/musa-dsl/series/queue-serie.rb +39 -43
  36. data/lib/musa-dsl/series/series-composer.rb +149 -0
  37. data/lib/musa-dsl/series/series.rb +6 -2
  38. data/lib/musa-dsl/series/timed-serie.rb +343 -0
  39. data/musa-dsl.gemspec +13 -3
  40. metadata +11 -11
  41. data/lib/musa-dsl/series/flattener-timed-serie.rb +0 -61
  42. data/lib/musa-dsl/series/holder-serie.rb +0 -87
@@ -0,0 +1,237 @@
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(main)
121
+ raise ArgumentError, "Can't restart a BufferSerie directly. Should use a buffer instance instead." unless main
122
+ return if @source_just_restarted
123
+
124
+ next_nil = @nils.find { |_| _ > main.index }
125
+
126
+ if next_nil && main.index < next_nil
127
+ main.last_nil_index = main.index = next_nil
128
+
129
+ else
130
+ until _next_value.nil?; end
131
+ main.last_nil_index = main.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
+ @source.next_value
220
+ value = _next_value
221
+ end
222
+
223
+ if value.nil?
224
+ @needs_restart = true
225
+ end
226
+ end
227
+
228
+ value
229
+ end
230
+ end
231
+
232
+ private_constant :Buffer
233
+ end
234
+
235
+ private_constant :BufferSerie
236
+ end
237
+ end
@@ -1,95 +1,174 @@
1
1
  module Musa
2
- module Series
3
- module SerieOperations
4
- def split
5
- Splitter.new(Splitter::BufferedProxy.new(self))
2
+ module Series::Operations
3
+ def split
4
+ Splitter.new(Splitter::BufferedProxy.new(self))
5
+ end
6
+
7
+ class Splitter
8
+ include Enumerable
9
+
10
+ def initialize(proxy)
11
+ @proxy = proxy
12
+ @series = {}
6
13
  end
7
14
 
8
- class Splitter
9
- def initialize(proxy)
10
- @proxy = proxy
11
- @series = {}
15
+ def [](key_or_index)
16
+ if @series.has_key?(key_or_index)
17
+ @series[key_or_index]
18
+ else
19
+ @series[key_or_index] = Split.new(@proxy, key_or_index)
12
20
  end
21
+ end
13
22
 
14
- def [](key_or_index)
15
- if @series.has_key?(key_or_index)
16
- @series[key_or_index]
23
+ def each
24
+ if block_given?
25
+ if @proxy.hash_mode?
26
+ @proxy.components.each do |key|
27
+ yield [key, self[key]]
28
+ end
29
+ elsif @proxy.array_mode?
30
+ @proxy.components.each do |index|
31
+ yield self[index]
32
+ end
17
33
  else
18
- @series[key_or_index] = Split.new(@proxy, key_or_index)
34
+ # do nothing
35
+ end
36
+ else
37
+ if @proxy.hash_mode?
38
+ @proxy.components.collect { |key| [key, self[key]] }.each
39
+ elsif @proxy.array_mode?
40
+ @proxy.components.collect { |index| self[index] }.each
41
+ else
42
+ [].each
19
43
  end
20
44
  end
45
+ end
21
46
 
22
- class BufferedProxy
23
- include SeriePrototyping
47
+ def to_hash
48
+ if @proxy.hash_mode?
49
+ @proxy.components.collect { |key| [key, self[key]] }.to_h
50
+ else
51
+ raise RuntimeError, 'Splitter is not based on Hash: can\'t convert to Hash'
52
+ end
53
+ end
24
54
 
25
- def initialize(hash_or_array_serie)
26
- @source = hash_or_array_serie
27
- restart restart_source: false
55
+ def to_ary
56
+ if @proxy.array_mode?
57
+ [].tap { |_| @proxy.components.each { |i| _[i] = self[i] } }
58
+ else
59
+ raise RuntimeError, 'Splitter is not based on Array: can\'t convert to Array'
60
+ end
61
+ end
62
+
63
+ class BufferedProxy
64
+ include Series::Serie::Prototyping
65
+
66
+ def initialize(hash_or_array_serie)
67
+ @source = hash_or_array_serie
68
+ mark_regarding! @source
69
+
70
+ init
71
+ end
72
+
73
+ attr_reader :components
74
+
75
+ def hash_mode?; @hash_mode; end
76
+ def array_mode?; @array_mode; end
77
+
78
+ def init
79
+ infer_components
80
+ end
28
81
 
29
- mark_regarding! @source
82
+ def restart(key_or_index = nil)
83
+ if key_or_index
84
+ @asked_to_restart[key_or_index] = true
85
+ else
86
+ @components.each { |c| @asked_to_restart[c] = true }
30
87
  end
31
88
 
32
- protected def _instance!
33
- super
34
- restart
89
+ if @asked_to_restart.values.all?
90
+ @source.restart
91
+ infer_components
35
92
  end
93
+ end
36
94
 
37
- def restart(restart_source: true)
38
- @source.restart if restart_source
95
+ private def infer_components
96
+ source = @source.instance
97
+ sample = source.current_value || source.peek_next_value
98
+
99
+ case sample
100
+ when Array
101
+ @components = (0..sample.size-1).to_a
102
+ @values = []
103
+ @array_mode = true
104
+ @hash_mode = false
105
+ when Hash
106
+ @components = sample.keys.clone
107
+ @values = {}
108
+ @array_mode = false
109
+ @hash_mode = true
110
+ else
111
+ @components = []
39
112
  @values = nil
113
+ @array_mode = @hash_mode = false
40
114
  end
41
115
 
42
- def next_value(key_or_index)
43
- if @values.nil? || @values[key_or_index].nil? || @values[key_or_index].empty?
44
- hash_or_array_value = @source.next_value
45
-
46
- case hash_or_array_value
47
- when Hash
48
- @values ||= {}
49
- hash_or_array_value.each do |k, v|
50
- @values[k] ||= []
51
- @values[k] << v
52
- end
53
- when Array
54
- @values ||= []
55
- hash_or_array_value.each_index do |i|
56
- @values[i] ||= []
57
- @values[i] << hash_or_array_value[i]
58
- end
59
- end
60
- end
116
+ @asked_to_restart = {}
61
117
 
62
- if @values && !@values[key_or_index].nil?
63
- @values[key_or_index].shift
64
- else
65
- nil
66
- end
118
+ @components.each do |component|
119
+ @asked_to_restart[component] = false
67
120
  end
68
121
  end
69
122
 
70
- class Split
71
- include Serie
123
+ def next_value(key_or_index)
124
+ if @values[key_or_index].nil? || @values[key_or_index].empty?
72
125
 
73
- def initialize(proxy, key_or_index)
74
- @source = proxy
75
- @key_or_index = key_or_index
126
+ hash_or_array_value = @source.next_value
76
127
 
77
- mark_regarding! @source
128
+ case hash_or_array_value
129
+ when Hash
130
+ hash_or_array_value.each do |k, v|
131
+ @values[k] ||= []
132
+ @values[k] << v
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
139
+ end
78
140
  end
79
141
 
80
- def _restart
81
- @source.restart
142
+ if @values && !@values[key_or_index].nil?
143
+ @values[key_or_index].shift
144
+ else
145
+ nil
82
146
  end
147
+ end
148
+ end
83
149
 
84
- def _next_value
85
- @source.next_value(@key_or_index)
86
- end
150
+ class Split
151
+ include Series::Serie.base
152
+
153
+ def initialize(proxy, key_or_index)
154
+ @source = proxy
155
+ @key_or_index = key_or_index
156
+
157
+ mark_regarding! @source
158
+ end
159
+
160
+ private def _restart
161
+ @source.restart @key_or_index
87
162
  end
88
163
 
89
- private_constant :Split
164
+ private def _next_value
165
+ @source.next_value(@key_or_index)
166
+ end
90
167
  end
91
168
 
92
- private_constant :Splitter
169
+ private_constant :Split
93
170
  end
171
+
172
+ private_constant :Splitter
94
173
  end
95
174
  end