/// <summary>
        /// Arrange candidates according to the corresponding calculation between initial signature and actual signature
        /// </summary>
        /// <param name="f">Actual signature gathered from the song</param>
        /// <param name="potentialCandidates">Potential fingerprints returned from the database</param>
        /// <param name="lHashTables">Number of L Hash tables</param>
        /// <param name="kKeys">Number of keys per table</param>
        /// <param name="trackIdQueryStats">Result set</param>
        /// <returns>Result set</returns>
        private static Dictionary <Int32, QueryStats> ArrangeCandidatesAccordingToFingerprints(bool[] f, Dictionary <Fingerprint, int> potentialCandidates,
                                                                                               int lHashTables, int kKeys, Dictionary <Int32, QueryStats> trackIdQueryStats)
        {
            // Most time consuming method while performing the necessary calculation
            foreach (KeyValuePair <Fingerprint, int> pair in potentialCandidates)
            {
                Fingerprint fingerprint = pair.Key;
                int         tableVotes  = pair.Value;

                // Compute Hamming Distance of actual and read signature
                int    hammingDistance = MinHash.CalculateHammingDistance(f, fingerprint.Signature) * tableVotes;
                double jaqSimilarity   = MinHash.CalculateJaqSimilarity(f, fingerprint.Signature);

                // Add to sample set
                Int32 trackId = fingerprint.TrackId;
                if (!trackIdQueryStats.ContainsKey(trackId))
                {
                    trackIdQueryStats.Add(trackId, new QueryStats(0, 0, 0, -1, -1, 0, Int32.MinValue, 0, Int32.MaxValue, Int32.MinValue, Int32.MinValue, Double.MaxValue));
                }

                QueryStats stats = trackIdQueryStats[trackId];
                stats.HammingDistance += hammingDistance;                       // Sum hamming distance of each potential candidate
                stats.NumberOfTrackIdOccurences++;                              // Increment occurrence count
                stats.NumberOfTotalTableVotes += tableVotes;                    // Find total table votes
                stats.HammingDistanceByTrack  += hammingDistance / tableVotes;  // Find hamming distance by track id occurrence
                if (stats.MinHammingDistance > hammingDistance / tableVotes)    // Find minimal hamming distance over the entire set
                {
                    stats.MinHammingDistance = hammingDistance / tableVotes;
                }
                if (stats.MaxTableVote < tableVotes)                 // Find maximal table vote
                {
                    stats.MaxTableVote = tableVotes;
                }
                if (stats.Similarity > jaqSimilarity)
                {
                    stats.Similarity = jaqSimilarity;
                }
            }
            return(trackIdQueryStats);
        }
        public CompareAudioForm()
        {
            //
            // The InitializeComponent() call is required for Windows Forms designer support.
            //
            InitializeComponent();

            //
            // TODO: Add constructor code after the InitializeComponent() call.
            //

            // Instansiate Soundfingerprinting Repository
            FingerprintService fingerprintService = Analyzer.GetSoundfingerprintingService();

            this.databaseService = DatabaseService.Instance;

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

            IFingerprintingConfiguration fingerprintingConfigCreation = new FullFrequencyFingerprintingConfiguration();

            repository = new Repository(permutations, databaseService, fingerprintService);
            ImageService imageService = new ImageService(fingerprintService.SpectrumService, fingerprintService.WaveletService);

            FileInfo filePathAudio1 = new FileInfo(@"C:\Users\perivar.nerseth\Music\Test Samples Database\VDUB1 Snare 004.wav");
            FileInfo filePathAudio2 = new FileInfo(@"C:\Users\perivar.nerseth\Music\Test Samples Search\VDUB1 Snare 004 - Start.wav");

            int fingerprintsPerRow = 2;

            double[][]    logSpectrogram1 = null;
            double[][]    logSpectrogram2 = null;
            List <bool[]> fingerprints1   = null;
            List <bool[]> fingerprints2   = null;

            WorkUnitParameterObject file1Param = Analyzer.GetWorkUnitParameterObjectFromAudioFile(filePathAudio1);

            if (file1Param != null)
            {
                file1Param.FingerprintingConfiguration = fingerprintingConfigCreation;

                // Get fingerprints
                fingerprints1 = fingerprintService.CreateFingerprintsFromAudioSamples(file1Param.AudioSamples, file1Param, out logSpectrogram1);

                pictureBox1.Image = imageService.GetSpectrogramImage(logSpectrogram1, logSpectrogram1.Length, logSpectrogram1[0].Length);
                pictureBoxWithInterpolationMode1.Image = imageService.GetImageForFingerprints(fingerprints1, file1Param.FingerprintingConfiguration.FingerprintLength, file1Param.FingerprintingConfiguration.LogBins, fingerprintsPerRow);
            }

            WorkUnitParameterObject file2Param = Analyzer.GetWorkUnitParameterObjectFromAudioFile(filePathAudio2);

            if (file2Param != null)
            {
                file2Param.FingerprintingConfiguration = fingerprintingConfigCreation;

                // Get fingerprints
                fingerprints2 = fingerprintService.CreateFingerprintsFromAudioSamples(file2Param.AudioSamples, file2Param, out logSpectrogram2);

                pictureBox2.Image = imageService.GetSpectrogramImage(logSpectrogram2, logSpectrogram2.Length, logSpectrogram2[0].Length);
                pictureBoxWithInterpolationMode2.Image = imageService.GetImageForFingerprints(fingerprints2, file2Param.FingerprintingConfiguration.FingerprintLength, file2Param.FingerprintingConfiguration.LogBins, fingerprintsPerRow);
            }


            MinHash minHash = repository.MinHash;

            // only use the first signatures
            bool[] signature1 = fingerprints1[0];
            bool[] signature2 = fingerprints2[0];

            if (signature1 != null && signature2 != null)
            {
                int    hammingDistance = MinHash.CalculateHammingDistance(signature1, signature2);
                double jaqSimilarity   = MinHash.CalculateJaqSimilarity(signature1, signature2);

                lblSimilarity.Text = String.Format("Hamming: {0} JAQ: {1}", hammingDistance, jaqSimilarity);
            }
        }