Class: Coltrane::Representation::Guitar::Chord

Inherits:
Object
  • Object
show all
Includes:
Comparable
Defined in:
lib/coltrane/representation/guitar/chord.rb

Overview

This class represents a group of guitar notes, strummed at the same time

Constant Summary collapse

MAX_FRET_SPAN =
3

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(target_chord, guitar_notes: [], free_fingers: 4, barre: nil, guitar:) ⇒ Chord

Returns a new instance of Chord.



20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/coltrane/representation/guitar/chord.rb', line 20

def initialize(target_chord,
               guitar_notes: [],
               free_fingers: 4,
               barre: nil,
               guitar:)

  @target_chord = target_chord
  @guitar_notes = guitar_notes
  @free_fingers = free_fingers
  @guitar       = guitar
  @barre        = barre
end

Instance Attribute Details

#barreObject

Returns the value of attribute barre.



9
10
11
# File 'lib/coltrane/representation/guitar/chord.rb', line 9

def barre
  @barre
end

#free_fingersObject (readonly)

Returns the value of attribute free_fingers.



9
10
11
# File 'lib/coltrane/representation/guitar/chord.rb', line 9

def free_fingers
  @free_fingers
end

#guitarObject (readonly)

Returns the value of attribute guitar.



9
10
11
# File 'lib/coltrane/representation/guitar/chord.rb', line 9

def guitar
  @guitar
end

#guitar_notesObject (readonly)

Returns the value of attribute guitar_notes.



9
10
11
# File 'lib/coltrane/representation/guitar/chord.rb', line 9

def guitar_notes
  @guitar_notes
end

#target_chordObject (readonly)

Returns the value of attribute target_chord.



9
10
11
# File 'lib/coltrane/representation/guitar/chord.rb', line 9

def target_chord
  @target_chord
end

Class Method Details

.find(chord, guitar:) ⇒ Object



13
14
15
16
17
18
# File 'lib/coltrane/representation/guitar/chord.rb', line 13

def self.find(chord, guitar:)
  new(chord, guitar: guitar)
  .fetch_descendant_chords
  .sort
  .reverse
end

Instance Method Details

#<=>(other) ⇒ Object



37
38
39
# File 'lib/coltrane/representation/guitar/chord.rb', line 37

def <=>(other)
  rank <=> other.rank
end

#analysisObject



48
49
50
51
52
53
54
55
# File 'lib/coltrane/representation/guitar/chord.rb', line 48

def analysis
  {
    completeness: completeness,
    fullness:     fullness,
    easyness:     easyness,
    spreadness:   spreadness
  }
end

#barre?Boolean

Returns:

  • (Boolean)


73
74
75
# File 'lib/coltrane/representation/guitar/chord.rb', line 73

def barre?
  !@barre.nil?
end

#completenessObject



61
62
63
# File 'lib/coltrane/representation/guitar/chord.rb', line 61

def completeness
  (target_chord.notes.size.to_f - notes_left.size) / target_chord.notes.size
end

#easynessObject



65
66
67
# File 'lib/coltrane/representation/guitar/chord.rb', line 65

def easyness
  frets.count(0).to_f / guitar_notes.size
end

#fetch_descendant_chordsObject



77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/coltrane/representation/guitar/chord.rb', line 77

def fetch_descendant_chords
  return [self] if guitar_notes.size >= guitar.strings.size
  possible_new_notes(notes_available.positive?).reduce([]) do |memo, n|
    barre = n.fret if guitar_notes.last == n.fret
    fingers_change = n.fret == barre || n.fret.zero? ? 0 : 1
    next memo if (free_fingers - fingers_change).negative?
    self.class.new(target_chord,
      guitar_notes: guitar_notes + [n],
      free_fingers: free_fingers - fingers_change,
      guitar: guitar,
      barre: barre
    ).fetch_descendant_chords + memo
  end
end

#fret_expansion_rangeObject



151
152
153
154
# File 'lib/coltrane/representation/guitar/chord.rb', line 151

def fret_expansion_range
  (lowest_possible_fret..highest_possible_fret).to_a +
    [(0 unless barre?)].compact
end

#fret_rangeObject



135
136
137
# File 'lib/coltrane/representation/guitar/chord.rb', line 135

def fret_range
  (lowest_fret..highest_fret)
end

#fretsObject



119
120
121
# File 'lib/coltrane/representation/guitar/chord.rb', line 119

def frets
  @frets ||= guitar_notes.map(&:fret)
end

#fullnessObject



69
70
71
# File 'lib/coltrane/representation/guitar/chord.rb', line 69

def fullness
  (guitar.strings.size.to_f - frets.count(nil)) / guitar.strings.size
end

#highest_fretObject



131
132
133
# File 'lib/coltrane/representation/guitar/chord.rb', line 131

def highest_fret
  non_zero_frets.max || 0
end

#highest_possible_fretObject



143
144
145
# File 'lib/coltrane/representation/guitar/chord.rb', line 143

def highest_possible_fret
  [(possible_span + (highest_fret == 0 ? guitar.frets : highest_fret)), guitar.frets].min
end

#lowest_fretObject



127
128
129
# File 'lib/coltrane/representation/guitar/chord.rb', line 127

def lowest_fret
  non_zero_frets.any? ? non_zero_frets.min : 0
end

#lowest_possible_fretObject



139
140
141
# File 'lib/coltrane/representation/guitar/chord.rb', line 139

def lowest_possible_fret
  lowest_fret.zero? ? 0 : [(lowest_fret - possible_span), 0].max
end

#max_fret_spanObject



33
34
35
# File 'lib/coltrane/representation/guitar/chord.rb', line 33

def max_fret_span
  MAX_FRET_SPAN
end

#non_zero_fretsObject



123
124
125
# File 'lib/coltrane/representation/guitar/chord.rb', line 123

def non_zero_frets
  frets.reject { |f| f.nil? || f.zero? }
end

#notesObject



115
116
117
# File 'lib/coltrane/representation/guitar/chord.rb', line 115

def notes
  guitar_notes.map(&:pitch)
end

#notes_availableObject



92
93
94
# File 'lib/coltrane/representation/guitar/chord.rb', line 92

def notes_available
  strings_available - notes_left.size
end

#notes_leftObject



100
101
102
103
104
105
106
107
108
109
# File 'lib/coltrane/representation/guitar/chord.rb', line 100

def notes_left
  @notes_left ||= begin
                    target_chord.notes - Theory::NoteSet[
                    *guitar_notes.map do |n|
                      next if n.pitch.nil?
                      n.pitch.pitch_class
                    end
                  ]
                  end
end

#possible_spanObject



147
148
149
# File 'lib/coltrane/representation/guitar/chord.rb', line 147

def possible_span
  MAX_FRET_SPAN - fret_range.size
end

#rankObject



41
42
43
44
45
46
# File 'lib/coltrane/representation/guitar/chord.rb', line 41

def rank
  +completeness * 10_000 +
  +fullness     * 1000 +
  -spreadness   * 100 +
  +easyness     * 1
end

#spreadnessObject



57
58
59
# File 'lib/coltrane/representation/guitar/chord.rb', line 57

def spreadness
  fret_range.size.to_f / MAX_FRET_SPAN
end

#strings_availableObject



96
97
98
# File 'lib/coltrane/representation/guitar/chord.rb', line 96

def strings_available
  guitar.strings.size - guitar_notes.size
end

#target_notesObject



111
112
113
# File 'lib/coltrane/representation/guitar/chord.rb', line 111

def target_notes
  notes_left.any? ? notes_left : target_chord.notes
end

#to_sObject



156
157
158
# File 'lib/coltrane/representation/guitar/chord.rb', line 156

def to_s
  guitar_notes.map { |n| n.fret.nil? ? 'x' : n.fret }.join('-')
end

#voicingObject



160
161
162
# File 'lib/coltrane/representation/guitar/chord.rb', line 160

def voicing
  Coltrane::Voicing.new(pitches: guitar_notes.map(&:pitch).compact)
end