mirror of
https://github.com/thestk/stk
synced 2026-01-11 12:01:52 +00:00
implemented changes proposed in #121
This commit is contained in:
@@ -13,10 +13,15 @@ namespace stk {
|
|||||||
Methods are provided for creating a resonance or notch in the
|
Methods are provided for creating a resonance or notch in the
|
||||||
frequency response while maintaining a constant filter gain.
|
frequency response while maintaining a constant filter gain.
|
||||||
|
|
||||||
|
Formulae used calculate coefficients for lowpass, highpass,
|
||||||
|
bandpass, bandreject and allpass are found on pg. 55 of
|
||||||
|
Udo Zölzer's "DAFX - Digital Audio Effects" (2011 2nd ed).
|
||||||
|
|
||||||
by Perry R. Cook and Gary P. Scavone, 1995--2021.
|
by Perry R. Cook and Gary P. Scavone, 1995--2021.
|
||||||
*/
|
*/
|
||||||
/***************************************************/
|
/***************************************************/
|
||||||
|
|
||||||
|
const StkFloat RECIP_SQRT_2 = static_cast<StkFloat>( M_SQRT1_2 );
|
||||||
class BiQuad : public Filter
|
class BiQuad : public Filter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -74,52 +79,72 @@ public:
|
|||||||
*/
|
*/
|
||||||
void setNotch( StkFloat frequency, StkFloat radius );
|
void setNotch( StkFloat frequency, StkFloat radius );
|
||||||
|
|
||||||
//! Set the filter coefficients for a low-pass at \e frequency (in Hz) with factor \e Q.
|
//! Set the filter coefficients for a low-pass with cutoff frequency \e fc (in Hz) and Q-factor \e Q.
|
||||||
/*!
|
/*!
|
||||||
This method determines the filter coefficients corresponding to
|
This method determines the filter coefficients corresponding to a
|
||||||
a low-pass filter with cutoff placed at \e frequency and
|
low-pass filter with cutoff placed at \e fc, where sloping behaviour
|
||||||
Q-factor set by \e Q. Both \e frequency and \e Q must be positive.
|
and resonance are determined by \e Q. The default value for \e Q is
|
||||||
|
1/sqrt(2), resulting in a gradual attenuation of frequencies higher than
|
||||||
|
\e fc without added resonance. Values greater than this will more
|
||||||
|
aggressively attenuate frequencies above \e fc while also adding a
|
||||||
|
resonance at \e fc. Values less than this will result in a more gradual
|
||||||
|
attenuation of frequencies above \e fc, but will also attenuate
|
||||||
|
frequencies below \e fc as well. Both \e fc and \e Q must be positive.
|
||||||
*/
|
*/
|
||||||
void setLowPass( StkFloat frequency, StkFloat Q );
|
void setLowPass( StkFloat fc, StkFloat Q=RECIP_SQRT_2 );
|
||||||
|
|
||||||
//! Set the filter coefficients for a high-pass at \e frequency (in Hz) with factor \e Q.
|
//! Set the filter coefficients for a high-pass with cutoff frequency \e fc (in Hz) and Q-factor \e Q.
|
||||||
/*!
|
/*!
|
||||||
This method determines the filter coefficients corresponding to
|
This method determines the filter coefficients corresponding to a high-pass
|
||||||
a high-pass filter with cutoff placed at \e frequency and
|
filter with cutoff placed at \e fc, where sloping behaviour and resonance
|
||||||
Q-factor set by \e Q. Both \e frequency and \e Q must be positive.
|
are determined by \e Q. The default value for \e Q is 1/sqrt(2), resulting
|
||||||
|
in a gradual attenuation of frequencies lower than \e fc without added
|
||||||
|
resonance. Values greater than this will more aggressively attenuate
|
||||||
|
frequencies below \e fc while also adding a resonance at \e fc. Values less
|
||||||
|
than this will result in a more gradual attenuation of frequencies below
|
||||||
|
\e fc, but will also attenuate frequencies above \e fc as well.
|
||||||
|
Both \e fc and \e Q must be positive.
|
||||||
*/
|
*/
|
||||||
void setHighPass( StkFloat frequency, StkFloat Q );
|
void setHighPass( StkFloat fc, StkFloat Q=RECIP_SQRT_2 );
|
||||||
|
|
||||||
//! Set the filter coefficients for a band-pass at \e frequency (in Hz) with factor \e Q.
|
//! Set the filter coefficients for a band-pass centered at \e fc (in Hz) with Q-factor \e Q.
|
||||||
/*!
|
/*!
|
||||||
This method determines the filter coefficients corresponding to
|
This method determines the filter coefficients corresponding to a band-pass
|
||||||
a band-pass filter with center placed at \e frequency and
|
filter with pass-band centered at \e fc, where band width and slope a
|
||||||
Q-factor set by \e Q. Both \e frequency and \e Q must be positive.
|
determined by \e Q. Values for \e Q that are less than 1.0 will attenuate
|
||||||
|
frequencies above and below \e fc more gradually, resulting in a convex
|
||||||
|
slope and a wider band. Values for \e Q greater than 1.0 will attenuate
|
||||||
|
frequencies above and below \e fc more aggressively, resulting in a
|
||||||
|
concave slope and a narrower band. Both \e fc and \e Q must be positive.
|
||||||
*/
|
*/
|
||||||
void setBandPass( StkFloat frequency, StkFloat Q );
|
void setBandPass( StkFloat fc, StkFloat Q );
|
||||||
|
|
||||||
//! Set the filter coefficients for a band-reject at \e frequency (in Hz) with factor \e Q.
|
//! Set the filter coefficients for a band-reject centered at \e fc (in Hz) with Q-factor \e Q.
|
||||||
/*!
|
/*!
|
||||||
This method determines the filter coefficients corresponding to
|
This method determines the filter coefficients corresponding to a
|
||||||
a band-reject filter with center placed at \e frequency and
|
band-reject filter with stop-band centered at \e fc, where band width
|
||||||
Q-factor set by \e Q. Both \e frequency and \e Q must be positive.
|
and slope are determined by \e Q. Values for \e Q that are less than 1.0
|
||||||
|
will yield a wider band with greater attenuation of \e fc. Values for \e Q
|
||||||
|
greater than 1.0 will yield a narrower band with less attenuation of \e fc.
|
||||||
|
Both \e fc and \e Q must be positive.
|
||||||
*/
|
*/
|
||||||
void setBandReject( StkFloat frequency, StkFloat Q );
|
void setBandReject( StkFloat fc, StkFloat Q );
|
||||||
|
|
||||||
//! Set the filter coefficients for an all-pass at \e frequency (in Hz) with factor \e Q.
|
//! Set the filter coefficients for an all-pass centered at \e fc (in Hz) with Q-factor \e Q.
|
||||||
/*!
|
/*!
|
||||||
This method determines the filter coefficients corresponding to
|
This method determines the filter coefficients corresponding to
|
||||||
an all-pass filter with center placed at \e frequency and
|
an all-pass filter whose phase response crosses -pi radians at \e fc.
|
||||||
Q-factor set by \e Q. Both \e frequency and \e Q must be positive.
|
High values for \e Q will result in a more instantaenous shift in phase
|
||||||
|
response at \e fc. Lower values will result in a more gradual shift in
|
||||||
|
phase response around \e fc. Both \e fc and \e Q must be positive.
|
||||||
*/
|
*/
|
||||||
void setAllPass( StkFloat frequency, StkFloat Q );
|
void setAllPass( StkFloat fc, StkFloat Q );
|
||||||
|
|
||||||
//! Sets the filter zeroes for equal resonance gain.
|
//! Sets the filter zeroes for equal resonance gain.
|
||||||
/*!
|
/*!
|
||||||
When using the filter as a resonator, zeroes places at z = 1, z
|
When using the filter as a resonator, zeroes places at z = 1, z
|
||||||
= -1 will result in a constant gain at resonance of 1 / (1 - R),
|
= -1 will result in a constant gain at resonance of 1 / (1 - R),
|
||||||
where R is the pole radius setting.
|
where R is the pole radius setting.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
void setEqualGainZeroes( void );
|
void setEqualGainZeroes( void );
|
||||||
|
|
||||||
@@ -156,8 +181,8 @@ public:
|
|||||||
virtual void sampleRateChanged( StkFloat newRate, StkFloat oldRate );
|
virtual void sampleRateChanged( StkFloat newRate, StkFloat oldRate );
|
||||||
|
|
||||||
// Helper function to update the three intermediate values for the predefined filter types
|
// Helper function to update the three intermediate values for the predefined filter types
|
||||||
// along with the feedback filter coefficients. Performs the debug check for frequency and Q-factor arguments.
|
// along with the feedback filter coefficients. Performs the debug check for fc and Q-factor arguments.
|
||||||
void setCommonFilterValues( StkFloat frequency, StkFloat Q );
|
void setCommonFilterValues( StkFloat fc, StkFloat Q );
|
||||||
|
|
||||||
StkFloat K_;
|
StkFloat K_;
|
||||||
StkFloat kSqr_;
|
StkFloat kSqr_;
|
||||||
|
|||||||
@@ -98,49 +98,53 @@ void BiQuad :: setNotch( StkFloat frequency, StkFloat radius )
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// This method does not attempt to normalize the filter gain.
|
// This method does not attempt to normalize the filter gain.
|
||||||
b_[2] = radius * radius;
|
b_[0] = 1.0;
|
||||||
b_[1] = (StkFloat) -2.0 * radius * cos( TWO_PI * (double) frequency / Stk::sampleRate() );
|
b_[1] = (StkFloat) -2.0 * radius * cos( TWO_PI * (double) frequency / Stk::sampleRate() );
|
||||||
|
b_[2] = radius * radius;
|
||||||
|
|
||||||
|
a_[1] = 0.0;
|
||||||
|
a_[2] = 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BiQuad :: setLowPass( StkFloat frequency, StkFloat Q )
|
void BiQuad :: setLowPass( StkFloat fc, StkFloat Q )
|
||||||
{
|
{
|
||||||
setCommonFilterValues(frequency, Q);
|
setCommonFilterValues(fc, Q);
|
||||||
|
|
||||||
b_[0] = kSqr_ * Q * denom_;
|
b_[0] = kSqr_ * Q * denom_;
|
||||||
b_[1] = 2 * b_[0];
|
b_[1] = 2 * b_[0];
|
||||||
b_[2] = b_[0];
|
b_[2] = b_[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
void BiQuad :: setHighPass( StkFloat frequency, StkFloat Q )
|
void BiQuad :: setHighPass( StkFloat fc, StkFloat Q )
|
||||||
{
|
{
|
||||||
setCommonFilterValues(frequency, Q);
|
setCommonFilterValues(fc, Q);
|
||||||
|
|
||||||
b_[0] = Q * denom_;
|
b_[0] = Q * denom_;
|
||||||
b_[1] = -2 * b_[0];
|
b_[1] = -2 * b_[0];
|
||||||
b_[2] = b_[0];
|
b_[2] = b_[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
void BiQuad :: setBandPass( StkFloat frequency, StkFloat Q )
|
void BiQuad :: setBandPass( StkFloat fc, StkFloat Q )
|
||||||
{
|
{
|
||||||
setCommonFilterValues(frequency, Q);
|
setCommonFilterValues(fc, Q);
|
||||||
|
|
||||||
b_[0] = K_ * denom_;
|
b_[0] = K_ * denom_;
|
||||||
b_[1] = 0.0;
|
b_[1] = 0.0;
|
||||||
b_[2] = -b_[0];
|
b_[2] = -b_[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
void BiQuad :: setBandReject( StkFloat frequency, StkFloat Q )
|
void BiQuad :: setBandReject( StkFloat fc, StkFloat Q )
|
||||||
{
|
{
|
||||||
setCommonFilterValues(frequency, Q);
|
setCommonFilterValues(fc, Q);
|
||||||
|
|
||||||
b_[0] = Q * (kSqr_ + 1) * denom_;
|
b_[0] = Q * (kSqr_ + 1) * denom_;
|
||||||
b_[1] = 2 * Q * (kSqr_ - 1) * denom_;
|
b_[1] = 2 * Q * (kSqr_ - 1) * denom_;
|
||||||
b_[2] = b_[0];
|
b_[2] = b_[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
void BiQuad :: setAllPass( StkFloat frequency, StkFloat Q )
|
void BiQuad :: setAllPass( StkFloat fc, StkFloat Q )
|
||||||
{
|
{
|
||||||
setCommonFilterValues(frequency, Q);
|
setCommonFilterValues(fc, Q);
|
||||||
|
|
||||||
b_[0] = a_[2];
|
b_[0] = a_[2];
|
||||||
b_[1] = a_[1];
|
b_[1] = a_[1];
|
||||||
@@ -154,11 +158,11 @@ void BiQuad :: setEqualGainZeroes( void )
|
|||||||
b_[2] = -1.0;
|
b_[2] = -1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BiQuad :: setCommonFilterValues( StkFloat frequency, StkFloat Q)
|
void BiQuad :: setCommonFilterValues( StkFloat fc, StkFloat Q)
|
||||||
{
|
{
|
||||||
#if defined(_STK_DEBUG_)
|
#if defined(_STK_DEBUG_)
|
||||||
if ( frequency < 0.0 ) {
|
if ( fc < 0.0 ) {
|
||||||
oStream_ << "BiQuad::updateKValues: frequency argument (" << frequency << ") is negative!";
|
oStream_ << "BiQuad::updateKValues: fc argument (" << fc << ") is negative!";
|
||||||
handleError( StkError::WARNING ); return;
|
handleError( StkError::WARNING ); return;
|
||||||
}
|
}
|
||||||
if ( Q < 0.0 ) {
|
if ( Q < 0.0 ) {
|
||||||
@@ -167,7 +171,7 @@ void BiQuad :: setCommonFilterValues( StkFloat frequency, StkFloat Q)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
K_ = tan(PI * frequency / Stk::sampleRate());
|
K_ = tan(PI * fc / Stk::sampleRate());
|
||||||
kSqr_ = K_ * K_;
|
kSqr_ = K_ * K_;
|
||||||
denom_ = 1 / (kSqr_ * Q + K_ + Q);
|
denom_ = 1 / (kSqr_ * Q + K_ + Q);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user