diff toolboxes/MIRtoolbox1.3.2/MIRToolbox/mirdist.m @ 0:e9a9cd732c1e tip

first hg version after svn
author wolffd
date Tue, 10 Feb 2015 15:05:51 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toolboxes/MIRtoolbox1.3.2/MIRToolbox/mirdist.m	Tue Feb 10 15:05:51 2015 +0000
@@ -0,0 +1,122 @@
+function d = mirdist(x,y,dist)
+%   d = mirdist(x,y) evaluates the distance between x and y.
+%   x is the feature values corresponding to one audio file, and y is the
+%       values (for the same feature) corrdponding to one (or several)
+%       audio files.
+%   If x and y are not decomposed into frames,
+%       d = mirdist(x,y,f) specifies distance function.
+%           Default value: f = 'Cosine'
+%   If x and y are composed of clustered frames (using mircluster), the
+%       cluster signatures are compared using Earth Mover Distance.
+%       (Logan, Salomon, 2001)
+%   If x and y contains peaks, the vectors representing the peak
+%       distributions are compared using Euclidean distance.
+%       (used with mirnovelty in Jacobson, 2006)
+%
+% The Earth Mover Distance is based on the implementation by Yossi Rubner,
+% wrapped for Matlab by Elias Pampalk.
+
+if not(isa(x,'mirdata'))
+    x = miraudio(x);
+end
+if not(isa(y,'mirdata'))
+    y = miraudio(y);
+end
+
+clx = get(x,'Clusters');
+if isempty(clx{1})
+    px = get(x,'PeakPos');
+    if not(iscell(px)) || isempty(px{1}) || ...
+            not(iscell(px{1})) || isempty(px{1}{1}) || not(iscell(px{1}{1}))
+        if nargin < 3
+            dist = 'Cosine';
+        end
+
+        d = get(x,'Data');
+        dd = d{1}{1};
+        if iscell(dd)
+            dd = dd{1};
+        end
+        if size(dd,2)>1
+            if size(dd,1)>1
+                error('ERROR IN MIRDIST: If the input is decomposed into frames, they should first be clustered.'); 
+            else
+                dd = dd';
+            end
+        end
+
+        e = get(y,'Data');
+        dt = cell(1,length(e));
+        for h = 1:length(e)
+            ee = e{h}{1};
+            if iscell(ee)
+                ee = ee{1};
+            end
+            if size(ee,2)>1
+                if size(ee,1)>1
+                    error('ERROR IN MIRDIST: If the input is decomposed into frames, they should first be clustered.'); 
+                else
+                    ee = ee';
+                end
+            end
+            if isempty(ee)
+                if isempty(dd)
+                    dt{h}{1} = 0;
+                else
+                    dt{h}{1} = Inf;
+                end
+            else
+                if length(dd)<length(ee)
+                    dd(length(ee)) = 0;
+                    %ee = ee(1:length(d));
+                elseif length(ee)<length(dd)
+                    ee(length(dd)) = 0;
+                    %dd = dd(1:length(ee));
+                end
+                if length(dd) == 1
+                    dt{h}{1} = abs(dd-ee);
+                elseif norm(dd) && norm(ee)
+                    dt{h}{1} = pdist([dd(:)';ee(:)'],dist);
+                else
+                    dt{h}{1} = NaN;
+                end
+            end
+        end
+    else
+        % Euclidean distance between vectors to compare data with peaks
+        % (used with mirnovelty in Jacobson, 2006).
+        sig = pi/4;
+        dx = get(x,'Data');
+        nx = length(px{1}{1}{1});
+        cx = mean(px{1}{1}{1}/length(dx{1}{1}));
+        dy = get(y,'Data');
+        py = get(y,'PeakPos');
+        dt = cell(1,length(py));
+        for h = 1:length(py)
+            ny = length(py{h}{1}{1});
+            cy = mean(py{h}{1}{1}/length(dy{h}{1}));
+            dt{h}{1} = sqrt((nx*cos(sig*cx)-ny*cos(sig*cy))^2 ...
+                           +(nx*sin(sig*cx)-ny*sin(sig*cy))^2);
+        end
+    end
+else
+    % Earth Mover's Distance to compare clustered data.
+    cly = get(y,'Clusters');
+    dt = cell(1,length(cly));
+    for h = 1:length(cly)
+        cost = zeros(length(clx{1}.weight),length(cly{h}.weight));
+        for i = 1:length(clx{1}.weight)
+            for j = 1:length(cly{h}.weight)
+                covx = clx{1}.covar(:,i);
+                covy = cly{h}.covar(:,j);
+                mux = clx{1}.centr(:,i);
+                muy = cly{h}.centr(:,j);
+                cost(i,j) = sum(covx./covy + covy./covx + ...
+                        (mux-muy).^2.*(1./covx + 1./covy) - 2);
+            end
+        end
+        dt{h}{1} = emd_wrapper(cost,clx{1}.weight,cly{h}.weight);
+    end
+end
+d = mirscalar(y,'Data',dt,'Title',[get(y,'Title'),' Distance'],...
+                'Name',get(x,'Name'),'Name2',get(y,'Name'));
\ No newline at end of file