summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/spg2xx_audio.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/machine/spg2xx_audio.cpp')
-rw-r--r--src/devices/machine/spg2xx_audio.cpp133
1 files changed, 77 insertions, 56 deletions
diff --git a/src/devices/machine/spg2xx_audio.cpp b/src/devices/machine/spg2xx_audio.cpp
index 2cf0fd822d8..05fea0b4724 100644
--- a/src/devices/machine/spg2xx_audio.cpp
+++ b/src/devices/machine/spg2xx_audio.cpp
@@ -89,7 +89,6 @@ void spg2xx_audio_device::device_start()
save_item(NAME(m_sample_shift));
save_item(NAME(m_sample_count));
- save_item(NAME(m_sample_addr));
save_item(NAME(m_channel_rate));
save_item(NAME(m_channel_rate_accum));
save_item(NAME(m_rampdown_frame));
@@ -120,7 +119,6 @@ void spg2xx_audio_device::device_reset()
memset(m_sample_shift, 0, 16);
memset(m_sample_count, 0, sizeof(uint32_t) * 16);
- memset(m_sample_addr, 0, sizeof(uint32_t) * 16);
memset(m_channel_rate, 0, sizeof(double) * 16);
memset(m_channel_rate_accum, 0, sizeof(double) * 16);
memset(m_rampdown_frame, 0, sizeof(uint32_t) * 16);
@@ -449,7 +447,9 @@ void spg2xx_audio_device::audio_ctrl_w(offs_t offset, uint16_t data)
case AUDIO_CHANNEL_ENABLE:
{
LOGMASKED(LOG_SPU_WRITES, "audio_ctrl_w: Channel Enable: %04x\n", data);
- const uint16_t changed = m_audio_ctrl_regs[AUDIO_CHANNEL_ENABLE] ^ data;
+ const uint16_t old = m_audio_ctrl_regs[offset];
+ m_audio_ctrl_regs[offset] = data;
+ const uint16_t changed = old ^ m_audio_ctrl_regs[offset];
for (uint32_t channel_bit = 0; channel_bit < 16; channel_bit++)
{
const uint16_t mask = 1 << channel_bit;
@@ -458,44 +458,24 @@ void spg2xx_audio_device::audio_ctrl_w(offs_t offset, uint16_t data)
if (data & mask)
{
+ LOGMASKED(LOG_SPU_WRITES, "Enabling channel %d, rate %f\n", channel_bit, m_channel_rate[channel_bit]);
+ if (m_audio_ctrl_regs[AUDIO_CHANNEL_STOP] & mask)
+ continue;
+
if (!(m_audio_ctrl_regs[AUDIO_CHANNEL_STATUS] & mask))
{
- LOGMASKED(LOG_SPU_WRITES, "Enabling channel %d, rate %f\n", channel_bit, m_channel_rate[channel_bit]);
- m_audio_ctrl_regs[offset] |= mask;
- if (BIT(m_audio_ctrl_regs[AUDIO_CHANNEL_FIQ_ENABLE], channel_bit))
- {
- m_channel_irq[channel_bit]->adjust(attotime::from_hz(m_channel_rate[channel_bit]), channel_bit, attotime::from_hz(m_channel_rate[channel_bit]));
- }
- else
- {
- m_channel_irq[channel_bit]->adjust(attotime::never);
- }
-
- if (!(m_audio_ctrl_regs[AUDIO_CHANNEL_STOP] & mask))
- {
- LOGMASKED(LOG_SPU_WRITES, "Stop not set, starting playback on channel %d, mask %04x\n", channel_bit, mask);
- m_audio_ctrl_regs[AUDIO_CHANNEL_STATUS] |= mask;
- m_sample_addr[channel_bit] = get_wave_addr(channel_bit);
- m_envelope_addr[channel_bit] = get_envelope_addr(channel_bit);
- set_envelope_count(channel_bit, get_envelope_load(channel_bit));
- }
- m_adpcm[channel_bit].reset();
- m_sample_shift[channel_bit] = 0;
- m_sample_count[channel_bit] = 0;
-
- if (get_adpcm36_bit(channel_bit))
- {
- memset(m_adpcm36_state + channel_bit, 0, sizeof(adpcm36_state));
- }
+ LOGMASKED(LOG_SPU_WRITES, "Stop not set, starting playback on channel %d, mask %04x\n", channel_bit, mask);
+ start_channel(channel_bit);
}
}
else
{
- stop_channel(channel_bit);
- //m_audio_ctrl_regs[offset] &= ~mask;
- //m_audio_ctrl_regs[AUDIO_CHANNEL_STATUS] &= ~mask;
- //m_audio_ctrl_regs[AUDIO_CHANNEL_STOP] |= mask;
- //m_audio_ctrl_regs[AUDIO_CHANNEL_TONE_RELEASE] &= ~mask;
+ LOGMASKED(LOG_SPU_WRITES, "Disabling channel %d\n", channel_bit);
+ if (m_audio_ctrl_regs[AUDIO_CHANNEL_STATUS] & mask)
+ {
+ LOGMASKED(LOG_SPU_WRITES, "Stopping channel %d\n", channel_bit);
+ stop_channel(channel_bit);
+ }
}
}
break;
@@ -612,9 +592,29 @@ void spg2xx_audio_device::audio_ctrl_w(offs_t offset, uint16_t data)
}
case AUDIO_CHANNEL_STOP:
+ {
LOGMASKED(LOG_SPU_WRITES, "audio_ctrl_w: Channel Stop Status: %04x\n", data);
+ const uint16_t old = m_audio_ctrl_regs[offset];
m_audio_ctrl_regs[offset] &= ~data;
+ const uint16_t changed = old ^ m_audio_ctrl_regs[offset];
+ for (uint32_t channel_bit = 0; channel_bit < 16; channel_bit++)
+ {
+ const uint16_t mask = 1 << channel_bit;
+ if (!(changed & mask))
+ continue;
+
+ LOGMASKED(LOG_SPU_WRITES, "Clearing stop status of channel %d, rate %f\n", channel_bit, m_channel_rate[channel_bit]);
+ if (!(m_audio_ctrl_regs[AUDIO_CHANNEL_ENABLE] & mask))
+ continue;
+
+ if (!(m_audio_ctrl_regs[AUDIO_CHANNEL_STATUS] & mask))
+ {
+ LOGMASKED(LOG_SPU_WRITES, "Enable set, starting playback on channel %d, mask %04x\n", channel_bit, mask);
+ start_channel(channel_bit);
+ }
+ }
break;
+ }
case AUDIO_CHANNEL_ZERO_CROSS:
LOGMASKED(LOG_SPU_WRITES, "audio_ctrl_w: Channel Zero-Cross Enable: %04x\n", data);
@@ -871,12 +871,9 @@ void spg2xx_audio_device::audio_w(offs_t offset, uint16_t data)
}
}
-void spg2xx_audio_device::sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs)
+void spg2xx_audio_device::sound_stream_update(sound_stream &stream)
{
- auto &out_l = outputs[0];
- auto &out_r = outputs[1];
-
- for (int i = 0; i < out_l.samples(); i++)
+ for (int i = 0; i < stream.samples(); i++)
{
int32_t left_total = 0;
int32_t right_total = 0;
@@ -976,14 +973,38 @@ void spg2xx_audio_device::sound_stream_update(sound_stream &stream, std::vector<
int32_t left_final = (int16_t)((left_total * (int16_t)m_audio_ctrl_regs[AUDIO_MAIN_VOLUME]) >> 7);
int32_t right_final = (int16_t)((right_total * (int16_t)m_audio_ctrl_regs[AUDIO_MAIN_VOLUME]) >> 7);
- out_l.put_int(i, int16_t(left_final), 32768);
- out_r.put_int(i, int16_t(right_final), 32768);
+ stream.put_int(0, i, int16_t(left_final), 32768);
+ stream.put_int(1, i, int16_t(right_final), 32768);
+ }
+}
+
+inline void spg2xx_audio_device::start_channel(const uint32_t channel)
+{
+ if (BIT(m_audio_ctrl_regs[AUDIO_CHANNEL_FIQ_ENABLE], channel))
+ {
+ m_channel_irq[channel]->adjust(attotime::from_hz(m_channel_rate[channel]), channel, attotime::from_hz(m_channel_rate[channel]));
+ }
+ else
+ {
+ m_channel_irq[channel]->adjust(attotime::never);
+ }
+
+ m_audio_ctrl_regs[AUDIO_CHANNEL_STATUS] |= (1 << channel);
+ m_envelope_addr[channel] = get_envelope_addr(channel);
+ set_envelope_count(channel, get_envelope_load(channel));
+
+ m_adpcm[channel].reset();
+ m_sample_shift[channel] = 0;
+ m_sample_count[channel] = 0;
+
+ if (get_adpcm36_bit(channel))
+ {
+ memset(m_adpcm36_state + channel, 0, sizeof(adpcm36_state));
}
}
inline void spg2xx_audio_device::stop_channel(const uint32_t channel)
{
- m_audio_ctrl_regs[AUDIO_CHANNEL_ENABLE] &= ~(1 << channel);
m_audio_ctrl_regs[AUDIO_CHANNEL_STATUS] &= ~(1 << channel);
m_audio_regs[(channel << 4) | AUDIO_MODE] &= ~AUDIO_ADPCM_MASK;
m_audio_ctrl_regs[AUDIO_CHANNEL_TONE_RELEASE] &= ~(1 << channel);
@@ -1026,7 +1047,7 @@ bool spg2xx_audio_device::advance_channel(const uint32_t channel)
if (m_sample_shift[channel] >= 16)
{
m_sample_shift[channel] = 0;
- m_sample_addr[channel]++;
+ inc_wave_addr(channel);
if (get_adpcm36_bit(channel))
{
m_adpcm36_state[channel].m_remaining--;
@@ -1036,7 +1057,7 @@ bool spg2xx_audio_device::advance_channel(const uint32_t channel)
else if (get_16bit_bit(channel))
{
// 16-bit mode
- m_sample_addr[channel]++;
+ inc_wave_addr(channel);
}
else
{
@@ -1045,7 +1066,7 @@ bool spg2xx_audio_device::advance_channel(const uint32_t channel)
if (m_sample_shift[channel] >= 16)
{
m_sample_shift[channel] = 0;
- m_sample_addr[channel]++;
+ inc_wave_addr(channel);
}
}
}
@@ -1102,12 +1123,12 @@ bool spg2xx_audio_device::fetch_sample(const uint32_t channel)
if (get_adpcm36_bit(channel) && tone_mode != 0 && m_adpcm36_state[channel].m_remaining == 0)
{
- m_adpcm36_state[channel].m_header = read_space(m_sample_addr[channel]);
+ m_adpcm36_state[channel].m_header = read_space(get_wave_addr(channel));
m_adpcm36_state[channel].m_remaining = 8;
- m_sample_addr[channel]++;
+ inc_wave_addr(channel);
}
- uint16_t raw_sample = tone_mode ? read_space(m_sample_addr[channel]) : m_audio_regs[wave_data_reg];
+ uint16_t raw_sample = tone_mode ? read_space(get_wave_addr(channel)) : m_audio_regs[wave_data_reg];
#if SPG_LOG_ADPCM36
if (get_adpcm36_bit(channel))
@@ -1140,6 +1161,7 @@ bool spg2xx_audio_device::fetch_sample(const uint32_t channel)
{
LOGMASKED(LOG_SAMPLES, "ADPCM stopped after %d samples\n", m_sample_count[channel]);
m_sample_count[channel] = 0;
+ m_audio_ctrl_regs[AUDIO_CHANNEL_STOP] |= (1 << channel);
stop_channel(channel);
return false;
}
@@ -1159,7 +1181,7 @@ bool spg2xx_audio_device::fetch_sample(const uint32_t channel)
if (get_adpcm36_bit(channel))
m_audio_regs[wave_data_reg] = decode_adpcm36_nybble(channel, adpcm_sample);
else
- m_audio_regs[wave_data_reg] = (uint16_t)(m_adpcm[channel].clock(adpcm_sample) << 4) ^ 0x8000;
+ m_audio_regs[wave_data_reg] = (uint16_t)(m_adpcm[channel].clock(adpcm_sample)) ^ 0x8000;
}
m_sample_count[channel]++;
}
@@ -1206,6 +1228,7 @@ bool spg2xx_audio_device::fetch_sample(const uint32_t channel)
{
LOGMASKED(LOG_SAMPLES, "Channel %d: 8-bit PCM stopped after %d samples\n", channel, m_sample_count[channel]);
m_sample_count[channel] = 0;
+ m_audio_ctrl_regs[AUDIO_CHANNEL_STOP] |= (1 << channel);
stop_channel(channel);
return false;
}
@@ -1229,9 +1252,9 @@ bool spg2xx_audio_device::fetch_sample(const uint32_t channel)
inline void spg2xx_audio_device::loop_channel(const uint32_t channel)
{
- m_sample_addr[channel] = get_loop_addr(channel);
+ set_wave_addr(channel, get_loop_addr(channel));
m_sample_shift[channel] = 0;
- LOGMASKED(LOG_SAMPLES, "Channel %d: Looping to address %08x\n", channel, m_sample_addr[channel]);
+ LOGMASKED(LOG_SAMPLES, "Channel %d: Looping to address %08x\n", channel, get_wave_addr(channel));
}
TIMER_CALLBACK_MEMBER(spg2xx_audio_device::audio_beat_tick)
@@ -1289,11 +1312,8 @@ void spg2xx_audio_device::audio_rampdown_tick(const uint32_t channel)
{
LOGMASKED(LOG_RAMPDOWN, "Stopping channel %d due to rampdown\n", channel);
const uint16_t channel_mask = 1 << channel;
- m_audio_ctrl_regs[AUDIO_CHANNEL_ENABLE] &= ~channel_mask;
- m_audio_ctrl_regs[AUDIO_CHANNEL_STATUS] &= ~channel_mask;
m_audio_ctrl_regs[AUDIO_CHANNEL_STOP] |= channel_mask;
- m_audio_ctrl_regs[AUDIO_ENV_RAMP_DOWN] &= ~channel_mask;
- m_audio_ctrl_regs[AUDIO_CHANNEL_TONE_RELEASE] &= ~channel_mask;
+ stop_channel(channel);
}
}
@@ -1362,6 +1382,7 @@ bool spg2xx_audio_device::audio_envelope_tick(const uint32_t channel)
if (new_edd == 0)
{
LOGMASKED(LOG_ENVELOPES, "Envelope %d at 0, stopping channel\n", channel);
+ m_audio_ctrl_regs[AUDIO_CHANNEL_STOP] |= (1 << channel);
stop_channel(channel);
return true;
}