From: kub Date: Fri, 19 Nov 2021 20:01:50 +0000 (+0100) Subject: sound, fix ym2612 ladder effect, add option X-Git-Tag: v2.00~407 X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=23cd73bc8fd4bcbac3c56b7b047a7e664b1f7a1b;p=picodrive.git sound, fix ym2612 ladder effect, add option --- diff --git a/pico/pico.h b/pico/pico.h index f474d56f..51021070 100644 --- a/pico/pico.h +++ b/pico/pico.h @@ -75,7 +75,7 @@ extern void *p32x_bios_g, *p32x_bios_m, *p32x_bios_s; #define POPT_EN_PWM (1<<21) #define POPT_PWM_IRQ_OPT (1<<22) #define POPT_DIS_FM_SSGEG (1<<23) -#define POPT_EN_FM_LADDER (1<<24) //x00 0000 +#define POPT_EN_FM_DAC (1<<24) //x00 0000 #define PAHW_MCD (1<<0) #define PAHW_32X (1<<1) diff --git a/pico/sound/sound.c b/pico/sound/sound.c index ac79a84a..083c642d 100644 --- a/pico/sound/sound.c +++ b/pico/sound/sound.c @@ -69,7 +69,7 @@ void PsndRerate(int preserve_state) } YM2612Init(Pico.m.pal ? OSC_PAL/7 : OSC_NTSC/7, PicoIn.sndRate, ((PicoIn.opt&POPT_DIS_FM_SSGEG) ? 0 : ST_SSG) | - ((PicoIn.opt&POPT_EN_FM_LADDER) ? ST_LADDER : 0)); + ((PicoIn.opt&POPT_EN_FM_DAC) ? ST_DAC : 0)); if (preserve_state) { // feed it back it's own registers, just like after loading state memcpy(YM2612GetRegs(), state, 0x204); diff --git a/pico/sound/ym2612.c b/pico/sound/ym2612.c index 502326e1..a10e6789 100644 --- a/pico/sound/ym2612.c +++ b/pico/sound/ym2612.c @@ -922,7 +922,8 @@ typedef struct static int clip(int n) { unsigned b = 14, s = n < 0; - if (s + (n>>(b-1))) n = (int)(s + INT_MAX) >> (8*sizeof(int)-b); + int m = s + INT_MAX; + if (s + (n>>(b-1))) n = m >> (8*sizeof(int)-b); return n; } @@ -1234,7 +1235,11 @@ static void chan_render_loop(chan_rend_context *ct, int *buffer, int length) /* mix sample to output buffer */ if (smp) { - smp = clip(smp); /* saturate to 14 bit */ + smp = clip(smp); /* saturate to 14 bit */ + if (ct->algo & 0x80) { + smp &= ~0x1f; /* drop bits (DAC has 9 bits) */ + smp -= (smp < 0 ? 7:0) << 5; /* discontinuity */ + } if (ct->pack & 1) { /* stereo */ if (ct->pack & 0x20) /* L */ /* TODO: check correctness */ buffer[scounter*2] += smp; @@ -1271,15 +1276,6 @@ static void chan_render_finish(int *buffer, unsigned short length, int active_ch ym2612.OPN.eg_timer = crct.eg_timer; g_lfo_ampm = crct.pack >> 16; // need_save ym2612.OPN.lfo_cnt = crct.lfo_cnt; - - /* apply ladder effect. NB only works if buffer was empty beforehand! */ - if (active_chans && (ym2612.OPN.ST.flags & ST_LADDER)) { - length <<= crct.pack & 1; - while (length--) { - *buffer -= (*buffer < 0)*4 << 5; - buffer++; - } - } } static UINT32 update_lfo_phase(FM_SLOT *SLOT, UINT32 block_fnum) @@ -1339,6 +1335,8 @@ static int chan_render(int *buffer, int length, int c, UINT32 flags) // flags: s crct.op1_out = crct.CH->op1_out; crct.algo = crct.CH->ALGO & 7; + if (ym2612.OPN.ST.flags & ST_DAC) + crct.algo |= 0x80; if(crct.CH->pms && (ym2612.OPN.ST.mode & 0xC0) && c == 2) { /* 3 slot mode */ diff --git a/pico/sound/ym2612.h b/pico/sound/ym2612.h index 9b7fff46..9d0f19ae 100644 --- a/pico/sound/ym2612.h +++ b/pico/sound/ym2612.h @@ -109,7 +109,7 @@ typedef struct } FM_ST; #define ST_SSG 1 -#define ST_LADDER 2 +#define ST_DAC 2 /***********************************************************/ /* OPN unit */ diff --git a/pico/sound/ym2612_arm.S b/pico/sound/ym2612_arm.S index 5cb42f21..bb748338 100644 --- a/pico/sound/ym2612_arm.S +++ b/pico/sound/ym2612_arm.S @@ -677,7 +677,7 @@ @ lr=context, r12=pack (stereo, ssg_enabled, disabled, lfo_enabled | pan_r, pan_l, ams[2] | AMmasks[4] | FB[4] | lfo_ampm[16]) -@ r0-r2=scratch, r3=sin_tab/scratch, r4=(length<<8)|unused[3],ssg_update,was_update,algo[3], r5=tl_tab/slot, +@ r0-r2=scratch, r3=sin_tab/scratch, r4=(length<<8)|dac,unused[2],ssg_update,was_update,algo[3], r5=tl_tab/slot, @ r6-r7=vol_out[4], r8=eg_timer, r9=eg_timer_add[31:16], r10=op1_out, r11=buffer .global chan_render_loop @ chan_rend_context *ct, int *buffer, int length @@ -688,8 +688,8 @@ chan_render_loop: ldr r12, [lr, #0x4c] ldr r0, [lr, #0x50] mov r11, r1 - and r0, r0, #7 - orr r4, r4, r0 @ (length<<8)|algo + and r0, r0, #0x87 + orr r4, r4, r0 @ (length<<8)|dac,unused[4],algo[3] ldr r8, [lr, #0x44] @ eg_timer ldr r9, [lr, #0x48] @ eg_timer_add ldr r10, [lr, #0x54] @ op1_out @@ -925,9 +925,12 @@ crl_algo_done: beq ctl_sample_skip orr r4, r4, #8 @ have_output lsr r1, r0, #31 @ clip (saturate) sample to 14 bit - adds r2, r1, r0, asr #13 + cmn r1, r0, asr #13 subne r0, r1, #0x80000001 asrne r0, r0, #18 + tst r4, r1, lsl #7 @ (sample < 0) && dac? + bicne r0, r0, #0x1f + subne r0, r0, #7<<5 tst r12, #1 beq ctl_sample_mono diff --git a/platform/common/menu_pico.c b/platform/common/menu_pico.c index b5b44533..1151ad48 100644 --- a/platform/common/menu_pico.c +++ b/platform/common/menu_pico.c @@ -561,7 +561,7 @@ static menu_entry e_menu_adv_options[] = mee_onoff ("Emulate Z80", MA_OPT2_ENABLE_Z80, PicoIn.opt, POPT_EN_Z80), mee_onoff ("Emulate YM2612 (FM)", MA_OPT2_ENABLE_YM2612, PicoIn.opt, POPT_EN_FM), mee_onoff ("Disable YM2612 SSG-EG", MA_OPT2_DISABLE_YM_SSG,PicoIn.opt, POPT_DIS_FM_SSGEG), - mee_onoff ("Enable YM2612 ladder effect",MA_OPT2_DISABLE_YM_LAD,PicoIn.opt, POPT_EN_FM_LADDER), + mee_onoff ("Enable YM2612 DAC noise", MA_OPT2_ENABLE_YM_DAC, PicoIn.opt, POPT_EN_FM_DAC), mee_onoff ("Emulate SN76496 (PSG)", MA_OPT2_ENABLE_SN76496,PicoIn.opt, POPT_EN_PSG), mee_onoff ("Emulate Game Gear LCD", MA_OPT2_ENABLE_GGLCD ,PicoIn.opt, POPT_EN_GG_LCD), mee_onoff ("Disable idle loop patching",MA_OPT2_NO_IDLE_LOOPS,PicoIn.opt, POPT_DIS_IDLE_DET), diff --git a/platform/common/menu_pico.h b/platform/common/menu_pico.h index 5b1800d1..0c81563b 100644 --- a/platform/common/menu_pico.h +++ b/platform/common/menu_pico.h @@ -50,7 +50,7 @@ typedef enum MA_OPT2_ENABLE_Z80, MA_OPT2_ENABLE_YM2612, MA_OPT2_DISABLE_YM_SSG, - MA_OPT2_DISABLE_YM_LAD, + MA_OPT2_ENABLE_YM_DAC, MA_OPT2_ENABLE_SN76496, MA_OPT2_ENABLE_YM2413, MA_OPT2_ENABLE_GGLCD, diff --git a/platform/libretro/libretro.c b/platform/libretro/libretro.c index f82dcbef..1e15a2ab 100644 --- a/platform/libretro/libretro.c +++ b/platform/libretro/libretro.c @@ -1594,6 +1594,15 @@ static void update_variables(bool first_run) PicoIn.opt &= ~POPT_EN_DRC; #endif + var.value = NULL; + var.key = "picodrive_dacnoise"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { + if (strcmp(var.value, "enabled") == 0) + PicoIn.opt |= POPT_EN_FM_DAC; + else + PicoIn.opt &= ~POPT_EN_FM_DAC; + } + old_snd_filter = PicoIn.opt & POPT_EN_SNDFILTER; var.value = NULL; var.key = "picodrive_audio_filter"; diff --git a/platform/libretro/libretro_core_options.h b/platform/libretro/libretro_core_options.h index 55ef834f..07e8b723 100644 --- a/platform/libretro/libretro_core_options.h +++ b/platform/libretro/libretro_core_options.h @@ -64,7 +64,7 @@ struct retro_core_option_v2_category option_cats_us[] = { { "audio", "Audio", - "Configure sample rate / emulated audio devices / low pass filter." + "Configure sample rate / emulated audio devices / low pass filter / DAC noise." }, { "input", @@ -231,11 +231,25 @@ struct retro_core_option_v2_definition option_defs_us[] = { }, "off" }, + { + "picodrive_dacnoise", + "Mega Drive FM DAC noise", + NULL, + "Enable emulation of YM2612 DAC noise. This option generates a distortion which existed on most Model 1 Mega Drive/Genesis, but not on newer models.", + NULL, + "audio", + { + { "off", "disabled" }, + { "on", "enabled" }, + { NULL, NULL }, + }, + "off" + }, { "picodrive_audio_filter", "Audio Filter", NULL, - "Enable a low pass audio filter to better simulate the characteristic sound of a Model 1 Genesis. This option is ignored when running Master System and PICO titles. Only the Genesis and its add-on hardware (Sega CD, 32X) employed a physical low pass filter.", + "Enable a low pass audio filter to better simulate the characteristic sound of a Model 1 Mega Drive/Genesis. Note that although only the Genesis and its add-on hardware (Sega CD, 32X) employed a physical low pass filter, the filter setting is not restricted to that.", NULL, "audio", {