Class: Musa::Chords::ChordDefinition

Inherits:
Object
  • Object
show all
Defined in:
lib/musa-dsl/music/chord-definition.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, offsets:, **features) ⇒ ChordDefinition

Returns a new instance of ChordDefinition.



56
57
58
59
60
61
62
# File 'lib/musa-dsl/music/chord-definition.rb', line 56

def initialize(name, offsets:, **features)
  @name = name.freeze
  @features = features.transform_values(&:dup).transform_values(&:freeze).freeze
  @pitch_offsets = offsets.dup.freeze
  @pitch_names = offsets.collect { |k, v| [v, k] }.to_h.freeze
  freeze
end

Instance Attribute Details

#featuresObject (readonly)

Returns the value of attribute features.



64
65
66
# File 'lib/musa-dsl/music/chord-definition.rb', line 64

def features
  @features
end

#nameObject (readonly)

Returns the value of attribute name.



64
65
66
# File 'lib/musa-dsl/music/chord-definition.rb', line 64

def name
  @name
end

#pitch_namesObject (readonly)

Returns the value of attribute pitch_names.



64
65
66
# File 'lib/musa-dsl/music/chord-definition.rb', line 64

def pitch_names
  @pitch_names
end

#pitch_offsetsObject (readonly)

Returns the value of attribute pitch_offsets.



64
65
66
# File 'lib/musa-dsl/music/chord-definition.rb', line 64

def pitch_offsets
  @pitch_offsets
end

Class Method Details

.[](name) ⇒ Object



6
7
8
# File 'lib/musa-dsl/music/chord-definition.rb', line 6

def self.[](name)
  @definitions[name]
end

.feature_key_of(feature_value) ⇒ Object



44
45
46
# File 'lib/musa-dsl/music/chord-definition.rb', line 44

def self.feature_key_of(feature_value)
  @features_by_value[feature_value]
end

.feature_keysObject



52
53
54
# File 'lib/musa-dsl/music/chord-definition.rb', line 52

def self.feature_keys
  @feature_keys
end

.feature_valuesObject



48
49
50
# File 'lib/musa-dsl/music/chord-definition.rb', line 48

def self.feature_values
  @features_by_value.keys
end

.features_from(values = nil, hash = nil) ⇒ Object



29
30
31
32
33
34
35
36
37
# File 'lib/musa-dsl/music/chord-definition.rb', line 29

def self.features_from(values = nil, hash = nil)
  values ||= []
  hash ||= {}

  features = hash.dup
  values.each { |v| features[@features_by_value[v]] = v }

  features
end

.find_by_features(*values, **hash) ⇒ Object



39
40
41
42
# File 'lib/musa-dsl/music/chord-definition.rb', line 39

def self.find_by_features(*values, **hash)
  features = features_from(values, hash)
  @definitions.values.select { |d| features <= d.features }
end

.find_by_pitches(pitches) ⇒ Object



25
26
27
# File 'lib/musa-dsl/music/chord-definition.rb', line 25

def self.find_by_pitches(pitches)
  @definitions.values.find { |d| d.matches(pitches) }
end

.register(name, offsets:, **features) ⇒ Object



10
11
12
13
14
15
16
17
18
19
20
21
22
23
# File 'lib/musa-dsl/music/chord-definition.rb', line 10

def self.register(name, offsets:, **features)
  definition = ChordDefinition.new(name, offsets: offsets, **features)

  @definitions ||= {}
  @definitions[definition.name] = definition

  @features_by_value ||= {}
  definition.features.each { |k, v| @features_by_value[v] = k }

  @feature_keys ||= Set[]
  features.keys.each { |feature_name| @feature_keys << feature_name }

  self
end

Instance Method Details

#in_scale?(scale, chord_root_pitch:) ⇒ Boolean

Returns:

  • (Boolean)


70
71
72
# File 'lib/musa-dsl/music/chord-definition.rb', line 70

def in_scale?(scale, chord_root_pitch:)
  !pitches(chord_root_pitch).find { |chord_pitch| scale.note_of_pitch(chord_pitch).nil? }
end

#inspectObject Also known as: to_s



104
105
106
# File 'lib/musa-dsl/music/chord-definition.rb', line 104

def inspect
  "<ChordDefinition: name = #{@name} features = #{@features} pitch_offsets = #{@pitch_offsets}>"
end

#matches(pitches) ⇒ Object



96
97
98
99
100
101
102
# File 'lib/musa-dsl/music/chord-definition.rb', line 96

def matches(pitches)
  reduced_pitches = octave_reduce(pitches).uniq

  !!reduced_pitches.find do |candidate_root_pitch|
    reduced_pitches.sort == octave_reduce(pitches(candidate_root_pitch)).uniq.sort
  end
end

#named_pitches(elements_or_pitches, &block) ⇒ Object



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/musa-dsl/music/chord-definition.rb', line 74

def named_pitches(elements_or_pitches, &block)
  pitches = elements_or_pitches.collect do |element_or_pitch|
    [if block_given?
       yield element_or_pitch
     else
       element_or_pitch
     end,
     element_or_pitch]
  end.to_h

  root_pitch = pitches.keys.find do |candidate_root_pitch|
    candidate_pitches = pitches.keys.collect { |p| p - candidate_root_pitch }
    octave_reduce(candidate_pitches).uniq == octave_reduce(@pitch_offsets.values).uniq
  end

  # TODO: OJO: problema con las notas duplicadas, con la identificación de inversiones y con las notas a distancias de más de una octava

  pitches.collect do |pitch, element|
    [@pitch_names[pitch - root_pitch], [element]]
  end.to_h
end

#pitches(root_pitch) ⇒ Object



66
67
68
# File 'lib/musa-dsl/music/chord-definition.rb', line 66

def pitches(root_pitch)
  @pitch_offsets.values.collect { |offset| root_pitch + offset }
end