|
|
@ -0,0 +1,98 @@ |
|
|
|
|
|
|
|
using CommunityToolkit.Mvvm.ComponentModel; |
|
|
|
|
|
|
|
using CommunityToolkit.Mvvm.Input; |
|
|
|
|
|
|
|
using GettingStarted.Filter; |
|
|
|
|
|
|
|
using OxyPlot; |
|
|
|
|
|
|
|
using OxyPlot.Series; |
|
|
|
|
|
|
|
using System; |
|
|
|
|
|
|
|
using System.Collections.Generic; |
|
|
|
|
|
|
|
using System.Linq; |
|
|
|
|
|
|
|
using System.Text; |
|
|
|
|
|
|
|
using System.Threading.Tasks; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace GettingStarted.ViewModels |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
internal partial class FIRFilterViewModel : ObservableObject |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[ObservableProperty] |
|
|
|
|
|
|
|
private PlotModel _myModel; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[ObservableProperty] |
|
|
|
|
|
|
|
private LineSeries _inputSeries; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[ObservableProperty] |
|
|
|
|
|
|
|
private LineSeries _outputSeries; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[ObservableProperty] |
|
|
|
|
|
|
|
private double _sampleRate; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[ObservableProperty] |
|
|
|
|
|
|
|
private double _cutoffFrequency; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[ObservableProperty] |
|
|
|
|
|
|
|
private int _filterLength; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
double[] _coefficients; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
FIRFilter _filter; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
double[] _inputSignal; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
double _noiseLevel = 0.3; |
|
|
|
|
|
|
|
public FIRFilterViewModel() |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
MyModel = new PlotModel() { Title = "FIR Low Pass Filter" }; |
|
|
|
|
|
|
|
InputSeries = new LineSeries() { Title = "Input" }; |
|
|
|
|
|
|
|
OutputSeries = new LineSeries() { Title = "Output" }; |
|
|
|
|
|
|
|
MyModel.Series.Add(InputSeries); |
|
|
|
|
|
|
|
MyModel.Series.Add(OutputSeries); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
SampleRate = 1000d; |
|
|
|
|
|
|
|
CutoffFrequency = 100d; |
|
|
|
|
|
|
|
FilterLength = 21; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Random rand = new Random(); |
|
|
|
|
|
|
|
List<double> inputSimulate = new List<double>(); |
|
|
|
|
|
|
|
int x = 0; |
|
|
|
|
|
|
|
for (int i = 0; i < 100; i++) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
double noise = (rand.NextDouble() - 0.5) * _noiseLevel; |
|
|
|
|
|
|
|
double value = Math.Sin(x++ * 0.1) + noise; |
|
|
|
|
|
|
|
inputSimulate.Add(value); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
_inputSignal = inputSimulate.ToArray(); ; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ProcessSignal(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[RelayCommand] |
|
|
|
|
|
|
|
private void ProcessSignal() |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
_coefficients = FIRFilter.DesignLowPassFilter(FilterLength, CutoffFrequency, SampleRate); |
|
|
|
|
|
|
|
_filter = new FIRFilter(_coefficients); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
double[] outputSignal = _filter.ProcessSignal(_inputSignal); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
InputSeries.Points.Clear(); |
|
|
|
|
|
|
|
int x = 0; |
|
|
|
|
|
|
|
DataPoint[] dataPoints = _inputSignal.Select(val => new DataPoint(++x, val)).ToArray(); |
|
|
|
|
|
|
|
InputSeries.Points.AddRange(dataPoints); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
OutputSeries.Points.Clear(); |
|
|
|
|
|
|
|
int x = 0; |
|
|
|
|
|
|
|
DataPoint[] dataPoints = outputSignal.Select(val => new DataPoint(++x, val)).ToArray(); |
|
|
|
|
|
|
|
OutputSeries.Points.AddRange(dataPoints); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
MyModel.InvalidatePlot(true); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |