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.
- checksums.yaml +4 -4
- data/lib/musa-dsl.rb +1 -1
- data/lib/musa-dsl/core-ext/inspect-nice.rb +1 -2
- data/lib/musa-dsl/datasets/p.rb +36 -15
- data/lib/musa-dsl/datasets/score/to-mxml/process-pdv.rb +14 -12
- data/lib/musa-dsl/datasets/score/to-mxml/process-ps.rb +32 -6
- data/lib/musa-dsl/datasets/score/to-mxml/to-mxml.rb +24 -10
- data/lib/musa-dsl/logger/logger.rb +6 -1
- data/lib/musa-dsl/matrix/matrix.rb +9 -7
- data/lib/musa-dsl/midi/midi-voices.rb +1 -0
- data/lib/musa-dsl/music/scales.rb +1 -1
- data/lib/musa-dsl/sequencer/base-sequencer-implementation-play-helper.rb +7 -2
- data/lib/musa-dsl/sequencer/base-sequencer-implementation-play-timed.rb +30 -129
- data/lib/musa-dsl/sequencer/base-sequencer-implementation.rb +10 -24
- data/lib/musa-dsl/sequencer/base-sequencer-tick-based.rb +9 -9
- data/lib/musa-dsl/sequencer/base-sequencer-tickless-based.rb +3 -5
- data/lib/musa-dsl/sequencer/{base-sequencer-public.rb → base-sequencer.rb} +15 -23
- data/lib/musa-dsl/sequencer/sequencer-dsl.rb +7 -4
- data/lib/musa-dsl/sequencer/sequencer.rb +8 -1
- data/lib/musa-dsl/series/base-series.rb +3 -3
- data/lib/musa-dsl/series/hash-or-array-serie-splitter.rb +90 -10
- data/lib/musa-dsl/series/main-serie-constructors.rb +8 -12
- data/lib/musa-dsl/series/main-serie-operations.rb +45 -5
- data/lib/musa-dsl/series/quantizer-serie.rb +25 -15
- data/lib/musa-dsl/series/series.rb +1 -1
- data/lib/musa-dsl/series/timed-serie.rb +356 -0
- data/musa-dsl.gemspec +3 -3
- metadata +6 -6
- 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:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e85f0a7bc9ddbb82ea9b6b36741a87c1dc04f2feb1c10ea0f5fcb92e4dfc7a37
|
4
|
+
data.tar.gz: 13ad3537ac0a2e03c07c589174a12a8dd9af5013be79f5bd1ee769820cd94347
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 06f58c414bbbd873179850c378f3022e1bc40eba16325b787824e1cb88b27229c7ac19d08032c8b0385c792ae38324c982970dcc94c91e7fd3d924208b640aa4
|
7
|
+
data.tar.gz: 63398fc18d40799119742df1587735f9736abec4a0c1d97e9a9b29202395b6f4223cea7c01075e95d6f0ae4d752dd7297ba88c9df8c2ac7c76dea439732a8435
|
data/lib/musa-dsl.rb
CHANGED
@@ -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:
|
45
|
+
inspect simple: !Rational.to_s_as_inspect
|
47
46
|
end
|
48
47
|
end
|
49
48
|
end
|
data/lib/musa-dsl/datasets/p.rb
CHANGED
@@ -22,24 +22,13 @@ module Musa::Datasets
|
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
|
-
def to_timed_serie(time_start
|
25
|
+
def to_timed_serie(time_start: nil, time_start_component: nil, base_duration: nil)
|
26
26
|
time_start ||= 0r
|
27
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
25
|
-
logger.debug ""
|
26
|
-
logger.debug
|
27
|
-
logger.debug "
|
28
|
-
logger.debug "
|
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
|
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 "
|
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
|
-
|
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
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
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],
|
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 "\
|
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 "\
|
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
|
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
|
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
|
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
|
|