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
@@ -0,0 +1,36 @@
1
+ module Coltrane
2
+ class RomanChord
3
+ DIGITS = {
4
+ 'I' => 1,
5
+ 'V' => 5,
6
+ }
7
+
8
+ def initialize(scale, roman_numeral)
9
+ @scale = scale
10
+ @roman_numeral = roman_numeral
11
+ end
12
+
13
+ def to_chord
14
+ Chord.new root_note: root_note,
15
+ quality: quality
16
+ end
17
+
18
+ def root_note
19
+ @scale[degree]
20
+ end
21
+
22
+ def degree
23
+ @roman_numeral.split('').reduce(0) do |memo, r|
24
+ memo + (DIGITS[r] || 0) + (DIGITS[r.swapcase] || 0)
25
+ end
26
+ end
27
+
28
+ def quality
29
+ ChordQuality.new(name: is_major? ? 'M' : 'm')
30
+ end
31
+
32
+ def is_major?
33
+ @roman_numeral[0] =~ /[[:upper]]/
34
+ end
35
+ end
36
+ end
@@ -3,23 +3,51 @@ module Coltrane
3
3
  extend ClassicScales
4
4
  attr_reader :interval_sequence, :tone
5
5
 
6
- def initialize(*interval_steps, tone: 'C', mode: 1)
7
- @tone = Note.new(tone)
8
- intervals = interval_steps.rotate(mode-1).reduce([0]) do |intervals, step|
9
- intervals << (intervals.last + step)
6
+ def initialize(*distances, tone: 'C', mode: 1, name: nil, notes: nil)
7
+ @name = name
8
+ if !distances.nil? && !tone.nil?
9
+ @tone = Note[tone]
10
+ distances = distances.rotate(mode-1)
11
+ @interval_sequence = IntervalSequence.new(distances: distances)
12
+ elsif !notes.nil?
13
+ ds = NoteSet[*notes].interval_sequence.distances
14
+ self.new(*ds, tone: notes.first)
15
+ else raise WrongKeywords.new('[*distances, (tone: "C", mode: 1)] || [notes:]')
10
16
  end
17
+ end
18
+
19
+ def id
20
+ [(name || @interval_sequence), tone.number]
21
+ end
22
+
23
+ def name
24
+ @name = begin
25
+ is = self.interval_sequence.distances
26
+ (0...is.size).each do |i|
27
+ if (scale_name = Coltrane::ClassicScales::SCALES.key(is.rotate(i)))
28
+ return scale_name
29
+ end
30
+ end
31
+ nil
32
+ end
33
+ end
11
34
 
12
- @interval_sequence = IntervalSequence.new(intervals)
35
+ def pretty_name
36
+ "#{tone.name} #{name}"
13
37
  end
14
38
 
15
- def [](degree)
16
- if degree < 1
17
- raise 'Wrong degree! Use music convention for requesting degrees'
39
+ alias_method :full_name, :pretty_name
40
+
41
+ def degree(d)
42
+ if d < 1 || d > size
43
+ raise WrongDegree.new(d)
18
44
  end
19
45
 
20
- tone + interval_sequence[(degree-1) % (size)].number
46
+ tone + interval_sequence[d - 1].semitones
21
47
  end
22
48
 
49
+ alias_method :[], :degree
50
+
23
51
  def degrees
24
52
  (1..size)
25
53
  end
@@ -35,14 +63,22 @@ module Coltrane
35
63
  return note + 1 unless note.nil?
36
64
  end
37
65
 
38
- def include_notes?(*arg_notes)
39
- arg_notes.each_with_object([]) do |n, memo|
40
- memo << n if notes.map(&:name).include?(n.name)
41
- end
66
+ def &(something)
67
+ raise HasNoNotes unless something.respond_to?(:notes)
68
+ notes & something
42
69
  end
43
70
 
71
+ def include_notes?(arg)
72
+ noteset = arg.is_a?(Note) ? NoteSet[arg] : arg
73
+ (self & noteset).size == noteset.size
74
+ end
75
+
76
+ alias_method :include?, :include_notes?
77
+
44
78
  def notes
45
- @notes ||= degrees.map { |d| self[d] }
79
+ Coltrane::Cache.find_or_record(cache_key("notes")) do
80
+ NoteSet[*degrees.map { |d| degree(d) }]
81
+ end
46
82
  end
47
83
 
48
84
  def interval(i)
@@ -50,89 +86,61 @@ module Coltrane
50
86
  end
51
87
 
52
88
  def size
53
- interval_sequence.all.count - 1
89
+ interval_sequence.size
54
90
  end
55
91
 
56
- def tertians
57
- degrees.reduce([]) do |chords, degree|
58
- intervals = IntervalSequence.new(3.times.map { |i| interval(degree+(i*2)) })
59
- intervals = intervals.shift(-intervals.numbers[0])
60
- chord_name = "#{self[degree].name}#{ChordQuality.new(intervals).name}"
61
- chords << Chord.new(chord_name)
92
+ def tertians(n=3)
93
+ degrees.size.times.reduce([]) do |memo, d|
94
+ ns = NoteSet[
95
+ *n.times.map { |i| notes[(d + (i*2)) % (size)]}
96
+ ]
97
+ chord = Chord.new(notes: ns)
98
+ chord.named? ? memo + [chord] : memo
62
99
  end
63
100
  end
64
101
 
65
- def sevenths
66
- degrees.reduce([]) do |chords, degree|
67
- intervals = IntervalSequence.new(4.times.map { |i| interval(degree+(i*2)) })
68
- intervals = intervals.shift(-intervals.numbers[0])
69
- chord_name = "#{self[degree].name}#{ChordQuality.new(intervals).name}"
70
- chords << Chord.new(chord_name)
71
- end
72
- end
73
-
74
- def on_guitar
75
- NoteSet.new(notes).guitar_notes.render
102
+ def triads
103
+ tertians(3)
76
104
  end
77
105
 
78
- def intervals_on_guitar
79
- NoteSet.new(notes).guitar_notes.render(tone)
80
- end
81
-
82
- def degrees_on_guitar
83
- GuitarRepresentation.render_degrees(NoteSet.new(notes).guitar_notes, self)
84
- end
85
-
86
- def notes_on_guitar
87
- GuitarRepresentation.render_notes(NoteSet.new(notes).guitar_notes, self)
88
- end
89
-
90
- def intervals_on_piano
91
- PianoRepresentation.render_intervals(notes, tone)
106
+ def sevenths
107
+ tertians(4)
92
108
  end
93
109
 
94
- def on_piano
95
- intervals_on_piano
110
+ def pentads
111
+ tertians(5)
96
112
  end
97
113
 
98
-
99
- def cache
100
- ScaleCache.find_or_create_by(
101
- interval_sequence: interval_sequence.numbers.to_s,
102
- tone: tone.name
103
- )
114
+ def progression(*degrees)
115
+ Progression.new(self, degrees)
104
116
  end
105
117
 
106
- def cached_chords(size)
107
- cchords = cache.chord_caches.where(size: size)
108
- cchords.map do |chord_cache|
109
- Chord.new(chord_cache.name)
110
- end
118
+ def cache_key(extra)
119
+ [
120
+ @tone.name,
121
+ @interval_sequence.intervals_semitones.join(),
122
+ extra
123
+ ].join('-')
111
124
  end
112
125
 
113
- def cache_chords(chords)
114
- []
115
- chords.each do |chord|
116
- cache.chord_caches.create name: chord.name, size: chord.size
126
+ def all_chords
127
+ (3..size).reduce([]) do |memo, s|
128
+ memo + chords(s)
117
129
  end
118
130
  end
119
131
 
120
132
  def chords(size)
121
- cchords = cached_chords(size)
122
- if cchords.empty?
123
- cache_chords(begin
124
- permutations = interval_sequence.numbers.permutation(size).map do |intervals|
125
- IntervalSequence.new(intervals)
133
+ Coltrane::Cache.find_or_record(cache_key("chords-#{size}")) do
134
+ included_names = []
135
+ notes.permutation(size).reduce([]) do |memo, ns|
136
+ chord = Chord.new(notes: ns)
137
+ if chord.named? && !included_names.include?(chord.name)
138
+ included_names << chord.name
139
+ memo + [chord]
140
+ else
141
+ memo
126
142
  end
127
- permutations.uniq.map do |c|
128
- quality = ChordQuality.new(c.zero_it)
129
- unless quality.name.nil?
130
- Chord.new "#{(tone + c[0].number).name}#{quality.name}"
131
- end
132
- end.compact
133
- end)
134
- else
135
- cchords
143
+ end
136
144
  end
137
145
  end
138
146
  end
@@ -1,3 +1,3 @@
1
1
  module Coltrane
2
- VERSION = "0.0.2"
2
+ VERSION = "1.0.0"
3
3
  end
@@ -0,0 +1,12 @@
1
+ class String
2
+ # Stolen from Active Support and changed a bit
3
+ def underscore
4
+ return self unless /[A-Z-]|::/.match?(self)
5
+ word = self.to_s.gsub("::", "/")
6
+ word.gsub!(/([A-Z\d]+)([A-Z][a-z])/, '\1_\2')
7
+ word.gsub!(/([a-z\d])([A-Z])/, '\1_\2')
8
+ word.tr!("-", "_")
9
+ word.downcase!
10
+ word
11
+ end
12
+ end
Binary file
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: coltrane
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pedro Maciel
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-05-25 00:00:00.000000000 Z
11
+ date: 2018-01-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -41,12 +41,15 @@ dependencies:
41
41
  description:
42
42
  email:
43
43
  - pedro@pedromaciel.com
44
- executables: []
44
+ executables:
45
+ - coltrane
45
46
  extensions: []
46
47
  extra_rdoc_files: []
47
48
  files:
48
49
  - ".bundle/config"
50
+ - ".gitignore"
49
51
  - ".rspec"
52
+ - ".ruby-version"
50
53
  - CODE_OF_CONDUCT.md
51
54
  - Gemfile
52
55
  - Gemfile.lock
@@ -55,7 +58,9 @@ files:
55
58
  - README.md
56
59
  - Rakefile
57
60
  - bin/_guard-core
61
+ - bin/bundle
58
62
  - bin/bundler
63
+ - bin/byebug
59
64
  - bin/coderay
60
65
  - bin/coltrane
61
66
  - bin/console
@@ -86,21 +91,27 @@ files:
86
91
  - db/cache_test.sqlite3
87
92
  - db/config.yml
88
93
  - db/schema.rb
94
+ - exe/coltrane
95
+ - lib/cli/bass_guitar.rb
96
+ - lib/cli/chord.rb
97
+ - lib/cli/errors.rb
98
+ - lib/cli/guitar.rb
99
+ - lib/cli/notes.rb
100
+ - lib/cli/piano.rb
101
+ - lib/cli/representation.rb
102
+ - lib/cli/scale.rb
103
+ - lib/cli/text.rb
104
+ - lib/cli/ukulele.rb
105
+ - lib/coltrane-cli.rb
89
106
  - lib/coltrane.rb
107
+ - lib/coltrane/cache.rb
90
108
  - lib/coltrane/cadence.rb
91
109
  - lib/coltrane/chord.rb
92
110
  - lib/coltrane/chord_cache.rb
93
111
  - lib/coltrane/chord_quality.rb
112
+ - lib/coltrane/classic_progressions.rb
94
113
  - lib/coltrane/classic_scales.rb
95
- - lib/coltrane/essential_guitar_chords.rb
96
- - lib/coltrane/fret_set.rb
97
- - lib/coltrane/guitar.rb
98
- - lib/coltrane/guitar_chord.rb
99
- - lib/coltrane/guitar_chord_finder.rb
100
- - lib/coltrane/guitar_note.rb
101
- - lib/coltrane/guitar_note_set.rb
102
- - lib/coltrane/guitar_representation.rb
103
- - lib/coltrane/guitar_string.rb
114
+ - lib/coltrane/errors.rb
104
115
  - lib/coltrane/interval.rb
105
116
  - lib/coltrane/interval_sequence.rb
106
117
  - lib/coltrane/interval_set.rb
@@ -111,10 +122,12 @@ files:
111
122
  - lib/coltrane/pitch.rb
112
123
  - lib/coltrane/progression.rb
113
124
  - lib/coltrane/qualities.rb
125
+ - lib/coltrane/roman_chord.rb
114
126
  - lib/coltrane/scale.rb
115
- - lib/coltrane/scale_cache.rb
116
127
  - lib/coltrane/scale_chord.rb
117
128
  - lib/coltrane/version.rb
129
+ - lib/core_ext.rb
130
+ - pkg/coltrane-0.0.2.gem
118
131
  homepage: http://github.com/pedrozath/coltrane
119
132
  licenses:
120
133
  - MIT
@@ -136,7 +149,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
136
149
  version: '0'
137
150
  requirements: []
138
151
  rubyforge_project:
139
- rubygems_version: 2.6.11
152
+ rubygems_version: 2.7.3
140
153
  signing_key:
141
154
  specification_version: 4
142
155
  summary: It deals with all sorts of calculations around music theory and allows for
@@ -1,82 +0,0 @@
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