Example #1
0
        private AcoustID.FingerprintAcoustID MakeAcoustIDFinger(string key, string filename)
        {
            // resample to 11025Hz
            IAudioDecoder decoder = new BassDecoder();

            try
            {
                decoder.Load(filename);

                ChromaContext context = new ChromaContext();

                context.Start(decoder.SampleRate, decoder.Channels);
                decoder.Decode(context.Consumer, 120);
                if (context.Finish())
                {
                    FingerprintAcoustID fingerprint = new FingerprintAcoustID();
                    fingerprint.Reference      = key;
                    fingerprint.DurationInMS   = (long)decoder.Duration * 1000;
                    fingerprint.SignatureInt32 = context.GetRawFingerprint();

                    return(fingerprint);
                }
            }
            catch (Exception e)
            {
                // Probleem waarschijnlijk met file.
                Console.Error.WriteLine(e.ToString());
            }
            finally
            {
                decoder.Dispose();
            }

            return(null);
        }
Example #2
0
        public void RunAcoustIDTest()
        {
            Console.WriteLine("AcoustID test.");
            if (!System.IO.Directory.Exists(acoustIDfingerLookupPath))
            {
                Console.WriteLine("AcoustID path not found.");
                return;
            }

            Console.WriteLine("Opening index. With larges indexes this can take a while.");
            IndexSearcher indexSubFinger = new IndexSearcher(IndexReader.Open(FSDirectory.Open(new System.IO.DirectoryInfo(acoustIDfingerLookupPath)), true));

            indexSubFinger.Similarity = new CDR.Indexer.SimilarityNoPriority();
            Console.WriteLine("Ready opening index.");

            AcoustIDQuery       query   = new AcoustIDQuery(indexSubFinger);
            FingerprintAcoustID fsQuery = null;
            Resultset           answer  = null;

            fsQuery = query.MakeAcoustIDFingerFromAudio(@"..\..\..\Audio\Samples\JK147510-0002-64kpbs.mp3");
            answer  = query.MatchAudioFingerprint(fsQuery);
            if (!retrieveMetadataFromMuziekweb)
            {
                ThrowIfInvalidAnswer(answer, "A5D062DE");
            }
            PrintAnswer(answer);
            Console.WriteLine();
        }
Example #3
0
 public FingerprintHit(FingerprintAcoustID fingerprint, float score, int indexNumberInMatchList, int fingerCountHitInFingerprint)
 {
     this.Fingerprint                 = fingerprint;
     this.Score                       = score;
     this.IndexNumberInMatchList      = indexNumberInMatchList;
     this.FingerCountHitInFingerprint = fingerCountHitInFingerprint;
 }
Example #4
0
        public Resultset MatchAudioFingerprint(FingerprintAcoustID fsQuery)
        {
            DateTime startTime = DateTime.Now;

            BooleanQuery.MaxClauseCount = 600000;
            Resultset result = new Resultset();

            result.Algorithm = FingerprintAlgorithm.AcoustIDFingerprint;

            int[] query = fsQuery.AcoustID_Extract_Query;
            if (query.Length <= 0)
            {
                goto exitFunc;
            }

            // Vuurt nu query af op lucene index
            DateTime dtStart = DateTime.Now;
            TopDocs  topHits = QuerySubAcoustIDFingers(query);

            int[] titelnummertrackIDs = LuceneTopDocs2TitelnummertrackIDs(topHits);
            result.FingerQueryTime = (DateTime.Now - dtStart);

            if (titelnummertrackIDs.Length == 0)
            {
                goto exitFunc;
            }

            dtStart = DateTime.Now;
            List <FingerprintAcoustID> fingerprints = GetFingerprintsMySQL(titelnummertrackIDs);

            result.FingerLoadTime = (DateTime.Now - dtStart);

            dtStart = DateTime.Now;
            ConcurrentDictionary <string, FingerprintHit> hits = FindPossibleMatch(fsQuery, fingerprints);

            result.MatchTime = (DateTime.Now - dtStart);

            // Geef resultaat terug
            List <ResultEntry> resultEntries = hits.OrderByDescending(e => e.Value.Score)
                                               .Select(e => new ResultEntry
            {
                Reference  = e.Value.Fingerprint.Reference,
                Similarity = Convert.ToInt32(e.Value.Score * 100),    // acoustic id math from 0 to 100%
                // Dummy settings
                TimeIndex = -1,                                       // match is on complete track (or al least first 120 seconds!)
                IndexNumberInMatchList         = e.Value.IndexNumberInMatchList,
                SubFingerCountHitInFingerprint = 0,
                SearchStrategy  = SearchStrategy.NotSet,
                SearchIteration = 0
            })
                                               .ToList();

            result.ResultEntries = resultEntries;
exitFunc:
            result.QueryTime = (DateTime.Now - startTime);
            return(result);
        }
Example #5
0
        private List <FingerprintAcoustID> GetFingerprintsMySQL(int[] fingerIDList)
        {
            DateTime startTime = DateTime.Now;

            System.Collections.Concurrent.ConcurrentBag <FingerprintAcoustID> fingerBag = new System.Collections.Concurrent.ConcurrentBag <FingerprintAcoustID>();

            using (MySql.Data.MySqlClient.MySqlConnection conn = CDR.DB_Helper.NewMySQLConnection())
            {
                StringBuilder sb = new StringBuilder(1024);
                sb.Append("SELECT *\r\n");
                sb.Append("FROM   FINGERID AS T1,\r\n");
                sb.Append("       TITELNUMMERTRACK_ID AS T2\r\n");
                sb.Append("WHERE  T1.TITELNUMMERTRACK_ID = T2.TITELNUMMERTRACK_ID\r\n");
                sb.Append("AND    T2.TITELNUMMERTRACK_ID IN (\r\n");

                int count = 0;
                System.Collections.Hashtable hTable = new System.Collections.Hashtable(fingerIDList.Length);
                foreach (int id in fingerIDList)
                {
                    if (count > 0)
                    {
                        sb.Append(',');
                    }
                    sb.Append(id.ToString());
                    hTable.Add(id, count);
                    count++;
                }
                sb.Append(')');

                MySql.Data.MySqlClient.MySqlCommand command = new MySql.Data.MySqlClient.MySqlCommand(sb.ToString(), conn);
                command.CommandTimeout = 60;

                MySql.Data.MySqlClient.MySqlDataAdapter adapter = new MySql.Data.MySqlClient.MySqlDataAdapter(command);
                System.Data.DataSet ds = new System.Data.DataSet();
                adapter.Fill(ds);
                if (ds.Tables.Count > 0)
                {
                    foreach (System.Data.DataRow row in ds.Tables[0].Rows)
                    {
                        FingerprintAcoustID fs = new FingerprintAcoustID();
                        fs.Reference    = row["TITELNUMMERTRACK"].ToString();
                        fs.Signature    = (byte[])row["SIGNATURE"];
                        fs.DurationInMS = Convert.ToInt64(row["DURATIONINMS"]);

                        int titelnummertrackID = Convert.ToInt32(row["TITELNUMMERTRACK_ID"]);
                        fs.Tag = hTable[titelnummertrackID];

                        fingerBag.Add(fs);
                    }
                }
            }

            List <FingerprintAcoustID> result = fingerBag.OrderBy(e => (int)e.Tag)
                                                .ToList();

            return(result);
        }
Example #6
0
        public void ScanDirectoryAndFingerprint(string directory)
        {
            // Expand directory to full directory path.
            // We needed to remove filename part because GetFullPath doesn't suppport wildcards
            string wildcard = Path.GetFileName(directory);

            directory = Path.GetDirectoryName(directory);
            directory = Path.GetFullPath(directory);
            directory = Path.Combine(directory, wildcard);

            foreach (string f in Directory.GetFiles(Path.GetDirectoryName(directory), Path.GetFileName(directory)))
            {
                Console.WriteLine(Path.GetFileName(f));

                // For best result you should return the same key for the same file. Muziekweb.nl uses an cataloguenumber (some chars and a number, 7 or 8 char long in total)
                // then we added the track number. (Fieldname: TITELNUMMERTRACK)
                string referenceKey = GenerateCRC32Key(f);


                FingerprintAcoustID  fingerprint    = MakeAcoustIDFinger(referenceKey, f);
                FingerprintSignature subFingerprint = MakeSubFingerID(referenceKey, f);

                // Fill with some subdata
                if (subFingerprint != null && fingerprint != null)
                {
                    // AcoustID
                    fingerprint.AudioSource       = Path.GetExtension(f).Replace(".", "").ToUpper();
                    fingerprint.Lokatie           = f;             // Path.GetDirectoryName(f);
                    fingerprint.DateRelease       = DateTime.Now.Date;
                    fingerprint.CatalogusCode     = "POPULAIR";    // POPULAIR or CLASSICAL
                    fingerprint.UniformeTitleLink = "";            // used in muziekweb.nl database to find the same track on different albums
                                                                   // Subfinger
                    subFingerprint.AudioSource       = Path.GetExtension(f).Replace(".", "").ToUpper();
                    subFingerprint.Lokatie           = f;          // Path.GetDirectoryName(f);
                    subFingerprint.DateRelease       = DateTime.Now.Date;
                    subFingerprint.CatalogusCode     = "POPULAIR"; // POPULAIR or CLASSICAL
                    subFingerprint.UniformeTitleLink = "";         // used in muziekweb.nl database to find the same track on different albums
                }

                // Store the data in de MySQL Database, this will later be used to create an inverted index using lucene.
                int titelnummertrackID;
                Exec_MySQL_SUBFINGERID_IU(subFingerprint.Reference.ToString(), subFingerprint.CatalogusCode, subFingerprint.DateRelease,
                                          subFingerprint.UniformeTitleLink, subFingerprint.AudioSource, subFingerprint.Lokatie, subFingerprint.DurationInMS, subFingerprint.Signature, out titelnummertrackID);
                Exec_MySQL_FINGERID_IU(fingerprint.Reference.ToString(), fingerprint.CatalogusCode, fingerprint.DateRelease,
                                       fingerprint.UniformeTitleLink, fingerprint.AudioSource, fingerprint.Lokatie, fingerprint.DurationInMS, fingerprint.Signature, out titelnummertrackID);
            } //foreach
        }
Example #7
0
        private ConcurrentDictionary <string, FingerprintHit> FindPossibleMatch(FingerprintAcoustID fsQuery, List <FingerprintAcoustID> fingerprints)
        {
            DateTime starttime = DateTime.Now;
            ConcurrentDictionary <string, FingerprintHit> possibleHits = new ConcurrentDictionary <string, FingerprintHit>();

            int indexNumberInMatchList = 0;

            int[] fsQueryInts = fsQuery.SignatureInt32;
            foreach (FingerprintAcoustID fsMatch in fingerprints)
            {
                indexNumberInMatchList++;

                // ---------------------------------------------------------------
                // Tel aantal hits dat we vonden
                int fingerCountHitInFingerprint = 0;
                foreach (int hash in fsQueryInts)
                {
                    if (fsMatch.IndexOf(hash).Length > 0)
                    {
                        fingerCountHitInFingerprint++;
                    }
                } //foreach
                  // ---------------------------------------------------------------

                float score = FingerprintAcoustID.MatchFingerprint(fsMatch, fsQuery, 0);
                if (score >= 0.60f) // 0.60 zoals ik terugvond levert te slechte resultaten op (engelse en nederlandse versie zijn dan hetzelfde)
                {
                    if (System.Math.Abs(100 - ((fsMatch.DurationInMS * 100) / fsQuery.DurationInMS)) < 15)
                    {
                        possibleHits.TryAdd(fsMatch.Reference.ToString(), new FingerprintHit(fsMatch, score, indexNumberInMatchList, fingerCountHitInFingerprint));
                    }
                }
            }

            return(possibleHits);
        }
Example #8
0
        public bool CreateAcoustIDFingerLookupIndex(string luceneIndexPath)
        {
            DateTime startTime = DateTime.Now;
            DateTime endTime   = startTime;

            Console.WriteLine("Creating acoustID Finger index");

            int minID;
            int maxID;

            if (!Exec_MySQL_MinAndMax_IDS(out minID, out maxID) && minID >= 1)
            {
                return(false);
            }

            if (!System.IO.Directory.Exists(luceneIndexPath))
            {
                System.IO.Directory.CreateDirectory(luceneIndexPath);
            }
            ClearFolder(luceneIndexPath);


            int fingerCount = 0;

            Lucene.Net.Store.Directory directory = FSDirectory.Open(new System.IO.DirectoryInfo(luceneIndexPath));
            IndexWriter iw = null;

            try
            {
                iw = new IndexWriter(directory, new StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_30), true, IndexWriter.MaxFieldLength.UNLIMITED);
                iw.UseCompoundFile = false;
                iw.SetSimilarity(new CDR.Indexer.DefaultSimilarityExtended());
                iw.MergeFactor = 10;                                          // default = 10
                iw.SetRAMBufferSizeMB(512 * 3);                               // use memory to do a flush
                iw.SetMaxBufferedDocs(IndexWriter.DISABLE_AUTO_FLUSH);        // only use memory as trigger to do a flush
                iw.SetMaxBufferedDeleteTerms(IndexWriter.DISABLE_AUTO_FLUSH); // only use memory as trigger to do a flush

                Document doc = new Document();
                doc.Add(new Field("TITELNUMMERTRACK_ID", "", Field.Store.YES, Field.Index.NOT_ANALYZED));
                doc.Add(new Field("FINGERID", "", Field.Store.NO, Field.Index.ANALYZED));

                Field fTitelnummertrackID = doc.GetField("TITELNUMMERTRACK_ID");
                fTitelnummertrackID.OmitNorms = true;
                fTitelnummertrackID.OmitTermFreqAndPositions = true;

                Field fFingerID = doc.GetField("FINGERID");
                fFingerID.OmitNorms = true;
                fFingerID.OmitTermFreqAndPositions = true;

                StringBuilder sb    = new StringBuilder(256 * 1024);
                int           start = minID;
                int           count = 5000;
                while (start <= maxID)
                {
                    DataTable dt;
                    if (Exec_MySQL_LOADFINGERIDS(start, (start + count - 1), out dt))
                    {
                        foreach (DataRow row in dt.Rows)
                        {
                            fingerCount++;
                            if ((fingerCount % 100) == 0 || fingerCount <= 1)
                            {
                                Console.Write("\rIndexing fingerprint #" + fingerCount.ToString());
                            }

                            FingerprintAcoustID fingerprint = new FingerprintAcoustID();
                            fingerprint.Signature = (byte[])row["SIGNATURE"];

                            // Bij AcoustiID halen we vanaf positie 80 (int32 gerekend) 120 (360 nu) int lang eruit. We bepalen de 28 belangrijkste bits
                            // en slaan deze getallen vervolgens op.
                            // Dit kan omdat we een fingerprint hebben van de gehele song (eigenlijk eerste 120 seconden) en die ook gaan vergelijken met
                            // een fingerprint die aan dezelfde voorwaarde voldoet.
                            sb.Clear();
                            List <int> query = new List <int>();
                            foreach (int subFingerValue in fingerprint.AcoustID_Extract_Query)
                            {
                                // deduplicate
                                if (query.Contains(subFingerValue))
                                {
                                    continue;
                                }
                                query.Add(subFingerValue);
                                sb.Append(subFingerValue.ToString());
                                sb.Append(' ');
                            }

                            fTitelnummertrackID.SetValue(row["TITELNUMMERTRACK_ID"].ToString());
                            fFingerID.SetValue(sb.ToString());

                            iw.AddDocument(doc);
                        } //foreach
                        Console.Write("\rIndexing fingerprint #" + fingerCount.ToString());
                        start += count;
                    }
                    else
                    {
                        if (!RetryDatabaseError())
                        {
                            return(false);
                        }
                    }
                } //while
            }
            finally
            {
                Console.WriteLine();
                Console.WriteLine("Optimizing.");
                if (iw != null)
                {
                    // Optimaliseer de index nu
                    iw.Commit();
                    iw.Optimize(1, true);
                    iw.Dispose();
                    iw = null;
                    GC.WaitForPendingFinalizers();
                }
            }

            endTime = DateTime.Now;
            TimeSpan ts = (endTime - startTime);

            Console.WriteLine(String.Format("Elapsed index time {0:00}:{1:00}:{2:00}.{3:000}", ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds));
            Console.WriteLine();

            return(true);
        }