musa-dsl 0.26.5 → 0.26.8

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 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 }