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