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,94 @@
1
+ require 'forwardable'
2
+
3
+ class Musa::Sequencer
4
+ extend Forwardable
5
+
6
+ def_delegators :@sequencer, :raw_at, :tick, :on_debug_at, :on_block_error
7
+ def_delegators :@sequencer, :on_fast_forward, :ticks_per_bar, :round, :position=, :size, :event_handler, :empty?
8
+
9
+ def_delegators :@context, :position, :log
10
+ def_delegators :@context, :with, :now, :at, :wait, :play, :every, :move
11
+ def_delegators :@context, :everying, :playing, :moving
12
+ def_delegators :@context, :launch, :on
13
+
14
+ def initialize(beats_per_bar, ticks_per_beat, sequencer: nil, do_log: nil, &block)
15
+ @sequencer ||= Musa::BaseSequencer.new beats_per_bar, ticks_per_beat, do_log: do_log
16
+ @context = DSLContext.new @sequencer
17
+
18
+ with &block if block
19
+ end
20
+
21
+ def reset
22
+ @sequencer.reset
23
+ end
24
+
25
+ class DSLContext
26
+ extend Forwardable
27
+
28
+ attr_reader :sequencer
29
+
30
+ def_delegators :@sequencer, :launch, :on,
31
+ :position, :everying, :playing, :moving,
32
+ :ticks_per_bar, :round, :log, :inspect
33
+
34
+ def initialize(sequencer)
35
+ @sequencer = sequencer
36
+ end
37
+
38
+ def with(*value_parameters, **key_parameters, &block)
39
+ block ||= proc {}
40
+
41
+ _as_context_run block, value_parameters, key_parameters
42
+ end
43
+
44
+ def now(*value_parameters, **key_parameters, &block)
45
+ block ||= proc {}
46
+
47
+ @sequencer.now *value_parameters, **key_parameters do |*value_args, **key_args|
48
+ _as_context_run block, value_args, key_args
49
+ end
50
+ end
51
+
52
+ def at(*value_parameters, **key_parameters, &block)
53
+ block ||= proc {}
54
+
55
+ @sequencer.at *value_parameters, **key_parameters do |*value_args, **key_args|
56
+ _as_context_run block, value_args, key_args
57
+ end
58
+ end
59
+
60
+ def wait(*value_parameters, **key_parameters, &block)
61
+ block ||= proc {}
62
+
63
+ @sequencer.wait *value_parameters, **key_parameters do | *values, **key_values |
64
+ _as_context_run block, values, key_values
65
+ end
66
+ end
67
+
68
+ def play(*value_parameters, **key_parameters, &block)
69
+ block ||= proc {}
70
+
71
+ @sequencer.play *value_parameters, **key_parameters do |*value_args, **key_args|
72
+ _as_context_run block, value_args, key_args
73
+ end
74
+ end
75
+
76
+ def every(*value_parameters, **key_parameters, &block)
77
+ block ||= proc {}
78
+
79
+ @sequencer.every *value_parameters, **key_parameters do |*value_args, **key_args|
80
+ _as_context_run block, value_args, KeyParametersProcedureBinder.new(block).apply(key_args)
81
+ end
82
+ end
83
+
84
+ def move(*value_parameters, **key_parameters, &block)
85
+ block ||= proc {}
86
+
87
+ @sequencer.move *value_parameters, **key_parameters do |*value_args, **key_args|
88
+ _as_context_run block, value_args, key_args
89
+ end
90
+ end
91
+ end
92
+
93
+ private_constant :DSLContext
94
+ end
@@ -0,0 +1,3 @@
1
+ require_relative 'base-sequencer-public'
2
+ require_relative 'base-sequencer-implementation'
3
+ require_relative 'sequencer-dsl'
@@ -0,0 +1 @@
1
+ require 'musa-dsl/sequencer/sequencer'
@@ -0,0 +1,245 @@
1
+ require 'musa-dsl/core-ext/duplicate'
2
+ require 'musa-dsl/generative/generative-grammar'
3
+
4
+ module Musa
5
+ module SerieOperations end
6
+
7
+ module SeriePrototyping
8
+ def prototype?
9
+ @is_instance ? false : true
10
+ end
11
+
12
+ def instance?
13
+ @is_instance ? true : false
14
+ end
15
+
16
+ def prototype
17
+ if @is_instance
18
+ @instance_of || (@instance_of = clone.tap(&:_prototype).mark_as_prototype!)
19
+ else
20
+ self
21
+ end
22
+ end
23
+
24
+ def _prototype
25
+ nil
26
+ end
27
+
28
+ alias_method :p, :prototype
29
+
30
+ def mark_as_prototype!
31
+ @is_instance = nil
32
+ freeze
33
+ end
34
+
35
+ protected :_prototype, :mark_as_prototype!
36
+
37
+ def mark_regarding!(source)
38
+ if source.prototype?
39
+ mark_as_prototype!
40
+ else
41
+ mark_as_instance!
42
+ end
43
+ end
44
+
45
+ protected :mark_regarding!
46
+
47
+ def instance
48
+ if @is_instance
49
+ self
50
+ else
51
+ clone(freeze: false).tap(&:_instance).mark_as_instance!(self)
52
+ end
53
+ end
54
+
55
+ alias_method :i, :instance
56
+
57
+ def _instance
58
+ nil
59
+ end
60
+
61
+ def mark_as_instance!(prototype = nil)
62
+ @instance_of = prototype
63
+ @is_instance = true
64
+ self
65
+ end
66
+
67
+ protected :_instance, :mark_as_instance!
68
+
69
+ class PrototypingSerieError < RuntimeError
70
+ def initialize(message = nil)
71
+ message ||= 'This serie is a prototype serie: cannot be consumed. To consume the serie use an instance serie via .instance method'
72
+ super message
73
+ end
74
+ end
75
+ end
76
+
77
+ module Serie
78
+ include SeriePrototyping
79
+ include SerieOperations
80
+
81
+ def restart
82
+ raise PrototypingSerieError unless @is_instance
83
+
84
+ @_have_peeked_next_value = false
85
+ @_peeked_next_value = nil
86
+ @_have_current_value = false
87
+ @_current_value = nil
88
+
89
+ _restart if respond_to? :_restart
90
+
91
+ self
92
+ end
93
+
94
+ def next_value
95
+ raise PrototypingSerieError unless @is_instance
96
+
97
+ unless @_have_current_value && @_current_value.nil?
98
+ if @_have_peeked_next_value
99
+ @_have_peeked_next_value = false
100
+ @_current_value = @_peeked_next_value
101
+ else
102
+ @_current_value = _next_value
103
+ end
104
+ end
105
+
106
+ propagate_value @_current_value
107
+
108
+ @_current_value
109
+ end
110
+
111
+ alias_method :v, :next_value
112
+
113
+ def peek_next_value
114
+ raise PrototypingSerieError unless @is_instance
115
+
116
+ unless @_have_peeked_next_value
117
+ @_have_peeked_next_value = true
118
+ @_peeked_next_value = _next_value
119
+ end
120
+
121
+ @_peeked_next_value
122
+ end
123
+
124
+ def current_value
125
+ raise PrototypingSerieError unless @is_instance
126
+
127
+ @_current_value
128
+ end
129
+
130
+ def infinite?
131
+ false
132
+ end
133
+
134
+ def to_a(recursive: nil, duplicate: nil, restart: nil, dr: nil)
135
+ recursive ||= false
136
+
137
+ dr ||= instance?
138
+
139
+ duplicate = dr if duplicate.nil?
140
+ restart = dr if restart.nil?
141
+
142
+ raise 'Cannot convert to array an infinite serie' if infinite?
143
+
144
+ array = []
145
+
146
+ serie = instance
147
+
148
+ serie = serie.duplicate if duplicate
149
+ serie = serie.restart if restart
150
+
151
+ while value = serie.next_value
152
+ array << if recursive
153
+ process_for_to_a(value)
154
+ else
155
+ value
156
+ end
157
+ end
158
+
159
+ array
160
+ end
161
+
162
+ alias_method :a, :to_a
163
+
164
+ def to_node(**attributes)
165
+ Nodificator.to_node(self, **attributes)
166
+ end
167
+
168
+ alias_method :node, :to_node
169
+
170
+ class Nodificator
171
+ extend Musa::GenerativeGrammar
172
+
173
+ def self.to_node(serie, **attributes)
174
+ N(serie, **attributes)
175
+ end
176
+ end
177
+
178
+ private_constant :Nodificator
179
+
180
+ protected
181
+
182
+ def propagate_value(value)
183
+ @_slaves.each { |s| s.push_next_value value } if @_slaves
184
+ end
185
+
186
+ private
187
+
188
+ def process_for_to_a(value)
189
+ case value
190
+ when Serie
191
+ value.to_a(recursive: true, restart: false, duplicate: false)
192
+ when Array
193
+ a = value.clone
194
+ a.collect! { |v| v.is_a?(Serie) ? v.to_a(recursive: true, restart: false, duplicate: false) : process_for_to_a(v) }
195
+ when Hash
196
+ h = value.clone
197
+ h.transform_values! { |v| v.is_a?(Serie) ? v.to_a(recursive: true, restart: false, duplicate: false) : process_for_to_a(v) }
198
+ else
199
+ value
200
+ end
201
+ end
202
+
203
+ end
204
+
205
+ class Slave
206
+ include Serie
207
+
208
+ attr_reader :master
209
+
210
+ def initialize(master)
211
+ @master = master
212
+ @next_value = []
213
+ end
214
+
215
+ def _restart
216
+ throw OperationNotAllowedError, "SlaveSerie #{self}: slave series cannot be restarted"
217
+ end
218
+
219
+ def next_value
220
+ value = @next_value.shift
221
+
222
+ raise "Warning: slave serie #{self} has lost sync with his master serie #{@master}" if value.nil? && !@master.peek_next_value.nil?
223
+
224
+ propagate_value value
225
+
226
+ value
227
+ end
228
+
229
+ def peek_next_value
230
+ value = @next_value.first
231
+
232
+ raise "Warning: slave serie #{self} has lost sync with his master serie #{@master}" if value.nil? && !@master.peek_next_value.nil?
233
+
234
+ value
235
+ end
236
+
237
+ def infinite?
238
+ @master.infinite?
239
+ end
240
+
241
+ def push_next_value(value)
242
+ @next_value << value
243
+ end
244
+ end
245
+ end
@@ -0,0 +1,194 @@
1
+ module Musa
2
+ # TODO: adapt to series prototyping
3
+ # TODO: full test cases
4
+
5
+ module SerieOperations
6
+ def split(buffered: nil, master: nil)
7
+ buffered ||= false
8
+
9
+ return HashSplitter.new HashSplitter::KeyProxy.new(self) if master.nil? && !buffered
10
+ return HashSplitter.new HashSplitter::MasterSlaveKeyProxy.new(self, master) if !master.nil? && !buffered
11
+ return HashSplitter.new HashSplitter::BufferedKeyProxy.new(self) if buffered
12
+ end
13
+
14
+ class HashSplitter
15
+ def initialize(proxy)
16
+ @proxy = proxy
17
+ @series = {}
18
+ end
19
+
20
+ def [](key)
21
+ serie = if @series.key? key
22
+ @series[key]
23
+ else
24
+ @series[key] = Splitted.new(@proxy, key: key)
25
+ end
26
+ end
27
+
28
+ class KeyProxy
29
+ def initialize(hash_serie)
30
+ @serie = hash_serie.instance
31
+ @values = {}
32
+ end
33
+
34
+ def restart
35
+ @serie.restart
36
+ @values = {}
37
+ end
38
+
39
+ def next_value(key)
40
+ return nil unless @values
41
+
42
+ value = @values[key]
43
+
44
+ if value.nil?
45
+ before_values = @values.collect { |k, v| [k, v] unless v.nil? }.compact.to_h
46
+
47
+ @values = @serie.next_value
48
+ value = @values[key] if @values
49
+
50
+ warn "Warning: splitted serie #{@serie} values #{before_values} are being lost" if !value.nil? && !before_values.empty?
51
+ end
52
+
53
+ @values[key] = nil if @values
54
+
55
+ value
56
+ end
57
+
58
+ def peek_next_value(key)
59
+ value = @values[key]
60
+
61
+ if value.nil?
62
+ peek_values = @serie.peek_next_value
63
+ value = peek_values[key] if peek_values
64
+ end
65
+
66
+ value
67
+ end
68
+ end
69
+
70
+ class BufferedKeyProxy
71
+ def initialize(hash_serie)
72
+ @serie = hash_serie.instance
73
+ @values = {}
74
+ end
75
+
76
+ def restart
77
+ @serie.restart
78
+ @values = {}
79
+ end
80
+
81
+ def next_value(key)
82
+ value = nil
83
+
84
+ if @values[key].nil? || @values[key].empty?
85
+ hash_value = @serie.next_value
86
+
87
+ if hash_value
88
+ hash_value.each do |k, v|
89
+ @values[k] = [] if @values[k].nil?
90
+ @values[k] << v
91
+ end
92
+ end
93
+ end
94
+
95
+ value = @values[key].shift if @values[key]
96
+
97
+ value
98
+ end
99
+
100
+ def peek_next_value(key)
101
+ value = nil
102
+
103
+ if @values[key] && !@values[key].empty?
104
+ value = @values[key].first
105
+ else
106
+ peek_values = @serie.peek_next_value
107
+ value = peek_values[key] if peek_values
108
+ end
109
+
110
+ value
111
+ end
112
+ end
113
+
114
+ class MasterSlaveKeyProxy
115
+ def initialize(hash_serie, master)
116
+ @serie = hash_serie.instance
117
+ @master = master
118
+ @values = {}
119
+ @values_counter = {}
120
+ end
121
+
122
+ def restart
123
+ @serie.restart
124
+ @values = {}
125
+ @values_counter = {}
126
+ end
127
+
128
+ def next_value(key)
129
+ return nil unless @values
130
+
131
+ value = @values[key]
132
+
133
+ if value.nil?
134
+ @values = @serie.next_value
135
+
136
+ value = @values[key] if @values
137
+
138
+ # warn "Info: splitted serie #{@serie} use count on next_value: #{@values_counter}"
139
+ @values_counter = {}
140
+ end
141
+
142
+ @values_counter[key] ||= 0
143
+ @values_counter[key] += 1
144
+
145
+ @values[key] = nil if key == @master && @values
146
+
147
+ value
148
+ end
149
+
150
+ def peek_next_value(key)
151
+ return nil unless @values
152
+
153
+ value = @values[key]
154
+
155
+ if value.nil?
156
+ peek_values = @serie.peek_next_value
157
+ value = peek_values[key] if peek_values
158
+ end
159
+
160
+ value
161
+ end
162
+ end
163
+
164
+ class Splitted
165
+ include Serie
166
+
167
+ def initialize(proxy, key:)
168
+ @proxy = proxy
169
+ @key = key
170
+
171
+ mark_as_instance!
172
+ end
173
+
174
+ def _prototype
175
+ raise PrototypingSerieError, 'Cannot get prototype of a splitted serie'
176
+ end
177
+
178
+ def _restart
179
+ @proxy.restart
180
+ end
181
+
182
+ def next_value
183
+ @proxy.next_value(@key)
184
+ end
185
+
186
+ def peek_next_value
187
+ @proxy.peek_next_value(@key)
188
+ end
189
+ end
190
+ end
191
+
192
+ private_constant :HashSplitter
193
+ end
194
+ end
@@ -0,0 +1,87 @@
1
+ module Musa
2
+ module Series
3
+ # TODO: adapt to series prototyping
4
+
5
+ def HOLDER(serie = nil)
6
+ Holder.new(serie)
7
+ end
8
+
9
+ class Holder
10
+ include Serie
11
+
12
+ attr_reader :hold, :next
13
+
14
+ def initialize(serie)
15
+ @hold = serie.instance if serie
16
+ @next = []
17
+
18
+ mark_as_instance!
19
+ end
20
+
21
+ def hold=(serie)
22
+ @hold = serie.instance
23
+ end
24
+
25
+ def <<(serie)
26
+ if @hold.nil?
27
+ @hold = serie.instance
28
+ else
29
+ @next << serie.instance
30
+ end
31
+
32
+ self
33
+ end
34
+
35
+ def _prototype
36
+ raise PrototypingSerieError, 'Cannot get prototype of a proxy serie'
37
+ end
38
+
39
+ def restart
40
+ if @next.empty? && @hold
41
+ @hold.restart
42
+ else
43
+ @hold = @next.shift
44
+ end
45
+
46
+ self
47
+ end
48
+
49
+ def current_value
50
+ @hold.current_value if @hold
51
+ end
52
+
53
+ def next_value
54
+ @hold.next_value if @hold
55
+ end
56
+
57
+ def peek_next_value
58
+ @hold.peek_next_value if @hold
59
+ end
60
+
61
+ def infinite?
62
+ @hold.infinite? if @hold
63
+ end
64
+
65
+ private
66
+
67
+ def method_missing(method_name, *args, **key_args, &block)
68
+ if @hold && @hold.respond_to?(method_name)
69
+ @hold.send_nice method_name, *args, **key_args, &block
70
+ else
71
+ super
72
+ end
73
+ end
74
+
75
+ def respond_to_missing?(method_name, include_private)
76
+ @hold && @hold.respond_to?(method_name, include_private) || super
77
+ end
78
+ end
79
+ end
80
+
81
+ module SerieOperations
82
+ # TODO add test case
83
+ def hold
84
+ Series::Holder.new self
85
+ end
86
+ end
87
+ end