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(); }
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()); }
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 }
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; } }
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 }
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); }