mirror of
https://github.com/libretro/mame2003-plus-libretro.git
synced 2024-11-27 10:30:29 +00:00
namco52 namco54 to mame091
This commit is contained in:
parent
95806c35f7
commit
b16dbc66e0
@ -1834,26 +1834,44 @@ static struct GfxDecodeInfo gfxdecodeinfo_digdug[] =
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* The resistance path of the namco sound is 16k compared to
|
||||
* the 10k of the highest gain 54xx filter. Giving a 10/16 gain.
|
||||
*/
|
||||
static struct namco_interface namco_interface =
|
||||
{
|
||||
18432000/6/32, /* 96 kHz sample rate */
|
||||
3, /* number of voices */
|
||||
100, /* playback volume */
|
||||
90*10/16, /* playback volume */
|
||||
REGION_SOUND1 /* memory region */
|
||||
};
|
||||
|
||||
/* Only used by bosco. After filtering the 4V 52xx output,
|
||||
* the signal is 1V, or 25%. The relative volume between
|
||||
* 52xx & 54xx is the same.
|
||||
*/
|
||||
static struct namco_52xx_interface namco_52xx_interface =
|
||||
{
|
||||
18432000/12, /* 1.536 MHz */
|
||||
50, /* volume */
|
||||
REGION_SOUND2 /* memory region */
|
||||
90, /* volume */
|
||||
REGION_SOUND2, /* memory region */
|
||||
4000, /* Playback frequency - from 555 timer 6M */
|
||||
80, /* High pass filter fc */
|
||||
0.3, /* High pass filter Q */
|
||||
2400, /* Low pass filter fc */
|
||||
0.9, /* Low pass filter Q */
|
||||
.25 /* Combined gain of both filters */
|
||||
};
|
||||
|
||||
static struct namco_54xx_interface namco_54xx_interface =
|
||||
{
|
||||
18432000/12, /* 1.536 MHz */
|
||||
{ 100, 100, 100 } /* volume of the three outputs */
|
||||
90, /* volume */
|
||||
{ RES_K(100), RES_K(47), RES_K(150) }, /* R24, R33, R42 */
|
||||
{ RES_K(22), RES_K(10), RES_K(22) }, /* R23, R34, R41 */
|
||||
{ RES_K(220), RES_K(150), RES_K(470) }, /* R22, R35, R40 */
|
||||
{ RES_K(33), RES_K(33), RES_K(10)}, /* R21, R36, R37 */
|
||||
{ CAP_U(.001), CAP_U(.01), CAP_U(.01) }, /* C31, C29, C27 */
|
||||
{ CAP_U(.001), CAP_U(.01), CAP_U(.01) }, /* C30, C28, C26 */
|
||||
};
|
||||
|
||||
static const char *bosco_sample_names[] =
|
||||
@ -1865,8 +1883,8 @@ static const char *bosco_sample_names[] =
|
||||
|
||||
static struct Samplesinterface samples_interface_bosco =
|
||||
{
|
||||
1, /* 1 channel */
|
||||
100, /* volume */
|
||||
1, /* 3 channel1 */
|
||||
95, /* volume */
|
||||
bosco_sample_names
|
||||
};
|
||||
|
||||
|
@ -782,14 +782,26 @@ static struct namco_interface namco_interface =
|
||||
static struct namco_52xx_interface namco_52xx_interface =
|
||||
{
|
||||
24576000/16, /* 1.536 MHz */
|
||||
25, /* volume */
|
||||
REGION_SOUND3 /* memory region */
|
||||
80, /* volume */
|
||||
REGION_SOUND3, /* memory region */
|
||||
0, /* Use internal Playback frequency */
|
||||
100, /* High pass filter fc */
|
||||
0.3, /* High pass filter Q */
|
||||
1200, /* Low pass filter fc */
|
||||
0.8, /* Low pass filter Q */
|
||||
.5 /* Combined gain of both filters */
|
||||
};
|
||||
|
||||
static struct namco_54xx_interface namco_54xx_interface =
|
||||
{
|
||||
24576000/16, /* 1.536 MHz */
|
||||
{ 100, 100, 100 } /* volume of the three outputs */
|
||||
80, /* volume */
|
||||
{ RES_K(22), RES_K(15), RES_K(22) }, /* R121, R133, R139 */
|
||||
{ RES_K(12), RES_K(15), RES_K(22) }, /* R125, R137, R143 */
|
||||
{ RES_K(120), RES_K(120), RES_K(180) }, /* R122, R134, R140 */
|
||||
{ 470, 470, 470 }, /* R123, R135, R141 */
|
||||
{ CAP_U(.0022), CAP_U(.022), CAP_U(.047) }, /* C27, C29, C33 */
|
||||
{ CAP_U(.0022), CAP_U(.022), CAP_U(.047) }, /* C28, C30, C34 */
|
||||
};
|
||||
|
||||
static struct CustomSound_interface custom_interface =
|
||||
|
@ -3,6 +3,7 @@
|
||||
Sound handler
|
||||
****************************************************************************/
|
||||
#include "driver.h"
|
||||
#include "../sound/filter.h"
|
||||
|
||||
static int sample_msb = 0;
|
||||
static int sample_lsb = 0;
|
||||
@ -10,13 +11,30 @@ static int sample_enable = 0;
|
||||
|
||||
static int sound_stream;
|
||||
|
||||
#define AMP(r) (r*128/10100)
|
||||
static int volume_table[8] =
|
||||
#define POLEPOS_R166 1000.0
|
||||
#define POLEPOS_R167 2200.0
|
||||
#define POLEPOS_R168 4700.0
|
||||
/* resistor values when shorted by 4066 running at 5V */
|
||||
#define POLEPOS_R166_SHUNT 1.0/(1.0/POLEPOS_R166 + 1.0/250)
|
||||
#define POLEPOS_R167_SHUNT 1.0/(1.0/POLEPOS_R166 + 1.0/250)
|
||||
#define POLEPOS_R168_SHUNT 1.0/(1.0/POLEPOS_R166 + 1.0/250)
|
||||
|
||||
static double volume_table[8] =
|
||||
{
|
||||
AMP(2200), AMP(3200), AMP(4400), AMP(5400),
|
||||
AMP(6900), AMP(7900), AMP(9100), AMP(10100)
|
||||
(POLEPOS_R168_SHUNT + POLEPOS_R167_SHUNT + POLEPOS_R166_SHUNT + 2200) / 10000,
|
||||
(POLEPOS_R168_SHUNT + POLEPOS_R167_SHUNT + POLEPOS_R166 + 2200) / 10000,
|
||||
(POLEPOS_R168_SHUNT + POLEPOS_R167 + POLEPOS_R166_SHUNT + 2200) / 10000,
|
||||
(POLEPOS_R168_SHUNT + POLEPOS_R167 + POLEPOS_R166 + 2200) / 10000,
|
||||
(POLEPOS_R168 + POLEPOS_R167_SHUNT + POLEPOS_R166_SHUNT + 2200) / 10000,
|
||||
(POLEPOS_R168 + POLEPOS_R167_SHUNT + POLEPOS_R166 + 2200) / 10000,
|
||||
(POLEPOS_R168 + POLEPOS_R167 + POLEPOS_R166_SHUNT + 2200) / 10000,
|
||||
(POLEPOS_R168 + POLEPOS_R167 + POLEPOS_R166 + 2200) / 10000
|
||||
};
|
||||
|
||||
static struct filter2_context filter_engine[3];
|
||||
|
||||
static double r_filt_out[3] = {RES_K(4.7), RES_K(7.5), RES_K(10)};
|
||||
static double r_filt_total = 1.0 / (1.0/RES_K(4.7) + 1.0/RES_K(7.5) + 1.0/RES_K(10));
|
||||
|
||||
/************************************/
|
||||
/* Stream updater */
|
||||
@ -24,9 +42,10 @@ static int volume_table[8] =
|
||||
static void engine_sound_update(int num, INT16 *buffer, int length)
|
||||
{
|
||||
static UINT32 current_position;
|
||||
UINT32 step, clock, slot, volume;
|
||||
UINT32 step, clock, slot;
|
||||
UINT8 *base;
|
||||
|
||||
double volume, i_total;
|
||||
int loop;
|
||||
|
||||
/* if we're not enabled, just fill with 0 */
|
||||
if (!sample_enable || Machine->sample_rate == 0)
|
||||
@ -47,7 +66,24 @@ static void engine_sound_update(int num, INT16 *buffer, int length)
|
||||
/* fill in the sample */
|
||||
while (length--)
|
||||
{
|
||||
*buffer++ = (base[(current_position >> 12) & 0x7ff] * volume);
|
||||
filter_engine[0].x0 = (3.4 / 255 * base[(current_position >> 12) & 0x7ff] - 2) * volume;
|
||||
filter_engine[1].x0 = filter_engine[0].x0;
|
||||
filter_engine[2].x0 = filter_engine[0].x0;
|
||||
|
||||
i_total = 0;
|
||||
for (loop = 0; loop < 3; loop++)
|
||||
{
|
||||
filter2_step(&filter_engine[loop]);
|
||||
/* The op-amp powered @ 5V will clip to 0V & 3.5V.
|
||||
* Adjusted to vRef of 2V, we will clip as follows: */
|
||||
if (filter_engine[loop].y0 > 1.5) filter_engine[loop].y0 = 1.5;
|
||||
if (filter_engine[loop].y0 < -2) filter_engine[loop].y0 = -2;
|
||||
|
||||
i_total += filter_engine[loop].y0 / r_filt_out[loop];
|
||||
}
|
||||
i_total *= r_filt_total * 32000/2; /* now contains voltage adjusted by final gain */
|
||||
|
||||
*buffer++ = (int)i_total;
|
||||
current_position += step;
|
||||
}
|
||||
}
|
||||
@ -57,12 +93,32 @@ static void engine_sound_update(int num, INT16 *buffer, int length)
|
||||
/************************************/
|
||||
int polepos_sh_start(const struct MachineSound *msound)
|
||||
{
|
||||
sound_stream = stream_init("Engine Sound", 25, Machine->sample_rate, 0, engine_sound_update);
|
||||
sound_stream = stream_init("Engine Sound", 77, Machine->sample_rate, 0, engine_sound_update);
|
||||
sample_msb = sample_lsb = 0;
|
||||
sample_enable = 0;
|
||||
|
||||
/* setup the filters */
|
||||
filter_opamp_m_bandpass_setup(RES_K(220), RES_K(33), RES_K(390), CAP_U(.01), CAP_U(.01),
|
||||
&filter_engine[0]);
|
||||
filter_opamp_m_bandpass_setup(RES_K(150), RES_K(22), RES_K(330), CAP_U(.0047), CAP_U(.0047),
|
||||
&filter_engine[1]);
|
||||
/* Filter 3 is a little different. Because of the input capacitor, it is
|
||||
* a high pass filter. */
|
||||
filter2_setup(FILTER_HIGHPASS, 950, Q_TO_DAMP(.707), 1,
|
||||
&filter_engine[2]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/************************************/
|
||||
/* Sound handler reset */
|
||||
/************************************/
|
||||
void polepos_sh_reset(void)
|
||||
{
|
||||
int loop;
|
||||
for (loop = 0; loop < 3; loop++) filter2_reset(&filter_engine[loop]);
|
||||
}
|
||||
|
||||
/************************************/
|
||||
/* Sound handler stop */
|
||||
/************************************/
|
||||
@ -75,6 +131,7 @@ void polepos_sh_stop(void)
|
||||
/************************************/
|
||||
WRITE_HANDLER( polepos_engine_sound_lsb_w )
|
||||
{
|
||||
/* Update stream first so all samples at old frequency are updated. */
|
||||
stream_update(sound_stream, 0);
|
||||
sample_lsb = data & 62;
|
||||
sample_enable = data & 1;
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "filter.h"
|
||||
#include "driver.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
@ -132,3 +133,103 @@ filter* filter_lp_fir_alloc(double freq, int order) {
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
|
||||
void filter2_setup(int type, double fc, double d, double gain,
|
||||
struct filter2_context *filter)
|
||||
{
|
||||
double w; /* cutoff freq, in radians/sec */
|
||||
double w_squared;
|
||||
double den; /* temp variable */
|
||||
double two_over_T = 2*Machine->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 = Machine->sample_rate*2.0*tan(M_PI*fc/Machine->sample_rate); /* pre-warping */
|
||||
w_squared = w*w;
|
||||
|
||||
den = two_over_T_squared + d*w*two_over_T + w_squared;
|
||||
|
||||
filter->a1 = 2.0*(-two_over_T_squared + w_squared)/den;
|
||||
filter->a2 = (two_over_T_squared - d*w*two_over_T + w_squared)/den;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case FILTER_LOWPASS:
|
||||
filter->b0 = filter->b2 = w_squared/den;
|
||||
filter->b1 = 2.0*(filter->b0);
|
||||
break;
|
||||
case FILTER_BANDPASS:
|
||||
filter->b0 = d*w*two_over_T/den;
|
||||
filter->b1 = 0.0;
|
||||
filter->b2 = -(filter->b0);
|
||||
break;
|
||||
case FILTER_HIGHPASS:
|
||||
filter->b0 = filter->b2 = two_over_T_squared/den;
|
||||
filter->b1 = -2.0*(filter->b0);
|
||||
break;
|
||||
default:
|
||||
logerror("filter2_setup() - Invalid filter type for 2nd order filter.");
|
||||
break;
|
||||
}
|
||||
|
||||
filter->b0 *= gain;
|
||||
filter->b1 *= gain;
|
||||
filter->b2 *= gain;
|
||||
}
|
||||
|
||||
|
||||
/* Reset the input/output voltages to 0. */
|
||||
void filter2_reset(struct filter2_context *filter)
|
||||
{
|
||||
filter->x0 = 0;
|
||||
filter->x1 = 0;
|
||||
filter->x2 = 0;
|
||||
filter->y0 = 0;
|
||||
filter->y1 = 0;
|
||||
filter->y2 = 0;
|
||||
}
|
||||
|
||||
|
||||
/* Step the filter. */
|
||||
void filter2_step(struct filter2_context *filter)
|
||||
{
|
||||
filter->y0 = -filter->a1 * filter->y1 - filter->a2 * filter->y2 +
|
||||
filter->b0 * filter->x0 + filter->b1 * filter->x1 + filter->b2 * filter->x2;
|
||||
filter->x2 = filter->x1;
|
||||
filter->x1 = filter->x0;
|
||||
filter->y2 = filter->y1;
|
||||
filter->y1 = filter->y0;
|
||||
}
|
||||
|
||||
|
||||
/* Setup a filter2 structure based on an op-amp multipole bandpass circuit. */
|
||||
void filter_opamp_m_bandpass_setup(double r1, double r2, double r3, double c1, double c2,
|
||||
struct filter2_context *filter)
|
||||
{
|
||||
double r_in, fc, d, gain;
|
||||
|
||||
if (r1 == 0)
|
||||
{
|
||||
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(FILTER_BANDPASS, fc, d, gain, filter);
|
||||
}
|
||||
|
@ -53,4 +53,64 @@ static INLINE void filter_insert(filter* f, filter_state* s, filter_real 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
|
||||
{
|
||||
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(int type, double fc, double d, double gain,
|
||||
struct filter2_context *filter);
|
||||
|
||||
|
||||
/* Reset the input/output voltages to 0. */
|
||||
void filter2_reset(struct filter2_context *filter);
|
||||
|
||||
|
||||
/* Step the filter.
|
||||
* x0 is the new input, which needs to be set before stepping.
|
||||
* y0 is the new filter output.
|
||||
*/
|
||||
void filter2_step(struct filter2_context *filter);
|
||||
|
||||
|
||||
/* 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(double r1, double r2, double r3, double c1, double c2,
|
||||
struct filter2_context *filter);
|
||||
|
||||
#endif
|
||||
|
@ -34,83 +34,146 @@ OUT = sound output
|
||||
GND|21 22|D0
|
||||
+------+
|
||||
|
||||
[1] in polepos, GND; in bosco, output from a 555 timer
|
||||
[1] in polepos, GND; in bosco, 4kHz output from a 555 timer
|
||||
[2] in polepos, +5V; in bosco, GND
|
||||
[3] in polepos, these are true address lines, in bosco they are chip select lines
|
||||
(each one select one of the four ROM chips). Behaviour related to [2]?
|
||||
|
||||
TODO:
|
||||
- the purpose of the 555 timer in bosco is unknown; maybe modulate the output?
|
||||
Jan 12, 2005. The 555 is probably an external playback frequency.
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#include "driver.h"
|
||||
#include "namco52.h"
|
||||
|
||||
/* macro to convert 4-bit unsigned samples to 8-bit signed samples */
|
||||
#define SAMPLE_CONV4(a) (0x11*((a&0x0f))-0x80)
|
||||
#include "filter.h"
|
||||
|
||||
|
||||
static INT8 *samples; /* 4-bit samples will be unpacked to 8-bit here */
|
||||
static int channel; /* channel assigned by the mixer */
|
||||
static const struct namco_52xx_interface *intf; /* pointer to our config data */
|
||||
static UINT8 *rom; /* pointer to sample ROM */
|
||||
static UINT8 *rom; /* pointer to sample ROM */
|
||||
static int rom_len;
|
||||
static int stream; /* the output stream */
|
||||
static double n52_pb_cycle; /* playback clock time based on machine sample rate */
|
||||
static double n52_step; /* playback clock step based on machine sample rate */
|
||||
/* n52_pb_cycle is incremented by n52_step every machine-sample.
|
||||
* At every integer value of n52_pb_cycle the next 4bit value is used. */
|
||||
static int n52_start; /* current effect start position in the ROM */
|
||||
static int n52_end; /* current effect end position in the ROM */
|
||||
static int n52_length; /* # of 4bit samples in current effect */
|
||||
static int n52_pos; /* current 4bit sample of effect */
|
||||
static struct filter2_context n52_hp_filter;
|
||||
static struct filter2_context n52_lp_filter;
|
||||
|
||||
|
||||
static void namco_52xx_stream_update_one(int num, INT16 *buffer, int length)
|
||||
{
|
||||
int i, rom_pos, whole_pb_cycles, buf;
|
||||
|
||||
if (n52_start >= n52_end)
|
||||
{
|
||||
memset(buffer, 0, length * sizeof(INT16));
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < length; i++)
|
||||
{
|
||||
n52_pb_cycle += n52_step;
|
||||
if (n52_pb_cycle >= 1)
|
||||
{
|
||||
whole_pb_cycles = (int)n52_pb_cycle;
|
||||
n52_pos += whole_pb_cycles;
|
||||
n52_pb_cycle -= whole_pb_cycles;
|
||||
}
|
||||
|
||||
if (n52_pos > n52_length)
|
||||
{
|
||||
/* sample done */
|
||||
memset(&buffer[i], 0, (length - i) * sizeof(INT16));
|
||||
i = length;
|
||||
namco_52xx_sh_reset();
|
||||
}
|
||||
else
|
||||
{
|
||||
/* filter and fill the buffer */
|
||||
rom_pos = n52_start + (n52_pos >> 1);
|
||||
/* get the 4bit sample from rom and shift to +7/-8 value */
|
||||
n52_hp_filter.x0 = (((n52_pos & 1) ? rom[rom_pos] >> 4 : rom[rom_pos]) & 0x0f) - 0x08;
|
||||
filter2_step(&n52_hp_filter);
|
||||
n52_lp_filter.x0 = n52_hp_filter.y0;
|
||||
filter2_step(&n52_lp_filter);
|
||||
/* convert 4bit filtered to 16bit allowing room for filter gain */
|
||||
buf = (int)(n52_lp_filter.y0 * 0x0fff);
|
||||
if (buf > 32767) buf = 32767;
|
||||
if (buf < -32768) buf = -32768;
|
||||
buffer[i] = buf;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void namco_52xx_sh_reset(void)
|
||||
{
|
||||
n52_pb_cycle = n52_start = n52_end = n52_length = n52_pos = 0;
|
||||
|
||||
filter2_reset(&n52_hp_filter);
|
||||
filter2_reset(&n52_lp_filter);
|
||||
}
|
||||
|
||||
int namco_52xx_sh_start(const struct MachineSound *msound)
|
||||
{
|
||||
int i;
|
||||
unsigned char bits;
|
||||
|
||||
intf = msound->sound_interface;
|
||||
rom = memory_region(intf->region);
|
||||
rom_len = memory_region_length(intf->region);
|
||||
|
||||
channel = mixer_allocate_channel(intf->mixing_level);
|
||||
mixer_set_name(channel,sound_name(msound));
|
||||
|
||||
samples = auto_malloc(2*rom_len);
|
||||
if (!samples)
|
||||
if (Machine->sample_rate == 0)
|
||||
return 1;
|
||||
|
||||
/* decode the rom samples */
|
||||
for (i = 0;i < rom_len;i++)
|
||||
if (intf->play_rate == 0)
|
||||
{
|
||||
bits = rom[i] & 0x0f;
|
||||
samples[2*i] = SAMPLE_CONV4(bits);
|
||||
|
||||
bits = (rom[i] & 0xf0) >> 4;
|
||||
samples[2*i + 1] = SAMPLE_CONV4(bits);
|
||||
/* If play clock is 0 (grounded) then default to internal clock */
|
||||
n52_step = (double)(intf->baseclock) / 384 / Machine->sample_rate;
|
||||
}
|
||||
else
|
||||
{
|
||||
n52_step = intf->play_rate / Machine->sample_rate;
|
||||
}
|
||||
filter2_setup(FILTER_HIGHPASS, intf->hp_filt_fc, Q_TO_DAMP(intf->hp_filt_q), 1, &n52_hp_filter);
|
||||
filter2_setup(FILTER_LOWPASS, intf->lp_filt_fc, Q_TO_DAMP(intf->lp_filt_q), intf->filt_gain, &n52_lp_filter);
|
||||
|
||||
|
||||
stream = stream_init(sound_name(msound), intf->mixing_level, Machine->sample_rate, 0, namco_52xx_stream_update_one);
|
||||
|
||||
/* handle failure */
|
||||
if (stream == -1)
|
||||
osd_die("Namco 52xx - Stream init returned an error\n");
|
||||
|
||||
namco_52xx_sh_reset();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void namco_52xx_sh_stop(void)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void namcoio_52XX_write(int data)
|
||||
{
|
||||
data &= 0x0f;
|
||||
|
||||
/*logerror("%04x: custom 52XX write %02x\n",activecpu_get_pc(),data); */
|
||||
|
||||
if (Machine->sample_rate == 0)
|
||||
return;
|
||||
|
||||
if (data != 0)
|
||||
{
|
||||
int start = rom[data-1] + (rom[data-1+0x10] << 8);
|
||||
int end = rom[data] + (rom[data+0x10] << 8);
|
||||
stream_update(stream, 0);
|
||||
|
||||
if (end >= rom_len)
|
||||
end = rom_len;
|
||||
n52_start = rom[data-1] + (rom[data-1+0x10] << 8);
|
||||
n52_end = rom[data] + (rom[data+0x10] << 8);
|
||||
|
||||
if (start < end)
|
||||
mixer_play_sample(channel, samples + start * 2, (end - start) * 2, intf->baseclock/384, 0);
|
||||
if (n52_end >= rom_len)
|
||||
n52_end = rom_len;
|
||||
|
||||
n52_length = (n52_end - n52_start) * 2;
|
||||
n52_pos = 0;
|
||||
n52_pb_cycle= 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void namco_52xx_sh_stop(void)
|
||||
{
|
||||
}
|
||||
|
@ -1,16 +1,38 @@
|
||||
#ifndef namco52_h
|
||||
#define namco52_h
|
||||
|
||||
/* While a little confusing, this interface uses 2 gains.
|
||||
*
|
||||
* "mixing_level" is the relative level of the signal
|
||||
* compared to other effects before entering the filter.
|
||||
*
|
||||
* "filt_gain" is the combined gain of the filters.
|
||||
*
|
||||
* If I did not do it this way, then the filters could
|
||||
* cause the signal to go beyond the 16bit range.
|
||||
*
|
||||
* If "play_rate" is 0 (ground) then the sample clock rate
|
||||
* defaults to the 52xx internal sample clock. (baseclock/384)
|
||||
*/
|
||||
|
||||
struct namco_52xx_interface
|
||||
{
|
||||
int baseclock; /* clock */
|
||||
int mixing_level; /* volume */
|
||||
int region; /* memory region */
|
||||
int baseclock; /* clock */
|
||||
int mixing_level; /* volume */
|
||||
int region; /* memory region */
|
||||
double play_rate; /* Playback frequency */
|
||||
double hp_filt_fc;
|
||||
double hp_filt_q;
|
||||
double lp_filt_fc;
|
||||
double lp_filt_q;
|
||||
double filt_gain;
|
||||
};
|
||||
|
||||
int namco_52xx_sh_start(const struct MachineSound *msound);
|
||||
void namco_52xx_sh_reset(void);
|
||||
void namco_52xx_sh_stop(void);
|
||||
|
||||
void namcoio_52XX_write(int data);
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -71,6 +71,7 @@ TODO:
|
||||
***************************************************************************/
|
||||
|
||||
#include "driver.h"
|
||||
#include "filter.h"
|
||||
|
||||
|
||||
static int fetch;
|
||||
@ -233,10 +234,14 @@ static UINT8 release_table[16][8]=
|
||||
{15,11,8,6,4,3,2,1}
|
||||
};
|
||||
|
||||
static struct filter2_context filter54[3];
|
||||
|
||||
|
||||
void namco_54xx_sh_reset(void)
|
||||
{
|
||||
int loop;
|
||||
for (loop = 0; loop < 3; loop++) filter2_reset(&filter54[loop]);
|
||||
|
||||
fetch = 0;
|
||||
fetchmode = 0;
|
||||
|
||||
@ -258,7 +263,7 @@ void namco_54xx_sh_reset(void)
|
||||
noise_B_will_change = 0;
|
||||
out_prev = 0;
|
||||
|
||||
/* wonder what are the default params after the reset ? */
|
||||
//wonder what are the default params after the reset ?
|
||||
|
||||
}
|
||||
|
||||
@ -348,9 +353,8 @@ int i;
|
||||
|
||||
static INT16 calc_A(void)
|
||||
{
|
||||
/*if (type_A_active)
|
||||
log_cb( RETRO_LOG_DEBUG,"calc a: env_state=%2i vol=%2i noise=%2i\n", type_A_state, type_A_curr_vol, noise_out_A);
|
||||
*/
|
||||
//if (type_A_active)
|
||||
// logerror("calc a: env_state=%2i vol=%2i noise=%2i\n", type_A_state, type_A_curr_vol, noise_out_A);
|
||||
|
||||
switch (type_A_state)
|
||||
{
|
||||
@ -408,16 +412,16 @@ static void advance(void)
|
||||
{
|
||||
int i,v;
|
||||
|
||||
/* type A */
|
||||
//type A
|
||||
type_A_pos += type_A_add;
|
||||
i = (type_A_pos >> PRECISION_SH);
|
||||
type_A_pos &= PRECISION_MASK;
|
||||
|
||||
if (i)
|
||||
{ /*switch to the next envelope state
|
||||
{ //switch to the next envelope state
|
||||
|
||||
//logerror("type A switch, from mode=%2i\n",type_A_state);
|
||||
|
||||
log_cb( RETRO_LOG_DEBUG,"type A switch, from mode=%2i\n",type_A_state);
|
||||
*/
|
||||
switch(type_A_state)
|
||||
{
|
||||
case ENV_OFF:
|
||||
@ -458,16 +462,16 @@ int i,v;
|
||||
}
|
||||
|
||||
|
||||
/* type B */
|
||||
//type B
|
||||
type_B_pos += type_B_add;
|
||||
i = (type_B_pos >> PRECISION_SH);
|
||||
type_B_pos &= PRECISION_MASK;
|
||||
|
||||
if (i)
|
||||
{ /* switch to the next envelope state
|
||||
{ //switch to the next envelope state
|
||||
|
||||
//logerror("type B switch, from mode=%2i\n",type_B_state);
|
||||
|
||||
log_cb( RETRO_LOG_DEBUG,"type B switch, from mode=%2i\n",type_B_state);
|
||||
*/
|
||||
switch(type_B_state)
|
||||
{
|
||||
case ENV_OFF:
|
||||
@ -510,7 +514,7 @@ int i,v;
|
||||
|
||||
|
||||
|
||||
/* TODO type C */
|
||||
//TODO type C
|
||||
|
||||
|
||||
noise_step();
|
||||
@ -521,7 +525,7 @@ int i,v;
|
||||
|
||||
void NAMCO54xxUpdateOne(int num, INT16 **buffers, int length)
|
||||
{
|
||||
int i;
|
||||
int i, loop;
|
||||
INT16 out1, out2, out3;
|
||||
INT16 *buf1, *buf2, *buf3;
|
||||
|
||||
@ -531,25 +535,38 @@ void NAMCO54xxUpdateOne(int num, INT16 **buffers, int length)
|
||||
|
||||
for (i = 0; i < length; i++)
|
||||
{
|
||||
/* if (fetch) /* no sound is produced while waiting for the parameters */
|
||||
//if (fetch) /* no sound is produced while waiting for the parameters */
|
||||
|
||||
out1 = calc_A(); /* pins 4-7 */
|
||||
out2 = calc_B(); /* pins 8-11 */
|
||||
out3 = calc_C(); /* pins 17-20 */
|
||||
|
||||
(buf1)[i] = out1 * 1024; /* with gain: 0 to 15K */
|
||||
(buf2)[i] = out2 * 1024; /* with gain: 0 to 15K */
|
||||
(buf3)[i] = out3 * 1024; /* with gain: 0 to 15K */
|
||||
/* Convert the binary value to a voltage and filter it. */
|
||||
/* I am assuming a 4V output when a bit is high. */
|
||||
filter54[0].x0 = 4.0/15 * out1 - 2;
|
||||
filter54[1].x0 = 4.0/15 * out2 - 2;
|
||||
filter54[2].x0 = 4.0/15 * out3 - 2;
|
||||
for (loop = 0; loop < 3; loop++)
|
||||
{
|
||||
filter2_step(&filter54[loop]);
|
||||
/* The op-amp powered @ 5V will clip to 0V & 3.5V.
|
||||
* Adjusted to vRef of 2V, we will clip as follows: */
|
||||
if (filter54[loop].y0 > 1.5) filter54[loop].y0 = 1.5;
|
||||
if (filter54[loop].y0 < -2) filter54[loop].y0 = -2;
|
||||
}
|
||||
|
||||
(buf1)[i] = filter54[0].y0 * (32768/2);
|
||||
(buf2)[i] = filter54[1].y0 * (32768/2);
|
||||
(buf3)[i] = filter54[2].y0 * (32768/2);
|
||||
|
||||
advance();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void namcoio_54XX_write(int data)
|
||||
{
|
||||
log_cb( RETRO_LOG_DEBUG,"%04x: custom 54XX write %02x\n",activecpu_get_pc(),data);
|
||||
logerror("%04x: custom 54XX write %02x\n",activecpu_get_pc(),data);
|
||||
|
||||
stream_update(stream, 0);
|
||||
|
||||
@ -599,7 +616,7 @@ void namcoio_54XX_write(int data)
|
||||
|
||||
case 0x50: /* type C, mode A, output sound on pins 17-20 only */
|
||||
if (memcmp(type_C_par,"\x08\x04\x21\x00\xf1",5) == 0)
|
||||
/* bosco */
|
||||
// bosco
|
||||
sample_start(0, 0, 0);
|
||||
break;
|
||||
|
||||
@ -609,7 +626,7 @@ void namcoio_54XX_write(int data)
|
||||
break;
|
||||
|
||||
case 0x70: /* type C, mode B, output sound on pins 17-20 only */
|
||||
/* polepos */
|
||||
// polepos
|
||||
/* 0x7n = Screech sound. n = volume (if 0 then no sound) */
|
||||
/* followed by 0x60 command */
|
||||
#if 1
|
||||
@ -641,11 +658,30 @@ int namco_54xx_sh_start(const struct MachineSound *msound)
|
||||
const char *name[NAMCO54xx_NUMBUF];
|
||||
int vol[NAMCO54xx_NUMBUF];
|
||||
|
||||
double scaler, c_value;
|
||||
double scaler, c_value, r_in, r_min;
|
||||
int i;
|
||||
|
||||
intf = msound->sound_interface;
|
||||
|
||||
/* setup the filters */
|
||||
r_min = intf->r4[0];
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
r_in = intf->r1[i] + ( 1.0 / ( 1.0/4700 + 1.0/10000 + 1.0/22000 + 1.0/47000));
|
||||
filter_opamp_m_bandpass_setup(r_in, intf->r2[i], intf->r3[i], intf->c1[i], intf->c2[i],
|
||||
&filter54[i]);
|
||||
if (intf->r4[i] < r_min) r_min = intf->r4[i];
|
||||
}
|
||||
|
||||
/* setup relative gains */
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
scaler = r_min / intf->r4[i];
|
||||
filter54[i].b0 *= scaler;
|
||||
filter54[i].b1 *= scaler;
|
||||
filter54[i].b2 *= scaler;
|
||||
}
|
||||
|
||||
chip_clock = intf->baseclock;
|
||||
chip_sampfreq = Machine->sample_rate;
|
||||
|
||||
@ -653,14 +689,14 @@ int namco_54xx_sh_start(const struct MachineSound *msound)
|
||||
|
||||
for (i = 0; i < NAMCO54xx_NUMBUF; i++)
|
||||
{
|
||||
vol[i] = intf->mixing_level[i];
|
||||
vol[i] = intf->mixing_level;
|
||||
name[i] = buf[i];
|
||||
sprintf(buf[i],"%s Ch %d",sound_name(msound),i);
|
||||
}
|
||||
|
||||
stream = stream_init_multi(NAMCO54xx_NUMBUF, name, vol, chip_sampfreq, 0, NAMCO54xxUpdateOne);
|
||||
|
||||
log_cb( RETRO_LOG_DEBUG,"Namco 54xx clock=%f sample rate=%f\n", chip_clock, chip_sampfreq);
|
||||
logerror("Namco 54xx clock=%f sample rate=%f\n", chip_clock, chip_sampfreq);
|
||||
|
||||
/* calculate emulation tables */
|
||||
scaler = chip_clock / chip_sampfreq;
|
||||
@ -678,14 +714,14 @@ altogether which corresponds to 1254 chip clock cycles. 13 samples = 543 cycles,
|
||||
c_value = ((double)(1<<PRECISION_SH)) / 209.0;
|
||||
RNG_delay = c_value * scaler; /* scaled to our sample rate */
|
||||
|
||||
log_cb( RETRO_LOG_DEBUG,"rng_f_0 =%08x\n", RNG_f_0);
|
||||
log_cb( RETRO_LOG_DEBUG,"rng_f_1 =%08x\n", RNG_f_1);
|
||||
log_cb( RETRO_LOG_DEBUG,"rng_delay=%08x\n", RNG_delay);
|
||||
logerror("rng_f_0 =%08x\n", RNG_f_0);
|
||||
logerror("rng_f_1 =%08x\n", RNG_f_1);
|
||||
logerror("rng_delay=%08x\n", RNG_delay);
|
||||
|
||||
/* 0 means no particular part so we allow 1 cycle */
|
||||
c_value = ((double)(1<<PRECISION_SH)) / 1.0;
|
||||
speeds[0] = c_value * scaler; /* scaled to our sample rate */
|
||||
log_cb( RETRO_LOG_DEBUG,"speed[%2i]=%08x\n", 0, speeds[0]);
|
||||
logerror("speed[%2i]=%08x\n", 0, speeds[0]);
|
||||
|
||||
for (i = 1; i < 256; i++)
|
||||
{
|
||||
@ -699,13 +735,13 @@ altogether which corresponds to 1254 chip clock cycles. 13 samples = 543 cycles,
|
||||
}
|
||||
c_value = ((double)(1<<PRECISION_SH)) / ((double)cycles_num);
|
||||
speeds[i] = c_value * scaler; /* scaled to our sample rate */
|
||||
log_cb( RETRO_LOG_DEBUG,"speed[%2i]=%08x\n", i, speeds[i]);
|
||||
logerror("speed[%2i]=%08x\n", i, speeds[i]);
|
||||
}
|
||||
|
||||
/* special case for sustain param =0, which takes 1003 cycles */
|
||||
c_value = ((double)(1<<PRECISION_SH)) / 1003.0;
|
||||
speeds[256] = c_value * scaler; /* scaled to our sample rate */
|
||||
log_cb( RETRO_LOG_DEBUG,"speed[%2i]=%08x\n", 256, speeds[256]);
|
||||
logerror("speed[%2i]=%08x\n", 256, speeds[256]);
|
||||
|
||||
|
||||
namco_54xx_sh_reset();
|
||||
|
@ -1,13 +1,42 @@
|
||||
#ifndef namco54_h
|
||||
#define namco54_h
|
||||
|
||||
|
||||
/*
|
||||
* The 4 bit output of each channel is passed through a bandpass filter.
|
||||
* D0 - D3 are probably TTL level. I will round it up to 4V until measured.
|
||||
* R1, R2, R3, C1, C2 select the filter specs. R4 is for mixing.
|
||||
*
|
||||
* 4.7k
|
||||
* D3 >--ZZZZ--. .--------+---------.
|
||||
* | | | |
|
||||
* 10k | --- c1 Z |
|
||||
* D2 >--ZZZZ--+ --- Z r3 |
|
||||
* | | Z |
|
||||
* 22k | r1 | c2 | |\ 5V |
|
||||
* D1 >--ZZZZ--+-----ZZZZ----+---------+--||----+ | \| |
|
||||
* | Z '--|- \ | r4
|
||||
* 47k | Z r2 | >--+----ZZZZ--> out
|
||||
* D0 >--ZZZZ--' Z .--|+ /
|
||||
* | | | /|
|
||||
* gnd 2V >---' |/ gnd
|
||||
*
|
||||
*/
|
||||
|
||||
struct namco_54xx_interface
|
||||
{
|
||||
int baseclock; /* clock */
|
||||
int mixing_level[3]; /* volume of the 3 output ports */
|
||||
int baseclock; /* clock */
|
||||
int mixing_level; /* volume */
|
||||
double r1[3];
|
||||
double r2[3];
|
||||
double r3[3];
|
||||
double r4[3];
|
||||
double c1[3];
|
||||
double c2[3];
|
||||
};
|
||||
|
||||
int namco_54xx_sh_start(const struct MachineSound *msound);
|
||||
void namco_54xx_sh_reset(void);
|
||||
void namco_54xx_sh_stop(void);
|
||||
|
||||
void namcoio_54XX_write(int data);
|
||||
|
@ -25,10 +25,7 @@ static void (*stream_callback[MIXER_MAX_CHANNELS])(int param,INT16 *buffer,int l
|
||||
static void (*stream_callback_multi[MIXER_MAX_CHANNELS])(int param,INT16 **buffer,int length);
|
||||
|
||||
static int memory[MIXER_MAX_CHANNELS];
|
||||
static int r1[MIXER_MAX_CHANNELS];
|
||||
static int r2[MIXER_MAX_CHANNELS];
|
||||
static int r3[MIXER_MAX_CHANNELS];
|
||||
static int c[MIXER_MAX_CHANNELS];
|
||||
static int k[MIXER_MAX_CHANNELS];
|
||||
|
||||
/*
|
||||
signal >--R1--+--R2--+
|
||||
@ -42,43 +39,49 @@ signal >--R1--+--R2--+
|
||||
/* set C = 0 to disable the filter */
|
||||
void set_RC_filter(int channel,int R1,int R2,int R3,int C)
|
||||
{
|
||||
r1[channel] = R1;
|
||||
r2[channel] = R2;
|
||||
r3[channel] = R3;
|
||||
c[channel] = C;
|
||||
}
|
||||
stream_update(channel, 0);
|
||||
|
||||
void apply_RC_filter(int channel,INT16 *buf,int len,int sample_rate)
|
||||
{
|
||||
float R1,R2,R3,C;
|
||||
float f_R1,f_R2,f_R3,f_C;
|
||||
float Req;
|
||||
int K;
|
||||
int i;
|
||||
|
||||
if (C == 0)
|
||||
{
|
||||
/* filter disabled */
|
||||
k[channel] = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (c[channel] == 0) return; /* filter disabled */
|
||||
|
||||
R1 = r1[channel];
|
||||
R2 = r2[channel];
|
||||
R3 = r3[channel];
|
||||
C = (float)c[channel] * 1E-12; /* convert pF to F */
|
||||
f_R1 = R1;
|
||||
f_R2 = R2;
|
||||
f_R3 = R3;
|
||||
f_C = (float)C * 1E-12; /* convert pF to F */
|
||||
|
||||
/* Cut Frequency = 1/(2*Pi*Req*C) */
|
||||
|
||||
Req = (R1*(R2+R3))/(R1+R2+R3);
|
||||
Req = (f_R1 * (f_R2 + f_R3)) / (f_R1 + f_R2 + f_R3);
|
||||
|
||||
K = 0x10000 * (1 - (exp(-1 / (Req * C) / sample_rate)));
|
||||
/* k = (1-(EXP(-TIMEDELTA/RC))) */
|
||||
k[channel] = 0x10000 * (1 - (exp(-1 / (Req * f_C) / stream_sample_rate[channel])));
|
||||
}
|
||||
|
||||
buf[0] = buf[0] + (memory[channel] - buf[0]) * K / 0x10000;
|
||||
|
||||
void apply_RC_filter(int channel,int len)
|
||||
{
|
||||
int i;
|
||||
INT16 *buf = stream_buffer[channel];
|
||||
|
||||
if (len == 0 || k[channel] == 0) return;
|
||||
|
||||
/* Next Value = PREV + (INPUT_VALUE - PREV) * k */
|
||||
buf[0] = memory[channel] + ((int)(buf[0] - memory[channel]) * k[channel] / 0x10000);
|
||||
|
||||
for (i = 1;i < len;i++)
|
||||
buf[i] = buf[i] + (buf[i-1] - buf[i]) * K / 0x10000;
|
||||
buf[i] = buf[i-1] + ((int)(buf[i] - buf[i-1]) * k[channel] / 0x10000);
|
||||
|
||||
memory[channel] = buf[len-1];
|
||||
}
|
||||
|
||||
|
||||
|
||||
int streams_sh_start(void)
|
||||
{
|
||||
int i;
|
||||
@ -144,7 +147,7 @@ void streams_sh_update(void)
|
||||
stream_buffer_pos[channel+i] = 0;
|
||||
|
||||
for (i = 0;i < stream_joined_channels[channel];i++)
|
||||
apply_RC_filter(channel+i,stream_buffer[channel+i],buflen,stream_sample_rate[channel+i]);
|
||||
apply_RC_filter(channel+i,buflen);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -160,7 +163,7 @@ void streams_sh_update(void)
|
||||
|
||||
stream_buffer_pos[channel] = 0;
|
||||
|
||||
apply_RC_filter(channel,stream_buffer[channel],buflen,stream_sample_rate[channel]);
|
||||
apply_RC_filter(channel,buflen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user