musa-dsl 0.26.5 → 0.26.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/gem-test-and-push.yml +6 -20
- data/Gemfile +3 -0
- data/lib/musa-dsl/core-ext/smart-proc-binder.rb +10 -10
- data/lib/musa-dsl/datasets/e.rb +1 -1
- data/lib/musa-dsl/datasets/gdvd.rb +1 -1
- data/lib/musa-dsl/generative/{backboner.rb → rules.rb} +34 -21
- data/lib/musa-dsl/generative.rb +1 -1
- data/lib/musa-dsl/music/chord-definition.rb +20 -6
- data/lib/musa-dsl/music/chord-definitions.rb +10 -2
- data/lib/musa-dsl/music/chords.rb +135 -241
- data/lib/musa-dsl/music/equally-tempered-12-tone-scale-system.rb +28 -28
- data/lib/musa-dsl/music/scales.rb +22 -12
- data/lib/musa-dsl/neumalang/neumalang.citrus +10 -4
- data/lib/musa-dsl/neumalang/neumalang.rb +14 -3
- data/lib/musa-dsl/repl/repl.rb +7 -3
- data/lib/musa-dsl/sequencer/base-sequencer-implementation-play-helper.rb +78 -70
- data/lib/musa-dsl/sequencer/base-sequencer-implementation-play.rb +18 -11
- data/lib/musa-dsl/sequencer/base-sequencer-implementation.rb +8 -8
- data/lib/musa-dsl/sequencer/sequencer-dsl.rb +1 -3
- data/lib/musa-dsl/series/main-serie-operations.rb +10 -3
- data/lib/musa-dsl/transport/input-midi-clock.rb +12 -1
- data/lib/musa-dsl.rb +2 -2
- data/musa-dsl.gemspec +3 -3
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a1598e463290a813acd81f7d4c2a380c2b4f904c266505efb1c0c76295a2e891
|
4
|
+
data.tar.gz: 7b6c53ec4109d923f6aab5a1c250672b87a0c1bcc275c0e3359e769b01dd9371
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8178a6d752685d3ae592c1e80374b85cba4f59ffdcc556d358d1f0c9a2787812421a74c6c247b890b80e05bf221ce3b490a60d2201361041419b0ca4e42f93cc
|
7
|
+
data.tar.gz: bfd208048b17a2e4f5374eedda0bd5dd5b2d6eb7268a867c63523477da6170f2a7a340d2dca8ab719467c58efd9662fed221118301d3d321c8176cb9785f380b
|
@@ -11,7 +11,7 @@ jobs:
|
|
11
11
|
runs-on: ubuntu-latest
|
12
12
|
strategy:
|
13
13
|
matrix:
|
14
|
-
ruby-version: ['2.7']
|
14
|
+
ruby-version: ['2.7.8']
|
15
15
|
|
16
16
|
steps:
|
17
17
|
- uses: actions/checkout@v2
|
@@ -32,31 +32,17 @@ jobs:
|
|
32
32
|
packages: write
|
33
33
|
|
34
34
|
steps:
|
35
|
-
- uses: actions/checkout@
|
36
|
-
- name: Set up Ruby 2.7
|
37
|
-
uses:
|
35
|
+
- uses: actions/checkout@v3
|
36
|
+
- name: Set up Ruby 2.7.8
|
37
|
+
uses: ruby/setup-ruby@v1
|
38
38
|
with:
|
39
|
-
ruby-version: 2.7.
|
40
|
-
|
41
|
-
# - name: Publish to GPR
|
42
|
-
# run: |
|
43
|
-
# mkdir -p $HOME/.gem
|
44
|
-
# touch $HOME/.gem/credentials
|
45
|
-
# chmod 0600 $HOME/.gem/credentials
|
46
|
-
# printf -- "---\n:github: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
|
47
|
-
# gem build *.gemspec
|
48
|
-
# gem push --KEY github --host https://rubygems.pkg.github.com/${OWNER} *.gem
|
49
|
-
# env:
|
50
|
-
# GEM_HOST_API_KEY: "Bearer ${{secrets.GITHUB_TOKEN}}"
|
51
|
-
# OWNER: ${{ github.repository_owner }}
|
39
|
+
ruby-version: 2.7.8
|
52
40
|
|
53
41
|
- name: Publish to RubyGems
|
54
42
|
run: |
|
55
43
|
mkdir -p $HOME/.gem
|
56
44
|
touch $HOME/.gem/credentials
|
57
45
|
chmod 0600 $HOME/.gem/credentials
|
58
|
-
printf -- "---\n:rubygems_api_key: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
|
46
|
+
printf -- "---\n:rubygems_api_key: ${{secrets.GEM_HOST_API_KEY}}\n" > $HOME/.gem/credentials
|
59
47
|
gem build *.gemspec
|
60
48
|
gem push *.gem
|
61
|
-
env:
|
62
|
-
GEM_HOST_API_KEY: "${{secrets.RUBYGEMS_AUTH_TOKEN}}"
|
data/Gemfile
CHANGED
@@ -29,36 +29,36 @@ module Musa
|
|
29
29
|
@block.parameters
|
30
30
|
end
|
31
31
|
|
32
|
-
def call(*value_parameters, **key_parameters)
|
33
|
-
_call value_parameters, key_parameters
|
32
|
+
def call(*value_parameters, **key_parameters, &block)
|
33
|
+
_call value_parameters, key_parameters, block
|
34
34
|
end
|
35
35
|
|
36
|
-
def _call(value_parameters, key_parameters = {})
|
36
|
+
def _call(value_parameters, key_parameters = {}, block = nil)
|
37
37
|
if @on_rescue
|
38
38
|
begin
|
39
|
-
__call value_parameters, key_parameters
|
39
|
+
__call value_parameters, key_parameters, block
|
40
40
|
rescue StandardError, ScriptError => e
|
41
41
|
@on_rescue.call e
|
42
42
|
end
|
43
43
|
else
|
44
|
-
__call value_parameters, key_parameters
|
44
|
+
__call value_parameters, key_parameters, block
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
48
|
-
private def __call(value_parameters, key_parameters = {})
|
48
|
+
private def __call(value_parameters, key_parameters = {}, block = nil)
|
49
49
|
effective_value_parameters, effective_key_parameters = apply(*value_parameters, **key_parameters)
|
50
50
|
|
51
51
|
if effective_key_parameters.empty?
|
52
52
|
if effective_value_parameters.empty?
|
53
|
-
@block.call
|
53
|
+
@block.call(&block)
|
54
54
|
else
|
55
|
-
@block.call
|
55
|
+
@block.call(*effective_value_parameters, &block)
|
56
56
|
end
|
57
57
|
else
|
58
58
|
if effective_value_parameters.empty?
|
59
|
-
@block.call
|
59
|
+
@block.call(**effective_key_parameters, &block)
|
60
60
|
else
|
61
|
-
@block.call
|
61
|
+
@block.call(*effective_value_parameters, **effective_key_parameters, &block)
|
62
62
|
end
|
63
63
|
end
|
64
64
|
end
|
data/lib/musa-dsl/datasets/e.rb
CHANGED
@@ -45,7 +45,7 @@ module Musa::Datasets
|
|
45
45
|
|
46
46
|
NaturalKeys = (NaturalKeys +
|
47
47
|
[:duration, # duration of the process (note reproduction, dynamics evolution, etc)
|
48
|
-
:note_duration, # duration of the note (a staccato note is
|
48
|
+
:note_duration, # duration of the note (a staccato note is effectively shorter than elapsed duration until next note)
|
49
49
|
:forward_duration # duration to wait until next event (if 0 means the next event should be executed at the same time than this one)
|
50
50
|
]).freeze
|
51
51
|
|
@@ -1,21 +1,22 @@
|
|
1
1
|
require_relative '../core-ext/smart-proc-binder'
|
2
2
|
require_relative '../core-ext/with'
|
3
3
|
|
4
|
-
# 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)
|
5
|
-
# TODO esto mismo sería aplicable en otros generadores? variatio/darwin? generative-grammar? markov?
|
4
|
+
# 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)
|
5
|
+
# TODO: esto mismo sería aplicable en otros generadores? variatio/darwin? generative-grammar? markov?
|
6
|
+
# TODO: optimizar la llamada a .with que internamente genera cada vez un SmartProcBinder; podría generarse sólo una vez por cada &block
|
6
7
|
|
7
8
|
module Musa
|
8
|
-
module
|
9
|
+
module Rules
|
9
10
|
using Musa::Extension::Arrayfy
|
10
11
|
|
11
|
-
class
|
12
|
+
class Rules
|
12
13
|
include Musa::Extension::With
|
13
14
|
|
14
15
|
def initialize(&block)
|
15
16
|
@dsl = RulesEvalContext.new(&block)
|
16
17
|
end
|
17
18
|
|
18
|
-
def generate_possibilities(object, confirmed_node = nil, node = nil, grow_rules = nil)
|
19
|
+
def generate_possibilities(object, confirmed_node = nil, node = nil, grow_rules = nil, **parameters)
|
19
20
|
node ||= Node.new
|
20
21
|
grow_rules ||= @dsl._grow_rules
|
21
22
|
|
@@ -26,11 +27,15 @@ module Musa
|
|
26
27
|
grow_rule = grow_rules.shift
|
27
28
|
|
28
29
|
if grow_rule
|
29
|
-
grow_rule.generate_possibilities(object, history).each do |new_object|
|
30
|
+
grow_rule.generate_possibilities(object, history, **parameters).each do |new_object|
|
30
31
|
new_node = Node.new new_object, node
|
31
|
-
|
32
|
+
if @dsl._has_ending? && @dsl._ended?(new_object, history, **parameters) ||
|
33
|
+
!@dsl._has_ending? && grow_rules.empty?
|
32
34
|
|
33
|
-
|
35
|
+
new_node.mark_as_ended!
|
36
|
+
end
|
37
|
+
|
38
|
+
rejection = @dsl._cut_rules.find { |cut_rule| cut_rule.rejects?(new_object, history, **parameters) }
|
34
39
|
# TODO: include rejection secondary reasons in rejection message
|
35
40
|
|
36
41
|
new_node.reject! rejection if rejection
|
@@ -41,14 +46,14 @@ module Musa
|
|
41
46
|
|
42
47
|
unless grow_rules.empty?
|
43
48
|
node.children.each do |node|
|
44
|
-
generate_possibilities node.object, confirmed_node, node, grow_rules unless node.rejected || node.ended?
|
49
|
+
generate_possibilities node.object, confirmed_node, node, grow_rules, **parameters unless node.rejected || node.ended?
|
45
50
|
end
|
46
51
|
end
|
47
52
|
|
48
53
|
node
|
49
54
|
end
|
50
55
|
|
51
|
-
def apply(object_or_list, node = nil)
|
56
|
+
def apply(object_or_list, node = nil, **parameters)
|
52
57
|
list = object_or_list.arrayfy.clone
|
53
58
|
|
54
59
|
node ||= Node.new
|
@@ -56,7 +61,7 @@ module Musa
|
|
56
61
|
seed = list.shift
|
57
62
|
|
58
63
|
if seed
|
59
|
-
result = generate_possibilities seed, node
|
64
|
+
result = generate_possibilities seed, node, **parameters
|
60
65
|
|
61
66
|
fished = result.fish
|
62
67
|
|
@@ -64,7 +69,7 @@ module Musa
|
|
64
69
|
|
65
70
|
fished.each do |object|
|
66
71
|
subnode = node.add(object).mark_as_ended!
|
67
|
-
apply list, subnode
|
72
|
+
apply list, subnode, **parameters
|
68
73
|
end
|
69
74
|
end
|
70
75
|
|
@@ -77,11 +82,12 @@ module Musa
|
|
77
82
|
attr_reader :_grow_rules, :_ended_when, :_cut_rules
|
78
83
|
|
79
84
|
def initialize(&block)
|
85
|
+
@_grow_rules = []
|
86
|
+
@_cut_rules = []
|
80
87
|
with &block
|
81
88
|
end
|
82
89
|
|
83
90
|
def grow(name, &block)
|
84
|
-
@_grow_rules ||= []
|
85
91
|
@_grow_rules << GrowRule.new(name, &block)
|
86
92
|
self
|
87
93
|
end
|
@@ -92,13 +98,20 @@ module Musa
|
|
92
98
|
end
|
93
99
|
|
94
100
|
def cut(reason, &block)
|
95
|
-
@_cut_rules ||= []
|
96
101
|
@_cut_rules << CutRule.new(reason, &block)
|
97
102
|
self
|
98
103
|
end
|
99
104
|
|
100
|
-
def
|
101
|
-
|
105
|
+
def _has_ending?
|
106
|
+
!@_ended_when.nil?
|
107
|
+
end
|
108
|
+
|
109
|
+
def _ended?(object, history, **parameters)
|
110
|
+
if @_ended_when
|
111
|
+
with object, history, **parameters, &@_ended_when
|
112
|
+
else
|
113
|
+
false
|
114
|
+
end
|
102
115
|
end
|
103
116
|
|
104
117
|
class GrowRule
|
@@ -109,10 +122,10 @@ module Musa
|
|
109
122
|
@block = block
|
110
123
|
end
|
111
124
|
|
112
|
-
def generate_possibilities(object, history)
|
125
|
+
def generate_possibilities(object, history, **parameters)
|
113
126
|
# TODO: optimize context using only one instance for all genereate_possibilities calls
|
114
127
|
context = GrowRuleEvalContext.new
|
115
|
-
context.with object, history, &@block
|
128
|
+
context.with object, history, **parameters, &@block
|
116
129
|
|
117
130
|
context._branches
|
118
131
|
end
|
@@ -145,10 +158,10 @@ module Musa
|
|
145
158
|
@block = block
|
146
159
|
end
|
147
160
|
|
148
|
-
def rejects?(object, history)
|
161
|
+
def rejects?(object, history, **parameters)
|
149
162
|
# TODO: optimize context using only one instance for all rejects? checks
|
150
163
|
context = CutRuleEvalContext.new
|
151
|
-
context.with object, history, &@block
|
164
|
+
context.with object, history, **parameters, &@block
|
152
165
|
|
153
166
|
reasons = context._secondary_reasons.collect { |_| ("#{@reason} (#{_})" if _) || @reason }
|
154
167
|
|
@@ -203,7 +216,7 @@ module Musa
|
|
203
216
|
@children.each(&:update_rejection_by_children!)
|
204
217
|
|
205
218
|
if !@children.empty? && !@children.find { |n| !n.rejected }
|
206
|
-
reject!
|
219
|
+
reject! 'Node rejected because all children are rejected'
|
207
220
|
end
|
208
221
|
|
209
222
|
@ended = true
|
data/lib/musa-dsl/generative.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
1
3
|
module Musa
|
2
4
|
module Chords
|
3
5
|
class ChordDefinition
|
@@ -6,7 +8,7 @@ module Musa
|
|
6
8
|
end
|
7
9
|
|
8
10
|
def self.register(name, offsets:, **features)
|
9
|
-
definition = ChordDefinition.new(name, offsets: offsets, **features)
|
11
|
+
definition = ChordDefinition.new(name, offsets: offsets, **features)
|
10
12
|
|
11
13
|
@definitions ||= {}
|
12
14
|
@definitions[definition.name] = definition
|
@@ -14,6 +16,9 @@ module Musa
|
|
14
16
|
@features_by_value ||= {}
|
15
17
|
definition.features.each { |k, v| @features_by_value[v] = k }
|
16
18
|
|
19
|
+
@feature_keys ||= Set[]
|
20
|
+
features.keys.each { |feature_name| @feature_keys << feature_name }
|
21
|
+
|
17
22
|
self
|
18
23
|
end
|
19
24
|
|
@@ -44,11 +49,16 @@ module Musa
|
|
44
49
|
@features_by_value.keys
|
45
50
|
end
|
46
51
|
|
52
|
+
def self.feature_keys
|
53
|
+
@feature_keys
|
54
|
+
end
|
55
|
+
|
47
56
|
def initialize(name, offsets:, **features)
|
48
|
-
@name = name
|
49
|
-
@features = features.
|
50
|
-
@pitch_offsets = offsets.
|
51
|
-
@pitch_names = offsets.collect { |k, v| [v, k] }.to_h
|
57
|
+
@name = name.freeze
|
58
|
+
@features = features.transform_values(&:dup).transform_values(&:freeze).freeze
|
59
|
+
@pitch_offsets = offsets.dup.freeze
|
60
|
+
@pitch_names = offsets.collect { |k, v| [v, k] }.to_h.freeze
|
61
|
+
freeze
|
52
62
|
end
|
53
63
|
|
54
64
|
attr_reader :name, :features, :pitch_offsets, :pitch_names
|
@@ -57,6 +67,10 @@ module Musa
|
|
57
67
|
@pitch_offsets.values.collect { |offset| root_pitch + offset }
|
58
68
|
end
|
59
69
|
|
70
|
+
def in_scale?(scale, chord_root_pitch:)
|
71
|
+
!pitches(chord_root_pitch).find { |chord_pitch| scale.note_of_pitch(chord_pitch).nil? }
|
72
|
+
end
|
73
|
+
|
60
74
|
def named_pitches(elements_or_pitches, &block)
|
61
75
|
pitches = elements_or_pitches.collect do |element_or_pitch|
|
62
76
|
[if block_given?
|
@@ -93,7 +107,7 @@ module Musa
|
|
93
107
|
|
94
108
|
alias to_s inspect
|
95
109
|
|
96
|
-
|
110
|
+
private
|
97
111
|
|
98
112
|
def octave_reduce(pitches)
|
99
113
|
pitches.collect { |p| p % 12 }
|
@@ -1,15 +1,23 @@
|
|
1
1
|
require_relative 'chord-definition'
|
2
2
|
|
3
|
+
# TODO trasladar los acordes de https://en.wikipedia.org/wiki/Chord_notation
|
4
|
+
|
3
5
|
Musa::Chords::ChordDefinition.register :maj, quality: :major, size: :triad, offsets: { root: 0, third: 4, fifth: 7 }
|
4
6
|
Musa::Chords::ChordDefinition.register :min, quality: :minor, size: :triad, offsets: { root: 0, third: 3, fifth: 7 }
|
7
|
+
Musa::Chords::ChordDefinition.register :dim, quality: :diminished, size: :triad, offsets: { root: 0, third: 3, fifth: 3 }
|
8
|
+
Musa::Chords::ChordDefinition.register :aug, quality: :augmented, size: :triad, offsets: { root: 0, third: 4, fifth: 8 }
|
5
9
|
|
6
10
|
Musa::Chords::ChordDefinition.register :maj7, quality: :major, size: :seventh, offsets: { root: 0, third: 4, fifth: 7, seventh: 11 }
|
7
|
-
Musa::Chords::ChordDefinition.register :maj7, quality: :major, size: :seventh, dominant: :dominant , offsets: { root: 0, third: 4, fifth: 7, seventh: 10 }
|
8
|
-
|
9
11
|
Musa::Chords::ChordDefinition.register :min7, quality: :minor, size: :seventh, offsets: { root: 0, third: 3, fifth: 7, seventh: 11 }
|
10
12
|
|
13
|
+
Musa::Chords::ChordDefinition.register :dom7, quality: :dominant, size: :seventh, offsets: { root: 0, third: 4, fifth: 7, seventh: 10 }
|
14
|
+
|
11
15
|
Musa::Chords::ChordDefinition.register :maj9, quality: :major, size: :ninth, offsets: { root: 0, third: 4, fifth: 7, seventh: 11, ninth: 14 }
|
12
16
|
Musa::Chords::ChordDefinition.register :min9, quality: :minor, size: :ninth, offsets: { root: 0, third: 3, fifth: 7, seventh: 11, ninth: 14 }
|
17
|
+
Musa::Chords::ChordDefinition.register :dom9, quality: :dominant, size: :ninth, offsets: { root: 0, third: 4, fifth: 7, seventh: 10, ninth: 14 }
|
13
18
|
|
14
19
|
Musa::Chords::ChordDefinition.register :maj11, quality: :major, size: :eleventh, offsets: { root: 0, third: 4, fifth: 7, seventh: 11, ninth: 14, eleventh: 17 }
|
15
20
|
Musa::Chords::ChordDefinition.register :min11, quality: :minor, size: :eleventh, offsets: { root: 0, third: 3, fifth: 7, seventh: 11, ninth: 14, eleventh: 17 }
|
21
|
+
|
22
|
+
Musa::Chords::ChordDefinition.register :maj13, quality: :major, size: :eleventh, offsets: { root: 0, third: 4, fifth: 7, seventh: 11, ninth: 14, eleventh: 17 }
|
23
|
+
Musa::Chords::ChordDefinition.register :min13, quality: :minor, size: :eleventh, offsets: { root: 0, third: 3, fifth: 7, seventh: 11, ninth: 14, eleventh: 17 }
|