コード例 #1
0
        public List <bool[]> CreateFingerprintsFromLogSpectrum(
            double[][] logarithmizedSpectrum, IStride stride, int fingerprintLength, int overlap, int topWavelets)
        {
            DbgTimer t = new DbgTimer();

            t.Start();

            // Cut the logaritmic spectrogram into smaller spectrograms with one stride between each
            List <double[][]> spectralImages = SpectrumService.CutLogarithmizedSpectrum(logarithmizedSpectrum, stride, fingerprintLength, overlap);

            // Then apply the wavelet transform on them to later reduce the resolution
            // do this in place
            WaveletService.ApplyWaveletTransformInPlace(spectralImages);

            // Then for each of the wavelet reduce the resolution by only keeping the top wavelets
            // and ignore the magnitude of the top wavelets.
            // Instead, we can simply keep the sign of it (+/-).
            // This information is enough to keep the extract perceptual characteristics of a song.
            List <bool[]> fingerprints = new List <bool[]>();

            foreach (var spectralImage in spectralImages)
            {
                bool[] image = FingerprintDescriptor.ExtractTopWavelets(spectralImage, topWavelets);
                fingerprints.Add(image);
            }

            Dbg.WriteLine("Created {1} Fingerprints from Log Spectrum - Execution Time: {0} ms", t.Stop().TotalMilliseconds, fingerprints.Count);
            return(fingerprints);
        }
コード例 #2
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);
        }
コード例 #3
0
    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");
    }
コード例 #4
0
        public double[][] CreateLogSpectrogram(
            float[] samples, IWindowFunction windowFunction, AudioServiceConfiguration configuration)
        {
            DbgTimer t = new DbgTimer();

            t.Start();

            if (configuration.NormalizeSignal)
            {
                NormalizeInPlace(samples);
            }

            int width = (samples.Length - configuration.WindowSize) / configuration.Overlap;             /*width of the image*/

            double[][] frames = new double[width][];
            int[]      logFrequenciesIndexes = GenerateLogFrequencies(configuration);
            double[]   window = windowFunction.GetWindow();
            for (int i = 0; i < width; i++)
            {
                double[] complexSignal = new double[2 * configuration.WindowSize];                 /*even - Re, odd - Img, thats how Exocortex works*/

                // take 371 ms each 11.6 ms (2048 samples each 64 samples, samplerate 5512)
                // or 256 ms each 16 ms (8192 samples each 512 samples, samplerate 32000)
                for (int j = 0; j < configuration.WindowSize; j++)
                {
                    // Weight by Hann Window
                    complexSignal[2 * j] = window[j] * samples[(i * configuration.Overlap) + j];

                    // need to clear out as fft modifies buffer (phase)
                    complexSignal[(2 * j) + 1] = 0;
                }

                lomonFFT.TableFFT(complexSignal, true);

                frames[i] = ExtractLogBins(complexSignal, logFrequenciesIndexes, configuration.LogBins);
            }

            Dbg.WriteLine("Create Log Spectrogram - Execution Time: {0} ms", t.Stop().TotalMilliseconds);
            return(frames);
        }
コード例 #5
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);
        }