コード例 #1
0
    private void FFTWindowChange(Complex[] channelData, FFTWindow window)
    {
        switch (window)
        {
        case FFTWindow.HannWindow:
            for (int i = 0; i < channelData.Length; i++)
            {
                channelData[i].X = (float)(channelData[i].X * FastFourierTransform.HannWindow(i, bufferSize));
            }
            break;

        case FFTWindow.HammingWindow:
            for (int i = 0; i < channelData.Length; i++)
            {
                channelData[i].X = (float)(channelData[i].X * FastFourierTransform.HammingWindow(i, bufferSize));
            }
            break;

        case FFTWindow.BlackmannHarrisWindow:
            for (int i = 0; i < channelData.Length; i++)
            {
                channelData[i].X = (float)(channelData[i].X * FastFourierTransform.BlackmannHarrisWindow(i, bufferSize));
            }
            break;
        }
        FastFourierTransform.FFT(false, binaryExponentitation, channelData);
    }
コード例 #2
0
    private void DataAvailable(object sender, WaveInEventArgs e)
    {
        // Convert byte[] to float[].
        float[] data = ConvertByteToFloat(e.Buffer, e.BytesRecorded);

        // For all data. Skip right channel on stereo (i += this.Format.Channels).
        for (int i = 0; i < data.Length; i += this.Format.Channels)
        {
            this._fftBuffer[_fftPos].X = (float)(data[i] * FastFourierTransform.HannWindow(_fftPos, _fftLength));
            this._fftBuffer[_fftPos].Y = 0;
            this._fftPos++;

            if (this._fftPos >= this._fftLength)
            {
                this._fftPos = 0;

                // NAudio FFT implementation.
                FastFourierTransform.FFT(true, this._m, this._fftBuffer);

                // Copy to buffer.
                lock (this._lock) {
                    for (int c = 0; c < this._fftLength; c++)
                    {
                        float amplitude = (float)Math.Sqrt(this._fftBuffer[c].X * this._fftBuffer[c].X + this._fftBuffer[c].Y * this._fftBuffer[c].Y);
                        this._lastFftBuffer[c] = amplitude;
                    }

                    this._fftBufferAvailable = true;
                }
            }
        }
    }
コード例 #3
0
        public IDisposable Subscribe(IObserver <float[]> obs)
        {
            var fftBuffer = new Complex[fftLength];
            var fftPos    = 0;

            return
                (source.Subscribe(wave =>
            {
                for (var i = 0; i < wave.ShortBufferCount; i++)
                {
                    var value = wave.ShortBuffer[i];
                    fftBuffer[fftPos].X = (float)(value * FastFourierTransform.HannWindow(fftPos, fftLength));
                    fftBuffer[fftPos].Y = 0;
                    fftPos++;
                    if (fftPos >= fftBuffer.Length)
                    {
                        fftPos = 0;
                        FastFourierTransform.FFT(true, m, fftBuffer);

                        var result =
                            fftBuffer
                            .Take(fftLength / 2)
                            .Select(GetDb)
                            .ToArray();
                        obs.OnNext(result);
                    }
                }
            },
                                  obs.OnError,
                                  obs.OnCompleted
                                  ));
        }
コード例 #4
0
        public static void AddSample(float value)
        {
            switch (Window)
            {
            case FFTWindow.BlackmannHarris:
                _fftBuffer[_fftPos].X = (float)(value * FastFourierTransform.BlackmannHarrisWindow(_fftPos, _fftLength));
                break;

            case FFTWindow.Hamming:
                _fftBuffer[_fftPos].X = (float)(value * FastFourierTransform.HammingWindow(_fftPos, _fftLength));
                break;

            case FFTWindow.Hann:
                _fftBuffer[_fftPos].X = (float)(value * FastFourierTransform.HannWindow(_fftPos, _fftLength));
                break;
            }
            _fftBuffer[_fftPos].Y = 0;
            _fftPos++;
            if (_fftPos >= _fftLength)
            {
                _fftPos = 0;
                FastFourierTransform.FFT(true, _m, _fftBuffer);
                FftCalculated();
            }
        }
コード例 #5
0
        public async IAsyncEnumerable <FrequencyAmplitude[]> EnumerateFrequencyAmplitudesAsync(InputOption option, [EnumeratorCancellation] CancellationToken token)
        {
            var samplesCount = Convert.ToInt32(Math.Pow(2, power));
            //var complexSamples = new Complex[samplesCount];
            var complexSamples = new Complex[samplesCount];
            //var doubleSamples = new double[samplesCount];
            var position = 0;

            await foreach (var samples in option.Owner.EnumerateSamplesAsync(option, token))
            {
                int i;
                for (i = 0; i < samples.Length; i++)
                {
                    complexSamples[position] = new Complex {
                        X = (float)(samples[i].Values[0] * FastFourierTransform.HannWindow(position, 1024)),
                        Y = 0 //Just the real part
                    };
                    //doubleSamples[position] = samples[i].Values[0];
                    position++;
                    if (position >= samplesCount)
                    {
                        FastFourierTransform.FFT(true, (int)Math.Log(samplesCount, 2.0), complexSamples);

                        //var amplitudes = complexSamples.Take(complexSamples.Length / 2).Select(
                        var j = 0;
                        var actualSamplesCount = (complexSamples.Length / 2) + 1;
                        var amplitudes         = complexSamples.Take(actualSamplesCount).Select(
                            c => new FrequencyAmplitude(
                                new Frequency(GetFrequency(j++, actualSamplesCount, option.SamplingFrequency)),
                                //new Amplitude(new float[] { Math.Abs(c.X + c.Y) })
                                //new Amplitude(new float[] { (float) Math.Log(Math.Abs(c.X + c.Y)) })
                                new Amplitude(new float[] { GetAmplitude(c) })
                                )
                            ).ToArray();

                        yield return(amplitudes);

                        position = 0;
                    }
                }

                /*while (complexSamples.Count >= samplesCount)
                 * {
                 *  Array.Copy()
                 *  FastFourierTransform.FFT(true, power, )
                 *  yield return new FrequencyAmplitude[1] { new FrequencyAmplitude(new Frequency(11), new Amplitude(new float[0])) };
                 * }*/
            }
        }
コード例 #6
0
 public void Add(float value)
 {
     if (PerformFFT && FftCalculated != null)
     {
         // Remember the window function! There are many others as well.
         fftBuffer[fftPos].X = (float)(value * FastFourierTransform.HannWindow(fftPos, fftLength));
         fftBuffer[fftPos].Y = 0; // This is always zero with audio.
         fftPos++;
         if (fftPos >= fftLength)
         {
             fftPos = 0;
             //FastFourierTransform.FFT(true, m, fftBuffer);
             FftCalculated(this, fftArgs);
         }
     }
 }
コード例 #7
0
    public void Add(float value)
    {
        if (PerformFFT && FftCalculated != null)
        {
            fftBuffer[fftPos].X = (float)(value * FastFourierTransform.HannWindow(fftPos, fftLength));

            fftBuffer[fftPos].Y = 0;
            fftPos++;
            if (fftPos >= fftLength)
            {
                fftPos = 0;
                FastFourierTransform.FFT(true, m, fftBuffer);
                FftCalculated(this, fftArgs);
            }
        }
    }
コード例 #8
0
        private void DataAvailable(object sender, WaveInEventArgs args)
        {
            var count  = args.BytesRecorded / 4; // 32-bit
            var buffer = new WaveBuffer(args.Buffer);

            for (int i = 0; i < count; ++i)
            {
                _fftBuffer[i].X = (float)(buffer.FloatBuffer[i] * FastFourierTransform.HannWindow(i, _fftLength));
                _fftBuffer[i].Y = 0;
                if (i + 1 >= _fftLength)
                {
                    FastFourierTransform.FFT(true, (int)Math.Log(this._fftLength, 2.0), _fftBuffer);
                    for (int j = 0; j < _fftLength; ++j)
                    {
                        _amplitudes[j] = (float)Math.Sqrt(Math.Pow(_fftBuffer[j].X, 2) + Math.Pow(_fftBuffer[j].Y, 2));
                    }
                    Visualizer.SetData(_amplitudes);
                    break;
                }
            }
        }
コード例 #9
0
ファイル: FFT.cs プロジェクト: tebjan/NewAudio
            private void Add(float value)
            {
                input[fftPos]   = value * FastFourierTransform.HannWindow(fftPos, fftLength);
                input2[fftPos2] = value * FastFourierTransform.HannWindow(fftPos2, fftLength);
                fftPos++;
                fftPos2++;

                if (fftPos >= fftLength || fftPos2 >= fftLength)
                {
                    var pin = pinIn;
                    if (fftPos2 >= fftLength)
                    {
                        pin     = pinIn2;
                        fftPos2 = 0;
                    }
                    else
                    {
                        fftPos = 0;
                    }


                    DFT.FFT(pin, pinOut);
                    for (int i = 1; i < fftLength / 2; i++)
                    {
                        var real = (float)pinOut[i].Real;
                        var img  = (float)pinOut[i].Imaginary;

                        var newValue = (float)(Math.Sqrt(real * real + img * img) / fftLength / (2 * 44100));
                        if (i < spreadBuilder.Count)
                        {
                            spreadBuilder[i] = newValue;
                        }
                        else
                        {
                            spreadBuilder.Add(newValue);
                        }
                    }
                    Spread = spreadBuilder.ToSpread();
                }
            }
コード例 #10
0
        /// <summary>
        /// Inits the capture:
        /// - inits the capture to listen to the current default output device
        /// - creates the listener
        /// - starts recording
        /// </summary>
        private void InitCapture()
        {
            // Takes the current default output device
            capture = new WasapiLoopbackCapture();

            // Used to get the audio spectrum using FFT
            int    fftPos = 0;
            int    m      = (int)Math.Log(fftLength, 2.0);
            object _lock  = new object();

            Complex[] fftBuffer = new Complex[fftLength]; // the data
            lastFftBuffer = new float[fftLength];         // the last data saved

            capture.DataAvailable += (object sender, WaveInEventArgs args) =>
            {
                // Interprets the sample as 32 bit floating point audio (-> FloatBuffer)
                soundLevel = 0;
                var buffer = new WaveBuffer(args.Buffer);

                for (int index = 0; index < args.BytesRecorded / 4; index++)
                {
                    var sample = buffer.FloatBuffer[index];

                    // Sound level
                    if (sample < 0)
                    {
                        sample = -sample;             // abs
                    }
                    if (sample > soundLevel)
                    {
                        soundLevel = sample;
                    }

                    // Bass level

                    if (listenForBass)
                    {
                        // HannWindow sample with amplitude -> amplitude to decibels
                        fftBuffer[fftPos].X = (float)(sample * FastFourierTransform.HannWindow(fftPos, fftLength));
                        fftBuffer[fftPos].Y = 0;
                        fftPos++;

                        if (fftPos >= fftLength)
                        {
                            fftPos = 0;

                            FastFourierTransform.FFT(true, m, fftBuffer);

                            lock (_lock)
                            {
                                bufferAvailible = false;

                                for (int c = 0; c < fftLength; c++)
                                {
                                    float amplitude = (float)Math.Sqrt(fftBuffer[c].X * fftBuffer[c].X + fftBuffer[c].Y * fftBuffer[c].Y);
                                    lastFftBuffer[c] = amplitude;
                                }

                                bufferAvailible = true;
                            }
                        }
                    }
                }
            };

            capture.StartRecording();
        }
コード例 #11
0
        public static AudioData GetFrequencyBands(float[] sampleArray)
        {
            NAudio.Dsp.Complex[] complices      = new NAudio.Dsp.Complex[sampleArray.Length];
            List <float>[]       amplitudeLists = GetEmptyFloatListArray();
            // Collates the amplitudes into complexes wtih the Hann window applied
            for (int fftPosition = 0; fftPosition < sampleArray.Length; fftPosition++)
            {
                complices[fftPosition].X = Convert.ToSingle(sampleArray[fftPosition] * FastFourierTransform.HannWindow(fftPosition, sampleArray.Length));
                complices[fftPosition].Y = 0;
            }
            // Performs the FFT to get the frequencies out
            FastFourierTransform.FFT(true, (int)Math.Log(sampleArray.Length, 2.0), complices);
            float[] realFrequencies = new float[complices.Length];
            // Gets the real numbers out of the complex numbers
            for (int realPosition = 0; realPosition < complices.Length; realPosition++)
            {
                realFrequencies[realPosition] = Convert.ToSingle(Math.Pow(complices[realPosition].X, 2) + Math.Pow(complices[realPosition].Y, 2));
            }
            // Creates an array of empty numbers to collate the counts of categorisation
            int[] counts       = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
            float maxFrequency = realFrequencies.Max();

            for (int lightPosition = 0; lightPosition < realFrequencies.Length; lightPosition++)
            {
                // Gets the frequency on a scale from 0 to 1 in this window
                float realFrequencyNormal = realFrequencies[lightPosition] / maxFrequency;
                int   lightToIncrement;
                // If the max frequency in this time slice is 0, that means that all of the values are 0 and we should avoid doing any more maths
                if (maxFrequency == 0)
                {
                    lightToIncrement = 0;
                }
                else
                {
                    lightToIncrement = Convert.ToInt32(Math.Round(16 * (Math.Sqrt(realFrequencyNormal))));
                }
                // Prevents the index from going over the maximum range
                if (lightToIncrement == 16)
                {
                    lightToIncrement = 15;
                }
                counts[lightToIncrement]++;
                amplitudeLists[lightToIncrement].Add(sampleArray[lightPosition]);
            }
            float[] averageAmplitudes = new float[16];
            for (int averageAmplitudePosition = 0; averageAmplitudePosition < averageAmplitudes.Length; averageAmplitudePosition++)
            {
                if (amplitudeLists[averageAmplitudePosition].Count != 0)
                {
                    averageAmplitudes[averageAmplitudePosition] = Math.Abs(amplitudeLists[averageAmplitudePosition].Average());
                }
                else
                {
                    averageAmplitudes[averageAmplitudePosition] = 0;
                }
            }
            AudioData output = new AudioData(counts, averageAmplitudes);

            // These mask functions were intended to distribute values, solving the issue of the frequencies dogpiling the first band, but I found these did more harm than good, and commented them out
            //Vector<short> countVector = GetLightVector(counts);
            //for (int vectorPosition = 0; vectorPosition < counts.Length; vectorPosition++)
            //{
            //    Vector<short> currentMask = GetMaskVector(vectorPosition);
            //    countVector = Vector.Divide(countVector, currentMask);
            //}
            //for (int vectorToArrayPosition = 0; vectorToArrayPosition < 16; vectorToArrayPosition++)
            //{
            //    counts[vectorToArrayPosition] = Convert.ToInt32(countVector[vectorToArrayPosition]);
            //}
            return(output);
        }