coltrane 0.0.2 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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