musa-dsl 0.22.2 → 0.23.0

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 (42) 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 +41 -16
  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/matrix/matrix.rb +9 -7
  16. data/lib/musa-dsl/midi/midi-voices.rb +1 -0
  17. data/lib/musa-dsl/music/scales.rb +1 -1
  18. data/lib/musa-dsl/neumalang/neumalang.rb +1 -1
  19. data/lib/musa-dsl/neumas/array-to-neumas.rb +1 -1
  20. data/lib/musa-dsl/sequencer/base-sequencer-implementation-play-helper.rb +9 -4
  21. data/lib/musa-dsl/sequencer/base-sequencer-implementation-play-timed.rb +30 -129
  22. data/lib/musa-dsl/sequencer/base-sequencer-implementation.rb +10 -24
  23. data/lib/musa-dsl/sequencer/base-sequencer-tick-based.rb +9 -9
  24. data/lib/musa-dsl/sequencer/base-sequencer-tickless-based.rb +3 -5
  25. data/lib/musa-dsl/sequencer/{base-sequencer-public.rb → base-sequencer.rb} +15 -23
  26. data/lib/musa-dsl/sequencer/sequencer-dsl.rb +9 -7
  27. data/lib/musa-dsl/sequencer/sequencer.rb +8 -1
  28. data/lib/musa-dsl/series/base-series.rb +293 -144
  29. data/lib/musa-dsl/series/buffer-serie.rb +237 -0
  30. data/lib/musa-dsl/series/hash-or-array-serie-splitter.rb +139 -60
  31. data/lib/musa-dsl/series/main-serie-constructors.rb +254 -165
  32. data/lib/musa-dsl/series/main-serie-operations.rb +308 -303
  33. data/lib/musa-dsl/series/proxy-serie.rb +21 -41
  34. data/lib/musa-dsl/series/quantizer-serie.rb +44 -46
  35. data/lib/musa-dsl/series/queue-serie.rb +39 -43
  36. data/lib/musa-dsl/series/series-composer.rb +149 -0
  37. data/lib/musa-dsl/series/series.rb +6 -2
  38. data/lib/musa-dsl/series/timed-serie.rb +343 -0
  39. data/musa-dsl.gemspec +13 -3
  40. metadata +11 -11
  41. data/lib/musa-dsl/series/flattener-timed-serie.rb +0 -61
  42. data/lib/musa-dsl/series/holder-serie.rb +0 -87
@@ -3,13 +3,8 @@ require_relative '../core-ext/with'
3
3
 
4
4
  using Musa::Extension::Arrayfy
5
5
 
6
- # incluir With -> hecho
7
- # eliminar method_missing
8
- # crear rama tb debe recibir la serie de la history -> ya lo hace
9
- # crear rama puede repetirse (hasta terminar según ended_when) -> no
10
- #
11
- # hacer que pueda funcionar en tiempo real? le vas suministrando seeds y le vas diciendo qué opción has elegido (p.ej. para hacer un armonizador en tiempo real)
12
- # esto mismo sería aplicable en otros generadores? variatio/darwin? generative-grammar? markov?
6
+ # TODO hacer que pueda funcionar en tiempo real? le vas suministrando seeds y le vas diciendo qué opción has elegido (p.ej. para hacer un armonizador en tiempo real)
7
+ # TODO esto mismo sería aplicable en otros generadores? variatio/darwin? generative-grammar? markov?
13
8
 
14
9
  module Musa
15
10
  module Backboner
@@ -17,12 +12,12 @@ module Musa
17
12
  include Musa::Extension::With
18
13
 
19
14
  def initialize(&block)
20
- @context = RulesEvalContext.new(&block)
15
+ @dsl = RulesEvalContext.new(&block)
21
16
  end
22
17
 
23
18
  def generate_possibilities(object, confirmed_node = nil, node = nil, grow_rules = nil)
24
19
  node ||= Node.new
25
- grow_rules ||= @context._grow_rules
20
+ grow_rules ||= @dsl._grow_rules
26
21
 
27
22
  history = confirmed_node.history if confirmed_node
28
23
  history ||= []
@@ -33,9 +28,9 @@ module Musa
33
28
  if grow_rule
34
29
  grow_rule.generate_possibilities(object, history).each do |new_object|
35
30
  new_node = Node.new new_object, node
36
- new_node.mark_as_ended! if @context._ended? new_object
31
+ new_node.mark_as_ended! if @dsl._ended? new_object
37
32
 
38
- rejection = @context._cut_rules.find { |cut_rule| cut_rule.rejects?(new_object, history) }
33
+ rejection = @dsl._cut_rules.find { |cut_rule| cut_rule.rejects?(new_object, history) }
39
34
  # TODO: include rejection secondary reasons in rejection message
40
35
 
41
36
  new_node.reject! rejection if rejection
@@ -100,9 +100,7 @@ module Musa
100
100
  options[index].to_serie.to_node
101
101
  end
102
102
 
103
- def to_serie(flatten: nil, &condition)
104
- flatten ||= true
105
-
103
+ def to_serie(flatten: true, &condition)
106
104
  serie = _options(&condition).collect { |o| o.collect(&:content) }.to_serie(of_series: true).merge
107
105
  serie = serie.flatten if flatten
108
106
 
@@ -7,9 +7,8 @@ module Musa
7
7
  module Markov
8
8
  class Markov
9
9
  include Musa::Extension::SmartProcBinder
10
- include Musa::Series::Serie
10
+ include Musa::Series::Serie.base
11
11
 
12
- attr_accessor :start, :finish, :random, :transitions
13
12
 
14
13
  def initialize(transitions:, start:, finish: nil, random: nil)
15
14
  @transitions = transitions.clone.freeze
@@ -22,23 +21,28 @@ module Musa
22
21
 
23
22
  @procedure_binders = {}
24
23
 
25
- _restart
24
+ init
26
25
  end
27
26
 
28
- def _restart
27
+ attr_accessor :start
28
+ attr_accessor :finish
29
+ attr_accessor :random
30
+ attr_accessor :transitions
31
+
32
+ private def _init
29
33
  @current = nil
30
34
  @finished = false
31
35
  @history = []
32
36
  end
33
37
 
34
- def _next_value
38
+ private def _next_value
35
39
  if @finished
36
40
  @current = nil
37
41
  else
38
42
  if @current.nil?
39
43
  @current = @start
40
44
  else
41
- if @transitions.has_key? @current
45
+ if @transitions.has_key?(@current)
42
46
  options = @transitions[@current]
43
47
 
44
48
  case options
@@ -1,7 +1,12 @@
1
1
  require 'logger'
2
2
 
3
+ require_relative '../core-ext/inspect-nice'
4
+
5
+
3
6
  module Musa; module Logger
4
7
  class Logger < ::Logger
8
+ using Musa::Extension::InspectNice
9
+
5
10
  def initialize(sequencer: nil, position_format: nil)
6
11
  super STDERR, level: WARN
7
12
 
@@ -22,7 +27,7 @@ module Musa; module Logger
22
27
 
23
28
  progname = "[#{progname}]" if progname
24
29
 
25
- "#{position}#{level}#{progname} #{msg}\n"
30
+ "#{position}#{level}#{progname}#{' ' if position || level || progname}#{msg}\n"
26
31
  else
27
32
  "\n"
28
33
  end
@@ -22,8 +22,8 @@ module Musa
22
22
  indexes
23
23
  end
24
24
 
25
- def to_p(time_dimension, keep_time: nil)
26
- condensed_matrices.collect { |m| m.to_p(time_dimension, keep_time: keep_time) }
25
+ def to_p(time_dimension:, keep_time: nil)
26
+ condensed_matrices.collect { |m| m.to_p(time_dimension: time_dimension, keep_time: keep_time) }
27
27
  end
28
28
 
29
29
  def condensed_matrices
@@ -69,14 +69,14 @@ module Musa
69
69
  refine ::Matrix do
70
70
  include Musa::Datasets
71
71
 
72
- def to_p(time_dimension, keep_time: nil)
72
+ def to_p(time_dimension:, keep_time: nil)
73
73
  decompose(self.to_a, time_dimension).collect do |points|
74
74
  line = []
75
75
 
76
76
  start_point = points[0]
77
77
  start_time = start_point[time_dimension]
78
78
 
79
- line << start_point.tap { |_| _.delete_at(time_dimension) unless keep_time; _ }.extend(Datasets::V)
79
+ line << start_point.clone.tap { |_| _.delete_at(time_dimension) unless keep_time; _ }.extend(Datasets::V)
80
80
 
81
81
  (1..points.size-1).each do |i|
82
82
  end_point = points[i]
@@ -84,7 +84,7 @@ module Musa
84
84
  end_time = end_point[time_dimension]
85
85
 
86
86
  line << end_time - start_time
87
- line << end_point.tap { |_| _.delete_at(time_dimension) unless keep_time; _ }.extend(Datasets::V)
87
+ line << end_point.clone.tap { |_| _.delete_at(time_dimension) unless keep_time; _ }.extend(Datasets::V)
88
88
 
89
89
  start_time = end_time
90
90
  end
@@ -107,8 +107,9 @@ module Musa
107
107
 
108
108
  x_dim_values_indexes.keys.sort.each do |value|
109
109
  x_dim_values_indexes[value].each do |index|
110
+ #
110
111
  # hacia un lado
111
-
112
+ #
112
113
  unless used_indexes.include?(index)
113
114
  i = index
114
115
  xx = array[i][time_dimension]
@@ -125,8 +126,9 @@ module Musa
125
126
 
126
127
  directional_segments << a if a.size > 1
127
128
 
129
+ #
128
130
  # y hacia el otro
129
-
131
+ #
130
132
  i = index
131
133
  xx = array[i][time_dimension]
132
134
 
@@ -169,6 +169,7 @@ module Musa
169
169
  private_constant :ControllersControl
170
170
 
171
171
  class NoteControl
172
+ attr_reader :voice, :pitch, :velocity, :velocity_off, :duration
172
173
  attr_reader :start_position, :end_position
173
174
 
174
175
  def initialize(voice, pitch:, velocity: nil, duration: nil, velocity_off: nil)
@@ -303,7 +303,7 @@ module Musa
303
303
 
304
304
  def [](grade_or_symbol)
305
305
 
306
- raise ArgumentError, "grade_or_symbol '#{grade_or_symbol}' should be a Numeric, String or Symbol" unless grade_or_symbol.is_a?(Symbol) || grade_or_symbol.is_a?(String) || grade_or_symbol.is_a?(Integer)
306
+ raise ArgumentError, "grade_or_symbol '#{grade_or_symbol}' should be a Integer, String or Symbol" unless grade_or_symbol.is_a?(Symbol) || grade_or_symbol.is_a?(String) || grade_or_symbol.is_a?(Integer)
307
307
 
308
308
  wide_grade, sharps = grade_of(grade_or_symbol)
309
309
 
@@ -15,7 +15,7 @@ module Musa
15
15
  include Musa::Neumas
16
16
 
17
17
  def value
18
- _SE(captures(:expression).collect(&:value), extends: Neuma::Serie)
18
+ S(*captures(:expression).collect(&:value)).extend(Neuma::Serie)
19
19
  end
20
20
  end
21
21
 
@@ -21,7 +21,7 @@ module Musa
21
21
  def convert_to_neumas(e)
22
22
  case e
23
23
  when Musa::Neumas::Neuma::Serie then e
24
- when Musa::Neumas::Neuma::Parallel then _SE([e], extends: Musa::Neumas::Neuma::Serie)
24
+ when Musa::Neumas::Neuma::Parallel then S(e).extend(Musa::Neumas::Neuma::Serie)
25
25
  when String then e.to_neumas
26
26
  else
27
27
  raise ArgumentError, "Don't know how to convert to neumas #{e}"
@@ -262,11 +262,11 @@ module Musa
262
262
 
263
263
  when Musa::Series::Serie
264
264
  { current_operation: :play,
265
- current_parameter: element.restart }
265
+ current_parameter: element.instance.restart }
266
266
 
267
267
  when Parallel
268
268
  { current_operation: :parallel_play,
269
- current_parameter: element.tap { |e| e.each(&:restart) } }
269
+ current_parameter: element.instance.tap { |e| e.each(&:restart) } }
270
270
 
271
271
  when Array
272
272
  { current_operation: :no_eval_play,
@@ -324,8 +324,13 @@ module Musa
324
324
  run_operation eval_use_variable(element[:use_variable])
325
325
 
326
326
  when :event
327
- value_parameters = element[:value_parameters] ? element[:value_parameters].collect { |e| subcontext.eval_element(e) } : []
328
- key_parameters = element[:key_parameters] ? element[:key_parameters].collect { |k, e| [k, subcontext.eval_element(e)] }.to_h : {}
327
+ value_parameters = element[:value_parameters] ?
328
+ element[:value_parameters].collect { |e| subcontext.eval_element(e) } :
329
+ []
330
+
331
+ key_parameters = element[:key_parameters] ?
332
+ element[:key_parameters].collect { |k, e| [k, subcontext.eval_element(e)] }.to_h :
333
+ {}
329
334
 
330
335
  { current_operation: :event,
331
336
  current_event: element[:event],
@@ -7,181 +7,82 @@ module Musa; module Sequencer
7
7
  class BaseSequencer
8
8
  private def _play_timed(timed_serie,
9
9
  control,
10
- reference: nil,
11
- step: nil,
12
- right_open: nil,
13
10
  &block)
14
11
 
15
- reference ||= 0r
16
- step ||= 1r
17
-
18
12
  if first_value_sample = timed_serie.peek_next_value
19
-
20
13
  debug "_play_timed: first_value_sample #{first_value_sample}"
21
14
 
22
15
  hash_mode = first_value_sample[:value].is_a?(Hash)
23
16
 
24
17
  if hash_mode
25
- components = first_value_sample[:value].keys
26
-
27
- reference = reference.hashify(keys: components)
28
- step = step.hashify(keys: components)
29
- right_open = right_open.hashify(keys:components)
18
+ component_ids = first_value_sample[:value].keys
30
19
  else
31
20
  size = first_value_sample[:value].size
32
- components = (0 .. size-1).to_a
33
-
34
- reference = reference.arrayfy(size: size)
35
- step = step.arrayfy(size: size)
36
- right_open = right_open.arrayfy(size: size)
37
- end
38
-
39
- split = timed_serie.flatten_timed.split
40
- quantized_series = hash_mode ? {} : []
41
-
42
- components.each do |component|
43
- quantized_series[component] =
44
- QUANTIZE(split[component],
45
- reference: reference[component],
46
- step: step[component],
47
- right_open: right_open[component],
48
- stops: true).instance
21
+ component_ids = (0 .. size-1).to_a
49
22
  end
23
+ extra_attribute_names = Set[*(first_value_sample.keys - [:time, :value])]
50
24
 
51
25
  last_positions = hash_mode ? {} : []
52
26
  end
53
27
 
54
28
  binder = SmartProcBinder.new(block)
55
29
 
56
- _play_timed_step(hash_mode, components, quantized_series, position, last_positions, binder, control)
30
+ _play_timed_step(hash_mode, component_ids, extra_attribute_names, timed_serie,
31
+ position, last_positions, binder, control)
57
32
  end
58
33
 
59
-
60
- private def _play_timed_step(hash_mode, components, quantized_series, start_position, last_positions,
34
+ private def _play_timed_step(hash_mode,
35
+ component_ids, extra_attribute_names,
36
+ timed_serie,
37
+ start_position,
38
+ last_positions,
61
39
  binder, control)
62
40
 
63
- affected_components_by_time = {}
64
-
65
- components.each do |component|
66
- if v = quantized_series[component].peek_next_value
41
+ source_next_value = timed_serie.next_value
67
42
 
68
- debug "_play_timed_step: quantized_series[#{component}].peek_next_value #{v}"
69
- time = v[:time]
70
-
71
- affected_components_by_time[time] ||= []
72
- affected_components_by_time[time] << component
73
- end
74
- end
43
+ affected_components = component_ids.select { |_| !source_next_value[:value][_].nil? } if source_next_value
75
44
 
76
- if affected_components_by_time.any?
77
- time = affected_components_by_time.keys.sort.first
45
+ if affected_components && affected_components.any?
46
+ time = source_next_value[:time]
78
47
 
79
48
  values = hash_mode ? {} : []
80
- next_values = hash_mode ? {} : []
81
- durations = hash_mode ? {} : []
82
- q_durations = hash_mode ? {} : []
49
+ extra_attributes = extra_attribute_names.collect { |_| [_, hash_mode ? {} : []] }.to_h
83
50
  started_ago = hash_mode ? {} : []
84
51
 
85
- affected_components_by_time[time].each do |component|
86
- value = quantized_series[component].next_value
87
-
88
- values[component] = value[:value]
89
- durations[component] = value[:duration]
90
-
91
- q_durations[component] =
92
- _quantize_position(time + durations[component], warn: false) -
93
- _quantize_position(time, warn: false)
52
+ affected_components.each do |component|
53
+ values[component] = source_next_value[:value][component]
94
54
 
95
- nv = quantized_series[component].peek_next_value
96
- next_values[component] = (nv && nv[:value] != values[component]) ? nv[:value] : nil
55
+ extra_attribute_names.each do |attribute_name|
56
+ extra_attributes[attribute_name][component] = source_next_value[attribute_name][component]
57
+ end
97
58
 
98
59
  last_positions[component] = _quantize_position(time, warn: false)
99
60
  end
100
61
 
101
- components.each do |component|
62
+ component_ids.each do |component|
102
63
  if last_positions[component] && last_positions[component] != time
103
64
  sa = _quantize_position(time, warn: false) - last_positions[component]
104
65
  started_ago[component] = (sa == 0) ? nil : sa
105
66
  end
106
67
  end
107
68
 
108
- _numeric_at start_position + _quantize_position(time, warn: false), control do
109
- debug "_play_timed_step: before binder.call: durations #{durations} q_durations #{q_durations}"
110
- binder.call(values, next_values,
111
- duration: durations,
112
- quantized_duration: q_durations,
69
+ _numeric_at _quantize_position(start_position + time, warn: true), control do
70
+ binder.call(values,
71
+ **extra_attributes,
72
+ time: start_position + time,
113
73
  started_ago: started_ago,
114
74
  control: control)
115
75
 
116
- _play_timed_step(hash_mode, components, quantized_series, start_position, last_positions,
76
+ _play_timed_step(hash_mode,
77
+ component_ids, extra_attribute_names,
78
+ timed_serie,
79
+ start_position,
80
+ last_positions,
117
81
  binder, control)
118
82
  end
119
83
  end
120
84
  end
121
85
 
122
- # TODO implement this alternative play method as another mode
123
- # Este es un modo muy interesante pero que implica un procesamiento diferente en el yield_block que no me
124
- # sirve para el código de samples/multidim_sample, puesto que en este el next_values es literal,
125
- # mientras que samples/multidim_sample necesita que el next_value sea nil si el valor no cambia durante el periodo.
126
- #
127
- private def _play_timed_step_b(hash_mode, components, quantized_series, start_position, last_positions,
128
- binder, control)
129
-
130
- affected_components_by_time = {}
131
-
132
- components.each do |component|
133
- if v = quantized_series[component].peek_next_value
134
- time = v[:time]
135
-
136
- affected_components_by_time[time] ||= []
137
- affected_components_by_time[time] << component
138
- end
139
- end
140
-
141
- if !affected_components_by_time.empty?
142
- time = affected_components_by_time.keys.sort.first
143
-
144
- values = hash_mode ? {} : []
145
- next_values = hash_mode ? {} : []
146
- durations = hash_mode ? {} : []
147
- q_durations = hash_mode ? {} : []
148
- started_ago = hash_mode ? {} : []
149
-
150
- affected_components_by_time[time].each do |component|
151
- value = quantized_series[component].next_value
152
-
153
- values[component] = value[:value]
154
- durations[component] = value[:duration]
155
-
156
- q_durations[component] =
157
- _quantize_position(time + durations[component], warn: false) -
158
- _quantize_position(time, warn: false)
159
-
160
- last_positions[component] = _quantize_position(time, warn: false)
161
- end
162
-
163
- components.each do |component|
164
- nv = quantized_series[component].peek_next_value
165
- next_values[component] = nv[:value] if nv
166
-
167
- if last_positions[component] && last_positions[component] != time
168
- started_ago[component] = _quantize_position(time, warn: false) - last_positions[component]
169
- end
170
- end
171
-
172
- _numeric_at start_position + _quantize_position(time, warn: false), control do
173
- binder.call(values, next_values,
174
- duration: durations,
175
- quantized_duration: q_durations,
176
- started_ago: started_ago,
177
- control: control)
178
-
179
- _play_timed_step_b(hash_mode, components, quantized_series, start_position, last_positions,
180
- binder, control)
181
- end
182
- end
183
- end
184
-
185
86
  class PlayTimedControl < EventHandler
186
87
  attr_reader :do_on_stop, :do_after
187
88