From 3c2fb88dd91a09d58bfed0647a660a89246d44c2 Mon Sep 17 00:00:00 2001 From: Theo Niessink Date: Wed, 24 Apr 2024 20:06:31 +0200 Subject: sound/swp30.cpp, sound/swx00.cpp: Improved DPCM sample decompression. (#12305) --- src/devices/sound/swp30.cpp | 18 ++++++++++++++---- src/devices/sound/swp30.h | 2 ++ src/devices/sound/swx00.cpp | 15 ++++++++++++--- src/devices/sound/swx00.h | 2 ++ 4 files changed, 30 insertions(+), 7 deletions(-) diff --git a/src/devices/sound/swp30.cpp b/src/devices/sound/swp30.cpp index 4f84d9f9ed3..70ba7c5c7e6 100644 --- a/src/devices/sound/swp30.cpp +++ b/src/devices/sound/swp30.cpp @@ -437,6 +437,8 @@ const std::array swp30_device::lfo_shape_centered_tri = { 0x00000000, 0x const std::array swp30_device::lfo_shape_offset_saw = { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }; // __////__ const std::array swp30_device::lfo_shape_offset_tri = { 0x00000000, 0x00000000, 0x000fffff, 0x000fffff }; // __/\/\__ +const std::array swp30_device::dpcm_offset = { 7, 6, 4, 0 }; + swp30_device::swp30_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : cpu_device(mconfig, SWP30, tag, owner, clock), device_sound_interface(mconfig, *this), @@ -478,7 +480,7 @@ void swp30_device::device_start() // Delta-packed samples decompression. for(int i=0; i<128; i++) { - s16 base = ((i & 0x1f) << (5+(i >> 5))) + (((1 << (i >> 5))-1) << 10); + s16 base = ((i & 0x1f) << (3+(i >> 5))) + (((1 << (i >> 5))-1) << 8); m_dpcm[i | 0x80] = - base; m_dpcm[i] = + base; } @@ -511,6 +513,7 @@ void swp30_device::device_start() save_item(NAME(m_dpcm_current)); save_item(NAME(m_dpcm_next)); save_item(NAME(m_dpcm_address)); + save_item(NAME(m_dpcm_sum)); save_item(NAME(m_sample_history)); @@ -568,6 +571,7 @@ void swp30_device::device_reset() std::fill(m_dpcm_current.begin(), m_dpcm_current.end(), false); std::fill(m_dpcm_next.begin(), m_dpcm_next.end(), false); std::fill(m_dpcm_address.begin(), m_dpcm_address.end(), false); + std::fill(m_dpcm_sum.begin(), m_dpcm_sum.end(), 0); std::fill(m_meg_program.begin(), m_meg_program.end(), 0); std::fill(m_meg_const.begin(), m_meg_const.end(), 0); @@ -731,6 +735,7 @@ void swp30_device::keyon_w(u16) if(m_sample_end[chan] & 0x80000000) dt = -dt; m_dpcm_address[chan] = ((m_sample_address[chan] & 0xffffff) << 2) - dt; + m_dpcm_sum[chan] = 0; m_lfo_phase[chan] = 0; @@ -1476,12 +1481,15 @@ void swp30_device::execute_run() } case 3: { // 8-bits delta-pcm + u8 offset = dpcm_offset[(m_sample_address[chan] >> 25) & 3]; + u8 scale = (m_sample_address[chan] >> 27) & 7; offs_t adr = m_dpcm_address[chan]; if(m_sample_end[chan] & 0x80000000) { u32 target_address = (base_address << 2) + spos - 1; while(adr >= target_address) { m_dpcm_current[chan] = m_dpcm_next[chan]; - s32 sample = m_dpcm_next[chan] + m_dpcm[(m_rom_cache.read_dword(adr >> 2) >> (8*(adr & 3))) & 0xff]; + m_dpcm_sum[chan] += m_dpcm[(m_rom_cache.read_dword(adr >> 2) >> (8*(adr & 3))) & 0xff] - offset; + s32 sample = (m_dpcm_sum[chan] << scale) >> 3; adr --; if(sample < -0x8000) sample = -0x8000; @@ -1493,7 +1501,8 @@ void swp30_device::execute_run() u32 target_address = (base_address << 2) + spos + 1; while(adr <= target_address) { m_dpcm_current[chan] = m_dpcm_next[chan]; - s32 sample = m_dpcm_next[chan] + m_dpcm[(m_rom_cache.read_dword(adr >> 2) >> (8*(adr & 3))) & 0xff]; + m_dpcm_sum[chan] += m_dpcm[(m_rom_cache.read_dword(adr >> 2) >> (8*(adr & 3))) & 0xff] - offset; + s32 sample = (m_dpcm_sum[chan] << scale) >> 3; // logerror("## + sample %08x %02x %d\n", adr, (m_rom_cache.read_dword(adr >> 2) >> (8*(adr & 3))) & 0xff, sample); adr ++; if(sample < -0x8000) @@ -1545,12 +1554,13 @@ void swp30_device::execute_run() else { s32 prev = m_sample_pos[chan]; do - m_sample_pos[chan] = m_sample_pos[chan] - ((m_sample_end[chan] & 0xffffff) << 8) + ((m_sample_address[chan] >> 22) & 0xfc); + m_sample_pos[chan] -= (m_sample_end[chan] & 0xffffff) << 8; while((m_sample_pos[chan] >> 8) >= (m_sample_end[chan] & 0xffffff)); if(m_sample_end[chan] & 0x80000000) m_dpcm_address[chan] -= (m_sample_pos[chan] >> 8) - (prev >> 8); else m_dpcm_address[chan] += (m_sample_pos[chan] >> 8) - (prev >> 8); + m_dpcm_sum[chan] = 0; } } diff --git a/src/devices/sound/swp30.h b/src/devices/sound/swp30.h index 6a2a8aff9b6..3529a39a032 100644 --- a/src/devices/sound/swp30.h +++ b/src/devices/sound/swp30.h @@ -66,6 +66,7 @@ private: static const std::array lfo_shape_centered_tri; static const std::array lfo_shape_offset_saw; static const std::array lfo_shape_offset_tri; + static const std::array dpcm_offset; std::array m_sample_start; std::array m_sample_end; @@ -92,6 +93,7 @@ private: std::array m_dpcm_current; std::array m_dpcm_next; std::array m_dpcm_address; + std::array m_dpcm_sum; std::array m_meg_program; std::array m_meg_const; diff --git a/src/devices/sound/swx00.cpp b/src/devices/sound/swx00.cpp index 26800471268..4f21fe1a90f 100644 --- a/src/devices/sound/swx00.cpp +++ b/src/devices/sound/swx00.cpp @@ -44,6 +44,8 @@ const std::array swx00_sound_device::panmap = { 0x300, 0x340, 0x380, 0xfff }; +const std::array swx00_sound_device::dpcm_offset = { 7, 6, 4, 0 }; + swx00_sound_device::swx00_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : device_t(mconfig, SWX00_SOUND, tag, owner, clock), device_sound_interface(mconfig, *this), @@ -93,6 +95,7 @@ void swx00_sound_device::device_start() save_item(NAME(m_dpcm_current)); save_item(NAME(m_dpcm_next)); save_item(NAME(m_dpcm_address)); + save_item(NAME(m_dpcm_sum)); for(int i=0; i != 128; i++) { @@ -111,7 +114,7 @@ void swx00_sound_device::device_start() // Delta-packed samples decompression. for(int i=0; i<128; i++) { - s16 base = ((i & 0x1f) << (5+(i >> 5))) + (((1 << (i >> 5))-1) << 10); + s16 base = ((i & 0x1f) << (3+(i >> 5))) + (((1 << (i >> 5))-1) << 8); m_dpcm[i | 0x80] = - base; m_dpcm[i] = + base; } @@ -147,6 +150,7 @@ void swx00_sound_device::device_reset() std::fill(m_dpcm_current.begin(), m_dpcm_current.end(), false); std::fill(m_dpcm_next.begin(), m_dpcm_next.end(), false); std::fill(m_dpcm_address.begin(), m_dpcm_address.end(), false); + std::fill(m_dpcm_sum.begin(), m_dpcm_sum.end(), 0); m_keyon = 0; m_state_sel = 0; @@ -346,6 +350,7 @@ void swx00_sound_device::keyon_commit_w(u8) m_dpcm_current[chan] = 0; m_dpcm_next[chan] = 0; m_dpcm_address[chan] = ((m_sample_address[chan] & 0xffffff) << 1) - m_sample_start[chan]; + m_dpcm_sum[chan] = 0; m_glo_level_cur[chan] = (m_glo_pan[chan] >> 4) & 0xff0; m_pan_l[chan] = panmap[(m_glo_pan[chan] >> 4) & 15]; @@ -618,6 +623,8 @@ void swx00_sound_device::sound_stream_update(sound_stream &stream, std::vector> 24) & 3]; + u8 scale = (m_sample_address[chan] >> 26) & 7; u32 target_address = (base_address << 1) + spos + 1; while(m_dpcm_address[chan] <= target_address) { m_dpcm_current[chan] = m_dpcm_next[chan]; @@ -626,7 +633,8 @@ void swx00_sound_device::sound_stream_update(sound_stream &stream, std::vector>= 8; - s32 sample = m_dpcm_next[chan] + m_dpcm[idx]; + m_dpcm_sum[chan] += m_dpcm[idx] - offset; + s32 sample = (m_dpcm_sum[chan] << scale) >> 3; m_dpcm_address[chan] ++; if(sample < -0x8000) sample = -0x8000; @@ -667,9 +675,10 @@ void swx00_sound_device::sound_stream_update(sound_stream &stream, std::vector> (24-9)); + m_sample_pos[chan] -= m_sample_end[chan] << 15; while((m_sample_pos[chan] >> 15) >= m_sample_end[chan]); m_dpcm_address[chan] += (m_sample_pos[chan] >> 15) - (prev >> 15); + m_dpcm_sum[chan] = 0; } } diff --git a/src/devices/sound/swx00.h b/src/devices/sound/swx00.h index 35a0fb1a52e..5ee8f700f1f 100644 --- a/src/devices/sound/swx00.h +++ b/src/devices/sound/swx00.h @@ -30,6 +30,7 @@ private: static const std::array attack_linear_step; static const std::array decay_linear_step; static const std::array panmap; + static const std::array dpcm_offset; std::array m_global_step; std::array m_dpcm; @@ -57,6 +58,7 @@ private: std::array m_dpcm_current; std::array m_dpcm_next; std::array m_dpcm_address; + std::array m_dpcm_sum; u32 m_keyon; u32 m_rom_address; -- cgit v1.2.3