{"id":22409214,"url":"https://github.com/ar1st0crat/nwaves","last_synced_at":"2025-05-15T23:04:20.999Z","repository":{"id":37335744,"uuid":"105904362","full_name":"ar1st0crat/NWaves","owner":"ar1st0crat","description":".NET DSP library with a lot of audio processing functions","archived":false,"fork":false,"pushed_at":"2022-09-27T18:42:31.000Z","size":7637,"stargazers_count":488,"open_issues_count":15,"forks_count":77,"subscribers_count":29,"default_branch":"master","last_synced_at":"2025-05-15T23:04:12.167Z","etag":null,"topics":["adaptive-filtering","audio","dsp","fda","feature-extraction","filtering","lpc","mfcc","mir","noise","pitch","psychoacoustics","resampling","signal","sound-effects","sound-synthesis","time-stretch","wav","wavelets"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ar1st0crat.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-10-05T15:04:55.000Z","updated_at":"2025-05-13T20:46:23.000Z","dependencies_parsed_at":"2023-01-17T14:31:33.050Z","dependency_job_id":null,"html_url":"https://github.com/ar1st0crat/NWaves","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ar1st0crat%2FNWaves","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ar1st0crat%2FNWaves/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ar1st0crat%2FNWaves/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ar1st0crat%2FNWaves/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ar1st0crat","download_url":"https://codeload.github.com/ar1st0crat/NWaves/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254436944,"owners_count":22070946,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["adaptive-filtering","audio","dsp","fda","feature-extraction","filtering","lpc","mfcc","mir","noise","pitch","psychoacoustics","resampling","signal","sound-effects","sound-synthesis","time-stretch","wav","wavelets"],"created_at":"2024-12-05T12:06:57.462Z","updated_at":"2025-05-15T23:04:20.877Z","avatar_url":"https://github.com/ar1st0crat.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# NWaves\n\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n![Version](https://img.shields.io/nuget/v/NWaves.svg?style=flat)\n![NuGet](https://img.shields.io/nuget/dt/NWaves.svg?style=flat)\n[![Gitter](https://badges.gitter.im/NWaves/community.svg)](https://gitter.im/NWaves/community?utm_source=badge\u0026utm_medium=badge\u0026utm_campaign=pr-badge)\n\n![logo](https://raw.githubusercontent.com/ar1st0crat/NWaves/master/assets/logo/logo_draft.bmp)\n\nNWaves is a .NET DSP library with a lot of audio processing functions.\n\n## Releases\n\nNWaves is [available on NuGet](https://www.nuget.org/packages/NWaves/):\n\n```PM\u003e Install-Package NWaves```\n\n[Read wiki documentation](https://github.com/ar1st0crat/NWaves/wiki)\n\nNew version **0.9.6** is out! Faster, smarter, more features. [Read about changes here](https://github.com/ar1st0crat/NWaves/wiki/Known-bugs-and-changelog)\n\n[Notes for non-experts in DSP](https://github.com/ar1st0crat/NWaves/wiki/Notes-for-non~experts-in-DSP)\n\n[NWaves for MATLAB/sciPy users](https://github.com/ar1st0crat/NWaves/wiki/NWaves-for-MATLAB-and-sciPy-users)\n\n[Watch survey video](https://www.youtube.com/watch?v=GyRixqQ613A) | [Playlist](https://www.youtube.com/playlist?list=PL1BjzwHbvgSWVbr32uA2ihdnVCLhVA8a5) | [Samples](https://github.com/ar1st0crat/NWaves.Samples)  |  [Benchmarks](https://github.com/ar1st0crat/NWaves/tree/master/NWaves.Benchmarks) | [Playground](https://ar1st0crat.github.io/NWaves.Playground/) ([code](https://github.com/ar1st0crat/NWaves.Playground))\n\n\n## Main features\n\n- [x] major DSP transforms (FFT, DCT, MDCT, STFT, FWT, Hilbert, Hartley, Mellin, cepstral, Goertzel)\n- [x] signal builders (sine, white/pink/red/Perlin noise, awgn, triangle, sawtooth, square, pulse, ramp, ADSR, wavetable)\n- [x] basic LTI digital filters (moving average, comb, Savitzky-Golay, pre/de-emphasis, DC removal, RASTA)\n- [x] FIR/IIR filtering (offline and online), zero-phase filtering\n- [x] BiQuad filters (low-pass, high-pass, band-pass, notch, all-pass, peaking, shelving)\n- [x] 1-pole filters (low-pass, high-pass)\n- [x] IIR filters (Bessel, Butterworth, Chebyshev I \u0026 II, Elliptic, Thiran)\n- [x] basic operations (convolution, cross-correlation, rectification, amplification, fade / crossfade)\n- [x] block convolution (overlap-add / overlap-save offline and online)\n- [x] basic filter design \u0026 analysis (group delay, zeros/poles, BP, BR, HP from/to LP, SOS, combining filters)\n- [x] state space representation of LTI filters\n- [x] FIR filter design: frequency sampling, window-sinc, equiripple (Remez / Parks-McClellan)\n- [x] IIR filter design: IirNotch / IirPeak / IirCombNotch / IirCombPeak\n- [x] non-linear filters (median filter, distortion effects, bit crusher)\n- [x] windowing functions (Hamming, Blackman, Hann, Gaussian, Kaiser, KBD, triangular, Lanczos, flat-top, Bartlett)\n- [x] periodograms (Welch / Lomb-Scargle)\n- [x] psychoacoustic filter banks (Mel, Bark, Critical Bands, ERB, octaves) and VTLN warping\n- [x] customizable feature extraction (time-domain, spectral, MFCC, PNCC/SPNCC, LPC, LPCC, PLP, AMS)\n- [x] preconfigured MFCC extractors: HTK (MFCC-FB24), Slaney (MFCC-FB40)\n- [x] LPC conversions: LPC\u003c-\u003ecepstrum, LPC\u003c-\u003eLSF\n- [x] feature post-processing (mean and variance normalization, adding deltas) and CSV serialization\n- [x] spectral features (centroid, spread, flatness, entropy, rolloff, contrast, crest, decrease, noiseness, MPEG7)\n- [x] harmonic features (harmonic centroid and spread, inharmonicity, tristimulus, odd-to-even ratio)\n- [x] time-domain characteristics (rms, energy, zero-crossing rate, entropy)\n- [x] pitch tracking (autocorrelation, YIN, ZCR + Schmitt trigger, HSS/HPS, cepstrum)\n- [x] chromagram (chroma feature extractor)\n- [x] time scale modification (phase vocoder, PV with identity phase locking, WSOLA, PaulStretch)\n- [x] simple resampling, interpolation, decimation\n- [x] bandlimited resampling\n- [x] wavelets: haar, db, symlet, coiflet\n- [x] polyphase filters\n- [x] noise reduction (spectral subtraction, sciPy-style Wiener filtering)\n- [x] sound effects (echo, tremolo, wahwah, phaser, chorus, vibrato, flanger, pitch shift, morphing, robotize, whisperize)\n- [x] 3D/Stereo audio (stereo panning, stereo and ping-pong delay, ITD-ILD, binaural panning)\n- [x] envelope following\n- [x] dynamics processing (limiter / compressor / expander / noise gate)\n- [x] harmonic/percussive separation\n- [x] Griffin-Lim algorithm\n- [x] Karplus-Strong synthesis\n- [x] PADSynth synthesis\n- [x] adaptive filtering (LMS, NLMS, LMF, SignLMS, RLS)\n- [x] simple modulation/demodulation (AM, ring, FM, PM)\n- [x] simple audio playback and recording\n\n\n## Philosophy of NWaves\n\nNWaves was initially intended for research, visualizing and teaching basics of DSP and sound programming. \n\nUsually, DSP code is quite complicated and difficult to read, because it's full of optimizations (which is actually a very good thing). NWaves project aims in particular at achieving a tradeoff between good understandable code/design and satisfactory performance. Yet, the main purpose of this lib is to offer the DSP codebase that would be:\n\n- easy to read and understand\n- easy to incorporate into existing projects\n- easy to port to other programming languages and frameworks\n- even possibly treated as the DSP/audio textbook.\n\nAccording to NWaves architecture, there are following general reusable building blocks for all kinds of DSP tasks:\n\n[Transforms](#transforms) | [Filters](#filters-and-effects) | [Signal builders](#signal-builders) | [Feature extractors](#feature-extractors)\n\n\n## Quickstart\n\n### Working with 1D signals\n\n```C#\n// Create signal from samples repeated 100 times\n\nfloat[] samples = new [] { 0.5f, 0.2f, -0.3f, 1.2f, 1.6f, -1.8f, 0.3f, -0.2f };\n\nvar s = new DiscreteSignal(8000, samples).Repeat(100);\n\nvar length = s.Length;\nvar duration = s.Duration;\n\nvar echoSignal = s + s.Delay(50);\n\nvar marginSignal = s.First(64).Concatenate(s.Last(64));\n\nvar repeatMiddle = s[400, 500].Repeat(10);\n\nvar mean = s.Samples.Average();\nvar sigma = s.Samples.Average(x =\u003e (x - mean) * (x - mean));\n\nvar normSignal = s - mean;\nnormSignal.Attenuate(sigma);\n\n```\n\n### Signal builders\n\n```C#\n\nDiscreteSignal sinusoid = \n    new SineBuilder()\n        .SetParameter(\"frequency\", 500.0/*Hz*/)\n        .SetParameter(\"phase\", Math.PI / 6)\n        .OfLength(1000)\n        .SampledAt(44100/*Hz*/)\n        .Build();\n\nDiscreteSignal noise = \n    new RedNoiseBuilder()\n        .SetParameter(\"min\", -2.5)\n        .SetParameter(\"max\", 2.5)\n        .OfLength(800)\n        .SampledAt(44100)\n        .DelayedBy(200)\n        .Build();\n\nDiscreteSignal noisy = \n    new SineBuilder()\n        .SetParameter(\"min\", -10.0)\n        .SetParameter(\"max\", 10.0)\n        .SetParameter(\"freq\", 1200.0/*Hz*/)\n        .OfLength(1000)\n        .SampledAt(44100)\n        .SuperimposedWith(noise)\n        .Build();\n\n```\n\nSignal builders can also act as real-time generators of samples:\n\n```C#\n\nSignalBuilder lfo = \n    new TriangleWaveBuilder()\n            .SetParameter(\"min\", 100)\n            .SetParameter(\"max\", 1500)\n            .SetParameter(\"frequency\", 2.0/*Hz*/)\n            .SampledAt(16000/*Hz*/);\n\n//while (...)\n{\n    var sample = lfo.NextSample();\n    //...\n}\n\n```\n\n\n### Signals and wave files:\n\n```C#\n\nWaveFile waveContainer;\n\n// load\n\nusing (var stream = new FileStream(\"sample.wav\", FileMode.Open))\n{\n    waveContainer = new WaveFile(stream);\n}\n\nDiscreteSignal left = waveContainer[Channels.Left];\nDiscreteSignal right = waveContainer[Channels.Right];\n\n\n// save\n\nvar waveFileOut = new WaveFile(left);\n\nusing (var stream = new FileStream(\"saved_mono.wav\", FileMode.Create))\n{\n    waveFileOut.SaveTo(stream);\n}\n\nvar waveFileStereo = new WaveFile(new [] { left, right });\n\nusing (var stream = new FileStream(\"saved_stereo.wav\", FileMode.Create))\n{\n    waveFileStereo.SaveTo(stream);\n}\n\n```\n\n\n### Transforms\n\nFor each transform there's a corresponding transformer object.\nEach transformer object has ```Direct()``` and ```Inverse()``` methods.\n\n#### FFT\n\n```C#\n\n// Complex FFT transformer:\n\nvar fft = new Fft(1024);\n\n// Real FFT transformer (faster):\n\nvar rfft = new RealFft(1024);\n\n\nfloat[] real = signal.First(1024).Samples;\nfloat[] imag = new float [1024];\n\n// in-place complex FFT\nfft.Direct(real, imag);\n\n// ...do something with real and imaginary parts of the spectrum...\n\n// in-place complex IFFT\nfft.Inverse(real, imag);\n\n// post-processed FFT:\n\nvar magnitudeSpectrum = \n    fft.MagnitudeSpectrum(signal[1000, 2024]);\n\nvar powerSpectrum = \n    fft.PowerSpectrum(signal.First(1024), normalize: false);\n\nvar logPowerSpectrum = \n    fft.PowerSpectrum(signal.Last(1024))\n       .Samples\n       .Select(s =\u003e Scale.ToDecibel(s))\n       .ToArray();\n\n\n// real FFT transforms real-valued signal to complex-valued spectrum:\n\nrfft.Direct(real, real, imag);   // real -\u003e (real, imag)\nrfft.Inverse(real, imag, real);  // (real, imag) -\u003e real\n\nvar magnitudeSpectrum = \n    rfft.MagnitudeSpectrum(signal[1000, 2024]);\n\nvar powerSpectrum = \n    rfft.PowerSpectrum(signal.First(1024), normalize: false);\n\n// ...\n\n```\n\nLot of methods in NWaves have overloaded versions with output buffers as parameters. So reuse memory whenever possible:\n\n```C#\n\nfloat[] spectrum = new float[1024];\n\nfor (var i = start; i \u003c end; i += step)\n{\n    rfft.MagnitudeSpectrum(signal[i, i + 1024], spectrum);\n    // ...\n    // do something with spectrum\n}\n\n```\n\n\n#### STFT\n\n```C#\n\n// Short-Time Fourier Transform:\n\nvar stft = new Stft(1024, 256, WindowTypes.Hamming);\nvar timefreq = stft.Direct(signal);\nvar reconstructed = stft.Inverse(timefreq);\n\nvar spectrogram = stft.Spectrogram(signal);\n\n```\n\n#### Cepstral transform\n\n```C#\n\n// Cepstral transformer:\n\nvar ct = new CepstralTransform(24, fftSize: 512);\n\n// complex cepstrum\nct.Direct(input, output);\n// or\nvar delay = ct.ComplexCepstrum(input, output);\n\n// real cepstrum\nct.RealCepstrum(input, output);\n\n// inverse complex cepstrum\nct.InverseComplexCepstrum(output, input, delay: delay);\n\n```\n\n#### Wavelets\n\n```C#\n\nvar fwt = new Fwt(192, new Wavelet(\"db5\"));\n\n// or\n//var fwt = new Fwt(192, new Wavelet(WaveletFamily.Daubechies, 5));\n\nvar output = new float[192];\nvar reconstructed = new float[192];\n\nfwt.Direct(input, output);\nfwt.Inverse(output, reconstructed);\n\n```\n\n\n### Operations:\n\n```C#\n// convolution\n\nvar conv = Operation.Convolve(signal, kernel);\nvar xcorr = Operation.CrossCorrelate(signal1, signal2);\n\n// block convolution\n\nvar filtered = Operation.BlockConvolve(signal, kernel, 4096, FilteringMethod.OverlapAdd);\n\n// periodogram evaluation\n\nvar periodogram = Operation.Welch(signal, 2048, 1024);\nvar pgram = Operation.LombScargle(x, y, freqs);\n\n// resampling\n\nvar resampled = Operation.Resample(signal, 22050);\nvar interpolated = Operation.Interpolate(signal, 3);\nvar decimated = Operation.Decimate(signal, 2);\nvar updown = Operation.ResampleUpDown(signal, 3, 2);\n\n// time scale modification\n\nvar stretch = Operation.TimeStretch(signal, 0.7, TsmAlgorithm.Wsola);\nvar cool = Operation.TimeStretch(signal, 16, TsmAlgorithm.PaulStretch);\n\n// envelope following\n\nvar envelope = Operation.Envelope(signal);\n\n// peak / rms normalization\n\nvar peakNorm = Operation.NormalizePeak(signal, -3/*dB*/);\nvar rmsNorm = Operation.NormalizeRms(signal, -3/*dB*/);\nvar rmsChanged = Operation.ChangeRms(signal, -6/*dB*/);\n\n// rectification\n\nvar halfRect = Operation.HalfRectify(signal);\nvar fullRect = Operation.FullRectify(signal);\n\n// spectral subtraction\n\nvar clean = Operation.SpectralSubtract(signal, noise);\n\n// crossfade\n\nvar crossfaded = song1.Crossfade(song2, 0.05/*sec*/);\n\n```\n\n\n### Filters and effects:\n\n```C#\n\nvar maFilter = new MovingAverageFilter(7);\nvar smoothedSignal = maFilter.ApplyTo(signal);\n\nvar frequency = 800.0/*Hz*/;\nvar notchFilter = new BiQuad.NotchFilter(frequency / signal.SamplingRate);\nvar notchedSignal = notchFilter.ApplyTo(signal);\n\n\n// filter analysis:\n\nvar transferFunction = new TransferFunction(new [] { 1, 0.5, 0.2 }, new [] { 1, -0.8, 0.3 });\n\nvar filter = new IirFilter(transferFunction);\n\n// we can also write this:\n\n// var filter = new IirFilter(new [] { 1, 0.5, 0.2 }, new [] { 1, -0.8, 0.3 });\n// var transferFunction = filter.Tf;\n// ...\n\n// if we simply want to apply filter and don't care much about FDA precision:\n// read more in tutorial\n\n\nvar impulseResponse = transferFunction.ImpulseResponse();\nvar magnitudeResponse = transferFunction.FrequencyResponse().Magnitude;\nvar phaseResponse = transferFunction.FrequencyResponse().Phase;\n\nvar b = transferFunction.Numerator;\nvar a = transferFunction.Denominator;\nvar zeros = transferFunction.Zeros;\nvar poles = transferFunction.Poles;\n\nvar gd = transferFunction.GroupDelay();\nvar pd = transferFunction.PhaseDelay();\n\n\n// some examples of FIR filter design:\n\nvar kernel = DesignFilter.FirWinLp(345, 0.15);\nvar lpFilter = new FirFilter(kernel);\n\n// HP filter can be obtained from LP with the same cutoff frequency:\nvar hpFilter = DesignFilter.FirLpToHp(lpFilter);\n\n// design BP filter\nvar bpFilter = DesignFilter.FirWinBp(123, 0.05, 0.15);\n\n// design equiripple HP filter\nvar bpFilter = DesignFilter.FirEquirippleHp(123, 0.34, 0.355, 0.05, 0.95);\n\n\n// sequence of filters:\n\nvar cascade = filter * firFilter * notchFilter;\nvar filtered = cascade.ApplyTo(signal);\n\n// filtering is conceptually equivalent to:\n\nvar filtered = filter.ApplyTo(signal);\nfiltered = firFilter.ApplyTo(filtered);\nfiltered = notchFilter.ApplyTo(filtered);\n\n// same but with double precision:\nvar cascadeTf = filter.Tf * firFilter.Tf * notchFilter.Tf;\nvar cascadeFilter = new IirFilter(cascadeTf);\nvar filtered = cascadeFilter.ApplyTo(signal);\n\n// parallel combination of filters:\n\nvar parallel = filter1 + filter2;\nfiltered = parallel.ApplyTo(signal);\n\n// same but with double precision:\nvar parallelTf = filter1.Tf + filter2.Tf;\nvar parallelFilter = new IirFilter(parallelTf);\nvar filtered = parallelFilter.ApplyTo(signal);\n\n// audio effects:\n\nvar flanger = new FlangerEffect(signal.SamplingRate);\nvar wahwah = new WahwahEffect(signal.SamplingRate, lfoFrequency: 2/*Hz*/);\n\nvar processed = wahwah.ApplyTo(flanger.ApplyTo(signal));\n// this will create intermediate copy of the signal\n\n\n// FilterChain is memory-efficient:\n\nvar filters = new FilterChain();\nfilters.Add(flanger);\nfilters.Add(wahwah);\n\nprocessed = filters.ApplyTo(signal);\n\n\n// Second-Order Sections:\n\nvar tf = new Butterworth.BandPassFilter(0.1, 0.16, 7).Tf;\n\n// get array of SOS from TF:\nTransferFunction[] sos = DesignFilter.TfToSos(tf);\n\nvar sosFilter = new FilterChain(sos);\n\nvar y = sosFilter.ApplyTo(x);\n\n// or process samples online:\n//    ... outSample = sosFilter.Process(sample);\n\n```\n\n\n### Online processing\n\nOnline processing is supported by all classes that implement the ```IOnlineFilter``` interface.\nCurrently, all LTI filters, ```FilterChain``` class, block convolvers (```OlaBlockConvolver```, ```OlsBlockConvolver```) and audio effects contain the ```Process(sample)``` and ```Process(bufferIn, bufferOut)``` methods responsible for online processing.\n\nSimply process data sample after sample:\n\n```C#\n\nvar outputSample = filter.Process(sample);\n\n```\n\nOr prepare necessary buffers (or just use them if they come from another part of your system):\n\n```C#\n\nfloat[] output;\n\n...\n\nvoid NewChunkAvailable(float[] chunk)\n{\n    filter.Process(chunk, output);\n}\n\n\n// if input chunk shouldn't necessarily be preserved, it can be overwritten:\n\nvoid NewChunkAvailable(float[] chunk)\n{\n    filter.Process(chunk, chunk);\n}\n\n```\n\n\nBlock convolvers:\n\n```C#\n\n// Overlap-Add / Overlap-Save\n\nFirFilter filter = new FirFilter(kernel);\n\nvar blockConvolver = OlaBlockConvolver.FromFilter(filter, 4096);\n\n// processing loop:\n// while new input sample is available\n{\n    var outputSample = blockConvolver.Process(sample);\n}\n\n// or:\n// while new input buffer is available\n{\n    blockConvolver.Process(input, output);\n}\n\n```\n\nSee also OnlineDemoForm code.\n\n![onlinedemo](https://raw.githubusercontent.com/ar1st0crat/NWaves/master/assets/screenshots/onlinedemo.gif)\n\n\n### Feature extractors\n\nHighly customizable feature extractors are available for offline and online processing (MFCC family, LPC, pitch and lot of others).\n\n```C#\n\nvar mfccOptions = new MfccOptions\n{\n    SamplingRate = signal.SamplingRate,\n    FeatureCount = 13,\n    FrameDuration = 0.032/*sec*/,\n    HopDuration = 0.015/*sec*/,\n    FilterBankSize = 26,\n    PreEmphasis = 0.97,\n    //...unspecified parameters will have default values \n};\n\nvar mfccExtractor = new MfccExtractor(mfccOptions);\nvar mfccVectors = mfccExtractor.ComputeFrom(signal);\n\n\n// serialize current config to JSON file:\n\nusing (var config = new FileStream(\"file.json\", FileMode.Create))\n{\n    config.SaveOptions(mfccOptions);\n}\n\n\nvar lpcOptions = new LpcOptions\n{\n    SamplingRate = signal.SamplingRate,\n    LpcOrder = 15\n};\n\nvar lpcExtractor = new LpcExtractor(lpcOptions);\nvar lpcVectors = lpcExtractor.ParallelComputeFrom(signal);\n\n\n\nvar opts = new MultiFeatureOptions\n{\n    SamplingRate = signal.SamplingRate,\n    FeatureList = \"centroid, flatness, c1+c2+c3\"\n};\n\nvar spectralExtractor = new SpectralFeaturesExtractor(opts);\n\nopts.FeatureList = \"all\";\nvar tdExtractor = new TimeDomainFeaturesExtractor(opts);\n\nvar vectors = FeaturePostProcessing.Join(\n                  tdExtractor.ParallelComputeFrom(signal), \n                  spectralExtractor.ParallelComputeFrom(signal));\n\n// each vector will contain 1) all time-domain features (energy, rms, entropy, zcr)\n//                          2) specified spectral features\n\n\n// open config from JSON file:\n\nPnccOptions options;\nusing (var config = new FileStream(\"file.json\", FileMode.Open))\n{\n    options = config.LoadOptions\u003cPnccOptions\u003e();\n}\n\nvar pnccExtractor = new PnccExtractor(pnccOptions);\nvar pnccVectors = pnccExtractor.ComputeFrom(signal, /*from*/1000, /*to*/60000 /*sample*/);\nFeaturePostProcessing.NormalizeMean(pnccVectors);\n\n\n// serialization\n\nusing (var csvFile = new FileStream(\"mfccs.csv\", FileMode.Create))\n{\n    var serializer = new CsvFeatureSerializer(mfccVectors);\n    await serializer.SerializeAsync(csvFile);\n}\n\n```\n\nPre-processing\n\n```C#\n\n// There are 3 options to perform pre-emphasis filtering:\n\n// 1) Set pre-emphasis coefficient in constructor of a feature extractor\n// 2) Apply filter before processing and process filtered signal\n// 3) Filter signal in-place and process it\n\n// (...read more in docs...)\n\n// option 1:\n\nvar opts = new MfccOptions\n{\n    SamplingRate = signal.SamplingRate,\n    FeatureCount = 13,\n    PreEmphasis = 0.95\n};\nvar mfccExtractor = new MfccExtractor(opts);\nvar mfccVectors = mfccExtractor.ComputeFrom(signal);\n\n// option 2:\n// ApplyTo() will create new signal (allocate new memory)\n\nopts.PreEmphasis = 0;\nmfccExtractor = new MfccExtractor(opts);\nvar pre = new PreEmphasisFilter(0.95);\nvar filtered = pre.ApplyTo(signal);\nmfccVectors = mfccExtractor.ComputeFrom(filtered);\n\n// option 3:\n// process array or DiscreteSignal samples in-place:\n\nfor (var i = 0; i \u003c signal.Length; i++)\n{\n    signal[i] = pre.Process(signal[i]);\n}\n// or simply:\n// pre.Process(signal.Samples, signal.Samples);\n\nmfccVectors = mfccExtractor.ComputeFrom(signal);\n\n```\n\n### Playing and recording\n\n```MciAudioPlayer``` and ```MciAudioRecorder``` work only at Windows-side, since they use winmm.dll and MCI commands.\n\n```C#\n\nIAudioPlayer player = new MciAudioPlayer();\n\n// play entire file\nawait player.PlayAsync(\"temp.wav\");\n\n// play file from 16000th sample to 32000th sample\nawait player.PlayAsync(\"temp.wav\", 16000, 32000);\n\n\n// ...in some event handler\nplayer.Pause();\n\n// ...in some event handler\nplayer.Resume();\n\n// ...in some event handler\nplayer.Stop();\n\n\n// recording\n\nIAudioRecorder recorder = new MciAudioRecorder();\n\n// ...in some event handler\nrecorder.StartRecording(16000);\n\n// ...in some event handler\nrecorder.StopRecording(\"temp.wav\");\n\n```\n\n### Samples\n\n![filters](https://raw.githubusercontent.com/ar1st0crat/NWaves/master/assets/screenshots/Filters.png)\n\n![pitch](https://raw.githubusercontent.com/ar1st0crat/NWaves/master/assets/screenshots/pitch.png)\n\n![lpc](https://raw.githubusercontent.com/ar1st0crat/NWaves/master/assets/screenshots/lpc.png)\n\n![mfcc](https://raw.githubusercontent.com/ar1st0crat/NWaves/master/assets/screenshots/mfcc.png)\n\n![spectral](https://raw.githubusercontent.com/ar1st0crat/NWaves/master/assets/screenshots/spectral.png)\n\n![effects](https://raw.githubusercontent.com/ar1st0crat/NWaves/master/assets/screenshots/effects.png)\n\n![wavelets](https://raw.githubusercontent.com/ar1st0crat/NWaves/master/assets/screenshots/wavelets.png)\n\n![adaptive](https://raw.githubusercontent.com/ar1st0crat/NWaves/master/assets/screenshots/adaptive.png)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Far1st0crat%2Fnwaves","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Far1st0crat%2Fnwaves","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Far1st0crat%2Fnwaves/lists"}