summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/sound/ay8910.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/sound/ay8910.cpp')
-rw-r--r--src/devices/sound/ay8910.cpp80
1 files changed, 32 insertions, 48 deletions
diff --git a/src/devices/sound/ay8910.cpp b/src/devices/sound/ay8910.cpp
index 1b1026b9e57..8ba53fb8b3f 100644
--- a/src/devices/sound/ay8910.cpp
+++ b/src/devices/sound/ay8910.cpp
@@ -593,7 +593,7 @@ YM2203 Japanese datasheet contents, translated: http://www.larwe.com/technical/c
#define ENABLE_REGISTER_TEST (0) /* Enable preprogrammed registers */
#define LOG_IGNORED_WRITES (0)
-static constexpr int MAX_OUTPUT = 0x7fff;
+static constexpr stream_buffer::sample_t MAX_OUTPUT = 1.0;
/*************************************
*
@@ -770,7 +770,7 @@ static const ay8910_device::mosfet_param ay8910_mosfet_param =
*
*************************************/
-static inline void build_3D_table(double rl, const ay8910_device::ay_ym_param *par, const ay8910_device::ay_ym_param *par_env, int normalize, double factor, int zero_is_off, s32 *tab)
+static inline void build_3D_table(double rl, const ay8910_device::ay_ym_param *par, const ay8910_device::ay_ym_param *par_env, int normalize, double factor, int zero_is_off, stream_buffer::sample_t *tab)
{
double min = 10.0, max = 0.0;
@@ -829,7 +829,7 @@ static inline void build_3D_table(double rl, const ay8910_device::ay_ym_param *p
/* for (e = 0;e<16;e++) printf("%d %d\n",e << 10, tab[e << 10]); */
}
-static inline void build_single_table(double rl, const ay8910_device::ay_ym_param *par, int normalize, s32 *tab, int zero_is_off)
+static inline void build_single_table(double rl, const ay8910_device::ay_ym_param *par, int normalize, stream_buffer::sample_t *tab, int zero_is_off)
{
double rt;
double rw;
@@ -867,7 +867,7 @@ static inline void build_single_table(double rl, const ay8910_device::ay_ym_para
}
-static inline void build_mosfet_resistor_table(const ay8910_device::mosfet_param &par, const double rd, s32 *tab)
+static inline void build_mosfet_resistor_table(const ay8910_device::mosfet_param &par, const double rd, stream_buffer::sample_t *tab)
{
for (int j = 0; j < par.m_count; j++)
{
@@ -878,18 +878,14 @@ static inline void build_mosfet_resistor_table(const ay8910_device::mosfet_param
const double Vs = p2 - sqrt(p2 * p2 - Vg * Vg);
const double res = rd * (Vd / Vs - 1.0);
- /* That's the biggest value we can stream on to netlist. */
- if (res > (1 << 28))
- tab[j] = (1 << 28);
- else
- tab[j] = res;
+ tab[j] = res;
//printf("%d %f %10d\n", j, rd / (res + rd) * 5.0, tab[j]);
}
}
-u16 ay8910_device::mix_3D()
+stream_buffer::sample_t ay8910_device::mix_3D()
{
int indx = 0;
@@ -1085,27 +1081,18 @@ void ay8910_device::ay8910_write_reg(int r, int v)
// sound_stream_update - handle a stream update
//-------------------------------------------------
-void ay8910_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
+void ay8910_device::sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs)
{
- stream_sample_t *buf[NUM_CHANNELS];
tone_t *tone;
envelope_t *envelope;
- buf[0] = outputs[0];
- buf[1] = nullptr;
- buf[2] = nullptr;
- if (m_streams == NUM_CHANNELS)
- {
- buf[1] = outputs[1];
- buf[2] = outputs[2];
- }
+ int samples = outputs[0].samples();
/* hack to prevent us from hanging when starting filtered outputs */
if (!m_ready)
{
- for (int chan = 0; chan < NUM_CHANNELS; chan++)
- if (buf[chan] != nullptr)
- memset(buf[chan], 0, samples * sizeof(*buf[chan]));
+ for (int chan = 0; chan < m_streams; chan++)
+ outputs[chan].fill(0);
}
/* The 8910 has three outputs, each output is the mix of one of the three */
@@ -1116,17 +1103,18 @@ void ay8910_device::sound_stream_update(sound_stream &stream, stream_sample_t **
/* is 1, not 0, and can be modulated changing the volume. */
/* buffering loop */
- while (samples)
+ for (int sampindex = 0; sampindex < samples; sampindex++)
{
for (int chan = 0; chan < NUM_CHANNELS; chan++)
{
tone = &m_tone[chan];
- tone->count++;
- if (tone->count >= tone->period)
+ const int period = std::max<int>(1,tone->period);
+ tone->count += is_expanded_mode() ? 16 : 1;
+ while (tone->count >= period)
{
tone->duty_cycle = (tone->duty_cycle - 1) & 0x1f;
- tone->output = (m_feature & PSG_HAS_EXPANDED_MODE) ? BIT(duty_cycle[tone_duty(tone)], tone->duty_cycle) : BIT(tone->duty_cycle, 0);
- tone->count = 0;
+ tone->output = is_expanded_mode() ? BIT(duty_cycle[tone_duty(tone)], tone->duty_cycle) : BIT(tone->duty_cycle, 0);
+ tone->count -= period;
}
}
@@ -1137,8 +1125,9 @@ void ay8910_device::sound_stream_update(sound_stream &stream, stream_sample_t **
* channels.
*/
m_count_noise = 0;
+ m_prescale_noise ^= 1;
- if (!m_prescale_noise)
+ if (!m_prescale_noise || is_expanded_mode()) // AY8930 noise generator rate is twice compares as compatibility mode
{
/* The Random Number Generator of the 8910 is a 17-bit shift */
/* register. The input to the shift register is bit0 XOR bit3 */
@@ -1147,9 +1136,7 @@ void ay8910_device::sound_stream_update(sound_stream &stream, stream_sample_t **
// TODO : get actually algorithm for AY8930
m_rng ^= (((m_rng & 1) ^ ((m_rng >> 3) & 1)) << 17);
m_rng >>= 1;
- m_prescale_noise = (m_feature & PSG_HAS_EXPANDED_MODE) ? 16 : 1;
}
- m_prescale_noise--;
}
for (int chan = 0; chan < NUM_CHANNELS; chan++)
@@ -1212,40 +1199,39 @@ void ay8910_device::sound_stream_update(sound_stream &stream, stream_sample_t **
{
env_volume >>= 1;
if (m_feature & PSG_EXTENDED_ENVELOPE) // AY8914 Has a two bit tone_envelope field
- *(buf[chan]++) = m_vol_table[chan][m_vol_enabled[chan] ? env_volume >> (3-tone_envelope(tone)) : 0];
+ outputs[chan].put(sampindex, m_vol_table[chan][m_vol_enabled[chan] ? env_volume >> (3-tone_envelope(tone)) : 0]);
else
- *(buf[chan]++) = m_vol_table[chan][m_vol_enabled[chan] ? env_volume : 0];
+ outputs[chan].put(sampindex, m_vol_table[chan][m_vol_enabled[chan] ? env_volume : 0]);
}
else
{
if (m_feature & PSG_EXTENDED_ENVELOPE) // AY8914 Has a two bit tone_envelope field
- *(buf[chan]++) = m_env_table[chan][m_vol_enabled[chan] ? env_volume >> (3-tone_envelope(tone)) : 0];
+ outputs[chan].put(sampindex, m_env_table[chan][m_vol_enabled[chan] ? env_volume >> (3-tone_envelope(tone)) : 0]);
else
- *(buf[chan]++) = m_env_table[chan][m_vol_enabled[chan] ? env_volume : 0];
+ outputs[chan].put(sampindex, m_env_table[chan][m_vol_enabled[chan] ? env_volume : 0]);
}
}
else
{
if (m_feature & PSG_EXTENDED_ENVELOPE) // AY8914 Has a two bit tone_envelope field
- *(buf[chan]++) = m_env_table[chan][m_vol_enabled[chan] ? env_volume >> (3-tone_envelope(tone)) : 0];
+ outputs[chan].put(sampindex, m_env_table[chan][m_vol_enabled[chan] ? env_volume >> (3-tone_envelope(tone)) : 0]);
else
- *(buf[chan]++) = m_env_table[chan][m_vol_enabled[chan] ? env_volume : 0];
+ outputs[chan].put(sampindex, m_env_table[chan][m_vol_enabled[chan] ? env_volume : 0]);
}
}
else
{
if (is_expanded_mode())
- *(buf[chan]++) = m_env_table[chan][m_vol_enabled[chan] ? tone_volume(tone) : 0];
+ outputs[chan].put(sampindex, m_env_table[chan][m_vol_enabled[chan] ? tone_volume(tone) : 0]);
else
- *(buf[chan]++) = m_vol_table[chan][m_vol_enabled[chan] ? tone_volume(tone) : 0];
+ outputs[chan].put(sampindex, m_vol_table[chan][m_vol_enabled[chan] ? tone_volume(tone) : 0]);
}
}
}
else
{
- *(buf[0]++) = mix_3D();
+ outputs[0].put(sampindex, mix_3D());
}
- samples--;
}
}
@@ -1344,13 +1330,13 @@ void ay8910_device::device_start()
m_streams = 1;
}
- m_vol3d_table = make_unique_clear<s32[]>(8*32*32*32);
+ m_vol3d_table = make_unique_clear<stream_buffer::sample_t[]>(8*32*32*32);
build_mixer_table();
/* The envelope is pacing twice as fast for the YM2149 as for the AY-3-8910, */
/* This handled by the step parameter. Consequently we use a multipler of 2 here. */
- m_channel = machine().sound().stream_alloc(*this, 0, m_streams, (m_feature & PSG_HAS_EXPANDED_MODE) ? master_clock * 2 : master_clock / 8);
+ m_channel = stream_alloc(0, m_streams, master_clock / 8);
ay_set_clock(master_clock);
ay8910_statesave();
@@ -1396,16 +1382,16 @@ void ay8910_device::set_volume(int channel,int volume)
{
for (int ch = 0; ch < m_streams; ch++)
if (channel == ch || m_streams == 1 || channel == ALL_8910_CHANNELS)
- m_channel->set_output_gain(ch, volume / 100.0);
+ set_output_gain(ch, volume / 100.0);
}
void ay8910_device::ay_set_clock(int clock)
{
// FIXME: this doesn't belong here, it should be an input pin exposed via devcb
if (((m_feature & PSG_PIN26_IS_CLKSEL) && (m_flags & YM2149_PIN26_LOW)) || (m_feature & PSG_HAS_INTERNAL_DIVIDER))
- m_channel->set_sample_rate((m_feature & PSG_HAS_EXPANDED_MODE) ? clock : clock / 16);
+ m_channel->set_sample_rate(clock / 16);
else
- m_channel->set_sample_rate((m_feature & PSG_HAS_EXPANDED_MODE) ? clock * 2 : clock / 8);
+ m_channel->set_sample_rate(clock / 8);
}
void ay8910_device::device_clock_changed()
@@ -1673,8 +1659,6 @@ void ay8910_device::set_type(psg_type_t psg_type)
m_par = &ym2149_param;
m_par_env = &ym2149_param_env;
}
- if (m_feature & PSG_HAS_EXPANDED_MODE)
- m_step *= 16;
}
DEFINE_DEVICE_TYPE(AY8912, ay8912_device, "ay8912", "AY-3-8912A PSG")