coltrane 0.0.2 → 1.0.0
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 +5 -5
- data/.gitignore +2 -0
- data/.ruby-version +1 -0
- data/Gemfile +15 -10
- data/Gemfile.lock +47 -128
- data/README.md +30 -8
- data/Rakefile +0 -4
- data/bin/bundle +105 -0
- data/bin/byebug +29 -0
- data/bin/coderay +12 -0
- data/bin/coltrane +25 -7
- data/bin/htmldiff +12 -0
- data/bin/kill-pry-rescue +12 -0
- data/bin/ldiff +12 -0
- data/bin/pry +12 -0
- data/bin/rake +12 -0
- data/bin/rescue +12 -0
- data/bin/rspec +12 -0
- data/bin/rubocop +12 -0
- data/bin/ruby-parse +12 -0
- data/bin/ruby-rewrite +12 -0
- data/exe/coltrane +173 -0
- data/lib/cli/bass_guitar.rb +9 -0
- data/lib/cli/chord.rb +24 -0
- data/lib/cli/errors.rb +28 -0
- data/lib/cli/guitar.rb +55 -0
- data/lib/cli/notes.rb +18 -0
- data/lib/cli/piano.rb +54 -0
- data/lib/cli/representation.rb +47 -0
- data/lib/cli/scale.rb +48 -0
- data/lib/cli/text.rb +13 -0
- data/lib/cli/ukulele.rb +11 -0
- data/lib/coltrane-cli.rb +12 -0
- data/lib/coltrane.rb +16 -31
- data/lib/coltrane/cache.rb +34 -0
- data/lib/coltrane/chord.rb +28 -41
- data/lib/coltrane/chord_quality.rb +14 -39
- data/lib/coltrane/classic_progressions.rb +37 -0
- data/lib/coltrane/classic_scales.rb +92 -118
- data/lib/coltrane/errors.rb +54 -0
- data/lib/coltrane/interval.rb +25 -17
- data/lib/coltrane/interval_sequence.rb +57 -27
- data/lib/coltrane/note.rb +44 -30
- data/lib/coltrane/note_set.rb +37 -22
- data/lib/coltrane/piano_representation.rb +0 -58
- data/lib/coltrane/pitch.rb +12 -3
- data/lib/coltrane/progression.rb +31 -0
- data/lib/coltrane/qualities.rb +115 -114
- data/lib/coltrane/roman_chord.rb +36 -0
- data/lib/coltrane/scale.rb +85 -77
- data/lib/coltrane/version.rb +1 -1
- data/lib/core_ext.rb +12 -0
- data/pkg/coltrane-0.0.2.gem +0 -0
- metadata +27 -14
- data/lib/coltrane/essential_guitar_chords.rb +0 -82
- data/lib/coltrane/fret_set.rb +0 -0
- data/lib/coltrane/guitar.rb +0 -15
- data/lib/coltrane/guitar_chord.rb +0 -50
- data/lib/coltrane/guitar_chord_finder.rb +0 -98
- data/lib/coltrane/guitar_note.rb +0 -50
- data/lib/coltrane/guitar_note_set.rb +0 -61
- data/lib/coltrane/guitar_representation.rb +0 -96
- data/lib/coltrane/guitar_string.rb +0 -52
- data/lib/coltrane/scale_cache.rb +0 -4
data/lib/coltrane/fret_set.rb
DELETED
File without changes
|
data/lib/coltrane/guitar.rb
DELETED
@@ -1,50 +0,0 @@
|
|
1
|
-
module Coltrane
|
2
|
-
# It describes a group of guitar notes
|
3
|
-
class GuitarChord < GuitarNoteSet
|
4
|
-
|
5
|
-
class << self
|
6
|
-
def new_from_notes(guitar_notes)
|
7
|
-
new(*frets_in_sequence(guitar_notes))
|
8
|
-
end
|
9
|
-
|
10
|
-
def new_from_frets(*frets)
|
11
|
-
gns = (0..5).each_with_object([]) do |string_index, memo|
|
12
|
-
fret = frets[5-string_index]
|
13
|
-
unless fret.nil?
|
14
|
-
memo << GuitarNote.new(guitar_string_index: string_index,
|
15
|
-
fret: fret)
|
16
|
-
end
|
17
|
-
end
|
18
|
-
new_from_notes(gns)
|
19
|
-
end
|
20
|
-
|
21
|
-
def frets_in_sequence(guitar_notes)
|
22
|
-
guitar_notes.each_with_object([]) do |gn, memo|
|
23
|
-
memo[gn.guitar_string_index] = gn.fret
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
def initialize(*frets_in_sequence)
|
29
|
-
arg = frets_in_sequence.each_with_index.map do |fret, i|
|
30
|
-
{ fret: fret, guitar_string_index: i }
|
31
|
-
end
|
32
|
-
super(arg)
|
33
|
-
end
|
34
|
-
|
35
|
-
def chord
|
36
|
-
Chord.new(notes)
|
37
|
-
end
|
38
|
-
|
39
|
-
def frets_in_sequence
|
40
|
-
self.class.frets_in_sequence(guitar_notes)
|
41
|
-
end
|
42
|
-
|
43
|
-
def to_s
|
44
|
-
fs = frets_in_sequence
|
45
|
-
(0..5).map { |x|
|
46
|
-
fs[5-x].nil? ? 'X ' : fs[5-x].to_s.ljust(2,' ')
|
47
|
-
}.join(' ')
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
@@ -1,98 +0,0 @@
|
|
1
|
-
# require 'digest'
|
2
|
-
|
3
|
-
module Coltrane
|
4
|
-
module GuitarChordFinder
|
5
|
-
class << self
|
6
|
-
# TODO Refactor this piece of shit
|
7
|
-
def by_chord_name(chord_name)
|
8
|
-
by_chord(Chord.new(chord_name))
|
9
|
-
end
|
10
|
-
|
11
|
-
def by_chord(chord)
|
12
|
-
gnotes = gnotes_for_chord(chord.notes)
|
13
|
-
frets = gnotes.map(&:fret).uniq.sort
|
14
|
-
frets.delete(0)
|
15
|
-
threads = []
|
16
|
-
frets.each do |fret|
|
17
|
-
threads << Thread.new do
|
18
|
-
gnotes_for_fret = gnotes.dup.delete_if do |gnote|
|
19
|
-
!(gnote.fret-fret).between?(0,4) && !gnote.fret.zero?
|
20
|
-
end
|
21
|
-
|
22
|
-
gnotes_to_start_with = gnotes_for_fret.dup.delete_if do |gnote|
|
23
|
-
gnote.fret != fret
|
24
|
-
end
|
25
|
-
|
26
|
-
gnotes_to_start_with.reduce([]) do |memo2, gnote|
|
27
|
-
gnotes_for_fret.delete(gnote)
|
28
|
-
memo2 + combine_gnotes_into_chords( gnotes_for_fret, [gnote])
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
chords = threads.map(&:value).flatten
|
33
|
-
remove_duplicate_chords(chords)
|
34
|
-
end
|
35
|
-
|
36
|
-
def gnotes_for_chord(notes)
|
37
|
-
gnotes = notes.reduce([]) do |memo_1, note|
|
38
|
-
memo_1 + Guitar.strings.reduce([]) do |memo_2, gs|
|
39
|
-
memo_2 + gs.guitar_notes_for_note_in_region(note, 0..12)
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
def combine_gnotes_into_chords(gnotes_left,
|
45
|
-
chord_notes=[],
|
46
|
-
repeat_notes: false,
|
47
|
-
color_gnotes: [])
|
48
|
-
|
49
|
-
if chord_notes.size == 6
|
50
|
-
return [GuitarChord.new_from_notes(chord_notes)]
|
51
|
-
elsif gnotes_left.empty?
|
52
|
-
if color_gnotes.empty?
|
53
|
-
return [GuitarChord.new_from_notes(chord_notes)]
|
54
|
-
else
|
55
|
-
return combine_gnotes_into_chords color_gnotes.uniq,
|
56
|
-
chord_notes,
|
57
|
-
repeat_notes: true
|
58
|
-
end
|
59
|
-
else
|
60
|
-
|
61
|
-
chords = []
|
62
|
-
|
63
|
-
gnotes_left.each do |gnote|
|
64
|
-
new_chord_notes = chord_notes + [gnote]
|
65
|
-
new_gnl = gnotes_left.dup
|
66
|
-
new_gnl.delete(gnote)
|
67
|
-
new_gnl.delete_if do |g|
|
68
|
-
next(true) if g.guitar_string_index == gnote.guitar_string_index
|
69
|
-
if g.note.name == gnote.note.name && !repeat_notes
|
70
|
-
color_gnotes << g
|
71
|
-
next(true)
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
chords += combine_gnotes_into_chords new_gnl,
|
76
|
-
new_chord_notes,
|
77
|
-
repeat_notes: repeat_notes,
|
78
|
-
color_gnotes: color_gnotes.uniq
|
79
|
-
end
|
80
|
-
|
81
|
-
return chords.compact
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
def remove_duplicate_chords(chords)
|
86
|
-
chords_to_include = chords.map(&:to_s).uniq
|
87
|
-
chords.each_with_object [] do |chord, new_chords|
|
88
|
-
chord_str = chord.to_s
|
89
|
-
if chords_to_include.include?(chord_str)
|
90
|
-
chords_to_include.delete(chord_str)
|
91
|
-
new_chords << chord
|
92
|
-
end
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
end
|
97
|
-
end
|
98
|
-
end
|
data/lib/coltrane/guitar_note.rb
DELETED
@@ -1,50 +0,0 @@
|
|
1
|
-
module Coltrane
|
2
|
-
# It describes a guitar note
|
3
|
-
class GuitarNote
|
4
|
-
attr_reader :position
|
5
|
-
|
6
|
-
def initialize(fret:, guitar_string_index:)
|
7
|
-
if fret.nil? || guitar_string_index.nil?
|
8
|
-
raise "invalid guitar note for f:#{fret} and s:#{guitar_string_index}"
|
9
|
-
end
|
10
|
-
@position = { fret: fret, guitar_string_index: guitar_string_index }
|
11
|
-
end
|
12
|
-
|
13
|
-
def new_from_guitar_string_and_note(gsi, note); end
|
14
|
-
|
15
|
-
def note
|
16
|
-
pitch.note
|
17
|
-
end
|
18
|
-
|
19
|
-
def to_s
|
20
|
-
"string: #{guitar_string_index}/fret: #{fret}"
|
21
|
-
end
|
22
|
-
|
23
|
-
def guitar_string_index
|
24
|
-
position[:guitar_string_index]
|
25
|
-
end
|
26
|
-
|
27
|
-
def fret
|
28
|
-
position[:fret]
|
29
|
-
end
|
30
|
-
|
31
|
-
def guitar_string
|
32
|
-
Guitar.strings[guitar_string_index]
|
33
|
-
end
|
34
|
-
|
35
|
-
def pitch
|
36
|
-
Pitch.new(guitar_string.pitch.number + fret)
|
37
|
-
end
|
38
|
-
|
39
|
-
def guitar_chord(_quality)
|
40
|
-
guitar_strings = (guitar_string_index..0).to_a
|
41
|
-
guitar_note_array = guitar_strings.each_with_object([]) do |gsi, memo|
|
42
|
-
if f < Guitar.frets
|
43
|
-
gn = new_from_guitar_string_and_note(gsi, note)
|
44
|
-
memo << gn unless gn.nil?
|
45
|
-
end
|
46
|
-
end
|
47
|
-
GuitarChord.new(guitar_note_array)
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
@@ -1,61 +0,0 @@
|
|
1
|
-
module Coltrane
|
2
|
-
class GuitarNoteSet
|
3
|
-
attr_reader :guitar_notes
|
4
|
-
|
5
|
-
def initialize(arg)
|
6
|
-
arg = [arg] unless arg.class == Array
|
7
|
-
@guitar_notes = arg.reduce([]) do |memo, arg_item|
|
8
|
-
case arg_item
|
9
|
-
when Hash
|
10
|
-
if arg_item[:fret].nil?
|
11
|
-
memo
|
12
|
-
else
|
13
|
-
(memo + [GuitarNote.new(arg_item)])
|
14
|
-
end
|
15
|
-
|
16
|
-
when GuitarNote then memo + [arg_item]
|
17
|
-
when Pitch then memo + guitar_notes_for_pitch(arg_item)
|
18
|
-
when String then memo + guitar_notes_for_pitch(Pitch.new(arg_item))
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
def guitar_notes_for_pitch(pitch)
|
24
|
-
Guitar.strings.each_with_index.each_with_object([]) do |object, memo|
|
25
|
-
guitar_string, index = object
|
26
|
-
fret = guitar_string.fret_by_pitch(pitch)
|
27
|
-
unless fret.nil?
|
28
|
-
memo << GuitarNote.new(guitar_string_index: index, fret: fret)
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
def root_note
|
34
|
-
lowest_pitch.note
|
35
|
-
end
|
36
|
-
|
37
|
-
def lowest_pitch
|
38
|
-
pitches.sort_by(&:number).first
|
39
|
-
end
|
40
|
-
|
41
|
-
def pitches
|
42
|
-
guitar_notes.collect(&:pitch)
|
43
|
-
end
|
44
|
-
|
45
|
-
def notes
|
46
|
-
guitar_notes.collect(&:note)
|
47
|
-
end
|
48
|
-
|
49
|
-
def note_string
|
50
|
-
notes.collect(&:name).join(' ')
|
51
|
-
end
|
52
|
-
|
53
|
-
def chord_quality
|
54
|
-
ChordQuality.new_from_pitches(*pitches)
|
55
|
-
end
|
56
|
-
|
57
|
-
def render(*args)
|
58
|
-
GuitarRepresentation.render(self, *args)
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
@@ -1,96 +0,0 @@
|
|
1
|
-
require 'paint'
|
2
|
-
module Coltrane
|
3
|
-
module GuitarRepresentation
|
4
|
-
class << self
|
5
|
-
def render(guitar_notes, ref_note=nil)
|
6
|
-
gns = guitar_notes.guitar_notes.map(&:position)
|
7
|
-
tabs = Guitar.strings.map do |string|
|
8
|
-
Guitar.frets.times.map.each do |fret|
|
9
|
-
position = { guitar_string_index: string.index, fret: fret }
|
10
|
-
present = gns.include?(position)
|
11
|
-
x = if present
|
12
|
-
gn = GuitarNote.new(position)
|
13
|
-
mark = ref_note ? (gn.note - ref_note).name : '◼︎◼︎'
|
14
|
-
Paint[mark, :red]
|
15
|
-
else
|
16
|
-
'--'
|
17
|
-
end
|
18
|
-
x + (fret.zero? ? '|' : ' ')
|
19
|
-
end.join('')
|
20
|
-
end.join("\n")
|
21
|
-
|
22
|
-
special_frets = [3,5,7,9,12,15,17,19,21]
|
23
|
-
visual_aids = Guitar.frets.times.map do |fret|
|
24
|
-
x = if special_frets.include?(fret)
|
25
|
-
Paint[fret.to_s.rjust(2, 0.to_s), :yellow]
|
26
|
-
else
|
27
|
-
' '
|
28
|
-
end
|
29
|
-
x + ' '
|
30
|
-
end.join('')
|
31
|
-
|
32
|
-
[tabs, "#{visual_aids}"].join("\n")
|
33
|
-
end
|
34
|
-
|
35
|
-
def render_degrees(guitar_notes, ref_scale)
|
36
|
-
gns = guitar_notes.guitar_notes.map(&:position)
|
37
|
-
tabs = Guitar.strings.map do |string|
|
38
|
-
Guitar.frets.times.map.each do |fret|
|
39
|
-
position = { guitar_string_index: string.index, fret: fret }
|
40
|
-
present = gns.include?(position)
|
41
|
-
x = if present
|
42
|
-
gn = GuitarNote.new(position)
|
43
|
-
mark = ref_scale.degree_of_note(gn.note).to_s.rjust(2, 0.to_s)
|
44
|
-
Paint[mark, :red]
|
45
|
-
else
|
46
|
-
'--'
|
47
|
-
end
|
48
|
-
x + (fret.zero? ? '|' : ' ')
|
49
|
-
end.join('')
|
50
|
-
end.join("\n")
|
51
|
-
|
52
|
-
special_frets = [3,5,7,9,12,15,17,19,21]
|
53
|
-
visual_aids = Guitar.frets.times.map do |fret|
|
54
|
-
x = if special_frets.include?(fret)
|
55
|
-
Paint[fret.to_s.rjust(2, 0.to_s), :yellow]
|
56
|
-
else
|
57
|
-
' '
|
58
|
-
end
|
59
|
-
x + ' '
|
60
|
-
end.join('')
|
61
|
-
|
62
|
-
[tabs, "#{visual_aids}"].join("\n")
|
63
|
-
end
|
64
|
-
|
65
|
-
def render_notes(guitar_notes, ref_scale)
|
66
|
-
gns = guitar_notes.guitar_notes.map(&:position)
|
67
|
-
tabs = Guitar.strings.map do |string|
|
68
|
-
Guitar.frets.times.map.each do |fret|
|
69
|
-
position = { guitar_string_index: string.index, fret: fret }
|
70
|
-
present = gns.include?(position)
|
71
|
-
x = if present
|
72
|
-
gn = GuitarNote.new(position)
|
73
|
-
mark = gn.note.name.to_s.ljust(2, ' ')
|
74
|
-
Paint[mark, :red]
|
75
|
-
else
|
76
|
-
'--'
|
77
|
-
end
|
78
|
-
x + (fret.zero? ? '|' : ' ')
|
79
|
-
end.join('')
|
80
|
-
end.join("\n")
|
81
|
-
|
82
|
-
special_frets = [3,5,7,9,12,15,17,19,21]
|
83
|
-
visual_aids = Guitar.frets.times.map do |fret|
|
84
|
-
x = if special_frets.include?(fret)
|
85
|
-
Paint[fret.to_s.rjust(2, 0.to_s), :yellow]
|
86
|
-
else
|
87
|
-
' '
|
88
|
-
end
|
89
|
-
x + ' '
|
90
|
-
end.join('')
|
91
|
-
|
92
|
-
[tabs, "#{visual_aids}"].join("\n")
|
93
|
-
end
|
94
|
-
end
|
95
|
-
end
|
96
|
-
end
|
@@ -1,52 +0,0 @@
|
|
1
|
-
module Coltrane
|
2
|
-
# It describes a guitar string
|
3
|
-
class GuitarString
|
4
|
-
attr_reader :pitch
|
5
|
-
|
6
|
-
def initialize(pitch)
|
7
|
-
@pitch = Pitch.new(pitch)
|
8
|
-
end
|
9
|
-
|
10
|
-
def fret_by_pitch(pitch)
|
11
|
-
pitch = Pitch.new(pitch) if pitch.class != Pitch
|
12
|
-
fret = pitch.number - @pitch.number
|
13
|
-
fret if fret >= 0
|
14
|
-
end
|
15
|
-
|
16
|
-
def pitch_by_fret(fret)
|
17
|
-
Pitch.new(pitch.number + fret)
|
18
|
-
end
|
19
|
-
|
20
|
-
def guitar_notes_for_note(note)
|
21
|
-
pitches_for_note(note).map do |pitch|
|
22
|
-
GuitarNote.new(fret: fret_by_pitch(pitch),
|
23
|
-
guitar_string_index: index)
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
def guitar_notes_for_note_in_region(note, region)
|
28
|
-
pitches_for_note(note).each_with_object([]) do |pitch, memo|
|
29
|
-
fret = fret_by_pitch(pitch)
|
30
|
-
if region.include?(fret) || fret == 0
|
31
|
-
memo << GuitarNote.new(fret: fret, guitar_string_index: index)
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
def index
|
37
|
-
Guitar.strings.index { |string| string.pitch.number == self.pitch.number }
|
38
|
-
end
|
39
|
-
|
40
|
-
def pitches_for_note(note)
|
41
|
-
pitches.each_with_object([]) do |pitch, memo|
|
42
|
-
memo << pitch if pitch.note.name == note.name
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
def pitches
|
47
|
-
Guitar.frets.times.map do |fret|
|
48
|
-
pitch_by_fret(fret)
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
data/lib/coltrane/scale_cache.rb
DELETED