sound/swp00.cpp: Improved DPCM sample decompression (#12300)
This commit is contained in:
parent
cf0f8bc748
commit
48161ce9ca
@ -91,6 +91,8 @@ const std::array<s32, 16> swp00_device::panmap = {
|
||||
0x300, 0x340, 0x380, 0xfff
|
||||
};
|
||||
|
||||
const std::array<u8, 4> swp00_device::dpcm_offset = { 7, 6, 4, 0 };
|
||||
|
||||
bool swp00_device::istep(s32 &value, s32 limit, s32 step)
|
||||
{
|
||||
// fprintf(stderr, "istep(%x, %x, %x)\n", value, limit, step);
|
||||
@ -314,7 +316,7 @@ void swp00_device::device_start()
|
||||
save_item(NAME(m_pitch));
|
||||
save_item(NAME(m_sample_start));
|
||||
save_item(NAME(m_sample_end));
|
||||
save_item(NAME(m_sample_dec_and_format));
|
||||
save_item(NAME(m_sample_dpcm_and_format));
|
||||
save_item(NAME(m_sample_address));
|
||||
save_item(NAME(m_lfo_step));
|
||||
save_item(NAME(m_lfo_pmod_depth));
|
||||
@ -342,6 +344,7 @@ void swp00_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++) {
|
||||
u32 v = 0;
|
||||
@ -359,7 +362,7 @@ void swp00_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;
|
||||
}
|
||||
@ -449,7 +452,7 @@ void swp00_device::device_reset()
|
||||
std::fill(m_pitch.begin(), m_pitch.end(), 0);
|
||||
std::fill(m_sample_start.begin(), m_sample_start.end(), 0);
|
||||
std::fill(m_sample_end.begin(), m_sample_end.end(), 0);
|
||||
std::fill(m_sample_dec_and_format.begin(), m_sample_dec_and_format.end(), 0);
|
||||
std::fill(m_sample_dpcm_and_format.begin(), m_sample_dpcm_and_format.end(), 0);
|
||||
std::fill(m_sample_address.begin(), m_sample_address.end(), 0);
|
||||
std::fill(m_lfo_step.begin(), m_lfo_step.end(), 0);
|
||||
std::fill(m_lfo_pmod_depth.begin(), m_lfo_pmod_depth.end(), 0);
|
||||
@ -477,6 +480,7 @@ void swp00_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);
|
||||
}
|
||||
|
||||
void swp00_device::rom_bank_pre_change()
|
||||
@ -514,7 +518,7 @@ void swp00_device::map(address_map &map)
|
||||
rchan(map, 0x2d).rw(FUNC(swp00_device::var_level_r), FUNC(swp00_device::var_level_w));
|
||||
rchan(map, 0x2e).rw(FUNC(swp00_device::glo_level_r), FUNC(swp00_device::glo_level_w));
|
||||
rchan(map, 0x2f).rw(FUNC(swp00_device::panning_r), FUNC(swp00_device::panning_w));
|
||||
rchan(map, 0x30).rw(FUNC(swp00_device::sample_dec_and_format_r), FUNC(swp00_device::sample_dec_and_format_w));
|
||||
rchan(map, 0x30).rw(FUNC(swp00_device::sample_dpcm_and_format_r), FUNC(swp00_device::sample_dpcm_and_format_w));
|
||||
rchan(map, 0x31).rw(FUNC(swp00_device::sample_address_r<2>), FUNC(swp00_device::sample_address_w<2>));
|
||||
rchan(map, 0x32).rw(FUNC(swp00_device::sample_address_r<1>), FUNC(swp00_device::sample_address_w<1>));
|
||||
rchan(map, 0x33).rw(FUNC(swp00_device::sample_address_r<0>), FUNC(swp00_device::sample_address_w<0>));
|
||||
@ -832,19 +836,19 @@ template<int sel> u8 swp00_device::sample_end_r(offs_t offset)
|
||||
return m_sample_end[chan] >> (8*sel);
|
||||
}
|
||||
|
||||
void swp00_device::sample_dec_and_format_w(offs_t offset, u8 data)
|
||||
void swp00_device::sample_dpcm_and_format_w(offs_t offset, u8 data)
|
||||
{
|
||||
int chan = offset >> 1;
|
||||
m_stream->update();
|
||||
|
||||
m_sample_dec_and_format[chan] = data;
|
||||
// logerror("sample_dec_and_format[%02x] = %02x\n", chan, m_sample_dec_and_format[chan]);
|
||||
m_sample_dpcm_and_format[chan] = data;
|
||||
// logerror("sample_dpcm_and_format[%02x] = %02x\n", chan, m_sample_dpcm_and_format[chan]);
|
||||
}
|
||||
|
||||
u8 swp00_device::sample_dec_and_format_r(offs_t offset)
|
||||
u8 swp00_device::sample_dpcm_and_format_r(offs_t offset)
|
||||
{
|
||||
int chan = offset >> 1;
|
||||
return m_sample_dec_and_format[chan];
|
||||
return m_sample_dpcm_and_format[chan];
|
||||
}
|
||||
|
||||
template<int sel> void swp00_device::sample_address_w(offs_t offset, u8 data)
|
||||
@ -900,7 +904,7 @@ u8 swp00_device::lfo_pmod_depth_r(offs_t offset)
|
||||
void swp00_device::keyon(int chan)
|
||||
{
|
||||
m_stream->update();
|
||||
logerror("keyon %02x a=%02x/%02x d=%02x/%02x glo=%02x pan=%02x [%x %x %x %x]\n", chan, m_attack_speed[chan], m_attack_level[chan], m_decay_speed[chan], m_decay_level[chan], m_glo_level[chan], m_panning[chan], m_sample_start[chan], m_sample_end[chan], m_sample_address[chan], m_sample_dec_and_format[chan]);
|
||||
logerror("keyon %02x a=%02x/%02x d=%02x/%02x glo=%02x pan=%02x [%x %x %x %x]\n", chan, m_attack_speed[chan], m_attack_level[chan], m_decay_speed[chan], m_decay_level[chan], m_glo_level[chan], m_panning[chan], m_sample_start[chan], m_sample_end[chan], m_sample_address[chan], m_sample_dpcm_and_format[chan]);
|
||||
m_lfo_phase[chan] = 0;
|
||||
m_sample_pos[chan] = -m_sample_start[chan] << 15;
|
||||
|
||||
@ -913,6 +917,7 @@ void swp00_device::keyon(int chan)
|
||||
m_dpcm_current[chan] = 0;
|
||||
m_dpcm_next[chan] = 0;
|
||||
m_dpcm_address[chan] = m_sample_address[chan] - m_sample_start[chan];
|
||||
m_dpcm_sum[chan] = 0;
|
||||
|
||||
m_lpf_value[chan] = m_lpf_target_value[chan];
|
||||
m_lpf_timer[chan] = 0x4000000;
|
||||
@ -1279,7 +1284,7 @@ void swp00_device::sound_stream_update(sound_stream &stream, std::vector<read_st
|
||||
s16 val0, val1;
|
||||
u32 base_address = m_sample_address[chan];
|
||||
s32 spos = m_sample_pos[chan] >> 15;
|
||||
switch(m_sample_dec_and_format[chan] >> 6) {
|
||||
switch(m_sample_dpcm_and_format[chan] >> 6) {
|
||||
case 0: { // 16-bits linear
|
||||
offs_t adr = base_address + (spos << 1);
|
||||
val0 = read_word(adr);
|
||||
@ -1329,10 +1334,13 @@ void swp00_device::sound_stream_update(sound_stream &stream, std::vector<read_st
|
||||
break;
|
||||
|
||||
case 3: { // 8-bits delta-pcm
|
||||
u8 offset = dpcm_offset[m_sample_dpcm_and_format[chan] & 3];
|
||||
u8 scale = (m_sample_dpcm_and_format[chan] >> 2) & 7;
|
||||
u32 target_address = base_address + spos + 1;
|
||||
while(m_dpcm_address[chan] <= target_address) {
|
||||
m_dpcm_current[chan] = m_dpcm_next[chan];
|
||||
s32 sample = m_dpcm_next[chan] + m_dpcm[read_byte(m_dpcm_address[chan])];
|
||||
m_dpcm_sum[chan] += m_dpcm[read_byte(m_dpcm_address[chan])] - offset;
|
||||
s32 sample = (m_dpcm_sum[chan] << scale) >> 3;
|
||||
m_dpcm_address[chan] ++;
|
||||
if(sample < -0x8000)
|
||||
sample = -0x8000;
|
||||
@ -1383,9 +1391,10 @@ void swp00_device::sound_stream_update(sound_stream &stream, std::vector<read_st
|
||||
else {
|
||||
s32 prev = m_sample_pos[chan];
|
||||
do
|
||||
m_sample_pos[chan] -= (m_sample_end[chan] << 15) | ((m_sample_dec_and_format[chan] & 0x3f) << 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -42,6 +42,7 @@ private:
|
||||
static const std::array<s32, 0x80> attack_linear_step;
|
||||
static const std::array<s32, 0x20> decay_linear_step;
|
||||
static const std::array<s32, 16> panmap;
|
||||
static const std::array<u8, 4> dpcm_offset;
|
||||
std::array<s32, 0x80> m_global_step;
|
||||
std::array<s16, 0x100> m_dpcm;
|
||||
|
||||
@ -76,7 +77,7 @@ private:
|
||||
std::array<u16, 0x20> m_pitch;
|
||||
std::array<u16, 0x20> m_sample_start;
|
||||
std::array<u16, 0x20> m_sample_end;
|
||||
std::array<u8, 0x20> m_sample_dec_and_format;
|
||||
std::array<u8, 0x20> m_sample_dpcm_and_format;
|
||||
std::array<u32, 0x20> m_sample_address;
|
||||
std::array<u8, 0x20> m_lfo_step;
|
||||
std::array<u8, 0x20> m_lfo_pmod_depth;
|
||||
@ -97,6 +98,7 @@ private:
|
||||
std::array<s16, 0x20> m_dpcm_current;
|
||||
std::array<s16, 0x20> m_dpcm_next;
|
||||
std::array<u32, 0x20> m_dpcm_address;
|
||||
std::array<s32, 0x20> m_dpcm_sum;
|
||||
|
||||
u16 m_waverom_val;
|
||||
u8 m_waverom_access;
|
||||
@ -167,8 +169,8 @@ private:
|
||||
template<int sel> u8 sample_start_r(offs_t offset);
|
||||
template<int sel> void sample_end_w(offs_t offset, u8 data);
|
||||
template<int sel> u8 sample_end_r(offs_t offset);
|
||||
void sample_dec_and_format_w(offs_t offset, u8 data);
|
||||
u8 sample_dec_and_format_r(offs_t offset);
|
||||
void sample_dpcm_and_format_w(offs_t offset, u8 data);
|
||||
u8 sample_dpcm_and_format_r(offs_t offset);
|
||||
template<int sel> void sample_address_w(offs_t offset, u8 data);
|
||||
template<int sel> u8 sample_address_r(offs_t offset);
|
||||
void lfo_step_w(offs_t offset, u8 data);
|
||||
|
Loading…
Reference in New Issue
Block a user