coltrane 2.1.5 → 2.2.1
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 +4 -4
- data/.travis.yml +17 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile +1 -2
- data/Gemfile.lock +9 -21
- data/README.md +4 -2
- data/bin/console +1 -1
- data/coltrane.gemspec +1 -1
- data/lib/cli.rb +1 -1
- data/lib/cli/chord.rb +1 -1
- data/lib/cli/config.rb +4 -3
- data/lib/cli/guitar_chords.rb +31 -31
- data/lib/cli/scale.rb +1 -1
- data/lib/coltrane.rb +4 -3
- data/lib/coltrane/chord_quality.rb +4 -4
- data/lib/coltrane/circle_of_fifths.rb +4 -2
- data/lib/coltrane/classic_scales.rb +2 -2
- data/lib/coltrane/diatonic_scale.rb +3 -1
- data/lib/coltrane/frequency.rb +1 -1
- data/lib/coltrane/frequency_interval.rb +81 -0
- data/lib/coltrane/interval.rb +177 -33
- data/lib/coltrane/interval_class.rb +147 -49
- data/lib/coltrane/interval_sequence.rb +53 -54
- data/lib/coltrane/key.rb +3 -1
- data/lib/coltrane/notable_progressions.rb +0 -1
- data/lib/coltrane/note.rb +4 -10
- data/lib/coltrane/note_set.rb +2 -2
- data/lib/coltrane/pitch_class.rb +24 -2
- data/lib/coltrane/qualities.rb +171 -169
- data/lib/coltrane/scale.rb +22 -15
- data/lib/coltrane/version.rb +1 -1
- data/lib/coltrane/voicing.rb +3 -2
- data/lib/coltrane_game/question.rb +4 -3
- data/lib/coltrane_instruments/guitar.rb +1 -1
- data/lib/coltrane_instruments/guitar/base.rb +1 -1
- data/lib/coltrane_instruments/guitar/chord.rb +18 -16
- data/lib/coltrane_synth.rb +3 -1
- data/lib/coltrane_synth/base.rb +9 -7
- data/lib/coltrane_synth/synth.rb +3 -1
- data/lib/core_ext.rb +1 -30
- data/lib/os.rb +4 -2
- metadata +19 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 73fefa27f1153e68849f503990c62b0f37d66a58f5979b6c8eca4292166ece20
|
4
|
+
data.tar.gz: f83f2490b0402555ef13f7d04790c4982e7e7f8274fcfd9f4290e497d357b3ed
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3aec21519141e0e6fd73a5bec77acbbc510cde319b16d1f6544a3fa256bb78d858dfa2525e049cd40b4d7f4acb5c480963906dd3aada7d3f6539f3ed5a14b7d1
|
7
|
+
data.tar.gz: 2ded1ec625ec59cc2cfb519128806b45b9e953ef123bb1822268a7a74f87b83e66027d0771e5e1bbf5c7ce26e1d63b6e901725cc68df71b0404378082de83265
|
data/.travis.yml
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
language: ruby
|
2
|
+
git:
|
3
|
+
depth: 1
|
4
|
+
rvm:
|
5
|
+
- 2.5.0
|
6
|
+
script:
|
7
|
+
- bin/rspec spec
|
8
|
+
deploy:
|
9
|
+
provider: rubygems
|
10
|
+
api_key:
|
11
|
+
secure: YLM/BiQPu0GMgns2tUeE1qO58JmzRVfo20ebgG6XNBqmptzPI3ReqEs/bYaUSdygYiK81pVhy69dWj3bjKjWV6C7EBr/w6tOE+qM6PUKEvd8rlcviXXUOgFfMCLLqREYi21zr+I0Z1Gj8mCRklBV2DFF+f6TTIcSh/afYVVWv8rktpMgivijB9Cexek5gP/8zhg8AaKAnGBzrmKzxraKZA7s97e5iWvZBMLtrDyqSe8mfkviKeOE6B1sKb8YdYLh9fSSpNewOEzKTtgS2AWmoCdP6IiUk+dhORTHu0s13Rz+nD2ZOYfkYIXt6iMNYlFHB30Nm1/4iusCrStIphDXlLqCD6DfBX4gRmBgRHsceCHoHggWqOCbgz28MI1vtkFsnoLz7/fJBlpPy/g+7VC6SnSt5fux35W4u26QcvMwmD3MkwJmjjktsi+GlIF9D+oDtb79VTUM1hzT2kkByWATZJnUK9M3CxxzGe4CqXpeFpVW5d0K84aMd0jpAuKFZf87jOVtQ80Jtl/ANFpHP/LO8P/SUil4OZh2eKmIADZg/z6itytkK/lcU5uEIpHIctP7q1oNqX27tLTPdoY1ht7gJ/x9IUL7lqTDsY7nRW7PrO3sNwzT1NCDIeAC2K/k7WCdrEKk3oj4C3Eqykho6X7tx+lfd2eTN6bzAcekCSseezE=
|
12
|
+
gem: coltrane
|
13
|
+
on:
|
14
|
+
repo: pedrozath/coltrane
|
15
|
+
notifications:
|
16
|
+
slack:
|
17
|
+
secure: A4qliXrG8AgvMi9skLwfTfGgRxeVRBIBS8O6tIF2k0oLn+i0XRCEPWYnK4Xa1YufgCnMTFlGA144sxsvuf3spBuwCJkOefA7YhJJVhKQTCpmkSq0IPEaF8+KpwESI1W1hBJuEWmCAxwL1Z+tZa7CON2ELyKgHukxEtUTfQsbXMY1eeISRm7a73xi4DlfTM4UEV2Cfd/Rg9cpP4QGsWANowDsaNm33aQ611BIokfVSZtKf7A4IPAthZOrXkGqD0R4FjUxbDUtQEd5gg3tpcPmWrHIxunlvJow/XBXtv+/qDlbo8LzUUxtkElcGjj1g3hsQEZmevoNxZdGW/8/F5DMMLYYQRfph7Ot9Xm6dNYj3rIUcHjNob1qUNb0ON2pko4gcO6HiU8VZ/oQUsUtBBrB7ddf1htXVdO3jHH2josFTCWgFCzPwgxsCuyP71lieDBolyaKFOyWGaWj6cZhqGUfkSosLZNyDoUEWERkImOHyqvi5TQaPVteZvUeCDkD6ZtCTyEjZI8zXdyPKKweBLxRuGMjUgpsA5QEyo3dlIguLe7OYCLWyYYmEcF+2QjYLevEBFNM1rl6tK8VEF6aost0pa6Rq6/VHRNEEKn0ejYTqbiPGljmOiDOwWSCxQWhlJ9tw692wnpLN5/y0Cda40PQ87hi1tXyvcvLrrvETfYfXcU=
|
data/CHANGELOG.md
CHANGED
@@ -5,6 +5,11 @@
|
|
5
5
|
- Fix chords so that they generate a barre and a non-barre version and prevent
|
6
6
|
barre chords from picking notes before the barre.
|
7
7
|
|
8
|
+
## [2.2.0]
|
9
|
+
|
10
|
+
- Intervals were completely refactored according to [#11](https://github.com/pedrozath/coltrane/issues/11) and (https://github.com/pedrozath/coltrane/issues/12). Thanks [@art-of-dom](https://github.com/art-of-dom) for the valuable information. We now have new interval classes and new ways on how to deal with them.
|
11
|
+
Check the [wiki](https://github.com/pedrozath/coltrane/wiki) for more details.
|
12
|
+
|
8
13
|
## [2.1.0]
|
9
14
|
|
10
15
|
- Correct Flat/Sharp on Diatonic Scales
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
coltrane (2.1
|
4
|
+
coltrane (2.2.1)
|
5
5
|
color (~> 1.8)
|
6
|
-
|
6
|
+
dry-monads (~> 0.4)
|
7
7
|
paint (~> 2.0)
|
8
8
|
pedrozath-mercenary (~> 0.3)
|
9
9
|
|
@@ -17,30 +17,27 @@ GEM
|
|
17
17
|
coderay (1.1.2)
|
18
18
|
color (1.8)
|
19
19
|
concurrent-ruby (1.0.5)
|
20
|
-
coreaudio (0.0.12)
|
21
|
-
narray (~> 0.6.0.0)
|
22
20
|
diff-lcs (1.3)
|
23
21
|
docile (1.1.5)
|
24
|
-
|
22
|
+
dry-core (0.4.5)
|
23
|
+
concurrent-ruby (~> 1.0)
|
24
|
+
dry-equalizer (0.2.0)
|
25
|
+
dry-monads (0.4.0)
|
26
|
+
dry-core (~> 0.3, >= 0.3.3)
|
27
|
+
dry-equalizer
|
25
28
|
faraday (0.14.0)
|
26
29
|
multipart-post (>= 1.2, < 3)
|
27
|
-
flay (2.10.0)
|
28
|
-
erubis (~> 2.7.0)
|
29
|
-
path_expander (~> 1.0)
|
30
|
-
ruby_parser (~> 3.0)
|
31
|
-
sexp_processor (~> 4.0)
|
32
30
|
gitlab (3.6.1)
|
33
31
|
httparty
|
34
32
|
terminal-table
|
35
33
|
hike (1.2.3)
|
36
|
-
httparty (0.16.
|
34
|
+
httparty (0.16.1)
|
37
35
|
multi_xml (>= 0.5.2)
|
38
36
|
interception (0.5)
|
39
37
|
json (2.1.0)
|
40
38
|
method_source (0.9.0)
|
41
39
|
multi_xml (0.6.0)
|
42
40
|
multipart-post (2.0.0)
|
43
|
-
narray (0.6.0.9)
|
44
41
|
octokit (4.8.0)
|
45
42
|
sawyer (~> 0.8.0, >= 0.5.3)
|
46
43
|
opal (0.10.5)
|
@@ -54,7 +51,6 @@ GEM
|
|
54
51
|
parallel (1.12.1)
|
55
52
|
parser (2.4.0.2)
|
56
53
|
ast (~> 2.3)
|
57
|
-
path_expander (1.0.2)
|
58
54
|
pedrozath-mercenary (0.3.6)
|
59
55
|
powerpack (0.1.1)
|
60
56
|
pronto (0.6.0)
|
@@ -62,9 +58,6 @@ GEM
|
|
62
58
|
octokit (~> 4.3, >= 4.1.0)
|
63
59
|
rugged (~> 0.24, >= 0.23.0)
|
64
60
|
thor (~> 0.19.0)
|
65
|
-
pronto-flay (0.6.2)
|
66
|
-
flay (~> 2.8)
|
67
|
-
pronto (~> 0.6.0)
|
68
61
|
pronto-rubocop (0.6.2)
|
69
62
|
pronto (~> 0.6.0)
|
70
63
|
rubocop (~> 0.38, >= 0.35.0)
|
@@ -102,13 +95,10 @@ GEM
|
|
102
95
|
ruby-progressbar (~> 1.7)
|
103
96
|
unicode-display_width (~> 1.0, >= 1.0.1)
|
104
97
|
ruby-progressbar (1.9.0)
|
105
|
-
ruby_parser (3.11.0)
|
106
|
-
sexp_processor (~> 4.9)
|
107
98
|
rugged (0.26.0)
|
108
99
|
sawyer (0.8.1)
|
109
100
|
addressable (>= 2.3.5, < 2.6)
|
110
101
|
faraday (~> 0.8, < 1.0)
|
111
|
-
sexp_processor (4.10.1)
|
112
102
|
simplecov (0.15.1)
|
113
103
|
docile (~> 1.1.0)
|
114
104
|
json (>= 1.8, < 3)
|
@@ -131,8 +121,6 @@ DEPENDENCIES
|
|
131
121
|
bundler (~> 1.14)
|
132
122
|
coltrane!
|
133
123
|
opal-rspec
|
134
|
-
pronto
|
135
|
-
pronto-flay
|
136
124
|
pronto-rubocop
|
137
125
|
pry
|
138
126
|
pry-byebug
|
data/README.md
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
[](https://travis-ci.org/pedrozath/coltrane)
|
2
|
+
|
1
3
|
# Coltrane
|
2
4
|
|
3
5
|
A music calculation library/CLI written in Ruby.
|
@@ -5,7 +7,7 @@ A music calculation library/CLI written in Ruby.
|
|
5
7
|

|
6
8
|
|
7
9
|
* [How to use this library](https://github.com/pedrozath/coltrane/wiki/Core-music-theory-library).
|
8
|
-
* [Why did I
|
10
|
+
* [Why did I write this library](https://medium.com/@pedrozath/so-i-wrote-a-library-to-help-me-compose-music-ddb4ae7c8227).
|
9
11
|
* [Chat room for discussing the project, answering questions, etc.](https://gitter.im/coltrane-music/Lobby)
|
10
12
|
|
11
13
|
## CLI (Command Line Interface)
|
@@ -50,4 +52,4 @@ We are looking for contributors. Find me on [our chatroom](https://gitter.im/col
|
|
50
52
|
|
51
53
|
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
52
54
|
|
53
|
-
by Pedro Maciel | [twitter](http://twitter.com/pedrozath) | pedro@pedromaciel.com
|
55
|
+
by Pedro Maciel | [twitter](http://twitter.com/pedrozath) | pedro@pedromaciel.com
|
data/bin/console
CHANGED
data/coltrane.gemspec
CHANGED
@@ -32,7 +32,7 @@ Gem::Specification.new do |spec|
|
|
32
32
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
33
33
|
spec.require_paths = ["lib"]
|
34
34
|
|
35
|
-
|
35
|
+
spec.add_runtime_dependency 'dry-monads', '~> 0.4'
|
36
36
|
spec.add_runtime_dependency 'paint', '~> 2.0'
|
37
37
|
spec.add_runtime_dependency 'color', '~> 1.8'
|
38
38
|
spec.add_runtime_dependency 'pedrozath-mercenary', '~> 0.3'
|
data/lib/cli.rb
CHANGED
data/lib/cli/chord.rb
CHANGED
@@ -29,7 +29,7 @@ module Coltrane
|
|
29
29
|
@chords.each do |chord|
|
30
30
|
desc = "#{chord.name} chord:"
|
31
31
|
Coltrane::Cli::Notes.new chord.notes, desc: desc
|
32
|
-
ColtraneSynth::Base.play(chord, 1) if Cli.config.sound
|
32
|
+
# ColtraneSynth::Base.play(chord, 1) if Cli.config.sound
|
33
33
|
end
|
34
34
|
end
|
35
35
|
end
|
data/lib/cli/config.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Coltrane
|
2
4
|
module Cli
|
3
5
|
class Config
|
@@ -5,7 +7,7 @@ module Coltrane
|
|
5
7
|
flavor: :notes,
|
6
8
|
sound: false,
|
7
9
|
on: :text
|
8
|
-
}
|
10
|
+
}.freeze
|
9
11
|
|
10
12
|
attr_accessor :flavor, :degrees, :sound
|
11
13
|
attr_reader :on
|
@@ -23,7 +25,6 @@ module Coltrane
|
|
23
25
|
else instrument
|
24
26
|
end
|
25
27
|
end
|
26
|
-
|
27
28
|
end
|
28
29
|
|
29
30
|
def self.config
|
@@ -35,4 +36,4 @@ module Coltrane
|
|
35
36
|
@config = nil
|
36
37
|
end
|
37
38
|
end
|
38
|
-
end
|
39
|
+
end
|
data/lib/cli/guitar_chords.rb
CHANGED
@@ -14,7 +14,7 @@ module Coltrane
|
|
14
14
|
target_chord = Coltrane::Chord.new(notes: @notes)
|
15
15
|
chords = ColtraneInstruments::Guitar::Base.find_chords(target_chord)
|
16
16
|
@chords = chords.sort[-6..-1].reverse
|
17
|
-
@chords.each { |c| ColtraneSynth::Base.play(c.voicing) } if false
|
17
|
+
# @chords.each { |c| ColtraneSynth::Base.play(c.voicing) } if false
|
18
18
|
end
|
19
19
|
|
20
20
|
def chord_height
|
@@ -34,32 +34,32 @@ module Coltrane
|
|
34
34
|
rchords = @chords.map { |c| render_chord(c).split("\n") }
|
35
35
|
rchords.max_by(&:size).size.times.reduce('') do |memo1, l|
|
36
36
|
memo1 +
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
37
|
+
rchords.reduce('') do |memo2, c|
|
38
|
+
memo2 +
|
39
|
+
(c[l].nil? ? ' ' * c.map(&:size).max + ' ' : "#{c[l]} ")
|
40
|
+
end +
|
41
|
+
"\n"
|
42
42
|
end
|
43
43
|
end
|
44
44
|
|
45
45
|
def render_chord(chord)
|
46
46
|
render_top(chord) +
|
47
|
-
|
47
|
+
(chord.lowest_fret..chord.lowest_fret + chord_height)
|
48
48
|
.each_with_index.reduce('') do |memo1, (f, y)|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
(chord.guitar.strings.size*2).times.map do |x|
|
49
|
+
memo1 +
|
50
|
+
' ' +
|
51
|
+
(chord.guitar.strings.size * 2).times.map { |x| base_color border(x, y) }.join('') +
|
52
|
+
"\n" +
|
53
|
+
chord.guitar.strings.reduce(base_color(f.to_s.ljust(2, ' '))) do |memo2, s|
|
54
|
+
memo2 +
|
55
|
+
' ' +
|
56
|
+
render_note(chord.guitar_notes.select do |n|
|
57
|
+
n.string == s && n.fret == f
|
58
|
+
end.any?)
|
59
|
+
end +
|
60
|
+
" \n"
|
61
|
+
end + ' ' +
|
62
|
+
(chord.guitar.strings.size * 2).times.map do |x|
|
63
63
|
base_color border(x, chord_height + 1)
|
64
64
|
end.join('')
|
65
65
|
end
|
@@ -70,8 +70,8 @@ module Coltrane
|
|
70
70
|
y_on_start = y == 0
|
71
71
|
x_on_edge = x == edge[0]
|
72
72
|
y_on_edge = y == edge[1]
|
73
|
-
x_on_middle = (0...edge[0]).
|
74
|
-
y_on_middle = (0...edge[1]).
|
73
|
+
x_on_middle = (0...edge[0]).cover?(x)
|
74
|
+
y_on_middle = (0...edge[1]).cover?(y)
|
75
75
|
|
76
76
|
if x_on_start && y_on_start then '┍'
|
77
77
|
elsif x_on_middle && y_on_start then x.odd? ? '━' : '┯'
|
@@ -103,14 +103,14 @@ module Coltrane
|
|
103
103
|
def render_top(chord)
|
104
104
|
chord.guitar.strings.reduce(' ') do |memo, s|
|
105
105
|
memo +
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
106
|
+
if chord.guitar_notes.select { |n|
|
107
|
+
n.string == s && n.fret == 0 }.any?
|
108
|
+
highlight '⬤ '
|
109
|
+
elsif chord.guitar_notes.select { |n| n.string == s && n.fret.nil? }.any?
|
110
|
+
alt 'x '
|
111
|
+
else
|
112
|
+
' '
|
113
|
+
end
|
114
114
|
end + "\n"
|
115
115
|
end
|
116
116
|
|
data/lib/cli/scale.rb
CHANGED
@@ -5,7 +5,7 @@ module Coltrane
|
|
5
5
|
# Interfaces commands with the scales functionality
|
6
6
|
class Scale
|
7
7
|
def self.parse(str)
|
8
|
-
raise BadScaleError unless str
|
8
|
+
raise BadScaleError unless str&.include?('-')
|
9
9
|
*scale_name, tone = str.split('-')
|
10
10
|
Coltrane::Scale.fetch(scale_name.join('_'), tone)
|
11
11
|
end
|
data/lib/coltrane.rb
CHANGED
@@ -4,11 +4,11 @@ require 'json'
|
|
4
4
|
require 'forwardable'
|
5
5
|
require 'core_ext'
|
6
6
|
require 'ostruct'
|
7
|
-
|
7
|
+
require 'dry-monads'
|
8
8
|
|
9
9
|
# The main module for working with Music Theory
|
10
10
|
module Coltrane
|
11
|
-
autoload :Frequency,
|
11
|
+
autoload :Frequency, 'coltrane/frequency'
|
12
12
|
|
13
13
|
BASE_OCTAVE = 4
|
14
14
|
BASE_PITCH_INTEGER = 9
|
@@ -33,8 +33,9 @@ module Coltrane
|
|
33
33
|
autoload :Note, 'coltrane/note'
|
34
34
|
autoload :NoteSet, 'coltrane/note_set'
|
35
35
|
|
36
|
-
autoload :
|
36
|
+
autoload :FrequencyInterval, 'coltrane/frequency_interval'
|
37
37
|
autoload :IntervalClass, 'coltrane/interval_class'
|
38
|
+
autoload :Interval, 'coltrane/interval'
|
38
39
|
autoload :UnorderedIntervalClass, 'coltrane/unordered_interval_class'
|
39
40
|
autoload :IntervalSequence, 'coltrane/interval_sequence'
|
40
41
|
autoload :Qualities, 'coltrane/qualities'
|
@@ -27,7 +27,7 @@ module Coltrane
|
|
27
27
|
hash ||= chord_trie
|
28
28
|
return quality_names if hash.empty?
|
29
29
|
if hash['name']
|
30
|
-
quality_names[hash.delete('name')] = intervals.map { |n|
|
30
|
+
quality_names[hash.delete('name')] = intervals.map { |n| Interval.public_send(n.underscore) }
|
31
31
|
end
|
32
32
|
hash.reduce(quality_names) do |memo, (interval, values)|
|
33
33
|
memo.merge intervals_per_name(hash: values,
|
@@ -45,7 +45,7 @@ module Coltrane
|
|
45
45
|
return trie['name']
|
46
46
|
end
|
47
47
|
interval = given_interval_names.shift
|
48
|
-
new_trie = trie[interval]
|
48
|
+
new_trie = trie[interval.full_name]
|
49
49
|
find_chord given_interval_names, last_name: (trie['name'] || last_name),
|
50
50
|
trie: new_trie
|
51
51
|
end
|
@@ -63,7 +63,7 @@ module Coltrane
|
|
63
63
|
end
|
64
64
|
|
65
65
|
def retrieve_chord_intervals(chord_sequence = normal_sequence)
|
66
|
-
ints = IntervalSequence.new(
|
66
|
+
ints = IntervalSequence.new(*self)
|
67
67
|
chord_sequence.map do |int_sym|
|
68
68
|
next unless interval_name = ints.public_send(int_sym)
|
69
69
|
ints.delete_if { |i| i.cents == IntervalClass.new(interval_name).cents }
|
@@ -91,7 +91,7 @@ module Coltrane
|
|
91
91
|
def initialize(name: nil, notes: nil, bass: nil)
|
92
92
|
if name
|
93
93
|
@name = bass.nil? ? name : [name, bass].join('/')
|
94
|
-
super(
|
94
|
+
super(*intervals_from_name(name))
|
95
95
|
elsif notes
|
96
96
|
super(notes: notes)
|
97
97
|
@name = get_name
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Coltrane
|
2
4
|
class CircleOfFifths
|
3
5
|
attr_reader :notes
|
@@ -22,8 +24,8 @@ module Coltrane
|
|
22
24
|
size: size - 1
|
23
25
|
end
|
24
26
|
|
25
|
-
def letters(i=nil)
|
27
|
+
def letters(i = nil)
|
26
28
|
i.nil? ? LETTER_SEQUENCE : LETTER_SEQUENCE[i % LETTER_SEQUENCE.size]
|
27
29
|
end
|
28
30
|
end
|
29
|
-
end
|
31
|
+
end
|
@@ -42,11 +42,11 @@ module Coltrane
|
|
42
42
|
end
|
43
43
|
|
44
44
|
# Factories for the diatonic scale
|
45
|
-
def major(note='C')
|
45
|
+
def major(note = 'C')
|
46
46
|
DiatonicScale.new(note)
|
47
47
|
end
|
48
48
|
|
49
|
-
def minor(note='A')
|
49
|
+
def minor(note = 'A')
|
50
50
|
DiatonicScale.new(note, major: false)
|
51
51
|
end
|
52
52
|
|