summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/sound/swp30.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/sound/swp30.cpp')
-rw-r--r--src/devices/sound/swp30.cpp101
1 files changed, 54 insertions, 47 deletions
diff --git a/src/devices/sound/swp30.cpp b/src/devices/sound/swp30.cpp
index dbff6180386..ac1a8b09083 100644
--- a/src/devices/sound/swp30.cpp
+++ b/src/devices/sound/swp30.cpp
@@ -337,23 +337,12 @@ void swp30_device::device_start()
m_global_step[i] = v;
}
- // Log to linear 8-bits sample decompression. Statistics say
- // that's what it should look like. Note that 0 can be encoded
- // both as 0x00 and 0x80, and as it happens 0x80 is never used in
- // these samples. Ends up with a 55dB dynamic range, to compare
- // with 8bits 48dB, 12bits 72dB and 16bits 96dB.
-
- // Rescale so that it's roughly 16 bits. Range ends up being +/- 78c0.
-
- for(int i=0; i<32; i++) {
- m_sample_log8[ i] = i << 0;
- m_sample_log8[0x20|i] = (i << 1) + 0x21;
- m_sample_log8[0x40|i] = (i << 2) + 0x62;
- m_sample_log8[0x60|i] = (i << 3) + 0xe3;
- }
+ // Delta-packed samples decompression.
+
for(int i=0; i<128; i++) {
- m_sample_log8[i] = m_sample_log8[i] << 6;
- m_sample_log8[i | 0x80] = -m_sample_log8[i];
+ s16 base = ((i & 0x1f) << (7+(i >> 5))) + (((1 << (i >> 5))-1) << 12);
+ m_dpcm[i | 0x80] = - base;
+ m_dpcm[i] = + base;
}
save_item(NAME(m_keyon_mask));
@@ -382,6 +371,10 @@ void swp30_device::device_start()
save_item(NAME(m_pan_l));
save_item(NAME(m_pan_r));
+ save_item(NAME(m_dpcm_current));
+ save_item(NAME(m_dpcm_next));
+ save_item(NAME(m_dpcm_address));
+
save_item(NAME(m_sample_history));
save_item(NAME(m_lpf_cutoff));
@@ -434,6 +427,10 @@ void swp30_device::device_reset()
std::fill(m_pan_l.begin(), m_pan_l.end(), 0);
std::fill(m_pan_r.begin(), m_pan_r.end(), 0);
+ 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_meg_program.begin(), m_meg_program.end(), 0);
std::fill(m_meg_const.begin(), m_meg_const.end(), 0);
std::fill(m_meg_offset.begin(), m_meg_offset.end(), 0);
@@ -583,6 +580,13 @@ void swp30_device::keyon_w(u16)
m_pan_l[chan] = (m_pan[chan] & 0xff00) >> 4;
m_pan_r[chan] = (m_pan[chan] & 0x00ff) << 4;
+ m_dpcm_current[chan] = 0;
+ m_dpcm_next[chan] = 0;
+ s32 dt = m_sample_start[chan] & 0xffffff;
+ if(m_sample_end[chan] & 0x80000000)
+ dt = -dt;
+ m_dpcm_address[chan] = ((m_sample_address[chan] & 0xffffff) << 2) - dt;
+
if(1)
logerror("[%08d] keyon %02x %08x %08x %08x vol %04x env %04x %04x %04x pan %04x disp %04x %04x\n", scount, chan, m_sample_start[chan], m_sample_end[chan], m_sample_address[chan], m_release_glo[chan], m_attack[chan], m_decay1[chan], m_decay2[chan], m_pan[chan], m_dry_rev[chan], m_cho_var[chan]);
}
@@ -1221,35 +1225,36 @@ void swp30_device::sound_stream_update(sound_stream &stream, std::vector<read_st
break;
}
- case 3: { // 8-bits dpcm
- offs_t adr = base_address + (spos >> 2);
- switch(spos & 3) {
- case 0: { // ....ABab ........
- u32 l0 = m_rom_cache.read_dword(adr);
- val0 = m_sample_log8[(l0 & 0x000000ff) ];
- val1 = m_sample_log8[(l0 & 0x0000ff00) >> 8];
- break;
- }
- case 1: { // ..ABab.. ........
- u32 l0 = m_rom_cache.read_dword(adr);
- val0 = m_sample_log8[(l0 & 0x0000ff00) >> 8];
- val1 = m_sample_log8[(l0 & 0x00ff0000) >> 16];
- break;
- }
- case 2: { // ABab.... ........
- u32 l0 = m_rom_cache.read_dword(adr);
- val0 = m_sample_log8[(l0 & 0x00ff0000) >> 16];
- val1 = m_sample_log8[(l0 & 0xff000000) >> 24];
- break;
- }
- case 3: { // ab...... ......AB
- u32 l0 = m_rom_cache.read_dword(adr);
- u32 l1 = m_rom_cache.read_dword(adr+1);
- val0 = m_sample_log8[(l0 & 0xff000000) >> 24];
- val1 = m_sample_log8[ l1 & 0x000000ff];
- break;
- }
+ case 3: { // 8-bits delta-pcm
+ 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];
+ adr --;
+ if(sample < -0x8000)
+ sample = -0x8000;
+ else if(sample > 0x7fff)
+ sample = 0x7fff;
+ m_dpcm_next[chan] = sample;
+ }
+ } else {
+ 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];
+ adr ++;
+ if(sample < -0x8000)
+ sample = -0x8000;
+ else if(sample > 0x7fff)
+ sample = 0x7fff;
+ m_dpcm_next[chan] = sample;
+ }
}
+ m_dpcm_address[chan] = adr;
+ val0 = m_dpcm_current[chan];
+ val1 = m_dpcm_next[chan];
break;
}
}
@@ -1277,9 +1282,6 @@ void swp30_device::sound_stream_update(sound_stream &stream, std::vector<read_st
s32 tremolo_level = 0;
dry_l += fpapply(m_envelope_level[chan] + (m_glo_level_cur[chan] << 16) + tremolo_level + ((m_dry_rev[chan] & 0xff00) << 12) + (m_pan_l[chan] << 16), sample);
dry_r += fpapply(m_envelope_level[chan] + (m_glo_level_cur[chan] << 16) + tremolo_level + ((m_dry_rev[chan] & 0xff00) << 12) + (m_pan_r[chan] << 16), sample);
- // logerror("%x %x %x %x - %x %x\n", m_envelope_level[chan], (m_glo_level_cur[chan] << 16), ((m_dry_rev[chan] & 0xff00) << 12), (m_pan_l[chan] << 16), sample, dry_l);
-
- // logerror("env %08x %d\n", m_envelope_level[chan], m_envelope_level[chan]);
#else
dry_l += sample;
@@ -1296,9 +1298,14 @@ void swp30_device::sound_stream_update(sound_stream &stream, std::vector<read_st
if(!(m_sample_end[chan] & 0xffffff))
m_envelope_mode[chan] = IDLE;
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);
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);
}
}