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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9d9154434fb485380e87cf24b6efa8ebdbaee0a223a94c2ad1988ae808b0a691
4
- data.tar.gz: 6323750820c35c1ef1e8b2220d4f511bba9fafaf504dacadce14aba33ee647f2
3
+ metadata.gz: a1598e463290a813acd81f7d4c2a380c2b4f904c266505efb1c0c76295a2e891
4
+ data.tar.gz: 7b6c53ec4109d923f6aab5a1c250672b87a0c1bcc275c0e3359e769b01dd9371
5
5
  SHA512:
6
- metadata.gz: 91e4c3067db836ae8eac4f0242bb4ac1dd6ee48da8959bb4f06b8133e49065260bf316d04dc893c1e2e9cd7f1cbf57b882167868ca3f27072869f15de9962424
7
- data.tar.gz: d0df67a8d02ce6ab12764cfd2478de3322a3006ada484bbbe32cef0e885eac35be2d157fda16ee7453db7b314bb93f81cb46bf83409b218b6936e673c1e4dc2a
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@v2
36
- - name: Set up Ruby 2.7
37
- uses: actions/setup-ruby@v1
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.x
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
@@ -1,3 +1,6 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
3
  gemspec
4
+ gem 'rubocop', group: 'development'
5
+ gem 'rubocop', group: 'development'
6
+ gem 'rubocop', group: 'development'
@@ -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 *effective_value_parameters
55
+ @block.call(*effective_value_parameters, &block)
56
56
  end
57
57
  else
58
58
  if effective_value_parameters.empty?
59
- @block.call **effective_key_parameters
59
+ @block.call(**effective_key_parameters, &block)
60
60
  else
61
- @block.call *effective_value_parameters, **effective_key_parameters
61
+ @block.call(*effective_value_parameters, **effective_key_parameters, &block)
62
62
  end
63
63
  end
64
64
  end
@@ -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 effectvely shorter than elapsed duration until next note)
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
 
@@ -109,7 +109,7 @@ module Musa::Datasets
109
109
  r
110
110
  end
111
111
 
112
- def normalize_to_scale(scale, grade, sharps)
112
+ private def normalize_to_scale(scale, grade, sharps)
113
113
  note = scale[grade].sharp(sharps)
114
114
  background = note.background_note
115
115
 
@@ -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 Backboner
9
+ module Rules
9
10
  using Musa::Extension::Arrayfy
10
11
 
11
- class Backboner
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
- new_node.mark_as_ended! if @dsl._ended? new_object
32
+ if @dsl._has_ending? && @dsl._ended?(new_object, history, **parameters) ||
33
+ !@dsl._has_ending? && grow_rules.empty?
32
34
 
33
- rejection = @dsl._cut_rules.find { |cut_rule| cut_rule.rejects?(new_object, history) }
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 _ended?(object)
101
- instance_exec object, &@_ended_when
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! "Node rejected because all children are rejected"
219
+ reject! 'Node rejected because all children are rejected'
207
220
  end
208
221
 
209
222
  @ended = true
@@ -1,5 +1,5 @@
1
1
  require_relative 'generative/variatio'
2
2
  require_relative 'generative/darwin'
3
- require_relative 'generative/backboner'
3
+ require_relative 'generative/rules'
4
4
  require_relative 'generative/markov'
5
5
  require_relative 'generative/generative-grammar'
@@ -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).freeze
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.clone.freeze
50
- @pitch_offsets = offsets.clone.freeze
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
- protected
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 }