musa-dsl 0.22.5 → 0.23.3

Sign up to get free protection for your applications and to get access to all the features.
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