From 950913e3af6c668c9564d5bc20dd1874d445e64d Mon Sep 17 00:00:00 2001 From: Lord-Nightmare Date: Wed, 17 Jul 2024 21:45:24 -0400 Subject: Add protection against biquad filters producing aliased output or other noise if the stream sample rate is below the cutoff of the filter. Converted to use logmacro.h and added some additional optional log messages. Fix some incorrect calculations for the MFB band-pass filter parameters. [Lord Nightmare] --- src/devices/sound/flt_biquad.cpp | 363 +++++++++++++++++++++------------------ 1 file changed, 194 insertions(+), 169 deletions(-) diff --git a/src/devices/sound/flt_biquad.cpp b/src/devices/sound/flt_biquad.cpp index 6ae1bde0109..f74bf6bae73 100644 --- a/src/devices/sound/flt_biquad.cpp +++ b/src/devices/sound/flt_biquad.cpp @@ -11,7 +11,7 @@ This biquad filter implementation is based on one written by Frank Palazzolo, K. Wilkins, Couriersud, and Derrick Renaud, with some changes: - * It uses the Q factor directly in the filter definitions, rather than the damping factor (1/Q) + * It uses the Q factor directly in the filter definitions, rather than the damping factor (1/2Q) * It implements every common type of digital biquad filter which I could find documentation for. * The filter is Direct-form II instead of Direct-form I, which results in shorter compiled code. * Optional direct control of the 5 normalized biquad parameters for a custom/raw parameter filter. @@ -23,14 +23,23 @@ #include "emu.h" #include "flt_biquad.h" +// enable this to display debug info about the filters being set up +#define LOG_SETUP (1U << 1) +// enable this to display the filter parameters upon being recalculated +#define LOG_PARAMS (1U << 2) +// enable this to display the biquad parameters upon being recalculated +#define LOG_CALC (1U << 3) + +#define LOG_ALL (LOG_SETUP|LOG_PARAMS|LOG_CALC) + +//#define VERBOSE (LOG_SETUP) +#include "logmacro.h" + // we need the M_SQRT2 constant #ifndef M_SQRT2 #define M_SQRT2 1.41421356237309504880 #endif -// define this to display debug info about the filters being set up -#undef FLT_BIQUAD_DEBUG_SETUP - // device type definition DEFINE_DEVICE_TYPE(FILTER_BIQUAD, filter_biquad_device, "filter_biquad", "Biquad Filter") @@ -134,6 +143,9 @@ void filter_biquad_device::modify_raw(double a1, double a2, double b0, double b1 //------------------------------------------------- // NOTE: if a resistor doesn't exist, pass a value of RES_M(999.99) or the like, i.e. an 'infinite resistor' // NOTE: if a resistor is a direct short, set its resistance to RES_R(0.001) +// NOTE: in all of these filters, vRef is not definable when setting up the filter. +// If the analog effects caused by vRef are important to the operation of the specific filter +// in question, a netlist implementation may work better under those circumstances. // Sallen-Key filters @@ -186,24 +198,22 @@ filter_biquad_device::biquad_params filter_biquad_device::opamp_sk_lowpass_calc( r.gain = 1.0 + (r4 / r3); // == (r3 + r4) / r3 r.fc = 1.0 / (2 * M_PI * sqrt(r1 * r2 * c1 * c2)); r.q = sqrt(r1 * r2 * c1 * c2) / ((r1 * c2) + (r2 * c2) + ((r2 * c1) * (1.0 - r.gain))); -#ifdef FLT_BIQUAD_DEBUG_SETUP - logerror("filter_biquad_device::opamp_sk_lowpass_calc(%f, %f, %f, %f, %f, %f) yields: fc = %f, Q = %f, gain = %f\n", r1, r2, r3, r4, c1*1000000, c2*1000000, r.fc, r.q, r.gain); -#endif + LOGMASKED(LOG_SETUP,"filter_biquad_device::opamp_sk_lowpass_calc(%f, %f, %f, %f, %f, %f) yields: fc = %f, Q = %f, gain = %f\n", r1, r2, r3, r4, c1*1000000, c2*1000000, r.fc, r.q, r.gain); return r; } +// TODO when needed: Sallen-Key high-pass filter + // Multiple-Feedback filters /* Setup a biquad filter structure based on a single op-amp Multiple-Feedback low-pass filter circuit. * This is sometimes called a "Rauch" filter circuit. - * NOTE: vRef is not definable when setting up the filter. - * If the analog effects caused by vRef are important to the operation of the specific - * filter in question, a netlist implementation may work better under those circumstances. - * NOTE2: There is a well known 'proper' 1st order version of this circuit where r2 is - * a dead short, and c1 omitted. set both c1 and r2 to 0 in this case. - * NOTE3: a variant of NOTE2 has only the c1 capacitor left off, and r2 present. if so, - * set c1 to 0 and r2 to its expected value. + * NOTE: There is a well known 'proper' 1st order version of this circuit where + * r2 is a dead short, and c1 omitted. As an exception to the usual rule about + * missing components, set both c1 and r2 to 0 in this case. + * NOTE: There is a variant of this filter with the c1 capacitor left off, and + * r2 present. if so, set c1 to 0 and r2 to its expected value. * TODO: make this compatible with the RES_M(999.99) and RES_R(0.001) rules! * * .--------+---------. @@ -252,22 +262,17 @@ filter_biquad_device::biquad_params filter_biquad_device::opamp_mfb_lowpass_calc r.q = sqrt(r2 * r3 * c1 * c2) / ((r3 * c2) + (r2 * c2) + ((r2 * c2) * -r.gain)); r.type = biquad_type::LOWPASS; } -#ifdef FLT_BIQUAD_DEBUG_SETUP - logerror("filter_biquad_device::opamp_mfb_lowpass_calc(%f, %f, %f, %f, %f) yields:\n\ttype = %d, fc = %f, Q = %f, gain = %f\n", r1, r2, r3, c1*1000000, c2*1000000, static_cast(r.type), r.fc, r.q, r.gain); -#endif + LOGMASKED(LOG_SETUP,"filter_biquad_device::opamp_mfb_lowpass_calc(%f, %f, %f, %f, %f) yields:\n\ttype = %d, fc = %f, Q = %f, gain = %f\n", r1, r2, r3, c1*1000000, c2*1000000, static_cast(r.type), r.fc, r.q, r.gain); return r; } /* Setup a biquad filter structure based on a single op-amp Multiple-Feedback band-pass filter circuit. * This is sometimes called a "modified Deliyannis" or "Deliyannis-friend" filter circuit, * or an "Infinite Gain Multiple-Feedback [band-pass] Filter" aka "IGMF". - * NOTE: vRef is not definable when setting up the filter, and is assumed to be grounded. - * If the analog effects caused by vRef are important to the operation of the specific filter - * in question, a netlist implementation may work better under those circumstances. * TODO: There is a documented modification to this filter which adds a resistor ladder between * ground and the op-amp output, with the 'rung' of the ladder connecting to the + input of * the op-amp, and this allows more control of the filter. - * NOTE2: If r2 is not used, then set it to RES_M(999.99), the code will effectively be an Infinite Gain MFB Bandpass. + * NOTE2: If r2 is not present, then set it to RES_M(999.99), the code will effectively be an Infinite Gain MFB Bandpass. * * .--------+---------. * | | | @@ -290,23 +295,15 @@ filter_biquad_device& filter_biquad_device::opamp_mfb_bandpass_setup(double r1, fatalerror("filter_biquad_device::opamp_mfb_bandpass_setup() - no parameters can be 0; parameters were: r1: %f, r2: %f, r3: %f, c1: %f, c2: %f", r1, r2, r3, c1, c2); /* Filter can not be setup. Undefined results. */ } - double const r_in = 1.0 / (1.0/r1 + 1.0/r2); // TODO: verify - // gain = (r2 / (r1 + r2)) * (-r3 / r_in * c2 / (c1 + c2)); // ??? wrong? - double const gain = -r3 / (2.0 * r1); - // q = sqrt(r3 / r_in * c1 * c2) / (c1 + c2); // ??? wrong? - double const q = 0.5 * sqrt(r3 / r1); - - double const fc = 1.0 / (sqrt(r_in * r3 * c1 * c2)); // technically this is the center frequency of the bandpass -#ifdef FLT_BIQUAD_DEBUG_SETUP - logerror("filter_biquad_device::opamp_mfb_bandpass_setup() yields: fc = %f, Q = %f, gain = %f\n", fc, q, gain); -#endif + double const r_in = 1.0 / ((1.0 / r1) + (1.0 / r2)); + double const gain = (r3 / r1) * (-c2 / (c1 + c2)); + double const q = sqrt((r3 / r_in) * c1 * c2) / (c1 + c2); + double const fc = 1.0 / (2 * M_PI * sqrt(r_in * r3 * c1 * c2)); // technically this is the center frequency of the bandpass + LOGMASKED(LOG_SETUP,"filter_biquad_device::opamp_mfb_bandpass_setup() yields: fc = %f, Q = %f, gain = %f\n", fc, q, gain); return setup(biquad_type::BANDPASS, fc, q, gain); } /* Setup a biquad filter structure based on a single op-amp Multiple-Feedback high-pass filter circuit. - * NOTE: vRef is not definable when setting up the filter. - * If the analog effects caused by vRef are important to the operation of the specific filter - * in question, a netlist implementation may work better under those circumstances. * * .--------+---------. * | | | @@ -332,17 +329,14 @@ filter_biquad_device& filter_biquad_device::opamp_mfb_highpass_setup(double r1, double const gain = -c1 / c3; double const fc = 1.0 / (2 * M_PI * sqrt(c2 * c3 * r1 * r2)); double const q = sqrt(c2 * c3 * r1 * r2) / ((c2 * r1) + (c3 * r1) + ((c3 * r1) * -gain)); -#ifdef FLT_BIQUAD_DEBUG_SETUP - logerror("filter_biquad_device::opamp_mfb_highpass_setup() yields: fc = %f, Q = %f, gain = %f\n", fc, q, gain); -#endif + LOGMASKED(LOG_SETUP,"filter_biquad_device::opamp_mfb_highpass_setup() yields: fc = %f, Q = %f, gain = %f\n", fc, q, gain); return setup(biquad_type::HIGHPASS, fc, q, gain); } +// Differentiator Filter + /* Setup a biquad filter structure based on a single op-amp Differentiator band-pass filter circuit. * This circuit is sometimes called an "Inverting Band Pass Filter Circuit" - * NOTE: vRef is not definable when setting up the filter. - * If the analog effects caused by vRef are important to the operation of the specific filter - * in question, a netlist implementation may work better under those circumstances. * * .--------+---------. * | | | @@ -384,9 +378,7 @@ filter_biquad_device::biquad_params filter_biquad_device::opamp_diff_bandpass_ca r.fc = pow(10.0, fct); r.q = r.fc / (f2 - f1); r.type = biquad_type::BANDPASS; -#ifdef FLT_BIQUAD_DEBUG_SETUP - logerror("filter_biquad_device::opamp_diff_bandpass_calc(%f, %f, %f, %f) yields:\n\ttype = %d, fc = %f (f1 = %f, f2 = %f), Q = %f, gain = %f\n", r1, r2, c1*1000000, c2*1000000, static_cast(r.type), r.fc, f1, f2, r.q, r.gain); -#endif + LOGMASKED(LOG_SETUP,"filter_biquad_device::opamp_diff_bandpass_calc(%f, %f, %f, %f) yields:\n\ttype = %d, fc = %f (f1 = %f, f2 = %f), Q = %f, gain = %f\n", r1, r2, c1*1000000, c2*1000000, static_cast(r.type), r.fc, f1, f2, r.q, r.gain); return r; } @@ -445,139 +437,174 @@ void filter_biquad_device::sound_stream_update(sound_stream &stream, std::vector /* Calculate the filter context based on the passed filter type info. * m_type - 1 of the 9 defined filter types - * m_fc - center frequency - * m_q - 'Q' (quality) factor of filter (1/damp) + * m_fc - cutoff or center frequency + * m_q - 'Q' (quality) factor of filter (1/(2*damp)) * m_gain - overall filter gain. Set to 1.0 if not needed. The exact meaning of gain changes depending on the filter type. */ void filter_biquad_device::recalc() { + LOGMASKED(LOG_PARAMS,"Filter type is: %d\n",static_cast(m_type)); if (m_type == biquad_type::RAWPARAMS) return; // if we're dealing with raw parameters, just return, don't touch anything. - - double const MGain = fabs(m_gain); // absolute multiplicative gain - double const DBGain = log10(MGain) * 20.0; // gain in dB - double const AMGain = pow(10, fabs(DBGain) / 20.0); // multiplicative gain of absolute DB - double const K = tan(M_PI * m_fc / m_stream->sample_rate()); - double const Ksquared = K * K; - double const KoverQ = K / m_q; - double normal = 1.0 / (1.0 + KoverQ + Ksquared); - - switch (m_type) + LOGMASKED(LOG_PARAMS,"Filter cutoff is: %f Hz\n",m_fc); + LOGMASKED(LOG_PARAMS,"Filter Q factor is: %f (damping ratio is: %f)\n",m_q,(1.0/(2.0*m_q))); + LOGMASKED(LOG_PARAMS,"Filter (multiplicative) gain is: %f\n",m_gain); + LOGMASKED(LOG_PARAMS,"Stream sample rate is: %f\n",m_stream->sample_rate()); + + // if the nyquist frequency of the stream sample rate is below the cutoff, + // we need to sanely bail out or we'll get all sorts of horrible aliasing + // and noise. + if (m_fc >= m_stream->sample_rate() / 2.0) { - case biquad_type::LOWPASS1P: - m_a1 = exp(-2.0 * M_PI * (m_fc / m_stream->sample_rate())); - m_b0 = 1.0 - m_a1; - m_a1 = -m_a1; - m_b1 = m_b2 = m_a2 = 0.0; - break; - case biquad_type::HIGHPASS1P: - m_a1 = -exp(-2.0 * M_PI * (0.5 - m_fc / m_stream->sample_rate())); - m_b0 = 1.0 + m_a1; - m_a1 = -m_a1; - m_b1 = m_b2 = m_a2 = 0.0; - break; - case biquad_type::LOWPASS: - m_b0 = Ksquared * normal; - m_b1 = 2.0 * m_b0; - m_b2 = 1.0 * m_b0; - m_a1 = 2.0 * (Ksquared - 1.0) * normal; - m_a2 = (1.0 - KoverQ + Ksquared) * normal; - break; - case biquad_type::HIGHPASS: - m_b0 = 1.0 * normal; - m_b1 = -2.0 * m_b0; - m_b2 = 1.0 * m_b0; - m_a1 = 2.0 * (Ksquared - 1.0) * normal; - m_a2 = (1.0 - KoverQ + Ksquared) * normal; - break; - case biquad_type::BANDPASS: - m_b0 = KoverQ * normal; - m_b1 = 0.0; - m_b2 = -1.0 * m_b0; - m_a1 = 2.0 * (Ksquared - 1.0) * normal; - m_a2 = (1.0 - KoverQ + Ksquared) * normal; - break; - case biquad_type::NOTCH: - m_b0 = (1.0 + Ksquared) * normal; - m_b1 = 2.0 * (Ksquared - 1.0) * normal; - m_b2 = 1.0 * m_b0; - m_a1 = 1.0 * m_b1; - m_a2 = (1.0 - KoverQ + Ksquared) * normal; - break; - case biquad_type::PEAK: - if (DBGain >= 0.0) - { - m_b0 = (1.0 + (AMGain * KoverQ) + Ksquared) * normal; - m_b1 = 2.0 * (Ksquared - 1.0) * normal; - m_b2 = (1.0 - (AMGain * KoverQ) + Ksquared) * normal; - m_a1 = 1.0 * m_b1; + switch (m_type) + { + // For lowpass and friends, just let the signal through unchanged. + case biquad_type::LOWPASS1P: + case biquad_type::LOWPASS: + case biquad_type::NOTCH: + case biquad_type::LOWSHELF: + default: + m_b0 = 1.0; + break; + // For highpass and friends, block the entire signal. + case biquad_type::HIGHPASS1P: + case biquad_type::HIGHPASS: + case biquad_type::BANDPASS: + case biquad_type::PEAK: + case biquad_type::HIGHSHELF: + m_b0 = 0.0; + break; + } + m_a1 = m_a2 = 0.0; + m_b1 = m_b2 = 0.0; + LOGMASKED(LOG_CALC,"Warning: Nyquist frequency of the stream sample rate is below the filter cutoff!\n"); + LOGMASKED(LOG_CALC,"Filter is mostly disabled (except for gain), and output is forced to %f * input [* gain]!\n", m_b0); + } + else + { + double const MGain = fabs(m_gain); // absolute multiplicative gain + double const DBGain = log10(MGain) * 20.0; // gain in dB + double const AMGain = pow(10, fabs(DBGain) / 20.0); // multiplicative gain of absolute DB + double const K = tan(M_PI * m_fc / m_stream->sample_rate()); + double const Ksquared = K * K; + double const KoverQ = K / m_q; + double normal = 1.0 / (1.0 + KoverQ + Ksquared); + + switch (m_type) + { + case biquad_type::LOWPASS1P: + m_a1 = exp(-2.0 * M_PI * (m_fc / m_stream->sample_rate())); + m_b0 = 1.0 - m_a1; + m_a1 = -m_a1; + m_b1 = m_b2 = m_a2 = 0.0; + break; + case biquad_type::HIGHPASS1P: + m_a1 = -exp(-2.0 * M_PI * (0.5 - m_fc / m_stream->sample_rate())); + m_b0 = 1.0 + m_a1; + m_a1 = -m_a1; + m_b1 = m_b2 = m_a2 = 0.0; + break; + case biquad_type::LOWPASS: + m_b0 = Ksquared * normal; + m_b1 = 2.0 * m_b0; + m_b2 = 1.0 * m_b0; + m_a1 = 2.0 * (Ksquared - 1.0) * normal; m_a2 = (1.0 - KoverQ + Ksquared) * normal; - } - else - { - normal = 1.0 / (1.0 + (AMGain * KoverQ) + Ksquared); - m_b0 = (1.0 + KoverQ + Ksquared) * normal; - m_b1 = 2.0 * (Ksquared - 1.0) * normal; - m_b2 = (1.0 - KoverQ + Ksquared) * normal; - m_a1 = 1.0 * m_b1; - m_a2 = (1.0 - (AMGain * KoverQ) + Ksquared) * normal; - } - break; - case biquad_type::LOWSHELF: - if (DBGain >= 0.0) - { - normal = 1.0 / (1.0 + M_SQRT2 * K + Ksquared); - m_b0 = (1.0 + sqrt(2.0 * AMGain) * K + AMGain * Ksquared) * normal; - m_b1 = 2.0 * (AMGain * Ksquared - 1.0) * normal; - m_b2 = (1.0 - sqrt(2.0 * AMGain) * K + AMGain * Ksquared) * normal; + break; + case biquad_type::HIGHPASS: + m_b0 = 1.0 * normal; + m_b1 = -2.0 * m_b0; + m_b2 = 1.0 * m_b0; m_a1 = 2.0 * (Ksquared - 1.0) * normal; - m_a2 = (1.0 - M_SQRT2 * K + Ksquared) * normal; - } - else - { - normal = 1.0 / (1.0 + sqrt(2.0 * AMGain) * K + AMGain * Ksquared); - m_b0 = (1.0 + M_SQRT2 * K + Ksquared) * normal; - m_b1 = 2.0 * (Ksquared - 1.0) * normal; - m_b2 = (1.0 - M_SQRT2 * K + Ksquared) * normal; - m_a1 = 2.0 * (AMGain * Ksquared - 1.0) * normal; - m_a2 = (1.0 - sqrt(2.0 * AMGain) * K + AMGain * Ksquared) * normal; - } - break; - case biquad_type::HIGHSHELF: - if (DBGain >= 0.0) - { - normal = 1.0 / (1.0 + M_SQRT2 * K + Ksquared); - m_b0 = (AMGain + sqrt(2.0 * AMGain) * K + Ksquared) * normal; - m_b1 = 2.0 * (Ksquared - AMGain) * normal; - m_b2 = (AMGain - sqrt(2.0 * AMGain) * K + Ksquared) * normal; + m_a2 = (1.0 - KoverQ + Ksquared) * normal; + break; + case biquad_type::BANDPASS: + m_b0 = KoverQ * normal; + m_b1 = 0.0; + m_b2 = -1.0 * m_b0; m_a1 = 2.0 * (Ksquared - 1.0) * normal; - m_a2 = (1.0 - M_SQRT2 * K + Ksquared) * normal; - } - else - { - normal = 1.0 / (AMGain + sqrt(2.0 * AMGain) * K + Ksquared); - m_b0 = (1.0 + M_SQRT2 * K + Ksquared) * normal; + m_a2 = (1.0 - KoverQ + Ksquared) * normal; + break; + case biquad_type::NOTCH: + m_b0 = (1.0 + Ksquared) * normal; m_b1 = 2.0 * (Ksquared - 1.0) * normal; - m_b2 = (1.0 - M_SQRT2 * K + Ksquared) * normal; - m_a1 = 2.0 * (Ksquared - AMGain) * normal; - m_a2 = (AMGain - sqrt(2.0 * AMGain) * K + Ksquared) * normal; - } - break; - default: - fatalerror("filter_biquad_device::recalc() - Invalid filter type!"); - break; + m_b2 = 1.0 * m_b0; + m_a1 = 1.0 * m_b1; + m_a2 = (1.0 - KoverQ + Ksquared) * normal; + break; + case biquad_type::PEAK: + if (DBGain >= 0.0) + { + m_b0 = (1.0 + (AMGain * KoverQ) + Ksquared) * normal; + m_b1 = 2.0 * (Ksquared - 1.0) * normal; + m_b2 = (1.0 - (AMGain * KoverQ) + Ksquared) * normal; + m_a1 = 1.0 * m_b1; + m_a2 = (1.0 - KoverQ + Ksquared) * normal; + } + else + { + normal = 1.0 / (1.0 + (AMGain * KoverQ) + Ksquared); + m_b0 = (1.0 + KoverQ + Ksquared) * normal; + m_b1 = 2.0 * (Ksquared - 1.0) * normal; + m_b2 = (1.0 - KoverQ + Ksquared) * normal; + m_a1 = 1.0 * m_b1; + m_a2 = (1.0 - (AMGain * KoverQ) + Ksquared) * normal; + } + break; + case biquad_type::LOWSHELF: + if (DBGain >= 0.0) + { + normal = 1.0 / (1.0 + M_SQRT2 * K + Ksquared); + m_b0 = (1.0 + sqrt(2.0 * AMGain) * K + AMGain * Ksquared) * normal; + m_b1 = 2.0 * (AMGain * Ksquared - 1.0) * normal; + m_b2 = (1.0 - sqrt(2.0 * AMGain) * K + AMGain * Ksquared) * normal; + m_a1 = 2.0 * (Ksquared - 1.0) * normal; + m_a2 = (1.0 - M_SQRT2 * K + Ksquared) * normal; + } + else + { + normal = 1.0 / (1.0 + sqrt(2.0 * AMGain) * K + AMGain * Ksquared); + m_b0 = (1.0 + M_SQRT2 * K + Ksquared) * normal; + m_b1 = 2.0 * (Ksquared - 1.0) * normal; + m_b2 = (1.0 - M_SQRT2 * K + Ksquared) * normal; + m_a1 = 2.0 * (AMGain * Ksquared - 1.0) * normal; + m_a2 = (1.0 - sqrt(2.0 * AMGain) * K + AMGain * Ksquared) * normal; + } + break; + case biquad_type::HIGHSHELF: + if (DBGain >= 0.0) + { + normal = 1.0 / (1.0 + M_SQRT2 * K + Ksquared); + m_b0 = (AMGain + sqrt(2.0 * AMGain) * K + Ksquared) * normal; + m_b1 = 2.0 * (Ksquared - AMGain) * normal; + m_b2 = (AMGain - sqrt(2.0 * AMGain) * K + Ksquared) * normal; + m_a1 = 2.0 * (Ksquared - 1.0) * normal; + m_a2 = (1.0 - M_SQRT2 * K + Ksquared) * normal; + } + else + { + normal = 1.0 / (AMGain + sqrt(2.0 * AMGain) * K + Ksquared); + m_b0 = (1.0 + M_SQRT2 * K + Ksquared) * normal; + m_b1 = 2.0 * (Ksquared - 1.0) * normal; + m_b2 = (1.0 - M_SQRT2 * K + Ksquared) * normal; + m_a1 = 2.0 * (Ksquared - AMGain) * normal; + m_a2 = (AMGain - sqrt(2.0 * AMGain) * K + Ksquared) * normal; + } + break; + default: + fatalerror("filter_biquad_device::recalc() - Invalid filter type!"); + break; + } + LOGMASKED(LOG_CALC,"Calculated Parameters:\n"); + LOGMASKED(LOG_CALC,"Gain (dB): %f, (raw): %f\n", DBGain, MGain); + LOGMASKED(LOG_CALC,"k: %f\n", K); + LOGMASKED(LOG_CALC,"normal: %f\n", normal); + LOGMASKED(LOG_CALC,"b0: %f\n", m_b0); + LOGMASKED(LOG_CALC,"b1: %f\n", m_b1); + LOGMASKED(LOG_CALC,"b2: %f\n", m_b2); + LOGMASKED(LOG_CALC,"a1: %f\n", m_a1); + LOGMASKED(LOG_CALC,"a2: %f\n", m_a2); } -#ifdef FLT_BIQUAD_DEBUG - logerror("Calculated Parameters:\n"); - logerror( "Gain (dB): %f, (raw): %f\n", DBGain, MGain); - logerror( "k: %f\n", K); - logerror( "normal: %f\n", normal); - logerror("b0: %f\n", m_b0); - logerror("b1: %f\n", m_b1); - logerror("b2: %f\n", m_b2); - logerror("a1: %f\n", m_a1); - logerror("a2: %f\n", m_a2); -#endif // peak and shelf filters do not use gain for the entire signal, only for the peak/shelf portions // side note: the first order lowpass and highpass filter analogs technically don't have gain either, // but this can be 'faked' by adjusting the bx factors, so we support that anyway, even if it isn't realistic. @@ -588,11 +615,9 @@ void filter_biquad_device::recalc() m_b0 *= m_gain; m_b1 *= m_gain; m_b2 *= m_gain; -#ifdef FLT_BIQUAD_DEBUG - logerror("b0g: %f\n", m_b0); - logerror("b1g: %f\n", m_b1); - logerror("b2g: %f\n", m_b2); -#endif + LOGMASKED(LOG_CALC,"b0g: %f\n", m_b0); + LOGMASKED(LOG_CALC,"b1g: %f\n", m_b1); + LOGMASKED(LOG_CALC,"b2g: %f\n", m_b2); } } -- cgit v1.2.3