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.
Files changed (64) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +2 -0
  3. data/.ruby-version +1 -0
  4. data/Gemfile +15 -10
  5. data/Gemfile.lock +47 -128
  6. data/README.md +30 -8
  7. data/Rakefile +0 -4
  8. data/bin/bundle +105 -0
  9. data/bin/byebug +29 -0
  10. data/bin/coderay +12 -0
  11. data/bin/coltrane +25 -7
  12. data/bin/htmldiff +12 -0
  13. data/bin/kill-pry-rescue +12 -0
  14. data/bin/ldiff +12 -0
  15. data/bin/pry +12 -0
  16. data/bin/rake +12 -0
  17. data/bin/rescue +12 -0
  18. data/bin/rspec +12 -0
  19. data/bin/rubocop +12 -0
  20. data/bin/ruby-parse +12 -0
  21. data/bin/ruby-rewrite +12 -0
  22. data/exe/coltrane +173 -0
  23. data/lib/cli/bass_guitar.rb +9 -0
  24. data/lib/cli/chord.rb +24 -0
  25. data/lib/cli/errors.rb +28 -0
  26. data/lib/cli/guitar.rb +55 -0
  27. data/lib/cli/notes.rb +18 -0
  28. data/lib/cli/piano.rb +54 -0
  29. data/lib/cli/representation.rb +47 -0
  30. data/lib/cli/scale.rb +48 -0
  31. data/lib/cli/text.rb +13 -0
  32. data/lib/cli/ukulele.rb +11 -0
  33. data/lib/coltrane-cli.rb +12 -0
  34. data/lib/coltrane.rb +16 -31
  35. data/lib/coltrane/cache.rb +34 -0
  36. data/lib/coltrane/chord.rb +28 -41
  37. data/lib/coltrane/chord_quality.rb +14 -39
  38. data/lib/coltrane/classic_progressions.rb +37 -0
  39. data/lib/coltrane/classic_scales.rb +92 -118
  40. data/lib/coltrane/errors.rb +54 -0
  41. data/lib/coltrane/interval.rb +25 -17
  42. data/lib/coltrane/interval_sequence.rb +57 -27
  43. data/lib/coltrane/note.rb +44 -30
  44. data/lib/coltrane/note_set.rb +37 -22
  45. data/lib/coltrane/piano_representation.rb +0 -58
  46. data/lib/coltrane/pitch.rb +12 -3
  47. data/lib/coltrane/progression.rb +31 -0
  48. data/lib/coltrane/qualities.rb +115 -114
  49. data/lib/coltrane/roman_chord.rb +36 -0
  50. data/lib/coltrane/scale.rb +85 -77
  51. data/lib/coltrane/version.rb +1 -1
  52. data/lib/core_ext.rb +12 -0
  53. data/pkg/coltrane-0.0.2.gem +0 -0
  54. metadata +27 -14
  55. data/lib/coltrane/essential_guitar_chords.rb +0 -82
  56. data/lib/coltrane/fret_set.rb +0 -0
  57. data/lib/coltrane/guitar.rb +0 -15
  58. data/lib/coltrane/guitar_chord.rb +0 -50
  59. data/lib/coltrane/guitar_chord_finder.rb +0 -98
  60. data/lib/coltrane/guitar_note.rb +0 -50
  61. data/lib/coltrane/guitar_note_set.rb +0 -61
  62. data/lib/coltrane/guitar_representation.rb +0 -96
  63. data/lib/coltrane/guitar_string.rb +0 -52
  64. data/lib/coltrane/scale_cache.rb +0 -4
File without changes
@@ -1,15 +0,0 @@
1
- module Coltrane
2
- # This holds default guitar features
3
- module Guitar
4
- extend EssentialGuitarChords
5
- def self.strings
6
- %w[E4 B3 G3 D3 A2 E2].map do |pitch|
7
- GuitarString.new(pitch)
8
- end
9
- end
10
-
11
- def self.frets
12
- 23
13
- end
14
- end
15
- end
@@ -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
@@ -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
@@ -1,4 +0,0 @@
1
- class ScaleCache < ActiveRecord::Base
2
- has_many :scale_chords
3
- has_many :chord_caches, through: :scale_chords
4
- end