private static int[] createFreqShiftMap(FFTs stft, int indexShift, SelectedWindowIndices indices = null, int order = 0, double thresh = 0.9) { (_, _, int freqIndex1, int freqIndex2) = indices != null?indices.Indices() : (0, stft.Count, 0, stft.fftSize); /** * Explanation of algorithm: * We basically want one half cycle of a cos(ang_freq * (centerIndex-i))^(order) * First we calculation the attenuation we want at the window boundaries, ie * cos(ang_freq*(centerIndex-freq1))^(order) = thresh * Then we solve for ang_freq to find the angular frequency of the window * Then we use that angular frequency for arbitrary values of i * * And then, depending on the shift direction, we don't care about shifts on the opposite side of the direction * * If order is zero, it results in a Linear Frequency Shifter */ int centerIndex = (freqIndex2 + freqIndex1) / 2; int[] shift_map = new int[stft.fftSize]; for (int i = 0; i < shift_map.Length / 2; i++) { double angular_freq = Math.Acos(Math.Pow(thresh, (1d / ((double)order)))) / (centerIndex - freqIndex1); double angle = angular_freq * (i - centerIndex); double mod = Math.Pow(Math.Cos(angle), order); //Don't care about values outside of the half period window if (Math.Abs(angle) >= Math.PI / 2) { mod = 0; } //Don't care about values past the window in the direction it's not shifting else if (indexShift > 0 && i < freqIndex1) { mod = 0; } else if (indexShift < 0 && i > freqIndex2) { mod = 0; } int shift = (int)(indexShift * mod); if (i >= freqIndex1 && i < freqIndex2) { shift_map[i] = indexShift; //first side shift_map[shift_map.Length - i - 1] = -indexShift; //mirrored side } else { shift_map[i] = shift; } } return(shift_map); }
private static double[] createFreqShiftModulation(FFTs stft, int shiftIndex, SelectedWindowIndices indices, bool freqDependent = false) { if (freqDependent) { ; //todo, implement createFreqDependentShiftMap first } double[] shift_mod = new double[stft.fftSize]; Array.Fill(shift_mod, 1); return(shift_mod); }
public void ApplyGain(double dbGain, bool applyToWindow = false) { FFTs stft = parentRef.GetSTFT(); SelectedWindowIndices indices = parentRef.GetSelectedWindowIndices(); if (applyToWindow) { if (!indices.Exists()) { MessageBox.Show("There is no window selected!"); return; } Processing.AddGain(stft, dbGain, indices, dB: true); } else { Processing.AddGain(stft, dbGain, dB: true); } }
public void ApplyWhiteNoiseFilter(double threshold, bool applyToWindow = false) { FFTs stft = parentRef.GetSTFT(); SelectedWindowIndices indices = parentRef.GetSelectedWindowIndices(); if (applyToWindow) { if (!indices.Exists()) { MessageBox.Show("There is no window selected!"); return; } Filters.WhiteNoiseFilter(stft, threshold, indices); } else { Filters.WhiteNoiseFilter(stft, threshold); } }
public static void AddGain(FFTs stft, double gain = 0, SelectedWindowIndices indices = null, bool dB = true) { (int timeIndex1, int timeIndex2, int freqIndex1, int freqIndex2) = indices != null?indices.Indices() : (0, stft.Count, 0, stft.fftSize); //Defaults to dB //Converts to linear gain for multiplying gain to data gain = dB ? Math.Pow(10, gain / 20) : gain; List <Complex[]> data = stft.GetFFTs(); for (int n = timeIndex1; n < timeIndex2; n++) { for (int k = freqIndex1; k < freqIndex2; k++) { data[n][k].Real *= gain; data[n][k].Imaginary *= gain; } } }
public static void WhiteNoiseFilter(FFTs stft, double threshold, SelectedWindowIndices indices = null, bool dB = true) { List <Complex[]> data = stft.GetFFTs(); (int timeIndex1, int timeIndex2, int freqIndex1, int freqIndex2) = indices != null?indices.Indices() : (0, data.Count, 0, stft.fftSize); threshold = dB ? Math.Pow(10, threshold / 20) : threshold; for (int n = timeIndex1; n < timeIndex2; n++) { for (int k = freqIndex1; k < freqIndex2; k++) { if (data[n][k].Magnitude < threshold) { data[n][k].Real = 0; data[n][k].Imaginary = 0; } } } }
private static void HighPassFilter(FFTs stft, double cutoff, SelectedWindowIndices indices = null) { (int timeIndex1, int timeIndex2, int freqIndex1, int freqIndex2) = indices != null?indices.Indices() : (0, stft.Count, 0, stft.fftSize / 2); List <Complex[]> data = stft.GetFFTs(); int index_cutoff = (int)(cutoff / stft.FreqResolution); for (int n = timeIndex1; n < timeIndex2; n++) { for (int k = freqIndex1; k < freqIndex2; k++) { if (k <= index_cutoff) { data[n][k] = new Complex(); data[n][stft.fftSize - 1 - k] = new Complex(); //Mirrored side } } } }
public static void FrequencyShifter(FFTs stft, int freq_shift, SelectedWindowIndices indices = null, int order = 0, double thresh = 0.9) { int indexShift = freq_shift / stft.FreqResolution; if (indexShift == 0) { return; } (int timeIndex1, int timeIndex2, int freqIndex1, int freqIndex2) = indices != null?indices.Indices() : (0, stft.Count, 0, stft.fftSize); //Shift map tells how far each index is going to shift //Order of 0 results in a linear shifter //shift_mod gives a scaling factor to each shifted index int[] shift_map = createFreqShiftMap(stft, indexShift, indices, order, thresh); double[] shift_mod = createFreqShiftModulation(stft, indexShift, indices); List <Complex[]> ffts = stft.GetFFTs(); for (int n = timeIndex1; n < timeIndex2; n++) { Complex[] fft = ffts[n]; Complex[] shifted_fft = new Complex[fft.Length]; for (int k = 0; k < fft.Length; k++) { if (k + shift_map[k] >= 0 && k + shift_map[k] < fft.Length) //Ignore the ones that get shifted too far { shifted_fft[k + shift_map[k]] += fft[k] * shift_mod[k]; } } Array.Copy(shifted_fft, fft, fft.Length); } }
private static int[] createRecursiveBandShiftMap(FFTs stft, int indexShift, SelectedWindowIndices indices = null) { throw new NotImplementedException(); }
private void PaintGrid_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) { selectedWindow.FinishDrawing(); (int t1, int t2, int f1, int f2) = WindowPoints(); selectedIndices = new SelectedWindowIndices(t1, t2, f1, f2); }
private void RemoveSelectedSpecWindow() { PaintGrid.Children.Remove(selectedWindow.windowToDraw); selectedWindow = new SelectedSpecWindow(); selectedIndices = new SelectedWindowIndices(); }