diff --git a/src/devices/sound/okiadpcm.cpp b/src/devices/sound/okiadpcm.cpp index 160ddc3519b..4b565042288 100644 --- a/src/devices/sound/okiadpcm.cpp +++ b/src/devices/sound/okiadpcm.cpp @@ -2,7 +2,7 @@ // copyright-holders:Andrew Gardner,Aaron Giles /*************************************************************************** - okiadpcm.h + okiadpcm.cpp OKI ADPCM emulation. @@ -39,14 +39,15 @@ int oki_adpcm_state::s_diff_lookup[49*16]; void oki_adpcm_state::reset() { // reset the signal/step - m_signal = -2; - m_step = 0; + m_signal = m_loop_signal = 0; + m_step = m_loop_step = 0; + m_saved = false; } //------------------------------------------------- -// device_clock_changed - called if the clock -// changes +// clock - decode single nibble and update +// ADPCM output //------------------------------------------------- int16_t oki_adpcm_state::clock(uint8_t nibble) @@ -72,6 +73,36 @@ int16_t oki_adpcm_state::clock(uint8_t nibble) } +//------------------------------------------------- +// save - save current ADPCM state to buffer +//------------------------------------------------- + +void oki_adpcm_state::save() +{ + if (!m_saved) + { + m_loop_signal = m_signal; + m_loop_step = m_step; + m_saved = true; + } +} + + +//------------------------------------------------- +// restore - restore previous ADPCM state +// from buffer +//------------------------------------------------- + +void oki_adpcm_state::restore() +{ + if (m_saved) + { + m_signal = m_loop_signal; + m_step = m_loop_step; + } +} + + //------------------------------------------------- // compute_tables - precompute tables for faster // sound generation @@ -128,14 +159,15 @@ int oki_adpcm2_state::s_diff_lookup[49*16]; void oki_adpcm2_state::reset() { // reset the signal/step - m_signal = -2; - m_step = 0; + m_signal = m_loop_signal = -2; + m_step = m_loop_step = 0; + m_saved = false; } //------------------------------------------------- -// device_clock_changed - called if the clock -// changes +// clock - decode single nibble and update +// ADPCM output //------------------------------------------------- int16_t oki_adpcm2_state::clock(uint8_t nibble) @@ -161,6 +193,36 @@ int16_t oki_adpcm2_state::clock(uint8_t nibble) } +//------------------------------------------------- +// save - save current ADPCM state to buffer +//------------------------------------------------- + +void oki_adpcm2_state::save() +{ + if (!m_saved) + { + m_loop_signal = m_signal; + m_loop_step = m_step; + m_saved = true; + } +} + + +//------------------------------------------------- +// restore - restore previous ADPCM state +// from buffer +//------------------------------------------------- + +void oki_adpcm2_state::restore() +{ + if (m_saved) + { + m_signal = m_loop_signal; + m_step = m_loop_step; + } +} + + //------------------------------------------------- // compute_tables - precompute tables for faster // sound generation diff --git a/src/devices/sound/okiadpcm.h b/src/devices/sound/okiadpcm.h index 62ff8d9a5fc..b89e3ab8db7 100644 --- a/src/devices/sound/okiadpcm.h +++ b/src/devices/sound/okiadpcm.h @@ -24,9 +24,15 @@ public: void reset(); int16_t clock(uint8_t nibble); + int16_t output() { return m_signal; } + void save(); + void restore(); int32_t m_signal; int32_t m_step; + int32_t m_loop_signal; + int32_t m_loop_step; + bool m_saved; private: static const int8_t s_index_shift[8]; @@ -48,9 +54,15 @@ public: void reset(); int16_t clock(uint8_t nibble); + int16_t output() { return m_signal; } + void save(); + void restore(); int32_t m_signal; int32_t m_step; + int32_t m_loop_signal; + int32_t m_loop_step; + bool m_saved; private: static const int8_t s_index_shift[8]; diff --git a/src/devices/sound/qs1000.cpp b/src/devices/sound/qs1000.cpp index 4f6f86fa6d1..0fd23945a2e 100644 --- a/src/devices/sound/qs1000.cpp +++ b/src/devices/sound/qs1000.cpp @@ -259,6 +259,9 @@ void qs1000_device::device_start() save_item(NAME(m_channels[i].m_regs), i); save_item(NAME(m_channels[i].m_adpcm.m_signal), i); save_item(NAME(m_channels[i].m_adpcm.m_step), i); + save_item(NAME(m_channels[i].m_adpcm.m_loop_signal), i); + save_item(NAME(m_channels[i].m_adpcm.m_loop_step), i); + save_item(NAME(m_channels[i].m_adpcm.m_saved), i); } } @@ -504,8 +507,17 @@ void qs1000_device::sound_stream_update(sound_stream &stream, stream_sample_t ** { chan.m_adpcm_addr++; - if (chan.m_start + chan.m_adpcm_addr >= chan.m_loop_end) + if (chan.m_start + chan.m_adpcm_addr >= chan.m_loop_end) + { chan.m_adpcm_addr = chan.m_loop_start - chan.m_start; +#if 0 // Looping disabled until envelopes work + chan.m_adpcm.restore(); + } + if (chan.m_start + chan.m_adpcm_addr == chan.m_loop_start) + { + chan.m_adpcm.save(); +#endif + } uint8_t data = read_byte(chan.m_start + (chan.m_adpcm_addr >> 1)); uint8_t nibble = (chan.m_adpcm_addr & 1 ? data : data >> 4) & 0xf;