musicality 0.11.1 → 0.12.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.
- checksums.yaml +5 -5
- data/.coveralls.yml +1 -0
- data/.ruby-version +1 -1
- data/.travis.yml +4 -0
- data/ChangeLog.md +11 -0
- data/README.md +3 -0
- data/Rakefile +11 -3
- data/lib/musicality/composition/model/rhythm.rb +33 -0
- data/lib/musicality/composition/model/rhythm_class.rb +30 -0
- data/lib/musicality/composition/sequencing/drum_machine/drum_kit.rb +18 -0
- data/lib/musicality/composition/sequencing/drum_machine/drum_machine.rb +59 -0
- data/lib/musicality/composition/sequencing/drum_machine/drum_parts.rb +21 -0
- data/lib/musicality/composition/sequencing/drum_machine/drum_pattern.rb +66 -0
- data/lib/musicality/composition/sequencing/drum_machine/drum_patterns/pop_drum_patterns.rb +146 -0
- data/lib/musicality/composition/sequencing/note_array.rb +33 -0
- data/lib/musicality/composition/sequencing/note_fifo.rb +73 -0
- data/lib/musicality/composition/sequencing/sequenceable.rb +9 -0
- data/lib/musicality/composition/sequencing/sequencer.rb +35 -0
- data/lib/musicality/errors.rb +2 -2
- data/lib/musicality/notation/model/dynamics.rb +2 -2
- data/lib/musicality/notation/model/key.rb +42 -91
- data/lib/musicality/notation/model/keys.rb +35 -34
- data/lib/musicality/notation/model/note.rb +31 -9
- data/lib/musicality/notation/model/pitch.rb +2 -2
- data/lib/musicality/notation/parsing/convenience_methods.rb +23 -12
- data/lib/musicality/notation/parsing/duration_parsing.rb +3 -3
- data/lib/musicality/notation/parsing/key_parsing.rb +150 -0
- data/lib/musicality/notation/parsing/key_parsing.treetop +37 -0
- data/lib/musicality/notation/parsing/meter_parsing.rb +3 -3
- data/lib/musicality/notation/parsing/numbers/nonnegative_float_parsing.rb +3 -1
- data/lib/musicality/notation/parsing/numbers/nonnegative_integer_parsing.rb +1 -0
- data/lib/musicality/notation/parsing/numbers/nonnegative_rational_parsing.rb +1 -1
- data/lib/musicality/notation/parsing/numbers/positive_float_parsing.rb +4 -1
- data/lib/musicality/notation/parsing/numbers/positive_rational_parsing.rb +1 -1
- data/lib/musicality/notation/parsing/parseable.rb +13 -17
- data/lib/musicality/notation/parsing/pitch_parsing.rb +7 -0
- data/lib/musicality/notation/parsing/segment_parsing.rb +3 -0
- data/lib/musicality/performance/conversion/note_sequence_extractor.rb +82 -134
- data/lib/musicality/performance/model/note_sequence.rb +22 -3
- data/lib/musicality/performance/supercollider/performer.rb +2 -2
- data/lib/musicality/performance/supercollider/sc_drum_kits.rb +29 -0
- data/lib/musicality/performance/supercollider/synthdefs/bass.rb +211 -0
- data/lib/musicality/performance/supercollider/synthdefs/claps.rb +80 -0
- data/lib/musicality/performance/supercollider/synthdefs/cymbals.rb +57 -0
- data/lib/musicality/performance/supercollider/synthdefs/hihats.rb +67 -0
- data/lib/musicality/performance/supercollider/synthdefs/kicks.rb +158 -0
- data/lib/musicality/performance/supercollider/synthdefs/mario.rb +49 -0
- data/lib/musicality/performance/supercollider/{synthdefs.rb → synthdefs/other.rb} +0 -767
- data/lib/musicality/performance/supercollider/synthdefs/pianos.rb +46 -0
- data/lib/musicality/performance/supercollider/synthdefs/snares.rb +169 -0
- data/lib/musicality/performance/supercollider/synthdefs/toms.rb +25 -0
- data/lib/musicality/performance/supercollider/synthdefs/volume.rb +20 -0
- data/lib/musicality/pitch_class.rb +1 -1
- data/lib/musicality/pitch_classes.rb +3 -5
- data/lib/musicality/version.rb +1 -1
- data/lib/musicality.rb +25 -1
- data/musicality.gemspec +3 -2
- data/spec/composition/convenience_methods_spec.rb +8 -8
- data/spec/composition/generation/random_rhythm_generator_spec.rb +5 -5
- data/spec/composition/model/pitch_class_spec.rb +22 -16
- data/spec/composition/model/pitch_classes_spec.rb +5 -5
- data/spec/composition/model/rhythm_class_spec.rb +42 -0
- data/spec/composition/model/rhythm_spec.rb +43 -0
- data/spec/composition/model/scale_class_spec.rb +26 -26
- data/spec/composition/model/scale_spec.rb +38 -38
- data/spec/composition/sequencing/drum_machine/drum_machine_spec.rb +67 -0
- data/spec/composition/sequencing/drum_machine/drum_pattern_spec.rb +58 -0
- data/spec/composition/sequencing/note_array_spec.rb +94 -0
- data/spec/composition/sequencing/note_fifo_spec.rb +183 -0
- data/spec/composition/sequencing/sequencer_spec.rb +76 -0
- data/spec/composition/util/adding_sequence_spec.rb +33 -33
- data/spec/composition/util/compound_sequence_spec.rb +6 -6
- data/spec/composition/util/note_generation_spec.rb +34 -34
- data/spec/composition/util/probabilities_spec.rb +7 -7
- data/spec/composition/util/random_sampler_spec.rb +3 -3
- data/spec/composition/util/repeating_sequence_spec.rb +28 -28
- data/spec/musicality_spec.rb +1 -1
- data/spec/notation/conversion/change_conversion_spec.rb +87 -87
- data/spec/notation/conversion/note_time_converter_spec.rb +22 -22
- data/spec/notation/conversion/score_conversion_spec.rb +1 -1
- data/spec/notation/conversion/score_converter_spec.rb +31 -31
- data/spec/notation/conversion/tempo_conversion_spec.rb +11 -11
- data/spec/notation/model/change_spec.rb +80 -80
- data/spec/notation/model/key_spec.rb +135 -69
- data/spec/notation/model/link_spec.rb +27 -27
- data/spec/notation/model/meter_spec.rb +28 -28
- data/spec/notation/model/note_spec.rb +68 -47
- data/spec/notation/model/part_spec.rb +19 -19
- data/spec/notation/model/pitch_spec.rb +69 -68
- data/spec/notation/model/score_spec.rb +50 -47
- data/spec/notation/parsing/articulation_parsing_spec.rb +4 -4
- data/spec/notation/parsing/convenience_methods_spec.rb +49 -10
- data/spec/notation/parsing/duration_nodes_spec.rb +13 -13
- data/spec/notation/parsing/duration_parsing_spec.rb +10 -10
- data/spec/notation/parsing/key_parsing_spec.rb +19 -0
- data/spec/notation/parsing/link_nodes_spec.rb +7 -7
- data/spec/notation/parsing/link_parsing_spec.rb +4 -4
- data/spec/notation/parsing/meter_parsing_spec.rb +5 -5
- data/spec/notation/parsing/note_node_spec.rb +19 -19
- data/spec/notation/parsing/note_parsing_spec.rb +4 -4
- data/spec/notation/parsing/numbers/nonnegative_float_spec.rb +8 -8
- data/spec/notation/parsing/numbers/nonnegative_integer_spec.rb +2 -2
- data/spec/notation/parsing/numbers/nonnegative_rational_spec.rb +1 -1
- data/spec/notation/parsing/numbers/positive_float_spec.rb +8 -8
- data/spec/notation/parsing/numbers/positive_integer_spec.rb +6 -6
- data/spec/notation/parsing/numbers/positive_rational_spec.rb +6 -6
- data/spec/notation/parsing/pitch_node_spec.rb +7 -7
- data/spec/notation/parsing/pitch_parsing_spec.rb +2 -2
- data/spec/notation/parsing/segment_parsing_spec.rb +3 -3
- data/spec/notation/util/function_spec.rb +15 -15
- data/spec/notation/util/transition_spec.rb +12 -12
- data/spec/notation/util/value_computer_spec.rb +35 -36
- data/spec/performance/conversion/glissando_converter_spec.rb +24 -24
- data/spec/performance/conversion/note_sequence_extractor_spec.rb +39 -39
- data/spec/performance/conversion/portamento_converter_spec.rb +23 -23
- data/spec/performance/midi/midi_util_spec.rb +41 -41
- data/spec/performance/midi/part_sequencer_spec.rb +10 -10
- data/spec/performance/midi/score_sequencer_spec.rb +15 -15
- data/spec/performance/midi/score_sequencing_spec.rb +2 -2
- data/spec/performance/util/optimization_spec.rb +9 -9
- data/spec/printing/note_engraving_spec.rb +16 -16
- data/spec/printing/score_engraver_spec.rb +5 -5
- data/spec/spec_helper.rb +5 -0
- metadata +85 -30
@@ -2,27 +2,28 @@ module Musicality
|
|
2
2
|
|
3
3
|
class Key
|
4
4
|
include Packable
|
5
|
-
|
5
|
+
|
6
6
|
FLAT = :flat
|
7
7
|
SHARP = :sharp
|
8
|
-
|
9
|
-
|
8
|
+
NONE = :none
|
9
|
+
ACCIDENTAL_TYPES = [FLAT, SHARP, NONE]
|
10
|
+
|
10
11
|
MAJOR = :major
|
11
12
|
MINOR = :minor
|
12
13
|
TRIAD_TYPES = [MAJOR, MINOR]
|
13
|
-
|
14
|
-
|
14
|
+
|
15
|
+
TONIC_PCS = {
|
15
16
|
MAJOR => {
|
16
17
|
FLAT => [PitchClasses::F, PitchClasses::Bb, PitchClasses::Eb,
|
17
|
-
PitchClasses::Ab, PitchClasses::Db, PitchClasses::Gb
|
18
|
+
PitchClasses::Ab, PitchClasses::Db, PitchClasses::Gb],
|
18
19
|
SHARP => [PitchClasses::G,PitchClasses::D,PitchClasses::A,
|
19
|
-
PitchClasses::E,PitchClasses::B
|
20
|
+
PitchClasses::E,PitchClasses::B]
|
20
21
|
},
|
21
22
|
MINOR => {
|
22
23
|
FLAT => [PitchClasses::D,PitchClasses::G,PitchClasses::C,
|
23
|
-
PitchClasses::F,PitchClasses::Bb,PitchClasses::Eb
|
24
|
+
PitchClasses::F,PitchClasses::Bb,PitchClasses::Eb],
|
24
25
|
SHARP => [PitchClasses::E,PitchClasses::B,PitchClasses::Fs,
|
25
|
-
PitchClasses::Cs,PitchClasses::Gs
|
26
|
+
PitchClasses::Cs,PitchClasses::Gs]
|
26
27
|
}
|
27
28
|
}
|
28
29
|
|
@@ -33,105 +34,55 @@ class Key
|
|
33
34
|
PitchClasses::Ds,PitchClasses::As,PitchClasses::Es,PitchClasses::Bs]
|
34
35
|
}
|
35
36
|
|
36
|
-
attr_reader :tonic_pc, :
|
37
|
-
|
38
|
-
def initialize tonic_pc, triad: MAJOR, accidental_pref: FLAT
|
39
|
-
self.tonic_pc = tonic_pc
|
40
|
-
self.triad = triad
|
41
|
-
self.accidental_pref = accidental_pref
|
42
|
-
end
|
43
|
-
|
44
|
-
def self.major_flat tonic_pc
|
45
|
-
Key.new(tonic_pc, triad: MAJOR, accidental_pref: FLAT)
|
46
|
-
end
|
47
|
-
|
48
|
-
def self.major_sharp tonic_pc
|
49
|
-
Key.new(tonic_pc, triad: MAJOR, accidental_pref: SHARP)
|
50
|
-
end
|
51
|
-
|
52
|
-
def self.minor_flat tonic_pc
|
53
|
-
Key.new(tonic_pc, triad: MINOR, accidental_pref: FLAT)
|
54
|
-
end
|
55
|
-
|
56
|
-
def self.minor_sharp tonic_pc
|
57
|
-
Key.new(tonic_pc, triad: MINOR, accidental_pref: SHARP)
|
58
|
-
end
|
59
|
-
|
60
|
-
def major?; @triad == MAJOR; end
|
61
|
-
def minor?; @triad == MINOR; end
|
62
|
-
|
63
|
-
def flat?; accidental_type == FLAT; end
|
64
|
-
def sharp?; accidental_type == SHARP; end
|
65
|
-
|
66
|
-
def accidental_free?
|
67
|
-
(major? && @tonic_pc == PitchClasses::C) || (minor? && @tonic_pc == PitchClasses::A)
|
68
|
-
end
|
37
|
+
attr_reader :tonic_pc, :triad_type, :accidentals, :accidental_type
|
69
38
|
|
70
|
-
def
|
71
|
-
|
72
|
-
|
73
|
-
|
39
|
+
def initialize tonic_pc, triad_type: MAJOR
|
40
|
+
raise ArgumentError, "Unknown triad type #{triad_type}" unless TRIAD_TYPES.include?(triad_type)
|
41
|
+
@triad_type = triad_type
|
42
|
+
@tonic_pc = PitchClass.from_i(tonic_pc)
|
43
|
+
|
44
|
+
if (@triad_type == MAJOR && @tonic_pc == PitchClasses::C) ||
|
45
|
+
(@triad_type == MINOR && @tonic_pc == PitchClasses::A)
|
46
|
+
@accidentals = []
|
47
|
+
@accidental_type = NONE
|
48
|
+
else
|
49
|
+
if TONIC_PCS[@triad_type][FLAT].include?(@tonic_pc)
|
50
|
+
@accidental_type = FLAT
|
51
|
+
elsif TONIC_PCS[@triad_type][SHARP].include?(@tonic_pc)
|
52
|
+
@accidental_type = SHARP
|
53
|
+
else
|
54
|
+
raise ArgumentError, "unknown tonic PC #{@tonic_pc}"
|
74
55
|
end
|
75
|
-
|
76
|
-
|
56
|
+
i = TONIC_PCS[@triad_type][@accidental_type].index(@tonic_pc)
|
57
|
+
@accidentals = ACCIDENTALS[@accidental_type][0..i]
|
77
58
|
end
|
78
59
|
end
|
79
60
|
|
80
|
-
def
|
81
|
-
|
82
|
-
unless ACCIDENTAL_TYPES.include? accidental_pref
|
83
|
-
raise ArgumentError, "Accidental type #{accidental_pref} is not supported"
|
84
|
-
end
|
85
|
-
@accidental_pref = accidental_pref
|
86
|
-
reset_accidentals
|
87
|
-
end
|
61
|
+
def self.major tonic_pc
|
62
|
+
Key.new(tonic_pc, triad_type: MAJOR)
|
88
63
|
end
|
89
64
|
|
90
|
-
def
|
91
|
-
|
92
|
-
@tonic_pc = PitchClass.from_i(tonic_pc)
|
93
|
-
reset_accidentals
|
94
|
-
end
|
65
|
+
def self.minor tonic_pc
|
66
|
+
Key.new(tonic_pc, triad_type: MINOR)
|
95
67
|
end
|
96
|
-
|
68
|
+
|
69
|
+
def major?; @triad_type == MAJOR; end
|
70
|
+
def minor?; @triad_type == MINOR; end
|
71
|
+
|
72
|
+
def flat?; @accidental_type == FLAT; end
|
73
|
+
def sharp?; @accidental_type == SHARP; end
|
74
|
+
|
97
75
|
def ==(other)
|
98
|
-
return @tonic_pc == other.tonic_pc && @
|
99
|
-
@accidental_pref == other.accidental_pref
|
76
|
+
return @tonic_pc == other.tonic_pc && @triad_type == other.triad_type
|
100
77
|
end
|
101
78
|
|
102
79
|
def clone
|
103
80
|
Marshal.load(Marshal.dump(self))
|
104
81
|
end
|
105
|
-
|
106
|
-
def accidentals
|
107
|
-
unless @accidentals
|
108
|
-
@accidentals = []
|
109
|
-
unless accidental_free?
|
110
|
-
acc_type = accidental_type
|
111
|
-
idx = TONICS[@triad][acc_type].index(@tonic_pc)
|
112
|
-
@accidentals = ACCIDENTALS[acc_type].take(idx+1)
|
113
|
-
end
|
114
|
-
end
|
115
|
-
return @accidentals
|
116
|
-
end
|
117
|
-
|
118
|
-
def accidental_type
|
119
|
-
if accidental_free? || TONICS[@triad][@accidental_pref].include?(@tonic_pc)
|
120
|
-
@accidental_pref
|
121
|
-
else
|
122
|
-
(@accidental_pref == FLAT) ? SHARP : FLAT
|
123
|
-
end
|
124
|
-
end
|
125
82
|
|
126
83
|
def transpose interval
|
127
|
-
|
128
|
-
new_key.tonic_pc += interval
|
129
|
-
return new_key
|
84
|
+
Key.new(PitchClass.from_i(@tonic_pc+interval), @triad_type)
|
130
85
|
end
|
131
|
-
|
132
|
-
private
|
133
|
-
|
134
|
-
def reset_accidentals; @accidentals = nil; end
|
135
86
|
end
|
136
87
|
|
137
88
|
end
|
@@ -1,37 +1,38 @@
|
|
1
1
|
module Musicality
|
2
2
|
module Keys
|
3
|
-
C_MAJOR = Key.
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
A_MINOR = Key.
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
3
|
+
C_MAJOR = Key.major(PitchClasses::C)
|
4
|
+
|
5
|
+
# Major keys with sharps
|
6
|
+
G_MAJOR = Key.major(PitchClasses::G)
|
7
|
+
D_MAJOR = Key.major(PitchClasses::D)
|
8
|
+
A_MAJOR = Key.major(PitchClasses::A)
|
9
|
+
E_MAJOR = Key.major(PitchClasses::E)
|
10
|
+
B_MAJOR = Key.major(PitchClasses::B)
|
11
|
+
|
12
|
+
# Major keys with flats
|
13
|
+
F_MAJOR = Key.major(PitchClasses::F)
|
14
|
+
Bb_MAJOR = Key.major(PitchClasses::Bb)
|
15
|
+
Eb_MAJOR = Key.major(PitchClasses::Eb)
|
16
|
+
Ab_MAJOR = Key.major(PitchClasses::Ab)
|
17
|
+
Db_MAJOR = Key.major(PitchClasses::Db)
|
18
|
+
Gb_MAJOR = Key.major(PitchClasses::Gb)
|
19
|
+
|
20
|
+
A_MINOR = Key.minor(PitchClasses::A)
|
21
|
+
|
22
|
+
# Minor keys with sharps
|
23
|
+
E_MINOR = Key.minor(PitchClasses::E)
|
24
|
+
B_MINOR = Key.minor(PitchClasses::B)
|
25
|
+
Fs_MINOR = Key.minor(PitchClasses::Fs)
|
26
|
+
Cs_MINOR = Key.minor(PitchClasses::Cs)
|
27
|
+
Gs_MINOR = Key.minor(PitchClasses::Gs)
|
28
|
+
|
29
|
+
# Minor keys with flats
|
30
|
+
D_MINOR = Key.minor(PitchClasses::D)
|
31
|
+
G_MINOR = Key.minor(PitchClasses::G)
|
32
|
+
C_MINOR = Key.minor(PitchClasses::C)
|
33
|
+
F_MINOR = Key.minor(PitchClasses::F)
|
34
|
+
Bb_MINOR = Key.minor(PitchClasses::Bb)
|
35
|
+
Eb_MINOR = Key.minor(PitchClasses::Eb)
|
36
|
+
end
|
37
|
+
|
36
38
|
end
|
37
|
-
end
|
@@ -5,10 +5,10 @@ require 'set'
|
|
5
5
|
class Note
|
6
6
|
include Packable
|
7
7
|
include Validatable
|
8
|
-
|
8
|
+
|
9
9
|
attr_reader :pitches, :links, :duration, :marks
|
10
10
|
attr_accessor :articulation
|
11
|
-
|
11
|
+
|
12
12
|
def initialize duration, pitches = [], links: {}, articulation: Articulations::NORMAL, marks: []
|
13
13
|
self.duration = duration
|
14
14
|
if !pitches.is_a? Enumerable
|
@@ -19,18 +19,24 @@ class Note
|
|
19
19
|
@articulation = articulation
|
20
20
|
@marks = marks
|
21
21
|
end
|
22
|
-
|
22
|
+
|
23
23
|
def check_methods
|
24
|
-
[ :check_pitches ]
|
24
|
+
[ :check_duration, :check_pitches ]
|
25
|
+
end
|
26
|
+
|
27
|
+
def check_duration
|
28
|
+
if duration <= 0
|
29
|
+
raise RangeError, "Duration is non-positive: #{duration}"
|
30
|
+
end
|
25
31
|
end
|
26
|
-
|
32
|
+
|
27
33
|
def check_pitches
|
28
34
|
non_pitches = @pitches.select {|p| !p.is_a?(Pitch) }
|
29
35
|
if non_pitches.any?
|
30
36
|
raise TypeError, "Found non-pitches: #{non_pitches}"
|
31
37
|
end
|
32
38
|
end
|
33
|
-
|
39
|
+
|
34
40
|
def == other
|
35
41
|
return (@duration == other.duration) &&
|
36
42
|
(self.pitches == other.pitches) &&
|
@@ -38,7 +44,7 @@ class Note
|
|
38
44
|
(@articulation == other.articulation) &&
|
39
45
|
(@marks == marks)
|
40
46
|
end
|
41
|
-
|
47
|
+
|
42
48
|
def clone
|
43
49
|
Marshal.load(Marshal.dump(self))
|
44
50
|
end
|
@@ -55,10 +61,26 @@ class Note
|
|
55
61
|
return new_note
|
56
62
|
end
|
57
63
|
|
64
|
+
def tie_to pitches
|
65
|
+
new_note = self.clone
|
66
|
+
if pitches.is_a? Pitch
|
67
|
+
pitches = [pitches]
|
68
|
+
end
|
69
|
+
|
70
|
+
pitches.each do |pitch|
|
71
|
+
new_note.links[pitch] = Link::Tie.new
|
72
|
+
end
|
73
|
+
return new_note
|
74
|
+
end
|
75
|
+
|
76
|
+
def mark_accented!
|
77
|
+
@articulation = Articulations::ACCENT
|
78
|
+
end
|
79
|
+
|
58
80
|
def transpose diff
|
59
81
|
self.clone.transpose! diff
|
60
82
|
end
|
61
|
-
|
83
|
+
|
62
84
|
def transpose! diff
|
63
85
|
@pitches = @pitches.map {|pitch| pitch.transpose(diff) }
|
64
86
|
@links = Hash[ @links.map do |k,v|
|
@@ -106,7 +128,7 @@ class Note
|
|
106
128
|
Note.new(dur, pitches, articulation: articulation, links: links, marks: marks)
|
107
129
|
end
|
108
130
|
end
|
109
|
-
|
131
|
+
|
110
132
|
{
|
111
133
|
:sixteenth => Rational(1,16),
|
112
134
|
:dotted_sixteenth => Rational(3,32),
|
@@ -13,9 +13,9 @@ module Musicality
|
|
13
13
|
# @author James Tunnell
|
14
14
|
#
|
15
15
|
# @!attribute [r] octave
|
16
|
-
# @return [
|
16
|
+
# @return [Integer] The pitch octave.
|
17
17
|
# @!attribute [r] semitone
|
18
|
-
# @return [
|
18
|
+
# @return [Integer] The pitch semitone.
|
19
19
|
#
|
20
20
|
class Pitch
|
21
21
|
include Comparable
|
@@ -5,13 +5,19 @@ module Musicality
|
|
5
5
|
CONVERSION_METHOD = :to_r
|
6
6
|
include Parseable
|
7
7
|
end
|
8
|
-
|
8
|
+
|
9
9
|
class Pitch
|
10
10
|
PARSER = Parsing::PitchParser.new
|
11
11
|
CONVERSION_METHOD = :to_pitch
|
12
12
|
include Parseable
|
13
13
|
end
|
14
|
-
|
14
|
+
|
15
|
+
class Key
|
16
|
+
PARSER = Parsing::KeyParser.new
|
17
|
+
CONVERSION_METHOD = :to_key
|
18
|
+
include Parseable
|
19
|
+
end
|
20
|
+
|
15
21
|
class Note
|
16
22
|
PARSER = Parsing::NoteParser.new
|
17
23
|
CONVERSION_METHOD = :to_note
|
@@ -23,7 +29,7 @@ module Musicality
|
|
23
29
|
CONVERSION_METHOD = :to_meter
|
24
30
|
include Parseable
|
25
31
|
end
|
26
|
-
|
32
|
+
|
27
33
|
class Segment
|
28
34
|
PARSER = Parsing::SegmentParser.new
|
29
35
|
CONVERSION_METHOD = :to_range
|
@@ -37,38 +43,43 @@ class String
|
|
37
43
|
end
|
38
44
|
alias :to_dur :to_duration
|
39
45
|
alias :to_d :to_duration
|
40
|
-
|
46
|
+
|
41
47
|
def to_durations pattern=" "
|
42
48
|
Musicality::Duration.split_parse(self, pattern)
|
43
49
|
end
|
44
50
|
alias :to_durs :to_durations
|
45
51
|
alias :to_ds :to_durations
|
46
|
-
|
47
|
-
def to_pitch
|
52
|
+
|
53
|
+
def to_pitch
|
48
54
|
Musicality::Pitch.parse(self)
|
49
55
|
end
|
50
56
|
alias :to_p :to_pitch
|
51
|
-
|
57
|
+
|
52
58
|
def to_pitches pattern=" "
|
53
59
|
Musicality::Pitch.split_parse(self, pattern)
|
54
60
|
end
|
55
61
|
alias :to_ps :to_pitches
|
56
|
-
|
62
|
+
|
63
|
+
def to_key
|
64
|
+
Musicality::Key.parse(self)
|
65
|
+
end
|
66
|
+
alias :to_k :to_key
|
67
|
+
|
57
68
|
def to_note
|
58
69
|
Musicality::Note.parse(self)
|
59
70
|
end
|
60
71
|
alias :to_n :to_note
|
61
|
-
|
72
|
+
|
62
73
|
def to_notes pattern=" "
|
63
74
|
Musicality::Note.split_parse(self, pattern)
|
64
75
|
end
|
65
76
|
alias :to_ns :to_notes
|
66
|
-
|
77
|
+
|
67
78
|
def to_meter
|
68
79
|
Musicality::Meter.parse(self)
|
69
80
|
end
|
70
|
-
|
81
|
+
|
71
82
|
def to_segment
|
72
83
|
Musicality::Segment.parse(self)
|
73
84
|
end
|
74
|
-
end
|
85
|
+
end
|
@@ -80,7 +80,7 @@ module Duration
|
|
80
80
|
r2 = true
|
81
81
|
@index += match_len
|
82
82
|
else
|
83
|
-
terminal_parse_failure("/")
|
83
|
+
terminal_parse_failure('"/"')
|
84
84
|
r2 = nil
|
85
85
|
end
|
86
86
|
s0 << r2
|
@@ -128,7 +128,7 @@ module Duration
|
|
128
128
|
r3 = true
|
129
129
|
@index += match_len
|
130
130
|
else
|
131
|
-
terminal_parse_failure("/")
|
131
|
+
terminal_parse_failure('"/"')
|
132
132
|
r3 = nil
|
133
133
|
end
|
134
134
|
if r3
|
@@ -173,7 +173,7 @@ module Duration
|
|
173
173
|
r1 = true
|
174
174
|
@index += match_len
|
175
175
|
else
|
176
|
-
terminal_parse_failure("/")
|
176
|
+
terminal_parse_failure('"/"')
|
177
177
|
r1 = nil
|
178
178
|
end
|
179
179
|
s0 << r1
|
@@ -0,0 +1,150 @@
|
|
1
|
+
# Autogenerated from a Treetop grammar. Edits may be lost.
|
2
|
+
|
3
|
+
|
4
|
+
module Musicality
|
5
|
+
module Parsing
|
6
|
+
|
7
|
+
module Key
|
8
|
+
include Treetop::Runtime
|
9
|
+
|
10
|
+
def root
|
11
|
+
@root ||= :key
|
12
|
+
end
|
13
|
+
|
14
|
+
include Pitch
|
15
|
+
|
16
|
+
module Key0
|
17
|
+
def pitch_letter
|
18
|
+
elements[0]
|
19
|
+
end
|
20
|
+
|
21
|
+
def mod
|
22
|
+
elements[1]
|
23
|
+
end
|
24
|
+
|
25
|
+
def major_minor
|
26
|
+
elements[2]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
module Key1
|
31
|
+
def to_key
|
32
|
+
sem = pitch_letter.to_semitone
|
33
|
+
modval = 0
|
34
|
+
if !mod.empty?
|
35
|
+
modval = case mod.text_value
|
36
|
+
when "#" then 1
|
37
|
+
when "b" then -1
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
triad_type = if major_minor.text_value.include?("maj")
|
42
|
+
Musicality::Key::MAJOR
|
43
|
+
else
|
44
|
+
Musicality::Key::MINOR
|
45
|
+
end
|
46
|
+
|
47
|
+
return Musicality::Key.new(sem + modval, triad_type: triad_type)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def _nt_key
|
52
|
+
start_index = index
|
53
|
+
if node_cache[:key].has_key?(index)
|
54
|
+
cached = node_cache[:key][index]
|
55
|
+
if cached
|
56
|
+
node_cache[:key][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
|
57
|
+
@index = cached.interval.end
|
58
|
+
end
|
59
|
+
return cached
|
60
|
+
end
|
61
|
+
|
62
|
+
i0, s0 = index, []
|
63
|
+
r1 = _nt_pitch_letter
|
64
|
+
s0 << r1
|
65
|
+
if r1
|
66
|
+
if has_terminal?(@regexps[gr = '\A[#b]'] ||= Regexp.new(gr), :regexp, index)
|
67
|
+
r3 = true
|
68
|
+
@index += 1
|
69
|
+
else
|
70
|
+
terminal_parse_failure('[#b]')
|
71
|
+
r3 = nil
|
72
|
+
end
|
73
|
+
if r3
|
74
|
+
r2 = r3
|
75
|
+
else
|
76
|
+
r2 = instantiate_node(SyntaxNode,input, index...index)
|
77
|
+
end
|
78
|
+
s0 << r2
|
79
|
+
if r2
|
80
|
+
r4 = _nt_major_minor
|
81
|
+
s0 << r4
|
82
|
+
end
|
83
|
+
end
|
84
|
+
if s0.last
|
85
|
+
r0 = instantiate_node(SyntaxNode,input, i0...index, s0)
|
86
|
+
r0.extend(Key0)
|
87
|
+
r0.extend(Key1)
|
88
|
+
else
|
89
|
+
@index = i0
|
90
|
+
r0 = nil
|
91
|
+
end
|
92
|
+
|
93
|
+
node_cache[:key][start_index] = r0
|
94
|
+
|
95
|
+
r0
|
96
|
+
end
|
97
|
+
|
98
|
+
def _nt_major_minor
|
99
|
+
start_index = index
|
100
|
+
if node_cache[:major_minor].has_key?(index)
|
101
|
+
cached = node_cache[:major_minor][index]
|
102
|
+
if cached
|
103
|
+
node_cache[:major_minor][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
|
104
|
+
@index = cached.interval.end
|
105
|
+
end
|
106
|
+
return cached
|
107
|
+
end
|
108
|
+
|
109
|
+
i0 = index
|
110
|
+
if (match_len = has_terminal?("maj", false, index))
|
111
|
+
r1 = instantiate_node(SyntaxNode,input, index...(index + match_len))
|
112
|
+
@index += match_len
|
113
|
+
else
|
114
|
+
terminal_parse_failure('"maj"')
|
115
|
+
r1 = nil
|
116
|
+
end
|
117
|
+
if r1
|
118
|
+
r1 = SyntaxNode.new(input, (index-1)...index) if r1 == true
|
119
|
+
r0 = r1
|
120
|
+
else
|
121
|
+
if (match_len = has_terminal?("min", false, index))
|
122
|
+
r2 = instantiate_node(SyntaxNode,input, index...(index + match_len))
|
123
|
+
@index += match_len
|
124
|
+
else
|
125
|
+
terminal_parse_failure('"min"')
|
126
|
+
r2 = nil
|
127
|
+
end
|
128
|
+
if r2
|
129
|
+
r2 = SyntaxNode.new(input, (index-1)...index) if r2 == true
|
130
|
+
r0 = r2
|
131
|
+
else
|
132
|
+
@index = i0
|
133
|
+
r0 = nil
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
node_cache[:major_minor][start_index] = r0
|
138
|
+
|
139
|
+
r0
|
140
|
+
end
|
141
|
+
|
142
|
+
end
|
143
|
+
|
144
|
+
class KeyParser < Treetop::Runtime::CompiledParser
|
145
|
+
include Key
|
146
|
+
end
|
147
|
+
|
148
|
+
|
149
|
+
end
|
150
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Musicality
|
2
|
+
module Parsing
|
3
|
+
|
4
|
+
grammar Key
|
5
|
+
include Pitch
|
6
|
+
|
7
|
+
rule key
|
8
|
+
pitch_letter mod:[#b]? major_minor {
|
9
|
+
def to_key
|
10
|
+
sem = pitch_letter.to_semitone
|
11
|
+
modval = 0
|
12
|
+
if !mod.empty?
|
13
|
+
modval = case mod.text_value
|
14
|
+
when "#" then 1
|
15
|
+
when "b" then -1
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
triad_type = if major_minor.text_value.include?("maj")
|
20
|
+
Musicality::Key::MAJOR
|
21
|
+
else
|
22
|
+
Musicality::Key::MINOR
|
23
|
+
end
|
24
|
+
|
25
|
+
return Musicality::Key.new(sem + modval, triad_type: triad_type)
|
26
|
+
end
|
27
|
+
}
|
28
|
+
end
|
29
|
+
|
30
|
+
rule major_minor
|
31
|
+
"maj" / "min"
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
@@ -80,7 +80,7 @@ module Meter
|
|
80
80
|
r2 = true
|
81
81
|
@index += match_len
|
82
82
|
else
|
83
|
-
terminal_parse_failure("/")
|
83
|
+
terminal_parse_failure('"/"')
|
84
84
|
r2 = nil
|
85
85
|
end
|
86
86
|
s0 << r2
|
@@ -142,7 +142,7 @@ module Meter
|
|
142
142
|
r2 = true
|
143
143
|
@index += match_len
|
144
144
|
else
|
145
|
-
terminal_parse_failure("*")
|
145
|
+
terminal_parse_failure('"*"')
|
146
146
|
r2 = nil
|
147
147
|
end
|
148
148
|
s0 << r2
|
@@ -154,7 +154,7 @@ module Meter
|
|
154
154
|
r4 = true
|
155
155
|
@index += match_len
|
156
156
|
else
|
157
|
-
terminal_parse_failure("/")
|
157
|
+
terminal_parse_failure('"/"')
|
158
158
|
r4 = nil
|
159
159
|
end
|
160
160
|
s0 << r4
|
@@ -36,12 +36,14 @@ module NonnegativeFloat
|
|
36
36
|
r1 = SyntaxNode.new(input, (index-1)...index) if r1 == true
|
37
37
|
r0 = r1
|
38
38
|
r0.extend(NonnegativeFloat0)
|
39
|
+
r0.extend(NonnegativeFloat0)
|
39
40
|
else
|
40
41
|
r2 = _nt_float2
|
41
42
|
if r2
|
42
43
|
r2 = SyntaxNode.new(input, (index-1)...index) if r2 == true
|
43
44
|
r0 = r2
|
44
45
|
r0.extend(NonnegativeFloat0)
|
46
|
+
r0.extend(NonnegativeFloat0)
|
45
47
|
else
|
46
48
|
@index = i0
|
47
49
|
r0 = nil
|
@@ -222,7 +224,7 @@ module NonnegativeFloat
|
|
222
224
|
r1 = true
|
223
225
|
@index += match_len
|
224
226
|
else
|
225
|
-
terminal_parse_failure("e")
|
227
|
+
terminal_parse_failure('"e"')
|
226
228
|
r1 = nil
|
227
229
|
end
|
228
230
|
s0 << r1
|