From c5efcd663d2519a4fcce204ddd2b83f5843dc277 Mon Sep 17 00:00:00 2001 From: eadmaster <51NMBsFda0ab1> Date: Mon, 30 Nov 2020 22:45:29 +0100 Subject: [PATCH] Added per-sound channel individual volume core options (#223) fixed PSG Noise channel volume scaling reworked PSG volume scaling formula, cleanups (#223) reworked MD volume scaling formula added preproc tests for libretro (#223) added first implementation of SMS FM (YM2413) channel volume scaling (#223) added core option Show Advanced Audio Volume Settings use USE_PER_SOUND_CHANNELS_CONFIG CFLAG for the new core options changed volumes array types to avoid casting (#223) minor fixes --- Makefile.libretro | 3 +- core/sound/psg.c | 21 +- core/sound/ym2413.c | 68 +++++-- core/sound/ym2612.c | 10 + libretro/libretro.c | 111 +++++++++-- libretro/libretro_core_options.h | 319 ++++++++++++++++++++++++++++++- libretro/osd.h | 3 + 7 files changed, 482 insertions(+), 53 deletions(-) diff --git a/Makefile.libretro b/Makefile.libretro index 8cd57a8c7..c8a886b40 100644 --- a/Makefile.libretro +++ b/Makefile.libretro @@ -696,7 +696,8 @@ LIBRETRO_CFLAGS += $(BPP_DEFINES) \ -DM68K_OVERCLOCK_SHIFT=20 \ -DZ80_OVERCLOCK_SHIFT=20 \ -DHAVE_YM3438_CORE \ - -DHAVE_OPLL_CORE + -DHAVE_OPLL_CORE \ + -DUSE_PER_SOUND_CHANNELS_CONFIG ifneq (,$(findstring msvc,$(platform))) LIBRETRO_CFLAGS += -DINLINE="static _inline" diff --git a/core/sound/psg.c b/core/sound/psg.c index a0e35bf08..6a04d2925 100644 --- a/core/sound/psg.c +++ b/core/sound/psg.c @@ -91,7 +91,6 @@ static struct int chanDelta[4][2]; int chanOut[4][2]; int chanAmp[4][2]; - int chanUserVolume[4]; } psg; static void psg_update(unsigned int clocks); @@ -379,14 +378,6 @@ void psg_write(unsigned int clocks, unsigned int data) psg.regs[index] = data; } -void psg_set_user_channel_volume(unsigned int channel, unsigned int volume) -{ - if(channel > 3 || volume > 100) return; // invalid args - // else - - psg.chanUserVolume[channel] = volume; -} - void psg_config(unsigned int clocks, unsigned int preamp, unsigned int panning) { int i; @@ -405,10 +396,16 @@ void psg_config(unsigned int clocks, unsigned int preamp, unsigned int panning) { /* channel internal volume */ int volume = psg.regs[i*2+1]; - + /* update channel stereo amplification */ - psg.chanAmp[i][0] = preamp * (psg.chanUserVolume[i]/100) * ((panning >> (i + 4)) & 1); - psg.chanAmp[i][1] = preamp * (psg.chanUserVolume[i]/100) * ((panning >> (i + 0)) & 1); + #ifndef USE_PER_SOUND_CHANNELS_CONFIG + psg.chanAmp[i][0] = preamp * ((panning >> (i + 4)) & 1); + psg.chanAmp[i][1] = preamp * ((panning >> (i + 0)) & 1); + #else + /* also apply user-set volume scaling */ + psg.chanAmp[i][0] = ((preamp * config.psg_ch_volumes[i]) / 100) * ((panning >> (i + 4)) & 1); + psg.chanAmp[i][1] = ((preamp * config.psg_ch_volumes[i]) / 100) * ((panning >> (i + 0)) & 1); + #endif /* tone channels */ if (i < 3) diff --git a/core/sound/ym2413.c b/core/sound/ym2413.c index ad453fa0e..0ef4074cc 100644 --- a/core/sound/ym2413.c +++ b/core/sound/ym2413.c @@ -769,7 +769,7 @@ INLINE signed int op_calc1(UINT32 phase, unsigned int env, signed int pm, unsign #define volume_calc(OP) ((OP)->TLL + ((UINT32)(OP)->volume) + (LFO_AM & (OP)->AMmask)) /* calculate output */ -INLINE void chan_calc( YM2413_OPLL_CH *CH ) +INLINE void chan_calc( YM2413_OPLL_CH *CH, unsigned int chan ) { YM2413_OPLL_SLOT *SLOT; unsigned int env; @@ -799,7 +799,13 @@ INLINE void chan_calc( YM2413_OPLL_CH *CH ) env = volume_calc(SLOT); if( env < ENV_QUIET ) { - output[0] += op_calc(SLOT->phase, env, phase_modulation, SLOT->wavetable); + output[0] += op_calc(SLOT->phase, env, phase_modulation, SLOT->wavetable) +#ifndef USE_PER_SOUND_CHANNELS_CONFIG + ; +#else + /* apply user-set volume scaling */ + * config.sms_fm_ch_volumes[chan]/100; +#endif } } @@ -877,7 +883,13 @@ INLINE void rhythm_calc( YM2413_OPLL_CH *CH, unsigned int noise ) SLOT++; env = volume_calc(SLOT); if( env < ENV_QUIET ) - output[1] += op_calc(SLOT->phase, env, phase_modulation, SLOT->wavetable); + output[1] += op_calc(SLOT->phase, env, phase_modulation, SLOT->wavetable) +#ifndef USE_PER_SOUND_CHANNELS_CONFIG + ; +#else + /* apply user-set volume scaling */ + * config.sms_fm_ch_volumes[6]/100; +#endif /* Phase generation is based on: */ @@ -945,7 +957,13 @@ INLINE void rhythm_calc( YM2413_OPLL_CH *CH, unsigned int noise ) phase = 0xd0>>2; } - output[1] += op_calc(phase< 8191) out_fm[5] = 8191; else if (out_fm[5] < -8192) out_fm[5] = -8192; + + #ifdef USE_PER_SOUND_CHANNELS_CONFIG + /* apply user volume scaling */ + if (config.md_ch_volumes[0] < 100) out_fm[0] = (out_fm[0] * config.md_ch_volumes[0]) / 100; + if (config.md_ch_volumes[1] < 100) out_fm[1] = (out_fm[1] * config.md_ch_volumes[1]) / 100; + if (config.md_ch_volumes[2] < 100) out_fm[2] = (out_fm[2] * config.md_ch_volumes[2]) / 100; + if (config.md_ch_volumes[3] < 100) out_fm[3] = (out_fm[3] * config.md_ch_volumes[3]) / 100; + if (config.md_ch_volumes[4] < 100) out_fm[4] = (out_fm[4] * config.md_ch_volumes[4]) / 100; + if (config.md_ch_volumes[5] < 100) out_fm[5] = (out_fm[5] * config.md_ch_volumes[5]) / 100; + #endif /* stereo DAC output panning & mixing */ lt = ((out_fm[0]) & ym2612.OPN.pan[0]); diff --git a/libretro/libretro.c b/libretro/libretro.c index a3729acb3..d9b56d520 100644 --- a/libretro/libretro.c +++ b/libretro/libretro.c @@ -211,6 +211,8 @@ static bool retro_audio_buff_underrun = false; static unsigned audio_latency = 0; static bool update_audio_latency = false; +static bool show_advanced_av_settings = true; + static void retro_audio_buff_status_cb( bool active, unsigned occupancy, bool underrun_likely) { @@ -938,6 +940,9 @@ static void config_default(void) config.ym2612 = YM2612_DISCRETE; config.ym2413 = 2; /* AUTO */ config.mono = 0; /* STEREO output */ + for (i = 0; i < 4; i++) config.psg_ch_volumes[i] = 100; /* individual channel volumes */ + for (i = 0; i < 6; i++) config.md_ch_volumes[i] = 100; /* individual channel volumes */ + for (i = 0; i < 9; i++) config.sms_fm_ch_volumes[i] = 100; /* individual channel volumes */ #ifdef HAVE_YM3438_CORE config.ym3438 = 0; #endif @@ -1540,26 +1545,6 @@ static void check_variables(bool first_run) } } - char sound_channel_volume_base_str[] = "genesis_plus_gx_psg_channel_0_volume"; - var.key = sound_channel_volume_base_str; - for (unsigned c = 0; c < 4; c++) { - sound_channel_volume_base_str[28] = c+'0'; - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var)) - { - psg_set_user_channel_volume(c, atoi(var.value)); - // need to recall config to have the settings applied - if ((system_hw & SYSTEM_PBC) == SYSTEM_MD) - { - psg_config(0, config.psg_preamp, 0xff); - } - else - { - psg_config(0, config.psg_preamp, io_reg[6]); - } - } - } - - var.key = "genesis_plus_gx_fm_preamp"; environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var); { @@ -1835,6 +1820,92 @@ static void check_variables(bool first_run) config.no_sprite_limit = 1; } + char psg_channel_volume_base_str[] = "genesis_plus_gx_psg_channel_0_volume"; + var.key = psg_channel_volume_base_str; + for (unsigned c = 0; c < 4; c++) { + psg_channel_volume_base_str[28] = c+'0'; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var)) + { + config.psg_ch_volumes[c] = atoi(var.value); + // need to recall config to have the settings applied + if ((system_hw & SYSTEM_PBC) == SYSTEM_MD) + { + psg_config(0, config.psg_preamp, 0xff); + } + else + { + psg_config(0, config.psg_preamp, io_reg[6]); + } + } + } + + char md_fm_channel_volume_base_str[] = "genesis_plus_gx_md_channel_0_volume"; + var.key = md_fm_channel_volume_base_str; + for (unsigned c = 0; c < 6; c++) { + md_fm_channel_volume_base_str[27] = c+'0'; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var)) + { + config.md_ch_volumes[c] = atoi(var.value); + } + } + + char sms_fm_channel_volume_base_str[] = "genesis_plus_gx_sms_fm_channel_0_volume"; + var.key = sms_fm_channel_volume_base_str; + for (unsigned c = 0; c < 9; c++) { + sms_fm_channel_volume_base_str[31] = c+'0'; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var)) + { + config.sms_fm_ch_volumes[c] = atoi(var.value); + } + } + + var.key = "genesis_plus_gx_show_advanced_audio_settings"; + var.value = NULL; + + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + bool show_advanced_av_settings_prev = show_advanced_av_settings; + + show_advanced_av_settings = true; + if (strcmp(var.value, "disabled") == 0) + show_advanced_av_settings = false; + + if (show_advanced_av_settings != show_advanced_av_settings_prev) + { + size_t i; + struct retro_core_option_display option_display; + char av_keys[19][40] = { + "genesis_plus_gx_psg_channel_0_volume", + "genesis_plus_gx_psg_channel_1_volume", + "genesis_plus_gx_psg_channel_2_volume", + "genesis_plus_gx_psg_channel_3_volume", + "genesis_plus_gx_md_channel_0_volume", + "genesis_plus_gx_md_channel_1_volume", + "genesis_plus_gx_md_channel_2_volume", + "genesis_plus_gx_md_channel_3_volume", + "genesis_plus_gx_md_channel_4_volume", + "genesis_plus_gx_md_channel_5_volume", + "genesis_plus_gx_sms_fm_channel_0_volume", + "genesis_plus_gx_sms_fm_channel_1_volume", + "genesis_plus_gx_sms_fm_channel_2_volume", + "genesis_plus_gx_sms_fm_channel_3_volume", + "genesis_plus_gx_sms_fm_channel_4_volume", + "genesis_plus_gx_sms_fm_channel_5_volume", + "genesis_plus_gx_sms_fm_channel_6_volume", + "genesis_plus_gx_sms_fm_channel_7_volume", + "genesis_plus_gx_sms_fm_channel_8_volume" + }; + + option_display.visible = show_advanced_av_settings; + + for (i = 0; i < 19; i++) + { + option_display.key = av_keys[i]; + environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY, &option_display); + } + } + } + if (reinit) { #ifdef HAVE_OVERCLOCK diff --git a/libretro/libretro_core_options.h b/libretro/libretro_core_options.h index d33988be3..1d77711cf 100644 --- a/libretro/libretro_core_options.h +++ b/libretro/libretro_core_options.h @@ -588,10 +588,21 @@ struct retro_core_option_definition option_defs_us[] = { }, "disabled" }, + { + "genesis_plus_gx_show_advanced_audio_settings", + "Show Advanced Audio Volume Settings (Reopen menu)", + "Enable configuration of low-level audio channel parameters. NOTE: Quick Menu must be toggled for this setting to take effect.", + { + { "enabled", NULL }, + { "disabled", NULL }, + { NULL, NULL}, + }, + "disabled" + }, { "genesis_plus_gx_psg_channel_0_volume", "PSG Tone Channel 0 Volume %", - "", + "Reduce the volume of the PSG Tone Channel 0.", { { "0", NULL }, { "10", NULL }, @@ -611,7 +622,7 @@ struct retro_core_option_definition option_defs_us[] = { { "genesis_plus_gx_psg_channel_1_volume", "PSG Tone Channel 1 Volume %", - "", + "Reduce the volume of the PSG Tone Channel 1.", { { "0", NULL }, { "10", NULL }, @@ -631,7 +642,7 @@ struct retro_core_option_definition option_defs_us[] = { { "genesis_plus_gx_psg_channel_2_volume", "PSG Tone Channel 2 Volume %", - "", + "Reduce the volume of the PSG Tone Channel 2.", { { "0", NULL }, { "10", NULL }, @@ -651,7 +662,307 @@ struct retro_core_option_definition option_defs_us[] = { { "genesis_plus_gx_psg_channel_3_volume", "PSG Noise Channel 3 Volume %", - "", + "Reduce the volume of the PSG Noise Channel 3.", + { + { "0", NULL }, + { "10", NULL }, + { "20", NULL }, + { "30", NULL }, + { "40", NULL }, + { "50", NULL }, + { "60", NULL }, + { "70", NULL }, + { "80", NULL }, + { "90", NULL }, + { "100", NULL }, + { NULL, NULL }, + }, + "100" + }, + { + "genesis_plus_gx_md_channel_0_volume", + "Mega Drive / Genesis FM Channel 0 Volume %", + "Reduce the volume of the Mega Drive / Genesis FM Channel 0. Only works with MAME FM emulators.", + { + { "0", NULL }, + { "10", NULL }, + { "20", NULL }, + { "30", NULL }, + { "40", NULL }, + { "50", NULL }, + { "60", NULL }, + { "70", NULL }, + { "80", NULL }, + { "90", NULL }, + { "100", NULL }, + { NULL, NULL }, + }, + "100" + }, + { + "genesis_plus_gx_md_channel_1_volume", + "Mega Drive / Genesis FM Channel 1 Volume %", + "Reduce the volume of the Mega Drive / Genesis FM Channel 1. Only works with MAME FM emulators.", + { + { "0", NULL }, + { "10", NULL }, + { "20", NULL }, + { "30", NULL }, + { "40", NULL }, + { "50", NULL }, + { "60", NULL }, + { "70", NULL }, + { "80", NULL }, + { "90", NULL }, + { "100", NULL }, + { NULL, NULL }, + }, + "100" + }, + { + "genesis_plus_gx_md_channel_2_volume", + "Mega Drive / Genesis FM Channel 2 Volume %", + "Reduce the volume of the Mega Drive / Genesis FM Channel 2. Only works with MAME FM emulators.", + { + { "0", NULL }, + { "10", NULL }, + { "20", NULL }, + { "30", NULL }, + { "40", NULL }, + { "50", NULL }, + { "60", NULL }, + { "70", NULL }, + { "80", NULL }, + { "90", NULL }, + { "100", NULL }, + { NULL, NULL }, + }, + "100" + }, + { + "genesis_plus_gx_md_channel_3_volume", + "Mega Drive / Genesis FM Channel 3 Volume %", + "Reduce the volume of the Mega Drive / Genesis FM Channel 3. Only works with MAME FM emulators.", + { + { "0", NULL }, + { "10", NULL }, + { "20", NULL }, + { "30", NULL }, + { "40", NULL }, + { "50", NULL }, + { "60", NULL }, + { "70", NULL }, + { "80", NULL }, + { "90", NULL }, + { "100", NULL }, + { NULL, NULL }, + }, + "100" + }, + { + "genesis_plus_gx_md_channel_4_volume", + "Mega Drive / Genesis FM Channel 4 Volume %", + "Reduce the volume of the Mega Drive / Genesis FM Channel 4. Only works with MAME FM emulators.", + { + { "0", NULL }, + { "10", NULL }, + { "20", NULL }, + { "30", NULL }, + { "40", NULL }, + { "50", NULL }, + { "60", NULL }, + { "70", NULL }, + { "80", NULL }, + { "90", NULL }, + { "100", NULL }, + { NULL, NULL }, + }, + "100" + }, + { + "genesis_plus_gx_md_channel_5_volume", + "Mega Drive / Genesis FM Channel 5 Volume %", + "Reduce the volume of the Mega Drive / Genesis FM Channel 5. Only works with MAME FM emulators.", + { + { "0", NULL }, + { "10", NULL }, + { "20", NULL }, + { "30", NULL }, + { "40", NULL }, + { "50", NULL }, + { "60", NULL }, + { "70", NULL }, + { "80", NULL }, + { "90", NULL }, + { "100", NULL }, + { NULL, NULL }, + }, + "100" + }, + { + "genesis_plus_gx_sms_fm_channel_0_volume", + "Master System FM (YM2413) Channel 0 Volume %", + "Reduce the volume of the Master System FM Channel 0.", + { + { "0", NULL }, + { "10", NULL }, + { "20", NULL }, + { "30", NULL }, + { "40", NULL }, + { "50", NULL }, + { "60", NULL }, + { "70", NULL }, + { "80", NULL }, + { "90", NULL }, + { "100", NULL }, + { NULL, NULL }, + }, + "100" + }, + { + "genesis_plus_gx_sms_fm_channel_1_volume", + "Master System FM (YM2413) Channel 1 Volume %", + "Reduce the volume of the Master System FM Channel 1.", + { + { "0", NULL }, + { "10", NULL }, + { "20", NULL }, + { "30", NULL }, + { "40", NULL }, + { "50", NULL }, + { "60", NULL }, + { "70", NULL }, + { "80", NULL }, + { "90", NULL }, + { "100", NULL }, + { NULL, NULL }, + }, + "100" + }, + { + "genesis_plus_gx_sms_fm_channel_2_volume", + "Master System FM (YM2413) Channel 2 Volume %", + "Reduce the volume of the Master System FM Channel 2.", + { + { "0", NULL }, + { "10", NULL }, + { "20", NULL }, + { "30", NULL }, + { "40", NULL }, + { "50", NULL }, + { "60", NULL }, + { "70", NULL }, + { "80", NULL }, + { "90", NULL }, + { "100", NULL }, + { NULL, NULL }, + }, + "100" + }, + { + "genesis_plus_gx_sms_fm_channel_3_volume", + "Master System FM (YM2413) Channel 3 Volume %", + "Reduce the volume of the Master System FM Channel 3.", + { + { "0", NULL }, + { "10", NULL }, + { "20", NULL }, + { "30", NULL }, + { "40", NULL }, + { "50", NULL }, + { "60", NULL }, + { "70", NULL }, + { "80", NULL }, + { "90", NULL }, + { "100", NULL }, + { NULL, NULL }, + }, + "100" + }, + { + "genesis_plus_gx_sms_fm_channel_4_volume", + "Master System FM (YM2413) Channel 4 Volume %", + "Reduce the volume of the Master System FM Channel 4.", + { + { "0", NULL }, + { "10", NULL }, + { "20", NULL }, + { "30", NULL }, + { "40", NULL }, + { "50", NULL }, + { "60", NULL }, + { "70", NULL }, + { "80", NULL }, + { "90", NULL }, + { "100", NULL }, + { NULL, NULL }, + }, + "100" + }, + { + "genesis_plus_gx_sms_fm_channel_5_volume", + "Master System FM (YM2413) Channel 5 Volume %", + "Reduce the volume of the Master System FM Channel 5.", + { + { "0", NULL }, + { "10", NULL }, + { "20", NULL }, + { "30", NULL }, + { "40", NULL }, + { "50", NULL }, + { "60", NULL }, + { "70", NULL }, + { "80", NULL }, + { "90", NULL }, + { "100", NULL }, + { NULL, NULL }, + }, + "100" + }, + { + "genesis_plus_gx_sms_fm_channel_6_volume", + "Master System FM (YM2413) Channel 6 Volume %", + "Reduce the volume of the Master System FM Channel 6.", + { + { "0", NULL }, + { "10", NULL }, + { "20", NULL }, + { "30", NULL }, + { "40", NULL }, + { "50", NULL }, + { "60", NULL }, + { "70", NULL }, + { "80", NULL }, + { "90", NULL }, + { "100", NULL }, + { NULL, NULL }, + }, + "100" + }, + { + "genesis_plus_gx_sms_fm_channel_7_volume", + "Master System FM (YM2413) Channel 7 Volume %", + "Reduce the volume of the Master System FM Channel 7.", + { + { "0", NULL }, + { "10", NULL }, + { "20", NULL }, + { "30", NULL }, + { "40", NULL }, + { "50", NULL }, + { "60", NULL }, + { "70", NULL }, + { "80", NULL }, + { "90", NULL }, + { "100", NULL }, + { NULL, NULL }, + }, + "100" + }, + { + "genesis_plus_gx_sms_fm_channel_8_volume", + "Master System FM (YM2413) Channel 8 Volume %", + "Reduce the volume of the Master System FM Channel 8.", { { "0", NULL }, { "10", NULL }, diff --git a/libretro/osd.h b/libretro/osd.h index 1ba4f612e..adde19dfa 100644 --- a/libretro/osd.h +++ b/libretro/osd.h @@ -129,6 +129,9 @@ typedef struct uint8 gun_cursor; uint32 overclock; uint8 no_sprite_limit; + unsigned int psg_ch_volumes[4]; + int32 md_ch_volumes[6]; + signed int sms_fm_ch_volumes[9]; } t_config; extern t_config config;