コード例 #1
0
        public List<bool[]> CreateFingerprintsFromAudioSamples(float[] samples, WorkUnitParameterObject param, out double[][] logSpectrogram, out List<double[][]> spectralImages)
        {
            IFingerprintingConfiguration configuration = param.FingerprintingConfiguration;
            AudioServiceConfiguration audioServiceConfiguration = new AudioServiceConfiguration
            {
                LogBins = configuration.LogBins,
                LogBase = configuration.LogBase,
                MaxFrequency = configuration.MaxFrequency,
                MinFrequency = configuration.MinFrequency,
                Overlap = configuration.Overlap,
                SampleRate = configuration.SampleRate,
                WindowSize = configuration.WindowSize,
                NormalizeSignal = configuration.NormalizeSignal,
                UseDynamicLogBase = configuration.UseDynamicLogBase
            };

            // store the log spectrogram in the out variable
            logSpectrogram = AudioService.CreateLogSpectrogram(
                samples, configuration.WindowFunction, audioServiceConfiguration);

            return this.CreateFingerprintsFromLogSpectrum(
                logSpectrogram,
                configuration.Stride,
                configuration.FingerprintLength,
                configuration.Overlap,
                configuration.TopWavelets,
                out spectralImages);
        }
コード例 #2
0
        private List<bool[]> CreateFingerprintsFromAudioSamples(float[] samples, WorkUnitParameterObject param)
        {
            IFingerprintingConfiguration configuration = param.FingerprintingConfiguration;
            AudioServiceConfiguration audioServiceConfiguration = new AudioServiceConfiguration
                {
                    LogBins = configuration.LogBins,
                    LogBase = configuration.LogBase,
                    MaxFrequency = configuration.MaxFrequency,
                    MinFrequency = configuration.MinFrequency,
                    Overlap = configuration.Overlap,
                    SampleRate = configuration.SampleRate,
                    WdftSize = configuration.WdftSize
                };

            float[][] spectrum = audioService.CreateLogSpectrogram(
                samples, configuration.WindowFunction, audioServiceConfiguration);

            return CreateFingerprintsFromSpectrum(
                spectrum,
                configuration.Stride,
                configuration.FingerprintLength,
                configuration.Overlap,
                configuration.LogBins,
                configuration.TopWavelets);
        }
コード例 #3
0
        public Task<List<bool[]>> Process(WorkUnitParameterObject details)
        {
            if (!string.IsNullOrEmpty(details.PathToAudioFile))
            {
                return Task.Factory.StartNew(() => CreateFingerprintsFromAudioFile(details));
            }

            return Task.Factory.StartNew(() => CreateFingerprintsFromAudioSamples(details.AudioSamples, details));
        }
コード例 #4
0
		public List<bool[]> CreateFingerprintsFromAudioFile(WorkUnitParameterObject param, out double[][] logSpectrogram)
		{
			float[] samples = AudioService.ReadMonoFromFile(
				param.PathToAudioFile,
				param.FingerprintingConfiguration.SampleRate,
				param.MillisecondsToProcess,
				param.StartAtMilliseconds);

			return CreateFingerprintsFromAudioSamples(samples, param, out logSpectrogram);
		}
コード例 #5
0
ファイル: Repository.cs プロジェクト: remy22/FindSimilar
        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;
        }
コード例 #6
0
ファイル: Analyzer.cs プロジェクト: nguyendauit/FindSimilar
        private static bool AnalyseAndAddScmsUsingFingerprints(List<double[][]> spectralImages,
		                                                       List<bool[]> fingerprints,
		                                                       WorkUnitParameterObject param,
		                                                       Db db,
		                                                       int trackId,
		                                                       bool doOutputDebugInfo=DEFAULT_DEBUG_INFO)
        {
            DbgTimer t = new DbgTimer();
            t.Start ();

            // Insert Statistical Cluster Model Similarity Audio Feature
            string fileName = param.FileName;

            // Merge the arrays in the List using Linq
            var result = spectralImages.SelectMany(i => i).ToArray();
            Comirva.Audio.Util.Maths.Matrix scmsMatrix = new Comirva.Audio.Util.Maths.Matrix(result);

            if (doOutputDebugInfo) {
                scmsMatrix.DrawMatrixImage(String.Format("{0}_spectral.png", fileName));
            }

            #region Store in a Statistical Cluster Model Similarity class.
            Scms audioFeature = Scms.GetScms(scmsMatrix, fileName);

            if (audioFeature != null) {

                // Store bitstring hash as well
                audioFeature.BitString = GetBitString(scmsMatrix);

                // Store duration
                audioFeature.Duration = (long) param.DurationInMs;

                // Store file name
                audioFeature.Name = param.PathToAudioFile;

                // Add to database
                int id = trackId;
                if (db.AddTrack(audioFeature) == -1) {
                    Console.Out.WriteLine("Failed! Could not add audio feature to database ({0})!", fileName);
                    return false;
                }
            } else {
                return false;
            }
            #endregion

            Dbg.WriteLine ("AnalyseAndAddScmsUsingFingerprints2 - Execution Time: {0} ms", t.Stop().TotalMilliseconds);
            return true;
        }
コード例 #7
0
ファイル: Repository.cs プロジェクト: remy22/FindSimilar
 /// <summary>
 /// Insert track into database
 /// </summary>
 /// <param name="track">Track</param>
 /// <param name="hashTables">Number of hash tables (e.g. 25)</param>
 /// <param name="hashKeys">Number of hash keys (e.g. 4)</param>
 /// <param name="param">WorkUnitParameterObject parameters</param>
 public bool InsertTrackInDatabaseUsingSamples(Track track, int hashTables, int hashKeys, WorkUnitParameterObject param, out double[][] logSpectrogram)
 {
     if (dbService.InsertTrack(track)) {
         List<bool[]> images = fingerprintService.CreateFingerprintsFromAudioSamples(param.AudioSamples, param, out logSpectrogram);
         List<Fingerprint> inserted = AssociateFingerprintsToTrack(images, track.Id);
         if (dbService.InsertFingerprint(inserted)) {
             return HashFingerprintsUsingMinHash(inserted, track, hashTables, hashKeys);
         } else {
             return false;
         }
     } else {
         logSpectrogram = null;
         return false;
     }
 }
コード例 #8
0
ファイル: Analyzer.cs プロジェクト: remy22/FindSimilar
        // TODO: Rememeber to use another stride when querying
        public static Dictionary<Track, double> SimilarTracksSoundfingerprinting(FileInfo filePath)
        {
            DbgTimer t = new DbgTimer();
            t.Start ();
            FindSimilar.AudioProxies.BassProxy bass = FindSimilar.AudioProxies.BassProxy.Instance;

            float[] audiodata = AudioFileReader.Decode(filePath.FullName, SAMPLING_RATE, SECONDS_TO_ANALYZE);
            if (audiodata == null || audiodata.Length == 0)  {
                Dbg.WriteLine("Error! - No Audio Found");
                return null;
            }

            // Name of file being processed
            string name = StringUtils.RemoveNonAsciiCharacters(Path.GetFileNameWithoutExtension(filePath.Name));

            // Calculate duration in ms
            double duration = (double) audiodata.Length / SAMPLING_RATE * 1000;

            // Explode samples to the range of 16 bit shorts (–32,768 to 32,767)
            // Matlab multiplies with 2^15 (32768)
            // e.g. if( max(abs(speech))<=1 ), speech = speech * 2^15; end;
            MathUtils.Multiply(ref audiodata, AUDIO_MULTIPLIER); // 65536

            // zero pad if the audio file is too short to perform a mfcc
            if (audiodata.Length < (fingerprintingConfig.WdftSize + fingerprintingConfig.Overlap))
            {
                int lenNew = fingerprintingConfig.WdftSize + fingerprintingConfig.Overlap;
                Array.Resize<float>(ref audiodata, lenNew);
            }

            // Get fingerprint signatures using the Soundfingerprinting methods

            // Get database
            DatabaseService databaseService = DatabaseService.Instance;

            IPermutations permutations = new LocalPermutations("Soundfingerprinting\\perms.csv", ",");
            Repository repository = new Repository(permutations, databaseService, fingerprintService);

            // work config
            WorkUnitParameterObject param = new WorkUnitParameterObject();
            param.FingerprintingConfiguration = fingerprintingConfig;
            param.PathToAudioFile = filePath.FullName;
            param.AudioSamples = audiodata;
            param.MillisecondsToProcess = SECONDS_TO_ANALYZE * 1000;
            param.StartAtMilliseconds = 0;

            Dictionary<Track, double> candidates = repository.FindSimilarFromAudioSamples(25, 4, 2, param);
            return candidates;

            /*
            // Use var keyword to enumerate dictionary
            foreach (var pair in candidates)
            {
                Console.WriteLine("{0} - {1:0.00}",
                                  pair.Key.Title,
                                  pair.Value);
            }
             */

            Dbg.WriteLine ("Soundfingerprinting - Total Execution Time: {0} ms", t.Stop().TotalMilliseconds);
        }
コード例 #9
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;
		}
コード例 #10
0
ファイル: Analyzer.cs プロジェクト: nguyendauit/FindSimilar
        /// <summary>
        /// Return information from the Audio File
        /// </summary>
        /// <param name="filePath">filepath object</param>
        /// <returns>a WorkUnitParameter object</returns>
        public static WorkUnitParameterObject GetWorkUnitParameterObjectFromAudioFile(FileInfo filePath, bool doOutputDebugInfo=DEFAULT_DEBUG_INFO)
        {
            DbgTimer t = new DbgTimer();
            t.Start ();

            float[] audiodata = AudioFileReader.Decode(filePath.FullName, SAMPLING_RATE, SECONDS_TO_ANALYZE);
            if (audiodata == null || audiodata.Length == 0)  {
                Dbg.WriteLine("Error! - No Audio Found");
                return null;
            }

            // Name of file being processed
            string fileName = StringUtils.RemoveNonAsciiCharacters(Path.GetFileNameWithoutExtension(filePath.Name));

            #if DEBUG
            if (DEBUG_INFO_VERBOSE) {
                if (DEBUG_OUTPUT_TEXT) WriteAscii(audiodata, fileName + "_audiodata.ascii");
                if (DEBUG_OUTPUT_TEXT) WriteF3Formatted(audiodata, fileName + "_audiodata.txt");
            }
            #endif

            if (doOutputDebugInfo) {
                DrawGraph(MathUtils.FloatToDouble(audiodata), fileName + "_audiodata.png");
            }

            // Calculate duration in ms
            double duration = (double) audiodata.Length / SAMPLING_RATE * 1000;

            // Explode samples to the range of 16 bit shorts (–32,768 to 32,767)
            // Matlab multiplies with 2^15 (32768)
            // e.g. if( max(abs(speech))<=1 ), speech = speech * 2^15; end;
            MathUtils.Multiply(ref audiodata, AUDIO_MULTIPLIER);

            // zero pad if the audio file is too short to perform a mfcc
            if (audiodata.Length < (WINDOW_SIZE + OVERLAP))
            {
                int lenNew = WINDOW_SIZE + OVERLAP;
                Array.Resize<float>(ref audiodata, lenNew);
            }

            // work config
            WorkUnitParameterObject param = new WorkUnitParameterObject();
            param.AudioSamples = audiodata;
            param.PathToAudioFile = filePath.FullName;
            param.MillisecondsToProcess = SECONDS_TO_ANALYZE * 1000;
            param.StartAtMilliseconds = 0;
            param.FileName = fileName;
            param.DurationInMs = duration;
            param.Tags = GetTagInfoFromFile(filePath.FullName);

            Dbg.WriteLine ("Get Audio File Parameters - Execution Time: {0} ms", t.Stop().TotalMilliseconds);
            return param;
        }
コード例 #11
0
ファイル: Analyzer.cs プロジェクト: remy22/FindSimilar
        private static List<int[]> TestSoundfingerprintingAlgorithm(float[] samples, string name)
        {
            // work config
            WorkUnitParameterObject param = new WorkUnitParameterObject();
            param.FingerprintingConfiguration = fingerprintingConfig;

            // Soundfingerprinting Service
            FingerprintService fingerprintService = GetSoundfingerprintingService();

            // Image Service
            ImageService imageService =
                new ImageService(fingerprintService.SpectrumService, fingerprintService.WaveletService);

            // Get fingerprints
            double[][] LogSpectrogram;
            List<bool[]> fingerprints = fingerprintService.CreateFingerprintsFromAudioSamples(samples, param, out LogSpectrogram);
            int width = param.FingerprintingConfiguration.FingerprintLength;
            int height = param.FingerprintingConfiguration.LogBins;
            imageService.GetImageForFingerprints(fingerprints, width, height, 2).Save("imageservice_" + name + "_fingerprints.png");

            IPermutations permutations = new LocalPermutations("Soundfingerprinting\\perms.csv", ",");

            /*
            Soundfingerprinting.DuplicatesDetector.DataAccess.Repository repository = new Soundfingerprinting.DuplicatesDetector.DataAccess.Repository(permutations);

            // Define track
            Soundfingerprinting.DuplicatesDetector.Model.Track track
                = new Soundfingerprinting.DuplicatesDetector.Model.Track {
                Title = name
            };
             */

            Soundfingerprinting.Hashing.MinHash hasher = new Soundfingerprinting.Hashing.MinHash(permutations);
            List<int[]> signatures = new List<int[]>();
            foreach (bool[] fingerprint in fingerprints)
            {
                int[] signature = hasher.ComputeMinHashSignature(fingerprint); /*Compute min-hash signature out of signature*/
                signatures.Add(signature);
            }
            return signatures;
        }
コード例 #12
0
ファイル: Analyzer.cs プロジェクト: remy22/FindSimilar
        private static void TestSoundfingerprintingAlgorithm(string filename, string name)
        {
            // work config
            WorkUnitParameterObject param = new WorkUnitParameterObject();
            param.PathToAudioFile = filename;
            param.StartAtMilliseconds = 0;
            param.MillisecondsToProcess = 0;
            param.FingerprintingConfiguration = fingerprintingConfig;

            // Soundfingerprinting Service
            FingerprintService fingerprintService = GetSoundfingerprintingService();

            // Image Service
            ImageService imageService = new ImageService(
                fingerprintService.SpectrumService,
                fingerprintService.WaveletService);

            // Configuration
            AudioServiceConfiguration audioServiceConfiguration = new AudioServiceConfiguration
            {
                LogBins = fingerprintingConfig.LogBins,
                LogBase = fingerprintingConfig.LogBase,
                MaxFrequency = fingerprintingConfig.MaxFrequency,
                MinFrequency = fingerprintingConfig.MinFrequency,
                Overlap = fingerprintingConfig.Overlap,
                SampleRate = fingerprintingConfig.SampleRate,
                WdftSize = fingerprintingConfig.WdftSize,
                NormalizeSignal = fingerprintingConfig.NormalizeSignal,
                UseDynamicLogBase = fingerprintingConfig.UseDynamicLogBase
            };

            double[][] spectrogram = fingerprintService.AudioService.CreateSpectrogram(filename, new Mirage.HannWindow(fingerprintingConfig.WdftSize), fingerprintingConfig.SampleRate, fingerprintingConfig.Overlap, fingerprintingConfig.WdftSize);
            imageService.GetSpectrogramImage(spectrogram, 600, 400).Save("imageservice_" + name + "_specgram.png");

            /*
            Comirva.Audio.Util.Maths.Matrix stftdata = new Comirva.Audio.Util.Maths.Matrix(spectrogram).Transpose();
            #if DEBUG
            if (Analyzer.DEBUG_INFO_VERBOSE) {
                if (DEBUG_OUTPUT_TEXT) {
                    stftdata.WriteAscii(name + "_stftdata2.ascii");
                    stftdata.WriteCSV(name + "_stftdata2.csv", ";");
                }

                // same as specgram(audio*32768, 2048, 44100, hanning(2048), 1024);
                stftdata.DrawMatrixImageLogValues(name + "_specgram2.png", true);

                // spec gram with log values for the y axis (frequency)
                stftdata.DrawMatrixImageLogY(name + "_specgramlog2.png", SAMPLING_RATE, 20, SAMPLING_RATE/2, 120, WINDOW_SIZE);
            }
            #endif
             */

            double[][] logSpectrogram = fingerprintService.AudioService.CreateLogSpectrogram(filename, new Mirage.HannWindow(fingerprintingConfig.WdftSize), audioServiceConfiguration);
            imageService.GetLogSpectralImages(logSpectrogram, fingerprintingConfig.Stride, fingerprintingConfig.FingerprintLength, fingerprintingConfig.Overlap, 2).Save("imageservice_" + name + "_specgram_logimages.png");

            Comirva.Audio.Util.Maths.Matrix stftdataLog = new Comirva.Audio.Util.Maths.Matrix(logSpectrogram).Transpose();
            #if DEBUG
            if (Analyzer.DEBUG_INFO_VERBOSE) {
                if (DEBUG_OUTPUT_TEXT) {
                    stftdataLog.WriteAscii(name + "_stftdataLog.ascii");
                    stftdataLog.WriteCSV(name + "_stftdataLog.csv", ";");
                }

                // same as specgram(audio*32768, 2048, 44100, hanning(2048), 1024);
                stftdataLog.DrawMatrixImageLogValues(name + "_stftdataLog.png", true);
            }
            #endif

            // Get fingerprints
            double[][] LogSpectrogram;
            List<bool[]> fingerprints = fingerprintService.CreateFingerprintsFromAudioFile(param, out LogSpectrogram);
            int width = fingerprintingConfig.FingerprintLength;
            int height = fingerprintingConfig.LogBins;
            imageService.GetImageForFingerprints(fingerprints, width, height, 2).Save("imageservice_" + name + "_fingerprints.png");

            /*
            IPermutations permutations = new LocalPermutations("Soundfingerprinting\\perms.csv", ",");
            Soundfingerprinting.DuplicatesDetector.DataAccess.Repository repository = new Soundfingerprinting.DuplicatesDetector.DataAccess.Repository(permutations);

            // Define track
            Soundfingerprinting.DuplicatesDetector.Model.Track track
                = new Soundfingerprinting.DuplicatesDetector.Model.Track {
                Title = name,
                Path = filename
            };

            // Get the HashSignatures
            List<Soundfingerprinting.DuplicatesDetector.Model.HashSignature> signatures = repository.GetSignatures(fingerprints, track, 25, 4);
            return signatures;
             */
        }
コード例 #13
0
ファイル: Repository.cs プロジェクト: nguyendauit/FindSimilar
        /// <summary>
        /// Find Similar Tracks using passed audio samples 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>
        /// <returns>a list of perceptually similar tracks</returns>
        public List<FindSimilar.QueryResult> FindSimilarFromAudioSamplesList(
			int lshHashTables,
			int lshGroupsPerKey,
			int thresholdTables,
			WorkUnitParameterObject param)
        {
            // Get fingerprints
            double[][] logSpectrogram;
            List<double[][]> spectralImages;
            List<bool[]> signatures = fingerprintService.CreateFingerprintsFromAudioSamples(param.AudioSamples, param, out logSpectrogram, out spectralImages);

            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
            // TODO: What does the 0.4 number do here?
            // there doesn't seem to be any change using another number?!

            // 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 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();

            return fingerprintList;
        }
コード例 #14
0
ファイル: Analyzer.cs プロジェクト: nguyendauit/FindSimilar
        /// <summary>
        /// Add the log spectrogram matrix as a Statistical Cluster Model Similarity class to the database
        /// </summary>
        /// <param name="logSpectrogramMatrix">log spectrogram matrix</param>
        /// <param name="fileName">clean filename without extension</param>
        /// <param name="fullFilePath">full file path</param>
        /// <param name="duration">duration in ms</param>
        /// <param name="db">database</param>
        /// <param name="trackId">track id to insert</param>
        /// <param name="doOutputDebugInfo">decide whether to output debug info like spectrogram and audiofile (default value can be set)</param>
        /// <param name="useHaarWavelet">decide whether to use haar wavelet compression or DCT compression</param>
        /// <returns>true if successful</returns>
        private static bool AnalyseAndAddScmsUsingLogSpectrogram(Comirva.Audio.Util.Maths.Matrix logSpectrogramMatrix,
		                                                         WorkUnitParameterObject param,
		                                                         Db db,
		                                                         int trackId,
		                                                         bool doOutputDebugInfo=DEFAULT_DEBUG_INFO,
		                                                         bool useHaarWavelet = true)
        {
            // Insert Statistical Cluster Model Similarity Audio Feature
            string fileName = param.FileName;

            Comirva.Audio.Util.Maths.Matrix scmsMatrix = null;
            if (useHaarWavelet) {
                #region Wavelet Transform
                int lastHeight = 0;
                int lastWidth = 0;
                scmsMatrix = mfccMirage.ApplyWaveletCompression(ref logSpectrogramMatrix, out lastHeight, out lastWidth);

                #if DEBUG
                if (DEBUG_INFO_VERBOSE) {
                    if (DEBUG_OUTPUT_TEXT) scmsMatrix.WriteAscii(fileName + "_waveletdata.ascii");
                }
                #endif

                if (doOutputDebugInfo) {
                    scmsMatrix.DrawMatrixImageLogValues(fileName + "_waveletdata.png", true);
                }

                #if DEBUG
                if (DEBUG_DO_INVERSE_TESTS) {
                    #region Inverse Wavelet
                    // try to do an inverse wavelet transform
                    Comirva.Audio.Util.Maths.Matrix stftdata_inverse_wavelet = mfccMirage.InverseWaveletCompression(ref scmsMatrix, lastHeight, lastWidth, logSpectrogramMatrix.Rows, logSpectrogramMatrix.Columns);

                    if (DEBUG_OUTPUT_TEXT) stftdata_inverse_wavelet.WriteCSV(fileName + "_specgramlog_inverse_wavelet.csv", ";");
                    stftdata_inverse_wavelet.DrawMatrixImageLogValues(fileName + "_specgramlog_inverse_wavelet.png", true);
                    #endregion
                }
                #endif
                #endregion
            } else {
                #region DCT Transform
                // It seems the Mirage way of applying the DCT is slightly faster than the
                // Comirva way due to less loops
                scmsMatrix = mfccMirage.ApplyDCT(ref logSpectrogramMatrix);

                #if DEBUG
                if (DEBUG_INFO_VERBOSE) {
                    if (DEBUG_OUTPUT_TEXT) scmsMatrix.WriteAscii(fileName + "_mfccdata.ascii");
                }
                #endif

                if (doOutputDebugInfo) {
                    scmsMatrix.DrawMatrixImageLogValues(fileName + "_mfccdata.png", true);
                }

                #if DEBUG
                if (DEBUG_DO_INVERSE_TESTS) {
                    #region Inverse MFCC
                    // try to do an inverse mfcc
                    Comirva.Audio.Util.Maths.Matrix stftdata_inverse_mfcc = mfccMirage.InverseDCT(ref scmsMatrix);

                    if (DEBUG_OUTPUT_TEXT) stftdata_inverse_mfcc.WriteCSV(fileName + "_stftdata_inverse_mfcc.csv", ";");
                    stftdata_inverse_mfcc.DrawMatrixImageLogValues(fileName + "_specgramlog_inverse_mfcc.png", true);
                    #endregion
                }
                #endif
                #endregion
            }

            // Store in a Statistical Cluster Model Similarity class.
            // i.e. a Gaussian representation of a song
            Scms audioFeature = Scms.GetScms(scmsMatrix, fileName);

            if (audioFeature != null) {

                // Store image if debugging
                if (doOutputDebugInfo) {
                    audioFeature.Image = scmsMatrix.DrawMatrixImageLogValues(fileName + "_featuredata.png", true, false, 0, 0, true);
                }

                // Store bitstring hash as well
                string hashString = GetBitString(scmsMatrix);
                audioFeature.BitString = hashString;

                // Store duration
                audioFeature.Duration = (long) param.DurationInMs;

                // Store file name
                audioFeature.Name = param.PathToAudioFile;

                // Add to database
                int id = trackId;
                if (db.AddTrack(ref id, audioFeature) == -1) {
                    Console.Out.WriteLine("Failed! Could not add audio feature to database ({0})!", fileName);
                    return false;
                } else {
                    return true;
                }
            } else {
                Console.Out.WriteLine("Error! Could not compute the Scms for '{0}'!", fileName);
                return false;
            }
        }
コード例 #15
0
ファイル: Analyzer.cs プロジェクト: remy22/FindSimilar
        //private static Mfcc mfccOptimized = new Mfcc(WINDOW_SIZE, SAMPLING_RATE, MEL_COEFFICIENTS, MFCC_COEFFICIENTS);
        //private static MFCC mfccComirva = new MFCC(SAMPLING_RATE, WINDOW_SIZE, MFCC_COEFFICIENTS, true, 20.0, SAMPLING_RATE/2, MEL_COEFFICIENTS);

        #endif

        #region Methods

        public static bool AnalyzeAndAdd(FileInfo filePath, Db db, DatabaseService databaseService, bool doOutputDebugInfo=DEFAULT_DEBUG_INFO, bool useHaarWavelet = true)
        {
            DbgTimer t = new DbgTimer();
            t.Start ();

            float[] audiodata = AudioFileReader.Decode(filePath.FullName, SAMPLING_RATE, SECONDS_TO_ANALYZE);
            if (audiodata == null || audiodata.Length == 0)  {
                Dbg.WriteLine("Error! - No Audio Found");
                return false;
            }

            // Read TAGs using BASS
            FindSimilar.AudioProxies.BassProxy bass = FindSimilar.AudioProxies.BassProxy.Instance;
            Un4seen.Bass.AddOn.Tags.TAG_INFO tag_info = bass.GetTagInfoFromFile(filePath.FullName);

            // Name of file being processed
            string name = StringUtils.RemoveNonAsciiCharacters(Path.GetFileNameWithoutExtension(filePath.Name));

            #if DEBUG
            if (Analyzer.DEBUG_INFO_VERBOSE) {
                if (DEBUG_OUTPUT_TEXT) WriteAscii(audiodata, name + "_audiodata.ascii");
                if (DEBUG_OUTPUT_TEXT) WriteF3Formatted(audiodata, name + "_audiodata.txt");
            }
            #endif

            if (doOutputDebugInfo) {
                DrawGraph(MathUtils.FloatToDouble(audiodata), name + "_audiodata.png");
            }

            // Calculate duration in ms
            double duration = (double) audiodata.Length / SAMPLING_RATE * 1000;

            // Explode samples to the range of 16 bit shorts (–32,768 to 32,767)
            // Matlab multiplies with 2^15 (32768)
            // e.g. if( max(abs(speech))<=1 ), speech = speech * 2^15; end;
            MathUtils.Multiply(ref audiodata, AUDIO_MULTIPLIER); // 65536

            // zero pad if the audio file is too short to perform a mfcc
            if (audiodata.Length < (fingerprintingConfig.WdftSize + fingerprintingConfig.Overlap))
            {
                int lenNew = fingerprintingConfig.WdftSize + fingerprintingConfig.Overlap;
                Array.Resize<float>(ref audiodata, lenNew);
            }

            // Get fingerprint signatures using the Soundfingerprinting methods
            IPermutations permutations = new LocalPermutations("Soundfingerprinting\\perms.csv", ",");
            Repository repository = new Repository(permutations, databaseService, fingerprintService);

            // Image Service
            ImageService imageService = new ImageService(
                fingerprintService.SpectrumService,
                fingerprintService.WaveletService);

            // work config
            WorkUnitParameterObject param = new WorkUnitParameterObject();
            param.FingerprintingConfiguration = fingerprintingConfig;
            param.AudioSamples = audiodata;
            param.PathToAudioFile = filePath.FullName;
            param.MillisecondsToProcess = SECONDS_TO_ANALYZE * 1000;
            param.StartAtMilliseconds = 0;

            // build track
            Track track = new Track();
            track.Title = name;
            track.TrackLengthMs = (int) duration;
            track.FilePath = filePath.FullName;
            track.Id = -1; // this will be set by the insert method

            #region parse tag_info
            if (tag_info != null) {
                Dictionary<string, string> tags = new Dictionary<string, string>();

                //if (tag_info.title != string.Empty) tags.Add("title", tag_info.title);
                if (tag_info.artist != string.Empty) tags.Add("artist", tag_info.artist);
                if (tag_info.album != string.Empty) tags.Add("album", tag_info.album);
                if (tag_info.albumartist != string.Empty) tags.Add("albumartist", tag_info.albumartist);
                if (tag_info.year != string.Empty) tags.Add("year", tag_info.year);
                if (tag_info.comment != string.Empty) tags.Add("comment", tag_info.comment);
                if (tag_info.genre != string.Empty) tags.Add("genre", tag_info.genre);
                if (tag_info.track != string.Empty) tags.Add("track", tag_info.track);
                if (tag_info.disc != string.Empty) tags.Add("disc", tag_info.disc);
                if (tag_info.copyright != string.Empty) tags.Add("copyright", tag_info.copyright);
                if (tag_info.encodedby != string.Empty) tags.Add("encodedby", tag_info.encodedby);
                if (tag_info.composer != string.Empty) tags.Add("composer", tag_info.composer);
                if (tag_info.publisher != string.Empty) tags.Add("publisher", tag_info.publisher);
                if (tag_info.lyricist != string.Empty) tags.Add("lyricist", tag_info.lyricist);
                if (tag_info.remixer != string.Empty) tags.Add("remixer", tag_info.remixer);
                if (tag_info.producer != string.Empty) tags.Add("producer", tag_info.producer);
                if (tag_info.bpm != string.Empty) tags.Add("bpm", tag_info.bpm);
                //if (tag_info.filename != string.Empty) tags.Add("filename", tag_info.filename);
                tags.Add("channelinfo", tag_info.channelinfo.ToString());
                //if (tag_info.duration > 0) tags.Add("duration", tag_info.duration.ToString());
                if (tag_info.bitrate > 0) tags.Add("bitrate", tag_info.bitrate.ToString());
                if (tag_info.replaygain_track_gain != -100f) tags.Add("replaygain_track_gain", tag_info.replaygain_track_gain.ToString());
                if (tag_info.replaygain_track_peak != -1f) tags.Add("replaygain_track_peak", tag_info.replaygain_track_peak.ToString());
                if (tag_info.conductor != string.Empty) tags.Add("conductor", tag_info.conductor);
                if (tag_info.grouping != string.Empty) tags.Add("grouping", tag_info.grouping);
                if (tag_info.mood != string.Empty) tags.Add("mood", tag_info.mood);
                if (tag_info.rating != string.Empty) tags.Add("rating", tag_info.rating);
                if (tag_info.isrc != string.Empty) tags.Add("isrc", tag_info.isrc);

                foreach(var nativeTag in tag_info.NativeTags) {
                    string[] keyvalue = nativeTag.Split('=');
                    tags.Add(keyvalue[0], keyvalue[1]);
                }
                track.Tags = tags;
            }
            #endregion

            double[][] logSpectrogram;
            if (repository.InsertTrackInDatabaseUsingSamples(track, 25, 4, param, out logSpectrogram)) {

                // store logSpectrogram as Matrix
                Comirva.Audio.Util.Maths.Matrix logSpectrogramMatrix = new Comirva.Audio.Util.Maths.Matrix(logSpectrogram);
                logSpectrogramMatrix = logSpectrogramMatrix.Transpose();

                #region Debug for Soundfingerprinting Method
                if (doOutputDebugInfo) {
                    imageService.GetLogSpectralImages(logSpectrogram, fingerprintingConfig.Stride, fingerprintingConfig.FingerprintLength, fingerprintingConfig.Overlap, 2).Save(name + "_specgram_logimages.png");

                    logSpectrogramMatrix.DrawMatrixImageLogValues(name + "_specgram_logimage.png", true);

                    if (DEBUG_OUTPUT_TEXT) {
                        logSpectrogramMatrix.WriteCSV(name + "_specgram_log.csv", ";");
                    }
                }
                #endregion

                #region Insert Statistical Cluster Model Similarity Audio Feature as well
                Comirva.Audio.Util.Maths.Matrix scmsMatrix = null;
                if (useHaarWavelet) {
                    #region Wavelet Transform
                    int lastHeight = 0;
                    int lastWidth = 0;
                    scmsMatrix = mfccMirage.ApplyWaveletCompression(ref logSpectrogramMatrix, out lastHeight, out lastWidth);

                    #if DEBUG
                    if (Analyzer.DEBUG_INFO_VERBOSE) {
                        if (DEBUG_OUTPUT_TEXT) scmsMatrix.WriteAscii(name + "_waveletdata.ascii");
                    }
                    #endif

                    if (doOutputDebugInfo) {
                        scmsMatrix.DrawMatrixImageLogValues(name + "_waveletdata.png", true);
                    }

                    #if DEBUG
                    if (Analyzer.DEBUG_INFO_VERBOSE) {
                        #region Inverse Wavelet
                        // try to do an inverse wavelet transform
                        Comirva.Audio.Util.Maths.Matrix stftdata_inverse_wavelet = mfccMirage.InverseWaveletCompression(ref scmsMatrix, lastHeight, lastWidth, logSpectrogramMatrix.Rows, logSpectrogramMatrix.Columns);

                        if (DEBUG_OUTPUT_TEXT) stftdata_inverse_wavelet.WriteCSV(name + "_specgramlog_inverse_wavelet.csv", ";");
                        stftdata_inverse_wavelet.DrawMatrixImageLogValues(name + "_specgramlog_inverse_wavelet.png", true);
                        #endregion
                    }
                    #endif
                    #endregion
                } else {
                    #region DCT Transform
                    // It seems the Mirage way of applying the DCT is slightly faster than the
                    // Comirva way due to less loops
                    scmsMatrix = mfccMirage.ApplyDCT(ref logSpectrogramMatrix);

                    #if DEBUG
                    if (Analyzer.DEBUG_INFO_VERBOSE) {
                        if (DEBUG_OUTPUT_TEXT) scmsMatrix.WriteAscii(name + "_mfccdata.ascii");
                    }
                    #endif

                    if (doOutputDebugInfo) {
                        scmsMatrix.DrawMatrixImageLogValues(name + "_mfccdata.png", true);
                    }

                    #if DEBUG
                    if (Analyzer.DEBUG_INFO_VERBOSE) {
                        #region Inverse MFCC
                        // try to do an inverse mfcc
                        Comirva.Audio.Util.Maths.Matrix stftdata_inverse_mfcc = mfccMirage.InverseDCT(ref scmsMatrix);

                        if (DEBUG_OUTPUT_TEXT) stftdata_inverse_mfcc.WriteCSV(name + "_stftdata_inverse_mfcc.csv", ";");
                        stftdata_inverse_mfcc.DrawMatrixImageLogValues(name + "_specgramlog_inverse_mfcc.png", true);
                        #endregion
                    }
                    #endif
                    #endregion
                }

                // Store in a Statistical Cluster Model Similarity class.
                // A Gaussian representation of a song
                Scms audioFeature = Scms.GetScms(scmsMatrix, name);

                if (audioFeature != null) {

                    // Store image if debugging
                    if (doOutputDebugInfo) {
                        audioFeature.Image = scmsMatrix.DrawMatrixImageLogValues(name + "_featuredata.png", true, false, 0, 0, true);
                    }

                    // Store bitstring hash as well
                    string hashString = GetBitString(scmsMatrix);
                    audioFeature.BitString = hashString;

                    // Store duration
                    audioFeature.Duration = (long) duration;

                    // Store file name
                    audioFeature.Name = filePath.FullName;

                    int id = track.Id;
                    if (db.AddTrack(ref id, audioFeature) == -1) {
                        Console.Out.WriteLine("Failed! Could not add audioFeature to database {0}!", name);
                    }
                }
                #endregion

            } else {
                // failed
                return false;
            }

            Dbg.WriteLine ("AnalyzeAndAdd - Total Execution Time: {0} ms", t.Stop().TotalMilliseconds);
            return true;
        }
コード例 #16
0
ファイル: Analyzer.cs プロジェクト: nguyendauit/FindSimilar
        private static List<bool[]> GetFingerprintSignatures(FingerprintService fingerprintService, float[] samples, string name)
        {
            Mirage.DbgTimer t = new Mirage.DbgTimer();
            t.Start();

            // work config
            WorkUnitParameterObject param = new WorkUnitParameterObject();
            param.FingerprintingConfiguration = fingerprintingConfigCreation;

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

            #if DEBUG
            if (Analyzer.DEBUG_INFO_VERBOSE) {
                // Image Service
                ImageService imageService =
                    new ImageService(fingerprintService.SpectrumService, fingerprintService.WaveletService);

                int width = param.FingerprintingConfiguration.FingerprintLength;
                int height = param.FingerprintingConfiguration.LogBins;
                imageService.GetImageForFingerprints(fingerprints, width, height, 2).Save(name + "_fingerprints.png");
            }
            #endif

            Mirage.Dbg.WriteLine("GetFingerprintSignatures Execution Time: " + t.Stop().TotalMilliseconds + " ms");
            return fingerprints;
        }
コード例 #17
0
ファイル: Analyzer.cs プロジェクト: remy22/FindSimilar
        public static AudioFeature AnalyzeSoundfingerprinting(FileInfo filePath, bool doOutputDebugInfo=DEFAULT_DEBUG_INFO, bool useHaarWavelet = true)
        {
            DbgTimer t = new DbgTimer();
            t.Start ();

            float[] audiodata = AudioFileReader.Decode(filePath.FullName, SAMPLING_RATE, SECONDS_TO_ANALYZE);
            if (audiodata == null || audiodata.Length == 0)  {
                Dbg.WriteLine("Error! - No Audio Found");
                return null;
            }

            // Read TAGs using BASS
            FindSimilar.AudioProxies.BassProxy bass = FindSimilar.AudioProxies.BassProxy.Instance;
            Un4seen.Bass.AddOn.Tags.TAG_INFO tag_info = bass.GetTagInfoFromFile(filePath.FullName);

            // Name of file being processed
            string name = StringUtils.RemoveNonAsciiCharacters(Path.GetFileNameWithoutExtension(filePath.Name));

            #if DEBUG
            if (Analyzer.DEBUG_INFO_VERBOSE) {
                if (DEBUG_OUTPUT_TEXT) WriteAscii(audiodata, name + "_audiodata.ascii");
                if (DEBUG_OUTPUT_TEXT) WriteF3Formatted(audiodata, name + "_audiodata.txt");
            }
            #endif

            if (doOutputDebugInfo) {
                DrawGraph(MathUtils.FloatToDouble(audiodata), name + "_audiodata.png");
            }

            // Calculate duration in ms
            double duration = (double) audiodata.Length / SAMPLING_RATE * 1000;

            // zero pad if the audio file is too short to perform a mfcc
            if (audiodata.Length < (fingerprintingConfig.WdftSize + fingerprintingConfig.Overlap))
            {
                int lenNew = fingerprintingConfig.WdftSize + fingerprintingConfig.Overlap;
                Array.Resize<float>(ref audiodata, lenNew);
            }

            // Get fingerprint signatures using the Soundfingerprinting methods

            // Get database
            DatabaseService databaseService = DatabaseService.Instance;

            IPermutations permutations = new LocalPermutations("Soundfingerprinting\\perms.csv", ",");
            Repository repository = new Repository(permutations, databaseService, fingerprintService);

            // Image Service
            ImageService imageService = new ImageService(
                fingerprintService.SpectrumService,
                fingerprintService.WaveletService);

            // work config
            WorkUnitParameterObject param = new WorkUnitParameterObject();
            param.FingerprintingConfiguration = fingerprintingConfig;
            param.AudioSamples = audiodata;
            param.PathToAudioFile = filePath.FullName;
            param.MillisecondsToProcess = SECONDS_TO_ANALYZE * 1000;
            param.StartAtMilliseconds = 0;

            // build track
            Track track = new Track();
            track.Title = name;
            track.TrackLengthMs = (int) duration;
            track.FilePath = filePath.FullName;
            track.Id = -1; // this will be set by the insert method

            #region parse tag_info
            if (tag_info != null) {
                Dictionary<string, string> tags = new Dictionary<string, string>();

                //if (tag_info.title != string.Empty) tags.Add("title", tag_info.title);
                if (tag_info.artist != string.Empty) tags.Add("artist", tag_info.artist);
                if (tag_info.album != string.Empty) tags.Add("album", tag_info.album);
                if (tag_info.albumartist != string.Empty) tags.Add("albumartist", tag_info.albumartist);
                if (tag_info.year != string.Empty) tags.Add("year", tag_info.year);
                if (tag_info.comment != string.Empty) tags.Add("comment", tag_info.comment);
                if (tag_info.genre != string.Empty) tags.Add("genre", tag_info.genre);
                if (tag_info.track != string.Empty) tags.Add("track", tag_info.track);
                if (tag_info.disc != string.Empty) tags.Add("disc", tag_info.disc);
                if (tag_info.copyright != string.Empty) tags.Add("copyright", tag_info.copyright);
                if (tag_info.encodedby != string.Empty) tags.Add("encodedby", tag_info.encodedby);
                if (tag_info.composer != string.Empty) tags.Add("composer", tag_info.composer);
                if (tag_info.publisher != string.Empty) tags.Add("publisher", tag_info.publisher);
                if (tag_info.lyricist != string.Empty) tags.Add("lyricist", tag_info.lyricist);
                if (tag_info.remixer != string.Empty) tags.Add("remixer", tag_info.remixer);
                if (tag_info.producer != string.Empty) tags.Add("producer", tag_info.producer);
                if (tag_info.bpm != string.Empty) tags.Add("bpm", tag_info.bpm);
                //if (tag_info.filename != string.Empty) tags.Add("filename", tag_info.filename);
                tags.Add("channelinfo", tag_info.channelinfo.ToString());
                //if (tag_info.duration > 0) tags.Add("duration", tag_info.duration.ToString());
                if (tag_info.bitrate > 0) tags.Add("bitrate", tag_info.bitrate.ToString());
                if (tag_info.replaygain_track_gain != -100f) tags.Add("replaygain_track_gain", tag_info.replaygain_track_gain.ToString());
                if (tag_info.replaygain_track_peak != -1f) tags.Add("replaygain_track_peak", tag_info.replaygain_track_peak.ToString());
                if (tag_info.conductor != string.Empty) tags.Add("conductor", tag_info.conductor);
                if (tag_info.grouping != string.Empty) tags.Add("grouping", tag_info.grouping);
                if (tag_info.mood != string.Empty) tags.Add("mood", tag_info.mood);
                if (tag_info.rating != string.Empty) tags.Add("rating", tag_info.rating);
                if (tag_info.isrc != string.Empty) tags.Add("isrc", tag_info.isrc);

                foreach(var nativeTag in tag_info.NativeTags) {
                    string[] keyvalue = nativeTag.Split('=');
                    tags.Add(keyvalue[0], keyvalue[1]);
                }
                track.Tags = tags;
            }
            #endregion

            AudioFeature audioFeature = null;
            double[][] logSpectrogram;
            if (repository.InsertTrackInDatabaseUsingSamples(track, 25, 4, param, out logSpectrogram)) {

                if (doOutputDebugInfo) {
                    imageService.GetLogSpectralImages(logSpectrogram, fingerprintingConfig.Stride, fingerprintingConfig.FingerprintLength, fingerprintingConfig.Overlap, 2).Save(name + "_specgram_logimages.png");

                    Comirva.Audio.Util.Maths.Matrix logSpectrogramMatrix = new Comirva.Audio.Util.Maths.Matrix(logSpectrogram);
                    logSpectrogramMatrix = logSpectrogramMatrix.Transpose();
                    logSpectrogramMatrix.DrawMatrixImageLogValues(name + "_specgram_logimage.png", true);

                    if (DEBUG_OUTPUT_TEXT) {
                        logSpectrogramMatrix.WriteCSV(name + "_specgram_log.csv", ";");
                    }
                }

                audioFeature = new DummyAudioFeature();

                // Store duration
                audioFeature.Duration = (long) duration;

                // Store file name
                audioFeature.Name = filePath.FullName;
            } else {
                // failed
            }

            Dbg.WriteLine ("Soundfingerprinting - Total Execution Time: {0} ms", t.Stop().TotalMilliseconds);
            return audioFeature;
        }
コード例 #18
0
ファイル: Analyzer.cs プロジェクト: nguyendauit/FindSimilar
        private static bool AnalyseAndAddScmsUsingFingerprints(List<bool[]> fingerprints,
		                                                       WorkUnitParameterObject param,
		                                                       Db db,
		                                                       int trackId,
		                                                       bool doOutputDebugInfo=DEFAULT_DEBUG_INFO)
        {
            DbgTimer t = new DbgTimer();
            t.Start ();

            // Insert Statistical Cluster Model Similarity Audio Feature
            string fileName = param.FileName;

            int fingerprintWidth = param.FingerprintingConfiguration.FingerprintLength;
            int fingerprintHeight = param.FingerprintingConfiguration.LogBins;
            int fingerprintCount = 0;

            foreach (bool[] fingerprint in fingerprints) {
                fingerprintCount++;
                Comirva.Audio.Util.Maths.Matrix scmsMatrix = new Comirva.Audio.Util.Maths.Matrix(fingerprintWidth, fingerprintHeight);

                for (int i = 0; i < fingerprintWidth /*128*/; i++) {
                    for (int j = 0; j < fingerprintHeight /*32*/; j++) {
                        // Negative Numbers = 01
                        // Positive Numbers = 10
                        // Zeros            = 00
                        bool v1 = fingerprint[(2 * fingerprintHeight * i) + (2 * j)];
                        bool v2 = fingerprint[(2 * fingerprintHeight * i) + (2 * j) + 1];

                        if (v1) {
                            scmsMatrix.MatrixData[i][j] = 2.0;
                        } else if (v2) {
                            scmsMatrix.MatrixData[i][j] = 0.0;
                        } else {
                            scmsMatrix.MatrixData[i][j] = 1.0;
                        }
                    }
                }

                if (doOutputDebugInfo) {
                    scmsMatrix.DrawMatrixImage(String.Format("{0}_fingerprint_{1}.png", fileName, fingerprintCount), fingerprintWidth, fingerprintHeight);
                }

                #region Store in a Statistical Cluster Model Similarity class.
                Scms audioFeature = Scms.GetScmsNoInverse(scmsMatrix, fileName);

                if (audioFeature != null) {

                    // Store bitstring hash as well
                    audioFeature.BitString = GetBitString(fingerprint);

                    // Store duration
                    audioFeature.Duration = (long) param.DurationInMs;

                    // Store file name
                    audioFeature.Name = param.PathToAudioFile;

                    // Add to database
                    int id = trackId;
                    if (db.AddTrack(audioFeature) == -1) {
                        Console.Out.WriteLine("Failed! Could not add audio feature to database ({0})!", fileName);
                        return false;
                    }
                } else {
                    return false;
                }
                #endregion
            }

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