From 9965636214771ff5e4c15c1e70e4b6baf068d263 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sun, 20 Nov 2022 13:30:31 +0600 Subject: [PATCH] OPTiMC: Fix OPL volume mixing Windows driver operates the chip in WSS mode so AUX2 volume filtering for OPL playback is required --- src/include/86box/snd_ad1848.h | 1 + src/include/86box/snd_sb.h | 3 +++ src/sound/snd_ad1848.c | 18 ++++++++++++++++++ src/sound/snd_optimc.c | 13 +++++++++++++ src/sound/snd_sb.c | 3 +++ 5 files changed, 38 insertions(+) diff --git a/src/include/86box/snd_ad1848.h b/src/include/86box/snd_ad1848.h index f9f73a60c..bdf5022e5 100644 --- a/src/include/86box/snd_ad1848.h +++ b/src/include/86box/snd_ad1848.h @@ -66,6 +66,7 @@ extern void ad1848_write(uint16_t addr, uint8_t val, void *priv); extern void ad1848_update(ad1848_t *ad1848); extern void ad1848_speed_changed(ad1848_t *ad1848); extern void ad1848_filter_cd_audio(int channel, double *buffer, void *priv); +extern void ad1848_filter_aux2(void* priv, double* out_l, double* out_r); extern void ad1848_init(ad1848_t *ad1848, uint8_t type); diff --git a/src/include/86box/snd_sb.h b/src/include/86box/snd_sb.h index 782a947f6..577335976 100644 --- a/src/include/86box/snd_sb.h +++ b/src/include/86box/snd_sb.h @@ -147,6 +147,9 @@ typedef struct sb_t { pnp_rom[512]; uint16_t opl_pnp_addr; + + void *opl_mixer; + void (*opl_mix)(void*, double*, double*); } sb_t; extern void sb_ct1345_mixer_write(uint16_t addr, uint8_t val, void *p); diff --git a/src/sound/snd_ad1848.c b/src/sound/snd_ad1848.c index bf3858aa3..5be928075 100644 --- a/src/sound/snd_ad1848.c +++ b/src/sound/snd_ad1848.c @@ -599,6 +599,24 @@ ad1848_filter_cd_audio(int channel, double *buffer, void *priv) *buffer = c; } +void +ad1848_filter_aux2(void* priv, double* out_l, double* out_r) +{ + ad1848_t *ad1848 = (ad1848_t *) priv; + + if (ad1848->regs[4] & 0x80) { + *out_l = 0.0; + } else { + *out_l = ((*out_l) * ad1848_vols_5bits_aux_gain[ad1848->regs[4] & 0x1f]) / 65536.0; + } + + if (ad1848->regs[5] & 0x80) { + *out_r = 0.0; + } else { + *out_r = ((*out_r) * ad1848_vols_5bits_aux_gain[ad1848->regs[5] & 0x1f]) / 65536.0; + } +} + void ad1848_init(ad1848_t *ad1848, uint8_t type) { diff --git a/src/sound/snd_optimc.c b/src/sound/snd_optimc.c index 3280a47ef..b377eac70 100644 --- a/src/sound/snd_optimc.c +++ b/src/sound/snd_optimc.c @@ -70,6 +70,16 @@ typedef struct optimc_t { uint8_t regs[6]; } optimc_t, opti_82c929_t; +static void +optimc_filter_opl(void* priv, double* out_l, double* out_r) +{ + optimc_t *optimc = (optimc_t *) priv; + + if (optimc->cur_wss_enabled) { + ad1848_filter_aux2((void*)&optimc->ad1848, out_l, out_r); + } +} + static uint8_t optimc_wss_read(uint16_t addr, void *priv) { @@ -372,6 +382,9 @@ optimc_init(const device_t *info) sb_dsp_setdma8(&optimc->sb->dsp, optimc->cur_dma); sb_ct1345_mixer_reset(optimc->sb); + optimc->sb->opl_mixer = optimc; + optimc->sb->opl_mix = optimc_filter_opl; + optimc->fm_type = (info->local & OPTIMC_OPL4) ? FM_YMF278B : FM_YMF262; fm_driver_get(optimc->fm_type, &optimc->sb->opl); io_sethandler(optimc->cur_addr + 0, 0x0004, optimc->sb->opl.read, NULL, NULL, optimc->sb->opl.write, NULL, NULL, optimc->sb->opl.priv); diff --git a/src/sound/snd_sb.c b/src/sound/snd_sb.c index 1c3b97756..7660ace90 100644 --- a/src/sound/snd_sb.c +++ b/src/sound/snd_sb.c @@ -290,6 +290,9 @@ sb_get_buffer_sbpro(int32_t *buffer, int len, void *p) } else { out_l = (((double) opl_buf[c]) * mixer->fm_l) * 0.7171630859375; out_r = (((double) opl_buf[c + 1]) * mixer->fm_r) * 0.7171630859375; + if (sb->opl_mix && sb->opl_mixer) { + sb->opl_mix(sb->opl_mixer, &out_l, &out_r); + } } }