예제 #1
0
    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
    public void Detect()
    {
        double[] input = null;
        Func <double, double> scale = null;

        if (InputData.GetType().Name == "Double[]")
        {
            input = (double[])InputData;
        }
        if (InputArgs.ContainsKey("SCALE"))
        {
            if (InputArgs["SCALE"].GetType().Name == "Func`2")
            {
                scale = (Func <double, double>)InputArgs["SCALE"];
            }
        }
        if (input == null || scale == null)
        {
            return;
        }

        double threshold   = input.Average() + (input.Max() - input.Average()) * double.Parse(Settings["THRESHOLD_FACTOR"][0]);
        double minFreq     = scale(0);
        int    binsPerNote = 1;

        while (scale(binsPerNote) < minFreq * 2)
        {
            binsPerNote++;
        }
        binsPerNote /= 12;

        int binsToRead = (int)Math.Floor((double)(binsPerNote - 1) / 2);
        Dictionary <double, double> output = new Dictionary <double, double>();
        List <double> positions            = new List <double>();

        for (int i = 0; i < input.Length; i += binsPerNote)
        {
            double freq         = scale(i);
            double avgComponent = 0;
            for (int j = -binsToRead; j <= binsToRead; j++)
            {
                if (i + j >= 0)
                {
                    avgComponent += input[i + j];
                }
            }
            avgComponent /= binsToRead * 2 + 1;
            if (avgComponent > threshold)
            {
                output.Add(freq, avgComponent);
                positions.Add(i);
            }
        }
        Output = output;
        OutputArgs.Add("POSITIONS", positions.ToArray());
    }
예제 #3
0
    public void Detect()
    {
        double[] input = null;
        double   scale = 0;

        if (InputData.GetType().Name == "Double[]")
        {
            input = (double[])InputData;
        }
        if (InputArgs.ContainsKey("SCALE"))
        {
            if (InputArgs["SCALE"].GetType().Name == "Double")
            {
                scale = (double)InputArgs["SCALE"];
            }
        }
        if (input == null || scale == 0)
        {
            return;
        }

        Dictionary <double, double> output = new Dictionary <double, double>();

        double[] derivative    = GetSlope(input, scale);
        double   gainThreshold = input.Average() + 25;

        for (int i = (int)(scale * int.Parse(Settings["MIN_FREQ"][0])); i < Math.Min(input.Length, (int)(scale * int.Parse(Settings["MAX_FREQ"][0]))); i++)
        {
            if (input[i] < gainThreshold)
            {
                continue;
            }

            if (derivative[i] > 0 && derivative[i + 1] < 0)
            {
                double freq          = (i + 1) / scale;
                double avgGainChange = (derivative[i] + derivative[i - 1] + derivative[i - 2]) / 3;
                if (avgGainChange > 3)
                {
                    output.Add(freq, input[i]);
                }
            }
        }

        Output = output.OrderByDescending(x => x.Value).ToDictionary(x => x.Key, x => x.Value); // Order: Gain - high to low
    }
예제 #4
0
    public void Process()
    {
        double[] input = null;
        if (InputBuffer.GetType().Name == "Double[]")
        {
            input = (double[])InputBuffer;
        }
        if (input == null)
        {
            return;
        }
        if (InputArgs.ContainsKey("SCALE"))
        {
            if (InputArgs["SCALE"] == null)
            {
                return;
            }
        }
        else
        {
            return;
        }

        if (Settings["ENABLED"][0] == "Yes")
        {
            double[] output = new double[input.Length];
            for (int i = 0; i < input.Length; i++)
            {
                if (InputArgs["SCALE"].GetType().Name == "Double")
                {
                    output[i] = GetFilteredSample(i * (double)InputArgs["SCALE"], input[i]);
                }
                else if (InputArgs["SCALE"].GetType().Name == "Func`2")
                {
                    var scaleFunc = (Func <int, double>)InputArgs["SCALE"];
                    output[i] = GetFilteredSample(scaleFunc(i), input[i]);
                }
            }
            OutputBuffer = output;
        }
        else
        {
            OutputBuffer = input;
        }
    }
예제 #5
0
    public void Detect()
    {
        double[] input = null;
        double   scale = 0;

        if (InputData.GetType().Name == "Double[]")
        {
            input = (double[])InputData;
        }
        if (InputArgs.ContainsKey("SCALE"))
        {
            if (InputArgs["SCALE"].GetType().Name == "Double")
            {
                scale = (double)InputArgs["SCALE"];
            }
        }
        if (input == null || scale == 0)
        {
            return;
        }

        Dictionary <double, double> output = new Dictionary <double, double>();
        double freq;
        double gainThreshold = input.Average() + int.Parse(Settings["THOLD_FROM_AVG"][0]);

        // Iterates through frequency data, storing the frequency and gain of the largest frequency bins
        for (int i = (int)(scale * int.Parse(Settings["MIN_FREQ"][0])); i < Math.Min(input.Length, (int)(scale * int.Parse(Settings["MAX_FREQ"][0]))); i++)
        {
            if (input[i] > gainThreshold)
            {
                freq = (i + 1) / scale; // Frequency value of bin

                output.Add(freq, input[i]);

                if (output.Count > int.Parse(Settings["PEAK_BUFFER"][0]))                                   // When fftPeaks overflows, remove smallest frequency bin
                {
                    output = output.OrderByDescending(x => x.Value).ToDictionary(x => x.Key, x => x.Value); // Order: Gain - high to low
                    double keyToRemove = GetDictKey(output, output.Count - 1);
                    output.Remove(keyToRemove);
                }
            }
        }

        output = output.OrderBy(x => x.Key).ToDictionary(x => x.Key, x => x.Value); // Order: Frequency - low to high
        List <KeyValuePair <double, double> > cluster     = null;
        KeyValuePair <double, double>         largestGain = new KeyValuePair <double, double>();
        int peakIndex = 0;

        while (peakIndex < output.Count) // Removes unwanted and redundant peaks
        {
            double myFreq = GetDictKey(output, peakIndex);

            if (cluster == null)
            {
                cluster     = new List <KeyValuePair <double, double> >();
                largestGain = new KeyValuePair <double, double>(myFreq, output[myFreq]);
                cluster.Add(largestGain);
                peakIndex++;
                continue;
            }
            else if ((myFreq - largestGain.Key) <= largestGain.Key / 100 * double.Parse(Settings["MAX_FREQ_CHANGE"][0])) // Finds clusters of points that represent the same peak
            {
                cluster.Add(new KeyValuePair <double, double>(myFreq, output[myFreq]));

                if (output[myFreq] > largestGain.Value)
                {
                    largestGain = new KeyValuePair <double, double>(myFreq, output[myFreq]);
                }

                if (peakIndex < output.Count - 1)
                {
                    peakIndex++;
                    continue;
                }
            }

            if (cluster.Count > 1) // Keeps only the largest value in the cluster
            {
                cluster.Remove(largestGain);
                for (int j = 0; j < cluster.Count; j++)
                {
                    output.Remove(cluster[j].Key);
                }
                peakIndex -= cluster.Count;
            }
            cluster = null;
        }

        output = output.OrderBy(x => x.Key).ToDictionary(x => x.Key, x => x.Value); // Order: Frequency - low to high
        List <double> discardFreqs = new List <double>();

        for (int i = 0; i < output.Count - 1; i++) // Removes any unwanted residual peaks after a large peak
        {
            double freqA = GetDictKey(output, i);
            double freqB = GetDictKey(output, i + 1);
            if (Math.Abs(output[freqA] - output[freqB]) >= double.Parse(Settings["MAX_GAIN_CHANGE"][0]))
            {
                if (output[freqA] > output[freqB]) // Discard lowest value
                {
                    discardFreqs.Add(freqB);
                }
                else
                {
                    discardFreqs.Add(freqA);
                }
            }
        }

        foreach (double frequency in discardFreqs)
        {
            output.Remove(frequency);
        }

        Output = output.OrderByDescending(x => x.Value).ToDictionary(x => x.Key, x => x.Value); // Order: Gain - high to low
    }
예제 #6
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);
    }
    public void Detect()
    {
        double[] input  = null;
        double   scale  = 0;
        double   tuning = 0;

        if (InputData.GetType().Name == "Double[]")
        {
            input = (double[])InputData;
        }
        if (InputArgs.ContainsKey("SCALE"))
        {
            if (InputArgs["SCALE"].GetType().Name == "Double")
            {
                scale = (double)InputArgs["SCALE"];
            }
        }
        if (InputArgs.ContainsKey("TUNING"))
        {
            if (InputArgs["TUNING"].GetType().Name == "Double")
            {
                tuning = (double)InputArgs["TUNING"];
            }
        }
        if (input == null || scale == 0)
        {
            return;
        }

        Dictionary <double, double> output = new Dictionary <double, double>();
        double spectAvg       = input.Average();
        double spectMax       = input.Max();
        int    notesPerOctave = 12;
        double minFreq        = double.Parse(Settings["MIN_FREQ"][0]) + (tuning * double.Parse(Settings["MIN_FREQ"][0]) / 100);

        double[] noteFreqs = new double[notesPerOctave * int.Parse(Settings["OCTAVES"][0])];
        for (int i = 0; i < noteFreqs.Length; i++)
        {
            noteFreqs[i] = minFreq * Math.Pow(2, (double)i / notesPerOctave);
        }

        double prevMag  = 0;
        double prevFreq = 0;

        for (int i = 0; i < noteFreqs.Length; i++)
        {
            int inputIndex  = (int)Math.Round(noteFreqs[i] * scale) - 1;
            int clusterSize = 0;
            while (clusterSize / scale <= noteFreqs[i] / 100 * double.Parse(Settings["FREQ_TOLERANCE"][0]))
            {
                clusterSize++;
            }

            if (inputIndex + clusterSize > input.Length)
            {
                break;
            }

            double avgMag = 0;
            double maxVal = 0, maxIndex = 0;
            for (int j = -clusterSize; j < clusterSize; j++)
            {
                avgMag += input[inputIndex + j];
                if (input[inputIndex + j] > maxVal)
                {
                    maxVal   = input[inputIndex + j];
                    maxIndex = inputIndex + j;
                }
            }
            avgMag /= 2 * clusterSize + 1;
            double maxFreq = maxIndex / scale;

            if (Math.Abs(prevMag - maxVal) > Math.Max(prevMag, maxVal) / 4 && noteFreqs[i] < 200)
            {
                if (prevMag - maxVal < 0)
                {
                    output.Remove(prevFreq);
                }
                else
                {
                    prevMag  = maxVal;
                    prevFreq = maxFreq;
                    continue;
                }
            }

            if (avgMag > spectAvg + ((spectMax - spectAvg) * double.Parse(Settings["MAG_THRESHOLD"][0])))
            {
                output[maxFreq] = maxVal;
            }
            prevMag  = maxVal;
            prevFreq = maxFreq;
            //Console.WriteLine("Note Freq: " + noteFreqs[i] + " Cluster Size: " + clusterSize + " Max Freq: " + (maxIndex / scale) + " Max Mag: " + maxVal);
        }
        output = output.OrderByDescending(x => x.Value).ToDictionary(x => x.Key, x => x.Value);
        Output = output.Take(int.Parse(Settings["MAX_VALS"][0])).ToDictionary(pair => pair.Key, pair => pair.Value);
    }