コード例 #1
0
        public float[][] CreateSpectrogram(AudioSamples audioSamples, int overlap, int wdftSize)
        {
            float[] window = new DefaultSpectrogramConfig().Window.GetWindow(wdftSize);
            float[] samples = audioSamples.Samples;
            int width = (samples.Length - wdftSize) / overlap;
            float[][] frames = new float[width][];
            for (int i = 0; i < width; i++)
            {
                float[] complexSignal = fftService.FFTForward(samples, i * overlap, wdftSize, window);
                float[] band = new float[(wdftSize / 2) + 1];
                for (int j = 0; j < (wdftSize / 2) + 1; j++)
                {
                    double re = complexSignal[2 * j];
                    double img = complexSignal[(2 * j) + 1];

                    re /= (float)wdftSize / 2;
                    img /= (float)wdftSize / 2;

                    band[j] = (float)((re * re) + (img * img));
                }

                frames[i] = band;
            }

            return frames;
        }
コード例 #2
0
        public void SubFingerprintsAreBuiltCorrectlyFromAudioSamplesForTrack()
        {
            const int TenSeconds = 10;
            var samples = new AudioSamples { Samples = TestUtilities.GenerateRandomFloatArray(SampleRate * TenSeconds) };
            const int ThreeFingerprints = 3;
            var rawFingerprints = GetGenericFingerprints(ThreeFingerprints);
            fingerprintService.Setup(service => service.CreateFingerprints(samples, It.IsAny<DefaultFingerprintConfiguration>())).Returns(rawFingerprints);
            lshAlgorithm.Setup(service => service.Hash(It.IsAny<Fingerprint>(), NumberOfHashTables, NumberOfHashKeysPerTable, It.IsAny<IEnumerable<string>>())).Returns(new HashedFingerprint(GenericSignature(), GenericHashBuckets(), 0, 0, Enumerable.Empty<string>()));

            var hashDatas = fingerprintCommandBuilder.BuildFingerprintCommand()
                                      .From(samples)
                                      .UsingServices(audioService.Object)
                                      .Hash()
                                      .Result;

            Assert.AreEqual(ThreeFingerprints, hashDatas.Count);
            byte[] genericSignature = GenericSignature();
            long[] genericHashBuckets = GenericHashBuckets();

            foreach (var hashData in hashDatas)
            {
                CollectionAssert.AreEqual(genericSignature, hashData.SubFingerprint);
                CollectionAssert.AreEqual(genericHashBuckets, hashData.HashBins);
            }
        }
コード例 #3
0
        public void SubFingerprintsAreBuiltCorrectlyFromFileForTrack()
        {
            const int TenSeconds = 10;
            var samples = new AudioSamples { Samples = TestUtilities.GenerateRandomFloatArray(SampleRate * TenSeconds) };
            const int ThreeFingerprints = 3;
            var rawFingerprints = GetGenericFingerprints(ThreeFingerprints);
            const string PathToAudioFile = "path-to-audio-file";
            audioService.Setup(service => service.ReadMonoSamplesFromFile(PathToAudioFile, SampleRate)).Returns(samples);
            fingerprintService.Setup(
                service => service.CreateFingerprints(samples, It.IsAny<DefaultFingerprintConfiguration>())).Returns(
                    rawFingerprints);
            lshAlgorithm.Setup(service => service.Hash(It.IsAny<Fingerprint>(), NumberOfHashTables, NumberOfHashKeysPerTable)).Returns(new HashedFingerprint(GenericSignature, GenericHashBuckets, 0, 0.928));

            var hashDatas = fingerprintCommandBuilder.BuildFingerprintCommand()
                                                     .From(PathToAudioFile)
                                                     .UsingServices(audioService.Object)
                                                     .Hash()
                                                     .Result;

            Assert.AreEqual(ThreeFingerprints, hashDatas.Count);
            foreach (var hashData in hashDatas)
            {
                Assert.AreSame(GenericSignature, hashData.SubFingerprint);
            }
        }
コード例 #4
0
 private AudioSamples Copy(AudioSamples chunk)
 {
     float[] withCached = new float[tailLength + chunk.Samples.Length];
     Buffer.BlockCopy(tailBuffer, 0, withCached, 0, sizeof(float) * tailLength);
     Buffer.BlockCopy(chunk.Samples, 0, withCached, sizeof(float) * tailLength, sizeof(float) * chunk.Samples.Length);
     return(new AudioSamples(withCached, chunk.Origin, chunk.SampleRate, relativeTo));
 }
コード例 #5
0
 private void NormalizeAudioIfNecessary(AudioSamples samples, FingerprintConfiguration configuration)
 {
     if (configuration.NormalizeSignal)
     {
         audioSamplesNormalizer.NormalizeInPlace(samples.Samples);
     }
 }
コード例 #6
0
        private void Cache(AudioSamples chunk)
        {
            int nextStride = Stride.NextStride;

            tailLength = tailBuffer.Length - nextStride;
            relativeTo = chunk.RelativeTo.AddSeconds((double)(chunk.Samples.Length - tailLength) / chunk.SampleRate);
            Buffer.BlockCopy(chunk.Samples, sizeof(float) * (chunk.Samples.Length - tailLength), tailBuffer, 0, sizeof(float) * tailLength);
        }
コード例 #7
0
        private void Cache(AudioSamples chunk)
        {
            int nextStride = Stride.NextStride;

            left       = chunk.Samples.Length - nextStride;
            relativeTo = chunk.RelativeTo.AddSeconds((double)(nextStride) / chunk.SampleRate);
            Buffer.BlockCopy(chunk.Samples, sizeof(float) * (nextStride), buffer, 0, sizeof(float) * left);
        }
コード例 #8
0
        public List<SpectralImage> CreateLogSpectrogram(AudioSamples audioSamples,  SpectrogramConfig configuration)
        {
            int width = (audioSamples.Samples.Length - configuration.WdftSize) / configuration.Overlap;
            if (width < 1)
            {
                return new List<SpectralImage>();
            }

            float[][] frames = new float[width][];
            int[] logFrequenciesIndexes = logUtility.GenerateLogFrequenciesRanges(audioSamples.SampleRate, configuration);
            float[] window = configuration.Window.GetWindow(configuration.WdftSize);
            Parallel.For(0, width, i => {
                float[] complexSignal = fftService.FFTForward(audioSamples.Samples, i * configuration.Overlap, configuration.WdftSize, window);
                frames[i] = ExtractLogBins(complexSignal, logFrequenciesIndexes, configuration.LogBins, configuration.WdftSize);
            });

            return CutLogarithmizedSpectrum(frames, audioSamples.SampleRate, configuration);
        }
コード例 #9
0
        public void FingerprintsAreBuiltCorrectlyFromFile()
        {
            const string PathToAudioFile = "path-to-audio-file";
            const int TenSeconds = 10;
            var samples = new AudioSamples { Samples = TestUtilities.GenerateRandomFloatArray(SampleRate * TenSeconds) };
            const int ThreeFingerprints = 3;
            var rawFingerprints = GetGenericFingerprints(ThreeFingerprints);
            audioService.Setup(service => service.ReadMonoSamplesFromFile(PathToAudioFile, SampleRate)).Returns(samples);
            fingerprintService.Setup(service => service.CreateFingerprints(samples, It.IsAny<DefaultFingerprintConfiguration>())).Returns(rawFingerprints);

            var fingerprints = ((FingerprintCommand)fingerprintCommandBuilder.BuildFingerprintCommand()
                                  .From(PathToAudioFile)
                                  .UsingServices(audioService.Object))
                                  .Fingerprint()
                                  .Result;

            Assert.AreEqual(ThreeFingerprints, fingerprints.Count);
            Assert.AreSame(rawFingerprints, fingerprints);
        }
コード例 #10
0
        public AudioSamples Aggregate(AudioSamples chunk)
        {
            if (chunk.Samples.Length < MinSize)
            {
                throw new ArgumentException($"{nameof(chunk)} cannot be less than {MinSize}");
            }

            inc++;
            if (inc == 0)
            {
                Cache(chunk);
                return(chunk);
            }

            var cached = Copy(chunk);

            Cache(chunk);
            return(cached);
        }
コード例 #11
0
        public void SubFingerprintsAreBuiltCorrectlyFromFileForTrackStartingAtSpecificSecond()
        {
            const string PathToAudioFile = "path-to-audio-file";
            const int StartSecond = 10;
            const int SecondsToProcess = 20;
            AudioSamples samples = new AudioSamples
                { Samples = TestUtilities.GenerateRandomFloatArray(SampleRate * 10) };
            const int ThreeFingerprints = 3;
            var rawFingerprints = GetGenericFingerprints(ThreeFingerprints);

            audioService.Setup(service => service.ReadMonoSamplesFromFile(PathToAudioFile, SampleRate, SecondsToProcess, StartSecond)).Returns(samples);
            fingerprintService.Setup(service => service.CreateFingerprints(samples, It.IsAny<DefaultFingerprintConfiguration>())).Returns(rawFingerprints);
            byte[] genericSignature = GenericSignature();
            lshAlgorithm.Setup(service => service.Hash(It.IsAny<Fingerprint>(), NumberOfHashTables, NumberOfHashKeysPerTable, It.IsAny<IEnumerable<string>>())).Returns(
                new HashedFingerprint(genericSignature, GenericHashBuckets(), 0, 0, Enumerable.Empty<string>()));

            var hashDatas = fingerprintCommandBuilder.BuildFingerprintCommand()
                                      .From(PathToAudioFile, SecondsToProcess, StartSecond)
                                      .UsingServices(audioService.Object)
                                      .Hash()
                                      .Result;

            Assert.AreEqual(ThreeFingerprints, hashDatas.Count);
            foreach (var hashData in hashDatas)
            {
                CollectionAssert.AreEqual(genericSignature, hashData.SubFingerprint);
            }

            audioService.Verify(service => service.ReadMonoSamplesFromFile(PathToAudioFile, SampleRate, SecondsToProcess, StartSecond));
        }
コード例 #12
0
 public List<Fingerprint> CreateFingerprints(AudioSamples samples, FingerprintConfiguration configuration)
 {
     NormalizeAudioIfNecessary(samples, configuration);
     var spectrum = spectrumService.CreateLogSpectrogram(samples, configuration.SpectrogramConfig);
     return CreateFingerprintsFromLogSpectrum(spectrum, configuration);
 }
コード例 #13
0
 public IWithFingerprintConfiguration From(AudioSamples audioSamples)
 {
     createFingerprintsMethod = () => fingerprintService.CreateFingerprints(audioSamples, FingerprintConfiguration);
     return this;
 }
コード例 #14
0
 public IWithQueryAndFingerprintConfiguration From(AudioSamples audioSamples)
 {
     fingerprintingMethodFromSelector = () => fingerprintCommandBuilder.BuildFingerprintCommand().From(audioSamples);
     return this;
 }
コード例 #15
0
 private void SetupFftService(DefaultSpectrogramConfig configuration, AudioSamples samples)
 {
     logUtility.Setup(utility => utility.GenerateLogFrequenciesRanges(SampleRate, configuration))
         .Returns(new[]
                 {
                     118, 125, 133, 141, 149, 158, 167, 177, 187, 198, 210, 223, 236, 250, 264, 280, 297, 314,
                     333, 352, 373, 395, 419, 443, 470, 497, 527, 558, 591, 626, 663, 702, 744,
                 });
     fftService.Setup(service => service.FFTForward(samples.Samples, It.IsAny<int>(), configuration.WdftSize, It.IsAny<float[]>()))
         .Returns(TestUtilities.GenerateRandomFloatArray(2048));
 }