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()); }
/// <summary>Get Distance</summary> /// <seealso cref="">comirva.audio.feature.AudioFeature#GetDistance(comirva.audio.feature.AudioFeature)</seealso> public override double GetDistance(AudioFeature f, AudioFeature.DistanceType t) { if (!(f is MandelEllis)) { new Exception("Can only handle AudioFeatures of type Mandel Ellis, not of: " + f); return(-1); } MandelEllis other = (MandelEllis)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.KullbackLeiblerDivergence: default: return(KullbackLeibler(this.gmmMe, other.gmmMe) + KullbackLeibler(other.gmmMe, this.gmmMe)); } Dtw dtw = new Dtw(this.GetArray(), other.GetArray(), distanceMeasure, true, true, null, null, null); return(dtw.GetCost()); }
public override double GetDistance(AudioFeature f, AudioFeature.DistanceType t) { throw new NotImplementedException(); }
private static void FindSimilar(string path, Db db, Analyzer.AnalysisMethod analysisMethod, int numToTake=25, double percentage=0.2, AudioFeature.DistanceType distanceType = AudioFeature.DistanceType.KullbackLeiblerDivergence) { var similarTracks = SimilarTracks(path, db, analysisMethod, numToTake, percentage, distanceType); foreach (var entry in similarTracks) { Console.WriteLine("{0}, {1}", entry.Key, entry.Value); } }
public static void Main(string[] args) { Analyzer.AnalysisMethod analysisMethod = Analyzer.AnalysisMethod.SCMS; //Analyzer.AnalysisMethod analysisMethod = Analyzer.AnalysisMethod.MandelEllis; string scanPath = ""; double skipDurationAboveSeconds = -1; // less than zero disables this string queryPath = ""; int queryId = -1; int numToTake = 20; double percentage = 0.4; // percentage below and above when querying bool resetdb = false; bool silent = false; AudioFeature.DistanceType distanceType = AudioFeature.DistanceType.KullbackLeiblerDivergence; // Command line parsing Arguments CommandLine = new Arguments(args); if(CommandLine["match"] != null) { queryPath = CommandLine["match"]; } if(CommandLine["matchid"] != null) { string matchId = CommandLine["matchid"]; queryId = int.Parse(matchId); } if(CommandLine["scandir"] != null) { scanPath = CommandLine["scandir"]; } if(CommandLine["skipduration"] != null) { double.TryParse(CommandLine["skipduration"], NumberStyles.Number,CultureInfo.InvariantCulture, out skipDurationAboveSeconds); } if(CommandLine["num"] != null) { string num = CommandLine["num"]; numToTake = int.Parse(num); } if(CommandLine["percentage"] != null) { double.TryParse(CommandLine["percentage"], NumberStyles.Number,CultureInfo.InvariantCulture, out percentage); } if(CommandLine["type"] != null) { string type = CommandLine["type"]; if (type.Equals("kl", StringComparison.InvariantCultureIgnoreCase)) { distanceType = AudioFeature.DistanceType.KullbackLeiblerDivergence; } else if (type.StartsWith("dtw", StringComparison.InvariantCultureIgnoreCase)) { if (type.Equals("dtwe", StringComparison.InvariantCultureIgnoreCase)) { distanceType = AudioFeature.DistanceType.Dtw_Euclidean; } else if (type.Equals("dtwe2", StringComparison.InvariantCultureIgnoreCase)) { distanceType = AudioFeature.DistanceType.Dtw_SquaredEuclidean; } else if (type.Equals("dtwman", StringComparison.InvariantCultureIgnoreCase)) { distanceType = AudioFeature.DistanceType.Dtw_Manhattan; } else if (type.Equals("dtwmax", StringComparison.InvariantCultureIgnoreCase)) { distanceType = AudioFeature.DistanceType.Dtw_Maximum; } else if (type.Equals("ucrdtw", StringComparison.InvariantCultureIgnoreCase)) { distanceType = AudioFeature.DistanceType.UCR_Dtw; } else { distanceType = AudioFeature.DistanceType.Dtw_Euclidean; } } } if(CommandLine["dtw"] != null || CommandLine["dtwe"] != null) { distanceType = AudioFeature.DistanceType.Dtw_Euclidean; } if(CommandLine["dtwe2"] != null) { distanceType = AudioFeature.DistanceType.Dtw_SquaredEuclidean; } if(CommandLine["dtwman"] != null) { distanceType = AudioFeature.DistanceType.Dtw_Manhattan; } if(CommandLine["dtwmax"] != null) { distanceType = AudioFeature.DistanceType.Dtw_Maximum; } if(CommandLine["kl"] != null) { distanceType = AudioFeature.DistanceType.KullbackLeiblerDivergence; } if(CommandLine["ucrdtw"] != null) { distanceType = AudioFeature.DistanceType.UCR_Dtw; } if(CommandLine["resetdb"] != null) { resetdb = true; } if(CommandLine["silent"] != null) { silent = true; } if(CommandLine["permutations"] != null) { Console.WriteLine("Generating hash permutations for used by the Soundfingerprinting methods."); Console.WriteLine("Saving to file: {0}", "Soundfingerprinting\\perms-new.csv"); Console.WriteLine(); PermutationGeneratorService permutationGeneratorService = new PermutationGeneratorService(); Analyzer.GenerateAndSavePermutations(permutationGeneratorService, "Soundfingerprinting\\perms-new.csv"); return; } if(CommandLine["?"] != null) { PrintUsage(); return; } if(CommandLine["help"] != null) { PrintUsage(); return; } if(CommandLine["gui"] != null) { StartGUI(); return; } if (queryPath == "" && queryId == -1 && scanPath == "") { PrintUsage(); return; } // Get database Db mandelEllisScmsDatabase = new Db(); // For MandelEllis and SCMS // Instansiate soundfingerprinting Repository FingerprintService fingerprintService = Analyzer.GetSoundfingerprintingService(); DatabaseService databaseService = DatabaseService.Instance; // For AudioFingerprinting IPermutations permutations = new LocalPermutations("Soundfingerprinting\\perms.csv", ","); //IPermutations permutations = new LocalPermutations("Soundfingerprinting\\perms-new.csv", ","); Repository repository = new Repository(permutations, databaseService, fingerprintService); if (scanPath != "") { if (IOUtils.IsDirectory(scanPath)) { if (resetdb) { // For MandelEllis and Scms mandelEllisScmsDatabase.RemoveTable(); mandelEllisScmsDatabase.AddTable(); // For AudioFingerprinting databaseService.RemoveFingerprintTable(); databaseService.AddFingerprintTable(); databaseService.RemoveHashBinTable(); databaseService.AddHashBinTable(); databaseService.RemoveTrackTable(); databaseService.AddTrackTable(); } Console.WriteLine("FindSimilar. Version {0}.", VERSION); ScanDirectory(scanPath, mandelEllisScmsDatabase, repository, skipDurationAboveSeconds, silent); } else { Console.Out.WriteLine("No directory found {0}!", scanPath); } } if (queryPath != "") { FileInfo fi = new FileInfo(queryPath); if (fi.Exists) { FindSimilar(queryPath, mandelEllisScmsDatabase, analysisMethod, numToTake, percentage, distanceType); } else { Console.Out.WriteLine("No file found {0}!", queryPath); } } if (queryId != -1) { FindSimilar(new int[] { queryId }, mandelEllisScmsDatabase, analysisMethod, numToTake, percentage, distanceType); } System.Console.ReadLine(); }
/// <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> /// 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; }
/// <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; }