public static Scms FromBytes(byte [] buf) { var scms = new Scms(Analyzer.MFCC_COEFFICIENTS); FromBytes(buf, scms); return(scms); }
/// <summary> /// Using the passed datareader pointer, fill the audio feature tracks array with content /// </summary> /// <param name="tracksIterator">datareader pointer</param> /// <param name="tracks">AudioFeature array</param> /// <param name="mapping">array of trackids</param> /// <param name="len">number of tracks to return</param> /// <param name="analysisMethod">analysis method (SCMS or MandelEllis)</param> /// <returns>number of tracks returned</returns> public int GetNextTracks(ref IDataReader tracksIterator, ref AudioFeature[] tracks, ref int[] mapping, int len, Analyzer.AnalysisMethod analysisMethod) { int i = 0; while ((i < len) && tracksIterator.Read()) { AudioFeature audioFeature = null; switch (analysisMethod) { case Analyzer.AnalysisMethod.MandelEllis: audioFeature = MandelEllis.FromBytes((byte[])tracksIterator.GetValue(0)); break; case Analyzer.AnalysisMethod.SCMS: audioFeature = Scms.FromBytes((byte[])tracksIterator.GetValue(0)); break; } mapping[i] = tracksIterator.GetInt32(1); audioFeature.Name = tracksIterator.GetString(2); audioFeature.Duration = tracksIterator.GetInt64(3); audioFeature.BitString = tracksIterator.GetString(4); tracks[i] = audioFeature; i++; } if (i == 0) { tracksIterator.Close(); tracksIterator = null; } return(i); }
// Manual deserialization of an Scms from a LittleEndian byte array public static void FromBytes(byte[] buf, Scms s) { byte [] buf4 = new byte[4]; int buf_i = 0; s.dim = GetInt32(buf, buf_i, buf4); buf_i += 4; for (int i = 0; i < s.mean.Length; i++) { s.mean[i] = GetFloat(buf, buf_i, buf4); buf_i += 4; } for (int i = 0; i < s.cov.Length; i++) { s.cov[i] = GetFloat(buf, buf_i, buf4); buf_i += 4; } for (int i = 0; i < s.icov.Length; i++) { s.icov[i] = GetFloat(buf, buf_i, buf4); buf_i += 4; } }
public static float CosineSimilarity(Scms s1, Scms s2) { float mean = 1 - CosineSimilarity(s1.mean, s2.mean); float cov = 1 - CosineSimilarity(s1.cov, s2.cov); //float icov = CosineSimilarity(s1.icov, s2.icov) * 100; return(mean + cov); // + icov; }
/** 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; }
/// <summary> /// Find Similar Tracks to an audio file using its file path /// </summary> /// <param name="searchForPath">audio file path</param> /// <param name="db">database</param> /// <param name="analysisMethod">analysis method (SCMS or MandelEllis)</param> /// <param name="numToTake">max number of entries to return</param> /// <param name="percentage">percentage below and above the duration in ms when querying (used if between 0.1 - 0.9)</param> /// <param name="distanceType">distance method to use (KullbackLeiblerDivergence is default)</param> /// <returns>a list of query results</returns> public static List<FindSimilar.QueryResult> SimilarTracksList(string searchForPath, Db db, Analyzer.AnalysisMethod analysisMethod, int numToTake=25, double percentage=0.2, AudioFeature.DistanceType distanceType = AudioFeature.DistanceType.KullbackLeiblerDivergence) { FileInfo fi = new FileInfo(searchForPath); AudioFeature seedAudioFeature = null; AudioFeature[] audioFeatures = null; switch (analysisMethod) { case Analyzer.AnalysisMethod.MandelEllis: seedAudioFeature = Analyzer.AnalyzeMandelEllis(fi); audioFeatures = new MandelEllis[100]; break; case Analyzer.AnalysisMethod.SCMS: seedAudioFeature = Analyzer.AnalyzeScms(fi); audioFeatures = new Scms[100]; break; } // Get all tracks from the DB except the seedSongs IDataReader r = db.GetTracks(null, seedAudioFeature.Duration, percentage); // store results in a query results list List<FindSimilar.QueryResult> queryResultList = new List<FindSimilar.QueryResult>(); int[] mapping = new int[100]; int read = 1; double dcur; while (read > 0) { read = db.GetNextTracks(ref r, ref audioFeatures, ref mapping, 100, analysisMethod); for (int i = 0; i < read; i++) { dcur = seedAudioFeature.GetDistance(audioFeatures[i], distanceType); // convert to positive values dcur = Math.Abs(dcur); QueryResult queryResult = new QueryResult(); queryResult.Id = mapping[i]; queryResult.Path = audioFeatures[i].Name; queryResult.Duration = audioFeatures[i].Duration; queryResult.Similarity = dcur; queryResultList.Add(queryResult); } } var sortedList = (from row in queryResultList orderby row.Similarity ascending select new QueryResult { Id = row.Id, Path = row.Path, Duration = row.Duration, Similarity = row.Similarity }).Take(numToTake).ToList(); return sortedList; }
public override double GetDistance(AudioFeature f) { if (!(f is Scms)) { new Exception("Can only handle AudioFeatures of type Scms, not of: " + f); return(-1); } Scms other = (Scms)f; return(Distance(this, other, new ScmsConfiguration(Analyzer.MFCC_COEFFICIENTS))); }
/// <summary> /// Computes a Scms model from the MFCC representation of a song. /// </summary> /// <param name="mfcc">Comirva.Audio.Util.Maths.Matrix mfcc</param> /// <returns></returns> public static Scms GetScmsNoInverse(Comirva.Audio.Util.Maths.Matrix mfccs, string name) { DbgTimer t = new DbgTimer(); t.Start(); Comirva.Audio.Util.Maths.Matrix mean = mfccs.Mean(2); #if DEBUG if (Analyzer.DEBUG_INFO_VERBOSE) { if (Analyzer.DEBUG_OUTPUT_TEXT) { mean.WriteText(name + "_mean.txt"); } mean.DrawMatrixGraph(name + "_mean.png"); } #endif // Covariance Comirva.Audio.Util.Maths.Matrix covarMatrix = mfccs.Cov(mean); #if DEBUG if (Analyzer.DEBUG_INFO_VERBOSE) { if (Analyzer.DEBUG_OUTPUT_TEXT) { covarMatrix.WriteText(name + "_covariance.txt"); } covarMatrix.DrawMatrixGraph(name + "_covariance.png"); } #endif Comirva.Audio.Util.Maths.Matrix covarMatrixInv = new Comirva.Audio.Util.Maths.Matrix(covarMatrix.Rows, covarMatrix.Columns); // Store the Mean, Covariance, Inverse Covariance in an optimal format. int dim = mean.Rows; Scms s = new Scms(dim); int l = 0; for (int i = 0; i < dim; i++) { s.mean[i] = (float)mean.MatrixData[i][0]; for (int j = i; j < dim; j++) { s.cov[l] = (float)covarMatrix.MatrixData[i][j]; s.icov[l] = (float)covarMatrixInv.MatrixData[i][j]; l++; } } Dbg.WriteLine("GetScmsNoInverse - Execution Time: {0} ms", t.Stop().TotalMilliseconds); return(s); }
/// <summary> /// Find Similar Tracks to an audio file using its file path /// </summary> /// <param name="searchForPath">audio file path</param> /// <param name="db">database</param> /// <param name="analysisMethod">analysis method (SCMS or MandelEllis)</param> /// <param name="numToTake">max number of entries to return</param> /// <param name="percentage">percentage below and above the duration in ms when querying (used if between 0.1 - 0.9)</param> /// <param name="distanceType">distance method to use (KullbackLeiblerDivergence is default)</param> /// <returns>a dictinary list of key value pairs (filepath and distance)</returns> public static Dictionary<KeyValuePair<int, string>, double> SimilarTracks(string searchForPath, Db db, Analyzer.AnalysisMethod analysisMethod, int numToTake=25, double percentage=0.2, AudioFeature.DistanceType distanceType = AudioFeature.DistanceType.KullbackLeiblerDivergence) { DbgTimer t = new DbgTimer(); t.Start(); FileInfo fi = new FileInfo(searchForPath); AudioFeature seedAudioFeature = null; AudioFeature[] audioFeatures = null; switch (analysisMethod) { case Analyzer.AnalysisMethod.MandelEllis: seedAudioFeature = Analyzer.AnalyzeMandelEllis(fi); audioFeatures = new MandelEllis[100]; break; case Analyzer.AnalysisMethod.SCMS: seedAudioFeature = Analyzer.AnalyzeScms(fi); audioFeatures = new Scms[100]; break; } // Get all tracks from the DB except the seedSongs IDataReader r = db.GetTracks(null, seedAudioFeature.Duration, percentage); // store results in a dictionary var NameDictionary = new Dictionary<KeyValuePair<int, string>, double>(); int[] mapping = new int[100]; int read = 1; double dcur; while (read > 0) { read = db.GetNextTracks(ref r, ref audioFeatures, ref mapping, 100, analysisMethod); for (int i = 0; i < read; i++) { dcur = seedAudioFeature.GetDistance(audioFeatures[i], distanceType); // convert to positive values dcur = Math.Abs(dcur); NameDictionary.Add(new KeyValuePair<int,string>(mapping[i], audioFeatures[i].Name), dcur); } } // sort by non unique values var sortedDict = (from entry in NameDictionary orderby entry.Value ascending select entry) .Take(numToTake) .ToDictionary(pair => pair.Key, pair => pair.Value); Console.Out.WriteLine(String.Format("Found Similar to ({0}) in {1} ms", seedAudioFeature.Name, t.Stop().TotalMilliseconds)); return sortedDict; }
public override double GetDistance(AudioFeature f, AudioFeature.DistanceType t) { if (!(f is Scms)) { new Exception("Can only handle AudioFeatures of type Scms, not of: " + f); return(-1); } Scms other = (Scms)f; DistanceMeasure distanceMeasure = DistanceMeasure.Euclidean; switch (t) { case AudioFeature.DistanceType.Dtw_Euclidean: distanceMeasure = DistanceMeasure.Euclidean; break; case AudioFeature.DistanceType.Dtw_SquaredEuclidean: distanceMeasure = DistanceMeasure.SquaredEuclidean; break; case AudioFeature.DistanceType.Dtw_Manhattan: distanceMeasure = DistanceMeasure.Manhattan; break; case AudioFeature.DistanceType.Dtw_Maximum: distanceMeasure = DistanceMeasure.Maximum; break; case AudioFeature.DistanceType.UCR_Dtw: return(UCRCSharp.UCR.DTW(this.GetArray(), other.GetArray())); case AudioFeature.DistanceType.CosineSimilarity: return(CosineSimilarity(this, other)); case AudioFeature.DistanceType.BitStringHamming: return(Imghash.ImagePHash.HammingDistance(this.BitString, other.BitString)); case AudioFeature.DistanceType.KullbackLeiblerDivergence: default: return(Distance(this, other, new ScmsConfiguration(Analyzer.MFCC_COEFFICIENTS))); } Dtw dtw = new Dtw(this.GetArray(), other.GetArray(), distanceMeasure, true, true, null, null, null); return(dtw.GetCost()); }
public static Scms Analyze(string file_path) { DbgTimer t = new DbgTimer(); t.Start(); Matrix stftdata = ad.Decode(file_path); Matrix mfccdata = mfcc.Apply(ref stftdata); Scms scms = Scms.GetScms(mfccdata); long stop = 0; t.Stop(ref stop); Dbg.WriteLine("Mirage - Total Execution Time: {0}ms", stop); return(scms); }
// Computes a Scms model from the MFCC representation of a song. public static Scms GetScms(Matrix mfcc) { DbgTimer t = new DbgTimer(); t.Start(); // Mean Vector m = mfcc.Mean(); // Covariance Matrix c = mfcc.Covariance(m); // Inverse Covariance Matrix ic; try { ic = c.Inverse(); } catch (MatrixSingularException) { throw new ScmsImpossibleException(); } // Store the Mean, Covariance, Inverse Covariance in an optimal format. int dim = m.rows; Scms s = new Scms(dim); int l = 0; for (int i = 0; i < dim; i++) { s.mean[i] = m.d[i, 0]; for (int j = i; j < dim; j++) { s.cov[l] = c.d[i, j]; s.icov[l] = ic.d[i, j]; l++; } } long stop = 0; t.Stop(ref stop); Dbg.WriteLine("Mirage - scms created in: {0}ms", stop); return(s); }
public override IEnumerable<float> Distance(Scms from) { if (from == null) { yield return float.MaxValue; yield break; } bool any_seeds = false; float last_weight = -99; foreach (var seed in seeds) { var distance = Scms.Distance (seed.Scms, from, Config); if (distance < 0) { // Ignore negative distance values continue; } if (distance < min_distance) { min_distance = distance; best_scms = from; } else if (distance > max_distance) { max_distance = distance; } float weighted_distance = distance / seed.Weight; if (debug) { if (seed.Weight != last_weight) { last_weight = seed.Weight; Console.WriteLine (" {0} seeds (weight {1,3:N1})", last_weight == ShuffledWeight ? "Shuffled" : last_weight == PlayedWeight ? "Played" : last_weight == SelectedWeight ? "Manually Selected" : "Skipped/Discarded", last_weight); } Console.WriteLine (" distance: {0,4:N1}, weighted: {1,4:N1} from artist_id {2,4}, uri {3}", distance, weighted_distance, seed.ArtistId, seed.Uri); } yield return weighted_distance; any_seeds = true; } if (!any_seeds) { // Return the highest distance possible yield return Single.MaxValue; } }
/// <summary> /// Get a track from the database using its id /// </summary> /// <param name="trackid">id</param> /// <param name="analysisMethod">analysis method (SCMS or MandelEllis)</param> /// <returns>an AudioFeature object</returns> public AudioFeature GetTrack(int trackid, Analyzer.AnalysisMethod analysisMethod) { IDbCommand dbcmd; lock (dbcon) { dbcmd = dbcon.CreateCommand(); } dbcmd.CommandText = "SELECT audioFeature, name, duration, bitstring FROM mirage " + "WHERE trackid = " + trackid; IDataReader reader = dbcmd.ExecuteReader(); if (!reader.Read()) { return(null); } byte[] buf = (byte[])reader.GetValue(0); string name = reader.GetString(1); long duration = reader.GetInt64(2); string bitstring = reader.GetString(3); reader.Close(); AudioFeature audioFeature = null; switch (analysisMethod) { case Analyzer.AnalysisMethod.MandelEllis: audioFeature = MandelEllis.FromBytes(buf); break; case Analyzer.AnalysisMethod.SCMS: audioFeature = Scms.FromBytes(buf); break; } audioFeature.Name = name; audioFeature.Duration = duration; audioFeature.BitString = bitstring; return(audioFeature); }
/** 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); }
public static float CosineSimilarity(Scms s1, Scms s2) { float mean = 1 - CosineSimilarity(s1.mean, s2.mean); float cov = 1 - CosineSimilarity(s1.cov, s2.cov); //float icov = CosineSimilarity(s1.icov, s2.icov) * 100; return mean + cov;// + icov; }
/// <summary> /// Computes a Scms model from the MFCC representation of a song. /// </summary> /// <param name="mfcc">Mirage.Matrix mfcc</param> /// <returns></returns> public static Scms GetScms(Matrix mfcc, string name) { DbgTimer t = new DbgTimer(); t.Start(); // Mean Vector m = mfcc.Mean(); #if DEBUG if (Analyzer.DEBUG_INFO_VERBOSE) { m.WriteText(name + "_mean_orig.txt"); m.DrawMatrixGraph(name + "_mean_orig.png"); } #endif // Covariance Matrix c = mfcc.Covariance(m); #if DEBUG if (Analyzer.DEBUG_INFO_VERBOSE) { c.WriteText(name + "_covariance_orig.txt"); c.DrawMatrixGraph(name + "_covariance_orig.png"); } #endif // Inverse Covariance Matrix ic; try { ic = c.Inverse(); } catch (MatrixSingularException) { //throw new ScmsImpossibleException(); Dbg.WriteLine("MatrixSingularException - Scms failed!"); return null; } #if DEBUG if (Analyzer.DEBUG_INFO_VERBOSE) { ic.WriteAscii(name + "_inverse_covariance_orig.txt"); ic.DrawMatrixGraph(name + "_inverse_covariance_orig.png"); } #endif // Store the Mean, Covariance, Inverse Covariance in an optimal format. int dim = m.rows; Scms s = new Scms(dim); int l = 0; for (int i = 0; i < dim; i++) { s.mean[i] = m.d[i, 0]; for (int j = i; j < dim; j++) { s.cov[l] = c.d[i, j]; s.icov[l] = ic.d[i, j]; l++; } } Dbg.WriteLine("(Mirage) - scms created in: {0} ms", t.Stop().TotalMilliseconds); return s; }
/// <summary> /// Computes a Scms model from the MFCC representation of a song. /// </summary> /// <param name="mfcc">Comirva.Audio.Util.Maths.Matrix mfcc</param> /// <returns></returns> public static Scms GetScms(Comirva.Audio.Util.Maths.Matrix mfccs, string name) { DbgTimer t = new DbgTimer(); t.Start(); Comirva.Audio.Util.Maths.Matrix mean = mfccs.Mean(2); #if DEBUG if (Analyzer.DEBUG_INFO_VERBOSE) { mean.WriteText(name + "_mean.txt"); mean.DrawMatrixGraph(name + "_mean.png"); } #endif // Covariance Comirva.Audio.Util.Maths.Matrix covarMatrix = mfccs.Cov(mean); #if DEBUG if (Analyzer.DEBUG_INFO_VERBOSE) { covarMatrix.WriteText(name + "_covariance.txt"); covarMatrix.DrawMatrixGraph(name + "_covariance.png"); } #endif // Inverse Covariance Comirva.Audio.Util.Maths.Matrix covarMatrixInv; try { covarMatrixInv = covarMatrix.InverseGausJordan(); } catch (Exception) { Dbg.WriteLine("MatrixSingularException - Scms failed!"); return null; } #if DEBUG if (Analyzer.DEBUG_INFO_VERBOSE) { covarMatrixInv.WriteAscii(name + "_inverse_covariance.ascii"); covarMatrixInv.DrawMatrixGraph(name + "_inverse_covariance.png"); } #endif // Store the Mean, Covariance, Inverse Covariance in an optimal format. int dim = mean.Rows; Scms s = new Scms(dim); int l = 0; for (int i = 0; i < dim; i++) { s.mean[i] = (float) mean.MatrixData[i][0]; for (int j = i; j < dim; j++) { s.cov[l] = (float) covarMatrix.MatrixData[i][j]; s.icov[l] = (float) covarMatrixInv.MatrixData[i][j]; l++; } } Dbg.WriteLine("(Comirva) - scms created in: {0} ms", t.Stop().TotalMilliseconds); return s; }
/// <summary> /// Manual deserialization of an Scms from a LittleEndian byte array /// </summary> /// <param name="buf">byte array</param> /// <param name="s">song model</param> public static void FromBytes(byte[] buf, Scms s) { byte [] buf4 = new byte[4]; int buf_i = 0; s.dim = GetInt32(buf, buf_i, buf4); buf_i += 4; for (int i = 0; i < s.mean.Length; i++) { s.mean[i] = GetFloat(buf, buf_i, buf4); buf_i += 4; } for (int i = 0; i < s.cov.Length; i++) { s.cov[i] = GetFloat(buf, buf_i, buf4); buf_i += 4; } for (int i = 0; i < s.icov.Length; i++) { s.icov[i] = GetFloat(buf, buf_i, buf4); buf_i += 4; } }
/// <summary> /// Manual deserialization a byte array to a Scms object /// </summary> /// <param name="buf">byte array</param> /// <returns>Song model</returns> public static Scms FromBytes(byte[] buf) { var scms = new Scms(Analyzer.MFCC_COEFFICIENTS); FromBytes(buf, scms); return scms; }
/// <summary> /// Find Similar Tracks to one or many audio files using their unique database id(s) /// </summary> /// <param name="id">an array of unique database ids for the audio files to search for similar matches</param> /// <param name="exclude">an array of unique database ids to ignore (normally the same as the id array)</param> /// <param name="db">database</param> /// <param name="analysisMethod">analysis method (SCMS or MandelEllis)</param> /// <param name="numToTake">max number of entries to return</param> /// <param name="percentage">percentage below and above the duration in ms when querying (used if between 0.1 - 0.9)</param> /// <param name="distanceType">distance method to use (KullbackLeiblerDivergence is default)</param> /// <returns>a list of query results</returns> public static List<FindSimilar.QueryResult> SimilarTracksList(int[] id, int[] exclude, Db db, Analyzer.AnalysisMethod analysisMethod, int numToTake=25, double percentage=0.2, AudioFeature.DistanceType distanceType = AudioFeature.DistanceType.KullbackLeiblerDivergence) { AudioFeature[] seedAudioFeatures = null; AudioFeature[] audioFeatures = null; switch (analysisMethod) { case Analyzer.AnalysisMethod.MandelEllis: seedAudioFeatures = new MandelEllis[id.Length]; audioFeatures = new MandelEllis[100]; break; case Analyzer.AnalysisMethod.SCMS: seedAudioFeatures = new Scms[id.Length]; audioFeatures = new Scms[100]; break; } for (int i = 0; i < seedAudioFeatures.Length; i++) { seedAudioFeatures[i] = db.GetTrack(id[i], analysisMethod); } // Get all tracks from the DB except the seedSongs IDataReader r = db.GetTracks(exclude, seedAudioFeatures[0].Duration, percentage); // store results in a query results list List<FindSimilar.QueryResult> queryResultList = new List<FindSimilar.QueryResult>(); int[] mapping = new int[100]; int read = 1; double d; double dcur; float count; while (read > 0) { read = db.GetNextTracks(ref r, ref audioFeatures, ref mapping, 100, analysisMethod); for (int i = 0; i < read; i++) { d = 0; count = 0; for (int j = 0; j < seedAudioFeatures.Length; j++) { dcur = seedAudioFeatures[j].GetDistance(audioFeatures[i], distanceType); // convert to positive values dcur = Math.Abs(dcur); d += dcur; count++; } if (d > 0) { QueryResult queryResult = new QueryResult(); queryResult.Id = mapping[i]; queryResult.Path = audioFeatures[i].Name; queryResult.Duration = audioFeatures[i].Duration; queryResult.Similarity = d/count; queryResultList.Add(queryResult); } } } var sortedList = (from row in queryResultList orderby row.Similarity ascending select new QueryResult { Id = row.Id, Path = row.Path, Duration = row.Duration, Similarity = row.Similarity }).Take(numToTake).ToList(); return sortedList; }
/// <summary> /// Find Similar Tracks to one or many audio files using their unique database id(s) /// </summary> /// <param name="id">an array of unique database ids for the audio files to search for similar matches</param> /// <param name="exclude">an array of unique database ids to ignore (normally the same as the id array)</param> /// <param name="db">database</param> /// <param name="analysisMethod">analysis method (SCMS or MandelEllis)</param> /// <param name="numToTake">max number of entries to return</param> /// <param name="percentage">percentage below and above the duration in ms when querying (used if between 0.1 - 0.9)</param> /// <param name="distanceType">distance method to use (KullbackLeiblerDivergence is default)</param> /// <returns>a dictinary list of key value pairs (filepath and distance)</returns> public static Dictionary<KeyValuePair<int, string>, double> SimilarTracks(int[] id, int[] exclude, Db db, Analyzer.AnalysisMethod analysisMethod, int numToTake=25, double percentage=0.2, AudioFeature.DistanceType distanceType = AudioFeature.DistanceType.KullbackLeiblerDivergence) { DbgTimer t = new DbgTimer(); t.Start(); AudioFeature[] seedAudioFeatures = null; AudioFeature[] audioFeatures = null; switch (analysisMethod) { case Analyzer.AnalysisMethod.MandelEllis: seedAudioFeatures = new MandelEllis[id.Length]; audioFeatures = new MandelEllis[100]; break; case Analyzer.AnalysisMethod.SCMS: seedAudioFeatures = new Scms[id.Length]; audioFeatures = new Scms[100]; break; } for (int i = 0; i < seedAudioFeatures.Length; i++) { seedAudioFeatures[i] = db.GetTrack(id[i], analysisMethod); } // Get all tracks from the DB except the seedSongs IDataReader r = db.GetTracks(exclude, seedAudioFeatures[0].Duration, percentage); // store results in a dictionary var NameDictionary = new Dictionary<KeyValuePair<int, string>, double>(); int[] mapping = new int[100]; int read = 1; double d; double dcur; float count; while (read > 0) { read = db.GetNextTracks(ref r, ref audioFeatures, ref mapping, 100, analysisMethod); for (int i = 0; i < read; i++) { d = 0; count = 0; for (int j = 0; j < seedAudioFeatures.Length; j++) { dcur = seedAudioFeatures[j].GetDistance(audioFeatures[i], distanceType); // convert to positive values dcur = Math.Abs(dcur); d += dcur; count++; } if (d > 0) { NameDictionary.Add(new KeyValuePair<int,string>(mapping[i], audioFeatures[i].Name), d/count); //NameDictionary.Add(new KeyValuePair<int,string>(mapping[i], String.Format("{0} ({1} ms)", audioFeatures[i].Name, audioFeatures[i].Duration)), d/count); } } } // sort by non unique values var sortedDict = (from entry in NameDictionary orderby entry.Value ascending select entry) .Take(numToTake) .ToDictionary(pair => pair.Key, pair => pair.Value); Console.Out.WriteLine(String.Format("Found Similar to ({0}) in {1} ms", String.Join(",", seedAudioFeatures.Select(p=>p.Name)), t.Stop().TotalMilliseconds)); return sortedDict; }
/// <summary> /// Computes a Scms model from the MFCC representation of a song. /// </summary> /// <param name="mfcc">Comirva.Audio.Util.Maths.Matrix mfcc</param> /// <returns></returns> public static Scms GetScms(Comirva.Audio.Util.Maths.Matrix mfccs, string name) { DbgTimer t = new DbgTimer(); t.Start(); Comirva.Audio.Util.Maths.Matrix mean = mfccs.Mean(2); #if DEBUG if (Analyzer.DEBUG_INFO_VERBOSE) { if (Analyzer.DEBUG_OUTPUT_TEXT) { mean.WriteText(name + "_mean.txt"); } mean.DrawMatrixGraph(name + "_mean.png"); } #endif // Covariance Comirva.Audio.Util.Maths.Matrix covarMatrix = mfccs.Cov(mean); #if DEBUG if (Analyzer.DEBUG_INFO_VERBOSE) { if (Analyzer.DEBUG_OUTPUT_TEXT) { covarMatrix.WriteText(name + "_covariance.txt"); } covarMatrix.DrawMatrixGraph(name + "_covariance.png"); } #endif // Inverse Covariance Comirva.Audio.Util.Maths.Matrix covarMatrixInv; try { covarMatrixInv = covarMatrix.InverseGausJordan(); } catch (Exception) { Dbg.WriteLine("MatrixSingularException - Scms failed!"); return(null); } #if DEBUG if (Analyzer.DEBUG_INFO_VERBOSE) { if (Analyzer.DEBUG_OUTPUT_TEXT) { covarMatrixInv.WriteAscii(name + "_inverse_covariance.ascii"); } covarMatrixInv.DrawMatrixGraph(name + "_inverse_covariance.png"); } #endif // Store the Mean, Covariance, Inverse Covariance in an optimal format. int dim = mean.Rows; Scms s = new Scms(dim); int l = 0; for (int i = 0; i < dim; i++) { s.mean[i] = (float)mean.MatrixData[i][0]; for (int j = i; j < dim; j++) { s.cov[l] = (float)covarMatrix.MatrixData[i][j]; s.icov[l] = (float)covarMatrixInv.MatrixData[i][j]; l++; } } Dbg.WriteLine("Compute Scms - Execution Time: {0} ms", t.Stop().TotalMilliseconds); return(s); }
// Computes a Scms model from the MFCC representation of a song. public static Scms GetScms(Matrix mfcc) { DbgTimer t = new DbgTimer(); t.Start(); // Mean Vector m = mfcc.Mean(); // Covariance Matrix c = mfcc.Covariance(m); // Inverse Covariance Matrix ic; try { ic = c.Inverse(); } catch (MatrixSingularException) { throw new ScmsImpossibleException(); } // Store the Mean, Covariance, Inverse Covariance in an optimal format. int dim = m.rows; Scms s = new Scms(dim); int l = 0; for (int i = 0; i < dim; i++) { s.mean[i] = m.d[i, 0]; for (int j = i; j < dim; j++) { s.cov[l] = c.d[i, j]; s.icov[l] = ic.d[i, j]; l++; } } long stop = 0; t.Stop(ref stop); Dbg.WriteLine("Mirage - scms created in: {0}ms", stop); return s; }
/// <summary> /// Computes a Scms model from the MFCC representation of a song. /// </summary> /// <param name="mfcc">Comirva.Audio.Util.Maths.Matrix mfcc</param> /// <returns></returns> public static Scms GetScmsNoInverse(Comirva.Audio.Util.Maths.Matrix mfccs, string name) { DbgTimer t = new DbgTimer(); t.Start(); Comirva.Audio.Util.Maths.Matrix mean = mfccs.Mean(2); #if DEBUG if (Analyzer.DEBUG_INFO_VERBOSE) { if (Analyzer.DEBUG_OUTPUT_TEXT) mean.WriteText(name + "_mean.txt"); mean.DrawMatrixGraph(name + "_mean.png"); } #endif // Covariance Comirva.Audio.Util.Maths.Matrix covarMatrix = mfccs.Cov(mean); #if DEBUG if (Analyzer.DEBUG_INFO_VERBOSE) { if (Analyzer.DEBUG_OUTPUT_TEXT) covarMatrix.WriteText(name + "_covariance.txt"); covarMatrix.DrawMatrixGraph(name + "_covariance.png"); } #endif Comirva.Audio.Util.Maths.Matrix covarMatrixInv = new Comirva.Audio.Util.Maths.Matrix(covarMatrix.Rows, covarMatrix.Columns); // Store the Mean, Covariance, Inverse Covariance in an optimal format. int dim = mean.Rows; Scms s = new Scms(dim); int l = 0; for (int i = 0; i < dim; i++) { s.mean[i] = (float) mean.MatrixData[i][0]; for (int j = i; j < dim; j++) { s.cov[l] = (float) covarMatrix.MatrixData[i][j]; s.icov[l] = (float) covarMatrixInv.MatrixData[i][j]; l++; } } Dbg.WriteLine("GetScmsNoInverse - Execution Time: {0} ms", t.Stop().TotalMilliseconds); return s; }
/// <summary> /// Computes a Scms model from the MFCC representation of a song. /// </summary> /// <param name="mfcc">Mirage.Matrix mfcc</param> /// <returns></returns> public static Scms GetScms(Matrix mfcc, string name) { DbgTimer t = new DbgTimer(); t.Start(); // Mean Vector m = mfcc.Mean(); #if DEBUG if (Analyzer.DEBUG_INFO_VERBOSE) { if (Analyzer.DEBUG_OUTPUT_TEXT) { m.WriteText(name + "_mean_orig.txt"); } m.DrawMatrixGraph(name + "_mean_orig.png"); } #endif // Covariance Matrix c = mfcc.Covariance(m); #if DEBUG if (Analyzer.DEBUG_INFO_VERBOSE) { if (Analyzer.DEBUG_OUTPUT_TEXT) { c.WriteText(name + "_covariance_orig.txt"); } c.DrawMatrixGraph(name + "_covariance_orig.png"); } #endif // Inverse Covariance Matrix ic; try { ic = c.Inverse(); } catch (MatrixSingularException) { //throw new ScmsImpossibleException(); Dbg.WriteLine("MatrixSingularException - Scms failed!"); return(null); } #if DEBUG if (Analyzer.DEBUG_INFO_VERBOSE) { if (Analyzer.DEBUG_OUTPUT_TEXT) { ic.WriteAscii(name + "_inverse_covariance_orig.txt"); } ic.DrawMatrixGraph(name + "_inverse_covariance_orig.png"); } #endif // Store the Mean, Covariance, Inverse Covariance in an optimal format. int dim = m.rows; Scms s = new Scms(dim); int l = 0; for (int i = 0; i < dim; i++) { s.mean[i] = m.d[i, 0]; for (int j = i; j < dim; j++) { s.cov[l] = c.d[i, j]; s.icov[l] = ic.d[i, j]; l++; } } Dbg.WriteLine("(Mirage) - scms created in: {0} ms", t.Stop().TotalMilliseconds); return(s); }
public abstract IEnumerable<float> Distance(Scms from);