A class representing the surge filter models with a easier-to-use api. More...
#include <api.h>
Public Types | |
using | legacyType_t = std::pair< sst::filters::FilterType, sst::filters::FilterSubType > |
This API connects us to the legacy enum types for a given model. | |
Public Member Functions | |
void | setFilterModel (FilterModel model) |
FilterModel | getFilterModel () const |
void | setPassband (Passband type) |
void | setSlope (Slope slope) |
void | setDriveMode (DriveMode drive) |
void | setSubmodel (FilterSubModel smt) |
void | setModelConfiguration (const ModelConfig &sk) |
ModelConfig | getModelConfiguration () const |
std::string | displayName () const |
A reasonable user facing display name for the given configuration. | |
void | provideDelayLine (int voice, float *memory) |
If a delay line is needed, each active voice requires one. | |
void | provideAllDelayLines (float *memory) |
Or provide them all in one go. | |
size_t | getBlockSize () const |
bool | prepareInstance () |
Once a filter has been set up with a model type and a configuration the instance needs preparation to resolve the internal state. | |
bool | requiresPreparation () const |
If a call to prepareInstance is required, this will return true. | |
void | makeCoefficients (int voice, float cutoff, float resonance, float extra=0.f, float extra2=0.f, float extra3=0.f) |
With a given voice, for a given cutoff and resonance, set the internal coefficient state. | |
void | copyCoefficientsFromVoiceToVoice (int from, int to) |
If you want two voices to share coefficients - so a stereo pair with the same cutoff and resonance for instance - it is usually faster to copy coefficients from voice A to voice B that it is to compute them twice. | |
void | makeConstantCoefficients (int voice, float cutoff, float resonance, float extra=0.f, float extra2=0.f, float extra3=0.f) |
With a given voice, for a given cutoff and resonance, set the internal coefficient state. | |
void | setActive (int voice, bool b) |
The filters can have a concept of an inactive voice which for some filters give a moderate CPU advantage in the SIMD pipelines. | |
void | setMono () |
void | setStereo () |
void | setQuad () |
void | setSampleRateAndBlockSize (double sampleRate, size_t blockSize) |
void | prepareBlock () |
prepareBlock must be called after coeffients are set but at the start of each block, as set by blockSize in setSampleRateAndBlockSize | |
SIMD_M128 | processSample (SIMD_M128 in) |
once prepare block has been called, you must call processSample exactly blockSize times, mapping the vector value in to the vector value out. | |
void | concludeBlock () |
At the end of blockSize samples, and before resetting coefficients or the next call to prepareBlock, you need to call concludeBlock. | |
float | processMonoSample (float in) |
convenience functions for mono channel if you dont want to manage simd | |
void | processStereoSample (float inL, float inR, float &outL, float &outR) |
convenience functions for stereo channel if you dont want to manage simd | |
void | processQuadSample (float in[4], float out[4]) |
convenience functions for quad channel if you dont want to manage simd. | |
void | init () |
Initializes the filter state. | |
void | reset () |
Resets the filter registers; leaves the rest of the state intact. | |
Static Public Member Functions | |
static size_t | requiredDelayLinesSizes (FilterModel model, const ModelConfig &k) |
Some model types require a float buffer for a delay line. | |
static int | coefficientsExtraCount (FilterModel model, const ModelConfig &c) |
Some models have coefficient features beyond jsut cutoff and resonance. | |
static std::vector< FilterModel > | availableModels () |
Get a list of the available models supported by the API. | |
static std::vector< ModelConfig > | availableModelConfigurations (FilterModel model, bool sort=false) |
For a given model, return the configurations that model supports. | |
static std::optional< legacyType_t > | getLegacyTypeFor (const FilterModel &m, const ModelConfig &c) |
Protected Attributes | |
details::FilterPayload | payload |
A class representing the surge filter models with a easier-to-use api.
The Filter
class provides an easier to use and enumerated interface on the existing surge filter models, which previously had a direct more-C-style interface and a relatively flat list of feature lookup capabilities. Both APIs are still supported, and the Filter
api is a wrapper on that more mechanical underlying API.
The Filter is configured in a two-part hierarchy, which is specified in enums.h
.
The top of the heirarchy is the FilterModel
enum. That provides the classes of filters which surge provides. The method Filter::availableFilterModel()
returns you a list of them.
Once you have a model, the model is configured by a tuple of {passtype, slopelevel, drivetype, submodel} each of which is a separate enum. Any of these can be left out (or set to UNSUPPORTED
). So for instance, the model FilterModel::VemberClassic
has a configuration {Passband::LP, SlopeLeveLs::Slope_12dB, DriveMode::Clean}
. You can enumerate all the configuration tuples ysing Filter::availableModelConfigurations()
.
Each of the filters is implemented to simultaneously run 4-wide SIMD on a vector of 4 floats in to 4 floats out. While a filter must have a consistent model across the voices, it can have varied resonances and cutoffs, so some apis take a voice parameter.
Finally the surge filters work on a two-rate principle, where there is a control rate block at which you can reset coefficients and a sample-rate api. Managing these two rates is possible with the API and is the responsibility of the API caller. At the outset of a block after setting coefficients, call prepareBlock, and at the conclusion of the block, call concludeBlock.
As such a typical session could look something like this
using legacyType_t = std::pair<sst::filters::FilterType, sst::filters::FilterSubType> |
This API connects us to the legacy enum types for a given model.
void setFilterModel | ( | FilterModel | model | ) |
References Filter::payload, and FilterPayload::setFilterModel().
FilterModel getFilterModel | ( | ) | const |
References FilterPayload::filterModel, and Filter::payload.
Referenced by Filter::prepareInstance(), and Filter::provideAllDelayLines().
void setPassband | ( | Passband | type | ) |
References Filter::payload, and FilterPayload::setPassband().
void setSlope | ( | Slope | slope | ) |
References Filter::payload, and FilterPayload::setSlope().
void setDriveMode | ( | DriveMode | drive | ) |
References Filter::payload, and FilterPayload::setDriveType().
void setSubmodel | ( | FilterSubModel | smt | ) |
References Filter::payload, and FilterPayload::setSubmodel().
void setModelConfiguration | ( | const ModelConfig & | sk | ) |
References Filter::payload, and FilterPayload::setModelConfiguration().
ModelConfig getModelConfiguration | ( | ) | const |
References FilterPayload::getModelConfiguration(), and Filter::payload.
Referenced by Filter::prepareInstance(), and Filter::provideAllDelayLines().
std::string displayName | ( | ) | const |
A reasonable user facing display name for the given configuration.
References FilterPayload::displayName(), and Filter::payload.
|
static |
Some model types require a float buffer for a delay line.
We assume this relatively large chunk of memory will be managed outside this object. This api returns 0 if no such buffer is required, and the requires size in 32 big floats if so. Currently only the comb filter models require this.
model | Which model |
k | Configured how |
References sst::filtersplusplus::Comb, SincTable::FIRipol_N, and sst::filters::utilities::MAX_FB_COMB.
Referenced by Filter::prepareInstance(), and Filter::provideAllDelayLines().
void provideDelayLine | ( | int | voice, |
float * | memory | ||
) |
If a delay line is needed, each active voice requires one.
voice | Each voice needs a distinct buffer |
memory | This is a pointer to memory which is not owned by this object and must outlive it |
References Filter::payload, and FilterPayload::provideDelayLine().
void provideAllDelayLines | ( | float * | memory | ) |
Or provide them all in one go.
References Filter::getFilterModel(), Filter::getModelConfiguration(), Filter::payload, FilterPayload::provideDelayLine(), and Filter::requiredDelayLinesSizes().
size_t getBlockSize | ( | ) | const |
References FilterPayload::blockSize, and Filter::payload.
|
static |
Some models have coefficient features beyond jsut cutoff and resonance.
For instance the OBXD 4 pole low pass has a continous pole morphing mode (Slope::Slope_Morph). In that case you will need to provide the 'extra' arguments to the makeCoefficients call to get the feature. This function tells you how manu such 'extra' arguments are consumed for a given model/config.
References sst::filtersplusplus::Bell, sst::filtersplusplus::Comb, sst::filtersplusplus::Comb_Bipolar_ContinuousMix, sst::filtersplusplus::CytomicSVF, ModelConfig::dt, sst::filtersplusplus::HighShelf, sst::filtersplusplus::K35, sst::filtersplusplus::K35_Continuous, sst::filtersplusplus::LowShelf, sst::filtersplusplus::OBXD_4Pole, ModelConfig::pt, sst::filtersplusplus::Slope_Morph, and ModelConfig::st.
|
static |
Get a list of the available models supported by the API.
References sst::filtersplusplus::Comb, sst::filtersplusplus::CutoffWarp, sst::filtersplusplus::CytomicSVF, sst::filtersplusplus::DiodeLadder, sst::filtersplusplus::K35, sst::filtersplusplus::None, sst::filtersplusplus::OBXD_2Pole, sst::filtersplusplus::OBXD_4Pole, sst::filtersplusplus::OBXD_Xpander, sst::filtersplusplus::ResonanceWarp, sst::filtersplusplus::SampleAndHold, sst::filtersplusplus::TriPole, sst::filtersplusplus::VemberClassic, sst::filtersplusplus::VemberLadder, and sst::filtersplusplus::VintageLadder.
|
static |
For a given model, return the configurations that model supports.
The list by default will be unsorted, but the sort option allows you to sort it. Note that this is an allocating API to make that vector so you dont want to use it while processing.
References FilterPayload::availableModelConfigurations().
bool prepareInstance | ( | ) |
Once a filter has been set up with a model type and a configuration the instance needs preparation to resolve the internal state.
This function will do so and will return true on success
References FilterPayload::externalDelayLines, FilterPayload::filterModel, FilterPayload::func, sst::filters::fut_none, Filter::getFilterModel(), Filter::getModelConfiguration(), sst::filtersplusplus::None, sst::filtersplusplus::offFun(), Filter::payload, Filter::requiredDelayLinesSizes(), Filter::reset(), FilterPayload::resolveLegacyType(), and FilterPayload::valid.
bool requiresPreparation | ( | ) | const |
If a call to prepareInstance is required, this will return true.
References Filter::payload, and FilterPayload::valid.
void makeCoefficients | ( | int | voice, |
float | cutoff, | ||
float | resonance, | ||
float | extra = 0.f , |
||
float | extra2 = 0.f , |
||
float | extra3 = 0.f |
||
) |
With a given voice, for a given cutoff and resonance, set the internal coefficient state.
This method will allow you to interpolate over blocks so is appropriate for per-block modification of coefficients, but as a result must be called every block before prepareBlock.
References FilterPayload::currentLegacyType, FilterPayload::filterModel, FilterPayload::makers, Filter::payload, and FilterPayload::valid.
Referenced by Filter::makeConstantCoefficients().
void copyCoefficientsFromVoiceToVoice | ( | int | from, |
int | to | ||
) |
If you want two voices to share coefficients - so a stereo pair with the same cutoff and resonance for instance - it is usually faster to copy coefficients from voice A to voice B that it is to compute them twice.
The voices retain independent registers of course, so will still do stereo or quad processing.
References FilterPayload::makers, sst::filters::n_cm_coeffs, and Filter::payload.
void makeConstantCoefficients | ( | int | voice, |
float | cutoff, | ||
float | resonance, | ||
float | extra = 0.f , |
||
float | extra2 = 0.f , |
||
float | extra3 = 0.f |
||
) |
With a given voice, for a given cutoff and resonance, set the internal coefficient state.
This method will assume the coefficients are fixed and so is appropriate for static filter configurations and only needs to be called once, between prepareInstance and prepareBlock, but is not suitable for dynamically changing cutoff and resonance.
References Filter::makeCoefficients(), FilterPayload::makers, sst::filters::n_cm_coeffs, and Filter::payload.
void setActive | ( | int | voice, |
bool | b | ||
) |
The filters can have a concept of an inactive voice which for some filters give a moderate CPU advantage in the SIMD pipelines.
References FilterPayload::active, and Filter::payload.
Referenced by Filter::setMono(), Filter::setQuad(), and Filter::setStereo().
void setMono | ( | ) |
References Filter::setActive().
void setStereo | ( | ) |
References Filter::setActive().
void setQuad | ( | ) |
References Filter::setActive().
void setSampleRateAndBlockSize | ( | double | sampleRate, |
size_t | blockSize | ||
) |
References Filter::payload, and FilterPayload::setSampleRateAndBlockSize().
void prepareBlock | ( | ) |
prepareBlock must be called after coeffients are set but at the start of each block, as set by blockSize in setSampleRateAndBlockSize
References FilterPayload::active, QuadFilterUnitState::active, QuadFilterUnitState::DB, FilterPayload::externalDelayLines, FilterPayload::makers, Filter::payload, FilterPayload::qfuState, FilterPayload::sampleRate, QuadFilterUnitState::sampleRate, FilterPayload::sampleRateInv, and QuadFilterUnitState::sampleRateInv.
SIMD_M128 processSample | ( | SIMD_M128 | in | ) |
once prepare block has been called, you must call processSample exactly blockSize times, mapping the vector value in to the vector value out.
Convenience functions for single float and dual float are below.
References FilterPayload::func, Filter::payload, and FilterPayload::qfuState.
Referenced by Filter::processMonoSample(), Filter::processQuadSample(), and Filter::processStereoSample().
void concludeBlock | ( | ) |
At the end of blockSize samples, and before resetting coefficients or the next call to prepareBlock, you need to call concludeBlock.
References FilterPayload::active, FilterPayload::makers, Filter::payload, and FilterPayload::qfuState.
float processMonoSample | ( | float | in | ) |
convenience functions for mono channel if you dont want to manage simd
References Filter::processSample().
void processStereoSample | ( | float | inL, |
float | inR, | ||
float & | outL, | ||
float & | outR | ||
) |
convenience functions for stereo channel if you dont want to manage simd
References Filter::processSample().
void processQuadSample | ( | float | in[4], |
float | out[4] | ||
) |
convenience functions for quad channel if you dont want to manage simd.
But probably you are better biting the bullet and managing the simd outside
References Filter::processSample().
void init | ( | ) |
Initializes the filter state.
References FilterPayload::init(), and Filter::payload.
void reset | ( | ) |
Resets the filter registers; leaves the rest of the state intact.
References Filter::payload, and FilterPayload::reset().
Referenced by Filter::prepareInstance().
|
static |
References FilterPayload::resolveLegacyTypeFor().
|
protected |
Referenced by Filter::concludeBlock(), Filter::copyCoefficientsFromVoiceToVoice(), Filter::displayName(), Filter::getBlockSize(), Filter::getFilterModel(), Filter::getModelConfiguration(), Filter::init(), Filter::makeCoefficients(), Filter::makeConstantCoefficients(), Filter::prepareBlock(), Filter::prepareInstance(), Filter::processSample(), Filter::provideAllDelayLines(), Filter::provideDelayLine(), Filter::requiresPreparation(), Filter::reset(), Filter::setActive(), Filter::setDriveMode(), Filter::setFilterModel(), Filter::setModelConfiguration(), Filter::setPassband(), Filter::setSampleRateAndBlockSize(), Filter::setSlope(), and Filter::setSubmodel().