From 1ea6ef5061546bd2ee657c8b3b7deaab6d12243c Mon Sep 17 00:00:00 2001 From: Nikos Chantziaras Date: Tue, 12 Apr 2022 15:50:26 +0300 Subject: [PATCH] libretro: Fix audio when video rendering is disabled In commit 6628042fe386197648334063f70e6a94350b9bf7, audio upload was moved from retro_run() to S9xDeinitUpdate(). This breaks audio when runahead is enabled in RetroArch. With second-instance runahead, S9xDeinitUpdate() is not called when video rendering is disabled and thus the core instance responsible for audio is not uploading the audio. With single-instance runahead, audio is uploaded twice because video rendering is always enabled and thus S9xDeinitUpdate() gets called twice per frame. Fix this by introducing a callback that gets called at the end of every screen refresh, regardless of whether or not rendering is active for this frame. We can then decide in the callback whether or not audio should be uploaded. --- gfx.cpp | 15 +++++++++++++++ gfx.h | 6 ++++++ libretro/libretro.cpp | 29 +++++++++++++++++++---------- 3 files changed, 40 insertions(+), 10 deletions(-) diff --git a/gfx.cpp b/gfx.cpp index d33623ff..cf2f8a04 100644 --- a/gfx.cpp +++ b/gfx.cpp @@ -98,6 +98,9 @@ bool8 S9xGraphicsInit (void) } } + GFX.EndScreenRefreshCallback = NULL; + GFX.EndScreenRefreshCallbackData = NULL; + return (TRUE); } @@ -107,6 +110,9 @@ void S9xGraphicsDeinit (void) if (GFX.SubScreen) { free(GFX.SubScreen); GFX.SubScreen = NULL; } if (GFX.ZBuffer) { free(GFX.ZBuffer); GFX.ZBuffer = NULL; } if (GFX.SubZBuffer) { free(GFX.SubZBuffer); GFX.SubZBuffer = NULL; } + + GFX.EndScreenRefreshCallback = NULL; + GFX.EndScreenRefreshCallbackData = NULL; } void S9xGraphicsScreenResize (void) @@ -263,6 +269,15 @@ void S9xEndScreenRefresh (void) } } } + + if (GFX.EndScreenRefreshCallback) + GFX.EndScreenRefreshCallback(GFX.EndScreenRefreshCallbackData); +} + +void S9xSetEndScreenRefreshCallback(const SGFX::Callback cb, void *const data) +{ + GFX.EndScreenRefreshCallback = cb; + GFX.EndScreenRefreshCallbackData = data; } void RenderLine (uint8 C) diff --git a/gfx.h b/gfx.h index 5e78c266..84d03ad0 100644 --- a/gfx.h +++ b/gfx.h @@ -11,6 +11,8 @@ struct SGFX { + typedef void (*Callback)(void *); + const uint32 Pitch = sizeof(uint16) * MAX_SNES_WIDTH; const uint32 RealPPL = MAX_SNES_WIDTH; // true PPL of Screen buffer const uint32 ScreenSize = MAX_SNES_WIDTH * SNES_HEIGHT_EXTENDED; @@ -67,6 +69,9 @@ struct SGFX const char *InfoString; uint32 InfoStringTimeout; char FrameDisplayString[256]; + + Callback EndScreenRefreshCallback; + void *EndScreenRefreshCallbackData; }; struct SBG @@ -202,6 +207,7 @@ struct COLOR_SUB void S9xStartScreenRefresh (void); void S9xEndScreenRefresh (void); +void S9xSetEndScreenRefreshCallback(SGFX::Callback cb, void *data); void S9xBuildDirectColourMaps (void); void RenderLine (uint8); void S9xComputeClipWindows (void); diff --git a/libretro/libretro.cpp b/libretro/libretro.cpp index 8273399d..58028418 100644 --- a/libretro/libretro.cpp +++ b/libretro/libretro.cpp @@ -753,6 +753,24 @@ static void update_variables(void) } } +static void S9xEndScreenRefreshCallback(void*) +{ + if (Settings.Mute) { + S9xClearSamples(); + return; + } + + static std::vector audio_buffer; + + size_t avail = S9xGetSampleCount(); + + if (audio_buffer.size() < avail) + audio_buffer.resize(avail); + + S9xMixSamples((uint8*)&audio_buffer[0], avail); + audio_batch_cb(&audio_buffer[0], avail >> 1); +} + void retro_get_system_info(struct retro_system_info *info) { memset(info,0,sizeof(retro_system_info)); @@ -1358,6 +1376,7 @@ void retro_init(void) ntsc_screen_buffer = (uint16*) calloc(1, MAX_SNES_WIDTH_NTSC * 2 * (MAX_SNES_HEIGHT + 16)); snes_ntsc_buffer = ntsc_screen_buffer + (MAX_SNES_WIDTH_NTSC >> 1) * 16; S9xGraphicsInit(); + S9xSetEndScreenRefreshCallback(S9xEndScreenRefreshCallback, NULL); S9xInitInputDevices(); for (int i = 0; i < 2; i++) @@ -2057,16 +2076,6 @@ bool8 S9xDeinitUpdate(int width, int height) video_cb(GFX.Screen + ((int)(GFX.Pitch >> 1) * overscan_offset), width, height, GFX.Pitch); } - static std::vector audio_buffer; - - size_t avail = S9xGetSampleCount(); - - if (audio_buffer.size() < avail) - audio_buffer.resize(avail); - - S9xMixSamples((uint8*)&audio_buffer[0], avail); - audio_batch_cb(&audio_buffer[0], avail >> 1); - return TRUE; }