sc01: Fix pitch and closure [O. Galibert]

wow, gorf: Fix sc01 hookup [O. Galibert, Frank Palazzolo, plgDavid]

Note that the dynamic clock changes will sound bad until Aaron's sound
stream fixes are in.
This commit is contained in:
Olivier Galibert 2020-08-21 22:08:57 +02:00
parent f4a9504181
commit e59030aa3d
4 changed files with 58 additions and 15 deletions

View File

@ -63,6 +63,7 @@ void filter_rc_device::sound_stream_update(sound_stream &stream, stream_sample_t
switch (m_type) switch (m_type)
{ {
case LOWPASS: case LOWPASS:
case LOWPASS_2C:
while (samples--) while (samples--)
{ {
memory += ((*src++ - memory) * m_k) / 0x10000; memory += ((*src++ - memory) * m_k) / 0x10000;
@ -93,10 +94,21 @@ void filter_rc_device::recalc()
{ {
/* filter disabled */ /* filter disabled */
m_k = 0x10000; m_k = 0x10000;
m_memory = 0x0;
return; return;
} }
Req = (m_R1 * (m_R2 + m_R3)) / (m_R1 + m_R2 + m_R3); Req = (m_R1 * (m_R2 + m_R3)) / (m_R1 + m_R2 + m_R3);
break; break;
case LOWPASS_2C:
if (m_C == 0.0)
{
/* filter disabled */
m_k = 0x10000;
m_memory = 0x0;
return;
}
Req = m_R1;
break;
case HIGHPASS: case HIGHPASS:
case AC: case AC:
if (m_C == 0.0) if (m_C == 0.0)

View File

@ -18,6 +18,16 @@
* *
* Set C=0 to disable filter * Set C=0 to disable filter
* *
* FLT_RC_LOWPASS_@C:
*
* signal >--R1--+----> amp
* |
* C
* |
* GND
*
* Set C=0 to disable filter
*
* FLT_RC_HIGHPASS: * FLT_RC_HIGHPASS:
* *
* signal >--C---+----> amp * signal >--C---+----> amp
@ -53,8 +63,9 @@ public:
enum enum
{ {
LOWPASS = 0, LOWPASS = 0,
HIGHPASS = 1, LOWPASS_2C = 2,
AC = 2 HIGHPASS = 3,
AC = 4
}; };
filter_rc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0); filter_rc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
@ -70,6 +81,16 @@ public:
return *this; return *this;
} }
filter_rc_device &set_lowpass(double R, double C)
{
m_type = LOWPASS_2C;
m_R1 = R;
m_R2 = 0;
m_R3 = 0;
m_C = C;
return *this;
}
filter_rc_device &filter_rc_set_RC(int type, double R1, double R2, double R3, double C) filter_rc_device &filter_rc_set_RC(int type, double R1, double R2, double R3, double C)
{ {
m_stream->update(); m_stream->update();

View File

@ -470,14 +470,17 @@ void votrax_sc01_device::chip_update()
// Pitch counter. Equality comparison, so it's possible to make // Pitch counter. Equality comparison, so it's possible to make
// it miss by manipulating the inflection inputs, but it'll wrap. // it miss by manipulating the inflection inputs, but it'll wrap.
// There's a delay, hence the +1. // There's a delay, hence the +2.
m_pitch = (m_pitch + 1) & 0x7f;
if(m_pitch == (0x7f ^ (m_inflection << 4) ^ m_filt_f1) + 1) // Intrinsically pre-divides by two, so we added one bit on the 7
m_pitch = (m_pitch + 1) & 0xff;
if(m_pitch == (0xe0 ^ (m_inflection << 5) ^ (m_filt_f1 << 1)) + 2)
m_pitch = 0; m_pitch = 0;
// Filters are updated in index 1 of the pitch wave, which does // Filters are updated in index 1 of the pitch wave, which does
// indeed mean four times in a row. // indeed mean four times in a row.
if((m_pitch >> 2) == 1) if((m_pitch & 0xf9) == 0x08)
filters_commit(false); filters_commit(false);
// Noise shift register. 15 bits, with a nxor on the last two // Noise shift register. 15 bits, with a nxor on the last two
@ -486,7 +489,7 @@ void votrax_sc01_device::chip_update()
m_noise = ((m_noise << 1) & 0x7ffe) | inp; m_noise = ((m_noise << 1) & 0x7ffe) | inp;
m_cur_noise = !(((m_noise >> 14) ^ (m_noise >> 13)) & 1); m_cur_noise = !(((m_noise >> 14) ^ (m_noise >> 13)) & 1);
// logerror("tick %02x.%03x 625=%d 208=%d pitch=%02x.%x ns=%04x ni=%d noise=%d cl=%x.%x clf=%d/%d\n", m_ticks, m_phonetick, tick_625, tick_208, m_pitch >> 2, m_pitch & 3, m_noise, inp, m_cur_noise, m_closure >> 2, m_closure & 3, m_rom_closure, m_cur_closure); // logerror("%s tick %02x.%03x 625=%d 208=%d pitch=%02x.%x ns=%04x ni=%d noise=%d cl=%x.%x clf=%d/%d\n", machine().time().to_string(), m_ticks, m_phonetick, tick_625, tick_208, m_pitch >> 3, m_pitch & 7, m_noise, inp, m_cur_noise, m_closure >> 2, m_closure & 3, m_rom_closure, m_cur_closure);
} }
void votrax_sc01_device::filters_commit(bool force) void votrax_sc01_device::filters_commit(bool force)
@ -570,7 +573,7 @@ stream_sample_t votrax_sc01_device::analog_calc()
// Voice-only path. // Voice-only path.
// 1. Pick up the pitch wave // 1. Pick up the pitch wave
double v = m_pitch >= (9 << 2) ? 0 : s_glottal_wave[m_pitch >> 2]; double v = m_pitch >= (9 << 3) ? 0 : s_glottal_wave[m_pitch >> 3];
// 2. Multiply by the initial amplifier. It's linear on the die, // 2. Multiply by the initial amplifier. It's linear on the die,
// even if it's not in the patent. // even if it's not in the patent.
@ -622,7 +625,7 @@ stream_sample_t votrax_sc01_device::analog_calc()
shift_hist(vn, m_vn_4); shift_hist(vn, m_vn_4);
// 13. Apply the glottal closure amplitude, also linear // 13. Apply the glottal closure amplitude, also linear
vn = vn * (7 ^ (m_cur_closure >> 2)) / 7.0; vn = vn * (7 ^ (m_closure >> 2)) / 7.0;
shift_hist(vn, m_vn_5); shift_hist(vn, m_vn_5);
// 13. Apply the final fixed filter // 13. Apply the final fixed filter

View File

@ -124,6 +124,7 @@
#include "machine/watchdog.h" #include "machine/watchdog.h"
#include "sound/ay8910.h" #include "sound/ay8910.h"
#include "sound/votrax.h" #include "sound/votrax.h"
#include "sound/flt_rc.h"
#include "speaker.h" #include "speaker.h"
@ -397,10 +398,11 @@ void tenpindx_state::lights_w(uint8_t data)
void astrocde_state::votrax_speech_w(uint8_t data) void astrocde_state::votrax_speech_w(uint8_t data)
{ {
m_votrax->inflection_w(data >> 6); // Note that the frequency change is smooth, but we just can't
// handle that.
m_votrax->set_clock(data & 0x40 ? 782000 : 756000);
m_votrax->inflection_w(data & 0x80 ? 0 : 2);
m_votrax->write(data & 0x3f); m_votrax->write(data & 0x3f);
/* Note : We should really also use volume in this as well as frequency */
} }
@ -1355,8 +1357,13 @@ void astrocde_state::wow(machine_config &config)
m_astrocade_sound1->so_cb<5>().set("outlatch", FUNC(cd4099_device::write_nibble_d0)); m_astrocade_sound1->so_cb<5>().set("outlatch", FUNC(cd4099_device::write_nibble_d0));
m_astrocade_sound1->so_cb<7>().set(FUNC(astrocde_state::votrax_speech_w)); m_astrocade_sound1->so_cb<7>().set(FUNC(astrocde_state::votrax_speech_w));
VOTRAX_SC01(config, m_votrax, 720000); VOTRAX_SC01(config, m_votrax, 756000);
m_votrax->add_route(ALL_OUTPUTS, "center", 0.85);
m_votrax->add_route(0, "f1", 0.85);
FILTER_RC(config, "f1").set_lowpass(110e3, 560e-12).add_route(0, "f2", 1.00);
FILTER_RC(config, "f2").set_lowpass(110e3, 560e-12).add_route(0, "f3", 1.00);
FILTER_RC(config, "f3").set_lowpass(110e3, 560e-12).add_route(0, "f4", 1.00);
FILTER_RC(config, "f4").set_lowpass(110e3, 560e-12).add_route(0, "center", 1.00);
} }
void astrocde_state::gorf(machine_config &config) void astrocde_state::gorf(machine_config &config)
@ -1406,7 +1413,7 @@ void astrocde_state::gorf(machine_config &config)
ASTROCADE_IO(config, "astrocade2", ASTROCADE_CLOCK/4).add_route(ALL_OUTPUTS, "lower", 1.0); ASTROCADE_IO(config, "astrocade2", ASTROCADE_CLOCK/4).add_route(ALL_OUTPUTS, "lower", 1.0);
VOTRAX_SC01(config, m_votrax, 720000); VOTRAX_SC01(config, m_votrax, 756000);
m_votrax->add_route(ALL_OUTPUTS, "upper", 0.85); m_votrax->add_route(ALL_OUTPUTS, "upper", 0.85);
} }