Class: Chords::Fretboard

Inherits:
Object
  • Object
show all
Defined in:
lib/chords/fretboard.rb

Constant Summary collapse

DEFAULT_FRETS =
14
TUNINGS =
{
 # Some usual ones
 :standard => [E.new, A.new, D.new, G.new(1), B.new(1), E.new(2)],
 :drop_d   => [D.new(-1), A.new, D.new, G.new(1), B.new(1), E.new(2)],
 :ddd      => [D.new(-1), A.new, D.new, G.new(1), B.new(1), D.new(1)], # double-dropped D
 :dadgad   => [D.new(-1), A.new, D.new, G.new(1), A.new(1), D.new(1)],
 
 # Major open tunings
 :open_e   => [E.new, B.new, E.new(1), Gs.new(1), B.new(1), E.new(2)],
 :open_d   => [D.new(-1), A.new, D.new, Fs.new(1), A.new(1), D.new(1)],
 :open_a   => [E.new, A.new, E.new(1), A.new(1), Cs.new(1), E.new(2)],
 :open_g   => [D.new(-1), G.new, D.new, G.new(1), B.new(1), D.new(1)],
 :open_c   => [C.new(-1), G.new, C.new, G.new(1), C.new(1), E.new(2)],
 
 # Cross-note tunings
 :cross_e  => [E.new, B.new, E.new(1), G.new(1), B.new(1), E.new(2)],
 :cross_d  => [D.new(-1), A.new, D.new, F.new(1), A.new(1), D.new(1)],
 :cross_a  => [E.new, A.new, E.new(1), A.new(1), C.new(1), E.new(2)],
 :cross_g  => [D.new(-1), G.new, D.new, G.new(1), As.new(1), D.new(1)],
 :cross_c  => [C.new(-1), G.new, C.new, G.new(1), C.new(1), Ds.new(1)],
 
 # Modal tunings
 :cacgce   => [C.new(-1), A.new, C.new, G.new(1), C.new(1), E.new(2)],
 :e_modal  => [E.new, B.new, E.new(1), E.new(1), B.new(1), E.new(2)],
 :g_modal  => [G.new, G.new, D.new, G.new(1), B.new(1), D.new(1)],
 :gsus2    => [D.new(-1), G.new, D.new, G.new(1), A.new(1), D.new(1)],
 :c15      => [C.new(-1), G.new, D.new, G.new(1), C.new(1), D.new(1)],
 
 # "Extended chord" tunings
 :dmaj7    => [D.new(-1), A.new, D.new, Fs.new(1), A.new(1), Cs.new(1)],
 
 # Other instruments
 :mandolin => [G.new, D.new, A.new(1), E.new(2)],
 :ukulele  => [G.new, C.new, E.new(1), A.new(1)],
 :banjo    => [G.new, D.new, G.new(1), B.new(1), D.new(1)]
}

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(open_notes, frets = DEFAULT_FRETS, formatter_class = TextFormatter) ⇒ Fretboard

Returns a new instance of Fretboard.



50
51
52
53
# File 'lib/chords/fretboard.rb', line 50

def initialize(open_notes, frets=DEFAULT_FRETS, formatter_class=TextFormatter)
  @open_notes, @frets = open_notes, frets
  @formatter = formatter_class.new(self)
end

Instance Attribute Details

#formatterObject (readonly)

Returns the value of attribute formatter.



48
49
50
# File 'lib/chords/fretboard.rb', line 48

def formatter
  @formatter
end

#fretsObject (readonly)

Returns the value of attribute frets.



48
49
50
# File 'lib/chords/fretboard.rb', line 48

def frets
  @frets
end

#open_notesObject (readonly)

Returns the value of attribute open_notes.



48
49
50
# File 'lib/chords/fretboard.rb', line 48

def open_notes
  @open_notes
end

Class Method Details

.method_missing(meth, *args) ⇒ Object



79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/chords/fretboard.rb', line 79

def self.method_missing(meth, *args)
  if TUNINGS.has_key?(meth)
    Fretboard.new(TUNINGS[meth], (args[0] || DEFAULT_FRETS),
                  args[1] || TextFormatter)
                  
  elsif meth.to_s =~ /^[efgabhcds]+$/
    Fretboard.new_by_string(meth.to_s, (args[0] || DEFAULT_FRETS),
                            args[1] || TextFormatter)
  
  else
    super
  end
end

.new_by_string(open_notes_str, frets = DEFAULT_FRETS, formatter_class = TextFormatter) ⇒ Object

Creates a new fretboard, parsing the open notes from the open_notes_str. All ‘b’:s are interpreted as B-notes, not flats, so use ‘s’ for sharps instead.



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/chords/fretboard.rb', line 57

def self.new_by_string(open_notes_str, frets=DEFAULT_FRETS, 
                       formatter_class=TextFormatter)
  open_notes_str.upcase!
  raise "Provide at least 3 strings" if open_notes_str.scan(/[^S]/m).size < 3
  open_notes = []
  
  open_notes_str.scan(/./m).each do |chr|
    if chr == 'S'
      raise "Invalid tuning!" if open_notes.empty?
      open_notes[open_notes.size-1] += 1
    else
      open_notes << Chords.const_get(chr).new
    end
  end
  
  (1..(open_notes.size-1)).each do |i|
    open_notes[i] += 12 while open_notes[i-1] > open_notes[i]
  end
  
  Fretboard.new(open_notes, frets, formatter_class)
end

.parse_positions(position_str, no_of_strings) ⇒ Object

parse positions from a string, for example ‘022100’ returns [max_fret_distance, positions], where max_fret_distance has a minimum of 2



125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# File 'lib/chords/fretboard.rb', line 125

def self.parse_positions(position_str, no_of_strings)
  position_str.downcase!
  positions = position_str.scan(/./).map{|pos| pos == 'x' ? nil : pos.to_i}
  over_tens = positions.size - no_of_strings
  
  while over_tens > 0
    idx = positions.index{|p| !p.nil? and p > 0 and p < 3}
    if idx
      positions[idx] = "#{positions[idx]}#{positions[idx+1]}".to_i
      positions.delete_at(idx+1)
    end
    over_tens -= 1
  end
  
  positions
end

Method for printing a single fingering using Fingering#fid, which contains also the tuning/fretboard used. Doesn’t handle big max_fret_distances right.



105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/chords/fretboard.rb', line 105

def self.print_fingering_by_fid(fid, opts={}, formatter_class=TextFormatter)
  fingering_part = fid.split(/[efgabhcds]/).last
  raise "Invalid fingering" if fingering_part.nil?
  tuning_part = fid.sub(fingering_part, '')
  
  fretboard = Fretboard.new_by_string(tuning_part, 50, formatter_class)
  
  positions = parse_positions(fingering_part, fretboard.open_notes.size)
  
  fingering = Fingering.new(fretboard, positions)
  max_fret_dist = fingering.max_fret_distance
  max_fret_dist = 2 if max_fret_dist < 2
                                                 
  fretboard.formatter.print('', [fingering],
                            opts.merge(:max_fret_distance => max_fret_dist))
end

Instance Method Details

#find(chord, opts = {}) ⇒ Object



93
94
95
# File 'lib/chords/fretboard.rb', line 93

def find(chord, opts={})
  Fingering.find_variations(self, chord, opts)
end


97
98
99
100
# File 'lib/chords/fretboard.rb', line 97

def print(chord, opts={})
  fingerings = find(chord, opts)
  @formatter.print(chord.title, fingerings, opts)
end