libretro: upload audio once per frame

This commit is contained in:
sonninnos 2024-05-28 14:27:02 +03:00
parent e69870033e
commit 9afc668bfa

View file

@ -69,6 +69,13 @@
#define SAMPLERATE 44100
/* Audio output buffer */
static struct {
int16_t *data;
int32_t size;
int32_t capacity;
} output_audio_buffer = {NULL, 0, 0};
// Calculated swap interval is 'stable' if the same
// value is recorded for a number of retro_run()
// calls equal to VSYNC_SWAP_INTERVAL_FRAMES
@ -97,6 +104,7 @@ namespace Libretro
static retro_audio_sample_batch_t audio_batch_cb;
static retro_input_poll_t input_poll_cb;
static retro_input_state_t input_state_cb;
static retro_log_printf_t log_cb;
static bool detectVsyncSwapInterval = false;
static bool detectVsyncSwapIntervalOptShown = true;
@ -110,6 +118,40 @@ namespace Libretro
static float runSpeed = 0.0f;
static s64 runTicksLast = 0;
static void ensure_output_audio_buffer_capacity(int32_t capacity)
{
if (capacity <= output_audio_buffer.capacity) {
return;
}
output_audio_buffer.data = (int16_t*)realloc(output_audio_buffer.data, capacity * sizeof(*output_audio_buffer.data));
output_audio_buffer.capacity = capacity;
log_cb(RETRO_LOG_DEBUG, "Output audio buffer capacity set to %d\n", capacity);
}
static void init_output_audio_buffer(int32_t capacity)
{
output_audio_buffer.data = NULL;
output_audio_buffer.size = 0;
output_audio_buffer.capacity = 0;
ensure_output_audio_buffer_capacity(capacity);
}
static void free_output_audio_buffer()
{
free(output_audio_buffer.data);
output_audio_buffer.data = NULL;
output_audio_buffer.size = 0;
output_audio_buffer.capacity = 0;
}
static void upload_output_audio_buffer()
{
audio_batch_cb(output_audio_buffer.data, output_audio_buffer.size / 2);
output_audio_buffer.size = 0;
}
/**
* Clamp a value to a given range.
*
@ -1103,6 +1145,7 @@ void retro_init(void)
struct retro_log_callback log;
if (environ_cb(RETRO_ENVIRONMENT_GET_LOG_INTERFACE, &log))
{
log_cb = log.log;
LogManager::Init(&g_Config.bEnableLogging);
printfLogger = new PrintfLogger(log);
LogManager* logman = LogManager::GetInstance();
@ -1140,6 +1183,8 @@ void retro_init(void)
g_Config.bDiscordPresence = false;
g_VFS.Register("", new DirectoryReader(retro_base_dir));
init_output_audio_buffer(2048);
}
void retro_deinit(void)
@ -1154,6 +1199,8 @@ void retro_deinit(void)
libretro_supports_option_categories = false;
VsyncSwapIntervalReset();
free_output_audio_buffer();
}
void retro_set_controller_port_device(unsigned port, unsigned device)
@ -1500,6 +1547,7 @@ void retro_run(void)
VsyncSwapIntervalDetect();
ctx->SwapBuffers();
upload_output_audio_buffer();
}
unsigned retro_get_region(void) { return RETRO_REGION_NTSC; }
@ -1753,6 +1801,8 @@ inline int16_t Clamp16(int32_t sample) {
void System_AudioPushSamples(const int32_t *audio, int numSamples) {
// Convert to 16-bit audio for further processing.
int16_t buffer[1024 * 2];
int origSamples = numSamples * 2;
while (numSamples > 0) {
int blockSize = std::min(1024, numSamples);
for (int i = 0; i < blockSize; i++) {
@ -1760,14 +1810,13 @@ void System_AudioPushSamples(const int32_t *audio, int numSamples) {
buffer[i * 2 + 1] = Clamp16(audio[i * 2 + 1]);
}
int framesToWrite = blockSize;
uint32_t framesWritten = audio_batch_cb(buffer, framesToWrite);
if (framesWritten != framesToWrite) {
// Let's just stop, and eat any left-over samples.
break;
}
numSamples -= blockSize;
}
if (output_audio_buffer.capacity - output_audio_buffer.size < origSamples)
ensure_output_audio_buffer_capacity((output_audio_buffer.capacity + origSamples) * 1.5);
memcpy(output_audio_buffer.data + output_audio_buffer.size, buffer, origSamples * sizeof(*output_audio_buffer.data));
output_audio_buffer.size += origSamples;
}
void System_AudioGetDebugStats(char *buf, size_t bufSize) { if (buf) buf[0] = '\0'; }