コード例 #1
0
ファイル: CQTProcessor.cs プロジェクト: Seank23/MusicAnalyser
    private void GetSparseKernel()
    {
        int sampleRate = 1;

        if (InputArgs.ContainsKey("SAMPLE_RATE"))
        {
            if (InputArgs["SAMPLE_RATE"].GetType().Name == "Int32")
            {
                sampleRate = (int)InputArgs["SAMPLE_RATE"];
            }
        }

        float  threshold     = 0.000054f;
        int    numOctaves    = int.Parse(Settings["OCTAVES"][0]);
        int    binsPerOctave = int.Parse(Settings["BINS_PER_OCTAVE"][0]);
        double minFreq       = double.Parse(Settings["MIN_FREQ"][0]);
        int    numBins       = numOctaves * binsPerOctave;
        double Q             = 1 / (Math.Pow(2, 1 / (double)binsPerOctave) - 1);

        int fftLen = 1;

        while (fftLen < Q * sampleRate / minFreq)
        {
            fftLen *= 2;
        }

        NAudio.Dsp.Complex[] tempKernel = new NAudio.Dsp.Complex[fftLen];
        List <Complex[]>     sparKernel = new List <Complex[]>();

        for (int k = 0; k < numBins; k++)
        {
            int N = (int)Math.Ceiling(Q * sampleRate / (minFreq * Math.Pow(2, k / (double)binsPerOctave)));
            for (int n = 0; n < N; n++)
            {
                Complex temp = NAudio.Dsp.FastFourierTransform.HammingWindow(n, N) / (N * (1 + (double.Parse(Settings["N_WEIGHTING"][0]) * N)))
                               * Complex.Exp(2 * Math.PI * Complex.ImaginaryOne * n * (Q / N)) * (1000 * (1 + (double.Parse(Settings["N_WEIGHTING"][0]) * 1000)));

                tempKernel[n].X = (float)temp.Real;
                tempKernel[n].Y = (float)temp.Imaginary;
            }
            NAudio.Dsp.FastFourierTransform.FFT(true, (int)Math.Log(fftLen, 2.0), tempKernel);
            Complex[] compKernel = new Complex[tempKernel.Length];
            for (int i = 0; i < tempKernel.Length; i++)
            {
                if (tempKernel[i].X < threshold && tempKernel[i].Y < threshold)
                {
                    compKernel[i] = new Complex(0, 0);
                }
                else
                {
                    compKernel[i] = new Complex(tempKernel[i].X, tempKernel[i].Y);
                }
            }
            sparKernel.Add(compKernel);
        }
        Matrix <Complex> kernelMat = CreateMatrix.SparseOfRowArrays(sparKernel.ToArray());

        kernelMat.Multiply(1000);
        kernel = kernelMat.ConjugateTranspose();
    }
コード例 #2
0
ファイル: Form1.cs プロジェクト: bodinroxana0/proiect_PMS
        void Analyze_chunk()
        {
            // fill data with FFT info
            short[] data = new short[fft_size];
            data = unanalyzed_values.GetRange(0, fft_size).ToArray();

            // remove the left-most (oldest) column of data
            spec_data.RemoveAt(0);

            // insert new data to the right-most (newest) position
            List <double> new_data = new List <double>();

            // prepare the complex data which will be FFT'd
            NAudio.Dsp.Complex[] fft_buffer = new NAudio.Dsp.Complex[fft_size];
            for (int i = 0; i < fft_size; i++)
            {
                //fft_buffer[i].X = (float)unanalyzed_values[i]; // no window
                fft_buffer[i].X = (float)(unanalyzed_values[i] * FastFourierTransform.HammingWindow(i, fft_size));
                fft_buffer[i].Y = 0;
            }

            // perform the FFT
            FastFourierTransform.FFT(true, (int)Math.Log(fft_size, 2.0), fft_buffer);

            // fill that new data list with fft values
            for (int i = 0; i < spec_data[spec_data.Count - 1].Count; i++)
            {
                double val;
                val = (double)fft_buffer[i].X + (double)fft_buffer[i].Y;
                val = Math.Abs(val);
                new_data.Add(val);
            }

            new_data.Reverse();
            spec_data.Insert(spec_data.Count, new_data); // replaces, doesn't append!

            // remove a certain amount of unanalyzed data
            unanalyzed_values.RemoveRange(0, fft_size / pixelsPerBuffer);
        }
コード例 #3
0
ファイル: CQTProcessor.cs プロジェクト: Seank23/MusicAnalyser
    public void Process()
    {
        short[] input = null;
        if (InputBuffer.GetType().Name == "Int16[]")
        {
            input = (short[])InputBuffer;
        }
        if (input == null)
        {
            return;
        }

        if (kernel == null)
        {
            GetSparseKernel();
        }

        if (input.Length != kernel.RowCount)
        {
            Array.Resize(ref input, kernel.RowCount);
        }

        int fftPoints = 2;

        while (fftPoints * 2 <= input.Length)
        {
            fftPoints *= 2;
        }

        NAudio.Dsp.Complex[] fftFull = new NAudio.Dsp.Complex[fftPoints];
        for (int i = 0; i < fftPoints; i++)
        {
            fftFull[i].X = (float)(input[i] * NAudio.Dsp.FastFourierTransform.HammingWindow(i, fftPoints));
        }

        NAudio.Dsp.FastFourierTransform.FFT(true, (int)Math.Log(kernel.RowCount, 2.0), fftFull);
        Complex[] fftComp = new Complex[fftFull.Length];

        for (int i = 0; i < fftComp.Length; i++)
        {
            fftComp[i] = new Complex(fftFull[i].X, fftFull[i].Y);
        }

        Matrix <Complex> fftVec = CreateVector.DenseOfArray(fftComp).ToRowMatrix();

        Complex[] product = (fftVec * kernel).Row(0).AsArray();
        double[]  mag     = new double[product.Length];

        for (int i = 0; i < mag.Length; i++)
        {
            mag[i] = product[i].Magnitude;
        }

        if (Settings["OUTPUT_MODE"][0] == "dB")
        {
            double maxDB = 20 * Math.Log10(mag.Max());
            for (int i = 0; i < mag.Length; i++)
            {
                mag[i] = 20 * Math.Log10(product[i].Magnitude) - maxDB;
            }
        }
        else if (Settings["SQUARE"][0] == "Yes")
        {
            for (int i = 0; i < mag.Length; i++)
            {
                mag[i] = Math.Pow(mag[i], 2) / 100;
            }
        }

        OutputBuffer = mag;
        Func <double, double> scale = i => double.Parse(Settings["MIN_FREQ"][0]) * Math.Pow(2, (double)i / int.Parse(Settings["BINS_PER_OCTAVE"][0]));

        OutputArgs.Add("SCALE", scale);
    }
コード例 #4
0
    public void Process()
    {
        short[] input = null;
        if (InputBuffer.GetType().Name == "Int16[]")
        {
            input = (short[])InputBuffer;
        }
        if (input == null)
        {
            return;
        }

        int sampleRate = 1;

        if (InputArgs.ContainsKey("SAMPLE_RATE"))
        {
            if (InputArgs["SAMPLE_RATE"].GetType().Name == "Int32")
            {
                sampleRate = (int)InputArgs["SAMPLE_RATE"];
            }
        }

        int fftPoints = 2;

        while (fftPoints * 2 <= input.Length) // Sets fftPoints to largest multiple of 2 in BUFFERSIZE
        {
            fftPoints *= 2;
        }
        double[] output = new double[fftPoints / 2];

        // FFT Process
        NAudio.Dsp.Complex[] fftFull = new NAudio.Dsp.Complex[fftPoints];
        for (int i = 0; i < fftPoints; i++)
        {
            if (Settings["WINDOW"][0] == "Hamming")
            {
                fftFull[i].X = (float)(input[i] * NAudio.Dsp.FastFourierTransform.HammingWindow(i, fftPoints));
            }
            else if (Settings["WINDOW"][0] == "Hann")
            {
                fftFull[i].X = (float)(input[i] * NAudio.Dsp.FastFourierTransform.HannWindow(i, fftPoints));
            }
            else if (Settings["WINDOW"][0] == "BlackmannHarris")
            {
                fftFull[i].X = (float)(input[i] * NAudio.Dsp.FastFourierTransform.BlackmannHarrisWindow(i, fftPoints));
            }
            else
            {
                fftFull[i].X = input[i];
            }
        }
        NAudio.Dsp.FastFourierTransform.FFT(true, (int)Math.Log(fftPoints, 2.0), fftFull);

        for (int i = 0; i < fftPoints / 2; i++) // Since FFT output is mirrored above Nyquist limit (fftPoints / 2), these bins are summed with those in base band
        {
            double fft       = Math.Abs(fftFull[i].X + fftFull[i].Y);
            double fftMirror = Math.Abs(fftFull[fftPoints - i - 1].X + fftFull[fftPoints - i - 1].Y);
            if (Settings["OUTPUT_MODE"][0] == "dB")
            {
                output[i] = 20 * Math.Log10(fft + fftMirror) - 20 * Math.Log10(input.Length); // Estimates gain of FFT bin
            }
            else
            {
                if (fft + fftMirror <= int.Parse(Settings["MAG_LIMIT"][0]))
                {
                    output[i] = (fft + fftMirror) * (0.5 + (i / (fftPoints * 2)));
                }
                else
                {
                    output[i] = int.Parse(Settings["MAG_LIMIT"][0]);
                }
            }
            if (Settings["SQUARE"][0] == "Yes")
            {
                output[i] = Math.Pow(output[i], 2) / 100;
            }
        }
        OutputBuffer = output;
        double scale = (double)fftPoints / sampleRate;

        OutputArgs.Add("SCALE", scale);
    }
コード例 #5
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);
        }