Example #1
0
        protected override void _Initialize()
        {
            int fftBufferSize = _channelSamples.CeilingToPowerOfTwo();

            fftBuffer = new Complex64[fftBufferSize];

            sideBandAmplitudes.Clear();

            double spectralModulatorTerm = -2.0 * Math.PI * spectralModulationRate / Math.Log(2.0);
            double spectralStartingPhase = 2.0 * Math.PI * randomizer.NextDouble();

            foreach (ComplexCarrierTone carrierBaseTone in carrierToneGenerator)
            {
                foreach (ComplexCarrierTone sideBand in sideBandGenerator(
                             modulationDepth: modulationDepth,
                             carrierTone: carrierBaseTone,
                             sidebandAmplitudeCache: sideBandAmplitudes,
                             modulationRate: temporalModulationRate,
                             spectralPhase: spectralStartingPhase + spectralModulatorTerm * Math.Log(carrierBaseTone.frequency)))
                {
                    FrequencyDomain.Populate(
                        buffer: fftBuffer,
                        frequency: sideBand.frequency,
                        amplitude: sideBand.amplitude);
                }
            }

            Fourier.Inverse(fftBuffer);
        }
        public void PlotSignals()
        {
            Signal workbookSourceSignal = workBookManager.ActiveWorkBook().SumOfSources();

            SignalWaveFile     = null;
            PlotPoints         = new List <DataPoint>(512);
            FrequencyViewModel = null;

            // Return empty set, this clears the display when all signals are off
            if (workbookSourceSignal == null)
            {
                NotifyPropertyChanged(nameof(PlotPoints));
                NotifyPropertyChanged(nameof(FrequencyViewModel));
                return;
            }

            CreateWavFile(workbookSourceSignal);

            for (int idx = 0; idx < workbookSourceSignal.Samples.Count; idx++)
            {
                PlotPoints.Add(new DataPoint(idx, workbookSourceSignal.Samples[idx]));
            }

            //IDFT cmplxFFT = new ComplexFastFourierTransform();
            IDFT cmplxFFT = new DSPGuideComplexDiscreteFourierTransform();

            FrequencyDomain frequencyDomain = cmplxFFT.Transform(workbookSourceSignal.Samples, workbookSourceSignal.SamplingHZ);


            FrequencyViewModel = new FrequencyHistogramViewModel(frequencyDomain);

            NotifyPropertyChanged(nameof(PlotPoints));
            NotifyPropertyChanged(nameof(FrequencyViewModel));
        }
Example #3
0
        protected override void _Initialize()
        {
            int fftBufferSize = _channelSamples.CeilingToPowerOfTwo();

            fftBuffer = new Complex64[fftBufferSize];

            foreach (ComplexCarrierTone carrierTone in CreateSideBands(freqLB, freqUB, frequencyCount, distribution))
            {
                FrequencyDomain.Populate(
                    buffer: fftBuffer,
                    frequency: carrierTone.frequency,
                    amplitude: carrierTone.amplitude);
            }

            Fourier.Inverse(fftBuffer);

            double currentRMS = 0.0;

            for (int i = 0; i < fftBufferSize; i++)
            {
                currentRMS += fftBuffer[i].Real * fftBuffer[i].Real;
            }

            currentRMS = Math.Sqrt(currentRMS / fftBufferSize);

            double factor = rms / currentRMS;

            for (int i = 0; i < fftBufferSize; i++)
            {
                fftBuffer[i] *= factor;
            }
        }
Example #4
0
        public ActionResult <FrequencyDomain> FFT([FromBody] List <Double> value)
        {
            ComplexFastFourierTransform fft       = new ComplexFastFourierTransform();
            FrequencyDomain             transform = fft.Transform(value);

            return(Ok(transform));
        }
Example #5
0
        private void ExportButton_Click(object sender, RoutedEventArgs e)
        {
            SaveFileDialog saveFileDialog = new SaveFileDialog();

            saveFileDialog.Filter = $"{Properties.Resources.FILTER_IMPORT_EXPORT_FILE_EXTENSION} (*{Properties.Resources.FILTER_IMPORT_EXPORT_FILE_EXTENSION})|*{Properties.Resources.FILTER_IMPORT_EXPORT_FILE_EXTENSION}|{Properties.Resources.ALL_FILES} (*.*)|*.*";
            if (saveFileDialog.ShowDialog() == true)
            {
                try
                {
                    using (StreamWriter fileWriter = File.CreateText(saveFileDialog.FileName))
                    {
                        fileWriter.WriteLine(Properties.Resources.FILTER_CSV_HEADER);
                        List <double> summedFilterData              = manager.ActiveWorkBook().CombinedFilterImpulseResponse(true);
                        ComplexFastFourierTransform cmplxFFT        = new ComplexFastFourierTransform();
                        FrequencyDomain             frequencyDomain = cmplxFFT.Transform(summedFilterData, manager.ActiveWorkBook().WindowedSyncFilters.Values.First().FilterLength);

                        var magPhaseList = ComplexFastFourierTransform.ToMagnitudePhaseList(frequencyDomain);

                        foreach (Tuple <double, double> coefficientMagPhase in magPhaseList)
                        {
                            fileWriter.WriteLine($"{coefficientMagPhase.Item1},{coefficientMagPhase.Item2}");
                        }
                    }
                } catch (Exception ex)
                {
                    Log.Warning(ex, ex.Message);
                    // TODO warn user
                }
            }
        }
Example #6
0
 /// <summary>
 /// Create a CustomFilter from a list of magnitudes and phases
 /// </summary>
 /// <param name="magPhaseList"></param>
 public CustomFilter(List <Tuple <double, double> > magPhaseList)
 {
     FreqDomain = new FrequencyDomain();
     foreach (Tuple <double, double> magPhase in magPhaseList)
     {
         Complex coefficient = Complex.FromPolarCoordinates(magPhase.Item1, magPhase.Item2);
         FreqDomain.FourierCoefficients.Add(coefficient);
     }
 }
Example #7
0
        public override int Read(float[] data, int offset, int count)
        {
            int samplesWritten = ReadBody(data, offset, count);

            while (samplesWritten < count)
            {
                bufferIndex = 0;
                bufferCount = STEP_SIZE;

                //Clear IFFT Buffer
                Array.Clear(ifftBuffer, 0, ifftBuffer.Length);

                foreach (ComplexCarrierTone carrierTone in carrierTones)
                {
                    FrequencyDomain.Populate(
                        buffer: ifftBuffer,
                        carrierTone: carrierTone.TimeShift(frame * timePerFrame));
                }

                //IFFT
                Fourier.Inverse(ifftBuffer);

                //Accumualte the window samples
                for (int i = 0; i < FRAME_SIZE; i++)
                {
                    outputAccumulation[i] += (float)(outputScalar * window[i] * ifftBuffer[i].Real);
                }

                //Advance Frame
                frame++;

                //Copy output samples to output buffer
                Array.Copy(
                    sourceArray: outputAccumulation,
                    destinationArray: cachedSampleBuffer,
                    length: STEP_SIZE);

                //Slide down output accumulation
                Array.Copy(
                    sourceArray: outputAccumulation,
                    sourceIndex: STEP_SIZE,
                    destinationArray: outputAccumulation,
                    destinationIndex: 0,
                    length: OVERLAP);

                //Clear empty output accumulation region
                Array.Clear(
                    array: outputAccumulation,
                    index: OVERLAP,
                    length: STEP_SIZE);

                samplesWritten += ReadBody(data, offset + samplesWritten, count - samplesWritten);
            }

            return(count);
        }
Example #8
0
        /// <summary>
        /// Export the supplied frequency domain to the supplied outputStream
        /// Writes the frequency domain data as a CSV format of magnitude,phase for each entry
        /// Note this does not stamp the header on the data, callers should do that on the stream before calling this
        /// </summary>
        /// <param name="frequencyDomain">Frequency Domain to serialize</param>
        /// <param name="outputStream">Output stream to write data to</param>
        /// <returns></returns>
        public static async Task <bool> SerializeFrequencyDomain(FrequencyDomain frequencyDomain, StreamWriter outputStream)
        {
            bool success = true;

            foreach (Complex coefficient in frequencyDomain.FourierCoefficients)
            {
                await outputStream.WriteLineAsync($"{coefficient.Magnitude},{coefficient.Phase}");
            }
            return(success);
        }
        private IList <HistogramItem> GetFrequencyBins(FrequencyDomain frequencyDomain)
        {
            int binCount = (int)Math.Ceiling(frequencyDomain.SampleRateHz / 2);
            List <HistogramItem> histogramItems = new List <HistogramItem>(binCount);

            foreach (var amplitude in frequencyDomain.FrequencyAmplitudes)
            {
                HistogramItem item = new HistogramItem(amplitude.Key - 0.25, amplitude.Key + 0.25, amplitude.Value, 1);
                histogramItems.Add(item);
            }

            return(histogramItems);
        }
Example #10
0
        public void PlotData()
        {
            List <double> summedFilterData = manager.ActiveWorkBook().CombinedFilterImpulseResponse();

            if (null == summedFilterData)
            {
                return;
            }

            Signal workbookSourceSignal = manager.ActiveWorkBook().SumOfSources();

            if (workbookSourceSignal == null)
            {
                return;
            }

            SignalPlotPoints = new List <DataPoint>(workbookSourceSignal.Samples.Count);

            for (int idx = 0; idx < workbookSourceSignal.Samples.Count; idx++)
            {
                SignalPlotPoints.Add(new DataPoint(idx, workbookSourceSignal.Samples[idx]));
            }

            ConvolutionPlotPoints = new List <DataPoint>(summedFilterData.Count);

            for (int idx = 0; idx < summedFilterData.Count; idx++)
            {
                ConvolutionPlotPoints.Add(new DataPoint(idx, summedFilterData[idx]));
            }

            List <double> convolutionResult = convolver.Convolve(summedFilterData, workbookSourceSignal.Samples, ConvolutionType.INPUTSIDE);

            ResultPlotPoints = new List <DataPoint>(convolutionResult.Count);
            for (int idx = 0; idx < convolutionResult.Count; idx++)
            {
                ResultPlotPoints.Add(new DataPoint(idx, convolutionResult[idx]));
            }

            //IDFT cmplxFFT = new ComplexFastFourierTransform();
            IDFT cmplxFFT = new DSPGuideComplexDiscreteFourierTransform();

            FrequencyDomain frequencyDomain = cmplxFFT.Transform(convolutionResult, workbookSourceSignal.SamplingHZ);

            ResultFrequencyHistogram = new FrequencyHistogramViewModel(frequencyDomain);

            NotifyPropertyChanged(nameof(SignalPlotPoints));
            NotifyPropertyChanged(nameof(ConvolutionPlotPoints));
            NotifyPropertyChanged(nameof(ResultPlotPoints));
            NotifyPropertyChanged(nameof(ResultFrequencyHistogram));
        }
Example #11
0
        static void Main(string[] args)
        {
            // ISignalGenerator sinusoid = new Sinusoid();
            // Sample sinusoidSamp = new Sample(1000, 1, 200, sinusoid);
            // List<double> signal = sinusoidSamp.GetNextSamplesForTimeSlice(64);
            // IDFT transform = new FastFourierTransform();
            // FrequencyDomain frequencyDomain = transform.Transform(signal);
            // List<double> synthesis = transform.Synthesize(frequencyDomain);

            try
            {
                StreamReader  input  = new StreamReader(args[0]);
                List <double> signal = new List <double>(64);

                while (input.Peek() > 0)
                {
                    double value;
                    if (Double.TryParse(input.ReadLine(), out value))
                    {
                        signal.Add(value);
                    }
                }
                IDFT            transform       = new RealFastFourierTransform();
                FrequencyDomain frequencyDomain = transform.Transform(signal);
                //List<double> synthesis = transform.Synthesize(frequencyDomain);
                FileStream output = new FileStream("FourierTransformResults.csv", FileMode.Create);

                if (output.CanWrite)
                {
                    StreamWriter writer = new StreamWriter(output);

                    // Write header row
                    writer.WriteLine("Index, Signal, Synthesis, Real, Imaginary");

                    for (int idx = 0; idx < signal.Count; idx++)
                    {
                        double sampleVal = signal[idx];
                        double synthVal  = 0.0f;
                        writer.WriteLine(idx + "," + sampleVal + "," + synthVal + "," + frequencyDomain.RealComponent[idx] + "," + frequencyDomain.ImaginaryComponent[idx]);
                    }

                    writer.Close();
                }
                output.Close();
            } catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
        private unsafe void GenerateFrequencyDomainImages()
        {
            FFT.SwapQuadrants(FrequencyDomain);
            Bitmap magnitude = SpatialDomain.Clone(new Rectangle(0, 0, SpatialDomain.Width, SpatialDomain.Height), SpatialDomain.PixelFormat);
            Bitmap phase     = SpatialDomain.Clone(new Rectangle(0, 0, SpatialDomain.Width, SpatialDomain.Height), SpatialDomain.PixelFormat);

            BitmapData bDataMagnitude = magnitude.LockBits(new Rectangle(0, 0, magnitude.Width, magnitude.Height), ImageLockMode.ReadWrite, magnitude.PixelFormat);
            byte *     scan0Magnitude = (byte *)bDataMagnitude.Scan0.ToPointer();

            BitmapData bDataPhase = phase.LockBits(new Rectangle(0, 0, phase.Width, phase.Height), ImageLockMode.ReadWrite, phase.PixelFormat);
            byte *     scan0Phase = (byte *)bDataPhase.Scan0.ToPointer();

            byte bitsPerPixel = ImageHelper.GetBitsPerPixel(bDataMagnitude.PixelFormat);

            List <double> phaseValues     = new List <double>();
            List <double> magnitudeValues = new List <double>();

            for (int i = 0; i < FrequencyDomain.GetUpperBound(0) + 1; i++)
            {
                for (int j = 0; j < FrequencyDomain.GetUpperBound(1) + 1; j++)
                {
                    phaseValues.Add(FrequencyDomain[i, j].Phase);
                    magnitudeValues.Add(FrequencyDomain[i, j].Magnitude);
                }
            }
            double phaseMax     = phaseValues.Max();
            double magnitudeMax = magnitudeValues.Max();

            for (int i = 0; i < bDataMagnitude.Height; ++i)
            {
                for (int j = 0; j < bDataMagnitude.Width; ++j)
                {
                    byte *dataMagnitude = scan0Magnitude + i * bDataMagnitude.Stride + j * bitsPerPixel / 8;
                    byte *dataPhase     = scan0Phase + i * bDataPhase.Stride + j * bitsPerPixel / 8;
                    dataMagnitude[0] = (byte)FFT.LogNormalize(FrequencyDomain[i, j].Magnitude, magnitudeMax, 255);
                    dataPhase[0]     = (byte)FFT.LogNormalize(FrequencyDomain[i, j].Phase, phaseMax, 255);
                }
            }

            magnitude.UnlockBits(bDataMagnitude);
            phase.UnlockBits(bDataPhase);

            MagnitudeImage = magnitude;
            PhaseImage     = phase;
            FFT.SwapQuadrants(FrequencyDomain);
        }
        public SpectralDecomp(double minFreq, double maxFreq, int windowSize, int windowCount)
        {
            fftMinFreqBin = FrequencyDomain.GetComplexFrequencyBin(windowSize, minFreq);

            //+2 to round outward AND to act as an exclusive upperbound
            fftMaxFreqBin = FrequencyDomain.GetComplexFrequencyBin(windowSize, maxFreq) + 2;
            fftMaxFreqBin = Math.Min(fftMaxFreqBin, windowSize / 2);

            spectralValues = new double[windowCount, fftMaxFreqBin - fftMinFreqBin];

            freqs = new double[fftMaxFreqBin - fftMinFreqBin];

            for (int i = 0; i < freqs.Length; i++)
            {
                freqs[i] = FrequencyDomain.GetComplexSampleFrequency(windowSize, fftMinFreqBin + i);
            }
        }
        public FrequencyHistogramViewModel(FrequencyDomain frequencyDomain)
        {
            Title = Properties.Resources.PLOT_FREQUENCY_HISTOGRAM_TITLE;
            Axes.Add(new LinearAxis {
                Position = AxisPosition.Left, Title = Properties.Resources.PLOT_FREQUENCY_HISTOGRAM_LEFT_AXIS
            });
            Axes.Add(new LinearAxis {
                Position = AxisPosition.Bottom, Title = Properties.Resources.PLOT_FREQUENCY_HISTOGRAM_BOTTOM_AXIS
            });

            if (frequencyDomain != null)
            {
                HistogramSeries chs = new HistogramSeries();
                chs.Items.AddRange(GetFrequencyBins(frequencyDomain));
                Series.Add(chs);
            }
        }
        protected override void _Initialize()
        {
            int    frameSize    = Samples.Length.CeilingToPowerOfTwo();
            double outputScalar = 2.0 / Math.Sqrt(frameSize);

            Complex64[] ifftBuffer = new Complex64[frameSize];

            foreach (ComplexCarrierTone carrierTone in carrierTones)
            {
                FrequencyDomain.Populate(ifftBuffer, carrierTone);
            }

            Fourier.Inverse(ifftBuffer);

            for (int i = 0; i < Samples.Length; i++)
            {
                Samples[i] = (float)(outputScalar * ifftBuffer[i].Real);
            }
        }
Example #16
0
        protected override void _Initialize()
        {
            Complex64[] samples      = stream.ComplexSamples();
            int         bufferLength = samples.Length;

            Fourier.Forward(samples);

            IEnumerator <double> distribution = frequencyDistribution.GetEnumerator();

            distribution.MoveNext();

            int lowerBound = FrequencyDomain.GetComplexFrequencyBin(bufferLength, distribution.Current);

            while (distribution.MoveNext())
            {
                int upperBound = FrequencyDomain.GetComplexFrequencyBin(bufferLength, distribution.Current);

                //Generate random offset for the range
                double offset = 2 * Math.PI * randomizer.NextDouble();

                for (int i = lowerBound; i < upperBound; i++)
                {
                    samples[i] *= Complex64.FromPolarCoordinates(2.0, i * offset);
                }

                lowerBound = upperBound;
            }

            for (int i = bufferLength / 2; i < bufferLength; i++)
            {
                samples[i] = 0.0;
            }

            Fourier.Inverse(samples);

            Samples = new float[bufferLength];

            for (int i = 0; i < bufferLength; i++)
            {
                Samples[i] = (float)samples[i].Real;
            }
        }
Example #17
0
        public void TestLoadFromFrequencyAmplitudes()
        {
            // low pass amplitude array
            double[] amplitudes = { 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
                                    1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
                                    0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
                                    0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
                                    0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
                                    0.0, 0.0 };

            List <double> frequencyDomain = new List <double>(amplitudes);
            //FrequencyDomain frequencyDomain = ComplexFastFourierTransform.LoadFourierCoefficients(new List<double>(amplitudes));

            ComplexFastFourierTransform synth      = new ComplexFastFourierTransform();
            FrequencyDomain             timeDomain = synth.Transform(frequencyDomain, 2 * frequencyDomain.Count());

            foreach (var value in timeDomain.FrequencyAmplitudes)
            {
                Console.WriteLine(value);
            }
        }
Example #18
0
        public void Initialize()
        {
            if (initialized)
            {
                return;
            }

            initialized = true;
            //Min of 10 periods of lowest frequency
            int bufferSizeLowerBound = (int)Math.Ceiling(SamplingRate * 10.0 / freqLB);

            fftBufferSize = bufferSizeLowerBound.CeilingToPowerOfTwo();
            fftBuffer     = new Complex64[fftBufferSize];

            foreach (ComplexCarrierTone carrierTone in CreateSideBands(freqLB, freqUB, frequencyCount, distribution))
            {
                FrequencyDomain.Populate(
                    buffer: fftBuffer,
                    frequency: carrierTone.frequency,
                    amplitude: carrierTone.amplitude);
            }

            Fourier.Inverse(fftBuffer);

            double currentRMS = 0.0;

            for (int i = 0; i < fftBufferSize; i++)
            {
                currentRMS += fftBuffer[i].Real * fftBuffer[i].Real;
            }

            currentRMS = Math.Sqrt(currentRMS / fftBufferSize);

            double factor = rms / currentRMS;

            for (int i = 0; i < fftBufferSize; i++)
            {
                fftBuffer[i] *= factor;
            }
        }
Example #19
0
        public SpectralDecomp(double minFreq, double maxFreq, int windowSize, int windowCount)
        {
            fftMinFreqBin = FrequencyDomain.GetComplexFrequencyBin(windowSize, minFreq);

            //+2 to round outward AND to act as an exclusive upperbound
            fftMaxFreqBin = FrequencyDomain.GetComplexFrequencyBin(windowSize, maxFreq) + 2;
            fftMaxFreqBin = Math.Min(fftMaxFreqBin, windowSize / 2);

            spectralValues = new double[windowCount, fftMaxFreqBin - fftMinFreqBin];

            freqs = new double[fftMaxFreqBin - fftMinFreqBin];

            for (int i = 0; i < freqs.Length; i++)
            {
                freqs[i] = FrequencyDomain.GetComplexSampleFrequency(windowSize, fftMinFreqBin + i);
            }

            amplitudeAdjustant = 10.0 * Math.Log10(windowSize);

            minAmplitude = double.PositiveInfinity;
            maxAmplitude = double.NegativeInfinity;
        }
Example #20
0
        // 64 channel sample with padCount zeros padded right
        public List <double> GetPaddedChannelSample(int sampleCount, int padCount)
        {
            int numSamplesToGet = (sampleCount - padCount);
            int curIDX          = _sampleIDX;

            if (curIDX + numSamplesToGet >= _samples.Count)
            {
                numSamplesToGet = _samples.Count - curIDX;
                if (numSamplesToGet <= 0)
                {
                    // Roll over to the beginning
                    _sampleIDX = 0;
                    return(GetPaddedChannelSample(sampleCount, padCount));
                }
            }

            _sampleIDX  += numSamplesToGet;
            _sliceSignal = _samples.GetRange(curIDX, numSamplesToGet);

            List <double> paddedSignal = new List <double>(sampleCount);

            paddedSignal.AddRange(_sliceSignal);
            // Pad
            int padLen = (sampleCount - numSamplesToGet);

            for (int cnt = 0; cnt < padLen; cnt++)
            {
                paddedSignal.Add(0.0);
            }

            IDFT ff_transform = new ComplexFastFourierTransform();
            IDFT cdf_tranform = new CorrelationFourierTransform();

            //_frequencyDomain = DFT.CorrelationTransform(paddedSignal);
            _frequencyDomain = ff_transform.Transform(paddedSignal);
            return(_sliceSignal);
        }
Example #21
0
        public List <double> GetNextSamplesForTimeSlice(double milliseconds)
        {
            int numSamplesToGet = (int)Math.Floor((milliseconds / 1000) * _sampleRate);
            int curIDX          = _sampleIDX;

            if (curIDX + numSamplesToGet >= _samples.Count)
            {
                numSamplesToGet = _samples.Count - curIDX - 1;
                if (numSamplesToGet <= 0)
                {
                    // Roll over to the beginning
                    _sampleIDX = 0;
                    return(GetNextSamplesForTimeSlice(milliseconds));
                }
            }
            _sampleIDX  += numSamplesToGet;
            _sliceSignal = _samples.GetRange(curIDX, numSamplesToGet);
            //_frequencyDomain = DFT.CorrelationTransform(_sliceSignal);
            //IDFT transform = new FastFourierTransform();
            IDFT transform = new CorrelationFourierTransform();

            _frequencyDomain = transform.Transform(_sliceSignal);
            return(_sliceSignal);
        }
        public static SpectralDecomp Decompose(
            IBGCStream stream,
            int windowCount   = 400,
            int windowOrder   = 12,
            int targetChannel = 0,
            double minFreq    = 0.0,
            double maxFreq    = double.PositiveInfinity)
        {
            //WindowSize is 2 ^ windowOrder
            int windowSize = 1 << windowOrder;

            if (stream.Channels <= targetChannel)
            {
                throw new ArgumentException(
                          $"TargetChannel ({targetChannel}) exceeded stream channels ({stream.Channels})",
                          nameof(targetChannel));
            }

            float[] samples = stream.IsolateChannel(targetChannel).HardClip().Cache().Samples;

            int sampleOffset = (int)((samples.Length - windowSize) / (double)(windowCount - 1));

            //Adjust windowSize to conform to sample size and requirements
            while (sampleOffset <= 0 && windowOrder > 4)
            {
                --windowOrder;
                windowSize   = 1 << windowOrder;
                windowCount /= 2;
                sampleOffset = (int)((samples.Length - windowSize) / (double)(windowCount - 1));
            }

            if (windowOrder == 4)
            {
                throw new ArgumentException("Clip too short to evaluate");
            }

            //Limit Max Frquency by the size of the window
            maxFreq = Math.Min(maxFreq, FrequencyDomain.GetComplexSampleFrequency(windowSize, windowSize / 2));

            //Limit Min Frequency by the
            minFreq = Math.Max(minFreq, FrequencyDomain.GetComplexSampleFrequency(windowSize, 1));

            //Our output will be just the real-valued amplitudes
            SpectralDecomp decomp = new SpectralDecomp(minFreq, maxFreq, windowSize, windowCount);

            Complex64[] fftBuffer = new Complex64[windowSize];

            IBGCEnvelopeStream windowStream = new BlackmanHarrisEnvelope(windowSize);

            for (int window = 0; window < windowCount; window++)
            {
                int specificOffset = sampleOffset * window;
                windowStream.Reset();

                //Copy samples into buffer
                for (int i = 0; i < windowSize; i++)
                {
                    //Set real value
                    fftBuffer[i] = samples[specificOffset + i] * windowStream.ReadNextSample();
                }

                Fourier.Forward(fftBuffer);

                decomp.Add(window, fftBuffer);
            }

            decomp.Rescale();

            return(decomp);
        }
Example #23
0
        public ActionResult <List <Double> > InverseFFT([FromBody] FrequencyDomain fd)
        {
            ComplexFastFourierTransform transformer = new ComplexFastFourierTransform();

            return(Ok(transformer.Synthesize(fd)));
        }
        public override int Read(float[] data, int offset, int count)
        {
            if (!initialized)
            {
                Initialize();
            }

            int samplesWritten = ReadBody(data, offset, count);

            while (samplesWritten < count)
            {
                //Slide over noise samples
                Array.Copy(
                    sourceArray: noiseBuffer,
                    sourceIndex: stepSize,
                    destinationArray: noiseBuffer,
                    destinationIndex: 0,
                    length: overlapSize);

                int read = stream.Read(inputBuffer, overlapSize, stepSize);

                if (read <= 0 && samplesHandled <= 0)
                {
                    //Done, No samples left to work with
                    break;
                }
                else if (read <= 0)
                {
                    //We are in buffer-dumping window
                    //Set rest of inputBuffer to zero
                    Array.Clear(inputBuffer, overlapSize, stepSize);
                }
                else if (read < stepSize)
                {
                    //Near or at the end
                    //Set rest of inputBuffer to zero
                    Array.Clear(inputBuffer, overlapSize + read, inputBuffer.Length - overlapSize - read);
                }

                //Generate new noise
                for (int i = 0; i < stepSize; i++)
                {
                    noiseBuffer[overlapSize + i] = noiseScalarA - noiseScalarB * randomizer.NextDouble();
                }

                //Copy in the input data
                for (int i = 0; i < fftSize; i++)
                {
                    signalFFTBuffer[i] = inputBuffer[i] * window[i];
                    noiseFFTBuffer[i]  = noiseBuffer[i];
                }

                //FFT
                Task.WaitAll(
                    Task.Run(() => Fourier.Forward(signalFFTBuffer)),
                    Task.Run(() => Fourier.Forward(noiseFFTBuffer)));

                //For each band...

                Parallel.For(
                    fromInclusive: 0,
                    toExclusive: bandFrequencies.Length - 1,
                    body: (int band) =>
                {
                    int lowerBound = FrequencyDomain.GetComplexFrequencyBin(fftSize, bandFrequencies[band]);
                    int upperBound = FrequencyDomain.GetComplexFrequencyBin(fftSize, bandFrequencies[band + 1]);

                    Complex64[] amplitudeBuffer = amplitudeBuffers[band];
                    Complex64[] noiseBandBuffer = noiseBandBuffers[band];

                    //Copy over band just the relevant frequency band
                    for (int i = lowerBound; i < upperBound; i++)
                    {
                        amplitudeBuffer[i] = 2.0 * signalFFTBuffer[i];
                        noiseBandBuffer[i] = 2.0 * noiseFFTBuffer[i];
                    }

                    Complex64 zero = Complex64.Zero;


                    //Clear rest of buffers
                    for (int i = 0; i < lowerBound; i++)
                    {
                        amplitudeBuffer[i] = zero;
                        noiseBandBuffer[i] = zero;
                    }

                    for (int i = upperBound; i < amplitudeBuffer.Length; i++)
                    {
                        amplitudeBuffer[i] = zero;
                        noiseBandBuffer[i] = zero;
                    }

                    //IFFT
                    Task.WaitAll(
                        Task.Run(() => Fourier.Inverse(amplitudeBuffer)),
                        Task.Run(() => Fourier.Inverse(noiseBandBuffer)));

                    for (int i = 0; i < amplitudeBuffer.Length; i++)
                    {
                        outputAccumulation[i] += outputFactor * window[i] * noiseBandBuffer[i].Real * amplitudeBuffer[i].Magnitude;
                    }
                });


                samplesHandled += read;

                if (--frameLag <= 0)
                {
                    bufferIndex     = 0;
                    bufferCount     = Math.Min(stepSize, samplesHandled);
                    samplesHandled -= bufferCount;

                    //Copy output samples to output buffer
                    for (int sample = 0; sample < bufferCount; sample++)
                    {
                        cachedSampleBuffer[sample] = (float)outputAccumulation[sample];
                    }
                }

                //Slide over input samples
                Array.Copy(
                    sourceArray: inputBuffer,
                    sourceIndex: stepSize,
                    destinationArray: inputBuffer,
                    destinationIndex: 0,
                    length: overlapSize);

                //Slide output samples
                Array.Copy(
                    sourceArray: outputAccumulation,
                    sourceIndex: stepSize,
                    destinationArray: outputAccumulation,
                    destinationIndex: 0,
                    length: overlapSize);

                //Clear empty output accumulation region
                Array.Clear(outputAccumulation, overlapSize, stepSize);

                samplesWritten += ReadBody(data, offset + samplesWritten, count - samplesWritten);
            }

            return(samplesWritten);
        }
        public override int Read(float[] data, int offset, int count)
        {
            int samplesWritten = ReadBody(data, offset, count);

            while (samplesWritten < count)
            {
                bufferIndex = 0;
                bufferCount = stepSize;

                //Clear IFFT Buffer
                Array.Clear(ifftBuffer, 0, ifftBuffer.Length);

                //If there are any leading frames...
                double timeShiftDeltaT = (frame + leadingFrames) * timePerStep;
                bool   isLeadingFrame  = leadingFrames < 0;

                foreach (ComplexCarrierTone carrierTone in carrierTones)
                {
                    FrequencyDomain.Populate(
                        buffer: ifftBuffer,
                        carrierTone: carrierTone.TimeShift(timeShiftDeltaT));
                }

                //IFFT
                Fourier.Inverse(ifftBuffer);

                //Accumualte the window samples
                for (int i = 0; i < frameSize; i++)
                {
                    outputAccumulation[i] += (float)(outputScalar * window[i] * ifftBuffer[i].Real);
                }

                //Advance Frame
                if (isLeadingFrame)
                {
                    leadingFrames++;
                }
                else
                {
                    frame++;
                }

                //Copy output samples to output buffer
                Array.Copy(
                    sourceArray: outputAccumulation,
                    destinationArray: cachedSampleBuffer,
                    length: stepSize);

                //Slide down output accumulation
                Array.Copy(
                    sourceArray: outputAccumulation,
                    sourceIndex: stepSize,
                    destinationArray: outputAccumulation,
                    destinationIndex: 0,
                    length: overlap);

                //Clear empty output accumulation region
                Array.Clear(
                    array: outputAccumulation,
                    index: overlap,
                    length: stepSize);

                if (!isLeadingFrame)
                {
                    samplesWritten += ReadBody(data, offset + samplesWritten, count - samplesWritten);
                }
            }

            return(count);
        }
Example #26
0
        private void LoadFilterData()
        {
            List <double> summedFilterData = manager.ActiveWorkBook().CombinedFilterImpulseResponse(true);

            // Return an empty set
            if (summedFilterData == null || summedFilterData.Count == 0)
            {
                ImpulseResponsePoints   = new List <DataPoint>();
                StepResponsePoints      = new List <DataPoint>();
                FrequencyResponsePoints = new List <DataPoint>();
                DecibelResponsePoints   = new List <DataPoint>();
                Filters = new ObservableCollection <UserControl>();

                NotifyPropertyChanged(nameof(ImpulseResponsePoints));
                NotifyPropertyChanged(nameof(FrequencyResponsePoints));
                NotifyPropertyChanged(nameof(DecibelResponsePoints));
                NotifyPropertyChanged(nameof(StepResponsePoints));
                NotifyPropertyChanged(nameof(SumModeActive));
                NotifyPropertyChanged(nameof(ConvolveModeActive));
                NotifyPropertyChanged(nameof(Filters));

                return;
            }

            ImpulseResponsePoints = new List <DataPoint>(summedFilterData.Count);
            StepResponsePoints    = new List <DataPoint>(summedFilterData.Count);

            Filters = new ObservableCollection <UserControl>();

            for (int idx = 0; idx < summedFilterData.Count; idx++)
            {
                ImpulseResponsePoints.Add(new DataPoint(idx, summedFilterData[idx]));
            }
            //IDFT cmplxFFT = new ComplexFastFourierTransform();
            IDFT cmplxFFT = new DSPGuideComplexDiscreteFourierTransform();

            int filterLength = 0;

            if (manager.ActiveWorkBook().WindowedSyncFilters.Count > 0)
            {
                filterLength = manager.ActiveWorkBook().WindowedSyncFilters.Values.First().FilterLength;
            }
            else if (manager.ActiveWorkBook().CustomFilters.Count > 0)
            {
                filterLength = manager.ActiveWorkBook().CustomFilters.Values.First().FilterLength;
            }
            else
            {
                return; // Count not find any filters to set length with
            }

            FrequencyDomain frequencyDomain = cmplxFFT.Transform(summedFilterData, filterLength);

            Convolution   convolver    = new Convolution();
            List <double> stepResponse = convolver.Convolve(summedFilterData, GetStepData(summedFilterData.Count + 16), ConvolutionType.INPUTSIDE);

            FrequencyResponsePoints = new List <DataPoint>(frequencyDomain.FrequencyAmplitudes.Count);
            DecibelResponsePoints   = new List <DataPoint>(FrequencyResponsePoints.Count);

            // Load the frequency response graph data
            // Only scan the first half of the coefficients (up to the Nyquist frequency)
            int coefficientMax = (frequencyDomain.FourierCoefficients.Count / 2);

            for (int idx = 0; idx < coefficientMax; idx++)
            {
                double coeffLen = Complex.Abs(frequencyDomain.FourierCoefficients[idx]);
                double cuttoffFrequencyPercent = (((double)idx + 1.0) / summedFilterData.Count);
                FrequencyResponsePoints.Add(new DataPoint(cuttoffFrequencyPercent, coeffLen));
                DecibelResponsePoints.Add(new DataPoint(cuttoffFrequencyPercent, 20 * Math.Log10(coeffLen)));
            }

            int startingOffset = (summedFilterData.Count / 2);
            int endingOffset   = startingOffset + summedFilterData.Count;
            int graphX         = 0;

            // Load the step response graph data
            for (int idx = (startingOffset - 1); idx < endingOffset; idx++)
            {
                StepResponsePoints.Add(new DataPoint(graphX, stepResponse[idx]));
                graphX++;
            }

            foreach (var filter in manager.ActiveWorkBook().WindowedSyncFilters.Values)
            {
                filter.PropertyChanged -= handleFilterUpdate;
                WindowedSyncFilterItemView viewItem = new WindowedSyncFilterItemView();
                viewItem.DataContext = filter;
                Filters.Add(viewItem);
                filter.PropertyChanged += handleFilterUpdate; // Remove/re-add to avoid leaks in event handlers
            }

            foreach (var filter in manager.ActiveWorkBook().CustomFilters.Values)
            {
                filter.PropertyChanged -= handleFilterUpdate;
                CustomFilterViewItem viewItem = new CustomFilterViewItem();
                viewItem.DataContext = filter;
                Filters.Add(viewItem);
                filter.PropertyChanged += handleFilterUpdate; // Remove/re-add to avoid leaks in event handlers
            }

            NotifyPropertyChanged(nameof(ImpulseResponsePoints));
            NotifyPropertyChanged(nameof(FrequencyResponsePoints));
            NotifyPropertyChanged(nameof(DecibelResponsePoints));
            NotifyPropertyChanged(nameof(StepResponsePoints));
            NotifyPropertyChanged(nameof(Filters));
        }
Example #27
0
        public void TestComplexTransform()
        {
            //IDFT complexFourierTransform = new ComplexFastFourierTransform();
            IDFT complexFourierTransform = new DSPGuideComplexDiscreteFourierTransform();


            FrequencyDomain result;
            List <double>   recreatedSignal;

            int           sampleRate = 1000; // hz
            List <double> timePoints = new List <double>(2 * sampleRate);

            for (double timePointVal = 0; timePointVal < 2.0; timePointVal += (1.0 / sampleRate))
            {
                timePoints.Add(timePointVal);
            }

            List <double> signal = new List <double>(timePoints.Count);

            foreach (double timePointVal in timePoints)
            {
                double signalValue = (2.5 * Math.Sin(2 * Math.PI * 4 * timePointVal)) + (1.5 * Math.Sin(2 * Math.PI * 6.5 * timePointVal));
                signal.Add(signalValue);
            }

            result = complexFourierTransform.Transform(signal, sampleRate);
            List <Tuple <double, double> > magPhaseList = ComplexFastFourierTransform.ToMagnitudePhaseList(result);
            FrequencyDomain fromMagPhaseList            = ComplexFastFourierTransform.FromMagnitudePhaseList(magPhaseList);

            for (int idx = 0; idx < result.FourierCoefficients.Count; idx++)
            {
                double absDifference = Complex.Abs(result.FourierCoefficients[idx] - fromMagPhaseList.FourierCoefficients[idx]);
                // Check that they are close, rounding error occurs, they wont be equal
                Assert.IsTrue(absDifference < 1.0E-10);
            }

            // This file can be viewed in Excel for plotting of hz and amplitudes
            StreamWriter amplitudeFile = new StreamWriter("frequencyAmplitudes.csv");

            if (amplitudeFile != null)
            {
                amplitudeFile.WriteLine("HZ, Amplitude");
                foreach (var frequencyAmplitude in result.FrequencyAmplitudes)
                {
                    amplitudeFile.WriteLine($"{frequencyAmplitude.Key}, {frequencyAmplitude.Value}");
                }
            }
            amplitudeFile.Close();
            recreatedSignal = complexFourierTransform.Synthesize(result);

            Assert.IsNotNull(result);
            Assert.IsNotNull(recreatedSignal);

            //double amplitude40 = result.FrequencyAmplitudes[4.0];
            //double amplitude65 = result.FrequencyAmplitudes[6.5];

            //Assert.IsTrue(Math.Abs(amplitude40 - 2.5) <= MaxAmplitudeDifference);
            //Assert.IsTrue(Math.Abs(amplitude65 - 1.5) <= MaxAmplitudeDifference);

            double maxDifference = 0.0;

            for (int idx = 0; idx < recreatedSignal.Count; idx++)
            {
                double calculateDifference = Math.Abs(recreatedSignal[idx] - signal[idx]);
                if (maxDifference < calculateDifference)
                {
                    maxDifference = calculateDifference;
                }
            }

            for (int idx = 0; idx < recreatedSignal.Count; idx++)
            {
                double calculateDifference = Math.Abs(recreatedSignal[idx] - signal[idx]);
                Assert.IsTrue(calculateDifference <= MaxSignalDifference);
            }
        }