matthiasm@8
|
1 function rootspelling = chordroot_spelling(key, root, degrees)
|
matthiasm@8
|
2
|
matthiasm@8
|
3 temp = strsplit(':', key);
|
matthiasm@8
|
4 keyroot = temp{1};
|
matthiasm@8
|
5 if length(temp) > 1
|
matthiasm@8
|
6 keymode = temp{2};
|
matthiasm@8
|
7 else
|
matthiasm@8
|
8 keymode = 'major';
|
matthiasm@8
|
9 end
|
matthiasm@8
|
10
|
matthiasm@8
|
11
|
matthiasm@8
|
12
|
matthiasm@8
|
13 % major scale
|
matthiasm@8
|
14 scale{1} = [0 2 4 5 7 9 11];
|
matthiasm@8
|
15 % harmonic minor scale
|
matthiasm@8
|
16 scale{2} = [0 2 3 5 7 8 11];
|
matthiasm@8
|
17
|
matthiasm@8
|
18 diatonic = {'C','D','E','F','G','A','B'};
|
matthiasm@8
|
19 keymode_number = find(strcmp({'major','minor'},keymode));
|
matthiasm@8
|
20
|
matthiasm@8
|
21 if ischar(root)
|
matthiasm@8
|
22 rootdegree = find(strcmp(diatonic,root(1)));
|
matthiasm@8
|
23 rootpc = scale{1}(strcmp(diatonic,root(1))) + length(strfind(root,'#')) - length(strfind(root,'b'));
|
matthiasm@8
|
24 else
|
matthiasm@8
|
25 [rootdegree, rootdegree]= min(abs(scale{1}-root));
|
matthiasm@8
|
26 rootpc = root;
|
matthiasm@8
|
27 end
|
matthiasm@8
|
28
|
matthiasm@8
|
29
|
matthiasm@8
|
30 deg = [];
|
matthiasm@8
|
31 pcs = [];
|
matthiasm@8
|
32 for ii = 1:length(degrees)
|
matthiasm@8
|
33 deg = [deg mod(rootdegree + str2num(degrees{ii}(end)) - 2,7)+1];
|
matthiasm@8
|
34 pcs = [pcs mod(rootpc + degree2semitone(degrees{ii}),12)];
|
matthiasm@8
|
35 end
|
matthiasm@8
|
36
|
matthiasm@8
|
37 keyrootpc = scale{1}(strcmp(diatonic,keyroot(1))) + length(strfind(keyroot,'#')) - length(strfind(keyroot,'b'));
|
matthiasm@8
|
38 keydegree = find(strcmp(diatonic,keyroot(1)));
|
matthiasm@8
|
39
|
matthiasm@8
|
40 scalesemitone = circshift(mod(scale{keymode_number} + keyrootpc,12),[0 keydegree-1]);
|
matthiasm@8
|
41
|
matthiasm@8
|
42 fit = [0 0 0];
|
matthiasm@8
|
43
|
matthiasm@8
|
44 for deviation = -1:1 % test if the best degree is lower, just right or higher
|
matthiasm@8
|
45 currdeg = mod(deg+deviation-1,7) + 1;
|
matthiasm@8
|
46 chordaccidentals = mod(scalesemitone(currdeg) - pcs + 12 + 6,12) - 6;
|
matthiasm@8
|
47 fit(deviation+2) = sum(abs(chordaccidentals));
|
matthiasm@8
|
48 end
|
matthiasm@8
|
49 [bestfitval, bestfit] = min(fit);
|
matthiasm@8
|
50 bestrootdegree = mod(rootdegree + bestfit - 2 - 1,7) + 1;
|
matthiasm@8
|
51 bestrootaccidentals = mod(rootpc - scale{1}(bestrootdegree)+6,12)-6;
|
matthiasm@8
|
52 switch bestrootaccidentals
|
matthiasm@8
|
53 case -2
|
matthiasm@8
|
54 suff = 'bb';
|
matthiasm@8
|
55 case -1
|
matthiasm@8
|
56 suff = 'b';
|
matthiasm@8
|
57 case 0
|
matthiasm@8
|
58 suff = '';
|
matthiasm@8
|
59 case 2
|
matthiasm@8
|
60 suff = '##';
|
matthiasm@8
|
61 case 1
|
matthiasm@8
|
62 suff = '#';
|
matthiasm@8
|
63 end
|
matthiasm@8
|
64 rootspelling = [diatonic{bestrootdegree}, suff]; |