Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
pulp::signal::TwoPoleResonatorT< SampleType > Class Template Reference

A single decaying resonance: one complex pole pair, excited by whatever the caller feeds it. More...

#include <two_pole_resonator.hpp>

Public Member Functions

 TwoPoleResonatorT ()
void set_sample_rate (double sr)
void set_frequency (double hz)
void set_t60_ms (double ms)
 Time for the ring to fall by 60 dB.
double frequency () const
double t60_ms () const
void reset ()
bool is_ringing () const
 Whether the ring is still above the denormal floor.
SampleType process (SampleType excitation)

Detailed Description

template<typename SampleType = float>
class pulp::signal::TwoPoleResonatorT< SampleType >

A single decaying resonance: one complex pole pair, excited by whatever the caller feeds it.

This is the smallest useful physical model. A struck body rings at a frequency and dies away at a rate, and a two-pole recurrence reproduces exactly that, so a percussion body is an impulse into one of these rather than an oscillator plus an envelope. The difference is audible: an oscillator with a decay envelope restarts at a known phase and decays on a schedule, while a resonator's ring is a function of what excited it, so the same body struck by a click and by a noise burst sounds different, and a second strike during the tail interferes with what is already ringing instead of replacing it.

ModalBankT is the same mathematics for many modes at once, laid out for SIMD and driven a block at a time. Use the bank for a body with a spectrum (a membrane, a plate, a shell); use this when there is one resonance and the surrounding code is per-sample.

The decay is specified as a T60 because that is how long a body is heard to ring.

Excitation is scaled by the sine of the pole angle, which makes the ring's peak roughly the excitation's amplitude at any tuning and any decay. Both normalisations that look more obvious are traps. Unit input gain leaves the impulse response peaking at one over that sine, so a body tuned to 50 Hz rings about fifty times louder than the same body at 5 kHz and the tuning knob becomes a volume knob. Scaling by one minus the pole radius normalises a sustained tone instead, which makes a longer decay produce a quieter strike. This scaling leaves the two controls doing only what they are named for.

RT contract: every member allocates nothing and takes no locks. The frequency and decay may be changed per sample; the state is the ring itself, so a coefficient change carries it rather than reinterpreting it.

Constructor & Destructor Documentation

◆ TwoPoleResonatorT()

template<typename SampleType = float>
pulp::signal::TwoPoleResonatorT< SampleType >::TwoPoleResonatorT ( )
inline

Member Function Documentation

◆ frequency()

template<typename SampleType = float>
double pulp::signal::TwoPoleResonatorT< SampleType >::frequency ( ) const
inline

◆ is_ringing()

template<typename SampleType = float>
bool pulp::signal::TwoPoleResonatorT< SampleType >::is_ringing ( ) const
inline

Whether the ring is still above the denormal floor.

A voice uses this to know the body has finished without tracking a separate envelope.

◆ process()

template<typename SampleType = float>
SampleType pulp::signal::TwoPoleResonatorT< SampleType >::process ( SampleType excitation)
inline

◆ reset()

template<typename SampleType = float>
void pulp::signal::TwoPoleResonatorT< SampleType >::reset ( )
inline

◆ set_frequency()

template<typename SampleType = float>
void pulp::signal::TwoPoleResonatorT< SampleType >::set_frequency ( double hz)
inline

◆ set_sample_rate()

template<typename SampleType = float>
void pulp::signal::TwoPoleResonatorT< SampleType >::set_sample_rate ( double sr)
inline

◆ set_t60_ms()

template<typename SampleType = float>
void pulp::signal::TwoPoleResonatorT< SampleType >::set_t60_ms ( double ms)
inline

Time for the ring to fall by 60 dB.

◆ t60_ms()

template<typename SampleType = float>
double pulp::signal::TwoPoleResonatorT< SampleType >::t60_ms ( ) const
inline

The documentation for this class was generated from the following file: