-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathparseChord_v2.m
192 lines (182 loc) · 7.72 KB
/
parseChord_v2.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
function [chordindex, bassnote] = parseChord_v2(chord, numchords)
% Parses chord and relates it to an index corresponding to a template with
% numchords chords. So, for example, 'C:maj' would correspond to index 1,
% 'B:min' would correspond to index 24. If numchords==24, then B:min7 would
% also correspond to index 24. If numchords==48, then it would correspond
% to 48.
% Uses a lot of code from loadGroundTruth.m, but this only handles one
% chord at a time.
true_chord = chord; % (Directly becomes string)
% get root name
if length(true_chord) > 1 && strcmp(true_chord(2),'#')==1 || strcmp(true_chord,'b')==1,
capital = true_chord(1:2); % Get the first character in string as capital
else
capital = true_chord(1);
end;
if capital == 'Ab'
id = 9;
elseif capital == 'A'
id = 10;
elseif capital == 'A#'
id = 11;
elseif capital == 'Bb'
id = 11;
elseif capital == 'B'
id = 12;
elseif capital == 'C'
id = 1;
elseif capital == 'C#'
id = 2;
elseif capital == 'Db'
id = 2;
elseif capital == 'D'
id = 3;
elseif capital == 'D#'
id = 4;
elseif capital == 'Eb'
id = 4;
elseif capital == 'E'
id = 5;
elseif capital == 'F'
id = 6;
elseif capital == 'F#'
id = 7;
elseif capital == 'Gb'
id = 7;
elseif capital == 'G'
id = 8;
elseif capital == 'G#'
id = 9;
elseif capital == 'N' % Map Null to zero
id = numchords+1;
elseif capital == 'X'
id = numchords+1;
end;
% Now I have an array of number between 1-12, and numchords+1 for N or X
% For Harte-specific inversion/seventh notation...
% intialize "bassnote" vector
bassnote = id; flat_bass = 0; sharp_bass = 0; two = 0; three = 1; five = 0; seven = 0;
% bassnote will be mod(id + bassnote, 12), ish...
% find '(' and '/' and ignore that shit
slash_index = find(true_chord=='/',1,'first');
if slash_index
% if doBass,
addl = str2num(true_chord(end));
if addl == 2 || addl == 9,
bassnote = mod(bassnote + 2, 12);
if bassnote == 0, bassnote = 12; end;
two = 1; % flag for second to check later if it's quality-dependent
elseif addl == 3,
bassnote = mod(bassnote + 4, 12); % check later if the chord is minor/diminished, and subtract one
if bassnote == 0, bassnote = 12; end;
three = 1;
elseif addl == 5,
bassnote = mod(bassnote + 7, 12); % check later if the chord is diminished, and subtract one
if bassnote == 0, bassnote = 12; end;
five = 1;
elseif addl == 7,
bassnote = mod(bassnote + 10, 12); % check later if it's a maj7
if bassnote == 0, bassnote = 12; end;
seven = 1;
end;
if length(true_chord)-slash_index == 2, % then we have a sharp or a flat, since there's no "/11" i don't think...
if true_chord(slash_index+1)=='b',
bassnote = bassnote-1;
if bassnote == 0, bassnote = 12; end;
flat_bass = 1;
sharp_bass = 0;
elseif true_chord(slash_index+1)=='#',
bassnote = mod(bassnote+1,12);
if bassnote == 0, bassnote = 12; end;
flat_bass = 0;
sharp_bass = 1;
end;
end;
% end; % end bassnote detection
true_chord = true_chord(1:slash_index-1); % ditch everything after and including the slash
end;
paren_index = find(true_chord=='(',1,'first');
if paren_index
true_chord = true_chord(1:paren_index-1);
end;
% in some cases this leaves a dangling ':', which is a major chord
if true_chord(end) == ':',
true_chord = true_chord(1:end-1);
end;
% if length(true_chord) > 2,
% if true_chord(end-1) == '/',
% bassnote = true_chord(end);
% true_chord = true_chord(1:end-2); % drop the slash, too
% elseif true_chord(end-2) == '/',
% bassnote = true_chord(end-1:end);
% true_chord = true_chord(1:end-3);
% end;
% end;
%
% % ignore shit in parentheses; just refers to non-chord tones that
% % aren't the root, i assume
% if length(true_chord) > 4,
% if true_chord(end-2) == '(',
% true_chord = true_chord(1:end-3);
% elseif true_chord(end-3) == '(',
% true_chord = true_chord(1:end-4);
% elseif true_chord(end-3) == '/', % potentially a "b11" could exist?
% bassnote = true_chord(end-2:end);
% true_chord = true_chord(1:end-4);
% end;
% end;
% determine if there's a seventh
seventh = 0; % initialize
if true_chord(end) == '7' || true_chord(end) == '9' && numchords == 48, % don't care whether it's a maj7 or min7 in our template
seventh = 1;
end;
% determine quality
fourth = 'n'; % initialize
if length(true_chord) > 4,
if true_chord(3) == 'm' || true_chord(4) == 'u' || true_chord(3) == 'd' || true_chord(3) == 'h', % e.g. 'F:maj','F:min','F:aug','F:dim'
fourth = true_chord(4); % quality will be either 'a' (maj), 'u' (aug), 'i' (dim), or 'd' (hdim)
elseif true_chord(4) == 'm' || true_chord(5) == 'u' || true_chord(4) == 'd' || true_chord(4) == 'h', % e.g. 'F#:maj',...,'F#:dim'
fourth = true_chord(5);
elseif true_chord(3) == 's', % if sustained
fourth = 'a'; % call it major
end;
end;
% place the chord on the template (applies to 24 and 48 numchords)
if true_chord(1) == 'N' || true_chord(1) == 'X',
chordindex = numchords+1; % map the 'silence' case to an unused index
elseif length(true_chord) < 3, % e.g. 'F' or 'F#'
chordindex = id;
elseif fourth == 'a' && seventh == 0, % e.g. 'F:maj' or 'F#:maj'
chordindex = id;
elseif length(true_chord) < 5 && seventh == 1, % e.g. 'F:7' or 'F#:7'
chordindex = id + 24;
elseif fourth == 'i' && seventh == 0, % e.g. 'F:min','F#:min','F:dim','F#:dim'
chordindex = id + 12;
if three, bassnote = bassnote - 1; end;
if bassnote == 0, bassnote = 12; end;
elseif fourth == 'a' && seventh == 1, % e.g. 'F:maj7','F#:maj7','F:majmin7', etc.
chordindex = id + 24;
if seven && true_chord(end-2) == 'a', bassnote = mod(bassnote + 1, 12); end;
if bassnote == 0, bassnote = 12; end;
elseif fourth == 'i' && seventh == 1, % e.g. 'F:min7','F#:min7','F:dim7','F#:dim7','F:minmaj7',...,'F#:dimmaj7'
chordindex = id + 36;
if seven && true_chord(end-2) == 'a', bassnote = mod(bassnote + 1, 12); end;
if bassnote == 0, bassnote = 12; end;
elseif fourth == 'u' && seventh == 0, % e.g. 'F:aug' or 'F#:aug'
chordindex = id;
if five, bassnote = bassnote + 1; end;
if bassnote == 13, bassnote = 1; end;
elseif fourth == 'u' && seventh == 1, % e.g. 'F:aug7' or 'F#:aug7'
chordindex = id + 24;
if five, bassnote = bassnote + 1; end;
if bassnote == 13, bassnote = 1; end;
elseif fourth == 'd' && seventh == 0, % e.g. 'F:hdim' or 'F#:hdim'
chordindex = id + 12;
if three || five, bassnote = bassnote - 1; end;
if bassnote == 0, bassnote = 12; end;
elseif fourth == 'd' && seventh == 1, % e.g. 'F:hdim7', ..., 'F#:hdimmaj7' (which would be redundant, btw)
chordindex = id + 36;
if three || five, bassnote = bassnote - 1; end;
if bassnote == 0, bassnote = 12; end;
end;
end