chowdsp_wdf
is a header only library for implementing real-time
Wave Digital Filter (WDF) circuit models in C++.
More information:
Since chowdsp_wdf
is a header-only library, it should be possible to use the library
simply by including include/chowdsp_wdf/chowdsp_wdf.h
. However, it is recommended to
use the library via CMake.
add_subdirectory(chowdsp_wdf)
target_link_libraries(my_cmake_target PUBLIC chowdsp_wdf)
A basic RC lowpass filter can be constructed as follows:
namespace wdft = chowdsp::wdft;
struct RCLowpass {
wdft::ResistorT<double> r1 { 1.0e3 }; // 1 KOhm Resistor
wdft::CapacitorT<double> c1 { 1.0e-6 }; // 1 uF capacitor
wdft::WDFSeriesT<double, decltype (r1), decltype (c1)> s1 { r1, c1 }; // series connection of r1 and c1
wdft::PolarityInverterT<float, decltype(s1)> i1 { s1 }; // invert polarity
wdft::IdealVoltageSourceT<double, decltype (s1)> vs { s1 }; // input voltage source
// prepare the WDF model here...
void prepare (double sampleRate) {
c1.prepare (sampleRate);
}
// use the WDF model to process one sample of data
inline double processSample (double x) {
vs.setVoltage (x);
vs.incident(i1.reflected());
i1.incident(vs.reflected());
return wdft::voltage<double> (c1);
}
};
More complicated examples can be found in the examples repository.
There are two specific situations where you may want to use SIMD intrinsics as part of your WDF model:
- You want to run the same circuit model on several values in parallel. For example, maybe you have a WDF model of a synthesizer voice, and want to run several voices, like for a polyphonic synthesizer.
- You have a circuit model that requires an R-Type adaptor. The R-Type adaptor requires a matrix multiply operation which can be greatly accelerated with SIMD intrinsics.
In both cases, to use SIMD intrinsics in your WDF model, you must include XSIMD
in your project before chowdsp_wdf
.
#include <xsimd/xsmd.hpp> // this must be included _before_ the chowdsp_wdf header!
#include <chowdsp_wdf/chowdsp_wdf.h>
For case 2 above, simply construct your circuit with an R-Type adaptor as desired, and the SIMD optomizations will be taken care of behind the scenes!
For case 1 above, you will want to construct your WDF model so that the circuit elements may process XSIMD types. Going back to the RC lowpass example:
namespace wdft = chowdsp::wdft;
// Define the WDF model to process a template-defined FloatType
template <typename FloatType>
struct RCLowpass {
wdft::ResistorT<FloatType> r1 { 1.0e3 }; // 1 KOhm Resistor
wdft::CapacitorT<FloatType> c1 { 1.0e-6 }; // 1 uF capacitor
wdft::WDFSeriesT<FloatType, decltype (r1), decltype (c1)> s1 { r1, c1 }; // series connection of r1 and c1
wdft::PolarityInverterT<FloatType, decltype(s1)> i1 { s1 }; // invert polarity
wdft::IdealVoltageSourceT<FloatType, decltype (s1)> vs { s1 }; // input voltage source
// prepare the WDF model here...
void prepare (double sampleRate) {
c1.prepare ((FloatType) sampleRate);
}
// use the WDF model to process one sample of data
inline FloatType processSample (FloatType x) {
vs.setVoltage (x);
vs.incident (i1.reflected());
i1.incident (vs.reflected());
return wdft::voltage<FloatType> (c1);
}
};
RCLowpass<xsimd::batch<double>> myFilter; // instantiate the WDF to process an XSIMD type!
If you are using chowdsp_wdf
with XSIMD, please remember to abide by the XSIMD license.
If you are using chowdsp_wdf
as part of an academic work, please cite the library as follows:
@article{chowdhury2022chowdspwdf,
title = {chowdsp_wdf: An Advanced C++ Library for Wave Digital Circuit Modelling},
author = {Chowdhury, Jatin},
year = {2022},
journal={arXiv preprint arXiv:2210.12554}
doi = {10.48550/ARXIV.2210.12554},
url = {https://arxiv.org/abs/2210.12554},
}
The design and implementation of the library were discussed on The Audio Programmer meetup in December 2021. The presentation can be watched on YouTube.
The following academic papers may also be useful:
[1] Alfred Fettweis, "Wave Digital Filters: Theory and Practice", 1986, IEEE Invited Paper, link.
[2] Julius Smith, "Wave Digital Filters", (Chapter from Physical Audio Signal Processing) link.
[3] David Yeh and Julius Smith, "Simulating Guitar Distortion Circuits Using Wave Digital And Nonlinear State Space Formulations", Proc. of the 11th Int. Conference on Digital Audio Effects, 2008, link.
[4] Kurt Werner, et al., "Wave Digital Filter Modeling of Circuits with Operational Amplifiers", 24th European Signal Processing Conference, 2016, link.
[5] Kurt Werner, et al., "Resolving Wave Digital Filters with Multiple/Multiport Nonlinearities", Proc. of the 18th Int. Conference on Digital Audio Effects, 2015, link.
[6] Kurt Werner, "Virtual Analog Modeling of Audio Circuitry Using Wave Digital Filters", PhD. Dissertation, Stanford University, 2016, link.
[7] Jingjie Zhang and Julius Smith, "Real-time Wave Digital Simulation of Cascaded Vacuum Tube Amplifiers Using Modified Blockwise Method", Proc. of the 21st International Conference on Digital Audio Effects, 2018, link.
The diode models in the library utilise an approximation of the Wright Omega function based on Stefano D'Angelo's implementation, which is licensed under the MIT license.
Many thanks to the following individuals who have contributed to the theory, design, and implementation of the library:
- Julius Smith
- Jingjie Zhang
- Kurt Werner
- Paul Walker
- Eyal Amir
- Dirk Roosenburg
The code in this repository is open source, and licensed under the BSD 3-Clause License. Enjoy!