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.
Files changed (38) 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 +38 -15
  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/midi/midi-voices.rb +8 -7
  16. data/lib/musa-dsl/music/scales.rb +1 -1
  17. data/lib/musa-dsl/neumalang/neumalang.rb +1 -1
  18. data/lib/musa-dsl/neumas/array-to-neumas.rb +1 -1
  19. data/lib/musa-dsl/sequencer/base-sequencer-implementation-play-helper.rb +2 -2
  20. data/lib/musa-dsl/sequencer/base-sequencer-implementation-play-timed.rb +2 -1
  21. data/lib/musa-dsl/sequencer/base-sequencer-implementation.rb +2 -0
  22. data/lib/musa-dsl/sequencer/base-sequencer-tick-based.rb +4 -2
  23. data/lib/musa-dsl/sequencer/sequencer-dsl.rb +6 -6
  24. data/lib/musa-dsl/series/base-series.rb +293 -144
  25. data/lib/musa-dsl/series/buffer-serie.rb +236 -0
  26. data/lib/musa-dsl/series/hash-or-array-serie-splitter.rb +145 -115
  27. data/lib/musa-dsl/series/main-serie-constructors.rb +249 -156
  28. data/lib/musa-dsl/series/main-serie-operations.rb +331 -318
  29. data/lib/musa-dsl/series/proxy-serie.rb +25 -41
  30. data/lib/musa-dsl/series/quantizer-serie.rb +38 -38
  31. data/lib/musa-dsl/series/queue-serie.rb +39 -43
  32. data/lib/musa-dsl/series/series-composer.rb +316 -0
  33. data/lib/musa-dsl/series/series.rb +5 -1
  34. data/lib/musa-dsl/series/timed-serie.rb +119 -130
  35. data/musa-dsl.gemspec +13 -3
  36. metadata +9 -9
  37. data/.ruby-version +0 -1
  38. 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
- module SerieOperations
4
- def split
5
- Splitter.new(Splitter::BufferedProxy.new(self))
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
- class Splitter
9
- include Enumerable
16
+ def source=(serie)
17
+ @source = serie
18
+ @proxy.source = @source if @proxy
19
+ end
10
20
 
11
- def initialize(proxy)
12
- @proxy = proxy
13
- @series = {}
14
- end
21
+ protected def _instance!
22
+ super
23
+ @proxy = SplitterProxy.new(@source)
24
+ end
15
25
 
16
- def [](key_or_index)
17
- if @series.has_key?(key_or_index)
18
- @series[key_or_index]
19
- else
20
- @series[key_or_index] = Split.new(@proxy, key_or_index)
21
- end
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
- def each
25
- if block_given?
26
- if @proxy.hash_mode?
27
- @proxy.components.each do |key|
28
- yield [key, self[key]]
29
- end
30
- elsif @proxy.array_mode?
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
- else
38
- if @proxy.hash_mode?
39
- @proxy.components.collect { |key| [key, self[key]] }.each
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
- end
47
-
48
- def to_hash
51
+ else
49
52
  if @proxy.hash_mode?
50
- @proxy.components.collect { |key| [key, self[key]] }.to_h
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
- raise RuntimeError, 'Splitter is not based on Hash: can\'t convert to Hash'
57
+ [].each
53
58
  end
54
59
  end
60
+ end
55
61
 
56
- def to_array
57
- if @proxy.array_mode?
58
- [].tap { |_| @proxy.components.each { |i| _[i] = self[i] } }
59
- else
60
- raise RuntimeError, 'Splitter is not based on Array: can\'t convert to Array'
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
- class BufferedProxy
65
- include SeriePrototyping
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
- def initialize(hash_or_array_serie)
68
- @source = hash_or_array_serie
69
- restart restart_source: false
78
+ class SplitterProxy
79
+ def initialize(hash_or_array_serie)
80
+ @source = hash_or_array_serie
81
+ infer_components
82
+ end
70
83
 
71
- mark_regarding! @source
72
- end
84
+ attr_reader :source
73
85
 
74
- attr_reader :components
86
+ def source=(hash_or_array_serie)
87
+ @source = hash_or_array_serie
88
+ infer_components
89
+ end
75
90
 
76
- def hash_mode?; @hash_mode; end
77
- def array_mode?; @array_mode; end
91
+ def hash_mode?; @hash_mode; end
78
92
 
79
- protected def _instance!
80
- super
81
- restart
82
- end
93
+ def array_mode?; @array_mode; end
83
94
 
84
- def restart(restart_source: true)
85
- @source.restart if restart_source
95
+ attr_reader :components
86
96
 
87
- source = @source.instance
88
- sample = source.current_value || source.peek_next_value
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
- case sample
91
- when Array
92
- @components = (0..sample.size-1).to_a
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
- def next_value(key_or_index)
109
- if @values[key_or_index].nil? || @values[key_or_index].empty?
110
- hash_or_array_value = @source.next_value
111
-
112
- case hash_or_array_value
113
- when Hash
114
- hash_or_array_value.each do |k, v|
115
- @values[k] ||= []
116
- @values[k] << v
117
- end
118
- when Array
119
- hash_or_array_value.each_index do |i|
120
- @values[i] ||= []
121
- @values[i] << hash_or_array_value[i]
122
- end
123
- end
124
- end
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
- if @values && !@values[key_or_index].nil?
127
- @values[key_or_index].shift
128
- else
129
- nil
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
- class Split
135
- include Serie
138
+ def next_value(key_or_index)
139
+ if @values[key_or_index].nil? || @values[key_or_index].empty?
136
140
 
137
- def initialize(proxy, key_or_index)
138
- @source = proxy
139
- @key_or_index = key_or_index
141
+ hash_or_array_value = @source.next_value
140
142
 
141
- mark_regarding! @source
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
- def _restart
145
- @source.restart
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
- def _next_value
149
- @source.next_value(@key_or_index)
150
- end
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
- private_constant :Split
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 :Splitter
184
+ private_constant :Split
157
185
  end
186
+
187
+ private_constant :Splitter
158
188
  end
159
189
  end