Beispiel #1
0
        public void SaveSnippet(string filename, int startIndex, int endIndex)
        {
            List <Complex[]> snippet      = CopyFFTs(startIndex, endIndex - startIndex);
            FFTs             stft_snippet = new FFTs(snippet, sampleRate, stepSize, window);

            stft_snippet.SaveToWav(filename);
        }
        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 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();
 }
 public static void SaveFFTsToWav(string filename, FFTs stft)
 {
     float[] audio = stft.GetAudioFloat();
     using WaveFileWriter writer = new NAudio.Wave.WaveFileWriter(filename, new WaveFormat(stft.sampleRate, 1));
     writer.WriteSamples(audio, 0, audio.Length);
 }