coltrane 2.2.1 → 3.0.0.pre
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 +16 -1
- data/CHANGELOG.md +11 -0
- data/Gemfile.lock +25 -2
- data/README.md +3 -0
- data/bin/console +6 -2
- data/coltrane.gemspec +2 -1
- data/exe/coltrane +14 -224
- data/lib/coltrane.rb +3 -50
- data/lib/coltrane/commands.rb +14 -0
- data/lib/coltrane/commands/chords.rb +77 -0
- data/lib/coltrane/commands/command.rb +45 -0
- data/lib/coltrane/commands/common_chords.rb +33 -0
- data/lib/coltrane/commands/errors.rb +44 -0
- data/lib/coltrane/commands/find_progression.rb +28 -0
- data/lib/coltrane/commands/find_scale.rb +39 -0
- data/lib/coltrane/commands/notes.rb +44 -0
- data/lib/coltrane/commands/progression.rb +27 -0
- data/lib/{cli → coltrane/commands}/representation.rb +0 -0
- data/lib/coltrane/commands/scale.rb +46 -0
- data/lib/coltrane/renderers.rb +6 -0
- data/lib/coltrane/renderers/renderer.rb +42 -0
- data/lib/coltrane/renderers/text_renderer.rb +23 -0
- data/lib/coltrane/renderers/text_renderer/array_drawer.rb +45 -0
- data/lib/coltrane/renderers/text_renderer/base_drawer.rb +20 -0
- data/lib/coltrane/renderers/text_renderer/hash_drawer.rb +16 -0
- data/lib/coltrane/renderers/text_renderer/representation_guitar_chord_drawer.rb +95 -0
- data/lib/coltrane/renderers/text_renderer/representation_guitar_note_set_drawer.rb +76 -0
- data/lib/coltrane/renderers/text_renderer/representation_piano_note_set_drawer.rb +49 -0
- data/lib/coltrane/renderers/text_renderer/theory_chord_drawer.rb +14 -0
- data/lib/coltrane/renderers/text_renderer/theory_note_set_drawer.rb +17 -0
- data/lib/coltrane/renderers/text_renderer/theory_progression_drawer.rb +13 -0
- data/lib/coltrane/renderers/text_renderer/theory_progression_set_drawer.rb +22 -0
- data/lib/coltrane/renderers/text_renderer/theory_scale_drawer.rb +13 -0
- data/lib/coltrane/renderers/text_renderer/theory_scale_set_drawer.rb +27 -0
- data/lib/coltrane/representation.rb +12 -0
- data/lib/coltrane/representation/guitar.rb +34 -0
- data/lib/coltrane/representation/guitar/chord.rb +180 -0
- data/lib/coltrane/representation/guitar/note.rb +26 -0
- data/lib/coltrane/representation/guitar/note_set.rb +35 -0
- data/lib/coltrane/representation/guitar/string.rb +31 -0
- data/lib/coltrane/representation/guitar_like_instruments.rb +21 -0
- data/lib/coltrane/representation/piano.rb +36 -0
- data/lib/coltrane/representation/piano/note_set.rb +22 -0
- data/lib/{coltrane_synth.rb → coltrane/synth.rb.rb} +0 -0
- data/lib/{coltrane_synth → coltrane/synth}/base.rb +0 -0
- data/lib/{coltrane_synth → coltrane/synth}/synth.rb +0 -0
- data/lib/coltrane/theory.rb +54 -0
- data/lib/coltrane/theory/cadence.rb +9 -0
- data/lib/coltrane/{changes.rb → theory/changes.rb} +0 -0
- data/lib/coltrane/theory/chord.rb +101 -0
- data/lib/coltrane/theory/chord_quality.rb +113 -0
- data/lib/coltrane/theory/chord_substitutions.rb +11 -0
- data/lib/coltrane/theory/circle_of_fifths.rb +33 -0
- data/lib/coltrane/theory/classic_scales.rb +113 -0
- data/lib/coltrane/theory/diatonic_scale.rb +38 -0
- data/lib/coltrane/theory/errors.rb +97 -0
- data/lib/coltrane/theory/frequency.rb +52 -0
- data/lib/coltrane/theory/frequency_interval.rb +83 -0
- data/lib/coltrane/theory/interval.rb +209 -0
- data/lib/coltrane/theory/interval_class.rb +212 -0
- data/lib/coltrane/theory/interval_sequence.rb +157 -0
- data/lib/coltrane/theory/key.rb +18 -0
- data/lib/coltrane/{mode.rb → theory/mode.rb} +0 -0
- data/lib/coltrane/theory/notable_progressions.rb +30 -0
- data/lib/coltrane/theory/note.rb +104 -0
- data/lib/coltrane/theory/note_set.rb +101 -0
- data/lib/coltrane/theory/pitch.rb +94 -0
- data/lib/coltrane/theory/pitch_class.rb +154 -0
- data/lib/coltrane/theory/progression.rb +81 -0
- data/lib/coltrane/theory/progression_set.rb +18 -0
- data/lib/coltrane/{qualities.rb → theory/qualities.rb} +0 -0
- data/lib/coltrane/theory/roman_chord.rb +114 -0
- data/lib/coltrane/theory/scale.rb +161 -0
- data/lib/coltrane/theory/scale_search_result.rb +6 -0
- data/lib/coltrane/theory/scale_set.rb +40 -0
- data/lib/coltrane/theory/voicing.rb +41 -0
- data/lib/coltrane/version.rb +1 -1
- metadata +88 -63
- data/bin/rails +0 -17
- data/data/qualities.yml +0 -83
- data/db/cache.sqlite3 +0 -0
- data/db/cache_test.sqlite3 +0 -0
- data/db/config.yml +0 -11
- data/lib/cli.rb +0 -24
- data/lib/cli/bass_guitar.rb +0 -12
- data/lib/cli/chord.rb +0 -39
- data/lib/cli/config.rb +0 -39
- data/lib/cli/errors.rb +0 -46
- data/lib/cli/guitar.rb +0 -67
- data/lib/cli/guitar_chords.rb +0 -122
- data/lib/cli/notes.rb +0 -20
- data/lib/cli/piano.rb +0 -57
- data/lib/cli/scale.rb +0 -53
- data/lib/cli/text.rb +0 -16
- data/lib/cli/ukulele.rb +0 -14
- data/lib/coltrane/cache.rb +0 -43
- data/lib/coltrane/cadence.rb +0 -7
- data/lib/coltrane/chord.rb +0 -89
- data/lib/coltrane/chord_quality.rb +0 -111
- data/lib/coltrane/chord_substitutions.rb +0 -9
- data/lib/coltrane/circle_of_fifths.rb +0 -31
- data/lib/coltrane/classic_scales.rb +0 -94
- data/lib/coltrane/diatonic_scale.rb +0 -36
- data/lib/coltrane/errors.rb +0 -95
- data/lib/coltrane/frequency.rb +0 -50
- data/lib/coltrane/frequency_interval.rb +0 -81
- data/lib/coltrane/interval.rb +0 -208
- data/lib/coltrane/interval_class.rb +0 -210
- data/lib/coltrane/interval_sequence.rb +0 -155
- data/lib/coltrane/key.rb +0 -16
- data/lib/coltrane/notable_progressions.rb +0 -28
- data/lib/coltrane/note.rb +0 -98
- data/lib/coltrane/note_set.rb +0 -89
- data/lib/coltrane/pitch.rb +0 -92
- data/lib/coltrane/pitch_class.rb +0 -148
- data/lib/coltrane/progression.rb +0 -74
- data/lib/coltrane/roman_chord.rb +0 -112
- data/lib/coltrane/scale.rb +0 -154
- data/lib/coltrane/unordered_interval_class.rb +0 -7
- data/lib/coltrane/voicing.rb +0 -39
- data/lib/coltrane_game/question.rb +0 -7
- data/lib/coltrane_instruments.rb +0 -7
- data/lib/coltrane_instruments/guitar.rb +0 -10
- data/lib/coltrane_instruments/guitar/base.rb +0 -29
- data/lib/coltrane_instruments/guitar/chord.rb +0 -170
- data/lib/coltrane_instruments/guitar/note.rb +0 -24
- data/lib/coltrane_instruments/guitar/string.rb +0 -29
- data/lib/os.rb +0 -21
data/lib/cli/bass_guitar.rb
DELETED
data/lib/cli/chord.rb
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Coltrane
|
|
4
|
-
module Cli
|
|
5
|
-
# Interfaces chord functionality with the lib
|
|
6
|
-
class Chord
|
|
7
|
-
def initialize(*chords, notes: nil)
|
|
8
|
-
Cli.config do |c|
|
|
9
|
-
if c.on == :guitar
|
|
10
|
-
c.on = :guitar_chords
|
|
11
|
-
elsif c.on == :guitar_arm
|
|
12
|
-
c.on = :guitar
|
|
13
|
-
end
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
@chords =
|
|
17
|
-
if !chords.empty?
|
|
18
|
-
if chords[0].is_a?(String)
|
|
19
|
-
chords.map { |c| Coltrane::Chord.new(name: c) }
|
|
20
|
-
else
|
|
21
|
-
chords
|
|
22
|
-
end
|
|
23
|
-
elsif !notes.nil?
|
|
24
|
-
[Coltrane::Chord.new(notes: notes)]
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
raise BadChordError unless @chords
|
|
28
|
-
|
|
29
|
-
@chords.each do |chord|
|
|
30
|
-
desc = "#{chord.name} chord:"
|
|
31
|
-
Coltrane::Cli::Notes.new chord.notes, desc: desc
|
|
32
|
-
# ColtraneSynth::Base.play(chord, 1) if Cli.config.sound
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
# rubocop:enable Metrics/MethodLength
|
data/lib/cli/config.rb
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Coltrane
|
|
4
|
-
module Cli
|
|
5
|
-
class Config
|
|
6
|
-
DEFAULTS = {
|
|
7
|
-
flavor: :notes,
|
|
8
|
-
sound: false,
|
|
9
|
-
on: :text
|
|
10
|
-
}.freeze
|
|
11
|
-
|
|
12
|
-
attr_accessor :flavor, :degrees, :sound
|
|
13
|
-
attr_reader :on
|
|
14
|
-
|
|
15
|
-
def initialize(defaults = DEFAULTS)
|
|
16
|
-
defaults.each do |key, val|
|
|
17
|
-
instance_variable_set(:"@#{key}", val)
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def on=(instrument)
|
|
22
|
-
@on = case instrument
|
|
23
|
-
when :ukelele then :ukulele
|
|
24
|
-
when :bass then :bass_guitar
|
|
25
|
-
else instrument
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
def self.config
|
|
31
|
-
@config = Config.new if @config.nil?
|
|
32
|
-
block_given? ? yield(@config) : @config
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
def self.erase_config
|
|
36
|
-
@config = nil
|
|
37
|
-
end
|
|
38
|
-
end
|
|
39
|
-
end
|
data/lib/cli/errors.rb
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
# rubocop:disable Style/Documentation
|
|
4
|
-
|
|
5
|
-
module Coltrane
|
|
6
|
-
module Cli
|
|
7
|
-
class ColtraneCliError < StandardError
|
|
8
|
-
def initialize(msg)
|
|
9
|
-
super msg
|
|
10
|
-
end
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
class WrongFlavorError < ColtraneCliError
|
|
14
|
-
def initialize(msg = nil)
|
|
15
|
-
super msg || 'Wrong flavor. Check possible flavors with `coltrane list flavors`.'
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
class BadFindScales < ColtraneCliError
|
|
20
|
-
def initialize(msg = nil)
|
|
21
|
-
super msg || 'Provide --notes or --chords. Ex: `coltrane find-scale --notes C-E-G`.'
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
class WrongRepresentationTypeError < ColtraneCliError
|
|
26
|
-
def initialize(type)
|
|
27
|
-
super "The provided representation type (#{type}) "\
|
|
28
|
-
'is not available at the moment.'
|
|
29
|
-
end
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
class BadScaleError < ColtraneCliError
|
|
33
|
-
def initialize(msg = nil)
|
|
34
|
-
super msg || 'Incorrect scale, please specify scale and root separated by `-`. Ex: `coltrane scale major-C'
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
class BadChordError < ColtraneCliError
|
|
39
|
-
def initialize(msg = nil)
|
|
40
|
-
super msg || 'Incorrect chord, please specify a set of chords separated by `-`. Ex: coltrane chord CM7'
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
# rubocop:enable Style/Documentation
|
data/lib/cli/guitar.rb
DELETED
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Coltrane
|
|
4
|
-
module Cli
|
|
5
|
-
# Renders notes in a common most popular ukulele scheme
|
|
6
|
-
class Guitar < Representation
|
|
7
|
-
SPECIAL_FRETS = [3, 5, 7, 9, 12, 15, 17, 19].freeze
|
|
8
|
-
|
|
9
|
-
include Color
|
|
10
|
-
def initialize(notes, tuning: %w[E A D G B E], frets: 22)
|
|
11
|
-
@notes = notes
|
|
12
|
-
@tuning = tuning.reverse
|
|
13
|
-
@frets = frets
|
|
14
|
-
@ref_note = @notes.first
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
def render
|
|
18
|
-
[render_notes, render_special_frets, hint].join("\n" * 2)
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def render_notes
|
|
22
|
-
@tuning.each_with_index.map do |string, str_i|
|
|
23
|
-
string_note = Note[string]
|
|
24
|
-
Array.new(@frets + 2) do |i|
|
|
25
|
-
if i.zero?
|
|
26
|
-
Paint[string, HSL.new(140 + str_i * 20, 50, 50).html]
|
|
27
|
-
else
|
|
28
|
-
fret = i - 1
|
|
29
|
-
note = string_note + fret
|
|
30
|
-
m = (@notes.include?(note) ? place_mark(note) : place_empty(str_i))
|
|
31
|
-
fret.zero? ? (m + ' |') : m
|
|
32
|
-
end
|
|
33
|
-
end.join(' ')
|
|
34
|
-
end.join("\n")
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
def render_special_frets
|
|
38
|
-
' ' +
|
|
39
|
-
Array.new(@frets + 2) do |fret|
|
|
40
|
-
m = SPECIAL_FRETS.include?(fret) ? fret.to_s.rjust(2, 0.to_s) : ' '
|
|
41
|
-
"#{m}#{' ' if fret.zero?}"
|
|
42
|
-
end.join(' ')
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
def place_empty(str_i)
|
|
46
|
-
Paint['--', HSL.new(180 + str_i * 3, 50, 30).html]
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
def place_mark(note)
|
|
50
|
-
mark = case Cli.config.flavor
|
|
51
|
-
when :notes then note.pretty_name.ljust(2, ' ')
|
|
52
|
-
when :intervals then (@ref_note - note).name.ljust(2, '-')
|
|
53
|
-
when :degrees then @notes.degree(note).to_s.rjust(2, '0')
|
|
54
|
-
when :marks then ' ' # '◼◼'
|
|
55
|
-
else raise WrongFlavorError
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
base_hue = (180 + note.integer * 10) % 360 # + 260
|
|
59
|
-
Paint[
|
|
60
|
-
mark,
|
|
61
|
-
HSL.new(0, 0, 100).html,
|
|
62
|
-
HSL.new(base_hue, 100, 30).html
|
|
63
|
-
]
|
|
64
|
-
end
|
|
65
|
-
end
|
|
66
|
-
end
|
|
67
|
-
end
|
data/lib/cli/guitar_chords.rb
DELETED
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Coltrane
|
|
4
|
-
module Cli
|
|
5
|
-
# Renders notes in a common most popular ukulele scheme
|
|
6
|
-
class GuitarChords < Representation
|
|
7
|
-
include Color
|
|
8
|
-
|
|
9
|
-
def initialize(notes, tuning: %w[E2 A2 D3 G3 B3 E4], frets: 23)
|
|
10
|
-
@notes = notes
|
|
11
|
-
@tuning = tuning.reverse
|
|
12
|
-
@frets = frets
|
|
13
|
-
|
|
14
|
-
target_chord = Coltrane::Chord.new(notes: @notes)
|
|
15
|
-
chords = ColtraneInstruments::Guitar::Base.find_chords(target_chord)
|
|
16
|
-
@chords = chords.sort[-6..-1].reverse
|
|
17
|
-
# @chords.each { |c| ColtraneSynth::Base.play(c.voicing) } if false
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def chord_height
|
|
21
|
-
ColtraneInstruments::Guitar::Chord::MAX_FRET_SPAN
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
def render
|
|
25
|
-
render_horizontally
|
|
26
|
-
# render_vertically
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
def render_vertically
|
|
30
|
-
@chords.map { |c| render_chord(c) }
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
def render_horizontally
|
|
34
|
-
rchords = @chords.map { |c| render_chord(c).split("\n") }
|
|
35
|
-
rchords.max_by(&:size).size.times.reduce('') do |memo1, l|
|
|
36
|
-
memo1 +
|
|
37
|
-
rchords.reduce('') do |memo2, c|
|
|
38
|
-
memo2 +
|
|
39
|
-
(c[l].nil? ? ' ' * c.map(&:size).max + ' ' : "#{c[l]} ")
|
|
40
|
-
end +
|
|
41
|
-
"\n"
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
def render_chord(chord)
|
|
46
|
-
render_top(chord) +
|
|
47
|
-
(chord.lowest_fret..chord.lowest_fret + chord_height)
|
|
48
|
-
.each_with_index.reduce('') do |memo1, (f, y)|
|
|
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
|
-
base_color border(x, chord_height + 1)
|
|
64
|
-
end.join('')
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
def border(x, y)
|
|
68
|
-
edge = [@tuning.size * 2 - 2, chord_height + 1]
|
|
69
|
-
x_on_start = x == 0
|
|
70
|
-
y_on_start = y == 0
|
|
71
|
-
x_on_edge = x == edge[0]
|
|
72
|
-
y_on_edge = y == edge[1]
|
|
73
|
-
x_on_middle = (0...edge[0]).cover?(x)
|
|
74
|
-
y_on_middle = (0...edge[1]).cover?(y)
|
|
75
|
-
|
|
76
|
-
if x_on_start && y_on_start then '┍'
|
|
77
|
-
elsif x_on_middle && y_on_start then x.odd? ? '━' : '┯'
|
|
78
|
-
elsif x_on_edge && y_on_start then '┑'
|
|
79
|
-
elsif x_on_start && y_on_middle then '┝'
|
|
80
|
-
elsif x_on_middle && y_on_middle then x.odd? ? '━' : '┿'
|
|
81
|
-
elsif x_on_edge && y_on_middle then '┥'
|
|
82
|
-
elsif x_on_start && y_on_edge then '┕'
|
|
83
|
-
elsif x_on_middle && y_on_edge then x.odd? ? '━' : '┷'
|
|
84
|
-
elsif x_on_edge && y_on_edge then '┙'
|
|
85
|
-
else ' '
|
|
86
|
-
end
|
|
87
|
-
# puts edge.inspect
|
|
88
|
-
# "#{x},#{y} "
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
def base_color(str)
|
|
92
|
-
Paint[str, '#6A4AC2']
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
def highlight(str)
|
|
96
|
-
Paint[str, '#E67831']
|
|
97
|
-
end
|
|
98
|
-
|
|
99
|
-
def alt(str)
|
|
100
|
-
Paint[str, '#2DD380']
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
def render_top(chord)
|
|
104
|
-
chord.guitar.strings.reduce(' ') do |memo, s|
|
|
105
|
-
memo +
|
|
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
|
-
end + "\n"
|
|
115
|
-
end
|
|
116
|
-
|
|
117
|
-
def render_note(found)
|
|
118
|
-
found ? highlight('⬤') : base_color('│')
|
|
119
|
-
end
|
|
120
|
-
end
|
|
121
|
-
end
|
|
122
|
-
end
|
data/lib/cli/notes.rb
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Coltrane
|
|
4
|
-
module Cli
|
|
5
|
-
# Interfaces notes outputting functionality with the lib
|
|
6
|
-
class Notes
|
|
7
|
-
def initialize(notes, desc: nil)
|
|
8
|
-
@desc = desc || 'The notes you supplied:'
|
|
9
|
-
notes = Coltrane::NoteSet.new(notes)
|
|
10
|
-
@representation = Representation.build(notes)
|
|
11
|
-
render
|
|
12
|
-
# notes.each {|n| ColtraneSynth::Base.play(n, 0.1) } if Cli.config.sound
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
def render
|
|
16
|
-
puts "\n" + [@desc, @representation.render].join("\n" * 2)
|
|
17
|
-
end
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
end
|
data/lib/cli/piano.rb
DELETED
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Coltrane
|
|
4
|
-
module Cli
|
|
5
|
-
# It allows rendering notes in an ASCII piano
|
|
6
|
-
class Piano < Representation
|
|
7
|
-
PIANO_TEMPLATE = <<~ASCII
|
|
8
|
-
┌─┬─┬┬─┬─╥─┬─┬┬─┬┬─┬─╥─┬─┬┬─┬─╥─┬─┬┬─┬┬─┬─┐
|
|
9
|
-
│ │ ││ │ ║ │ ││ ││ │ ║ │ ││ │ ║ │ ││ ││ │ │
|
|
10
|
-
│ │X││X│ ║ │X││X││X│ ║ │X││X│ ║ │X││X││X│ │
|
|
11
|
-
│ │X││X│ ║ │X││X││X│ ║ │X││X│ ║ │X││X││X│ │
|
|
12
|
-
│ ┕╥┙┕╥┙ ║ ┕╥┙┕╥┙┕╥┙ ║ ┕╥┙┕╥┙ ║ ┕╥┙┕╥┙┕╥┙ │
|
|
13
|
-
│ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ │
|
|
14
|
-
│XX║XX║XX║XX║XX║XX║XX║XX║XX║XX║XX║XX║XX║XX│
|
|
15
|
-
└──╨──╨──╨──╨──╨──╨──╨──╨──╨──╨──╨──╨──╨──┘
|
|
16
|
-
ASCII
|
|
17
|
-
|
|
18
|
-
def render
|
|
19
|
-
PIANO_TEMPLATE.each_line.map.each_with_index do |l, ln|
|
|
20
|
-
case ln
|
|
21
|
-
when 2, 3 then replace_x(l, black_notes, 1, ln - 2)
|
|
22
|
-
when 6 then replace_x(l, white_notes, 2)
|
|
23
|
-
else l
|
|
24
|
-
end
|
|
25
|
-
end.join + "\n#{hint}"
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
private
|
|
29
|
-
|
|
30
|
-
def replace_x(line, notes, size, index = 0)
|
|
31
|
-
line.gsub('X' * size).with_index do |_match, i|
|
|
32
|
-
note = notes[i % notes.size]
|
|
33
|
-
next ' ' * size unless @notes.include?(note)
|
|
34
|
-
Paint[replacer(note)[size == 2 ? 0..2 : index], 'red']
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
def replacer(note)
|
|
39
|
-
# TODO: Maybe extract this method into its own class/module
|
|
40
|
-
case Cli.config.flavor
|
|
41
|
-
when :intervals then (@ref_note - note).name
|
|
42
|
-
when :marks then '◼ '
|
|
43
|
-
when :degrees then @notes.degree(note).to_s.rjust(2, '0')
|
|
44
|
-
when :notes then note.pretty_name.to_s.ljust(2, "\u266E")
|
|
45
|
-
end
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
def white_notes
|
|
49
|
-
Coltrane::Scale.major.notes
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
def black_notes
|
|
53
|
-
Coltrane::Scale.pentatonic_major('C#', 4).notes
|
|
54
|
-
end
|
|
55
|
-
end
|
|
56
|
-
end
|
|
57
|
-
end
|
data/lib/cli/scale.rb
DELETED
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Coltrane
|
|
4
|
-
module Cli
|
|
5
|
-
# Interfaces commands with the scales functionality
|
|
6
|
-
class Scale
|
|
7
|
-
def self.parse(str)
|
|
8
|
-
raise BadScaleError unless str&.include?('-')
|
|
9
|
-
*scale_name, tone = str.split('-')
|
|
10
|
-
Coltrane::Scale.fetch(scale_name.join('_'), tone)
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
def self.find(notes: [], chords: [])
|
|
14
|
-
if notes.any?
|
|
15
|
-
puts "\nSearching for scales containing #{notes.join(', ')}:\n\n"
|
|
16
|
-
notes = NoteSet[*notes]
|
|
17
|
-
elsif chords.any?
|
|
18
|
-
puts "\nSearching for scales containing #{chords.join(', ')}:\n\n"
|
|
19
|
-
notes = chords.reduce(NoteSet[]) do |memo, c|
|
|
20
|
-
memo + Coltrane::Chord.new(name: c).notes
|
|
21
|
-
end
|
|
22
|
-
else raise BadFindScales
|
|
23
|
-
end
|
|
24
|
-
render_search(notes)
|
|
25
|
-
puts "\nUnderlined means the scale has all notes"
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
def self.render_search(searched_notes)
|
|
29
|
-
search = Coltrane::Scale.having_notes(searched_notes)
|
|
30
|
-
output = []
|
|
31
|
-
scale_width = search[:results].keys.map(&:size).max
|
|
32
|
-
search[:results].each do |name, scales_by_tone|
|
|
33
|
-
output << name.ljust(scale_width + 1, ' ')
|
|
34
|
-
scales_by_tone.each do |tone_number, notes|
|
|
35
|
-
p = (notes.size.to_f / searched_notes.size) * 100
|
|
36
|
-
l = p == 100 ? p : (p + 20) * 0.4
|
|
37
|
-
und = p == 100 ? :underline : nil
|
|
38
|
-
color = Color::HSL.new(30, p, l / 2).html
|
|
39
|
-
output << Paint["#{Note[tone_number].name}(#{notes.size})", color, und]
|
|
40
|
-
output << ' '
|
|
41
|
-
end
|
|
42
|
-
output << "\n"
|
|
43
|
-
end
|
|
44
|
-
puts output.join
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
def initialize(scale)
|
|
48
|
-
desc = "This is the #{scale.tone.name} #{scale.name} scale:"
|
|
49
|
-
Coltrane::Cli::Notes.new(scale.notes)
|
|
50
|
-
end
|
|
51
|
-
end
|
|
52
|
-
end
|
|
53
|
-
end
|