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.
Files changed (72) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +10 -0
  3. data/Gemfile +20 -0
  4. data/LICENSE.md +157 -0
  5. data/README.md +8 -0
  6. data/lib/musa-dsl/core-ext/array-apply-get.rb +18 -0
  7. data/lib/musa-dsl/core-ext/array-explode-ranges.rb +29 -0
  8. data/lib/musa-dsl/core-ext/array-to-neumas.rb +28 -0
  9. data/lib/musa-dsl/core-ext/array-to-serie.rb +20 -0
  10. data/lib/musa-dsl/core-ext/arrayfy.rb +15 -0
  11. data/lib/musa-dsl/core-ext/as-context-run.rb +44 -0
  12. data/lib/musa-dsl/core-ext/duplicate.rb +134 -0
  13. data/lib/musa-dsl/core-ext/dynamic-proxy.rb +55 -0
  14. data/lib/musa-dsl/core-ext/inspect-nice.rb +28 -0
  15. data/lib/musa-dsl/core-ext/key-parameters-procedure-binder.rb +85 -0
  16. data/lib/musa-dsl/core-ext/proc-nice.rb +13 -0
  17. data/lib/musa-dsl/core-ext/send-nice.rb +21 -0
  18. data/lib/musa-dsl/core-ext/string-to-neumas.rb +27 -0
  19. data/lib/musa-dsl/core-ext.rb +13 -0
  20. data/lib/musa-dsl/datasets/gdv-decorators.rb +221 -0
  21. data/lib/musa-dsl/datasets/gdv.rb +499 -0
  22. data/lib/musa-dsl/datasets/pdv.rb +44 -0
  23. data/lib/musa-dsl/datasets.rb +5 -0
  24. data/lib/musa-dsl/generative/darwin.rb +145 -0
  25. data/lib/musa-dsl/generative/generative-grammar.rb +294 -0
  26. data/lib/musa-dsl/generative/markov.rb +78 -0
  27. data/lib/musa-dsl/generative/rules.rb +282 -0
  28. data/lib/musa-dsl/generative/variatio.rb +331 -0
  29. data/lib/musa-dsl/generative.rb +5 -0
  30. data/lib/musa-dsl/midi/midi-recorder.rb +83 -0
  31. data/lib/musa-dsl/midi/midi-voices.rb +274 -0
  32. data/lib/musa-dsl/midi.rb +2 -0
  33. data/lib/musa-dsl/music/chord-definition.rb +99 -0
  34. data/lib/musa-dsl/music/chord-definitions.rb +13 -0
  35. data/lib/musa-dsl/music/chords.rb +326 -0
  36. data/lib/musa-dsl/music/equally-tempered-12-tone-scale-system.rb +204 -0
  37. data/lib/musa-dsl/music/scales.rb +584 -0
  38. data/lib/musa-dsl/music.rb +6 -0
  39. data/lib/musa-dsl/neuma/neuma.rb +181 -0
  40. data/lib/musa-dsl/neuma.rb +1 -0
  41. data/lib/musa-dsl/neumalang/neumalang.citrus +294 -0
  42. data/lib/musa-dsl/neumalang/neumalang.rb +179 -0
  43. data/lib/musa-dsl/neumalang.rb +3 -0
  44. data/lib/musa-dsl/repl/repl.rb +143 -0
  45. data/lib/musa-dsl/repl.rb +1 -0
  46. data/lib/musa-dsl/sequencer/base-sequencer-implementation-control.rb +189 -0
  47. data/lib/musa-dsl/sequencer/base-sequencer-implementation-play-helper.rb +354 -0
  48. data/lib/musa-dsl/sequencer/base-sequencer-implementation.rb +382 -0
  49. data/lib/musa-dsl/sequencer/base-sequencer-public.rb +261 -0
  50. data/lib/musa-dsl/sequencer/sequencer-dsl.rb +94 -0
  51. data/lib/musa-dsl/sequencer/sequencer.rb +3 -0
  52. data/lib/musa-dsl/sequencer.rb +1 -0
  53. data/lib/musa-dsl/series/base-series.rb +245 -0
  54. data/lib/musa-dsl/series/hash-serie-splitter.rb +194 -0
  55. data/lib/musa-dsl/series/holder-serie.rb +87 -0
  56. data/lib/musa-dsl/series/main-serie-constructors.rb +726 -0
  57. data/lib/musa-dsl/series/main-serie-operations.rb +1151 -0
  58. data/lib/musa-dsl/series/proxy-serie.rb +69 -0
  59. data/lib/musa-dsl/series/queue-serie.rb +94 -0
  60. data/lib/musa-dsl/series/series.rb +8 -0
  61. data/lib/musa-dsl/series.rb +1 -0
  62. data/lib/musa-dsl/transport/clock.rb +36 -0
  63. data/lib/musa-dsl/transport/dummy-clock.rb +47 -0
  64. data/lib/musa-dsl/transport/external-tick-clock.rb +31 -0
  65. data/lib/musa-dsl/transport/input-midi-clock.rb +124 -0
  66. data/lib/musa-dsl/transport/timer-clock.rb +102 -0
  67. data/lib/musa-dsl/transport/timer.rb +40 -0
  68. data/lib/musa-dsl/transport/transport.rb +137 -0
  69. data/lib/musa-dsl/transport.rb +9 -0
  70. data/lib/musa-dsl.rb +17 -0
  71. data/musa-dsl.gemspec +17 -0
  72. 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