chords 0.3.2 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
- if !Chords::Fretboard::TUNINGS.has_key?(t.to_sym)
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"
@@ -87,7 +87,12 @@ module Chords
87
87
  @positions.hash
88
88
  end
89
89
 
90
- # fingering id, a unique identifier for fretboard/fingering combo
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
@@ -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), Bb.new(1), D.new(1)],
30
- :cross_c => [C.new(-1), G.new, C.new, G.new(1), C.new(1), Eb.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: 23
4
+ hash: 13
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 3
9
- - 2
10
- version: 0.3.2
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-07-23 00:00:00 +03:00
18
+ date: 2010-08-10 00:00:00 +03:00
19
19
  default_executable:
20
20
  dependencies: []
21
21