head_music 0.3.1 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/head_music/functional_interval.rb +9 -0
- data/lib/head_music/pitch.rb +2 -1
- data/lib/head_music/scale.rb +33 -28
- data/lib/head_music/version.rb +1 -1
- data/lib/head_music.rb +1 -0
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 072224f0fd9e0fff2051143e6a786daf70a975e4
|
4
|
+
data.tar.gz: a5c8934d86c94c68c26607a88e324f6670ceb97b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d68c00dbf07773b7001c6d245dfc11957a111f979d4f919f98b7f9c336108017024ba86ad4a6b9353b054dbef7432230e72d10c9b9beaa49d0040c9572be4ef3
|
7
|
+
data.tar.gz: d722a4f6569009c22db17dac114f2a61a9e9efdbbca1e8a71a727ac2dfdd238d06e551e78716537a8520c2dbe691b3f14942833be2e68bbc2a7ef0b8c0373f01
|
data/lib/head_music/pitch.rb
CHANGED
@@ -29,7 +29,7 @@ class HeadMusic::Pitch
|
|
29
29
|
def self.from_number_and_letter(number, letter)
|
30
30
|
letter = HeadMusic::Letter.get(letter)
|
31
31
|
natural_letter_pitch = get(HeadMusic::Letter.get(letter).pitch_class)
|
32
|
-
natural_letter_pitch += 12 while (number - natural_letter_pitch.to_i) >=
|
32
|
+
natural_letter_pitch += 12 while (number - natural_letter_pitch.to_i) >= 11
|
33
33
|
natural_letter_pitch = get(natural_letter_pitch)
|
34
34
|
accidental_interval = natural_letter_pitch.smallest_interval_to(HeadMusic::PitchClass.get(number))
|
35
35
|
accidental = HeadMusic::Accidental.for_interval(accidental_interval)
|
@@ -59,6 +59,7 @@ class HeadMusic::Pitch
|
|
59
59
|
end
|
60
60
|
|
61
61
|
alias_method :midi, :midi_note_number
|
62
|
+
alias_method :number, :midi_note_number
|
62
63
|
|
63
64
|
def to_s
|
64
65
|
name
|
data/lib/head_music/scale.rb
CHANGED
@@ -15,46 +15,51 @@ class HeadMusic::Scale
|
|
15
15
|
@scale_type = HeadMusic::ScaleType.get(scale_type)
|
16
16
|
end
|
17
17
|
|
18
|
-
def pitches
|
19
|
-
@pitches ||=
|
18
|
+
def pitches(direction: :ascending, octaves: 1)
|
19
|
+
@pitches ||= {}
|
20
|
+
@pitches[direction] ||= {}
|
21
|
+
@pitches[direction][octaves] ||= begin
|
20
22
|
letter_cycle = root_pitch.letter_cycle
|
21
23
|
semitones_from_root = 0
|
22
24
|
[root_pitch].tap do |pitches|
|
23
|
-
|
24
|
-
|
25
|
-
|
25
|
+
if [:ascending, :both].include?(direction)
|
26
|
+
(1..octaves).each do |i|
|
27
|
+
scale_type.ascending_intervals.each_with_index do |semitones, i|
|
28
|
+
semitones_from_root += semitones
|
29
|
+
pitches << pitch_for_step(i+1, semitones_from_root, :ascending)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
if [:descending, :both].include?(direction)
|
34
|
+
(1..octaves).each do |i|
|
35
|
+
scale_type.descending_intervals.each_with_index do |semitones, i|
|
36
|
+
semitones_from_root -= semitones
|
37
|
+
pitches << pitch_for_step(i+1, semitones_from_root, :descending)
|
38
|
+
end
|
39
|
+
end
|
26
40
|
end
|
27
41
|
end
|
28
42
|
end
|
29
43
|
end
|
30
44
|
|
31
|
-
def
|
45
|
+
def spellings
|
32
46
|
pitches.map(&:spelling).map(&:to_s)
|
33
47
|
end
|
34
48
|
|
35
|
-
def
|
36
|
-
|
37
|
-
spellings = []
|
38
|
-
letter_index = HeadMusic::Letter::all.index(spelling.letter)
|
39
|
-
starting_pitch_class = spelling.pitch_class
|
40
|
-
pattern.each do |interval_from_tonic|
|
41
|
-
letter = HeadMusic::Letter.all[letter_index]
|
42
|
-
if interval_from_tonic
|
43
|
-
accidental_interval = letter.pitch_class.smallest_interval_to(HeadMusic::PitchClass.get(starting_pitch_class + interval_from_tonic))
|
44
|
-
accidental = HeadMusic::Accidental.for_interval(accidental_interval)
|
45
|
-
spellings << HeadMusic::Spelling.get([letter, accidental].join)
|
46
|
-
end
|
47
|
-
letter_index = (letter_index + 1) % 7
|
48
|
-
end
|
49
|
-
spellings
|
49
|
+
def pitch_names(direction: :ascending, octaves: 1)
|
50
|
+
pitches(direction: direction, octaves: octaves).map(&:name)
|
50
51
|
end
|
51
52
|
|
52
53
|
def letter_cycle
|
53
54
|
@letter_cycle ||= root_pitch.letter_cycle
|
54
55
|
end
|
55
56
|
|
56
|
-
def
|
57
|
-
@
|
57
|
+
def root_pitch_number
|
58
|
+
@root_pitch_number ||= root_pitch.number
|
59
|
+
end
|
60
|
+
|
61
|
+
def degree(degree_number)
|
62
|
+
pitches[degree_number - 1]
|
58
63
|
end
|
59
64
|
|
60
65
|
private
|
@@ -69,10 +74,10 @@ class HeadMusic::Scale
|
|
69
74
|
}
|
70
75
|
end
|
71
76
|
|
72
|
-
def letter_for_step(step, semitones_from_root)
|
77
|
+
def letter_for_step(step, semitones_from_root, direction)
|
73
78
|
pitch_class_number = (root_pitch.pitch_class.to_i + semitones_from_root) % 12
|
74
79
|
if scale_type.intervals.length == 7
|
75
|
-
letter_cycle[step % 7]
|
80
|
+
direction == :ascending ? letter_cycle[step % 7] : letter_cycle[-step % 7]
|
76
81
|
elsif scale_type.intervals.length < 7 && parent_scale_pitches
|
77
82
|
parent_scale_pitch_for(semitones_from_root).letter
|
78
83
|
elsif root_pitch.flat?
|
@@ -82,9 +87,9 @@ class HeadMusic::Scale
|
|
82
87
|
end
|
83
88
|
end
|
84
89
|
|
85
|
-
def pitch_for_step(step, semitones_from_root)
|
86
|
-
pitch_number =
|
87
|
-
letter = letter_for_step(step, semitones_from_root)
|
90
|
+
def pitch_for_step(step, semitones_from_root, direction)
|
91
|
+
pitch_number = root_pitch_number + semitones_from_root
|
92
|
+
letter = letter_for_step(step, semitones_from_root, direction)
|
88
93
|
HeadMusic::Pitch.from_number_and_letter(pitch_number, letter)
|
89
94
|
end
|
90
95
|
end
|
data/lib/head_music/version.rb
CHANGED
data/lib/head_music.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: head_music
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rob Head
|
@@ -102,6 +102,7 @@ files:
|
|
102
102
|
- lib/head_music.rb
|
103
103
|
- lib/head_music/accidental.rb
|
104
104
|
- lib/head_music/circle.rb
|
105
|
+
- lib/head_music/functional_interval.rb
|
105
106
|
- lib/head_music/interval.rb
|
106
107
|
- lib/head_music/key_signature.rb
|
107
108
|
- lib/head_music/letter.rb
|