├── .gitattributes
├── .gitignore
├── DspSharp.DynamicInterop
├── App.config
├── DspSharp.DynamicInterop.csproj
├── DynamicInterop.cs
├── Program.cs
└── Properties
│ └── AssemblyInfo.cs
├── DspSharp.sln
├── DspSharp.sln.DotSettings
├── DspSharp
├── Algorithms
│ ├── ComplexVectors.cs
│ ├── CubicSpline
│ │ ├── CubicSpline.cs
│ │ └── TriDiagonalMatrix.cs
│ ├── Experimental.cs
│ ├── Fft.cs
│ ├── FrequencyDomain.cs
│ ├── IFftProvider.cs
│ ├── Interpolation.cs
│ ├── Mathematic.cs
│ ├── SignalGenerators.cs
│ ├── Statistics.cs
│ ├── TimeDomain.cs
│ ├── Unsafe.cs
│ ├── VectorArithmeticC.cs
│ ├── VectorArithmeticD.cs
│ ├── VectorConversions.cs
│ ├── VectorFunctions.cs
│ └── VectorOperations.cs
├── AudioSource
│ ├── BufferCompletedEventArgs.cs
│ ├── BufferCompletedEventHandler.cs
│ ├── FilterStreamer.cs
│ └── IAudioSource.cs
├── Buffers
│ ├── BufferSwitchEventArgs.cs
│ ├── CircularArray.cs
│ ├── CircularBlockBuffer.cs
│ ├── CircularBuffer.cs
│ └── DoubleBlockBuffer.cs
├── DspSharp.Interop.dll
├── DspSharp.csproj
├── DspSharp.csproj.DotSettings
├── Exceptions
│ └── SamplerateMismatchException.cs
├── Extensions
│ ├── FilterExtensions.cs
│ ├── SignalExtensions.cs
│ ├── SpectrumExtensions.cs
│ └── Utilities.cs
├── Filter
│ ├── ChangeEventHandler.cs
│ ├── FilterBase.cs
│ ├── FilterChangedEventArgs.cs
│ ├── FilterFactory
│ │ ├── FilterFactory.cs
│ │ └── FilterTypes.cs
│ ├── FilterSet.cs
│ ├── FiniteFilter.cs
│ ├── FiniteFilterSet.cs
│ ├── IFilter.cs
│ ├── IFiniteFilter.cs
│ ├── ISignalBasedFilter.cs
│ ├── LtiFilters
│ │ ├── Fir
│ │ │ ├── Convolver.cs
│ │ │ ├── CorrectingFilter.cs
│ │ │ ├── CustomConvolver.cs
│ │ │ └── FirFilter.cs
│ │ ├── Iir
│ │ │ ├── Biquad.cs
│ │ │ ├── ButterworthFilter.cs
│ │ │ ├── CustomIirFilter.cs
│ │ │ ├── IIRFilter.cs
│ │ │ └── SecondOrderPrototpyeFilter.cs
│ │ └── Primitive
│ │ │ ├── DelayFilter.cs
│ │ │ ├── DiracFilter.cs
│ │ │ ├── GainFilter.cs
│ │ │ ├── InvertFilter.cs
│ │ │ └── ZeroFilter.cs
│ └── NonlinearFilters
│ │ ├── AwgnFilter.cs
│ │ ├── CustomFilter.cs
│ │ ├── CustomFiniteFilter.cs
│ │ └── DistortionFilter.cs
├── PropertyTools.dll
├── Series
│ ├── ConstantSeries.cs
│ ├── CustomSeries.cs
│ ├── FftSeries.cs
│ ├── ISeries.cs
│ ├── SeriesBase.cs
│ ├── SeriesUtil.cs
│ └── UniformSeries.cs
├── Signal
│ ├── BaseImplementations
│ │ ├── EnumerableSignal.cs
│ │ ├── FiniteSignal.cs
│ │ ├── InfiniteSignal.cs
│ │ ├── SignalBase.cs
│ │ └── SyntheticSignal.cs
│ ├── Interfaces
│ │ ├── IEnumerableSignal.cs
│ │ ├── IFiniteSignal.cs
│ │ ├── ISignal.cs
│ │ └── ISyntheticSignal.cs
│ ├── SignalTypes
│ │ ├── Dirac.cs
│ │ ├── IdealHighpass.cs
│ │ ├── IdealLowpass.cs
│ │ ├── LogSweep.cs
│ │ ├── Sinc.cs
│ │ ├── Sinus.cs
│ │ └── WhiteNoise.cs
│ └── Windows
│ │ ├── Window.cs
│ │ ├── WindowModes.cs
│ │ └── WindowTypes.cs
├── Spectrum
│ ├── FftSpectrum.cs
│ ├── IFftSpectrum.cs
│ ├── ISpectrum.cs
│ └── Spectrum.cs
└── Utilities
│ ├── Collections
│ ├── Extensions.cs
│ ├── IObservableList.cs
│ ├── IReadOnlyObservableList.cs
│ ├── ISortedObservableList.cs
│ ├── ObservableList.cs
│ ├── ObservableSortedDictionary.cs
│ ├── ReadOnlyObservableList.cs
│ └── SortedObservableList.cs
│ ├── HashHelper.cs
│ └── Observable.cs
├── DspSharpAsio
├── ASIODriver.cs
├── ASIODriverExt.cs
├── ASIOStructures.cs
├── Asio64Bit.cs
├── AsioCallbacks.cs
├── AsioChannelInfo.cs
├── AsioDriverCapability.cs
├── AsioDriverExt.cd
├── AsioError.cs
├── AsioFillBufferCallback.cs
├── AsioMessageSelector.cs
├── AsioSampleType.cs
├── DspSharpAsio.csproj
├── Properties
│ └── AssemblyInfo.cs
└── SampleTypeConverter.cs
├── DspSharpDemo
├── App.config
├── App.xaml
├── App.xaml.cs
├── DspSharpDemo.csproj
├── EnumCombo.cs
├── EnumToStringConverter.cs
├── IListItemConverter.cs
├── LocalPropertyGridControlFactory.cs
├── MainWindow.xaml
├── MainWindow.xaml.cs
├── MultiSelectBehaviours.cs
├── PerformanceHelper.cs
├── Properties
│ ├── AssemblyInfo.cs
│ ├── Resources.Designer.cs
│ ├── Resources.resx
│ ├── Settings.Designer.cs
│ └── Settings.settings
├── RelayCommand.cs
├── SignalFactory
│ ├── AvailableSignals.cs
│ ├── CommonSignalConfig.cs
│ ├── DialogClose.cs
│ ├── DiracFactory.cs
│ ├── FileFrequencyResponseFactory.cs
│ ├── FileImpulseResponseFactory.cs
│ ├── IdealHighpassFactory.cs
│ ├── IdealLowpassFactory.cs
│ ├── LogSweepFactory.cs
│ ├── SignalDialog.xaml
│ ├── SignalDialog.xaml.cs
│ ├── SignalFactory.cs
│ ├── SignalFactoryFactory.cs
│ ├── SincFactory.cs
│ ├── SinusFactory.cs
│ ├── ViewModel.cs
│ ├── WhiteNoiseFactory.cs
│ └── WindowFactory.cs
├── TwoListSynchronizer.cs
├── ViewModel.cs
└── packages.config
├── DspSharpFftw
├── ComplexFftPlan.cs
├── DspSharp.Interop.dll
├── DspSharpFftw.csproj
├── FftPlan.cs
├── FftwDirection.cs
├── FftwFlags.cs
├── FftwInterop.cs
├── FftwKind.cs
├── FftwProvider.cs
├── ForwardRealFftPlan.cs
├── InverseRealFftPlan.cs
├── Pointers
│ └── ManagedPointer.cs
├── RealFftPlan.cs
├── libfftw3-3-32.dll
└── libfftw3-3-64.dll
├── DspSharpPlot
├── App.config
├── App.xaml
├── App.xaml.cs
├── Axes
│ ├── AmplitudeAxis.cs
│ ├── DefaultAxis.cs
│ ├── FrequencyAxis.cs
│ ├── GroupDelayAxis.cs
│ ├── ImpulseResponseAxis.cs
│ ├── PhaseAxis.cs
│ └── SampleAxis.cs
├── DspSharpPlot.csproj
├── DspSharpPlot.csproj.DotSettings
├── FilterPlot.csproj.DotSettings
├── FilterPlot.nuspec
├── Graphs
│ └── ImpulseResponseGraph.cs
├── Plot.cs
├── PlotServer
│ ├── IPlotContract.cs
│ ├── ITestContract.cs
│ └── PlotServer.cs
├── PlotWindow.xaml
├── PlotWindow.xaml.cs
├── PlotWindowViewModel.cs
├── Plots
│ ├── FinitePlot.cs
│ ├── IXCanBeLogarithmic.cs
│ ├── IYCanBeLogarithmic.cs
│ ├── ImpulseResponsePlot.cs
│ ├── MagnitudePlot.cs
│ ├── PhasePlot.cs
│ ├── SignalPlot.cs
│ └── SpectrumPlot.cs
├── Program.cs
├── Properties
│ ├── AssemblyInfo.cs
│ ├── Resources.Designer.cs
│ ├── Resources.resx
│ ├── Settings.Designer.cs
│ └── Settings.settings
└── packages.config
├── DspSharpTest
├── AlgorithmTest.cs
├── CircularBuffersTest.cs
├── ComplexVectorTests.cs
├── DspSharpTest.csproj
├── FftTest.cs
├── FilterAssert.cs
├── MlsTest.cs
├── Properties
│ └── AssemblyInfo.cs
├── TestFrequencyDomainAlgorithms.cs
├── TestInterpolation.cs
├── TestMathematicAlgorithms.cs
├── TestSignalGenerators.cs
├── TestStatistics.cs
├── TestTimeDomainAlgorithms.cs
├── TestVectorArithmeticC.cs
├── TestVectorArithmeticD.cs
├── TestVectorFunctions.cs
├── TestVectorOperations.cs
├── UnsafeAlgorithmsTest.cs
└── packages.config
├── LICENSE.txt
├── README.md
└── licenses
├── CPOL.txt
├── GPL.txt
├── MIT.txt
└── Ms-PL.txt
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
4 | # Custom for Visual Studio
5 | *.cs diff=csharp
6 |
7 | # Standard to msysgit
8 | *.doc diff=astextplain
9 | *.DOC diff=astextplain
10 | *.docx diff=astextplain
11 | *.DOCX diff=astextplain
12 | *.dot diff=astextplain
13 | *.DOT diff=astextplain
14 | *.pdf diff=astextplain
15 | *.PDF diff=astextplain
16 | *.rtf diff=astextplain
17 | *.RTF diff=astextplain
18 |
--------------------------------------------------------------------------------
/DspSharp.DynamicInterop/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/DspSharp.DynamicInterop/DspSharp.DynamicInterop.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {74829BDE-ED15-489C-A29E-09C260F38F3A}
8 | Exe
9 | Properties
10 | DspSharp.DynamicInterop
11 | DspSharp.DynamicInterop
12 | v4.6.2
13 | 512
14 | true
15 |
16 |
17 | AnyCPU
18 | true
19 | full
20 | false
21 | bin\Debug\
22 | DEBUG;TRACE
23 | prompt
24 | 4
25 |
26 |
27 | AnyCPU
28 | pdbonly
29 | true
30 | bin\Release\
31 | TRACE
32 | prompt
33 | 4
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
61 |
--------------------------------------------------------------------------------
/DspSharp.DynamicInterop/Program.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2017 Jonathan Arweck, see LICENSE.txt for license information
4 | //
5 | // --------------------------------------------------------------------------------------------------------------------
6 |
7 | namespace DspSharp.DynamicInterop
8 | {
9 | class Program
10 | {
11 | static void Main(string[] args)
12 | {
13 | DynamicInterop.Generate();
14 | }
15 | }
16 | }
--------------------------------------------------------------------------------
/DspSharp.DynamicInterop/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2017 Jonathan Arweck, see LICENSE.txt for license information
4 | //
5 | // --------------------------------------------------------------------------------------------------------------------
6 |
7 | using System.Reflection;
8 | using System.Runtime.InteropServices;
9 |
10 | // General Information about an assembly is controlled through the following
11 | // set of attributes. Change these attribute values to modify the information
12 | // associated with an assembly.
13 |
14 | [assembly: AssemblyTitle("DynamicInterop")]
15 | [assembly: AssemblyDescription("")]
16 | [assembly: AssemblyConfiguration("")]
17 | [assembly: AssemblyCompany("")]
18 | [assembly: AssemblyProduct("DynamicInterop")]
19 | [assembly: AssemblyCopyright("Copyright © 2017")]
20 | [assembly: AssemblyTrademark("")]
21 | [assembly: AssemblyCulture("")]
22 |
23 | // Setting ComVisible to false makes the types in this assembly not visible
24 | // to COM components. If you need to access a type in this assembly from
25 | // COM, set the ComVisible attribute to true on that type.
26 |
27 | [assembly: ComVisible(false)]
28 |
29 | // The following GUID is for the ID of the typelib if this project is exposed to COM
30 |
31 | [assembly: Guid("74829bde-ed15-489c-a29e-09c260f38f3a")]
32 |
33 | // Version information for an assembly consists of the following four values:
34 | //
35 | // Major Version
36 | // Minor Version
37 | // Build Number
38 | // Revision
39 | //
40 | // You can specify all the values or you can default the Build and Revision Numbers
41 | // by using the '*' as shown below:
42 | // [assembly: AssemblyVersion("1.0.*")]
43 |
44 | [assembly: AssemblyVersion("1.0.0.0")]
45 | [assembly: AssemblyFileVersion("1.0.0.0")]
--------------------------------------------------------------------------------
/DspSharp/Algorithms/FrequencyDomain.cs:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jonarw/DspSharp/f1b987ec1b5c21f572b9a1e409c661925f4d7455/DspSharp/Algorithms/FrequencyDomain.cs
--------------------------------------------------------------------------------
/DspSharp/AudioSource/BufferCompletedEventArgs.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2017 Jonathan Arweck, see LICENSE.txt for license information
4 | //
5 | // --------------------------------------------------------------------------------------------------------------------
6 |
7 | using System;
8 | using System.Collections.Generic;
9 |
10 | namespace DspSharp.AudioSource
11 | {
12 | public class BufferCompletedEventArgs : EventArgs
13 | {
14 | public BufferCompletedEventArgs(IReadOnlyList inputs, IReadOnlyList outputs)
15 | {
16 | this.Inputs = inputs;
17 | this.Outputs = outputs;
18 | }
19 |
20 | public IReadOnlyList Inputs { get; }
21 | public IReadOnlyList Outputs { get; }
22 | }
23 | }
--------------------------------------------------------------------------------
/DspSharp/AudioSource/BufferCompletedEventHandler.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2017 Jonathan Arweck, see LICENSE.txt for license information
4 | //
5 | // --------------------------------------------------------------------------------------------------------------------
6 |
7 | namespace DspSharp.AudioSource
8 | {
9 | public delegate void BufferCompletedEventHandler(IAudioSource sender, BufferCompletedEventArgs e);
10 | }
--------------------------------------------------------------------------------
/DspSharp/AudioSource/FilterStreamer.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2017 Jonathan Arweck, see LICENSE.txt for license information
4 | //
5 | // --------------------------------------------------------------------------------------------------------------------
6 |
7 | using System;
8 | using System.Collections.Generic;
9 | using DspSharp.Algorithms;
10 | using DspSharp.Filter;
11 |
12 | namespace DspSharp.AudioSource
13 | {
14 | public class FilterStreamer
15 | {
16 | private readonly IFilter _filter;
17 |
18 | public FilterStreamer(IFilter filter)
19 | {
20 | this._filter = filter;
21 | this.StreamEnumerator = filter.Process(this.Stream).GetEnumerator();
22 | }
23 |
24 | private IReadOnlyList CurrentBlock { get; set; }
25 |
26 | private IEnumerable Stream
27 | {
28 | get
29 | {
30 | while (true)
31 | {
32 | foreach (var d in this.CurrentBlock)
33 | {
34 | yield return d;
35 | }
36 | }
37 | // ReSharper disable once IteratorNeverReturns
38 | }
39 | }
40 |
41 | private IEnumerator StreamEnumerator { get; }
42 |
43 | public void InputBlock(IEnumerable block)
44 | {
45 | this.CurrentBlock = block.ToReadOnlyList();
46 | }
47 |
48 | public double[] OutputBlock()
49 | {
50 | if (this.CurrentBlock == null)
51 | throw new InvalidOperationException();
52 |
53 | return this.GetBlock();
54 | }
55 |
56 | public double[] StreamBlock(IEnumerable block)
57 | {
58 | this.InputBlock(block);
59 | return this.GetBlock();
60 | }
61 |
62 | private double[] GetBlock()
63 | {
64 | lock (this.StreamEnumerator)
65 | {
66 | var ret = new double[this.CurrentBlock.Count];
67 |
68 | for (var i = 0; i < this.CurrentBlock.Count; i++)
69 | {
70 | this.StreamEnumerator.MoveNext();
71 | ret[i] = this.StreamEnumerator.Current;
72 | }
73 |
74 | return ret;
75 | }
76 | }
77 | }
78 | }
--------------------------------------------------------------------------------
/DspSharp/AudioSource/IAudioSource.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2017 Jonathan Arweck, see LICENSE.txt for license information
4 | //
5 | // --------------------------------------------------------------------------------------------------------------------
6 |
7 | namespace DspSharp.AudioSource
8 | {
9 | public interface IAudioSource
10 | {
11 | int BlockSize { get; }
12 | event BufferCompletedEventHandler BufferCompleted;
13 | }
14 | }
--------------------------------------------------------------------------------
/DspSharp/Buffers/BufferSwitchEventArgs.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2017 Jonathan Arweck, see LICENSE.txt for license information
4 | //
5 | // --------------------------------------------------------------------------------------------------------------------
6 |
7 | using System;
8 |
9 | namespace DspSharp.Buffers
10 | {
11 | ///
12 | /// Represents event data for a BufferSwitchEvent.
13 | ///
14 | ///
15 | public unsafe class BufferSwitchEventArgs : EventArgs
16 | {
17 | ///
18 | /// Initializes a new instance of the class.
19 | ///
20 | /// The new work buffer after the buffer switch.
21 | /// The new input buffer after the buffer switch.
22 | public BufferSwitchEventArgs(byte* newWorkBuffer, byte* newInputBuffer)
23 | {
24 | this.NewWorkBuffer = newWorkBuffer;
25 | this.NewInputBuffer = newInputBuffer;
26 | }
27 |
28 | ///
29 | /// Gets or sets a value indicating whether the buffer switch operation should be canceled. In that case, the buffers
30 | /// will not be switched; the will continue its operation overwriting the current
31 | /// input block.
32 | ///
33 | public bool Cancel { get; set; }
34 |
35 | ///
36 | /// Gets the new input buffer (after the buffer switch).
37 | ///
38 | public byte* NewInputBuffer { get; }
39 |
40 | ///
41 | /// Gets the new work buffer (after the buffer switch).
42 | ///
43 | public byte* NewWorkBuffer { get; }
44 | }
45 | }
--------------------------------------------------------------------------------
/DspSharp/Buffers/CircularArray.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2017 Jonathan Arweck, see LICENSE.txt for license information
4 | //
5 | // --------------------------------------------------------------------------------------------------------------------
6 |
7 | using System;
8 | using System.Collections.Generic;
9 | using System.Linq;
10 |
11 | namespace DspSharp.Buffers
12 | {
13 | public class CircularArray
14 | {
15 | public CircularArray(IReadOnlyList items)
16 | {
17 | this.Items = items.ToArray();
18 | this.Length = this.Items.Length;
19 | }
20 |
21 | public int Length { get; }
22 |
23 | public int Position { get; private set; }
24 | private T[] Items { get; }
25 |
26 | public T[] GetRange(int count)
27 | {
28 | var ret = new T[count];
29 |
30 | if (count + this.Position < this.Length)
31 | {
32 | Array.Copy(this.Items, this.Position, ret, 0, count);
33 | this.Position += count;
34 | }
35 | else
36 | {
37 | var tmp = this.Length - this.Position;
38 | Array.Copy(this.Items, this.Position, ret, 0, tmp);
39 | this.PeriodCompleted?.Invoke(this, EventArgs.Empty);
40 |
41 | while (count - tmp > this.Length)
42 | {
43 | Array.Copy(this.Items, 0, ret, tmp, this.Length);
44 | tmp += this.Length;
45 | this.PeriodCompleted?.Invoke(this, EventArgs.Empty);
46 | }
47 |
48 | Array.Copy(this.Items, 0, ret, tmp, count - tmp);
49 | this.Position = count - tmp;
50 | }
51 |
52 | return ret;
53 | }
54 |
55 | public T GetValue()
56 | {
57 | var ret = this.Items[this.Position++];
58 |
59 | if (this.Position > this.Items.Length)
60 | {
61 | this.Position -= this.Items.Length;
62 | this.PeriodCompleted?.Invoke(this, EventArgs.Empty);
63 | }
64 |
65 | return ret;
66 | }
67 |
68 | public event EventHandler PeriodCompleted;
69 | }
70 | }
--------------------------------------------------------------------------------
/DspSharp/DspSharp.Interop.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jonarw/DspSharp/f1b987ec1b5c21f572b9a1e409c661925f4d7455/DspSharp/DspSharp.Interop.dll
--------------------------------------------------------------------------------
/DspSharp/DspSharp.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard1.3;net45;net46
5 | True
6 | 0.1.8-pre
7 | Jonathan Arweck
8 |
9 | DspSharp - Digital Audio Signal Processing in C#
10 | © 2017 Jonathan Arweck
11 | https://github.com/Jonarw/DspSharp/blob/dev/LICENSE.txt
12 | https://github.com/Jonarw/DspSharp/
13 | audio signal processing dsp filter fir iir
14 |
15 |
16 |
17 | True
18 | 0.1.8.0
19 | 0.1.8.0
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | DspSharp.Interop.dll
30 |
31 |
32 | PropertyTools.dll
33 |
34 |
35 |
36 |
37 |
38 | true
39 | PreserveNewest
40 |
41 |
42 | true
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/DspSharp/DspSharp.csproj.DotSettings:
--------------------------------------------------------------------------------
1 |
2 | False
3 | True
4 | True
5 | False
6 | True
7 | True
8 | True
9 | True
10 | True
11 | False
--------------------------------------------------------------------------------
/DspSharp/Exceptions/SamplerateMismatchException.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2017 Jonathan Arweck, see LICENSE.txt for license information
4 | //
5 | // --------------------------------------------------------------------------------------------------------------------
6 |
7 | using System;
8 |
9 | namespace DspSharp.Exceptions
10 | {
11 | public class SamplerateMismatchException : Exception
12 | {
13 | }
14 | }
--------------------------------------------------------------------------------
/DspSharp/Extensions/FilterExtensions.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2017 Jonathan Arweck, see LICENSE.txt for license information
4 | //
5 | // --------------------------------------------------------------------------------------------------------------------
6 |
7 | using DspSharp.Algorithms;
8 | using DspSharp.Filter;
9 | using DspSharp.Signal;
10 |
11 | namespace DspSharp.Extensions
12 | {
13 | ///
14 | /// Provides static extension for the IFilter interface.
15 | ///
16 | public static class FilterExtensions
17 | {
18 | ///
19 | /// Computes the impulse response of the filter.
20 | ///
21 | /// The filter.
22 | /// The impulse response.
23 | public static IEnumerableSignal GetImpulseResponse(this IFilter filter)
24 | {
25 | return new EnumerableSignal(filter.Process(1.0.ToEnumerable()), filter.Samplerate);
26 | }
27 |
28 | public static IFilter Chain(this IFilter filter1, IFilter filter2)
29 | {
30 | var set = filter1 as FilterSet;
31 | if (set != null)
32 | set.Filters.Add(filter2);
33 | else
34 | {
35 | set = new FilterSet(filter1.Samplerate);
36 | set.Filters.Add(filter1);
37 | set.Filters.Add(filter2);
38 | }
39 |
40 | return set;
41 | }
42 | }
43 | }
--------------------------------------------------------------------------------
/DspSharp/Extensions/SpectrumExtensions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using DspSharp.Algorithms;
3 | using DspSharp.Spectrum;
4 |
5 | namespace DspSharp.Extensions
6 | {
7 | public static class SpectrumExtensions
8 | {
9 | public static IFftSpectrum Multiply(this IFftSpectrum spectrum1, IFftSpectrum spectrum2)
10 | {
11 | if (spectrum1 == null)
12 | throw new ArgumentNullException(nameof(spectrum1));
13 | if (spectrum2 == null)
14 | throw new ArgumentNullException(nameof(spectrum2));
15 | if (!spectrum1.Frequencies.Equals(spectrum2.Frequencies))
16 | throw new ArgumentException();
17 |
18 | return new FftSpectrum(spectrum1.Frequencies, spectrum1.Values.Multiply(spectrum2.Values).ToReadOnlyList());
19 | }
20 |
21 | public static IFftSpectrum Divide(this IFftSpectrum spectrum1, IFftSpectrum spectrum2)
22 | {
23 | if (spectrum1 == null)
24 | throw new ArgumentNullException(nameof(spectrum1));
25 | if (spectrum2 == null)
26 | throw new ArgumentNullException(nameof(spectrum2));
27 | if (!spectrum1.Frequencies.Equals(spectrum2.Frequencies))
28 | throw new ArgumentException();
29 |
30 | return new FftSpectrum(spectrum1.Frequencies, spectrum1.Values.Divide(spectrum2.Values).ToReadOnlyList());
31 | }
32 | }
33 | }
--------------------------------------------------------------------------------
/DspSharp/Extensions/Utilities.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2017 Jonathan Arweck, see LICENSE.txt for license information
4 | //
5 | // --------------------------------------------------------------------------------------------------------------------
6 |
7 | using System.Collections.Generic;
8 | using System.Linq;
9 |
10 | namespace DspSharp.Extensions
11 | {
12 | public static class Utilities
13 | {
14 | ///
15 | /// Determines whether the collection is null or contains no elements.
16 | ///
17 | /// The IEnumerable type.
18 | /// The enumerable, which may be null or empty.
19 | ///
20 | /// true if the IEnumerable is null or empty; otherwise, false.
21 | ///
22 | public static bool IsNullOrEmpty(this IEnumerable enumerable)
23 | {
24 | if (enumerable == null)
25 | return true;
26 |
27 | var collection = enumerable as ICollection;
28 | if (collection != null)
29 | return collection.Count < 1;
30 |
31 | return !enumerable.Any();
32 | }
33 | }
34 | }
--------------------------------------------------------------------------------
/DspSharp/Filter/ChangeEventHandler.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2017 Jonathan Arweck, see LICENSE.txt for license information
4 | //
5 | // --------------------------------------------------------------------------------------------------------------------
6 |
7 | namespace DspSharp.Filter
8 | {
9 | public delegate void ChangeEventHandler(IFilter sender, FilterChangedEventArgs e);
10 | }
--------------------------------------------------------------------------------
/DspSharp/Filter/FilterChangedEventArgs.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2017 Jonathan Arweck, see LICENSE.txt for license information
4 | //
5 | // --------------------------------------------------------------------------------------------------------------------
6 |
7 | using System;
8 |
9 | namespace DspSharp.Filter
10 | {
11 | public class FilterChangedEventArgs : EventArgs
12 | {
13 | }
14 | }
--------------------------------------------------------------------------------
/DspSharp/Filter/FilterFactory/FilterFactory.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2017 Jonathan Arweck, see LICENSE.txt for license information
4 | //
5 | // --------------------------------------------------------------------------------------------------------------------
6 |
7 | using System;
8 | using DspSharp.Filter.LtiFilters.Fir;
9 | using DspSharp.Filter.LtiFilters.Iir;
10 | using DspSharp.Filter.LtiFilters.Primitive;
11 | using DspSharp.Filter.NonlinearFilters;
12 | using DspSharp.Signal;
13 | using DspSharp.Utilities.Collections;
14 |
15 | namespace DspSharp.Filter
16 | {
17 | ///
18 | /// Provides a static function from creating new filter objects.
19 | ///
20 | public static class FilterFactory
21 | {
22 | ///
23 | /// Creates a new filter object of the specified filter type.
24 | ///
25 | /// The filter type.
26 | /// The samplerate.
27 | /// The available signals for all filters that are based on existing signals.
28 | ///
29 | /// null
30 | public static IFilter CreateFilter(
31 | FilterTypes type,
32 | double samplerate,
33 | IReadOnlyObservableList availableSignals = null)
34 | {
35 | if (type == FilterTypes.Distortion)
36 | return new DistortionFilter(samplerate);
37 |
38 | if (type == FilterTypes.Biquad)
39 | return new BiquadFilter(samplerate);
40 |
41 | if (type == FilterTypes.CustomConvolver)
42 | return new CustomConvolver(samplerate) {AvailableSignals = availableSignals};
43 |
44 | if (type == FilterTypes.Correcting)
45 | return new CorrectingFilter(samplerate);
46 |
47 | if (type == FilterTypes.Delay)
48 | return new DelayFilter(samplerate);
49 |
50 | if (type == FilterTypes.Dirac)
51 | return new DiracFilter(samplerate);
52 |
53 | if (type == FilterTypes.Fir)
54 | return new FirFilter(samplerate);
55 |
56 | if (type == FilterTypes.Gain)
57 | return new GainFilter(samplerate);
58 |
59 | if (type == FilterTypes.Iir)
60 | return new IirFilter(samplerate);
61 |
62 | if (type == FilterTypes.Invert)
63 | return new InvertFilter(samplerate);
64 |
65 | if (type == FilterTypes.Zero)
66 | return new ZeroFilter(samplerate);
67 |
68 | throw new ArgumentOutOfRangeException(nameof(type), type, null);
69 | }
70 | }
71 | }
--------------------------------------------------------------------------------
/DspSharp/Filter/FilterFactory/FilterTypes.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2017 Jonathan Arweck, see LICENSE.txt for license information
4 | //
5 | // --------------------------------------------------------------------------------------------------------------------
6 |
7 | using System.ComponentModel;
8 |
9 | namespace DspSharp.Filter
10 | {
11 | ///
12 | /// Enumerates the available filter types.
13 | ///
14 | public enum FilterTypes
15 | {
16 | [Description("distortion")] Distortion,
17 | [Description("biquad")] Biquad,
18 | [Description("convolver (custom signal)")] CustomConvolver,
19 | [Description("correcting (experimental)")] Correcting,
20 | [Description("delay")] Delay,
21 | [Description("dirac")] Dirac,
22 | [Description("fir highpass/lowpass")] Fir,
23 | [Description("simple gain")] Gain,
24 | [Description("IIR filter with custom coefficients")] Iir,
25 | [Description("inverter")] Invert,
26 | [Description("muter")] Zero
27 | }
28 | }
--------------------------------------------------------------------------------
/DspSharp/Filter/FilterSet.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2017 Jonathan Arweck, see LICENSE.txt for license information
4 | //
5 | // --------------------------------------------------------------------------------------------------------------------
6 |
7 | using System.Collections.Generic;
8 | using System.Collections.Specialized;
9 | using System.Linq;
10 | using DspSharp.Utilities.Collections;
11 |
12 | namespace DspSharp.Filter
13 | {
14 | ///
15 | /// Represents a set of filters which are applied in succession.
16 | ///
17 | ///
18 | public class FilterSet : FilterBase
19 | {
20 | private readonly IObservableList _Filters = new ObservableList();
21 |
22 | ///
23 | /// Initializes a new instance of the class.
24 | ///
25 | /// The samplerate.
26 | public FilterSet(double samplerate) : base(samplerate)
27 | {
28 | this._Filters.CollectionChanged += this.FilterCollectionChanged;
29 | }
30 |
31 | ///
32 | /// Gets the contained filters.
33 | ///
34 | public IList Filters => this._Filters;
35 |
36 | ///
37 | /// Gets a value indicating whether this instance has infinite impulse response.
38 | ///
39 | ///
40 | /// true if this instance has an infinite impulse response; otherwise, false.
41 | ///
42 | public override bool HasInfiniteImpulseResponse => this.Filters.Any(f => f.HasInfiniteImpulseResponse);
43 |
44 | protected override bool HasEffectOverride => this.Filters.Count > 0;
45 |
46 | ///
47 | /// Processes the specified signal.
48 | ///
49 | /// The signal.
50 | ///
51 | /// The processed signal.
52 | ///
53 | public override IEnumerable ProcessOverride(IEnumerable signal)
54 | {
55 | foreach (var filter in this.Filters)
56 | {
57 | signal = filter.Process(signal);
58 | }
59 |
60 | return signal;
61 | }
62 |
63 | private void FilterCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
64 | {
65 | this.RaiseChangedEvent();
66 | }
67 | }
68 | }
--------------------------------------------------------------------------------
/DspSharp/Filter/FiniteFilter.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2017 Jonathan Arweck, see LICENSE.txt for license information
4 | //
5 | // --------------------------------------------------------------------------------------------------------------------
6 |
7 | using System.Collections.Generic;
8 | using DspSharp.Algorithms;
9 |
10 | namespace DspSharp.Filter
11 | {
12 | ///
13 | /// Represents a filter with a finite impulse response.
14 | ///
15 | ///
16 | ///
17 | public abstract class FiniteFilter : FilterBase, IFiniteFilter
18 | {
19 | ///
20 | /// Initializes a new instance of the class.
21 | ///
22 | /// The samplerate.
23 | protected FiniteFilter(double samplerate) : base(samplerate)
24 | {
25 | }
26 |
27 | ///
28 | /// Gets a value indicating whether this instance has infinite impulse response.
29 | ///
30 | ///
31 | /// true if this instance has an infinite impulse response; otherwise, false.
32 | ///
33 | public sealed override bool HasInfiniteImpulseResponse => false;
34 |
35 | public IReadOnlyList Process(IReadOnlyList input)
36 | {
37 | return this.HasEffect ? this.ProcessOverride(input) : input;
38 | }
39 |
40 | ///
41 | /// Processes the specified sequence.
42 | ///
43 | /// The sequence.
44 | ///
45 | public IReadOnlyList ProcessOverride(IReadOnlyList input)
46 | {
47 | return this.ProcessOverride((IEnumerable)input).ToReadOnlyList();
48 | }
49 | }
50 | }
--------------------------------------------------------------------------------
/DspSharp/Filter/FiniteFilterSet.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2017 Jonathan Arweck, see LICENSE.txt for license information
4 | //
5 | // --------------------------------------------------------------------------------------------------------------------
6 |
7 | using System.Collections.Generic;
8 | using System.Collections.Specialized;
9 | using DspSharp.Utilities.Collections;
10 |
11 | namespace DspSharp.Filter
12 | {
13 | ///
14 | /// Represents a set of finite filters which are applied in succession.
15 | ///
16 | ///
17 | public class FiniteFilterSet : FiniteFilter
18 | {
19 | private readonly IObservableList _Filters = new ObservableList();
20 |
21 | public FiniteFilterSet(double samplerate) : base(samplerate)
22 | {
23 | this._Filters.CollectionChanged += this.FilterCollectionChanged;
24 | }
25 |
26 | ///
27 | /// Gets the contained filters.
28 | ///
29 | public IList Filters => this._Filters;
30 |
31 | ///
32 | /// Specifies whether the filter object has an effect or not.
33 | ///
34 | protected override bool HasEffectOverride => this.Filters.Count > 0;
35 |
36 | ///
37 | /// Processes the specified sequence.
38 | ///
39 | /// The sequence.
40 | ///
41 | public override IEnumerable ProcessOverride(IEnumerable input)
42 | {
43 | foreach (var filter in this.Filters)
44 | {
45 | input = filter.Process(input);
46 | }
47 |
48 | return input;
49 | }
50 |
51 | private void FilterCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
52 | {
53 | this.RaiseChangedEvent();
54 | }
55 | }
56 | }
--------------------------------------------------------------------------------
/DspSharp/Filter/IFilter.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2017 Jonathan Arweck, see LICENSE.txt for license information
4 | //
5 | // --------------------------------------------------------------------------------------------------------------------
6 |
7 | using System.Collections.Generic;
8 | using System.ComponentModel;
9 |
10 | namespace DspSharp.Filter
11 | {
12 | ///
13 | /// Describes a digital filter.
14 | ///
15 | ///
16 | public interface IFilter : INotifyPropertyChanged
17 | {
18 | ///
19 | /// Gets a value indicating whether this instance has an infinite impulse response.
20 | ///
21 | bool HasInfiniteImpulseResponse { get; }
22 |
23 | ///
24 | /// Gets the samplerate.
25 | ///
26 | double Samplerate { get; }
27 |
28 | ///
29 | /// Processes the specified input.
30 | ///
31 | /// The input.
32 | IEnumerable Process(IEnumerable input);
33 | }
34 | }
--------------------------------------------------------------------------------
/DspSharp/Filter/IFiniteFilter.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2017 Jonathan Arweck, see LICENSE.txt for license information
4 | //
5 | // --------------------------------------------------------------------------------------------------------------------
6 |
7 | using System.Collections.Generic;
8 |
9 | namespace DspSharp.Filter
10 | {
11 | ///
12 | /// Describes a digital filter with a finite impulse response.
13 | ///
14 | ///
15 | public interface IFiniteFilter : IFilter
16 | {
17 | ///
18 | /// Processes the specified input.
19 | ///
20 | /// The input.
21 | IReadOnlyList Process(IReadOnlyList input);
22 | }
23 | }
--------------------------------------------------------------------------------
/DspSharp/Filter/ISignalBasedFilter.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2017 Jonathan Arweck, see LICENSE.txt for license information
4 | //
5 | // --------------------------------------------------------------------------------------------------------------------
6 |
7 | using DspSharp.Signal;
8 | using DspSharp.Utilities.Collections;
9 |
10 | namespace DspSharp.Filter
11 | {
12 | ///
13 | /// Describes a filter that uses a predefined signal from a list of available signals.
14 | ///
15 | public interface ISignalBasedFilter
16 | {
17 | ///
18 | /// Gets or sets the available signals.
19 | ///
20 | IReadOnlyObservableList AvailableSignals { get; set; }
21 | }
22 | }
--------------------------------------------------------------------------------
/DspSharp/Filter/LtiFilters/Fir/Convolver.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2017 Jonathan Arweck, see LICENSE.txt for license information
4 | //
5 | // --------------------------------------------------------------------------------------------------------------------
6 |
7 | using System.Collections.Generic;
8 | using DspSharp.Algorithms;
9 |
10 | namespace DspSharp.Filter.LtiFilters.Fir
11 | {
12 | ///
13 | /// Base class for all filters that can be described by their impulse response.
14 | ///
15 | ///
16 | public abstract class Convolver : FiniteFilter
17 | {
18 | protected Convolver(double samplerate) : base(samplerate)
19 | {
20 | this.Name = "Convolver";
21 | }
22 |
23 | public abstract IReadOnlyList ImpulseResponse { get; }
24 |
25 | protected override bool HasEffectOverride
26 | {
27 | get
28 | {
29 | if (this.ImpulseResponse == null)
30 | return false;
31 |
32 | return true;
33 | }
34 | }
35 |
36 | public override IEnumerable ProcessOverride(IEnumerable signal)
37 | {
38 | return TimeDomain.Convolve(signal, this.ImpulseResponse);
39 | }
40 | }
41 | }
--------------------------------------------------------------------------------
/DspSharp/Filter/LtiFilters/Iir/CustomIirFilter.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 |
3 | namespace DspSharp.Filter.LtiFilters.Iir
4 | {
5 | public class CustomIirFilter : IirFilter
6 | {
7 | public CustomIirFilter(double samplerate, IEnumerable a, IEnumerable b) : base(samplerate)
8 | {
9 | base.SetCoefficients(a, b);
10 | }
11 |
12 | public CustomIirFilter(double samplerate) : base(samplerate)
13 | {
14 | }
15 |
16 | public new void SetCoefficients(IEnumerable a, IEnumerable b)
17 | {
18 | base.SetCoefficients(a, b);
19 | }
20 | }
21 | }
--------------------------------------------------------------------------------
/DspSharp/Filter/LtiFilters/Primitive/DelayFilter.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2017 Jonathan Arweck, see LICENSE.txt for license information
4 | //
5 | // --------------------------------------------------------------------------------------------------------------------
6 |
7 | using System;
8 | using System.Collections.Generic;
9 | using System.Linq;
10 | using DspSharp.Algorithms;
11 | using PropertyTools.DataAnnotations;
12 |
13 | namespace DspSharp.Filter.LtiFilters.Primitive
14 | {
15 | ///
16 | /// Represents a filter with a constant group delay and no effects otherwise.
17 | ///
18 | public class DelayFilter : FiniteFilter
19 | {
20 | private double _delay;
21 | private int _SampleDelay;
22 |
23 | public DelayFilter(double samplerate) : base(samplerate)
24 | {
25 | this.Name = "delay filter";
26 | }
27 |
28 | ///
29 | /// True if is not 0, false otherwise.
30 | ///
31 | protected override bool HasEffectOverride
32 | {
33 | get
34 | {
35 | if (this.SampleDelay == 0)
36 | return false;
37 | return true;
38 | }
39 | }
40 |
41 | public override IEnumerable ProcessOverride(IEnumerable signal)
42 | {
43 | return SignalGenerators.GetZeros(this.SampleDelay).Concat(signal);
44 | }
45 |
46 | ///
47 | /// Gets or sets the delay of the in integer samples.
48 | ///
49 | [Category("delay")]
50 | [DisplayName("delay in samples")]
51 | public int SampleDelay
52 | {
53 | get { return Convert.ToInt32(this.Delay * this.Samplerate); }
54 | set
55 | {
56 | if (!this.SetField(ref this._SampleDelay, value))
57 | return;
58 |
59 | this.Delay = value / this.Samplerate;
60 | this.RaiseChangedEvent();
61 | }
62 | }
63 |
64 | ///
65 | /// Gets the delay of the in seconds.
66 | ///
67 | [DisplayName("delay in seconds")]
68 | public double Delay
69 | {
70 | get { return this._delay; }
71 | private set { this.SetField(ref this._delay, value); }
72 | }
73 | }
74 | }
--------------------------------------------------------------------------------
/DspSharp/Filter/LtiFilters/Primitive/DiracFilter.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2017 Jonathan Arweck, see LICENSE.txt for license information
4 | //
5 | // --------------------------------------------------------------------------------------------------------------------
6 |
7 | using System.Collections.Generic;
8 |
9 | namespace DspSharp.Filter.LtiFilters.Primitive
10 | {
11 | ///
12 | /// A filter with a transfer function of 1.
13 | ///
14 | public class DiracFilter : FiniteFilter
15 | {
16 | public DiracFilter(double samplerate) : base(samplerate)
17 | {
18 | this.Name = "Dirac Filter";
19 | }
20 |
21 | ///
22 | /// Returns false.
23 | ///
24 | protected override bool HasEffectOverride => false;
25 |
26 | public override IEnumerable ProcessOverride(IEnumerable signal)
27 | {
28 | return signal;
29 | }
30 | }
31 | }
--------------------------------------------------------------------------------
/DspSharp/Filter/LtiFilters/Primitive/GainFilter.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2017 Jonathan Arweck, see LICENSE.txt for license information
4 | //
5 | // --------------------------------------------------------------------------------------------------------------------
6 |
7 | using System.Collections.Generic;
8 | using DspSharp.Algorithms;
9 | using PropertyTools.DataAnnotations;
10 |
11 | namespace DspSharp.Filter.LtiFilters.Primitive
12 | {
13 | ///
14 | /// Represents a filter with a constant gain and no effects otherwise.
15 | ///
16 | public class GainFilter : FiniteFilter
17 | {
18 | private double _Gain = 1;
19 |
20 | public GainFilter(double samplerate) : base(samplerate)
21 | {
22 | this.Name = "Gain Filter";
23 | }
24 |
25 | ///
26 | /// True if is not 1, false otherwise.
27 | ///
28 | protected override bool HasEffectOverride
29 | {
30 | get
31 | {
32 | if (this.Gain == 1)
33 | return false;
34 |
35 | return true;
36 | }
37 | }
38 |
39 | public override IEnumerable ProcessOverride(IEnumerable signal)
40 | {
41 | return signal.Multiply(this.Gain);
42 | }
43 |
44 | ///
45 | /// Gets or sets the linear gain factor of the .
46 | ///
47 | [Category("Gain Filter")]
48 | [DisplayName("Gain")]
49 | public double Gain
50 | {
51 | get { return this._Gain; }
52 | set { this.SetField(ref this._Gain, value); }
53 | }
54 | }
55 | }
--------------------------------------------------------------------------------
/DspSharp/Filter/LtiFilters/Primitive/InvertFilter.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2017 Jonathan Arweck, see LICENSE.txt for license information
4 | //
5 | // --------------------------------------------------------------------------------------------------------------------
6 |
7 | using System.Collections.Generic;
8 | using DspSharp.Algorithms;
9 |
10 | namespace DspSharp.Filter.LtiFilters.Primitive
11 | {
12 | ///
13 | /// A filter with a transfer function of -1.
14 | ///
15 | public class InvertFilter : FiniteFilter
16 | {
17 | public InvertFilter(double samplerate) : base(samplerate)
18 | {
19 | this.Name = "invert filter";
20 | }
21 |
22 | ///
23 | /// Returns true.
24 | ///
25 | protected override bool HasEffectOverride => true;
26 |
27 | public override IEnumerable ProcessOverride(IEnumerable signal)
28 | {
29 | return signal.Negate();
30 | }
31 | }
32 | }
--------------------------------------------------------------------------------
/DspSharp/Filter/LtiFilters/Primitive/ZeroFilter.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2017 Jonathan Arweck, see LICENSE.txt for license information
4 | //
5 | // --------------------------------------------------------------------------------------------------------------------
6 |
7 | using System.Collections.Generic;
8 | using System.Linq;
9 |
10 | namespace DspSharp.Filter.LtiFilters.Primitive
11 | {
12 | ///
13 | /// Represents a filter with a constant gain and no effects otherwise.
14 | ///
15 | public class ZeroFilter : FiniteFilter
16 | {
17 | public ZeroFilter(double samplerate) : base(samplerate)
18 | {
19 | this.Name = "Zero Filter";
20 | }
21 |
22 | ///
23 | /// Returns true.
24 | ///
25 | protected override bool HasEffectOverride => true;
26 |
27 | public override IEnumerable ProcessOverride(IEnumerable signal)
28 | {
29 | return signal.Select(d => 0.0);
30 | }
31 | }
32 | }
--------------------------------------------------------------------------------
/DspSharp/Filter/NonlinearFilters/AwgnFilter.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2017 Jonathan Arweck, see LICENSE.txt for license information
4 | //
5 | // --------------------------------------------------------------------------------------------------------------------
6 |
7 | using System;
8 | using System.Collections.Generic;
9 | using DspSharp.Algorithms;
10 | using PropertyTools.DataAnnotations;
11 |
12 | namespace DspSharp.Filter.NonlinearFilters
13 | {
14 | ///
15 | /// Represents a filter that adds white Gaussian noise to a signal.
16 | ///
17 | ///
18 | public class AwgnFilter : FiniteFilter
19 | {
20 | private double _Sigma;
21 | private double _Variance;
22 |
23 | ///
24 | /// Initializes a new instance of the class.
25 | ///
26 | /// The samplerate.
27 | public AwgnFilter(double samplerate) : base(samplerate)
28 | {
29 | this.Variance = .1;
30 | }
31 |
32 | ///
33 | /// Specifies whether the filter object has an effect or not.
34 | ///
35 | protected override bool HasEffectOverride => true;
36 |
37 | ///
38 | /// Processes the specified sequence.
39 | ///
40 | /// The sequence.
41 | ///
42 | public override IEnumerable ProcessOverride(IEnumerable input)
43 | {
44 | return input.Add(SignalGenerators.WhiteNoise().Multiply(this.Sigma));
45 | }
46 |
47 | [Category("Noise Configuration")]
48 | [DisplayName("Variance")]
49 | public double Variance
50 | {
51 | get { return this._Variance; }
52 | set
53 | {
54 | this.SetField(ref this._Variance, value);
55 | this._Sigma = Math.Sqrt(this.Variance);
56 | this.RaisePropertyChanged(nameof(this.Sigma));
57 | }
58 | }
59 |
60 | [DisplayName("Sigma")]
61 | public double Sigma
62 | {
63 | get { return this._Sigma; }
64 | set
65 | {
66 | this.SetField(ref this._Sigma, value);
67 | this._Variance = Math.Pow(this.Sigma, 2);
68 | this.RaisePropertyChanged(nameof(this.Variance));
69 | }
70 | }
71 | }
72 | }
--------------------------------------------------------------------------------
/DspSharp/Filter/NonlinearFilters/CustomFilter.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2017 Jonathan Arweck, see LICENSE.txt for license information
4 | //
5 | // --------------------------------------------------------------------------------------------------------------------
6 |
7 | using System;
8 | using System.Collections.Generic;
9 |
10 | namespace DspSharp.Filter.NonlinearFilters
11 | {
12 | ///
13 | /// Represents a filter that is based on a custom filter function.
14 | ///
15 | ///
16 | public class CustomFilter : FilterBase
17 | {
18 | ///
19 | /// Initializes a new instance of the class.
20 | ///
21 | /// The samplerate.
22 | /// The filter function.
23 | public CustomFilter(double samplerate, Func, IEnumerable> filterFunction)
24 | : base(samplerate)
25 | {
26 | this.FilterFunction = filterFunction;
27 | }
28 |
29 | ///
30 | /// Gets the filter function.
31 | ///
32 | public Func, IEnumerable> FilterFunction { get; }
33 |
34 | ///
35 | /// Specifies whether the filter object has an effect or not.
36 | ///
37 | protected override bool HasEffectOverride => true;
38 |
39 | ///
40 | /// Processes the specified signal.
41 | ///
42 | /// The signal.
43 | ///
44 | /// The processed signal.
45 | ///
46 | public override IEnumerable ProcessOverride(IEnumerable signal)
47 | {
48 | return this.FilterFunction(signal);
49 | }
50 | }
51 | }
--------------------------------------------------------------------------------
/DspSharp/Filter/NonlinearFilters/CustomFiniteFilter.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2017 Jonathan Arweck, see LICENSE.txt for license information
4 | //
5 | // --------------------------------------------------------------------------------------------------------------------
6 |
7 | using System;
8 | using System.Collections.Generic;
9 |
10 | namespace DspSharp.Filter.NonlinearFilters
11 | {
12 | ///
13 | /// Represents a filter that is based on a custom finite filter function.
14 | ///
15 | ///
16 | public class CustomFiniteFilter : FiniteFilter
17 | {
18 | ///
19 | /// Initializes a new instance of the class.
20 | ///
21 | /// The samplerate.
22 | /// The filter function.
23 | public CustomFiniteFilter(double samplerate, Func, IEnumerable> filterFunction)
24 | : base(samplerate)
25 | {
26 | this.FilterFunction = filterFunction;
27 | }
28 |
29 | ///
30 | /// Gets the filter function.
31 | ///
32 | public Func, IEnumerable> FilterFunction { get; }
33 |
34 | ///
35 | /// Specifies whether the filter object has an effect or not.
36 | ///
37 | protected override bool HasEffectOverride => true;
38 |
39 | ///
40 | /// Processes the specified sequence.
41 | ///
42 | /// The sequence.
43 | ///
44 | public override IEnumerable ProcessOverride(IEnumerable input)
45 | {
46 | return this.FilterFunction(input);
47 | }
48 | }
49 | }
--------------------------------------------------------------------------------
/DspSharp/Filter/NonlinearFilters/DistortionFilter.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2017 Jonathan Arweck, see LICENSE.txt for license information
4 | //
5 | // --------------------------------------------------------------------------------------------------------------------
6 |
7 | using System;
8 | using System.Collections.Generic;
9 | using System.Linq;
10 |
11 | namespace DspSharp.Filter.NonlinearFilters
12 | {
13 | ///
14 | /// Represents a filter with non-linear distortions, useful for testing other algorithms.
15 | ///
16 | ///
17 | public class DistortionFilter : FiniteFilter
18 | {
19 | public DistortionFilter(double samplerate) : base(samplerate)
20 | {
21 | }
22 |
23 | ///
24 | /// Specifies whether the filter object has an effect or not.
25 | ///
26 | protected override bool HasEffectOverride => true;
27 |
28 | ///
29 | /// Processes the override.
30 | ///
31 | /// The signal.
32 | ///
33 | public override IEnumerable ProcessOverride(IEnumerable signal)
34 | {
35 | return signal.Select(d => d < 0 ? -Math.Log(1 - d) : Math.Log(1 + Math.Sqrt(d)) );
36 | }
37 | }
38 | }
--------------------------------------------------------------------------------
/DspSharp/PropertyTools.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jonarw/DspSharp/f1b987ec1b5c21f572b9a1e409c661925f4d7455/DspSharp/PropertyTools.dll
--------------------------------------------------------------------------------
/DspSharp/Series/ConstantSeries.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2017 Jonathan Arweck, see LICENSE.txt for license information
4 | //
5 | // --------------------------------------------------------------------------------------------------------------------
6 |
7 | using DspSharp.Algorithms;
8 |
9 | namespace DspSharp.Series
10 | {
11 | ///
12 | /// Special kind of series that only has one point. Used for constant frequency
13 | /// responses.
14 | ///
15 | public class ConstantSeries : SeriesBase
16 | {
17 | ///
18 | /// Initializes a new instance of the class.
19 | ///
20 | /// The frequency at which the constant value should be evaluated.
21 | public ConstantSeries(double frequency = 1000) : base(frequency.ToEnumerable(), false)
22 | {
23 | this.Frequency = frequency;
24 | }
25 |
26 | ///
27 | /// Gets the frequency at which the constant value should be evaluated.
28 | ///
29 | public double Frequency { get; }
30 |
31 | public override int Length => 1;
32 |
33 | ///
34 | /// Compares the to an other for equality.
35 | ///
36 | /// The other .
37 | /// True if the other object is a not null and a , false otherwise.
38 | public override bool Equals(ISeries other)
39 | {
40 | if (other == null)
41 | return false;
42 | return this.Equals(other as ConstantSeries);
43 | }
44 |
45 | ///
46 | /// Compares the to an other .
47 | ///
48 | /// The other .
49 | /// True if the other is not null, false otherwise.
50 | public bool Equals(ConstantSeries other)
51 | {
52 | if (other == null)
53 | return false;
54 |
55 | if (other.Frequency != this.Frequency)
56 | return false;
57 |
58 | return true;
59 | }
60 |
61 | ///
62 | /// Computes the Hashcode for the .
63 | ///
64 | /// The Hashcode.
65 | public override int GetHashCode()
66 | {
67 | return this.Frequency.GetHashCode();
68 | }
69 | }
70 | }
--------------------------------------------------------------------------------
/DspSharp/Series/ISeries.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2017 Jonathan Arweck, see LICENSE.txt for license information
4 | //
5 | // --------------------------------------------------------------------------------------------------------------------
6 |
7 | using System;
8 | using System.Collections.Generic;
9 |
10 | namespace DspSharp.Series
11 | {
12 | ///
13 | /// Defines methods and properties used to interface a series of values.
14 | ///
15 | public interface ISeries : IEquatable
16 | {
17 | ///
18 | /// True for a logarithmic series.
19 | ///
20 | bool IsLogarithmic { get; }
21 |
22 | int Length { get; }
23 |
24 | IReadOnlyList Values { get; }
25 |
26 | ///
27 | /// Computes the Hashcode for the object.
28 | ///
29 | /// The Hashcode.
30 | int GetHashCode();
31 | }
32 | }
--------------------------------------------------------------------------------
/DspSharp/Series/SeriesBase.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2017 Jonathan Arweck, see LICENSE.txt for license information
4 | //
5 | // --------------------------------------------------------------------------------------------------------------------
6 |
7 | using System.Collections.Generic;
8 | using DspSharp.Algorithms;
9 |
10 | namespace DspSharp.Series
11 | {
12 | public abstract class SeriesBase : ISeries
13 | {
14 | protected SeriesBase(IEnumerable source, bool logarithmic)
15 | {
16 | this.Values = source.ToReadOnlyList();
17 | this.IsLogarithmic = logarithmic;
18 | }
19 |
20 | public abstract bool Equals(ISeries other);
21 |
22 | public bool IsLogarithmic { get; }
23 |
24 | public abstract int Length { get; }
25 |
26 | public IReadOnlyList Values { get; }
27 | }
28 | }
--------------------------------------------------------------------------------
/DspSharp/Series/SeriesUtil.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2017 Jonathan Arweck, see LICENSE.txt for license information
4 | //
5 | // --------------------------------------------------------------------------------------------------------------------
6 |
7 | using System.Linq;
8 |
9 | namespace DspSharp.Series
10 | {
11 | ///
12 | /// Provides methods for operating on objects.
13 | ///
14 | public sealed class SeriesUtil
15 | {
16 | ///
17 | /// Computes the union of two objects, which contains every value in either of the source series
18 | /// exactly once.
19 | ///
20 | /// The first source series.
21 | /// The second source series.
22 | /// A new object containing the result.
23 | public static ISeries Merge(ISeries s1, ISeries s2)
24 | {
25 | if (s1.Equals(s2))
26 | return s1;
27 | var values = s1.Values.Union(s2.Values).OrderBy(m => m);
28 |
29 | return new CustomSeries(values, s1.IsLogarithmic && s2.IsLogarithmic);
30 | }
31 | }
32 | }
--------------------------------------------------------------------------------
/DspSharp/Signal/BaseImplementations/SignalBase.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2017 Jonathan Arweck, see LICENSE.txt for license information
4 | //
5 | // --------------------------------------------------------------------------------------------------------------------
6 |
7 | using System.Collections.Generic;
8 | using DspSharp.Algorithms;
9 | using DspSharp.Utilities;
10 | using PropertyTools.DataAnnotations;
11 |
12 | namespace DspSharp.Signal
13 | {
14 | ///
15 | /// Base class for all signals.
16 | ///
17 | ///
18 | ///
19 | public abstract class SignalBase : ISignal
20 | {
21 | ///
22 | /// Initializes a new instance of the class.
23 | ///
24 | /// The sample rate.
25 | protected SignalBase(double sampleRate)
26 | {
27 | this.SampleRate = sampleRate;
28 | }
29 |
30 | ///
31 | /// Gets a section of the signal in time domain.
32 | ///
33 | /// The start of the section.
34 | /// The length of the section.
35 | ///
36 | /// The specified section.
37 | ///
38 | public abstract IEnumerable GetWindowedSamples(int start, int length);
39 |
40 | public IFiniteSignal GetWindowedSignal(int start, int length)
41 | {
42 | return new FiniteSignal(this.GetWindowedSamples(start, length).ToReadOnlyList(), this.SampleRate);
43 | }
44 |
45 | [Category("general")]
46 | [DisplayName("display name")]
47 | public string DisplayName { get; set; }
48 |
49 | [DisplayName("sample rate")]
50 | public double SampleRate { get; }
51 | }
52 | }
--------------------------------------------------------------------------------
/DspSharp/Signal/BaseImplementations/SyntheticSignal.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2017 Jonathan Arweck, see LICENSE.txt for license information
4 | //
5 | // --------------------------------------------------------------------------------------------------------------------
6 |
7 | using DspSharp.Spectrum;
8 |
9 | namespace DspSharp.Signal
10 | {
11 | ///
12 | /// Represents a digital signal representable in time domain with a known and analytically calculable spectrum.
13 | ///
14 | ///
15 | ///
16 | public abstract class SyntheticSignal : InfiniteSignal, ISyntheticSignal
17 | {
18 | ///
19 | /// Initializes a new instance of the class.
20 | ///
21 | /// The sample function.
22 | /// The sample rate.
23 | protected SyntheticSignal(TimeDomainFunc sampleFunction, double sampleRate) : base(sampleFunction, sampleRate)
24 | {
25 | this.DisplayName = "synthetic signal";
26 | }
27 |
28 | ///
29 | /// Initializes a new instance of the class.
30 | ///
31 | /// The time domain range function.
32 | /// The sample rate.
33 | protected SyntheticSignal(TimeDomainRangeFunc timeDomainFunction, double sampleRate)
34 | : base(timeDomainFunction, sampleRate)
35 | {
36 | this.DisplayName = "synthetic signal";
37 | }
38 |
39 | ///
40 | /// Gets the spectrum.
41 | ///
42 | public abstract ISpectrum Spectrum { get; }
43 | }
44 | }
--------------------------------------------------------------------------------
/DspSharp/Signal/Interfaces/IEnumerableSignal.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2017 Jonathan Arweck, see LICENSE.txt for license information
4 | //
5 | // --------------------------------------------------------------------------------------------------------------------
6 |
7 | using System.Collections.Generic;
8 | using DspSharp.Spectrum;
9 |
10 | namespace DspSharp.Signal
11 | {
12 | ///
13 | /// Describes a digital signal that is representable in time domain with a fixed starting time. The signal can still be
14 | /// infinitely long in the positive direction, but not in the negative direction.
15 | ///
16 | public interface IEnumerableSignal : ISignal
17 | {
18 | ///
19 | /// Gets the signal in time domain.
20 | ///
21 | IEnumerable Signal { get; }
22 |
23 | ///
24 | /// Gets the start time of the signal.
25 | ///
26 | int Start { get; }
27 |
28 | ///
29 | /// Computes the spectrum.
30 | ///
31 | /// Length of the FFT used to compute the spectrum.
32 | /// The spectrum.
33 | IFftSpectrum GetSpectrum(int fftLength);
34 | }
35 | }
--------------------------------------------------------------------------------
/DspSharp/Signal/Interfaces/IFiniteSignal.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2017 Jonathan Arweck, see LICENSE.txt for license information
4 | //
5 | // --------------------------------------------------------------------------------------------------------------------
6 |
7 | using System.Collections.Generic;
8 | using DspSharp.Spectrum;
9 |
10 | namespace DspSharp.Signal
11 | {
12 | ///
13 | /// Describes a digital signal that is representable in time domain with a finite number of time samples.
14 | ///
15 | public interface IFiniteSignal : IEnumerableSignal
16 | {
17 | ///
18 | /// Gets the length.
19 | ///
20 | int Length { get; }
21 |
22 | ///
23 | /// Gets the signal.
24 | ///
25 | new IReadOnlyList Signal { get; }
26 |
27 | ///
28 | /// Gets the spectrum.
29 | ///
30 | IFftSpectrum Spectrum { get; }
31 |
32 | ///
33 | /// Gets the index of the sample following the last sample.
34 | ///
35 | int Stop { get; }
36 |
37 | ///
38 | /// Gets the sample at the specified time.
39 | ///
40 | /// The time.
41 | /// The sample.
42 | double GetSample(int time);
43 | }
44 | }
--------------------------------------------------------------------------------
/DspSharp/Signal/Interfaces/ISignal.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2017 Jonathan Arweck, see LICENSE.txt for license information
4 | //
5 | // --------------------------------------------------------------------------------------------------------------------
6 |
7 | using System.Collections.Generic;
8 |
9 | namespace DspSharp.Signal
10 | {
11 | ///
12 | /// Describes an arbitrary digital signal representable in time domain.
13 | ///
14 | public interface ISignal
15 | {
16 | ///
17 | /// Gets or sets the name.
18 | ///
19 | string DisplayName { get; set; }
20 |
21 | ///
22 | /// Gets the sample rate.
23 | ///
24 | double SampleRate { get; }
25 |
26 | ///
27 | /// Gets a section of the signal in time domain.
28 | ///
29 | /// The start of the section.
30 | /// The length of the section.
31 | /// The specified section.
32 | IEnumerable GetWindowedSamples(int start, int length);
33 |
34 | ///
35 | /// Gets a section of the signal in time domain.
36 | ///
37 | /// The start of the section.
38 | /// The length of the section.
39 | /// The specified section.
40 | IFiniteSignal GetWindowedSignal(int start, int length);
41 | }
42 | }
--------------------------------------------------------------------------------
/DspSharp/Signal/Interfaces/ISyntheticSignal.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2017 Jonathan Arweck, see LICENSE.txt for license information
4 | //
5 | // --------------------------------------------------------------------------------------------------------------------
6 |
7 | using DspSharp.Spectrum;
8 |
9 | namespace DspSharp.Signal
10 | {
11 | ///
12 | /// Describes a digital signal representable in time domain with a known and analytically calculable spectrum.
13 | ///
14 | public interface ISyntheticSignal : ISignal
15 | {
16 | ///
17 | /// Gets the spectrum.
18 | ///
19 | ISpectrum Spectrum { get; }
20 | }
21 | }
--------------------------------------------------------------------------------
/DspSharp/Signal/SignalTypes/Dirac.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2017 Jonathan Arweck, see LICENSE.txt for license information
4 | //
5 | // --------------------------------------------------------------------------------------------------------------------
6 |
7 | using DspSharp.Algorithms;
8 | using PropertyTools.DataAnnotations;
9 |
10 | namespace DspSharp.Signal
11 | {
12 | ///
13 | /// Represents a scaled dirac pulse.
14 | ///
15 | public class Dirac : FiniteSignal
16 | {
17 | ///
18 | /// Initializes a new instance of the class.
19 | ///
20 | /// The sample rate.
21 | /// The gain.
22 | public Dirac(double sampleRate, double gain = 1) : base(new[] {gain}.ToReadOnlyList(), sampleRate)
23 | {
24 | this.Gain = gain;
25 | this.DisplayName = "dirac, gain = " + gain;
26 | }
27 |
28 | [Category("dirac")]
29 | [DisplayName("gain")]
30 | public double Gain { get; }
31 | }
32 | }
--------------------------------------------------------------------------------
/DspSharp/Signal/SignalTypes/IdealHighpass.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2017 Jonathan Arweck, see LICENSE.txt for license information
4 | //
5 | // --------------------------------------------------------------------------------------------------------------------
6 |
7 | using System;
8 | using System.Numerics;
9 | using DspSharp.Algorithms;
10 | using DspSharp.Series;
11 | using DspSharp.Spectrum;
12 | using PropertyTools.DataAnnotations;
13 |
14 | namespace DspSharp.Signal
15 | {
16 | ///
17 | /// Represents an ideal sinc-based highpass.
18 | ///
19 | ///
20 | public class IdealHighpass : SyntheticSignal
21 | {
22 | ///
23 | /// Initializes a new instance of the class.
24 | ///
25 | /// The sample rate.
26 | /// The corner frequency.
27 | ///
28 | public IdealHighpass(double sampleRate, double fc)
29 | : base(time => (time == 0 ? 1.0 : 0.0) - Mathematic.Sinc(2 * fc * time / sampleRate) * (2 * fc / sampleRate), sampleRate
30 | )
31 | {
32 | if ((fc < 0) || (fc > sampleRate / 2))
33 | throw new Exception();
34 |
35 | this.Fc = fc;
36 | var frequencies = new CustomSeries(new[] {0, 20, fc, fc, sampleRate / 2});
37 | this.Spectrum = new Spectrum.Spectrum(frequencies, new Complex[] {0, 0, 0, 1, 1});
38 | this.DisplayName = "ideal highpass, fc = " + fc;
39 | }
40 |
41 | ///
42 | /// Gets the spectrum.
43 | ///
44 | public override ISpectrum Spectrum { get; }
45 |
46 | [Category("ideal highpass")]
47 | [DisplayName("cutoff frequency")]
48 | public double Fc { get; }
49 | }
50 | }
--------------------------------------------------------------------------------
/DspSharp/Signal/SignalTypes/IdealLowpass.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2017 Jonathan Arweck, see LICENSE.txt for license information
4 | //
5 | // --------------------------------------------------------------------------------------------------------------------
6 |
7 | using System;
8 | using System.Numerics;
9 | using DspSharp.Algorithms;
10 | using DspSharp.Series;
11 | using DspSharp.Spectrum;
12 | using PropertyTools.DataAnnotations;
13 |
14 | namespace DspSharp.Signal
15 | {
16 | ///
17 | /// Represents an ideal sinc-based Lowpass.
18 | ///
19 | ///
20 | public class IdealLowpass : SyntheticSignal
21 | {
22 | ///
23 | /// Initializes a new instance of the class.
24 | ///
25 | /// The sample rate.
26 | /// The corner frequency.
27 | ///
28 | public IdealLowpass(double sampleRate, double fc)
29 | : base(time => Mathematic.Sinc(2 * fc * time / sampleRate) * (2 * fc / sampleRate), sampleRate)
30 | {
31 | if ((fc < 0) || (fc > sampleRate / 2))
32 | throw new Exception();
33 |
34 | this.Fc = fc;
35 | var frequencies = new CustomSeries(new[] {0, 20, fc, fc, sampleRate / 2});
36 | this.Spectrum = new Spectrum.Spectrum(frequencies, new Complex[] {1, 1, 1, 0, 0});
37 | this.DisplayName = "ideal lowpass, fc = " + fc;
38 | }
39 |
40 | ///
41 | /// Gets the spectrum.
42 | ///
43 | public override ISpectrum Spectrum { get; }
44 |
45 | [Category("ideal lowpass")]
46 | [DisplayName("cutoff frequency")]
47 | public double Fc { get; }
48 | }
49 | }
--------------------------------------------------------------------------------
/DspSharp/Signal/SignalTypes/LogSweep.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2017 Jonathan Arweck, see LICENSE.txt for license information
4 | //
5 | // --------------------------------------------------------------------------------------------------------------------
6 |
7 | using DspSharp.Algorithms;
8 | using PropertyTools.DataAnnotations;
9 |
10 | namespace DspSharp.Signal
11 | {
12 | ///
13 | /// Represents a logarithmic sine sweep.
14 | ///
15 | public class LogSweep : FiniteSignal
16 | {
17 | ///
18 | /// Initializes a new instance of the Class.
19 | ///
20 | /// The start frequency.
21 | /// The stop frequency.
22 | /// The length in seconds.
23 | /// The samplerate.
24 | public LogSweep(double from, double to, double length, double samplerate)
25 | : base(SignalGenerators.LogSweep(from, to, length, samplerate).ToReadOnlyList(), samplerate)
26 | {
27 | this.From = from;
28 | this.To = to;
29 | this.DisplayName = "logarithmic sweep";
30 | }
31 |
32 | [Category("logarithmic sweep")]
33 | [DisplayName("start frequency")]
34 | public double From { get; }
35 |
36 | [DisplayName("stop frequency")]
37 | public double To { get; }
38 | }
39 | }
--------------------------------------------------------------------------------
/DspSharp/Signal/SignalTypes/Sinc.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2017 Jonathan Arweck, see LICENSE.txt for license information
4 | //
5 | // --------------------------------------------------------------------------------------------------------------------
6 |
7 | using System;
8 | using System.Numerics;
9 | using DspSharp.Algorithms;
10 | using DspSharp.Series;
11 | using DspSharp.Spectrum;
12 | using PropertyTools.DataAnnotations;
13 |
14 | namespace DspSharp.Signal
15 | {
16 | ///
17 | /// Represents a Sinc (sin(pi*x) / (pi*x)) pulse.
18 | ///
19 | ///
20 | public class Sinc : SyntheticSignal
21 | {
22 | ///
23 | /// Initializes a new instance of the class.
24 | ///
25 | /// The sample rate.
26 | /// The frequency.
27 | ///
28 | public Sinc(double sampleRate, double frequency)
29 | : base(time => Mathematic.Sinc(frequency * time / sampleRate), sampleRate)
30 | {
31 | this.Frequency = frequency;
32 | if ((frequency < 0) || (frequency > sampleRate / 2))
33 | throw new Exception();
34 |
35 | var frequencies = new CustomSeries(new[] {0, frequency, frequency, sampleRate / 2});
36 | this.Spectrum = new Spectrum.Spectrum(frequencies, new Complex[] {1 / (2 * frequency), 1 / (2 * frequency), 0, 0});
37 | this.DisplayName = "sinc, f = " + frequency;
38 | }
39 |
40 | ///
41 | /// Gets the spectrum.
42 | ///
43 | public override ISpectrum Spectrum { get; }
44 |
45 | [Category("sinc")]
46 | [DisplayName("frequency")]
47 | public double Frequency { get; }
48 | }
49 | }
--------------------------------------------------------------------------------
/DspSharp/Signal/SignalTypes/Sinus.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2017 Jonathan Arweck, see LICENSE.txt for license information
4 | //
5 | // --------------------------------------------------------------------------------------------------------------------
6 |
7 | using System;
8 | using System.Numerics;
9 | using DspSharp.Series;
10 | using DspSharp.Spectrum;
11 | using PropertyTools.DataAnnotations;
12 |
13 | namespace DspSharp.Signal
14 | {
15 | ///
16 | /// Represents a sine wave.
17 | ///
18 | ///
19 | public class Sinus : SyntheticSignal
20 | {
21 | ///
22 | /// Initializes a new instance of the class.
23 | ///
24 | /// The sample rate.
25 | /// The frequency.
26 | /// The phase offset in radians.
27 | ///
28 | public Sinus(double sampleRate, double frequency, double phaseOffset = 0)
29 | : base(time => Math.Sin(2 * Math.PI * time * frequency / sampleRate + phaseOffset), sampleRate)
30 | {
31 | this.Frequency = frequency;
32 | this.PhaseOffset = phaseOffset;
33 | if ((frequency < 0) || (frequency > sampleRate / 2))
34 | throw new Exception();
35 |
36 | var frequencies = new CustomSeries(new[] {0, frequency, frequency, frequency, sampleRate / 2});
37 | this.Spectrum = new Spectrum.Spectrum(frequencies, new Complex[] {0, 0, double.PositiveInfinity, 0, 0});
38 | this.DisplayName = "sinus, f = " + frequency;
39 | }
40 |
41 | ///
42 | /// Gets the spectrum.
43 | ///
44 | public override ISpectrum Spectrum { get; }
45 |
46 | [Category("sinus")]
47 | [DisplayName("frequency")]
48 | public double Frequency { get; }
49 |
50 | [DisplayName("phase offset")]
51 | public double PhaseOffset { get; }
52 | }
53 | }
--------------------------------------------------------------------------------
/DspSharp/Signal/Windows/WindowModes.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2017 Jonathan Arweck, see LICENSE.txt for license information
4 | //
5 | // --------------------------------------------------------------------------------------------------------------------
6 |
7 | using System.ComponentModel;
8 |
9 | namespace DspSharp.Signal.Windows
10 | {
11 | ///
12 | /// Enumerates the available window modes.
13 | ///
14 | public enum WindowModes
15 | {
16 | ///
17 | /// Symmetric window (starting with 0, then rising towards 1, then declining towards 0)
18 | ///
19 | [Description("symmetric")] Symmetric,
20 |
21 | ///
22 | /// Causal window (starting with 1, then declining).
23 | ///
24 | [Description("causal")] Causal,
25 |
26 | ///
27 | /// Anti-causal window (starting with 0, then rising towards 1)
28 | ///
29 | [Description("anti-causal")] AntiCausal
30 | }
31 | }
--------------------------------------------------------------------------------
/DspSharp/Signal/Windows/WindowTypes.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2017 Jonathan Arweck, see LICENSE.txt for license information
4 | //
5 | // --------------------------------------------------------------------------------------------------------------------
6 |
7 | using System.ComponentModel;
8 |
9 | namespace DspSharp.Signal.Windows
10 | {
11 | ///
12 | /// Enumeration of all supported window types.
13 | ///
14 | public enum WindowTypes
15 | {
16 | ///
17 | /// The rectangular window.
18 | ///
19 | [Description("rectangular")] Rectangular,
20 |
21 | ///
22 | /// The Hann window.
23 | ///
24 | [Description("Hann")] Hann,
25 |
26 | ///
27 | /// The Hamming window.
28 | ///
29 | [Description("Hamming")] Hamming,
30 |
31 | ///
32 | /// The triangular window.
33 | ///
34 | [Description("triangular")] Triangular,
35 |
36 | ///
37 | /// The Welch window.
38 | ///
39 | [Description("Welch")] Welch,
40 |
41 | ///
42 | /// The Blackman window.
43 | ///
44 | [Description("Blackman")] Blackman,
45 |
46 | ///
47 | /// The Blackman-Harris window.
48 | ///
49 | [Description("Blackman-Harris")] BlackmanHarris,
50 |
51 | ///
52 | /// The Kaiser window with alpha=2.
53 | ///
54 | [Description("Kaiser, alpha = 2")] KaiserAlpha2,
55 |
56 | ///
57 | /// The Kaiser window with alpha=3.
58 | ///
59 | [Description("Kaiser, alpha = 3")] KaiserAlpha3
60 | }
61 | }
--------------------------------------------------------------------------------
/DspSharp/Spectrum/IFftSpectrum.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2017 Jonathan Arweck, see LICENSE.txt for license information
4 | //
5 | // --------------------------------------------------------------------------------------------------------------------
6 |
7 | using System.Collections.Generic;
8 | using DspSharp.Series;
9 |
10 | namespace DspSharp.Spectrum
11 | {
12 | public interface IFftSpectrum : ISpectrum
13 | {
14 | new FftSeries Frequencies { get; }
15 | IReadOnlyList GetTimeDomainSignal();
16 | }
17 | }
--------------------------------------------------------------------------------
/DspSharp/Spectrum/ISpectrum.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2017 Jonathan Arweck, see LICENSE.txt for license information
4 | //
5 | // --------------------------------------------------------------------------------------------------------------------
6 |
7 | using System.Collections.Generic;
8 | using System.Numerics;
9 | using DspSharp.Series;
10 |
11 | namespace DspSharp.Spectrum
12 | {
13 | ///
14 | /// Describes the spectrum of a digital signal.
15 | ///
16 | public interface ISpectrum
17 | {
18 | ///
19 | /// Gets the frequencies where the spectrum is defined.
20 | ///
21 | ISeries Frequencies { get; }
22 |
23 | ///
24 | /// Gets the group delay.
25 | ///
26 | IReadOnlyList GroupDelay { get; }
27 |
28 | ///
29 | /// Gets the magnitude.
30 | ///
31 | IReadOnlyList Magnitude { get; }
32 |
33 | ///
34 | /// Gets the phase.
35 | ///
36 | IReadOnlyList Phase { get; }
37 |
38 | ///
39 | /// Gets the complex values.
40 | ///
41 | IReadOnlyList Values { get; }
42 |
43 | ///
44 | /// Gets the value at the specified frequency.
45 | ///
46 | /// The frequency.
47 | ///
48 | Complex GetValue(double frequency);
49 | }
50 | }
--------------------------------------------------------------------------------
/DspSharp/Utilities/Collections/Extensions.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Linq;
3 |
4 | namespace DspSharp.Utilities.Collections
5 | {
6 | public static class Extensions
7 | {
8 | private static readonly IDictionary> OfTypeDictionary =
9 | new Dictionary>();
10 |
11 | public static int IndexOf(this IEnumerable enumerable, T element, IEqualityComparer comparer = null)
12 | {
13 | int i = 0;
14 | comparer = comparer ?? EqualityComparer.Default;
15 | foreach (var currentElement in enumerable)
16 | {
17 | if (comparer.Equals(currentElement, element))
18 | return i;
19 |
20 | i++;
21 | }
22 |
23 | return -1;
24 | }
25 |
26 | public static IObservableList OfTypeObservable(this IObservableList source)
27 | {
28 | IList typelist;
29 | if (OfTypeDictionary.ContainsKey(source))
30 | typelist = OfTypeDictionary[source];
31 | else
32 | {
33 | typelist = new List();
34 | OfTypeDictionary.Add(source, typelist);
35 | }
36 |
37 | var list = typelist.OfType>().FirstOrDefault();
38 | if (list != null)
39 | return list;
40 |
41 | var ret = new ObservableList();
42 | source.CollectionChanged += (sender, e) => ret.Reset(source.OfType());
43 | ret.Reset(source.OfType());
44 | typelist.Add(ret);
45 | return ret;
46 | }
47 |
48 | public static IReadOnlyObservableList ToReadOnlyObservableList(this IObservableList input)
49 | {
50 | return new ReadOnlyObservableList(input);
51 | }
52 | }
53 | }
--------------------------------------------------------------------------------
/DspSharp/Utilities/Collections/IObservableList.cs:
--------------------------------------------------------------------------------
1 | using System.Collections;
2 | using System.Collections.Generic;
3 | using System.Collections.Specialized;
4 | using System.ComponentModel;
5 |
6 | namespace DspSharp.Utilities.Collections
7 | {
8 | public interface IObservableList : IList, INotifyCollectionChanged, INotifyPropertyChanged
9 | {
10 | }
11 |
12 | ///
13 | /// Describes an observable list.
14 | ///
15 | ///
16 | ///
17 | ///
18 | ///
19 | public interface IObservableList : IList, INotifyPropertyChanged, INotifyCollectionChanged
20 | {
21 | ///
22 | /// Adds the range of specified items.
23 | ///
24 | /// The items.
25 | void AddRange(IEnumerable items);
26 |
27 | ///
28 | /// Occurs when a property of an item in the collection has changed.
29 | ///
30 | event PropertyChangedEventHandler ItemPropertyChanged;
31 |
32 | ///
33 | /// Moves an item to the specified index.
34 | ///
35 | /// The item.
36 | /// The new index of the item after moving.
37 | void MoveItem(T item, int newIndex);
38 |
39 | ///
40 | /// Removes the range of specified items.
41 | ///
42 | /// The items.
43 | void RemoveRange(IEnumerable items);
44 |
45 | ///
46 | /// Resets the the list with the specified new items.
47 | ///
48 | /// The new items.
49 | void Reset(IEnumerable newItems);
50 | }
51 | }
--------------------------------------------------------------------------------
/DspSharp/Utilities/Collections/IReadOnlyObservableList.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Collections.Specialized;
3 | using System.ComponentModel;
4 |
5 | namespace DspSharp.Utilities.Collections
6 | {
7 | public interface IReadOnlyObservableList : IReadOnlyList, INotifyPropertyChanged, INotifyCollectionChanged
8 | {
9 | ///
10 | /// Occurs when a property of an item in the collection has changed.
11 | ///
12 | event PropertyChangedEventHandler ItemPropertyChanged;
13 | }
14 | }
--------------------------------------------------------------------------------
/DspSharp/Utilities/Collections/ISortedObservableList.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace DspSharp.Utilities.Collections
5 | {
6 | public interface ISortedObservableList : IObservableList
7 | {
8 | IComparer Comparer { get; }
9 | Func KeyFunction { get; }
10 | //void Remove(TValue item);
11 | //void Add(TValue item);
12 | //void AddRange(IEnumerable items);
13 | //void RemoveRange(IEnumerable items);
14 | //void Reset(IEnumerable items);
15 | //void Clear();
16 | }
17 | }
--------------------------------------------------------------------------------
/DspSharp/Utilities/Collections/ReadOnlyObservableList.cs:
--------------------------------------------------------------------------------
1 | using System.Collections;
2 | using System.Collections.Generic;
3 | using System.Collections.Specialized;
4 | using System.ComponentModel;
5 |
6 | namespace DspSharp.Utilities.Collections
7 | {
8 | public class ReadOnlyObservableList : IReadOnlyObservableList
9 | {
10 | public ReadOnlyObservableList(IObservableList list)
11 | {
12 | this.List = list;
13 | }
14 |
15 | private IObservableList List { get; }
16 |
17 | IEnumerator IEnumerable.GetEnumerator()
18 | {
19 | return ((IEnumerable)this.List).GetEnumerator();
20 | }
21 |
22 | public IEnumerator GetEnumerator()
23 | {
24 | return this.List.GetEnumerator();
25 | }
26 |
27 | public event NotifyCollectionChangedEventHandler CollectionChanged
28 | {
29 | add => this.List.CollectionChanged += value;
30 | remove => this.List.CollectionChanged -= value;
31 | }
32 |
33 | public event PropertyChangedEventHandler PropertyChanged
34 | {
35 | add => this.List.PropertyChanged += value;
36 | remove => this.List.PropertyChanged -= value;
37 | }
38 |
39 | public int Count => this.List.Count;
40 |
41 | public T this[int index] => this.List[index];
42 |
43 | public event PropertyChangedEventHandler ItemPropertyChanged
44 | {
45 | add => this.List.ItemPropertyChanged += value;
46 | remove => this.List.ItemPropertyChanged -= value;
47 | }
48 | }
49 | }
--------------------------------------------------------------------------------
/DspSharpAsio/Asio64Bit.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2017 NAudio contributors, see LICENSE.txt for license information
4 | //
5 | // --------------------------------------------------------------------------------------------------------------------
6 |
7 | using System.Runtime.InteropServices;
8 |
9 | namespace DspSharpAsio
10 | {
11 | ///
12 | /// ASIO 64 bit value
13 | /// Unfortunately the ASIO API was implemented it before compiler supported consistently 64 bit
14 | /// integer types. By using the structure the data layout on a little-endian system like the
15 | /// Intel x86 architecture will result in a "non native" storage of the 64 bit data. The most
16 | /// significant 32 bit are stored first in memory, the least significant bits are stored in the
17 | /// higher memory space. However each 32 bit is stored in the native little-endian fashion
18 | ///
19 | [StructLayout(LayoutKind.Sequential, Pack = 4)]
20 | public struct Asio64Bit
21 | {
22 | ///
23 | /// most significant bits (Bits 32..63)
24 | ///
25 | public uint hi;
26 |
27 | ///
28 | /// least significant bits (Bits 0..31)
29 | ///
30 | public uint lo;
31 |
32 | // TODO: IMPLEMENT AN EASY WAY TO CONVERT THIS TO double AND long
33 | }
34 | }
--------------------------------------------------------------------------------
/DspSharpAsio/AsioChannelInfo.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2017 NAudio contributors, see LICENSE.txt for license information
4 | //
5 | // --------------------------------------------------------------------------------------------------------------------
6 |
7 | using System.Runtime.InteropServices;
8 |
9 | namespace DspSharpAsio
10 | {
11 | ///
12 | /// ASIO Channel Info
13 | ///
14 | [StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Ansi)]
15 | public struct AsioChannelInfo
16 | {
17 | ///
18 | /// on input, channel index
19 | ///
20 | public int channel;
21 |
22 | ///
23 | /// Is Input
24 | ///
25 | public bool isInput;
26 |
27 | ///
28 | /// Is Active
29 | ///
30 | public bool isActive;
31 |
32 | ///
33 | /// Channel Info
34 | ///
35 | public int channelGroup;
36 |
37 | ///
38 | /// ASIO Sample Type
39 | ///
40 | [MarshalAs(UnmanagedType.U4)] public AsioSampleType type;
41 |
42 | ///
43 | /// Name
44 | ///
45 | [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] public string name;
46 | }
47 | }
--------------------------------------------------------------------------------
/DspSharpAsio/AsioDriverCapability.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2017 NAudio contributors, see LICENSE.txt for license information
4 | //
5 | // --------------------------------------------------------------------------------------------------------------------
6 |
7 | namespace DspSharpAsio
8 | {
9 | ///
10 | /// ASIODriverCapability holds all the information from the AsioDriver.
11 | /// Use ASIODriverExt to get the Capabilities
12 | ///
13 | public class AsioDriverCapability
14 | {
15 | ///
16 | /// Buffer Granularity
17 | ///
18 | public int BufferGranularity;
19 |
20 | ///
21 | /// Buffer Maximum Size
22 | ///
23 | public int BufferMaxSize;
24 |
25 | ///
26 | /// Buffer Minimum Size
27 | ///
28 | public int BufferMinSize;
29 |
30 | ///
31 | /// Buffer Preferred Size
32 | ///
33 | public int BufferPreferredSize;
34 |
35 | ///
36 | /// Drive Name
37 | ///
38 | public string DriverName;
39 |
40 | ///
41 | /// Input Channel Info
42 | ///
43 | public AsioChannelInfo[] InputChannelInfos;
44 |
45 | ///
46 | /// Input Latency
47 | ///
48 | public int InputLatency;
49 |
50 | ///
51 | /// Number of Input Channels
52 | ///
53 | public int NbInputChannels;
54 |
55 | ///
56 | /// Number of Output Channels
57 | ///
58 | public int NbOutputChannels;
59 |
60 | ///
61 | /// Output Channel Info
62 | ///
63 | public AsioChannelInfo[] OutputChannelInfos;
64 |
65 | ///
66 | /// Output Latency
67 | ///
68 | public int OutputLatency;
69 |
70 | ///
71 | /// Sample Rate
72 | ///
73 | public double SampleRate;
74 | }
75 | }
--------------------------------------------------------------------------------
/DspSharpAsio/AsioDriverExt.cd:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 | AABARDAAUGAAAAADCAACAAACYAhBgAIQIACACAAAAAE=
28 | ASIODriverExt.cs
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/DspSharpAsio/AsioError.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2017 NAudio contributors, see LICENSE.txt for license information
4 | //
5 | // --------------------------------------------------------------------------------------------------------------------
6 |
7 | namespace DspSharpAsio
8 | {
9 | ///
10 | /// ASIO Error Codes
11 | ///
12 | public enum AsioError
13 | {
14 | ///
15 | /// This value will be returned whenever the call succeeded
16 | ///
17 | ASE_OK = 0,
18 |
19 | ///
20 | /// unique success return value for ASIOFuture calls
21 | ///
22 | ASE_SUCCESS = 0x3f4847a0,
23 |
24 | ///
25 | /// hardware input or output is not present or available
26 | ///
27 | ASE_NotPresent = -1000,
28 |
29 | ///
30 | /// hardware is malfunctioning (can be returned by any ASIO function)
31 | ///
32 | ASE_HWMalfunction,
33 |
34 | ///
35 | /// input parameter invalid
36 | ///
37 | ASE_InvalidParameter,
38 |
39 | ///
40 | /// hardware is in a bad mode or used in a bad mode
41 | ///
42 | ASE_InvalidMode,
43 |
44 | ///
45 | /// hardware is not running when sample position is inquired
46 | ///
47 | ASE_SPNotAdvancing,
48 |
49 | ///
50 | /// sample clock or rate cannot be determined or is not present
51 | ///
52 | ASE_NoClock,
53 |
54 | ///
55 | /// not enough memory for completing the request
56 | ///
57 | ASE_NoMemory
58 | }
59 | }
--------------------------------------------------------------------------------
/DspSharpAsio/AsioFillBufferCallback.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2017 NAudio contributors, see LICENSE.txt for license information
4 | //
5 | // --------------------------------------------------------------------------------------------------------------------
6 |
7 | using System;
8 |
9 | namespace DspSharpAsio
10 | {
11 | ///
12 | /// Callback used by the AsioDriverExt to get wave data
13 | ///
14 | public delegate void AsioFillBufferCallback(IntPtr[] inputChannels, IntPtr[] outputChannels);
15 | }
--------------------------------------------------------------------------------
/DspSharpAsio/AsioMessageSelector.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2017 NAudio contributors, see LICENSE.txt for license information
4 | //
5 | // --------------------------------------------------------------------------------------------------------------------
6 |
7 | namespace DspSharpAsio
8 | {
9 | ///
10 | /// ASIO Message Selector
11 | ///
12 | public enum AsioMessageSelector
13 | {
14 | ///
15 | /// selector in <value>, returns 1L if supported,
16 | ///
17 | kAsioSelectorSupported = 1,
18 |
19 | ///
20 | /// returns engine (host) asio implementation version,
21 | ///
22 | kAsioEngineVersion,
23 |
24 | ///
25 | /// request driver reset. if accepted, this
26 | ///
27 | kAsioResetRequest,
28 |
29 | ///
30 | /// not yet supported, will currently always return 0L.
31 | ///
32 | kAsioBufferSizeChange,
33 |
34 | ///
35 | /// the driver went out of sync, such that
36 | ///
37 | kAsioResyncRequest,
38 |
39 | ///
40 | /// the drivers latencies have changed. The engine
41 | ///
42 | kAsioLatenciesChanged,
43 |
44 | ///
45 | /// if host returns true here, it will expect the
46 | ///
47 | kAsioSupportsTimeInfo,
48 |
49 | ///
50 | /// supports timecode
51 | ///
52 | kAsioSupportsTimeCode,
53 |
54 | ///
55 | /// unused - value: number of commands, message points to mmc commands
56 | ///
57 | kAsioMMCCommand,
58 |
59 | ///
60 | /// kAsioSupportsXXX return 1 if host supports this
61 | ///
62 | kAsioSupportsInputMonitor,
63 |
64 | ///
65 | /// unused and undefined
66 | ///
67 | kAsioSupportsInputGain,
68 |
69 | ///
70 | /// unused and undefined
71 | ///
72 | kAsioSupportsInputMeter,
73 |
74 | ///
75 | /// unused and undefined
76 | ///
77 | kAsioSupportsOutputGain,
78 |
79 | ///
80 | /// unused and undefined
81 | ///
82 | kAsioSupportsOutputMeter,
83 |
84 | ///
85 | /// driver detected an overload
86 | ///
87 | kAsioOverload
88 | }
89 | }
--------------------------------------------------------------------------------
/DspSharpAsio/DspSharpAsio.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net45;net46
5 | True
6 | 0.1.0-pre
7 | Jonathan Arweck
8 |
9 | DspSharpAsio - ASIO Support for DspSharp
10 | © 2017 Jonathan Arweck
11 | https://github.com/Jonarw/DspSharp/blob/dev/LICENSE.txt
12 | https://github.com/Jonarw/DspSharp/
13 | audio signal processing dsp filter fir iir asio
14 |
15 |
16 |
17 | True
18 | 0.1.0.0
19 | 0.1.0.0
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/DspSharpAsio/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2017 Jonathan Arweck, see LICENSE.txt for license information
4 | //
5 | // --------------------------------------------------------------------------------------------------------------------
6 |
7 | using System.Runtime.InteropServices;
8 |
9 | // Setting ComVisible to false makes the types in this assembly not visible
10 | // to COM components. If you need to access a type in this assembly from
11 | // COM, set the ComVisible attribute to true on that type.
12 |
13 | [assembly: ComVisible(false)]
14 |
15 | // The following GUID is for the ID of the typelib if this project is exposed to COM
16 |
17 | [assembly: Guid("8420c3e2-ca65-44a1-bbc7-f259751fae9c")]
18 |
19 |
--------------------------------------------------------------------------------
/DspSharpAsio/SampleTypeConverter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace DspSharpAsio
5 | {
6 | public static class AsioSampleTypeExtensions
7 | {
8 | public static int GetSize(this AsioSampleType sampleType)
9 | {
10 | return SampleTypeConverter.SizeOf(sampleType);
11 | }
12 | }
13 |
14 | public static unsafe class SampleTypeConverter
15 | {
16 | public static IReadOnlyList SupportedSampleFormats { get; } =
17 | new List {AsioSampleType.Int32LSB, AsioSampleType.Float32LSB}.AsReadOnly();
18 |
19 | public static int SizeOf(AsioSampleType sampleType)
20 | {
21 | if (sampleType == AsioSampleType.Int32LSB)
22 | return sizeof(int);
23 | if (sampleType == AsioSampleType.Float32LSB)
24 | return sizeof(float);
25 |
26 | throw new NotSupportedException();
27 | }
28 |
29 | public static void ConvertFrom(AsioSampleType sampleType, void* input, double* output, int length)
30 | {
31 | if (sampleType == AsioSampleType.Int32LSB)
32 | {
33 | var intinput = (int*)input;
34 |
35 | for (int i = 0; i < length; i++)
36 | {
37 | *(output + i) = *(intinput + i) / 2147483648d;
38 | }
39 | }
40 | else if (sampleType == AsioSampleType.Float32LSB)
41 | {
42 | var floatinput = (float*)input;
43 |
44 | for (int i = 0; i < length; i++)
45 | {
46 | output[i] = floatinput[i];
47 | }
48 | }
49 | else
50 | throw new NotSupportedException();
51 |
52 | }
53 |
54 | public static void ConvertTo(AsioSampleType sampleType, double* input, void* output, int length)
55 | {
56 | if (sampleType == AsioSampleType.Int32LSB)
57 | {
58 | var intoutput = (int*)output;
59 |
60 | for (int i = 0; i < length; i++)
61 | {
62 | *(intoutput + i) = (int)(Math.Max(Math.Min(*(input + i), 8388607.0d / 8388608.0d), -1) * 2147483648d);
63 | }
64 | }
65 | else if (sampleType == AsioSampleType.Float32LSB)
66 | {
67 | var floatoutput = (float*)output;
68 |
69 | for (int i = 0; i < length; i++)
70 | {
71 | floatoutput[i] = (float)input[i];
72 | }
73 | }
74 | else
75 | throw new NotSupportedException();
76 |
77 | }
78 | }
79 | }
--------------------------------------------------------------------------------
/DspSharpDemo/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/DspSharpDemo/App.xaml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/DspSharpDemo/App.xaml.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2017 Jonathan Arweck, see LICENSE.txt for license information
4 | //
5 | // --------------------------------------------------------------------------------------------------------------------
6 |
7 | using System.Windows;
8 |
9 | namespace DspSharpDemo
10 | {
11 | ///
12 | /// Interaction logic for App.xaml
13 | ///
14 | public partial class App : Application
15 | {
16 | }
17 | }
--------------------------------------------------------------------------------
/DspSharpDemo/EnumCombo.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2017 Jonathan Arweck, see LICENSE.txt for license information
4 | //
5 | // --------------------------------------------------------------------------------------------------------------------
6 |
7 | using System;
8 | using System.Linq;
9 | using System.Windows;
10 | using System.Windows.Controls;
11 |
12 | namespace DspSharpDemo
13 | {
14 | ///
15 | /// Enhanced ComboBox for displaying quantities in various units.
16 | ///
17 | ///
18 | public class EnumCombo : ComboBox
19 | {
20 | ///
21 | /// The value property.
22 | ///
23 | public static readonly DependencyProperty EnumProperty = DependencyProperty.Register(
24 | "Enum",
25 | typeof(Type),
26 | typeof(EnumCombo),
27 | new FrameworkPropertyMetadata(
28 | null,
29 | FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
30 | EnumPropertyChanged));
31 |
32 | ///
33 | /// Gets the available units.
34 | ///
35 | public Type Enum
36 | {
37 | get { return (Type)this.GetValue(EnumProperty); }
38 | set { this.SetValue(EnumProperty, value); }
39 | }
40 |
41 | private static void EnumPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
42 | {
43 | var ec = (EnumCombo)d;
44 | var value = (Type)e.NewValue;
45 | if (value == null)
46 | {
47 | ec.ItemsSource = Enumerable.Empty();
48 | return;
49 | }
50 |
51 | ec.ItemsSource = System.Enum.GetValues(value).Cast().Select(en => new EnumItem(EnumToStringConverter.GetEnumDescription(en), en));
52 | ec.DisplayMemberPath = "DisplayName";
53 | ec.SelectedValuePath = "Enum";
54 | }
55 |
56 | public struct EnumItem
57 | {
58 | public EnumItem(string displayName, Enum @enum)
59 | {
60 | this.DisplayName = displayName;
61 | this.Enum = @enum;
62 | }
63 |
64 | public string DisplayName { get; }
65 | public Enum Enum { get; }
66 | }
67 | }
68 | }
--------------------------------------------------------------------------------
/DspSharpDemo/EnumToStringConverter.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2017 Jonathan Arweck, see LICENSE.txt for license information
4 | //
5 | // --------------------------------------------------------------------------------------------------------------------
6 |
7 | using System;
8 | using System.ComponentModel;
9 | using System.Globalization;
10 | using System.Linq;
11 | using System.Reflection;
12 | using DspSharp.Algorithms;
13 |
14 | namespace DspSharpDemo
15 | {
16 | public class EnumToStringConverter : TypeConverter
17 | {
18 | public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
19 | {
20 | return sourceType == typeof(Enum);
21 | }
22 |
23 | public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
24 | {
25 | return destinationType == typeof(string);
26 | }
27 |
28 | public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
29 | {
30 | if (!(destinationType == typeof(string)))
31 | throw new ArgumentException("Can only convert to string.", nameof(destinationType));
32 |
33 | if (!value.GetType().IsEnum)
34 | throw new ArgumentException("Can only convert an instance of Enum.", nameof(value));
35 |
36 | return GetEnumDescription((Enum)value);
37 | }
38 |
39 | public static string GetEnumDescription(Enum value)
40 | {
41 | FieldInfo fi = value.GetType().GetField(value.ToString());
42 |
43 | var attributes = fi.GetCustomAttributes(false);
44 | var d1 = attributes.OfType().ToReadOnlyList();
45 |
46 | if (d1.Count > 0)
47 | return d1[0].Description;
48 |
49 | var d2 = attributes.OfType().ToReadOnlyList();
50 |
51 | if (d2.Count > 0)
52 | return d2[0].Description;
53 |
54 | return value.ToString();
55 | }
56 | }
57 | }
--------------------------------------------------------------------------------
/DspSharpDemo/IListItemConverter.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2017 Jonathan Arweck, see LICENSE.txt for license information
4 | //
5 | // --------------------------------------------------------------------------------------------------------------------
6 |
7 | namespace DspSharpDemo
8 | {
9 | ///
10 | /// Converts items in the Master list to Items in the target list, and back again.
11 | ///
12 | public interface IListItemConverter
13 | {
14 | ///
15 | /// Converts the specified master list item.
16 | ///
17 | /// The master list item.
18 | /// The result of the conversion.
19 | object Convert(object masterListItem);
20 |
21 | ///
22 | /// Converts the specified target list item.
23 | ///
24 | /// The target list item.
25 | /// The result of the conversion.
26 | object ConvertBack(object targetListItem);
27 | }
28 | }
--------------------------------------------------------------------------------
/DspSharpDemo/LocalPropertyGridControlFactory.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2017 Jonathan Arweck, see LICENSE.txt for license information
4 | //
5 | // --------------------------------------------------------------------------------------------------------------------
6 |
7 | using System.Collections.ObjectModel;
8 | using System.Windows;
9 | using System.Windows.Controls;
10 | using System.Windows.Controls.Primitives;
11 | using System.Windows.Input;
12 | using PropertyTools.Wpf;
13 |
14 | namespace DspSharpDemo
15 | {
16 | ///
17 | /// Slightly adapted PropertyControlFactory that creates appropriate controls for enums.
18 | ///
19 | public class LocalPropertyGridControlFactory : PropertyGridControlFactory
20 | {
21 | public override FrameworkElement CreateControl(PropertyItem pi, PropertyControlFactoryOptions options)
22 | {
23 | if ((pi.ItemsSourceDescriptor != null) || (pi.ItemsSource != null))
24 | return this.CreateComboBoxControl(pi);
25 |
26 | if (pi.Is(typeof(Collection)))
27 | return this.CreateListControl(pi);
28 |
29 | if (pi.Is(typeof(ICommand)))
30 | return this.CreateCommandControl(pi);
31 |
32 | return base.CreateControl(pi, options);
33 | }
34 |
35 | protected virtual FrameworkElement CreateCommandControl(PropertyItem property)
36 | {
37 | var c = new Button();
38 | c.SetBinding(ButtonBase.CommandProperty, property.CreateBinding());
39 | return c;
40 | }
41 |
42 | protected override FrameworkElement CreateEnumControl(PropertyItem property, PropertyControlFactoryOptions options)
43 | {
44 | var enumType = TypeHelper.GetEnumType(property.Descriptor.PropertyType);
45 |
46 | var c = new EnumCombo {Enum = enumType};
47 | c.SetBinding(Selector.SelectedValueProperty, property.CreateBinding());
48 | return c;
49 | }
50 |
51 | protected virtual FrameworkElement CreateListControl(PropertyItem property)
52 | {
53 | var c = new ListBox();
54 | c.SetBinding(ItemsControl.ItemsSourceProperty, property.CreateBinding());
55 | return c;
56 | }
57 | }
58 | }
--------------------------------------------------------------------------------
/DspSharpDemo/MainWindow.xaml.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2017 Jonathan Arweck, see LICENSE.txt for license information
4 | //
5 | // --------------------------------------------------------------------------------------------------------------------
6 |
7 | using System.Windows;
8 |
9 | namespace DspSharpDemo
10 | {
11 | ///
12 | /// Interaction logic for MainWindow.xaml
13 | ///
14 | public partial class MainWindow : Window
15 | {
16 | public MainWindow()
17 | {
18 | this.InitializeComponent();
19 | }
20 | }
21 | }
--------------------------------------------------------------------------------
/DspSharpDemo/PerformanceHelper.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2017 Jonathan Arweck, see LICENSE.txt for license information
4 | //
5 | // --------------------------------------------------------------------------------------------------------------------
6 |
7 | using System;
8 | using System.Diagnostics;
9 | using System.Threading;
10 |
11 | namespace DspSharpDemo
12 | {
13 | public static class PerformanceHelper
14 | {
15 | public static void Bench(Action func, double benchtime = 1000, bool silentmode = false, string description = "")
16 | {
17 | int iterations = 1;
18 | double elapsed;
19 |
20 | while ((elapsed = Profile(iterations, func).TotalMilliseconds) < benchtime * 0.1)
21 | {
22 | iterations *= 10;
23 | }
24 |
25 | iterations = Convert.ToInt32(iterations * benchtime / elapsed);
26 |
27 | double timeperaction = Profile(iterations, func).TotalMilliseconds / iterations;
28 |
29 | if (!silentmode)
30 | {
31 | Console.Write(description);
32 | Console.WriteLine(" Time per action {0} ns", timeperaction * 1000);
33 | }
34 | }
35 |
36 | public static TimeSpan Profile(int iterations, Action func, bool silentmode = true, string description = "")
37 | {
38 | //Run at highest priority to minimize fluctuations caused by other processes/threads
39 | Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.High;
40 | Thread.CurrentThread.Priority = ThreadPriority.Highest;
41 |
42 | // warm up
43 | func();
44 |
45 | var watch = new Stopwatch();
46 |
47 | // clean up
48 | GC.Collect();
49 | GC.WaitForPendingFinalizers();
50 | GC.Collect();
51 |
52 | watch.Start();
53 | for (int i = 0; i < iterations; i++)
54 | {
55 | func();
56 | }
57 | watch.Stop();
58 |
59 | if (!silentmode)
60 | {
61 | Console.Write(description);
62 | Console.WriteLine(" Time Elapsed {0} ns", watch.Elapsed.TotalMilliseconds * 1000);
63 | }
64 | return watch.Elapsed;
65 | }
66 | }
67 | }
--------------------------------------------------------------------------------
/DspSharpDemo/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2017 Jonathan Arweck, see LICENSE.txt for license information
4 | //
5 | // --------------------------------------------------------------------------------------------------------------------
6 |
7 | using System.Reflection;
8 | using System.Runtime.InteropServices;
9 | using System.Windows;
10 |
11 | // General Information about an assembly is controlled through the following
12 | // set of attributes. Change these attribute values to modify the information
13 | // associated with an assembly.
14 |
15 | [assembly: AssemblyTitle("FilterTest")]
16 | [assembly: AssemblyDescription("")]
17 | [assembly: AssemblyConfiguration("")]
18 | [assembly: AssemblyCompany("")]
19 | [assembly: AssemblyProduct("FilterTest")]
20 | [assembly: AssemblyCopyright("Copyright © 2016")]
21 | [assembly: AssemblyTrademark("")]
22 | [assembly: AssemblyCulture("")]
23 |
24 | // Setting ComVisible to false makes the types in this assembly not visible
25 | // to COM components. If you need to access a type in this assembly from
26 | // COM, set the ComVisible attribute to true on that type.
27 |
28 | [assembly: ComVisible(false)]
29 |
30 | //In order to begin building localizable applications, set
31 | //CultureYouAreCodingWith in your .csproj file
32 | //inside a . For example, if you are using US english
33 | //in your source files, set the to en-US. Then uncomment
34 | //the NeutralResourceLanguage attribute below. Update the "en-US" in
35 | //the line below to match the UICulture setting in the project file.
36 |
37 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
38 |
39 | [assembly: ThemeInfo(
40 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
41 | //(used if a resource is not found in the page,
42 | // or application resource dictionaries)
43 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
44 | //(used if a resource is not found in the page,
45 | // app, or any theme specific resource dictionaries)
46 | )]
47 |
48 | // Version information for an assembly consists of the following four values:
49 | //
50 | // Major Version
51 | // Minor Version
52 | // Build Number
53 | // Revision
54 | //
55 | // You can specify all the values or you can default the Build and Revision Numbers
56 | // by using the '*' as shown below:
57 | // [assembly: AssemblyVersion("1.0.*")]
58 |
59 | [assembly: AssemblyVersion("1.0.0.0")]
60 | [assembly: AssemblyFileVersion("1.0.0.0")]
--------------------------------------------------------------------------------
/DspSharpDemo/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace DspSharpDemo.Properties {
12 |
13 |
14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "14.0.0.0")]
16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
17 |
18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
19 |
20 | public static Settings Default {
21 | get {
22 | return defaultInstance;
23 | }
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/DspSharpDemo/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/DspSharpDemo/RelayCommand.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2017 Jonathan Arweck, see LICENSE.txt for license information
4 | //
5 | // --------------------------------------------------------------------------------------------------------------------
6 |
7 | using System;
8 | using System.Diagnostics;
9 | using System.Windows.Input;
10 |
11 | namespace DspSharpDemo
12 | {
13 | ///
14 | /// A command whose sole purpose is to
15 | /// relay its functionality to other
16 | /// objects by invoking delegates. The
17 | /// default return value for the CanExecute
18 | /// method is 'true'.
19 | ///
20 | public class RelayCommand : ICommand
21 | {
22 | readonly Predicate