Beispiel #1
0
        /// <summary>
        /// Find Similar Tracks using passed audio samples as input and return a Dictionary
        /// </summary>
        /// <param name="lshHashTables">Number of hash tables from the database</param>
        /// <param name="lshGroupsPerKey">Number of groups per hash table</param>
        /// <param name="thresholdTables">Minimum number of hash tables that must be found for one signature to be considered a candidate (0 and 1 = return all candidates, 2+ = return only exact matches)</param>
        /// <param name="param">Audio File Work Unit Parameter Object</param>
        /// <returns>a dictionary of perceptually similar tracks</returns>
        public Dictionary <Track, double> FindSimilarFromAudioSamples(
            int lshHashTables,
            int lshGroupsPerKey,
            int thresholdTables,
            WorkUnitParameterObject param)
        {
            DbgTimer t = new DbgTimer();

            t.Start();

            // Get fingerprints
            double[][]    logSpectrogram;
            List <bool[]> signatures = fingerprintService.CreateFingerprintsFromAudioSamples(param.AudioSamples, param, out logSpectrogram);

            long elapsedMiliseconds = 0;

            // Query the database using Min Hash
            Dictionary <int, QueryStats> allCandidates = QueryFingerprintManager.QueryOneSongMinHash(
                signatures,
                dbService,
                minHash,
                lshHashTables,
                lshGroupsPerKey,
                thresholdTables,
                ref elapsedMiliseconds);

            IEnumerable <int> ids    = allCandidates.Select(p => p.Key);
            IList <Track>     tracks = dbService.ReadTrackById(ids);

            // Order by Hamming Similarity
            // Using PLINQ
            //OrderedParallelQuery<KeyValuePair<int, QueryStats>> order = allCandidates.AsParallel()
            IOrderedEnumerable <KeyValuePair <int, QueryStats> > order = allCandidates
                                                                         .OrderBy((pair) => pair.Value.OrderingValue =
                                                                                      pair.Value.HammingDistance / pair.Value.NumberOfTotalTableVotes
                                                                                      + 0.4 * pair.Value.MinHammingDistance);

            // Join on the ID properties.
            var joined = from o in order
                         join track in tracks on o.Key equals track.Id
                         select new { track, o.Value.Similarity };

            Dictionary <Track, double> stats = joined.ToDictionary(Key => Key.track, Value => Value.Similarity);

            Dbg.WriteLine("Find Similar From Audio Samples - Total Execution Time: {0} ms", t.Stop().TotalMilliseconds);
            return(stats);
        }
Beispiel #2
0
        /// <summary>
        /// Find Similar Tracks using passed audio file as input
        /// </summary>
        /// <param name="lshHashTables">Number of hash tables from the database</param>
        /// <param name="lshGroupsPerKey">Number of groups per hash table</param>
        /// <param name="thresholdTables">Threshold percentage [0.07 for 20 LHash Tables, 0.17 for 25 LHashTables]</param>
        /// <param name="param">Audio File Work Unit Parameter Object</param>
        /// <param name="splashScreen">The "please wait" splash screen (or null)</param>
        /// <returns>a dictionary of perceptually similar tracks</returns>
        public Dictionary <Track, QueryStats> FindSimilarFromAudioFile(
            int lshHashTables,
            int lshGroupsPerKey,
            int thresholdTables,
            WorkUnitParameterObject param)
        {
            // Get fingerprints
            // TODO: Note that this method might return too few samples
            double[][]    LogSpectrogram;
            List <bool[]> signatures = fingerprintService.CreateFingerprintsFromAudioFile(param, out LogSpectrogram);

            long elapsedMiliseconds = 0;

            // Query the database using Min Hash
            Dictionary <int, QueryStats> allCandidates = QueryFingerprintManager.QueryOneSongMinHash(
                signatures,
                dbService,
                minHash,
                lshHashTables,
                lshGroupsPerKey,
                thresholdTables,
                ref elapsedMiliseconds);

            IEnumerable <int> ids    = allCandidates.Select(p => p.Key);
            IList <Track>     tracks = dbService.ReadTrackById(ids);

            // Order by Hamming Similarity
            // Using PLINQ
            //OrderedParallelQuery<KeyValuePair<int, QueryStats>> order = allCandidates.AsParallel()
            IOrderedEnumerable <KeyValuePair <int, QueryStats> > order = allCandidates
                                                                         .OrderBy((pair) => pair.Value.OrderingValue =
                                                                                      pair.Value.HammingDistance / pair.Value.NumberOfTotalTableVotes
                                                                                      + 0.4 * pair.Value.MinHammingDistance);

            // Join on the ID properties.
            var joined = from o in order
                         join track in tracks on o.Key equals track.Id
                         select new { track, o.Value };

            Dictionary <Track, QueryStats> stats = joined.ToDictionary(Key => Key.track, Value => Value.Value);

            return(stats);
        }
Beispiel #3
0
        /// <summary>
        /// Find Similar Tracks using passed audio samples as input and return a List
        /// </summary>
        /// <param name="lshHashTables">Number of hash tables from the database</param>
        /// <param name="lshGroupsPerKey">Number of groups per hash table</param>
        /// <param name="thresholdTables">Minimum number of hash tables that must be found for one signature to be considered a candidate (0 and 1 = return all candidates, 2+ = return only exact matches)</param>
        /// <param name="param">Audio File Work Unit Parameter Object</param>
        /// <param name="optimizeSignatureCount">Reduce the number of signatures in order to increase the search performance</param>
        /// <param name="doSearchEverything">disregard the local sensitivity hashes and search the whole database</param>
        /// <param name="splashScreen">The "please wait" splash screen (or null)</param>
        /// <returns>a list of perceptually similar tracks</returns>
        public List <FindSimilar.QueryResult> FindSimilarFromAudioSamplesList(
            int lshHashTables,
            int lshGroupsPerKey,
            int thresholdTables,
            WorkUnitParameterObject param,
            bool optimizeSignatureCount,
            bool doSearchEverything,
            SplashSceenWaitingForm splashScreen)
        {
            DbgTimer t = new DbgTimer();

            t.Start();

            if (splashScreen != null)
            {
                splashScreen.SetProgress(2, "Creating fingerprints from audio samples ...");
            }

            // Get fingerprints
            double[][]    logSpectrogram;
            List <bool[]> fingerprints = fingerprintService.CreateFingerprintsFromAudioSamples(param.AudioSamples, param, out logSpectrogram);

                        #if DEBUG
            // Save debug images using fingerprinting methods
            //Analyzer.SaveFingerprintingDebugImages(param.FileName, logSpectrogram, fingerprints, fingerprintService, param.FingerprintingConfiguration);
                        #endif

            if (splashScreen != null)
            {
                splashScreen.SetProgress(3, String.Format("Successfully created {0} fingerprints.", fingerprints.Count));
            }

            // If the number of signatures is to big, only keep the first MAX_SIGNATURE_COUNT to avoid a very time consuming search
            if (optimizeSignatureCount && fingerprints.Count > MAX_SIGNATURE_COUNT)
            {
                if (splashScreen != null)
                {
                    splashScreen.SetProgress(4, String.Format("Only using the first {0} fingerprints out of {1}.", MAX_SIGNATURE_COUNT, fingerprints.Count));
                }
                fingerprints.RemoveRange(MAX_SIGNATURE_COUNT, fingerprints.Count - MAX_SIGNATURE_COUNT);
                Dbg.WriteLine("Only using the first {0} fingerprints.", MAX_SIGNATURE_COUNT);
            }

            long elapsedMiliseconds = 0;

            // Query the database using Min Hash
            Dictionary <int, QueryStats> allCandidates = QueryFingerprintManager.QueryOneSongMinHash(
                fingerprints,
                dbService,
                minHash,
                lshHashTables,
                lshGroupsPerKey,
                thresholdTables,
                ref elapsedMiliseconds,
                doSearchEverything,
                splashScreen);

            if (splashScreen != null)
            {
                splashScreen.SetProgress(91, String.Format("Found {0} candidates.", allCandidates.Count));
            }

            IEnumerable <int> ids    = allCandidates.Select(p => p.Key);
            IList <Track>     tracks = dbService.ReadTrackById(ids);

            if (splashScreen != null)
            {
                splashScreen.SetProgress(95, String.Format("Reading {0} tracks.", tracks.Count));
            }

            // Order by Hamming Similarity
            // TODO: What does the 0.4 number do here?
            // there doesn't seem to be any change using another number?!

            /*
             * // Using PLINQ
             * IOrderedEnumerable<KeyValuePair<int, QueryStats>> order = allCandidates
             *      .OrderBy((pair) => pair.Value.OrderingValue =
             *               pair.Value.HammingDistance / pair.Value.NumberOfTotalTableVotes
             + 0.4 * pair.Value.MinHammingDistance);
             +
             +
             + var fingerprintList = (from o in order
             +                     join track in tracks on o.Key equals track.Id
             +                     select new FindSimilar.QueryResult {
             +                      Id = track.Id,
             +                      Path = track.FilePath,
             +                      Duration = track.TrackLengthMs,
             +                      Similarity = o.Value.Similarity
             +                     }).ToList();
             */

            // http://msdn.microsoft.com/en-us/library/dd460719(v=vs.110).aspx
            // http://stackoverflow.com/questions/2767709/c-sharp-joins-where-with-linq-and-lambda
            // Lambda query to order the candidates
            var order = allCandidates.AsParallel()
                        .OrderBy((pair) => pair.Value.OrderingValue =
                                     pair.Value.HammingDistance / pair.Value.NumberOfTotalTableVotes
                                     + 0.4 * pair.Value.MinHammingDistance)
                        .Take(200);

            // TODO: Be able to create the above query as a LINQ query

            // Join on the ID properties.
            var fingerprintList = (from o in order.AsParallel()
                                   join track in tracks.AsParallel() on o.Key equals track.Id
                                   select new FindSimilar.QueryResult {
                Id = track.Id,
                Path = track.FilePath,
                Duration = track.TrackLengthMs,
                Similarity = o.Value.Similarity
            })
                                  .OrderByDescending((ord) => ord.Similarity)
                                  .ToList();

            if (splashScreen != null)
            {
                splashScreen.SetProgress(100, "Ready!");
            }

            Dbg.WriteLine("FindSimilarFromAudioSamplesList - Total Execution Time: {0} ms", t.Stop().TotalMilliseconds);
            return(fingerprintList);
        }