musa-dsl 0.22.1 → 0.22.6

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 (29) hide show
  1. checksums.yaml +4 -4
  2. data/lib/musa-dsl.rb +1 -1
  3. data/lib/musa-dsl/core-ext/inspect-nice.rb +1 -2
  4. data/lib/musa-dsl/datasets/p.rb +36 -15
  5. data/lib/musa-dsl/datasets/score/to-mxml/process-pdv.rb +14 -12
  6. data/lib/musa-dsl/datasets/score/to-mxml/process-ps.rb +32 -6
  7. data/lib/musa-dsl/datasets/score/to-mxml/to-mxml.rb +24 -10
  8. data/lib/musa-dsl/logger/logger.rb +6 -1
  9. data/lib/musa-dsl/matrix/matrix.rb +9 -7
  10. data/lib/musa-dsl/midi/midi-voices.rb +1 -0
  11. data/lib/musa-dsl/music/scales.rb +1 -1
  12. data/lib/musa-dsl/sequencer/base-sequencer-implementation-play-helper.rb +7 -2
  13. data/lib/musa-dsl/sequencer/base-sequencer-implementation-play-timed.rb +30 -129
  14. data/lib/musa-dsl/sequencer/base-sequencer-implementation.rb +10 -24
  15. data/lib/musa-dsl/sequencer/base-sequencer-tick-based.rb +9 -9
  16. data/lib/musa-dsl/sequencer/base-sequencer-tickless-based.rb +3 -5
  17. data/lib/musa-dsl/sequencer/{base-sequencer-public.rb → base-sequencer.rb} +15 -23
  18. data/lib/musa-dsl/sequencer/sequencer-dsl.rb +7 -4
  19. data/lib/musa-dsl/sequencer/sequencer.rb +8 -1
  20. data/lib/musa-dsl/series/base-series.rb +3 -3
  21. data/lib/musa-dsl/series/hash-or-array-serie-splitter.rb +90 -10
  22. data/lib/musa-dsl/series/main-serie-constructors.rb +8 -12
  23. data/lib/musa-dsl/series/main-serie-operations.rb +45 -5
  24. data/lib/musa-dsl/series/quantizer-serie.rb +25 -15
  25. data/lib/musa-dsl/series/series.rb +1 -1
  26. data/lib/musa-dsl/series/timed-serie.rb +356 -0
  27. data/musa-dsl.gemspec +3 -3
  28. metadata +6 -6
  29. data/lib/musa-dsl/series/flattener-timed-serie.rb +0 -61
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4498538210551ab83a9f167c0e9d8656c9c5b70c9bc51f97e99e540109e5de7e
4
- data.tar.gz: 9957a89a6db2ed2a4e0d75900f2eb3e1051c6dfc3fcc25c40ed5da1ba8fb6957
3
+ metadata.gz: e85f0a7bc9ddbb82ea9b6b36741a87c1dc04f2feb1c10ea0f5fcb92e4dfc7a37
4
+ data.tar.gz: 13ad3537ac0a2e03c07c589174a12a8dd9af5013be79f5bd1ee769820cd94347
5
5
  SHA512:
6
- metadata.gz: 6c2bbea949c5c22dba0247a6f2ce050f515383ddf23aedf1c0b5755d8d94ddf355ebc2beedee3b6c03aea758da905d393db4fd559f26bb52a667bc9f82cf023e
7
- data.tar.gz: da8bf0de7ba0cc96d5e96188293b901135bd4f052218ead671783620cf294c40eed37f89a46220d2eefd32f3cc1e03634c392783efac9164e725635e70b0e1c4
6
+ metadata.gz: 06f58c414bbbd873179850c378f3022e1bc40eba16325b787824e1cb88b27229c7ac19d08032c8b0385c792ae38324c982970dcc94c91e7fd3d924208b640aa4
7
+ data.tar.gz: 63398fc18d40799119742df1587735f9736abec4a0c1d97e9a9b29202395b6f4223cea7c01075e95d6f0ae4d752dd7297ba88c9df8c2ac7c76dea439732a8435
@@ -1,5 +1,5 @@
1
1
  module Musa
2
- VERSION = '0.22.1'
2
+ VERSION = '0.22.6'
3
3
  end
4
4
 
5
5
  require_relative 'musa-dsl/core-ext'
@@ -12,7 +12,6 @@ module Musa
12
12
  alias to_s inspect
13
13
  end
14
14
 
15
-
16
15
  refine Rational.singleton_class do
17
16
  attr_accessor :to_s_as_inspect
18
17
  end
@@ -43,7 +42,7 @@ module Musa
43
42
  end
44
43
 
45
44
  def to_s
46
- inspect simple: true # !Rational.to_s_as_inspect
45
+ inspect simple: !Rational.to_s_as_inspect
47
46
  end
48
47
  end
49
48
  end
@@ -22,24 +22,13 @@ module Musa::Datasets
22
22
  end
23
23
  end
24
24
 
25
- def to_timed_serie(time_start = nil, base_duration: nil)
25
+ def to_timed_serie(time_start: nil, time_start_component: nil, base_duration: nil)
26
26
  time_start ||= 0r
27
- base_duration ||= 1/4r # TODO review incoherence between neumalang 1/4r base duration for quarter notes and general 1r size of bar
28
-
29
- # TODO if instead of using clone (needed because of p.shift) we use index counter the P elements would be evaluated on the last moment
27
+ time_start += self.first[time_start_component] if time_start_component
30
28
 
31
- Musa::Series::E(clone, base_duration, context: { time: time_start }) do |p, base_duration, context: |
32
- value = p.shift
33
-
34
- if value
35
- r = { time: context[:time], value: value } if !value.nil?
36
-
37
- delta_time = p.shift
38
- context[:time] += delta_time * base_duration if delta_time
29
+ base_duration ||= 1/4r # TODO review incoherence between neumalang 1/4r base duration for quarter notes and general 1r size of bar
39
30
 
40
- r&.extend(AbsTimed)
41
- end
42
- end
31
+ PtoTimedSerie.new(self, base_duration, time_start)
43
32
  end
44
33
 
45
34
  def map(&block)
@@ -55,5 +44,37 @@ module Musa::Datasets
55
44
  end
56
45
  end
57
46
  end
47
+
48
+ class PtoTimedSerie
49
+ include Musa::Series::Serie
50
+
51
+ attr_reader :origin
52
+
53
+ def initialize(origin, base_duration, time_start)
54
+ @origin = origin
55
+ @base_duration = base_duration
56
+ @time_start = time_start
57
+
58
+ _restart
59
+
60
+ mark_as_prototype!
61
+ end
62
+
63
+ def _restart
64
+ @p = @origin.clone
65
+ @time = @time_start
66
+ end
67
+
68
+ def _next_value
69
+ if value = @p.shift
70
+ r = { time: @time, value: value }.extend(AbsTimed)
71
+
72
+ delta_time = @p.shift
73
+ @time += delta_time * @base_duration if delta_time
74
+
75
+ r
76
+ end
77
+ end
78
+ end
58
79
  end
59
80
  end
@@ -1,9 +1,9 @@
1
1
  require 'prime'
2
2
 
3
3
  module Musa::Datasets::Score::ToMXML
4
- private
4
+ using Musa::Extension::InspectNice
5
5
 
6
- def process_pdv(measure, bar, divisions_per_bar, element, pointer, logger, do_log)
6
+ private def process_pdv(measure, bar, divisions_per_bar, element, pointer, logger, do_log)
7
7
 
8
8
  pitch, octave, sharps = pitch_and_octave_and_sharps(element[:dataset])
9
9
 
@@ -21,24 +21,26 @@ module Musa::Datasets::Score::ToMXML
21
21
  decompose_as_sum_of_simple_durations(effective_duration))
22
22
 
23
23
  if do_log
24
- logger.debug "\nprocess_pdv #{element}"
25
- logger.debug ""
26
- logger.debug " pointer #{pointer} continue_from_previous #{continue_from_previous_bar} continue_to_next #{continue_to_next_bar}"
27
- logger.debug " effective_start #{effective_start} effective_duration #{effective_duration}"
28
- logger.debug " duration decomposition #{effective_duration_decomposition}"
24
+ logger.debug ''
25
+ logger.debug('process_pdv') { "processing #{element.inspect}" }
26
+ logger.debug { "" }
27
+ logger.debug { " pointer #{pointer.inspect} continue_from_previous #{continue_from_previous_bar} continue_to_next #{continue_to_next_bar}" }
28
+ logger.debug { " effective_start #{effective_start.inspect} effective_duration #{effective_duration.inspect}" }
29
+ logger.debug { " duration decomposition #{effective_duration_decomposition}" }
29
30
  end
30
31
 
31
32
  if pointer > effective_start
32
33
  duration_to_go_back = (pointer - effective_start)
33
34
 
34
- logger.debug "\n -> adding backup #{duration_to_go_back * divisions_per_bar}" if do_log
35
+ logger.debug ''
36
+ logger.debug { " -> adding backup #{duration_to_go_back * divisions_per_bar}" } if do_log
35
37
 
36
38
  measure.add_backup(duration_to_go_back * divisions_per_bar)
37
39
  pointer -= duration_to_go_back
38
40
 
39
41
 
40
42
  elsif pointer < effective_start
41
- warn "\n -> adding start rest duration #{effective_start - pointer} start #{bar + pointer} finish #{bar + effective_start}" if do_log
43
+ logger.warn { " -> adding start rest duration #{effective_start - pointer} start #{bar + pointer} finish #{bar + effective_start}" } if do_log
42
44
 
43
45
  pointer = process_pdv(measure, bar, divisions_per_bar,
44
46
  { start: bar + pointer,
@@ -125,7 +127,7 @@ module Musa::Datasets::Score::ToMXML
125
127
  pointer
126
128
  end
127
129
 
128
- def pitch_and_octave_and_sharps(pdv)
130
+ private def pitch_and_octave_and_sharps(pdv)
129
131
  if pdv[:pitch] == :silence
130
132
  [:silence, nil, nil]
131
133
  else
@@ -143,7 +145,7 @@ module Musa::Datasets::Score::ToMXML
143
145
  end
144
146
  end
145
147
 
146
- def dynamics_index_of(midi_velocity)
148
+ private def dynamics_index_of(midi_velocity)
147
149
  return nil unless midi_velocity
148
150
 
149
151
  # ppp = midi 16 ... fff = midi 127
@@ -153,7 +155,7 @@ module Musa::Datasets::Score::ToMXML
153
155
  .index { |r| r.cover? midi_velocity.round.to_i }
154
156
  end
155
157
 
156
- def dynamics_to_string(dynamics_index)
158
+ private def dynamics_to_string(dynamics_index)
157
159
  return nil unless dynamics_index
158
160
  ['pppppp', 'ppppp', 'pppp', 'ppp', 'pp', 'p', 'mp', 'mf', 'f', 'ff', 'fff'][dynamics_index.round.to_i]
159
161
  end
@@ -1,13 +1,14 @@
1
1
  module Musa::Datasets::Score::ToMXML
2
- private
2
+ using Musa::Extension::InspectNice
3
3
 
4
4
  DynamicsContext = Struct.new(:last_dynamics)
5
5
  private_constant :DynamicsContext
6
6
 
7
- def process_ps(measure, element, context, logger, do_log)
7
+ private def process_ps(measure, element, context, logger, do_log)
8
8
  context ||= DynamicsContext.new
9
9
 
10
- logger.debug "\nprocess_ps #{element}" if do_log
10
+ logger.debug ''
11
+ logger.debug('process_ps') { "processing #{element.inspect}" } if do_log
11
12
 
12
13
  case element[:dataset][:type]
13
14
  when :crescendo, :diminuendo
@@ -15,7 +16,14 @@ module Musa::Datasets::Score::ToMXML
15
16
  dynamics = dynamics_to_string(element[:dataset][:from])
16
17
 
17
18
  if dynamics != context.last_dynamics
18
- measure.add_dynamics dynamics, placement: 'below' if dynamics && element[:dataset][:from] > 0
19
+ if dynamics
20
+ if element[:dataset][:from] < 0
21
+ logger.warn { "dynamics #{element[:dataset][:from]} not renderizable" } if do_log
22
+ elsif element[:dataset][:from] > 0
23
+ measure.add_dynamics dynamics, placement: 'below'
24
+ end
25
+ end
26
+
19
27
  context.last_dynamics = dynamics
20
28
  end
21
29
 
@@ -29,7 +37,16 @@ module Musa::Datasets::Score::ToMXML
29
37
 
30
38
  dynamics = dynamics_to_string(element[:dataset][:to])
31
39
 
32
- measure.add_dynamics dynamics, placement: 'below' if dynamics && element[:dataset][:to] > 0
40
+ if dynamics != context.last_dynamics
41
+ if dynamics
42
+ if element[:dataset][:to] < 0
43
+ logger.warn { "dynamics #{element[:dataset][:to]} not renderizable" } if do_log
44
+ elsif element[:dataset][:to] > 0
45
+ measure.add_dynamics dynamics, placement: 'below'
46
+ end
47
+ end
48
+ end
49
+
33
50
  context.last_dynamics = dynamics
34
51
  end
35
52
 
@@ -37,7 +54,16 @@ module Musa::Datasets::Score::ToMXML
37
54
  dynamics = dynamics_to_string(element[:dataset][:from])
38
55
 
39
56
  if dynamics != context.last_dynamics
40
- measure.add_dynamics dynamics, placement: 'below'
57
+
58
+
59
+ if dynamics
60
+ if element[:dataset][:from] < 0
61
+ logger.warn { "dynamics #{element[:dataset][:to]} not renderizable" } if do_log
62
+ elsif element[:dataset][:from] > 0
63
+ measure.add_dynamics dynamics, placement: 'below'
64
+ end
65
+ end
66
+
41
67
  context.last_dynamics = dynamics
42
68
  end
43
69
 
@@ -1,5 +1,6 @@
1
1
  require_relative '../../../logger'
2
2
  require_relative '../../../musicxml'
3
+ require_relative '../../../core-ext/inspect-nice'
3
4
 
4
5
  require_relative 'process-time'
5
6
  require_relative 'process-pdv'
@@ -10,6 +11,8 @@ module Musa::Datasets; class Score
10
11
  include Musa::MusicXML::Builder
11
12
  include Musa::Datasets
12
13
 
14
+ using Musa::Extension::InspectNice
15
+
13
16
  def to_mxml(beats_per_bar, ticks_per_beat,
14
17
  bpm: nil,
15
18
  title: nil,
@@ -22,7 +25,12 @@ module Musa::Datasets; class Score
22
25
  bpm ||= 90
23
26
  title ||= 'Untitled'
24
27
  creators ||= { composer: 'Unknown' }
25
- logger ||= Musa::Logger::Logger.new
28
+
29
+ if logger.nil?
30
+ logger = Musa::Logger::Logger.new
31
+ logger.debug! if do_log
32
+ end
33
+
26
34
  do_log ||= nil
27
35
 
28
36
  mxml = ScorePartwise.new do |_|
@@ -54,12 +62,16 @@ module Musa::Datasets; class Score
54
62
  end
55
63
 
56
64
  if do_log
57
- logger.debug"\nscore.to_mxl log:"
58
- logger.debug "-----------------"
65
+ logger.debug ""
66
+ logger.debug"score.to_mxml log:"
67
+ logger.debug"------------------"
59
68
  end
60
69
 
61
70
  parts.each_key do |part_id|
62
- fill_part mxml.parts[part_id], beats_per_bar * ticks_per_beat, (parts.size > 1 ? part_id : nil), logger, do_log
71
+ fill_part mxml.parts[part_id],
72
+ beats_per_bar * ticks_per_beat,
73
+ (parts.size > 1 ? part_id : nil),
74
+ logger, do_log
63
75
  end
64
76
 
65
77
  mxml
@@ -74,7 +86,7 @@ module Musa::Datasets; class Score
74
86
  (1..finish || 0).each do |bar|
75
87
  if do_log
76
88
  logger.debug ""
77
- logger.debug msg = "filling part #{part.name} (#{instrument}): processing bar #{bar}"
89
+ logger.debug msg = "filling part #{part.name} (#{instrument || 'nil'}): processing bar #{bar}"
78
90
  logger.debug "-" * msg.size
79
91
  end
80
92
 
@@ -83,7 +95,7 @@ module Musa::Datasets; class Score
83
95
 
84
96
  pointer = 0r
85
97
 
86
- instrument_score = subset { |dataset| dataset[:instrument] == instrument }
98
+ instrument_score = subset { |dataset| instrument.nil? || dataset[:instrument] == instrument }
87
99
 
88
100
  bar_elements = \
89
101
  (instrument_score.changes_between(bar, bar + 1).select { |p| p[:dataset].is_a?(PS) } +
@@ -92,7 +104,7 @@ module Musa::Datasets; class Score
92
104
  e[:dataset].is_a?(PS) ? 0 : 1 ] }
93
105
 
94
106
  if pdvs.empty?
95
- logger.debug "\nadded full bar silence" if do_log
107
+ logger.debug "\nadding full bar silence..." if do_log
96
108
 
97
109
  process_pdv(measure, bar, divisions_per_bar,
98
110
  { start: bar,
@@ -104,7 +116,7 @@ module Musa::Datasets; class Score
104
116
  else
105
117
  first = bar_elements.first
106
118
 
107
- logger.debug "\nfirst element #{first}" if do_log
119
+ logger.debug "\nfirst element #{first.inspect}" if do_log
108
120
 
109
121
  # TODO habrá que arreglar el cálculo de pointer cuando haya avances y retrocesos para que
110
122
  # TODO no añada silencios incorrectos al principio o al final
@@ -113,7 +125,7 @@ module Musa::Datasets; class Score
113
125
 
114
126
  silence_duration = first[:start_in_interval] - bar
115
127
 
116
- logger.debug "\nadded initial silence for duration #{silence_duration}" if do_log
128
+ logger.debug "\nadding initial silence for duration #{silence_duration}..." if do_log
117
129
 
118
130
  pointer = process_pdv(measure, bar, divisions_per_bar,
119
131
  { start: bar,
@@ -124,6 +136,8 @@ module Musa::Datasets; class Score
124
136
  do_log)
125
137
  end
126
138
 
139
+ logger.debug "\nadding PDV and PS elements..." if do_log
140
+
127
141
  bar_elements.each do |element|
128
142
  case element[:dataset]
129
143
  when PDV
@@ -140,7 +154,7 @@ module Musa::Datasets; class Score
140
154
  if pointer < 1r
141
155
  silence_duration = 1r - pointer
142
156
 
143
- logger.debug "\nadded ending silence for duration #{silence_duration}" if do_log
157
+ logger.debug "\nadded ending silence for duration #{silence_duration}..." if do_log
144
158
 
145
159
  process_pdv(measure, bar, divisions_per_bar,
146
160
  { start: bar + pointer,
@@ -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