mirror of
https://github.com/holub/mame
synced 2025-06-15 08:57:05 +03:00
Removed specific filter implementation and merged it with placed where used (nw)
This commit is contained in:
parent
583eaef9f0
commit
97a195ef03
@ -205,8 +205,6 @@ files {
|
|||||||
MAME_DIR .. "src/emu/debug/express.h",
|
MAME_DIR .. "src/emu/debug/express.h",
|
||||||
MAME_DIR .. "src/emu/debug/textbuf.cpp",
|
MAME_DIR .. "src/emu/debug/textbuf.cpp",
|
||||||
MAME_DIR .. "src/emu/debug/textbuf.h",
|
MAME_DIR .. "src/emu/debug/textbuf.h",
|
||||||
MAME_DIR .. "src/emu/sound/filter.cpp",
|
|
||||||
MAME_DIR .. "src/emu/sound/filter.h",
|
|
||||||
MAME_DIR .. "src/emu/sound/wavwrite.cpp",
|
MAME_DIR .. "src/emu/sound/wavwrite.cpp",
|
||||||
MAME_DIR .. "src/emu/sound/wavwrite.h",
|
MAME_DIR .. "src/emu/sound/wavwrite.h",
|
||||||
MAME_DIR .. "src/emu/drivers/empty.cpp",
|
MAME_DIR .. "src/emu/drivers/empty.cpp",
|
||||||
|
@ -1,234 +0,0 @@
|
|||||||
// license:BSD-3-Clause
|
|
||||||
// copyright-holders:Derrick Renaud, Couriersud
|
|
||||||
#include "emu.h"
|
|
||||||
#include "filter.h"
|
|
||||||
|
|
||||||
static filter* filter_alloc(void) {
|
|
||||||
auto f = global_alloc(filter);
|
|
||||||
return f;
|
|
||||||
}
|
|
||||||
|
|
||||||
void filter_free(filter* f) {
|
|
||||||
global_free(f);
|
|
||||||
}
|
|
||||||
|
|
||||||
void filter_state_reset(filter* f, filter_state* s) {
|
|
||||||
int i;
|
|
||||||
s->prev_mac = 0;
|
|
||||||
for(i=0;i<f->order;++i) {
|
|
||||||
s->xprev[i] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
filter_state* filter_state_alloc(void) {
|
|
||||||
int i;
|
|
||||||
auto s = global_alloc(filter_state);
|
|
||||||
s->prev_mac = 0;
|
|
||||||
for(i=0;i<FILTER_ORDER_MAX;++i)
|
|
||||||
s->xprev[i] = 0;
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
void filter_state_free(filter_state* s) {
|
|
||||||
global_free(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************/
|
|
||||||
/* FIR */
|
|
||||||
|
|
||||||
filter_real filter_compute(filter* f, filter_state* s) {
|
|
||||||
unsigned order = f->order;
|
|
||||||
unsigned midorder = f->order / 2;
|
|
||||||
filter_real y = 0;
|
|
||||||
unsigned i,j,k;
|
|
||||||
|
|
||||||
/* i == [0] */
|
|
||||||
/* j == [-2*midorder] */
|
|
||||||
i = s->prev_mac;
|
|
||||||
j = i + 1;
|
|
||||||
if (j == order)
|
|
||||||
j = 0;
|
|
||||||
|
|
||||||
/* x */
|
|
||||||
for(k=0;k<midorder;++k) {
|
|
||||||
y += f->xcoeffs[midorder-k] * (s->xprev[i] + s->xprev[j]);
|
|
||||||
++j;
|
|
||||||
if (j == order)
|
|
||||||
j = 0;
|
|
||||||
if (i == 0)
|
|
||||||
i = order - 1;
|
|
||||||
else
|
|
||||||
--i;
|
|
||||||
}
|
|
||||||
y += f->xcoeffs[0] * s->xprev[i];
|
|
||||||
|
|
||||||
#ifdef FILTER_USE_INT
|
|
||||||
return y >> FILTER_INT_FRACT;
|
|
||||||
#else
|
|
||||||
return y;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
filter* filter_lp_fir_alloc(double freq, int order) {
|
|
||||||
filter* f = filter_alloc();
|
|
||||||
unsigned midorder = (order - 1) / 2;
|
|
||||||
unsigned i;
|
|
||||||
double gain;
|
|
||||||
|
|
||||||
assert( order <= FILTER_ORDER_MAX );
|
|
||||||
assert( order % 2 == 1 );
|
|
||||||
assert( 0 < freq && freq <= 0.5 );
|
|
||||||
|
|
||||||
/* Compute the antitrasform of the perfect low pass filter */
|
|
||||||
gain = 2*freq;
|
|
||||||
#ifdef FILTER_USE_INT
|
|
||||||
f->xcoeffs[0] = gain * (1 << FILTER_INT_FRACT);
|
|
||||||
#else
|
|
||||||
f->xcoeffs[0] = gain;
|
|
||||||
#endif
|
|
||||||
for(i=1;i<=midorder;++i) {
|
|
||||||
/* number of the sample starting from 0 to (order-1) included */
|
|
||||||
unsigned n = i + midorder;
|
|
||||||
|
|
||||||
/* sample value */
|
|
||||||
double c = sin(2*M_PI*freq*i) / (M_PI*i);
|
|
||||||
|
|
||||||
/* apply only one window or none */
|
|
||||||
/* double w = 2 - 2*n/(order-1); */ /* Bartlett (triangular) */
|
|
||||||
/* double w = 0.5 * (1 - cos(2*M_PI*n/(order-1))); */ /* Hanning */
|
|
||||||
double w = 0.54 - 0.46 * cos(2*M_PI*n/(order-1)); /* Hamming */
|
|
||||||
/* double w = 0.42 - 0.5 * cos(2*M_PI*n/(order-1)) + 0.08 * cos(4*M_PI*n/(order-1)); */ /* Blackman */
|
|
||||||
|
|
||||||
/* apply the window */
|
|
||||||
c *= w;
|
|
||||||
|
|
||||||
/* update the gain */
|
|
||||||
gain += 2*c;
|
|
||||||
|
|
||||||
/* insert the coeff */
|
|
||||||
#ifdef FILTER_USE_INT
|
|
||||||
f->xcoeffs[i] = c * (1 << FILTER_INT_FRACT);
|
|
||||||
#else
|
|
||||||
f->xcoeffs[i] = c;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/* adjust the gain to be exact 1.0 */
|
|
||||||
for(i=0;i<=midorder;++i) {
|
|
||||||
#ifdef FILTER_USE_INT
|
|
||||||
f->xcoeffs[i] /= gain;
|
|
||||||
#else
|
|
||||||
f->xcoeffs[i] = f->xcoeffs[i] * (double)(1 << FILTER_INT_FRAC) / gain;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/* decrease the order if the last coeffs are 0 */
|
|
||||||
i = midorder;
|
|
||||||
while (i > 0 && f->xcoeffs[i] == 0.0)
|
|
||||||
--i;
|
|
||||||
|
|
||||||
f->order = i * 2 + 1;
|
|
||||||
|
|
||||||
return f;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void filter2_setup(device_t *device, int type, double fc, double d, double gain,
|
|
||||||
filter2_context *filter2)
|
|
||||||
{
|
|
||||||
int sample_rate = device->machine().sample_rate();
|
|
||||||
double w; /* cutoff freq, in radians/sec */
|
|
||||||
double w_squared;
|
|
||||||
double den; /* temp variable */
|
|
||||||
double two_over_T = 2*sample_rate;
|
|
||||||
double two_over_T_squared = two_over_T * two_over_T;
|
|
||||||
|
|
||||||
/* calculate digital filter coefficents */
|
|
||||||
/*w = 2.0*M_PI*fc; no pre-warping */
|
|
||||||
w = sample_rate*2.0*tan(M_PI*fc/sample_rate); /* pre-warping */
|
|
||||||
w_squared = w*w;
|
|
||||||
|
|
||||||
den = two_over_T_squared + d*w*two_over_T + w_squared;
|
|
||||||
|
|
||||||
filter2->a1 = 2.0*(-two_over_T_squared + w_squared)/den;
|
|
||||||
filter2->a2 = (two_over_T_squared - d*w*two_over_T + w_squared)/den;
|
|
||||||
|
|
||||||
switch (type)
|
|
||||||
{
|
|
||||||
case FILTER_LOWPASS:
|
|
||||||
filter2->b0 = filter2->b2 = w_squared/den;
|
|
||||||
filter2->b1 = 2.0*(filter2->b0);
|
|
||||||
break;
|
|
||||||
case FILTER_BANDPASS:
|
|
||||||
filter2->b0 = d*w*two_over_T/den;
|
|
||||||
filter2->b1 = 0.0;
|
|
||||||
filter2->b2 = -(filter2->b0);
|
|
||||||
break;
|
|
||||||
case FILTER_HIGHPASS:
|
|
||||||
filter2->b0 = filter2->b2 = two_over_T_squared/den;
|
|
||||||
filter2->b1 = -2.0*(filter2->b0);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
device->logerror("filter2_setup() - Invalid filter type for 2nd order filter.");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
filter2->b0 *= gain;
|
|
||||||
filter2->b1 *= gain;
|
|
||||||
filter2->b2 *= gain;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Reset the input/output voltages to 0. */
|
|
||||||
void filter2_reset(filter2_context *filter2)
|
|
||||||
{
|
|
||||||
filter2->x0 = 0;
|
|
||||||
filter2->x1 = 0;
|
|
||||||
filter2->x2 = 0;
|
|
||||||
filter2->y0 = 0;
|
|
||||||
filter2->y1 = 0;
|
|
||||||
filter2->y2 = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Step the filter. */
|
|
||||||
void filter2_step(filter2_context *filter2)
|
|
||||||
{
|
|
||||||
filter2->y0 = -filter2->a1 * filter2->y1 - filter2->a2 * filter2->y2 +
|
|
||||||
filter2->b0 * filter2->x0 + filter2->b1 * filter2->x1 + filter2->b2 * filter2->x2;
|
|
||||||
filter2->x2 = filter2->x1;
|
|
||||||
filter2->x1 = filter2->x0;
|
|
||||||
filter2->y2 = filter2->y1;
|
|
||||||
filter2->y1 = filter2->y0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Setup a filter2 structure based on an op-amp multipole bandpass circuit. */
|
|
||||||
void filter_opamp_m_bandpass_setup(device_t *device, double r1, double r2, double r3, double c1, double c2,
|
|
||||||
filter2_context *filter2)
|
|
||||||
{
|
|
||||||
double r_in, fc, d, gain;
|
|
||||||
|
|
||||||
if (r1 == 0)
|
|
||||||
{
|
|
||||||
device->logerror("filter_opamp_m_bandpass_setup() - r1 can not be 0");
|
|
||||||
return; /* Filter can not be setup. Undefined results. */
|
|
||||||
}
|
|
||||||
|
|
||||||
if (r2 == 0)
|
|
||||||
{
|
|
||||||
gain = 1;
|
|
||||||
r_in = r1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
gain = r2 / (r1 + r2);
|
|
||||||
r_in = 1.0 / (1.0/r1 + 1.0/r2);
|
|
||||||
}
|
|
||||||
|
|
||||||
fc = 1.0 / (2 * M_PI * sqrt(r_in * r3 * c1 * c2));
|
|
||||||
d = (c1 + c2) / sqrt(r3 / r_in * c1 * c2);
|
|
||||||
gain *= -r3 / r_in * c2 / (c1 + c2);
|
|
||||||
|
|
||||||
filter2_setup(device, FILTER_BANDPASS, fc, d, gain, filter2);
|
|
||||||
}
|
|
@ -1,133 +0,0 @@
|
|||||||
// license:BSD-3-Clause
|
|
||||||
// copyright-holders:Derrick Renaud, Couriersud
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#ifndef __FILTER_H__
|
|
||||||
#define __FILTER_H__
|
|
||||||
|
|
||||||
/* Max filter order */
|
|
||||||
#define FILTER_ORDER_MAX 51
|
|
||||||
|
|
||||||
/* Define to use integer calculation */
|
|
||||||
#define FILTER_USE_INT
|
|
||||||
|
|
||||||
#ifdef FILTER_USE_INT
|
|
||||||
typedef int filter_real;
|
|
||||||
#define FILTER_INT_FRACT 15 /* fractional bits */
|
|
||||||
#else
|
|
||||||
typedef double filter_real;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct filter
|
|
||||||
{
|
|
||||||
filter_real xcoeffs[(FILTER_ORDER_MAX+1)/2];
|
|
||||||
unsigned order;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct filter_state
|
|
||||||
{
|
|
||||||
unsigned prev_mac;
|
|
||||||
filter_real xprev[FILTER_ORDER_MAX];
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Allocate a FIR Low Pass filter */
|
|
||||||
filter* filter_lp_fir_alloc(double freq, int order);
|
|
||||||
void filter_free(filter* f);
|
|
||||||
|
|
||||||
/* Allocate a filter state */
|
|
||||||
filter_state* filter_state_alloc(void);
|
|
||||||
|
|
||||||
/* Free the filter state */
|
|
||||||
void filter_state_free(filter_state* s);
|
|
||||||
|
|
||||||
/* Clear the filter state */
|
|
||||||
void filter_state_reset(filter* f, filter_state* s);
|
|
||||||
|
|
||||||
/* Insert a value in the filter state */
|
|
||||||
static inline void filter_insert(filter* f, filter_state* s, filter_real x) {
|
|
||||||
/* next state */
|
|
||||||
++s->prev_mac;
|
|
||||||
if (s->prev_mac >= f->order)
|
|
||||||
s->prev_mac = 0;
|
|
||||||
|
|
||||||
/* set x[0] */
|
|
||||||
s->xprev[s->prev_mac] = x;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Compute the filter output */
|
|
||||||
filter_real filter_compute(filter* f, filter_state* s);
|
|
||||||
|
|
||||||
|
|
||||||
/* Filter types */
|
|
||||||
#define FILTER_LOWPASS 0
|
|
||||||
#define FILTER_HIGHPASS 1
|
|
||||||
#define FILTER_BANDPASS 2
|
|
||||||
|
|
||||||
#define Q_TO_DAMP(q) (1.0/q)
|
|
||||||
|
|
||||||
struct filter2_context
|
|
||||||
{
|
|
||||||
filter2_context() :
|
|
||||||
x0(0.0),
|
|
||||||
x1(0.0),
|
|
||||||
x2(0.0),
|
|
||||||
y0(0.0),
|
|
||||||
y1(0.0),
|
|
||||||
y2(0.0),
|
|
||||||
a1(0.0),
|
|
||||||
a2(0.0),
|
|
||||||
b0(0.0),
|
|
||||||
b1(0.0),
|
|
||||||
b2(0.0)
|
|
||||||
{}
|
|
||||||
|
|
||||||
double x0, x1, x2; /* x[k], x[k-1], x[k-2], current and previous 2 input values */
|
|
||||||
double y0, y1, y2; /* y[k], y[k-1], y[k-2], current and previous 2 output values */
|
|
||||||
double a1, a2; /* digital filter coefficients, denominator */
|
|
||||||
double b0, b1, b2; /* digital filter coefficients, numerator */
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/* Setup the filter context based on the passed filter type info.
|
|
||||||
* type - 1 of the 3 defined filter types
|
|
||||||
* fc - center frequency
|
|
||||||
* d - damp = 1/Q
|
|
||||||
* gain - overall filter gain. Set to 1 if not needed.
|
|
||||||
*/
|
|
||||||
void filter2_setup(device_t *device, int type, double fc, double d, double gain,
|
|
||||||
filter2_context *filter2);
|
|
||||||
|
|
||||||
|
|
||||||
/* Reset the input/output voltages to 0. */
|
|
||||||
void filter2_reset(filter2_context *filter2);
|
|
||||||
|
|
||||||
|
|
||||||
/* Step the filter.
|
|
||||||
* x0 is the new input, which needs to be set before stepping.
|
|
||||||
* y0 is the new filter output.
|
|
||||||
*/
|
|
||||||
void filter2_step(filter2_context *filter2);
|
|
||||||
|
|
||||||
|
|
||||||
/* Setup a filter2 structure based on an op-amp multipole bandpass circuit.
|
|
||||||
* NOTE: If r2 is not used then set to 0.
|
|
||||||
* vRef is not needed to setup filter.
|
|
||||||
*
|
|
||||||
* .--------+---------.
|
|
||||||
* | | |
|
|
||||||
* --- c1 Z |
|
|
||||||
* --- Z r3 |
|
|
||||||
* | Z |
|
|
||||||
* r1 | c2 | |\ |
|
|
||||||
* In >----ZZZZ----+---------+--||----+ | \ |
|
|
||||||
* Z '--|- \ |
|
|
||||||
* Z r2 | >--+------> out
|
|
||||||
* Z .--|+ /
|
|
||||||
* | | | /
|
|
||||||
* gnd vRef >---' |/
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
void filter_opamp_m_bandpass_setup(device_t *device, double r1, double r2, double r3, double c1, double c2,
|
|
||||||
filter2_context *filter2);
|
|
||||||
|
|
||||||
#endif /* __FILTER_H__ */
|
|
@ -36,7 +36,191 @@ static const double volume_table[8] =
|
|||||||
static const double r_filt_out[3] = {RES_K(4.7), RES_K(7.5), RES_K(10)};
|
static const double r_filt_out[3] = {RES_K(4.7), RES_K(7.5), RES_K(10)};
|
||||||
static const double r_filt_total = 1.0 / (1.0/RES_K(4.7) + 1.0/RES_K(7.5) + 1.0/RES_K(10));
|
static const double r_filt_total = 1.0 / (1.0/RES_K(4.7) + 1.0/RES_K(7.5) + 1.0/RES_K(10));
|
||||||
|
|
||||||
|
/* Max filter order */
|
||||||
|
#define FILTER_ORDER_MAX 51
|
||||||
|
|
||||||
|
/* Define to use integer calculation */
|
||||||
|
#define FILTER_USE_INT
|
||||||
|
|
||||||
|
#ifdef FILTER_USE_INT
|
||||||
|
typedef int filter_real;
|
||||||
|
#define FILTER_INT_FRACT 15 /* fractional bits */
|
||||||
|
#else
|
||||||
|
typedef double filter_real;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct filter
|
||||||
|
{
|
||||||
|
filter_real xcoeffs[(FILTER_ORDER_MAX+1)/2];
|
||||||
|
unsigned order;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct filter_state
|
||||||
|
{
|
||||||
|
unsigned prev_mac;
|
||||||
|
filter_real xprev[FILTER_ORDER_MAX];
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Insert a value in the filter state */
|
||||||
|
static inline void filter_insert(filter* f, filter_state* s, filter_real x) {
|
||||||
|
/* next state */
|
||||||
|
++s->prev_mac;
|
||||||
|
if (s->prev_mac >= f->order)
|
||||||
|
s->prev_mac = 0;
|
||||||
|
|
||||||
|
/* set x[0] */
|
||||||
|
s->xprev[s->prev_mac] = x;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Filter types */
|
||||||
|
#define FILTER_LOWPASS 0
|
||||||
|
#define FILTER_HIGHPASS 1
|
||||||
|
#define FILTER_BANDPASS 2
|
||||||
|
|
||||||
|
#define Q_TO_DAMP(q) (1.0/q)
|
||||||
|
|
||||||
|
/* Setup the filter context based on the passed filter type info.
|
||||||
|
* type - 1 of the 3 defined filter types
|
||||||
|
* fc - center frequency
|
||||||
|
* d - damp = 1/Q
|
||||||
|
* gain - overall filter gain. Set to 1 if not needed.
|
||||||
|
*/
|
||||||
|
static void filter2_setup(device_t *device, int type, double fc, double d, double gain,
|
||||||
|
filter2_context *filter2);
|
||||||
|
|
||||||
|
|
||||||
|
/* Reset the input/output voltages to 0. */
|
||||||
|
static void filter2_reset(filter2_context *filter2);
|
||||||
|
|
||||||
|
|
||||||
|
/* Step the filter.
|
||||||
|
* x0 is the new input, which needs to be set before stepping.
|
||||||
|
* y0 is the new filter output.
|
||||||
|
*/
|
||||||
|
static void filter2_step(filter2_context *filter2);
|
||||||
|
|
||||||
|
|
||||||
|
/* Setup a filter2 structure based on an op-amp multipole bandpass circuit.
|
||||||
|
* NOTE: If r2 is not used then set to 0.
|
||||||
|
* vRef is not needed to setup filter.
|
||||||
|
*
|
||||||
|
* .--------+---------.
|
||||||
|
* | | |
|
||||||
|
* --- c1 Z |
|
||||||
|
* --- Z r3 |
|
||||||
|
* | Z |
|
||||||
|
* r1 | c2 | |\ |
|
||||||
|
* In >----ZZZZ----+---------+--||----+ | \ |
|
||||||
|
* Z '--|- \ |
|
||||||
|
* Z r2 | >--+------> out
|
||||||
|
* Z .--|+ /
|
||||||
|
* | | | /
|
||||||
|
* gnd vRef >---' |/
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static void filter_opamp_m_bandpass_setup(device_t *device, double r1, double r2, double r3, double c1, double c2,
|
||||||
|
filter2_context *filter2);
|
||||||
|
|
||||||
|
|
||||||
|
static void filter2_setup(device_t *device, int type, double fc, double d, double gain,
|
||||||
|
filter2_context *filter2)
|
||||||
|
{
|
||||||
|
int sample_rate = device->machine().sample_rate();
|
||||||
|
double w; /* cutoff freq, in radians/sec */
|
||||||
|
double w_squared;
|
||||||
|
double den; /* temp variable */
|
||||||
|
double two_over_T = 2*sample_rate;
|
||||||
|
double two_over_T_squared = two_over_T * two_over_T;
|
||||||
|
|
||||||
|
/* calculate digital filter coefficents */
|
||||||
|
/*w = 2.0*M_PI*fc; no pre-warping */
|
||||||
|
w = sample_rate*2.0*tan(M_PI*fc/sample_rate); /* pre-warping */
|
||||||
|
w_squared = w*w;
|
||||||
|
|
||||||
|
den = two_over_T_squared + d*w*two_over_T + w_squared;
|
||||||
|
|
||||||
|
filter2->a1 = 2.0*(-two_over_T_squared + w_squared)/den;
|
||||||
|
filter2->a2 = (two_over_T_squared - d*w*two_over_T + w_squared)/den;
|
||||||
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case FILTER_LOWPASS:
|
||||||
|
filter2->b0 = filter2->b2 = w_squared/den;
|
||||||
|
filter2->b1 = 2.0*(filter2->b0);
|
||||||
|
break;
|
||||||
|
case FILTER_BANDPASS:
|
||||||
|
filter2->b0 = d*w*two_over_T/den;
|
||||||
|
filter2->b1 = 0.0;
|
||||||
|
filter2->b2 = -(filter2->b0);
|
||||||
|
break;
|
||||||
|
case FILTER_HIGHPASS:
|
||||||
|
filter2->b0 = filter2->b2 = two_over_T_squared/den;
|
||||||
|
filter2->b1 = -2.0*(filter2->b0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
device->logerror("filter2_setup() - Invalid filter type for 2nd order filter.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
filter2->b0 *= gain;
|
||||||
|
filter2->b1 *= gain;
|
||||||
|
filter2->b2 *= gain;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Reset the input/output voltages to 0. */
|
||||||
|
static void filter2_reset(filter2_context *filter2)
|
||||||
|
{
|
||||||
|
filter2->x0 = 0;
|
||||||
|
filter2->x1 = 0;
|
||||||
|
filter2->x2 = 0;
|
||||||
|
filter2->y0 = 0;
|
||||||
|
filter2->y1 = 0;
|
||||||
|
filter2->y2 = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Step the filter. */
|
||||||
|
static void filter2_step(filter2_context *filter2)
|
||||||
|
{
|
||||||
|
filter2->y0 = -filter2->a1 * filter2->y1 - filter2->a2 * filter2->y2 +
|
||||||
|
filter2->b0 * filter2->x0 + filter2->b1 * filter2->x1 + filter2->b2 * filter2->x2;
|
||||||
|
filter2->x2 = filter2->x1;
|
||||||
|
filter2->x1 = filter2->x0;
|
||||||
|
filter2->y2 = filter2->y1;
|
||||||
|
filter2->y1 = filter2->y0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Setup a filter2 structure based on an op-amp multipole bandpass circuit. */
|
||||||
|
static void filter_opamp_m_bandpass_setup(device_t *device, double r1, double r2, double r3, double c1, double c2,
|
||||||
|
filter2_context *filter2)
|
||||||
|
{
|
||||||
|
double r_in, fc, d, gain;
|
||||||
|
|
||||||
|
if (r1 == 0)
|
||||||
|
{
|
||||||
|
device->logerror("filter_opamp_m_bandpass_setup() - r1 can not be 0");
|
||||||
|
return; /* Filter can not be setup. Undefined results. */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r2 == 0)
|
||||||
|
{
|
||||||
|
gain = 1;
|
||||||
|
r_in = r1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gain = r2 / (r1 + r2);
|
||||||
|
r_in = 1.0 / (1.0/r1 + 1.0/r2);
|
||||||
|
}
|
||||||
|
|
||||||
|
fc = 1.0 / (2 * M_PI * sqrt(r_in * r3 * c1 * c2));
|
||||||
|
d = (c1 + c2) / sqrt(r3 / r_in * c1 * c2);
|
||||||
|
gain *= -r3 / r_in * c2 / (c1 + c2);
|
||||||
|
|
||||||
|
filter2_setup(device, FILTER_BANDPASS, fc, d, gain, filter2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// device type definition
|
// device type definition
|
||||||
|
@ -6,11 +6,32 @@
|
|||||||
|
|
||||||
*************************************************************************/
|
*************************************************************************/
|
||||||
|
|
||||||
#include "sound/filter.h"
|
|
||||||
#include "sound/namco.h"
|
#include "sound/namco.h"
|
||||||
#include "sound/tms5220.h"
|
#include "sound/tms5220.h"
|
||||||
#include "sound/discrete.h"
|
#include "sound/discrete.h"
|
||||||
|
|
||||||
|
struct filter2_context
|
||||||
|
{
|
||||||
|
filter2_context() :
|
||||||
|
x0(0.0),
|
||||||
|
x1(0.0),
|
||||||
|
x2(0.0),
|
||||||
|
y0(0.0),
|
||||||
|
y1(0.0),
|
||||||
|
y2(0.0),
|
||||||
|
a1(0.0),
|
||||||
|
a2(0.0),
|
||||||
|
b0(0.0),
|
||||||
|
b1(0.0),
|
||||||
|
b2(0.0)
|
||||||
|
{}
|
||||||
|
|
||||||
|
double x0, x1, x2; /* x[k], x[k-1], x[k-2], current and previous 2 input values */
|
||||||
|
double y0, y1, y2; /* y[k], y[k-1], y[k-2], current and previous 2 output values */
|
||||||
|
double a1, a2; /* digital filter coefficients, denominator */
|
||||||
|
double b0, b1, b2; /* digital filter coefficients, numerator */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class polepos_state : public driver_device
|
class polepos_state : public driver_device
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user