Class: Musa::Chords::ChordDefinition
- Defined in:
- lib/musa-dsl/music/chord-definition.rb
Overview
Chord template defining structure and features.
ChordDefinition is a template that specifies the intervals and characteristics of a chord type. It's defined once and used to create many chord instances.
Components
- Name: Unique identifier (:maj, :min, :dom7, etc.)
- Offsets: Semitone intervals from root ({ root: 0, third: 4, fifth: 7 })
- Features: Characteristics (quality: :major, size: :triad)
Registration
Chord definitions are registered globally:
ChordDefinition.register :maj,
quality: :major,
size: :triad,
offsets: { root: 0, third: 4, fifth: 7 }
Finding Definitions
By name:
ChordDefinition[:maj] # => <ChordDefinition :maj>
By features:
ChordDefinition.find_by_features(quality: :major, size: :triad)
# => [<ChordDefinition :maj>]
By pitches:
ChordDefinition.find_by_pitches([60, 64, 67]) # C E G
# => <ChordDefinition :maj>
Instance Attribute Summary collapse
-
#features ⇒ Hash{Symbol => Symbol}
readonly
Chord features (quality, size, etc.).
-
#name ⇒ Symbol
readonly
Chord name.
-
#pitch_names ⇒ Hash{Integer => Symbol}
readonly
Position names by semitone offset.
-
#pitch_offsets ⇒ Hash{Symbol => Integer}
readonly
Semitone offsets by position name.
Class Method Summary collapse
-
.feature_key_of(feature_value) ⇒ Symbol
Returns feature key for a feature value.
-
.feature_keys ⇒ Set<Symbol>
Returns all registered feature keys.
-
.feature_values ⇒ Array<Symbol>
Returns all registered feature values.
-
.features_from(values = nil, hash = nil) ⇒ Hash
Converts feature values to feature hash.
-
.find_by_features(*values, **hash) ⇒ Array<ChordDefinition>
Finds definitions matching specified features.
-
.find_by_pitches(pitches) ⇒ ChordDefinition?
Finds chord definition matching a set of pitches.
-
.get(name) ⇒ ChordDefinition?
(also: [])
Retrieves a registered chord definition by name.
-
.register(name, offsets:, **features) ⇒ self
Registers a new chord definition.
Instance Method Summary collapse
-
#in_scale?(scale, chord_root_pitch:) ⇒ Boolean
Checks if chord fits within a scale.
-
#initialize(name, offsets:, **features) ⇒ ChordDefinition
constructor
private
Creates a chord definition.
-
#inspect ⇒ String
(also: #to_s)
Returns string representation.
-
#matches(pitches) ⇒ Boolean
Checks if pitches match this chord definition.
-
#named_pitches(elements_or_pitches) {|element| ... } ⇒ Hash{Symbol => Array}
private
Maps elements to named chord positions.
-
#pitches(root_pitch) ⇒ Array<Integer>
Calculates chord pitches from root pitch.
Constructor Details
#initialize(name, offsets:, **features) ⇒ ChordDefinition
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Creates a chord definition.
235 236 237 238 239 240 241 |
# File 'lib/musa-dsl/music/chord-definition.rb', line 235 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
#features ⇒ Hash{Symbol => Symbol} (readonly)
Chord features (quality, size, etc.).
249 250 251 |
# File 'lib/musa-dsl/music/chord-definition.rb', line 249 def features @features end |
#name ⇒ Symbol (readonly)
Chord name.
245 246 247 |
# File 'lib/musa-dsl/music/chord-definition.rb', line 245 def name @name end |
#pitch_names ⇒ Hash{Integer => Symbol} (readonly)
Position names by semitone offset.
257 258 259 |
# File 'lib/musa-dsl/music/chord-definition.rb', line 257 def pitch_names @pitch_names end |
#pitch_offsets ⇒ Hash{Symbol => Integer} (readonly)
Semitone offsets by position name.
253 254 255 |
# File 'lib/musa-dsl/music/chord-definition.rb', line 253 def pitch_offsets @pitch_offsets end |
Class Method Details
.feature_key_of(feature_value) ⇒ Symbol
Returns feature key for a feature value.
210 211 212 |
# File 'lib/musa-dsl/music/chord-definition.rb', line 210 def self.feature_key_of(feature_value) @features_by_value[feature_value] end |
.feature_keys ⇒ Set<Symbol>
Returns all registered feature keys.
224 225 226 |
# File 'lib/musa-dsl/music/chord-definition.rb', line 224 def self.feature_keys @feature_keys end |
.feature_values ⇒ Array<Symbol>
Returns all registered feature values.
217 218 219 |
# File 'lib/musa-dsl/music/chord-definition.rb', line 217 def self.feature_values @features_by_value.keys end |
.features_from(values = nil, hash = nil) ⇒ Hash
Converts feature values to feature hash.
182 183 184 185 186 187 188 189 190 |
# File 'lib/musa-dsl/music/chord-definition.rb', line 182 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) ⇒ Array<ChordDefinition>
Finds definitions matching specified features.
201 202 203 204 |
# File 'lib/musa-dsl/music/chord-definition.rb', line 201 def self.find_by_features(*values, **hash) features = features_from(values, hash) @definitions.values.select { |d| features <= d.features } end |
.find_by_pitches(pitches) ⇒ ChordDefinition?
Finds chord definition matching a set of pitches.
Identifies chord by comparing pitch intervals, accounting for octave reduction.
169 170 171 |
# File 'lib/musa-dsl/music/chord-definition.rb', line 169 def self.find_by_pitches(pitches) @definitions.values.find { |d| d.matches(pitches) } end |
.get(name) ⇒ ChordDefinition? Also known as: []
Retrieves a registered chord definition by name.
116 117 118 |
# File 'lib/musa-dsl/music/chord-definition.rb', line 116 def self.get(name) @definitions[name] end |
.register(name, offsets:, **features) ⇒ self
Registers a new chord definition.
Creates and registers a chord definition with specified intervals and features. The definition becomes available globally for chord creation.
145 146 147 148 149 150 151 152 153 154 155 156 157 158 |
# File 'lib/musa-dsl/music/chord-definition.rb', line 145 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.each_key { |feature_name| @feature_keys << feature_name } self end |
Instance Method Details
#in_scale?(scale, chord_root_pitch:) ⇒ Boolean
Checks if chord fits within a scale.
278 279 280 |
# File 'lib/musa-dsl/music/chord-definition.rb', line 278 def in_scale?(scale, chord_root_pitch:) !pitches(chord_root_pitch).find { |chord_pitch| scale.note_of_pitch(chord_pitch).nil? } end |
#inspect ⇒ String Also known as: to_s
Returns string representation.
332 333 334 |
# File 'lib/musa-dsl/music/chord-definition.rb', line 332 def inspect "<ChordDefinition: name = #{@name} features = #{@features} pitch_offsets = #{@pitch_offsets}>" end |
#matches(pitches) ⇒ Boolean
Checks if pitches match this chord definition.
Compares octave-reduced pitch sets to determine if they form this chord.
321 322 323 324 325 326 327 |
# File 'lib/musa-dsl/music/chord-definition.rb', line 321 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) {|element| ... } ⇒ Hash{Symbol => Array}
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Maps elements to named chord positions.
289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 |
# File 'lib/musa-dsl/music/chord-definition.rb', line 289 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) ⇒ Array<Integer>
Calculates chord pitches from root pitch.
266 267 268 |
# File 'lib/musa-dsl/music/chord-definition.rb', line 266 def pitches(root_pitch) @pitch_offsets.values.collect { |offset| root_pitch + offset } end |