Skip to content

Commit 3c2fb88

Browse files
authored
sound/swp30.cpp, sound/swx00.cpp: Improved DPCM sample decompression. (#12305)
1 parent e0f125b commit 3c2fb88

File tree

4 files changed

+30
-7
lines changed

4 files changed

+30
-7
lines changed

src/devices/sound/swp30.cpp

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,8 @@ const std::array<u32, 4> swp30_device::lfo_shape_centered_tri = { 0x00000000, 0x
437437
const std::array<u32, 4> swp30_device::lfo_shape_offset_saw = { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }; // __////__
438438
const std::array<u32, 4> swp30_device::lfo_shape_offset_tri = { 0x00000000, 0x00000000, 0x000fffff, 0x000fffff }; // __/\/\__
439439

440+
const std::array<u8, 4> swp30_device::dpcm_offset = { 7, 6, 4, 0 };
441+
440442
swp30_device::swp30_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
441443
: cpu_device(mconfig, SWP30, tag, owner, clock),
442444
device_sound_interface(mconfig, *this),
@@ -478,7 +480,7 @@ void swp30_device::device_start()
478480
// Delta-packed samples decompression.
479481

480482
for(int i=0; i<128; i++) {
481-
s16 base = ((i & 0x1f) << (5+(i >> 5))) + (((1 << (i >> 5))-1) << 10);
483+
s16 base = ((i & 0x1f) << (3+(i >> 5))) + (((1 << (i >> 5))-1) << 8);
482484
m_dpcm[i | 0x80] = - base;
483485
m_dpcm[i] = + base;
484486
}
@@ -511,6 +513,7 @@ void swp30_device::device_start()
511513
save_item(NAME(m_dpcm_current));
512514
save_item(NAME(m_dpcm_next));
513515
save_item(NAME(m_dpcm_address));
516+
save_item(NAME(m_dpcm_sum));
514517

515518
save_item(NAME(m_sample_history));
516519

@@ -568,6 +571,7 @@ void swp30_device::device_reset()
568571
std::fill(m_dpcm_current.begin(), m_dpcm_current.end(), false);
569572
std::fill(m_dpcm_next.begin(), m_dpcm_next.end(), false);
570573
std::fill(m_dpcm_address.begin(), m_dpcm_address.end(), false);
574+
std::fill(m_dpcm_sum.begin(), m_dpcm_sum.end(), 0);
571575

572576
std::fill(m_meg_program.begin(), m_meg_program.end(), 0);
573577
std::fill(m_meg_const.begin(), m_meg_const.end(), 0);
@@ -731,6 +735,7 @@ void swp30_device::keyon_w(u16)
731735
if(m_sample_end[chan] & 0x80000000)
732736
dt = -dt;
733737
m_dpcm_address[chan] = ((m_sample_address[chan] & 0xffffff) << 2) - dt;
738+
m_dpcm_sum[chan] = 0;
734739

735740
m_lfo_phase[chan] = 0;
736741

@@ -1476,12 +1481,15 @@ void swp30_device::execute_run()
14761481
}
14771482

14781483
case 3: { // 8-bits delta-pcm
1484+
u8 offset = dpcm_offset[(m_sample_address[chan] >> 25) & 3];
1485+
u8 scale = (m_sample_address[chan] >> 27) & 7;
14791486
offs_t adr = m_dpcm_address[chan];
14801487
if(m_sample_end[chan] & 0x80000000) {
14811488
u32 target_address = (base_address << 2) + spos - 1;
14821489
while(adr >= target_address) {
14831490
m_dpcm_current[chan] = m_dpcm_next[chan];
1484-
s32 sample = m_dpcm_next[chan] + m_dpcm[(m_rom_cache.read_dword(adr >> 2) >> (8*(adr & 3))) & 0xff];
1491+
m_dpcm_sum[chan] += m_dpcm[(m_rom_cache.read_dword(adr >> 2) >> (8*(adr & 3))) & 0xff] - offset;
1492+
s32 sample = (m_dpcm_sum[chan] << scale) >> 3;
14851493
adr --;
14861494
if(sample < -0x8000)
14871495
sample = -0x8000;
@@ -1493,7 +1501,8 @@ void swp30_device::execute_run()
14931501
u32 target_address = (base_address << 2) + spos + 1;
14941502
while(adr <= target_address) {
14951503
m_dpcm_current[chan] = m_dpcm_next[chan];
1496-
s32 sample = m_dpcm_next[chan] + m_dpcm[(m_rom_cache.read_dword(adr >> 2) >> (8*(adr & 3))) & 0xff];
1504+
m_dpcm_sum[chan] += m_dpcm[(m_rom_cache.read_dword(adr >> 2) >> (8*(adr & 3))) & 0xff] - offset;
1505+
s32 sample = (m_dpcm_sum[chan] << scale) >> 3;
14971506
// logerror("## + sample %08x %02x %d\n", adr, (m_rom_cache.read_dword(adr >> 2) >> (8*(adr & 3))) & 0xff, sample);
14981507
adr ++;
14991508
if(sample < -0x8000)
@@ -1545,12 +1554,13 @@ void swp30_device::execute_run()
15451554
else {
15461555
s32 prev = m_sample_pos[chan];
15471556
do
1548-
m_sample_pos[chan] = m_sample_pos[chan] - ((m_sample_end[chan] & 0xffffff) << 8) + ((m_sample_address[chan] >> 22) & 0xfc);
1557+
m_sample_pos[chan] -= (m_sample_end[chan] & 0xffffff) << 8;
15491558
while((m_sample_pos[chan] >> 8) >= (m_sample_end[chan] & 0xffffff));
15501559
if(m_sample_end[chan] & 0x80000000)
15511560
m_dpcm_address[chan] -= (m_sample_pos[chan] >> 8) - (prev >> 8);
15521561
else
15531562
m_dpcm_address[chan] += (m_sample_pos[chan] >> 8) - (prev >> 8);
1563+
m_dpcm_sum[chan] = 0;
15541564
}
15551565
}
15561566

src/devices/sound/swp30.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ class swp30_device : public cpu_device, public device_sound_interface, public sw
6666
static const std::array<u32, 4> lfo_shape_centered_tri;
6767
static const std::array<u32, 4> lfo_shape_offset_saw;
6868
static const std::array<u32, 4> lfo_shape_offset_tri;
69+
static const std::array<u8, 4> dpcm_offset;
6970

7071
std::array<s32, 0x40> m_sample_start;
7172
std::array<s32, 0x40> m_sample_end;
@@ -92,6 +93,7 @@ class swp30_device : public cpu_device, public device_sound_interface, public sw
9293
std::array<s16, 0x40> m_dpcm_current;
9394
std::array<s16, 0x40> m_dpcm_next;
9495
std::array<u32, 0x40> m_dpcm_address;
96+
std::array<s32, 0x40> m_dpcm_sum;
9597

9698
std::array<u64, 0x180> m_meg_program;
9799
std::array<s16, 0x180> m_meg_const;

src/devices/sound/swx00.cpp

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ const std::array<s32, 16> swx00_sound_device::panmap = {
4444
0x300, 0x340, 0x380, 0xfff
4545
};
4646

47+
const std::array<u8, 4> swx00_sound_device::dpcm_offset = { 7, 6, 4, 0 };
48+
4749
swx00_sound_device::swx00_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
4850
: device_t(mconfig, SWX00_SOUND, tag, owner, clock),
4951
device_sound_interface(mconfig, *this),
@@ -93,6 +95,7 @@ void swx00_sound_device::device_start()
9395
save_item(NAME(m_dpcm_current));
9496
save_item(NAME(m_dpcm_next));
9597
save_item(NAME(m_dpcm_address));
98+
save_item(NAME(m_dpcm_sum));
9699

97100

98101
for(int i=0; i != 128; i++) {
@@ -111,7 +114,7 @@ void swx00_sound_device::device_start()
111114
// Delta-packed samples decompression.
112115

113116
for(int i=0; i<128; i++) {
114-
s16 base = ((i & 0x1f) << (5+(i >> 5))) + (((1 << (i >> 5))-1) << 10);
117+
s16 base = ((i & 0x1f) << (3+(i >> 5))) + (((1 << (i >> 5))-1) << 8);
115118
m_dpcm[i | 0x80] = - base;
116119
m_dpcm[i] = + base;
117120
}
@@ -147,6 +150,7 @@ void swx00_sound_device::device_reset()
147150
std::fill(m_dpcm_current.begin(), m_dpcm_current.end(), false);
148151
std::fill(m_dpcm_next.begin(), m_dpcm_next.end(), false);
149152
std::fill(m_dpcm_address.begin(), m_dpcm_address.end(), false);
153+
std::fill(m_dpcm_sum.begin(), m_dpcm_sum.end(), 0);
150154

151155
m_keyon = 0;
152156
m_state_sel = 0;
@@ -346,6 +350,7 @@ void swx00_sound_device::keyon_commit_w(u8)
346350
m_dpcm_current[chan] = 0;
347351
m_dpcm_next[chan] = 0;
348352
m_dpcm_address[chan] = ((m_sample_address[chan] & 0xffffff) << 1) - m_sample_start[chan];
353+
m_dpcm_sum[chan] = 0;
349354

350355
m_glo_level_cur[chan] = (m_glo_pan[chan] >> 4) & 0xff0;
351356
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<r
618623
}
619624

620625
case 3: { // 8-bits delta-pcm
626+
u8 offset = dpcm_offset[(m_sample_address[chan] >> 24) & 3];
627+
u8 scale = (m_sample_address[chan] >> 26) & 7;
621628
u32 target_address = (base_address << 1) + spos + 1;
622629
while(m_dpcm_address[chan] <= target_address) {
623630
m_dpcm_current[chan] = m_dpcm_next[chan];
@@ -626,7 +633,8 @@ void swx00_sound_device::sound_stream_update(sound_stream &stream, std::vector<r
626633
idx &= 0xff;
627634
else
628635
idx >>= 8;
629-
s32 sample = m_dpcm_next[chan] + m_dpcm[idx];
636+
m_dpcm_sum[chan] += m_dpcm[idx] - offset;
637+
s32 sample = (m_dpcm_sum[chan] << scale) >> 3;
630638
m_dpcm_address[chan] ++;
631639
if(sample < -0x8000)
632640
sample = -0x8000;
@@ -667,9 +675,10 @@ void swx00_sound_device::sound_stream_update(sound_stream &stream, std::vector<r
667675
else {
668676
s32 prev = m_sample_pos[chan];
669677
do
670-
m_sample_pos[chan] -= (m_sample_end[chan] << 15) | ((m_sample_address[chan] & 0x3f000000) >> (24-9));
678+
m_sample_pos[chan] -= m_sample_end[chan] << 15;
671679
while((m_sample_pos[chan] >> 15) >= m_sample_end[chan]);
672680
m_dpcm_address[chan] += (m_sample_pos[chan] >> 15) - (prev >> 15);
681+
m_dpcm_sum[chan] = 0;
673682
}
674683
}
675684

src/devices/sound/swx00.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ class swx00_sound_device : public device_t, public device_sound_interface, publi
3030
static const std::array<s32, 0x80> attack_linear_step;
3131
static const std::array<s32, 0x20> decay_linear_step;
3232
static const std::array<s32, 16> panmap;
33+
static const std::array<u8, 4> dpcm_offset;
3334
std::array<s32, 0x80> m_global_step;
3435
std::array<s16, 0x100> m_dpcm;
3536

@@ -57,6 +58,7 @@ class swx00_sound_device : public device_t, public device_sound_interface, publi
5758
std::array<s16, 0x20> m_dpcm_current;
5859
std::array<s16, 0x20> m_dpcm_next;
5960
std::array<u32, 0x20> m_dpcm_address;
61+
std::array<s32, 0x20> m_dpcm_sum;
6062

6163
u32 m_keyon;
6264
u32 m_rom_address;

0 commit comments

Comments
 (0)