musa-dsl 0.14.16

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