diff options
Diffstat (limited to 'src/devices/machine/spg2xx_audio.cpp')
-rw-r--r-- | src/devices/machine/spg2xx_audio.cpp | 133 |
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; } |