coltrane 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.bundle/config +2 -0
- data/.rspec +2 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +17 -0
- data/Gemfile.lock +164 -0
- data/Guardfile +71 -0
- data/LICENSE.txt +21 -0
- data/README.md +41 -0
- data/Rakefile +6 -0
- data/bin/_guard-core +17 -0
- data/bin/bundler +17 -0
- data/bin/coderay +17 -0
- data/bin/coltrane +11 -0
- data/bin/console +14 -0
- data/bin/erubis +17 -0
- data/bin/guard +17 -0
- data/bin/htmldiff +17 -0
- data/bin/kill-pry-rescue +17 -0
- data/bin/ldiff +17 -0
- data/bin/listen +17 -0
- data/bin/nokogiri +17 -0
- data/bin/pry +17 -0
- data/bin/rackup +17 -0
- data/bin/rails +17 -0
- data/bin/rake +17 -0
- data/bin/rdoc +17 -0
- data/bin/rescue +17 -0
- data/bin/ri +17 -0
- data/bin/rspec +17 -0
- data/bin/rubocop +17 -0
- data/bin/ruby-parse +17 -0
- data/bin/ruby-rewrite +17 -0
- data/bin/setup +8 -0
- data/bin/sprockets +17 -0
- data/bin/thor +17 -0
- data/bin/tilt +17 -0
- data/coltrane.gemspec +35 -0
- data/db/cache.sqlite3 +0 -0
- data/db/cache_test.sqlite3 +0 -0
- data/db/config.yml +11 -0
- data/db/schema.rb +30 -0
- data/lib/coltrane.rb +48 -0
- data/lib/coltrane/cadence.rb +4 -0
- data/lib/coltrane/chord.rb +81 -0
- data/lib/coltrane/chord_cache.rb +4 -0
- data/lib/coltrane/chord_quality.rb +48 -0
- data/lib/coltrane/classic_scales.rb +134 -0
- data/lib/coltrane/essential_guitar_chords.rb +82 -0
- data/lib/coltrane/fret_set.rb +0 -0
- data/lib/coltrane/guitar.rb +15 -0
- data/lib/coltrane/guitar_chord.rb +50 -0
- data/lib/coltrane/guitar_chord_finder.rb +98 -0
- data/lib/coltrane/guitar_note.rb +50 -0
- data/lib/coltrane/guitar_note_set.rb +61 -0
- data/lib/coltrane/guitar_representation.rb +96 -0
- data/lib/coltrane/guitar_string.rb +52 -0
- data/lib/coltrane/interval.rb +33 -0
- data/lib/coltrane/interval_sequence.rb +70 -0
- data/lib/coltrane/interval_set.rb +23 -0
- data/lib/coltrane/mode.rb +0 -0
- data/lib/coltrane/note.rb +98 -0
- data/lib/coltrane/note_set.rb +50 -0
- data/lib/coltrane/piano_representation.rb +58 -0
- data/lib/coltrane/pitch.rb +27 -0
- data/lib/coltrane/progression.rb +4 -0
- data/lib/coltrane/qualities.rb +115 -0
- data/lib/coltrane/scale.rb +139 -0
- data/lib/coltrane/scale_cache.rb +4 -0
- data/lib/coltrane/scale_chord.rb +4 -0
- data/lib/coltrane/version.rb +3 -0
- metadata +144 -0
data/coltrane.gemspec
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'coltrane/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "coltrane"
|
8
|
+
spec.version = Coltrane::VERSION
|
9
|
+
spec.authors = ["Pedro Maciel"]
|
10
|
+
spec.email = ["pedro@pedromaciel.com"]
|
11
|
+
|
12
|
+
spec.summary = %q{It deals with all sorts of calculations around music theory
|
13
|
+
and allows for graphical representations of it}
|
14
|
+
spec.homepage = "http://github.com/pedrozath/coltrane"
|
15
|
+
spec.license = "MIT"
|
16
|
+
|
17
|
+
# Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
|
18
|
+
# to allow pushing to a single host or delete this section to allow pushing to any host.
|
19
|
+
if spec.respond_to?(:metadata)
|
20
|
+
spec.metadata['allowed_push_host'] = "https://rubygems.org"
|
21
|
+
else
|
22
|
+
raise "RubyGems 2.0 or newer is required to protect against " \
|
23
|
+
"public gem pushes."
|
24
|
+
end
|
25
|
+
|
26
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
27
|
+
f.match(%r{^(test|spec|features)/})
|
28
|
+
end
|
29
|
+
spec.bindir = "exe"
|
30
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
31
|
+
spec.require_paths = ["lib"]
|
32
|
+
|
33
|
+
spec.add_development_dependency "bundler", "~> 1.14"
|
34
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
35
|
+
end
|
data/db/cache.sqlite3
ADDED
Binary file
|
Binary file
|
data/db/config.yml
ADDED
data/db/schema.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# This file is auto-generated from the current state of the database. Instead
|
2
|
+
# of editing this file, please use the migrations feature of Active Record to
|
3
|
+
# incrementally modify your database, and then regenerate this schema definition.
|
4
|
+
#
|
5
|
+
# Note that this schema.rb definition is the authoritative source for your
|
6
|
+
# database schema. If you need to create the application database on another
|
7
|
+
# system, you should be using db:schema:load, not running all the migrations
|
8
|
+
# from scratch. The latter is a flawed and unsustainable approach (the more migrations
|
9
|
+
# you'll amass, the slower it'll run and the greater likelihood for issues).
|
10
|
+
#
|
11
|
+
# It's strongly recommended that you check this file into your version control system.
|
12
|
+
|
13
|
+
ActiveRecord::Schema.define(version: 20170508162849) do
|
14
|
+
|
15
|
+
create_table "scale_caches", force: :cascade do |t|
|
16
|
+
t.string "interval_sequence"
|
17
|
+
t.string "tone"
|
18
|
+
end
|
19
|
+
|
20
|
+
create_table "chord_caches", force: :cascade do |t|
|
21
|
+
t.string "name"
|
22
|
+
t.integer "size"
|
23
|
+
end
|
24
|
+
|
25
|
+
create_table "scale_chords", force: :cascade do |t|
|
26
|
+
t.integer "scale_cache_id"
|
27
|
+
t.integer "chord_cache_id"
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
data/lib/coltrane.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
# $LOAD_PATH << __dir__
|
2
|
+
|
3
|
+
# require 'bundler'
|
4
|
+
|
5
|
+
# Bundler.require
|
6
|
+
|
7
|
+
# ActiveSupport::Inflector.inflections do |inflect|
|
8
|
+
# inflect.irregular 'cache', 'caches'
|
9
|
+
# end
|
10
|
+
|
11
|
+
# ActiveRecord::Base.establish_connection YAML.load_file("#{__dir__}/../db/config.yml")['production']
|
12
|
+
# require "#{__dir__}/../db/schema.rb"
|
13
|
+
|
14
|
+
require 'coltrane/cadence'
|
15
|
+
|
16
|
+
require 'coltrane/qualities'
|
17
|
+
require 'coltrane/chord_quality'
|
18
|
+
require 'coltrane/chord'
|
19
|
+
|
20
|
+
require 'coltrane/classic_scales'
|
21
|
+
require 'coltrane/fret_set'
|
22
|
+
|
23
|
+
# require 'coltrane/piano_representation'
|
24
|
+
# require 'coltrane/guitar_representation'
|
25
|
+
require 'coltrane/essential_guitar_chords'
|
26
|
+
require 'coltrane/guitar_chord_finder'
|
27
|
+
require 'coltrane/guitar_note_set'
|
28
|
+
require 'coltrane/guitar_chord'
|
29
|
+
require 'coltrane/guitar_note'
|
30
|
+
require 'coltrane/guitar_string'
|
31
|
+
require 'coltrane/guitar'
|
32
|
+
|
33
|
+
require 'coltrane/interval_sequence'
|
34
|
+
require 'coltrane/interval_set'
|
35
|
+
require 'coltrane/interval'
|
36
|
+
|
37
|
+
require 'coltrane/note_set'
|
38
|
+
require 'coltrane/note'
|
39
|
+
|
40
|
+
require 'coltrane/pitch'
|
41
|
+
require 'coltrane/progression'
|
42
|
+
require 'coltrane/scale'
|
43
|
+
require 'coltrane/mode'
|
44
|
+
|
45
|
+
# require 'coltrane/scale_chord'
|
46
|
+
# require 'coltrane/chord_cache'
|
47
|
+
# require 'coltrane/scale_cache'
|
48
|
+
# require 'terminal_input'
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module Coltrane
|
2
|
+
# It describe a chord
|
3
|
+
class Chord
|
4
|
+
attr_reader :root_note, :quality
|
5
|
+
|
6
|
+
def initialize(arg)
|
7
|
+
@root_note, @quality = case arg
|
8
|
+
when String then note_and_quality_from_name(arg)
|
9
|
+
when GuitarNoteSet then [arg.root_note, arg.chord_quality]
|
10
|
+
when Array
|
11
|
+
case arg[0]
|
12
|
+
when String then note_and_quality_from_notes(*arg.map{|a| Note.new(a)})
|
13
|
+
when Note then note_and_quality_from_notes(*arg)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def guitar_chords
|
19
|
+
GuitarChordFinder.by_chord(self)
|
20
|
+
end
|
21
|
+
|
22
|
+
def guitar_notes_for_root
|
23
|
+
root_note.guitar_notes
|
24
|
+
end
|
25
|
+
|
26
|
+
def name
|
27
|
+
return '—' if root_note.nil? || quality.nil?
|
28
|
+
"#{root_note.name}#{quality.name}"
|
29
|
+
end
|
30
|
+
|
31
|
+
def notes
|
32
|
+
quality.intervals.each_with_object([]) do |interval, notes|
|
33
|
+
notes << Note.new(root_note.number + interval)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def intervals
|
38
|
+
IntervalSequence.new(NoteSet.new(notes))
|
39
|
+
end
|
40
|
+
|
41
|
+
def on_guitar
|
42
|
+
name + "\n" +
|
43
|
+
NoteSet.new(notes).guitar_notes.render(root_note) + "\n\n"
|
44
|
+
end
|
45
|
+
|
46
|
+
def on_piano
|
47
|
+
PianoRepresentation.render_intervals(notes, root_note)
|
48
|
+
end
|
49
|
+
|
50
|
+
def size
|
51
|
+
notes.size
|
52
|
+
end
|
53
|
+
|
54
|
+
def scales
|
55
|
+
Scale.having_chord(self.name)
|
56
|
+
end
|
57
|
+
|
58
|
+
def next_inversion
|
59
|
+
Chord.new(notes.rotate(1))
|
60
|
+
end
|
61
|
+
|
62
|
+
def invert(n=1)
|
63
|
+
Chord.new(notes.rotate(n))
|
64
|
+
end
|
65
|
+
|
66
|
+
def previous_inversion
|
67
|
+
Chord.new(notes.rotate(-1))
|
68
|
+
end
|
69
|
+
|
70
|
+
protected
|
71
|
+
|
72
|
+
def note_and_quality_from_name(chord_name)
|
73
|
+
_, name, quality = chord_name.match(/([A-Z]#?)(.*)/).to_a
|
74
|
+
[Note.new(name), ChordQuality.new_from_string(quality)]
|
75
|
+
end
|
76
|
+
|
77
|
+
def note_and_quality_from_notes(*notes)
|
78
|
+
[notes.first, ChordQuality.new_from_notes(notes)]
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
module Coltrane
|
4
|
+
# It describe the quality of a chord, like maj7 or dim.
|
5
|
+
class ChordQuality
|
6
|
+
attr_reader :name
|
7
|
+
include Qualities
|
8
|
+
|
9
|
+
def initialize(interval_sequence)
|
10
|
+
if interval_sequence.class != IntervalSequence
|
11
|
+
interval_sequence = IntervalSequence.new(interval_sequence)
|
12
|
+
end
|
13
|
+
@name = find_chord_name(interval_sequence)
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.new_from_notes(notes)
|
17
|
+
note_set = NoteSet.new(notes) unless notes.class == NoteSet
|
18
|
+
new(note_set.interval_sequence.reordered)
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.new_from_pitches(*pitches)
|
22
|
+
notes = pitches.sort_by(&:number)
|
23
|
+
.collect(&:note)
|
24
|
+
.collect(&:name)
|
25
|
+
.uniq
|
26
|
+
|
27
|
+
new_from_notes(notes)
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.new_from_string(quality_string)
|
31
|
+
new(CHORD_QUALITIES[quality_string])
|
32
|
+
end
|
33
|
+
|
34
|
+
def intervals
|
35
|
+
CHORD_QUALITIES[name]
|
36
|
+
end
|
37
|
+
|
38
|
+
protected
|
39
|
+
|
40
|
+
def find_chord_name(note_intervals, inversion = 0)
|
41
|
+
inversion >= note_intervals.all.size && return
|
42
|
+
CHORD_QUALITIES.key(note_intervals.numbers) ||
|
43
|
+
CHORD_QUALITIES.key(note_intervals.numbers.sort) ||
|
44
|
+
find_chord_name(note_intervals.next_inversion, inversion + 1) ||
|
45
|
+
nil
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,134 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
|
3
|
+
module ClassicScales
|
4
|
+
|
5
|
+
SCALES = {
|
6
|
+
'Major' => [2,2,1,2,2,2,1],
|
7
|
+
'Natural Minor' => [2,1,2,2,1,2,2],
|
8
|
+
'Harmonic Minor' => [2,1,2,2,1,3,1],
|
9
|
+
'Hungarian Minor' => [2,1,2,1,1,3,1],
|
10
|
+
'Pentatonic Major' => [2,2,3,2,3],
|
11
|
+
'Pentatonic Minor' => [3,2,2,3,2],
|
12
|
+
'Blues Major' => [2,1,1,3,2,3],
|
13
|
+
'Blues Minor' => [3,2,1,1,3,2],
|
14
|
+
'Whole Tone' => [2,2,2,2,2,2]
|
15
|
+
}
|
16
|
+
|
17
|
+
def major(tone='C', mode=1)
|
18
|
+
new(*SCALES['Major'], tone: tone, mode: mode)
|
19
|
+
end
|
20
|
+
|
21
|
+
def natural_minor(tone='C', mode=1)
|
22
|
+
new(*SCALES['Natural Minor'], tone: tone, mode: mode)
|
23
|
+
end
|
24
|
+
|
25
|
+
def harmonic_minor(tone='C', mode=1)
|
26
|
+
new(*SCALES['Harmonic Minor'], tone: tone, mode: mode)
|
27
|
+
end
|
28
|
+
|
29
|
+
def hungarian_minor(tone='C', mode=1)
|
30
|
+
new(*SCALES['Hungarian Minor'], tone: tone, mode: mode)
|
31
|
+
end
|
32
|
+
|
33
|
+
def pentatonic_major(tone='C', mode=1)
|
34
|
+
new(*SCALES['Pentatonic Major'], tone: tone, mode: mode)
|
35
|
+
end
|
36
|
+
|
37
|
+
def pentatonic_minor(tone='C', mode=1)
|
38
|
+
new(*SCALES['Pentatonic Minor'], tone: tone, mode: mode)
|
39
|
+
end
|
40
|
+
|
41
|
+
def blues_major(tone='C', mode=1)
|
42
|
+
new(*SCALES['Blues Major'], tone: tone, mode: mode)
|
43
|
+
end
|
44
|
+
|
45
|
+
def blues_minor(tone='C', mode=1)
|
46
|
+
new(*SCALES['Blues Minor'], tone: tone, mode: mode)
|
47
|
+
end
|
48
|
+
|
49
|
+
def whole_tone(tone='C', mode=1)
|
50
|
+
new(*SCALES['Blues Minor'], tone: tone, mode: mode)
|
51
|
+
end
|
52
|
+
|
53
|
+
def chromatic(tone='C', mode=1)
|
54
|
+
new(*([1]*12), tone: tone, mode: mode)
|
55
|
+
end
|
56
|
+
|
57
|
+
def ionian(tone='C')
|
58
|
+
new(*SCALES['Major'], tone: tone, mode: 1)
|
59
|
+
end
|
60
|
+
|
61
|
+
def dorian(tone='C')
|
62
|
+
new(*SCALES['Major'], tone: tone, mode: 2)
|
63
|
+
end
|
64
|
+
|
65
|
+
def phrygian(tone='C')
|
66
|
+
new(*SCALES['Major'], tone: tone, mode: 3)
|
67
|
+
end
|
68
|
+
|
69
|
+
def lydian(tone='C')
|
70
|
+
new(*SCALES['Major'], tone: tone, mode: 4)
|
71
|
+
end
|
72
|
+
|
73
|
+
def mixolydian(tone='C')
|
74
|
+
new(*SCALES['Major'], tone: tone, mode: 5)
|
75
|
+
end
|
76
|
+
|
77
|
+
def aeolian(tone='C')
|
78
|
+
new(*SCALES['Major'], tone: tone, mode: 6)
|
79
|
+
end
|
80
|
+
|
81
|
+
def locrian(tone='C')
|
82
|
+
new(*SCALES['Major'], tone: tone, mode: 7)
|
83
|
+
end
|
84
|
+
|
85
|
+
def having_chord(chord)
|
86
|
+
puts "\nSearching #{chord} in scales:\n\n"
|
87
|
+
scale_name_size = SCALES.keys.map(&:size).max
|
88
|
+
chord = Chord.new(chord)
|
89
|
+
SCALES.each_with_object([]) do |scale_obj, results|
|
90
|
+
scale_name, intervals = scale_obj
|
91
|
+
print Paint[scale_name.ljust(scale_name_size), 'yellow']
|
92
|
+
Note.all.each do |note|
|
93
|
+
found_sth = false
|
94
|
+
print ' '
|
95
|
+
scale = Scale.new(*intervals, tone: note.name)
|
96
|
+
degree = scale.degree_of_chord(chord)
|
97
|
+
unless degree.nil?
|
98
|
+
found_sth = true
|
99
|
+
results << OpenStruct.new({ name: "#{note.name} #{scale_name}",
|
100
|
+
degree: degree,
|
101
|
+
scale: scale})
|
102
|
+
end
|
103
|
+
print Paint[note.name, found_sth ? 'yellow' : 'black']
|
104
|
+
end
|
105
|
+
print "\n"
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def having_notes(*notes)
|
110
|
+
puts "\nSearching #{notes.join(', ')} in scales:\n\n"
|
111
|
+
scale_name_size = SCALES.keys.map(&:size).max
|
112
|
+
notes = notes.map { |n| Note.new(n) }
|
113
|
+
SCALES.each_with_object([]) do |scale_obj, results|
|
114
|
+
scale_name, intervals = scale_obj
|
115
|
+
print Paint[scale_name.ljust(scale_name_size), 'yellow']
|
116
|
+
Note.all.each do |note|
|
117
|
+
found_sth = false
|
118
|
+
print ' '
|
119
|
+
scale = Scale.new(*intervals, tone: note.name)
|
120
|
+
notes_included = scale.include_notes?(*notes)
|
121
|
+
if notes_included == notes
|
122
|
+
found_sth = true
|
123
|
+
results << OpenStruct.new({
|
124
|
+
name: "#{note.name} #{scale_name}",
|
125
|
+
notes: notes_included
|
126
|
+
})
|
127
|
+
end
|
128
|
+
print Paint[note.name, found_sth ? 'yellow' : 'black']
|
129
|
+
print Paint["(#{notes_included.count || 0})", found_sth ? 'gray' : 'black']
|
130
|
+
end
|
131
|
+
print "\n"
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
module Coltrane
|
2
|
+
module EssentialGuitarChords
|
3
|
+
CHORDS = {
|
4
|
+
'C' => [nil, 3, 2, 0, 1, 0],
|
5
|
+
'Cm' => [nil, 10, 10, 8, 6, 4],
|
6
|
+
'Cmaj7' => [nil, 3, 5, 4, 5, nil],
|
7
|
+
'C7' => [nil, 10, 10, 9, 11, nil],
|
8
|
+
'Cm7' => [6,6,5,5,nil,nil],
|
9
|
+
'Cm7b5' => [nil, 3,4,3,4, nil],
|
10
|
+
'C#' => [nil,8,6,6,6,nil],
|
11
|
+
'C#m' => [nil,5,6,6,5,nil],
|
12
|
+
'C#maj7' => [4,4,3,5,nil,nil],
|
13
|
+
'C#7' => [nil, nil, 6,6,6,7],
|
14
|
+
'C#m7' => [nil, 2,2,1,2],
|
15
|
+
'C#m7b5' => [nil, 4,5,4,5, nil],
|
16
|
+
'D' => [5,5,4,nil,nil,nil],
|
17
|
+
'Dm' => [10,nil,nil,10,10,nil],
|
18
|
+
'Dmaj7' => [5,5,4,6,nil,nil],
|
19
|
+
'D7' => [5,5,4,5,nil,nil],
|
20
|
+
'Dm7' => [nil,3,3,2,3,nil],
|
21
|
+
'Dm7b5' => [],
|
22
|
+
'D#' => [],
|
23
|
+
'D#m' => [],
|
24
|
+
'D#maj7' => [],
|
25
|
+
'D#7' => [],
|
26
|
+
'D#m7' => [],
|
27
|
+
'D#m7b5' => [],
|
28
|
+
'E' => [],
|
29
|
+
'Em' => [],
|
30
|
+
'Emaj7' => [],
|
31
|
+
'E7' => [],
|
32
|
+
'Em7' => [],
|
33
|
+
'Em7b5' => [],
|
34
|
+
'F' => [],
|
35
|
+
'Fm' => [],
|
36
|
+
'Fmaj7' => [],
|
37
|
+
'F7' => [],
|
38
|
+
'Fm7' => [],
|
39
|
+
'Fm7b5' => [],
|
40
|
+
'F#' => [],
|
41
|
+
'F#m' => [],
|
42
|
+
'F#maj7' => [],
|
43
|
+
'F#7' => [],
|
44
|
+
'F#m7' => [],
|
45
|
+
'F#m7b5' => [],
|
46
|
+
'G' => [],
|
47
|
+
'Gm' => [],
|
48
|
+
'Gmaj7' => [],
|
49
|
+
'G7' => [],
|
50
|
+
'Gm7' => [],
|
51
|
+
'Gm7b5' => [],
|
52
|
+
'G#' => [],
|
53
|
+
'G#m' => [],
|
54
|
+
'G#maj7' => [],
|
55
|
+
'G#7' => [],
|
56
|
+
'G#m7' => [],
|
57
|
+
'G#m7b5' => [],
|
58
|
+
'A' => [],
|
59
|
+
'Am' => [],
|
60
|
+
'Amaj7' => [],
|
61
|
+
'A7' => [],
|
62
|
+
'Am7' => [],
|
63
|
+
'Am7b5' => [],
|
64
|
+
'A#' => [],
|
65
|
+
'A#m' => [],
|
66
|
+
'A#maj7' => [],
|
67
|
+
'A#7' => [],
|
68
|
+
'A#m7' => [],
|
69
|
+
'A#m7b5' => [],
|
70
|
+
'B' => [],
|
71
|
+
'Bm' => [],
|
72
|
+
'Bmaj7' => [],
|
73
|
+
'B7' => [],
|
74
|
+
'Bm7' => [],
|
75
|
+
'Bm7b5' => []
|
76
|
+
}
|
77
|
+
|
78
|
+
def [](name)
|
79
|
+
GuitarChord.new_from_frets(*CHORDS[name])
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|