chords 0.3.2 → 0.4.1
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/chords/command_line_parser.rb +5 -2
- data/lib/chords/fingering.rb +6 -1
- data/lib/chords/fretboard.rb +61 -3
- metadata +5 -5
@@ -43,10 +43,11 @@ module Chords
|
|
43
43
|
|
44
44
|
@opts.on("-t", "--tuning TUNING",
|
45
45
|
"Tuning to use. See -l for list of available tunings and chords.") do |t|
|
46
|
-
|
46
|
+
begin
|
47
|
+
@tuning = Fretboard.send(t.downcase).open_notes
|
48
|
+
rescue Exception => e
|
47
49
|
raise OptionParser::ParseError.new("Invalid tuning")
|
48
50
|
end
|
49
|
-
@tuning = Chords::Fretboard::TUNINGS[t.to_sym]
|
50
51
|
end
|
51
52
|
|
52
53
|
@opts.on("--pdf", "Output to pdf. Requires Prawn.") do
|
@@ -109,6 +110,8 @@ module Chords
|
|
109
110
|
Chords::Fretboard::TUNINGS.each do |key, value|
|
110
111
|
out += "#{key.to_s.ljust(12, ' ')}: #{value.map{|n| n.class.to_s.gsub(/.*::/,'')}.join(',')}\n"
|
111
112
|
end
|
113
|
+
out += "\nYou can also give a tuning as a string of notes, e.g. 'eadgbe'. Note that "+
|
114
|
+
"all 'b':s are considered notes, not flats, so use 's':s for sharps instead.\n"
|
112
115
|
out += "\nChords:\n======\n"
|
113
116
|
Chords::ChordFactory::CHORDS.each do |key, value|
|
114
117
|
out += "#{key}\n"
|
data/lib/chords/fingering.rb
CHANGED
@@ -87,7 +87,12 @@ module Chords
|
|
87
87
|
@positions.hash
|
88
88
|
end
|
89
89
|
|
90
|
-
#
|
90
|
+
# Fingering id, a unique identifier for fretboard/fingering combo.
|
91
|
+
# Actually, fid is not unique if max_fret_distance >= 9,
|
92
|
+
# as positions [0,10,0,0,1,0] and [0,1,0,0,0,10] produce the
|
93
|
+
# same fid (if the tuning is the same).
|
94
|
+
# However, max_fret_distance of 9 or greater is not
|
95
|
+
# realistic.
|
91
96
|
def fid
|
92
97
|
@fretboard.open_notes.map{|n| n.class.title}.to_s +
|
93
98
|
@positions.map{|pos| pos.nil? ? 'x' : pos}.to_s
|
data/lib/chords/fretboard.rb
CHANGED
@@ -26,8 +26,8 @@ module Chords
|
|
26
26
|
:cross_e => [E.new, B.new, E.new(1), G.new(1), B.new(1), E.new(2)],
|
27
27
|
:cross_d => [D.new(-1), A.new, D.new, F.new(1), A.new(1), D.new(1)],
|
28
28
|
:cross_a => [E.new, A.new, E.new(1), A.new(1), C.new(1), E.new(2)],
|
29
|
-
:cross_g => [D.new(-1), G.new, D.new, G.new(1),
|
30
|
-
:cross_c => [C.new(-1), G.new, C.new, G.new(1), C.new(1),
|
29
|
+
:cross_g => [D.new(-1), G.new, D.new, G.new(1), As.new(1), D.new(1)],
|
30
|
+
:cross_c => [C.new(-1), G.new, C.new, G.new(1), C.new(1), Ds.new(1)],
|
31
31
|
|
32
32
|
# Modal tunings
|
33
33
|
:cacgce => [C.new(-1), A.new, C.new, G.new(1), C.new(1), E.new(2)],
|
@@ -47,15 +47,44 @@ module Chords
|
|
47
47
|
|
48
48
|
attr_reader :frets, :open_notes, :formatter
|
49
49
|
|
50
|
-
def initialize(open_notes, frets, formatter_class=TextFormatter)
|
50
|
+
def initialize(open_notes, frets=DEFAULT_FRETS, formatter_class=TextFormatter)
|
51
51
|
@open_notes, @frets = open_notes, frets
|
52
52
|
@formatter = formatter_class.new(self)
|
53
53
|
end
|
54
54
|
|
55
|
+
# Creates a new fretboard, parsing the open notes from the open_notes_str.
|
56
|
+
# All 'b':s are interpreted as B-notes, not flats, so use 's' for sharps instead.
|
57
|
+
def self.new_by_string(open_notes_str, frets=DEFAULT_FRETS,
|
58
|
+
formatter_class=TextFormatter)
|
59
|
+
open_notes_str.upcase!
|
60
|
+
raise "Provide at least 3 strings" if open_notes_str.scan(/[^S]/m).size < 3
|
61
|
+
open_notes = []
|
62
|
+
|
63
|
+
open_notes_str.scan(/./m).each do |chr|
|
64
|
+
if chr == 'S'
|
65
|
+
raise "Invalid tuning!" if open_notes.empty?
|
66
|
+
open_notes[open_notes.size-1] += 1
|
67
|
+
else
|
68
|
+
open_notes << Chords.const_get(chr).new
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
(1..(open_notes.size-1)).each do |i|
|
73
|
+
open_notes[i] += 12 while open_notes[i-1] > open_notes[i]
|
74
|
+
end
|
75
|
+
|
76
|
+
Fretboard.new(open_notes, frets, formatter_class)
|
77
|
+
end
|
78
|
+
|
55
79
|
def self.method_missing(meth, *args)
|
56
80
|
if TUNINGS.has_key?(meth)
|
57
81
|
Fretboard.new(TUNINGS[meth], (args[0] || DEFAULT_FRETS),
|
58
82
|
args[1] || TextFormatter)
|
83
|
+
|
84
|
+
elsif meth.to_s =~ /^[efgabhcds]+$/
|
85
|
+
Fretboard.new_by_string(meth.to_s, (args[0] || DEFAULT_FRETS),
|
86
|
+
args[1] || TextFormatter)
|
87
|
+
|
59
88
|
else
|
60
89
|
super
|
61
90
|
end
|
@@ -70,5 +99,34 @@ module Chords
|
|
70
99
|
@formatter.print(chord.title, fingerings, opts)
|
71
100
|
end
|
72
101
|
|
102
|
+
# Method for printing a single fingering using Fingering#fid,
|
103
|
+
# which contains also the tuning/fretboard used.
|
104
|
+
# Doesn't handle big max_fret_distances right.
|
105
|
+
def self.print_fingering_by_fid(fid, opts={}, formatter_class=TextFormatter)
|
106
|
+
fingering_part = fid.split(/[efgabhcds]/).last
|
107
|
+
raise "Invalid fingering" if fingering_part.nil?
|
108
|
+
tuning_part = fid.sub(fingering_part, '')
|
109
|
+
|
110
|
+
fretboard = Fretboard.new_by_string(tuning_part, 50, formatter_class)
|
111
|
+
over_tens = fingering_part.size - fretboard.open_notes.size
|
112
|
+
|
113
|
+
i=0
|
114
|
+
positions = []
|
115
|
+
|
116
|
+
while i < fingering_part.size
|
117
|
+
fp = fingering_part[i,1]
|
118
|
+
fp == 'x' ? pos = nil : pos = fp.to_i
|
119
|
+
if over_tens > 0 and pos and pos < 4
|
120
|
+
over_tens -= 1
|
121
|
+
i += 2
|
122
|
+
pos = "#{pos}#{fingering_part[i+1,1]}".to_i
|
123
|
+
else
|
124
|
+
i += 1
|
125
|
+
end
|
126
|
+
positions << pos
|
127
|
+
end
|
128
|
+
fretboard.formatter.print('', [Fingering.new(fretboard, positions)], opts)
|
129
|
+
end
|
130
|
+
|
73
131
|
end
|
74
132
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: chords
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 13
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 0.
|
8
|
+
- 4
|
9
|
+
- 1
|
10
|
+
version: 0.4.1
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Antti Hakala
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-
|
18
|
+
date: 2010-08-10 00:00:00 +03:00
|
19
19
|
default_executable:
|
20
20
|
dependencies: []
|
21
21
|
|