/** Function to compute the spectral distance between two song models. * This is a fast implementation of the symmetrized Kullback Leibler * Divergence. */ public static float Distance(Scms s1, Scms s2, ScmsConfiguration c) { float val = 0; int i; int k; int idx = 0; int dim = c.Dimension; int covlen = c.CovarianceLength; float tmp1; unsafe { fixed (float* s1cov = s1.cov, s2icov = s2.icov, s1icov = s1.icov, s2cov = s2.cov, s1mean = s1.mean, s2mean = s2.mean, mdiff = c.MeanDiff, aicov = c.AddInverseCovariance) { for (i = 0; i < covlen; i++) { aicov[i] = s1icov[i] + s2icov[i]; } for (i = 0; i < dim; i++) { idx = i*dim - (i*i+i)/2; val += s1cov[idx+i] * s2icov[idx+i] + s2cov[idx+i] * s1icov[idx+i]; for (k = i+1; k < dim; k++) { val += 2*s1cov[idx+k] * s2icov[idx+k] + 2*s2cov[idx+k] * s1icov[idx+k]; } } for (i = 0; i < dim; i++) { mdiff[i] = s1mean[i] - s2mean[i]; } for (i = 0; i < dim; i++) { idx = i - dim; tmp1 = 0; for (k = 0; k <= i; k++) { idx += dim - k; tmp1 += aicov[idx] * mdiff[k]; } for (k = i + 1; k < dim; k++) { idx++; tmp1 += aicov[idx] * mdiff[k]; } val += tmp1 * mdiff[i]; } } } // FIXME: fix the negative return values //val = Math.Max(0.0f, (val/2 - s1.cov.dim)); val = val / 4 - c.Dimension / 2; return val; }
private static void Test() { mirageaudio_initgst(); string song1_filename = "/home/lorentz/Music/Library/Pachelbel/Johann Pachelbel - Canon And Gigue In D Major For 3 Violins And Basso Continuo.mp3"; string song2_filename = "/home/lorentz/Music/Library/Karajan Adagios/CD 1/Pachelbel - Canon in d Major (Kanon And Gigue in d Major = d Dur) av Johann Pachelbel.mp3"; Scms song1 = null; Scms song2 = null; DbgTimer t1 = new DbgTimer(); t1.Start(); int runs = 10; for (int i = 0; i < runs; i++) { Analyzer.Analyze(song1_filename); } long l1 = 0; t1.Stop(ref l1); Dbg.WriteLine("Analysis: " + runs + " times - " + l1 + "ms; " + (double)l1/(double)runs + "ms per analysis"); song1 = Analyzer.Analyze(song1_filename); song2 = Analyzer.Analyze(song2_filename); ScmsConfiguration config = new ScmsConfiguration (Analyzer.MFCC_COEFFICIENTS); Console.WriteLine("Distance = " + Scms.Distance (song1, song2, config)); DbgTimer t2 = new DbgTimer(); t2.Start(); runs = 100000; for (int i = 0; i < runs; i++) { Scms.Distance (song1, song2, config); } long l2 = 0; t2.Stop(ref l2); Dbg.WriteLine("Distance Computation: " + runs + " times - " + l2 + "ms; " + (double)l2/(double)runs + "ms per comparison"); }
/** Function to compute the spectral distance between two song models. * This is a fast implementation of the symmetrized Kullback Leibler * Divergence. */ public static float Distance(Scms s1, Scms s2, ScmsConfiguration c) { float val = 0; int i; int k; int idx = 0; int dim = c.Dimension; int covlen = c.CovarianceLength; float tmp1; unsafe { fixed(float *s1cov = s1.cov, s2icov = s2.icov, s1icov = s1.icov, s2cov = s2.cov, s1mean = s1.mean, s2mean = s2.mean, mdiff = c.MeanDiff, aicov = c.AddInverseCovariance) { for (i = 0; i < covlen; i++) { aicov[i] = s1icov[i] + s2icov[i]; } for (i = 0; i < dim; i++) { idx = i * dim - (i * i + i) / 2; val += s1cov[idx + i] * s2icov[idx + i] + s2cov[idx + i] * s1icov[idx + i]; for (k = i + 1; k < dim; k++) { val += 2 * s1cov[idx + k] * s2icov[idx + k] + 2 * s2cov[idx + k] * s1icov[idx + k]; } } for (i = 0; i < dim; i++) { mdiff[i] = s1mean[i] - s2mean[i]; } for (i = 0; i < dim; i++) { idx = i - dim; tmp1 = 0; for (k = 0; k <= i; k++) { idx += dim - k; tmp1 += aicov[idx] * mdiff[k]; } for (k = i + 1; k < dim; k++) { idx++; tmp1 += aicov[idx] * mdiff[k]; } val += tmp1 * mdiff[i]; } } } // FIXME: fix the negative return values //val = Math.Max(0.0f, (val/2 - s1.cov.dim)); val = val / 4 - c.Dimension / 2; return(val); }