forked from miditoolbox/1.1
-
Notifications
You must be signed in to change notification settings - Fork 0
/
meldistance.m
executable file
·135 lines (128 loc) · 4.52 KB
/
meldistance.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
function y = meldistance(nmat1,nmat2,repr,metric,samples,rescale)
% Measurement of distance between two NMATs
% y=melsim(nmat1,nmat2,<repr>,<metric>,<samples>,<rescale>)
% Calculates the similarity of two NMATs in a particular representation.
% Output is a value indicating distance between nmat1 and nmat2 under
% the given representation and metric. Output value is rescaled to [0, 1] if
% rescale is set to 1.
%
% Input arguments:
% NMAT1= first notematrix
% NMAT2= second notematrix
% REPR= string denoting the specific representation used for comparison of the two NMATs:
% 'pcdist1' (default)= distribution of pitch classes
% 'pcdist2'= distribution of pitch class dyads
% 'ivdist1'= distribution of intervals
% 'ivdist2'= distribution of interval dyads
% 'contour'= melodic contour (input number of samples)
% 'combcontour'= Combinatorial Contour (does not accept a metric argument)
% 'durdist1'= distribution of note durations
% 'durdist2'= distribution of note duration dyads
% METRIC= string denoting the distance metric used for comparison:
% 'taxi' (default)=the taxicab norm
% 'euc'=euclidean distance measure
% 'cosine' =measure of cosine of the angle between vectors
% SAMPLES= integer number of samples for contour representation.
% default value is 10.
% RESCALE= rescales distance to similarity value between 0 and 1. Default
% is no rescaling. Set to 1 to rescale values.
%
% Output:
% y = value representing the distance between the two
% melodies under the given representation and metric.
%
% Example:
% meldistance(nmat1,nmat2,'pcdist1','taxi');
%
% Authors:
% Date Time Prog Note
% 15.2.2004 15:30 MB Created under MATLAB 6.1 (PC)
%© Part of the MIDI Toolbox, Copyright © 2004, University of Jyväskylä, Finland
% See License.txt
if isempty(nmat1), return; end
if isempty(nmat2), return; end
if ~ismonophonic(nmat1), disp([mfilename, ' works only with monophonic input!']); y=[]; return; end
if ~ismonophonic(nmat2), disp([mfilename, ' works only with monophonic input!']); y=[]; return; end
% Includes firstnbeats selector function, combcontour CSIM matrix constructor
if nargin <3
repr='pcdist1';
metric='taxi';
rescale=0;
elseif nargin <4
metric='taxi';
rescale=0;
elseif nargin<5
samples=10;
rescale=0;
elseif nargin<6
rescale=0;
end
switch lower(repr)
%if representation is a normalised distribution, we only need to calculate it.
case {'ivdist1','ivdist2','pcdist1','pcdist2','durdist1','durdist2'}
repr_of_1=feval(char(repr),nmat1);
repr_of_2=feval(char(repr),nmat2);
y=distance(repr_of_1,repr_of_2,metric);
%Now we rescale to map y->[0,1]
if rescale
if strcmp(metric,'taxi')
refl=1;
elseif strcmp(metric,'euc')
refl=1;
elseif strcmp(metric,'cosine')
refl=.15;
end
if y < refl
y=(2*(refl-y)+y)/2;
else
y=(y-2*(y-refl))/2;
end
end
%if the representation chosen is contour, we need to scale the contour stepsize so that
%both contour vectors are of the same length. Note: in order to be useful we are operating
%under theassumption that the nmats passed to mel_sim are of reasonably similar length.
case 'contour'
repr_of_1=melcontour(nmat1,samples,'rel');
repr_of_2=melcontour(nmat2,samples,'rel');
%Now we subtract the mean of the contour vectors to effectively discard pitch height
repr_of_1=repr_of_1-mean(repr_of_1);
repr_of_2=repr_of_2-mean(repr_of_2);
y=distance(repr_of_1,repr_of_2,metric);
if rescale % rescale y->[0,1]
if strcmp(metric,'taxi')
refl=8*samples;
elseif strcmp(metric,'euc')
refl=2*samples;
elseif strcmp(metric,'cosine')
refl=15*samples;
y=y+11*samples;
end
if y < refl
y=(2*refl-y)/(2*refl);
else
y=(y-2*(y-refl))/(2*refl);
end
end
case 'combcontour'
notes1=length(nmat1);
notes2=length(nmat2);
if notes1>=notes2
repr_of_1=combcontour(nmat1(1:notes2,:));
repr_of_2=combcontour(nmat2);
else
repr_of_1=combcontour(nmat1);
repr_of_2=combcontour(nmat2(1:notes1,:));
end;
diff=abs(repr_of_1-repr_of_2); %Comb contour ignores the chosen metric and uses the CSIM metric instead.
n=length(diff);
y=(sum(sum(diff)))/(n^2-n);
% rescale to map y=[0,1]
if rescale
refl=.5;
if y < refl
y=(2*(refl-y)+y);
else
y=(y-2*(y-refl));
end
end
end