sst-filters
Filters submodule for the Surge Synthesizer
Loading...
Searching...
No Matches
Public Types | Public Member Functions | Static Public Member Functions | Protected Attributes | List of all members
Filter Struct Reference

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< FilterModelavailableModels ()
 Get a list of the available models supported by the API.
 
static std::vector< ModelConfigavailableModelConfigurations (FilterModel model, bool sort=false)
 For a given model, return the configurations that model supports.
 
static std::optional< legacyType_tgetLegacyTypeFor (const FilterModel &m, const ModelConfig &c)
 

Protected Attributes

details::FilterPayload payload
 

Detailed Description

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

namespace sfpp = sst::filtersplusplus;
auto filter = sfpp::Filter();
filter.setSampleRateAndBlockSize(48000, 16);
filter.setFilterModel(sfpp::FilterModel::OBXD_4Pole);
filter.setPassband(sfpp::Passband::LP);
filter.setSlope(sfpp::Slope::Slope_18dB);
if (!filter.prepareInstance())
REQUIRE(false);
size_t blockPos{0};
for (int i=0; i<100; ++i)
{
if (blockPos == 0)
{
for (int v=0; v<4; ++v)
{
filter.makeCoefficients(v, -9, 0.1 + v * 0.2);
}
filter.prepareBlock();
}
auto out = filter.processSample(SIMD_MM(setzero_ps)());
blockPos ++;
if (blockPos == filter.getBlockSize())
{
filter.concludeBlock();
blockPos = 0;
}
}
#define REQUIRE(...)
Definition catch2.hpp:17659
Definition api.h:29

Member Typedef Documentation

◆ legacyType_t

This API connects us to the legacy enum types for a given model.

Member Function Documentation

◆ setFilterModel()

void setFilterModel ( FilterModel  model)

◆ getFilterModel()

FilterModel getFilterModel ( ) const

◆ setPassband()

void setPassband ( Passband  type)

◆ setSlope()

void setSlope ( Slope  slope)

◆ setDriveMode()

void setDriveMode ( DriveMode  drive)

◆ setSubmodel()

void setSubmodel ( FilterSubModel  smt)

◆ setModelConfiguration()

void setModelConfiguration ( const ModelConfig sk)

◆ getModelConfiguration()

ModelConfig getModelConfiguration ( ) const

◆ displayName()

std::string displayName ( ) const

A reasonable user facing display name for the given configuration.

References FilterPayload::displayName(), and Filter::payload.

◆ requiredDelayLinesSizes()

size_t requiredDelayLinesSizes ( FilterModel  model,
const ModelConfig k 
)
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.

Parameters
modelWhich model
kConfigured how
Returns
how many floats must the delay line have

References sst::filtersplusplus::Comb, SincTable::FIRipol_N, and sst::filters::utilities::MAX_FB_COMB.

Referenced by Filter::prepareInstance(), and Filter::provideAllDelayLines().

◆ provideDelayLine()

void provideDelayLine ( int  voice,
float *  memory 
)

If a delay line is needed, each active voice requires one.

Parameters
voiceEach voice needs a distinct buffer
memoryThis is a pointer to memory which is not owned by this object and must outlive it

References Filter::payload, and FilterPayload::provideDelayLine().

◆ provideAllDelayLines()

void provideAllDelayLines ( float *  memory)

◆ getBlockSize()

size_t getBlockSize ( ) const

◆ coefficientsExtraCount()

int coefficientsExtraCount ( FilterModel  model,
const ModelConfig c 
)
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.

◆ availableModels()

std::vector< FilterModel > availableModels ( )
static

◆ availableModelConfigurations()

static std::vector< ModelConfig > availableModelConfigurations ( FilterModel  model,
bool  sort = false 
)
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().

◆ prepareInstance()

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.

◆ requiresPreparation()

bool requiresPreparation ( ) const

If a call to prepareInstance is required, this will return true.

References Filter::payload, and FilterPayload::valid.

◆ makeCoefficients()

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().

◆ copyCoefficientsFromVoiceToVoice()

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.

◆ makeConstantCoefficients()

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.

◆ setActive()

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().

◆ setMono()

void setMono ( )

References Filter::setActive().

◆ setStereo()

void setStereo ( )

References Filter::setActive().

◆ setQuad()

void setQuad ( )

References Filter::setActive().

◆ setSampleRateAndBlockSize()

void setSampleRateAndBlockSize ( double  sampleRate,
size_t  blockSize 
)

◆ prepareBlock()

void prepareBlock ( )

◆ processSample()

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().

◆ concludeBlock()

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.

◆ processMonoSample()

float processMonoSample ( float  in)

convenience functions for mono channel if you dont want to manage simd

References Filter::processSample().

◆ processStereoSample()

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().

◆ processQuadSample()

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().

◆ init()

void init ( )

Initializes the filter state.

References FilterPayload::init(), and Filter::payload.

◆ reset()

void reset ( )

Resets the filter registers; leaves the rest of the state intact.

References Filter::payload, and FilterPayload::reset().

Referenced by Filter::prepareInstance().

◆ getLegacyTypeFor()

static std::optional< legacyType_t > getLegacyTypeFor ( const FilterModel m,
const ModelConfig c 
)
static

Member Data Documentation

◆ payload

details::FilterPayload payload
protected

The documentation for this struct was generated from the following files: