From 21cf4d3cd4fee5c83b52ea50afaf4f178edd301a Mon Sep 17 00:00:00 2001 From: Tony Konzel Date: Thu, 9 Jun 2022 07:05:08 -0500 Subject: [PATCH] sound/k054539.cpp: Fixed DPCM table, and added cubic interpolation. (#9778) Using powers of 2 rather than squares for the DPCM table fixes DC offsets for 4-bit sample playback. --- src/devices/sound/k054539.cpp | 59 ++++++++++++++++++++++++++++++----- src/devices/sound/k054539.h | 4 +++ 2 files changed, 56 insertions(+), 7 deletions(-) diff --git a/src/devices/sound/k054539.cpp b/src/devices/sound/k054539.cpp index ae0ac92e310..639303cefac 100644 --- a/src/devices/sound/k054539.cpp +++ b/src/devices/sound/k054539.cpp @@ -104,13 +104,34 @@ void k054539_device::keyoff(int channel) regs[0x22c] &= ~(1 << channel); } +void k054539_device::advance_filter(int channel, int val) +{ + auto &hist = filter_hist[channel]; + hist[0] = hist[1]; + hist[1] = hist[2]; + hist[2] = hist[3]; + hist[3] = ((float) val) / 32768.0f; +} + +float k054539_device::calculate_filter(int channel, float t) +{ + // Cubic hermite interpolation + // t is domain [0,1] + + auto &hist = filter_hist[channel]; + const float a = (-hist[0] / 2.0f) + (3.0f * hist[1] / 2.0f) - (3.0f * hist[2] / 2.0f) + (hist[3] / 2.0f); + const float b = hist[0] - (5.0f * hist[1] / 2.0f) + (2.0f * hist[2]) - (hist[3] / 2.0f); + const float c = (-hist[0] / 2.0f) + (hist[2] / 2.0f); + return (t * t * t * a) + (t * t * b) + (t * c) + hist[1]; +} + void k054539_device::sound_stream_update(sound_stream &stream, std::vector const &inputs, std::vector &outputs) { #define VOL_CAP 1.80 static const int16_t dpcm[16] = { - 0 * 0x100, 1 * 0x100, 4 * 0x100, 9 * 0x100, 16 * 0x100, 25 * 0x100, 36 * 0x100, 49 * 0x100, - -64 * 0x100, -49 * 0x100, -36 * 0x100, -25 * 0x100, -16 * 0x100, -9 * 0x100, -4 * 0x100, -1 * 0x100 + 0 * 0x100, 1 * 0x100, 2 * 0x100, 4 * 0x100, 8 * 0x100, 16 * 0x100, 32 * 0x100, 64 * 0x100, + 0 * 0x100, -64 * 0x100, -32 * 0x100, -16 * 0x100, -8 * 0x100, -4 * 0x100, -2 * 0x100, -1 * 0x100 }; @@ -195,6 +216,8 @@ void k054539_device::sound_stream_update(sound_stream &stream, std::vectorpval; } + float filter_frac = 0; + switch(base2[0] & 0xc) { case 0x0: { // 8bit pcm cur_pfrac += delta; @@ -208,12 +231,17 @@ void k054539_device::sound_stream_update(sound_stream &stream, std::vector 32767) cur_val = 32767; + + advance_filter(ch, cur_val); } + filter_frac = (float)(cur_pfrac & 0xffff) / 65536.0f; + cur_pfrac >>= 1; if(cur_pos & 1) cur_pfrac |= 0x8000; @@ -285,9 +322,12 @@ void k054539_device::sound_stream_update(sound_stream &stream, std::vectorpos = cur_pos; chan->pfrac = cur_pfrac; @@ -299,10 +339,13 @@ void k054539_device::sound_stream_update(sound_stream &stream, std::vector> 8 & 0xff; base1[0x0e] = cur_pos>>16 & 0xff; } + } else { + // Fill the interpolation vectors with silence when channel is disabled + advance_filter(ch, 0); } reverb_pos = (reverb_pos + 1) & 0x1fff; - outputs[0].put_int(sample, lval, 32768); - outputs[1].put_int(sample, rval, 32768); + outputs[0].put(sample, lval); + outputs[1].put(sample, rval); } } @@ -317,6 +360,7 @@ void k054539_device::init_chip() { memset(regs, 0, sizeof(regs)); memset(posreg_latch, 0, sizeof(posreg_latch)); //* + memset(filter_hist, 0, sizeof(filter_hist)); flags |= UPDATE_AT_KEYON; //* make it default until proven otherwise ram = std::make_unique(0x4000); @@ -339,6 +383,7 @@ void k054539_device::init_chip() save_item(NAME(cur_ptr)); save_item(NAME(cur_limit)); save_item(NAME(rom_addr)); + save_item(NAME(filter_hist)); save_item(NAME(m_timer_state)); } diff --git a/src/devices/sound/k054539.h b/src/devices/sound/k054539.h index 406836af65a..8581957318e 100644 --- a/src/devices/sound/k054539.h +++ b/src/devices/sound/k054539.h @@ -88,6 +88,8 @@ private: uint8_t posreg_latch[8][3]; int flags; + float filter_hist[8][4]; + unsigned char regs[0x230]; std::unique_ptr ram; int reverb_pos; @@ -108,6 +110,8 @@ private: void keyon(int channel); void keyoff(int channel); void init_chip(); + void advance_filter(int channel, int val); + float calculate_filter(int channel, float t); }; DECLARE_DEVICE_TYPE(K054539, k054539_device)