musa-dsl 0.14.16
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 +7 -0
- data/.gitignore +10 -0
- data/Gemfile +20 -0
- data/LICENSE.md +157 -0
- data/README.md +8 -0
- data/lib/musa-dsl/core-ext/array-apply-get.rb +18 -0
- data/lib/musa-dsl/core-ext/array-explode-ranges.rb +29 -0
- data/lib/musa-dsl/core-ext/array-to-neumas.rb +28 -0
- data/lib/musa-dsl/core-ext/array-to-serie.rb +20 -0
- data/lib/musa-dsl/core-ext/arrayfy.rb +15 -0
- data/lib/musa-dsl/core-ext/as-context-run.rb +44 -0
- data/lib/musa-dsl/core-ext/duplicate.rb +134 -0
- data/lib/musa-dsl/core-ext/dynamic-proxy.rb +55 -0
- data/lib/musa-dsl/core-ext/inspect-nice.rb +28 -0
- data/lib/musa-dsl/core-ext/key-parameters-procedure-binder.rb +85 -0
- data/lib/musa-dsl/core-ext/proc-nice.rb +13 -0
- data/lib/musa-dsl/core-ext/send-nice.rb +21 -0
- data/lib/musa-dsl/core-ext/string-to-neumas.rb +27 -0
- data/lib/musa-dsl/core-ext.rb +13 -0
- data/lib/musa-dsl/datasets/gdv-decorators.rb +221 -0
- data/lib/musa-dsl/datasets/gdv.rb +499 -0
- data/lib/musa-dsl/datasets/pdv.rb +44 -0
- data/lib/musa-dsl/datasets.rb +5 -0
- data/lib/musa-dsl/generative/darwin.rb +145 -0
- data/lib/musa-dsl/generative/generative-grammar.rb +294 -0
- data/lib/musa-dsl/generative/markov.rb +78 -0
- data/lib/musa-dsl/generative/rules.rb +282 -0
- data/lib/musa-dsl/generative/variatio.rb +331 -0
- data/lib/musa-dsl/generative.rb +5 -0
- data/lib/musa-dsl/midi/midi-recorder.rb +83 -0
- data/lib/musa-dsl/midi/midi-voices.rb +274 -0
- data/lib/musa-dsl/midi.rb +2 -0
- data/lib/musa-dsl/music/chord-definition.rb +99 -0
- data/lib/musa-dsl/music/chord-definitions.rb +13 -0
- data/lib/musa-dsl/music/chords.rb +326 -0
- data/lib/musa-dsl/music/equally-tempered-12-tone-scale-system.rb +204 -0
- data/lib/musa-dsl/music/scales.rb +584 -0
- data/lib/musa-dsl/music.rb +6 -0
- data/lib/musa-dsl/neuma/neuma.rb +181 -0
- data/lib/musa-dsl/neuma.rb +1 -0
- data/lib/musa-dsl/neumalang/neumalang.citrus +294 -0
- data/lib/musa-dsl/neumalang/neumalang.rb +179 -0
- data/lib/musa-dsl/neumalang.rb +3 -0
- data/lib/musa-dsl/repl/repl.rb +143 -0
- data/lib/musa-dsl/repl.rb +1 -0
- data/lib/musa-dsl/sequencer/base-sequencer-implementation-control.rb +189 -0
- data/lib/musa-dsl/sequencer/base-sequencer-implementation-play-helper.rb +354 -0
- data/lib/musa-dsl/sequencer/base-sequencer-implementation.rb +382 -0
- data/lib/musa-dsl/sequencer/base-sequencer-public.rb +261 -0
- data/lib/musa-dsl/sequencer/sequencer-dsl.rb +94 -0
- data/lib/musa-dsl/sequencer/sequencer.rb +3 -0
- data/lib/musa-dsl/sequencer.rb +1 -0
- data/lib/musa-dsl/series/base-series.rb +245 -0
- data/lib/musa-dsl/series/hash-serie-splitter.rb +194 -0
- data/lib/musa-dsl/series/holder-serie.rb +87 -0
- data/lib/musa-dsl/series/main-serie-constructors.rb +726 -0
- data/lib/musa-dsl/series/main-serie-operations.rb +1151 -0
- data/lib/musa-dsl/series/proxy-serie.rb +69 -0
- data/lib/musa-dsl/series/queue-serie.rb +94 -0
- data/lib/musa-dsl/series/series.rb +8 -0
- data/lib/musa-dsl/series.rb +1 -0
- data/lib/musa-dsl/transport/clock.rb +36 -0
- data/lib/musa-dsl/transport/dummy-clock.rb +47 -0
- data/lib/musa-dsl/transport/external-tick-clock.rb +31 -0
- data/lib/musa-dsl/transport/input-midi-clock.rb +124 -0
- data/lib/musa-dsl/transport/timer-clock.rb +102 -0
- data/lib/musa-dsl/transport/timer.rb +40 -0
- data/lib/musa-dsl/transport/transport.rb +137 -0
- data/lib/musa-dsl/transport.rb +9 -0
- data/lib/musa-dsl.rb +17 -0
- data/musa-dsl.gemspec +17 -0
- metadata +174 -0
@@ -0,0 +1,726 @@
|
|
1
|
+
require 'musa-dsl/core-ext/arrayfy'
|
2
|
+
|
3
|
+
# TODO: añadir en for: steps: (nº de pasos en los que repartir el incremento)
|
4
|
+
|
5
|
+
module Musa
|
6
|
+
module Series
|
7
|
+
def NIL
|
8
|
+
NilSerie.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def S(*values)
|
12
|
+
FromArray.new values.explode_ranges
|
13
|
+
end
|
14
|
+
|
15
|
+
def _SE(values, extends:)
|
16
|
+
FromArray.new values.explode_ranges, extends
|
17
|
+
end
|
18
|
+
|
19
|
+
def H(**series_hash)
|
20
|
+
FromHash.new series_hash, false
|
21
|
+
end
|
22
|
+
|
23
|
+
def HC(**series_hash)
|
24
|
+
FromHash.new series_hash, true
|
25
|
+
end
|
26
|
+
|
27
|
+
def A(*series)
|
28
|
+
FromArrayOfSeries.new series, false
|
29
|
+
end
|
30
|
+
|
31
|
+
def AC(*series)
|
32
|
+
FromArrayOfSeries.new series, true
|
33
|
+
end
|
34
|
+
|
35
|
+
def E(**args, &block)
|
36
|
+
if args.key?(:start) && args.length == 1
|
37
|
+
FromAutoEvalBlockOnSeed.new args[:start], &block
|
38
|
+
elsif args.empty?
|
39
|
+
FromEvalBlock.new &block
|
40
|
+
else
|
41
|
+
raise ArgumentError, 'only optional start: argument is allowed'
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def FOR(from: nil, to: nil, step: nil)
|
46
|
+
from ||= 0
|
47
|
+
step ||= 1
|
48
|
+
ForLoop.new from, to, step
|
49
|
+
end
|
50
|
+
|
51
|
+
def RND(*values, from: nil, to: nil, step: nil, random: nil)
|
52
|
+
random = Random.new random if random.is_a?(Integer)
|
53
|
+
random ||= Random.new
|
54
|
+
|
55
|
+
if !values.empty? && from.nil? && to.nil? && step.nil?
|
56
|
+
RandomValuesFromArray.new values.explode_ranges, random
|
57
|
+
elsif values.empty? && !to.nil?
|
58
|
+
from ||= 0
|
59
|
+
step ||= 1
|
60
|
+
RandomNumbersFromRange.new from, to, step, random
|
61
|
+
else
|
62
|
+
raise ArgumentError, 'cannot use values and from:/to:/step: together'
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def MERGE(*values)
|
67
|
+
Sequence.new(values)
|
68
|
+
end
|
69
|
+
|
70
|
+
def RND1(*values, from: nil, to: nil, step: nil, random: nil)
|
71
|
+
random = Random.new random if random.is_a?(Integer)
|
72
|
+
random ||= Random.new
|
73
|
+
|
74
|
+
if !values.empty? && from.nil? && to.nil? && step.nil?
|
75
|
+
RandomValueFromArray.new values.explode_ranges, random
|
76
|
+
elsif values.empty? && !to.nil?
|
77
|
+
from ||= 0
|
78
|
+
step ||= 1
|
79
|
+
RandomNumberFromRange.new from, to, step, random
|
80
|
+
else
|
81
|
+
raise ArgumentError, 'cannot use values and from:/to:/step: parameters together'
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def SIN(start_value: nil, steps: nil, amplitude: nil, center: nil)
|
86
|
+
amplitude ||= 1.0
|
87
|
+
center ||= 0.0
|
88
|
+
start_value ||= center
|
89
|
+
SinFunction.new start_value, steps, amplitude, center
|
90
|
+
end
|
91
|
+
|
92
|
+
def FIBO()
|
93
|
+
Fibonacci.new
|
94
|
+
end
|
95
|
+
|
96
|
+
def HARMO(error: nil, extended: nil)
|
97
|
+
error ||= 0.5
|
98
|
+
extended ||= false
|
99
|
+
HarmonicNotes.new error, extended
|
100
|
+
end
|
101
|
+
|
102
|
+
###
|
103
|
+
### Implementation
|
104
|
+
###
|
105
|
+
|
106
|
+
class NilSerie
|
107
|
+
include Serie
|
108
|
+
def _next_value
|
109
|
+
nil
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
private_constant :NilSerie
|
114
|
+
|
115
|
+
class FromArray
|
116
|
+
include Serie
|
117
|
+
|
118
|
+
attr_reader :values
|
119
|
+
|
120
|
+
def initialize(values = nil, extends = nil)
|
121
|
+
@values = values.clone.freeze
|
122
|
+
@index = 0
|
123
|
+
|
124
|
+
extends.arrayfy.each { |e| extend(e) }
|
125
|
+
|
126
|
+
mark_as_prototype!
|
127
|
+
end
|
128
|
+
|
129
|
+
def _restart
|
130
|
+
@index = 0
|
131
|
+
end
|
132
|
+
|
133
|
+
def _next_value
|
134
|
+
if @values && @index < @values.size
|
135
|
+
value = @values[@index]
|
136
|
+
@index += 1
|
137
|
+
else
|
138
|
+
value = nil
|
139
|
+
end
|
140
|
+
|
141
|
+
value
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
private_constant :FromArray
|
146
|
+
|
147
|
+
class Sequence
|
148
|
+
include Serie
|
149
|
+
|
150
|
+
attr_reader :sources
|
151
|
+
|
152
|
+
def initialize(series)
|
153
|
+
@sources = if series[0].prototype?
|
154
|
+
series.collect(&:prototype).freeze
|
155
|
+
else
|
156
|
+
series.collect(&:instance)
|
157
|
+
end
|
158
|
+
|
159
|
+
_restart false
|
160
|
+
|
161
|
+
mark_regarding! series[0]
|
162
|
+
end
|
163
|
+
|
164
|
+
def _prototype
|
165
|
+
@sources = @sources.collect(&:prototype).freeze
|
166
|
+
end
|
167
|
+
|
168
|
+
def _instance
|
169
|
+
@sources = @sources.collect(&:instance)
|
170
|
+
end
|
171
|
+
|
172
|
+
def _restart(restart_sources = true)
|
173
|
+
@index = 0
|
174
|
+
@sources[@index].restart if restart_sources
|
175
|
+
end
|
176
|
+
|
177
|
+
def _next_value
|
178
|
+
value = nil
|
179
|
+
|
180
|
+
if @index < @sources.size
|
181
|
+
value = @sources[@index].next_value
|
182
|
+
|
183
|
+
if value.nil?
|
184
|
+
@index += 1
|
185
|
+
if @index < @sources.size
|
186
|
+
@sources[@index].restart
|
187
|
+
value = next_value
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
value
|
193
|
+
end
|
194
|
+
|
195
|
+
def infinite?
|
196
|
+
!!@sources.find(&:infinite?)
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
private_constant :Sequence
|
201
|
+
|
202
|
+
class FromAutoEvalBlockOnSeed
|
203
|
+
include Serie
|
204
|
+
|
205
|
+
attr_reader :start, :block
|
206
|
+
|
207
|
+
def initialize(start, &block)
|
208
|
+
@start = start
|
209
|
+
@block = block
|
210
|
+
|
211
|
+
@current = nil
|
212
|
+
@first = true
|
213
|
+
|
214
|
+
mark_as_prototype!
|
215
|
+
end
|
216
|
+
|
217
|
+
def _restart
|
218
|
+
@current = nil
|
219
|
+
@first = true
|
220
|
+
end
|
221
|
+
|
222
|
+
def _next_value
|
223
|
+
if @first
|
224
|
+
@first = false
|
225
|
+
@current = @start
|
226
|
+
else
|
227
|
+
raise 'Block is undefined' unless @block
|
228
|
+
|
229
|
+
@current = @block.call @current unless @current.nil?
|
230
|
+
end
|
231
|
+
|
232
|
+
@current
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
private_constant :FromAutoEvalBlockOnSeed
|
237
|
+
|
238
|
+
class FromEvalBlock
|
239
|
+
include Serie
|
240
|
+
|
241
|
+
attr_reader :block
|
242
|
+
|
243
|
+
def initialize(&block)
|
244
|
+
@block = block
|
245
|
+
_restart
|
246
|
+
|
247
|
+
mark_as_prototype!
|
248
|
+
end
|
249
|
+
|
250
|
+
def _restart
|
251
|
+
@index = 0
|
252
|
+
@value = nil
|
253
|
+
end
|
254
|
+
|
255
|
+
def _next_value
|
256
|
+
raise 'Block is undefined' unless @block
|
257
|
+
|
258
|
+
@value = @block.call @index unless @value.nil? && @index > 0
|
259
|
+
value = @value
|
260
|
+
@index += 1
|
261
|
+
|
262
|
+
value
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
private_constant :FromEvalBlock
|
267
|
+
|
268
|
+
class ForLoop
|
269
|
+
include Serie
|
270
|
+
|
271
|
+
attr_reader :from, :to, :step
|
272
|
+
|
273
|
+
def initialize(from, to, step)
|
274
|
+
@from = from
|
275
|
+
@to = to
|
276
|
+
@step = step
|
277
|
+
|
278
|
+
sign_adjust_step
|
279
|
+
|
280
|
+
_restart
|
281
|
+
|
282
|
+
mark_as_prototype!
|
283
|
+
end
|
284
|
+
|
285
|
+
def _restart
|
286
|
+
@value = @from
|
287
|
+
end
|
288
|
+
|
289
|
+
def _next_value
|
290
|
+
if @value
|
291
|
+
value = @value
|
292
|
+
@value += @step
|
293
|
+
end
|
294
|
+
|
295
|
+
@value = nil if @to && @value && (@value > @to && @step.positive? || @value < @to && @step.negative?)
|
296
|
+
|
297
|
+
value
|
298
|
+
end
|
299
|
+
|
300
|
+
def infinite?
|
301
|
+
@to.nil?
|
302
|
+
end
|
303
|
+
|
304
|
+
private
|
305
|
+
|
306
|
+
def sign_adjust_step
|
307
|
+
@step = (-@step if @to && (@from < @to && @step < 0 || @from > @to && @step > 0)) || @step
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
311
|
+
private_constant :ForLoop
|
312
|
+
|
313
|
+
class RandomValueFromArray
|
314
|
+
include Serie
|
315
|
+
|
316
|
+
attr_reader :values, :random
|
317
|
+
|
318
|
+
def initialize(values, random)
|
319
|
+
@values = values.clone.freeze
|
320
|
+
@random = random
|
321
|
+
|
322
|
+
_restart
|
323
|
+
|
324
|
+
mark_as_prototype!
|
325
|
+
end
|
326
|
+
|
327
|
+
def _restart
|
328
|
+
@value = nil
|
329
|
+
end
|
330
|
+
|
331
|
+
def _next_value
|
332
|
+
if @value
|
333
|
+
nil
|
334
|
+
else
|
335
|
+
@value = @values[@random.rand(0...@values.size)]
|
336
|
+
end
|
337
|
+
end
|
338
|
+
end
|
339
|
+
|
340
|
+
private_constant :RandomValueFromArray
|
341
|
+
|
342
|
+
class RandomNumberFromRange
|
343
|
+
include Serie
|
344
|
+
|
345
|
+
attr_reader :from, :to, :step, :random
|
346
|
+
|
347
|
+
def initialize(from, to, step, random)
|
348
|
+
@from = from
|
349
|
+
@to = to
|
350
|
+
@step = step
|
351
|
+
|
352
|
+
adjust_step
|
353
|
+
|
354
|
+
@random = random
|
355
|
+
|
356
|
+
_restart
|
357
|
+
|
358
|
+
mark_as_prototype!
|
359
|
+
end
|
360
|
+
|
361
|
+
def _restart
|
362
|
+
@value = nil
|
363
|
+
end
|
364
|
+
|
365
|
+
def _next_value
|
366
|
+
if @value
|
367
|
+
nil
|
368
|
+
else
|
369
|
+
@value = @from + @random.rand(0..@step_count) * @step
|
370
|
+
end
|
371
|
+
end
|
372
|
+
|
373
|
+
private
|
374
|
+
|
375
|
+
def adjust_step
|
376
|
+
@step = (-@step if @from < @to && @step < 0 || @from > @to && @step > 0) || @step
|
377
|
+
@step_count = ((@to - @from) / @step).to_i
|
378
|
+
end
|
379
|
+
end
|
380
|
+
|
381
|
+
private_constant :RandomNumberFromRange
|
382
|
+
|
383
|
+
class RandomValuesFromArray
|
384
|
+
include Serie
|
385
|
+
|
386
|
+
attr_reader :values, :random
|
387
|
+
|
388
|
+
def initialize(values, random)
|
389
|
+
@values = values.clone.freeze
|
390
|
+
@random = random
|
391
|
+
|
392
|
+
_restart
|
393
|
+
|
394
|
+
mark_as_prototype!
|
395
|
+
end
|
396
|
+
|
397
|
+
def _restart
|
398
|
+
@available_values = @values.dup
|
399
|
+
end
|
400
|
+
|
401
|
+
def _next_value
|
402
|
+
value = nil
|
403
|
+
unless @available_values.empty?
|
404
|
+
i = @random.rand(0...@available_values.size)
|
405
|
+
value = @available_values[i]
|
406
|
+
@available_values.delete_at i
|
407
|
+
end
|
408
|
+
value
|
409
|
+
end
|
410
|
+
end
|
411
|
+
|
412
|
+
private_constant :RandomValuesFromArray
|
413
|
+
|
414
|
+
class RandomNumbersFromRange
|
415
|
+
include Serie
|
416
|
+
|
417
|
+
attr_reader :from, :to, :step, :random
|
418
|
+
|
419
|
+
def initialize(from, to, step, random)
|
420
|
+
@from = from
|
421
|
+
@to = to
|
422
|
+
@step = step
|
423
|
+
|
424
|
+
adjust_step
|
425
|
+
|
426
|
+
@random = random
|
427
|
+
|
428
|
+
_restart
|
429
|
+
|
430
|
+
mark_as_prototype!
|
431
|
+
end
|
432
|
+
|
433
|
+
def _restart
|
434
|
+
@available_steps = (0..@step_count).to_a
|
435
|
+
end
|
436
|
+
|
437
|
+
def _next_value
|
438
|
+
value = nil
|
439
|
+
unless @available_steps.empty?
|
440
|
+
i = @random.rand(0...@available_steps.size)
|
441
|
+
value = @from + @available_steps[i] * @step unless @value
|
442
|
+
@available_steps.delete_at i
|
443
|
+
end
|
444
|
+
value
|
445
|
+
end
|
446
|
+
|
447
|
+
private
|
448
|
+
|
449
|
+
def adjust_step
|
450
|
+
@step = (-@step if @from < @to && @step < 0 || @from > @to && @step > 0) || @step
|
451
|
+
@step_count = ((@to - @from) / @step).to_i
|
452
|
+
end
|
453
|
+
end
|
454
|
+
|
455
|
+
private_constant :RandomNumbersFromRange
|
456
|
+
|
457
|
+
class FromHash
|
458
|
+
include Serie
|
459
|
+
|
460
|
+
attr_reader :sources, :cycle
|
461
|
+
|
462
|
+
def initialize(series_hash, cycle_all_series)
|
463
|
+
@sources = series_hash.clone.transform_values(&:prototype).freeze
|
464
|
+
@cycle = cycle_all_series
|
465
|
+
|
466
|
+
_restart false
|
467
|
+
|
468
|
+
mark_as_prototype!
|
469
|
+
end
|
470
|
+
|
471
|
+
def _prototype
|
472
|
+
@sources = @sources.clone.transform_values(&:prototype).freeze
|
473
|
+
end
|
474
|
+
|
475
|
+
def _instance
|
476
|
+
@sources = @sources.clone.transform_values(&:instance)
|
477
|
+
end
|
478
|
+
|
479
|
+
def _restart(restart_sources = true)
|
480
|
+
@have_current = false
|
481
|
+
@value = nil
|
482
|
+
|
483
|
+
if restart_sources
|
484
|
+
@sources.each do |_key, serie|
|
485
|
+
serie.restart
|
486
|
+
end
|
487
|
+
end
|
488
|
+
end
|
489
|
+
|
490
|
+
def _soft_restart
|
491
|
+
@sources.each do |_key, serie|
|
492
|
+
serie.restart if serie.current_value.nil?
|
493
|
+
end
|
494
|
+
end
|
495
|
+
|
496
|
+
def _next_value
|
497
|
+
unless @have_current && @value.nil?
|
498
|
+
pre_value = @sources.collect { |key, serie| [key, serie.peek_next_value] }.to_h
|
499
|
+
|
500
|
+
nils = 0
|
501
|
+
pre_value.each do |key, value|
|
502
|
+
if value.nil?
|
503
|
+
@sources[key].next_value
|
504
|
+
nils += 1
|
505
|
+
end
|
506
|
+
end
|
507
|
+
|
508
|
+
if nils.zero?
|
509
|
+
@value = @sources.collect { |key, serie| [key, serie.next_value] }.to_h
|
510
|
+
|
511
|
+
elsif nils < @sources.size && @cycle
|
512
|
+
_soft_restart
|
513
|
+
@value = next_value
|
514
|
+
|
515
|
+
else
|
516
|
+
@value = nil
|
517
|
+
end
|
518
|
+
|
519
|
+
@have_current = true
|
520
|
+
end
|
521
|
+
|
522
|
+
@value
|
523
|
+
end
|
524
|
+
end
|
525
|
+
|
526
|
+
private_constant :FromHash
|
527
|
+
|
528
|
+
class FromArrayOfSeries
|
529
|
+
include Serie
|
530
|
+
|
531
|
+
attr_reader :sources, :cycle
|
532
|
+
|
533
|
+
def initialize(series_array, cycle_all_series)
|
534
|
+
@sources = series_array.collect(&:prototype).freeze
|
535
|
+
@cycle = cycle_all_series
|
536
|
+
|
537
|
+
_restart false
|
538
|
+
|
539
|
+
mark_as_prototype!
|
540
|
+
end
|
541
|
+
|
542
|
+
def _prototype
|
543
|
+
@sources = @sources.collect(&:prototype).freeze
|
544
|
+
end
|
545
|
+
|
546
|
+
def _instance
|
547
|
+
@sources = @sources.collect(&:instance)
|
548
|
+
end
|
549
|
+
|
550
|
+
def _restart(restart_sources = true)
|
551
|
+
@have_current = false
|
552
|
+
@value = nil
|
553
|
+
|
554
|
+
if restart_sources
|
555
|
+
@sources.each do |serie|
|
556
|
+
serie.restart if serie.current_value.nil?
|
557
|
+
end
|
558
|
+
end
|
559
|
+
end
|
560
|
+
|
561
|
+
def _soft_restart
|
562
|
+
@sources.each do |serie|
|
563
|
+
serie.restart if serie.current_value.nil?
|
564
|
+
end
|
565
|
+
end
|
566
|
+
|
567
|
+
def _next_value
|
568
|
+
unless @have_current && @value.nil?
|
569
|
+
pre_value = @sources.collect(&:peek_next_value)
|
570
|
+
|
571
|
+
nils = 0
|
572
|
+
pre_value.each_index do |i|
|
573
|
+
if pre_value[i].nil?
|
574
|
+
@sources[i].next_value
|
575
|
+
nils += 1
|
576
|
+
end
|
577
|
+
end
|
578
|
+
|
579
|
+
if nils.zero?
|
580
|
+
@value = @sources.collect(&:next_value)
|
581
|
+
|
582
|
+
elsif nils < @sources.size && @cycle
|
583
|
+
_soft_restart
|
584
|
+
@value = next_value
|
585
|
+
|
586
|
+
else
|
587
|
+
@value = nil
|
588
|
+
end
|
589
|
+
|
590
|
+
@have_current = true
|
591
|
+
end
|
592
|
+
|
593
|
+
@value
|
594
|
+
end
|
595
|
+
end
|
596
|
+
|
597
|
+
private_constant :FromArrayOfSeries
|
598
|
+
|
599
|
+
class SinFunction
|
600
|
+
include Serie
|
601
|
+
|
602
|
+
attr_reader :start, :steps, :amplitude, :center
|
603
|
+
|
604
|
+
def initialize(start, steps, amplitude, center)
|
605
|
+
@start = start.to_f
|
606
|
+
|
607
|
+
@steps = steps
|
608
|
+
@amplitude = amplitude.to_f
|
609
|
+
@center = center.to_f
|
610
|
+
|
611
|
+
update
|
612
|
+
|
613
|
+
_restart
|
614
|
+
|
615
|
+
mark_as_prototype!
|
616
|
+
end
|
617
|
+
|
618
|
+
def _restart
|
619
|
+
@position = 0
|
620
|
+
end
|
621
|
+
|
622
|
+
def _next_value
|
623
|
+
value = nil
|
624
|
+
unless @position >= @steps
|
625
|
+
value = Math.sin(@offset + @step_size * @position) * (@amplitude / 2.0) + @center
|
626
|
+
@position += 1
|
627
|
+
end
|
628
|
+
value
|
629
|
+
end
|
630
|
+
|
631
|
+
def to_s
|
632
|
+
"offset: #{@offset.round(3)}rd amplitude: #{@amplitude.round(3)} center: #{@center.round(3)} length: #{@length} step_size: #{@step_size.round(6)}"
|
633
|
+
end
|
634
|
+
|
635
|
+
private
|
636
|
+
|
637
|
+
def update
|
638
|
+
y = 2 * (@start - @center) / @amplitude
|
639
|
+
warn "WARNING: value for offset calc #{y} is outside asin range" if y < -1 || y > 1
|
640
|
+
y = 1.0 if y > 1.0 # por los errores de precisión infinitesimal en el cálculo de y cuando es muy próximo a 1.0
|
641
|
+
y = -1.0 if y < -1.0
|
642
|
+
|
643
|
+
@offset = Math.asin(y)
|
644
|
+
@step_size = 2.0 * Math::PI / @steps
|
645
|
+
end
|
646
|
+
end
|
647
|
+
|
648
|
+
private_constant :SinFunction
|
649
|
+
|
650
|
+
class Fibonacci
|
651
|
+
include Serie
|
652
|
+
|
653
|
+
def initialize
|
654
|
+
_restart
|
655
|
+
|
656
|
+
mark_as_prototype!
|
657
|
+
end
|
658
|
+
|
659
|
+
def _restart
|
660
|
+
@a = 0
|
661
|
+
@b = 1
|
662
|
+
end
|
663
|
+
|
664
|
+
def _next_value
|
665
|
+
initial_b = @b
|
666
|
+
@b = @a + @b
|
667
|
+
@a = initial_b
|
668
|
+
|
669
|
+
@a
|
670
|
+
end
|
671
|
+
|
672
|
+
def infinite?
|
673
|
+
true
|
674
|
+
end
|
675
|
+
end
|
676
|
+
|
677
|
+
private_constant :Fibonacci
|
678
|
+
|
679
|
+
class HarmonicNotes
|
680
|
+
include Serie
|
681
|
+
|
682
|
+
attr_reader :error, :extended
|
683
|
+
|
684
|
+
def initialize(error, extended)
|
685
|
+
@error = error
|
686
|
+
@extended = extended
|
687
|
+
|
688
|
+
_restart
|
689
|
+
|
690
|
+
mark_as_prototype!
|
691
|
+
end
|
692
|
+
|
693
|
+
def _restart
|
694
|
+
@harmonic = 0
|
695
|
+
end
|
696
|
+
|
697
|
+
def _next_value
|
698
|
+
begin
|
699
|
+
@harmonic += 1
|
700
|
+
|
701
|
+
candidate_note = 12 * Math::log(@harmonic, 2)
|
702
|
+
|
703
|
+
lo = candidate_note.floor
|
704
|
+
hi = candidate_note.ceil
|
705
|
+
|
706
|
+
best = (candidate_note - lo) <= (hi - candidate_note) ? lo : hi
|
707
|
+
|
708
|
+
error = candidate_note - best
|
709
|
+
|
710
|
+
end until error.abs <= @error
|
711
|
+
|
712
|
+
if @extended
|
713
|
+
{ pitch: best, error: error }
|
714
|
+
else
|
715
|
+
best
|
716
|
+
end
|
717
|
+
end
|
718
|
+
|
719
|
+
def infinite?
|
720
|
+
true
|
721
|
+
end
|
722
|
+
end
|
723
|
+
|
724
|
+
private_constant :HarmonicNotes
|
725
|
+
end
|
726
|
+
end
|