Park the main thread while getting audio frames from the game

The main justification for this is that normal behaviour from a
backend is to have the main thread be interrupted by the audio system
and to then stay within the audio system while getting audio
frames. Parking the main thread simulates this by ensuring nothing
else happens in the game's logical flow at the same time.
This commit is contained in:
John Lorentzson 2025-04-06 23:44:17 +02:00
parent faa808e238
commit e3ce9ae828

View file

@ -2,8 +2,10 @@
// See LICENCE.txt for details.
#include "Backend.h"
#include "../../Misc.h"
#include <cstdint>
#include <csignal>
#include <stdint.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
@ -15,8 +17,10 @@
#include <sys/audioio.h>
#include <pthread.h>
int sndfp;
void (*parent_callback)(long *stream, size_t frames_total);
static pthread_t mainThread;
static int sndfp;
static void (*parent_callback)(long *stream, size_t frames_total);
static bool audioDone = false;
static void* soundcheckthread(void*) {
unsigned long for_as_long_as_it_seems_we_should = 0;
@ -38,17 +42,35 @@ static void* soundcheckthread(void*) {
long mix[0x400 * 2];
memset(mix, 0, 0x400 * 2);
// park the main thread since the game probably expects it to not be
// doing anything else while we're requesting audio frames.
audioDone = false;
pthread_kill(mainThread, SIGUSR1);
parent_callback(mix, 0x400 * 2);
// unpark the main thread now that we're not using game state anymore
audioDone = true;
write(sndfp, mix, 0x400 * 2);
for_as_long_as_it_seems_we_should = (0x400 / 48000) * 1000000;
}
}
static void threadPark(int signo) {
while(audioDone == false);
}
unsigned long SoftwareMixerBackend_Init(void (*callback)(long *stream, size_t frames_total)) {
sndfp = open("/dev/audio", 0, O_WRONLY);
if(sndfp == -1) {
Backend_PrintError("Failed to open audio device.\n");
return 0;
}
audio_prinfo_t audioInfo;
ioctl(sndfp, AUDIO_GETINFO, &audioInfo);
audioInfo.sample_rate = 48000;
@ -58,6 +80,13 @@ unsigned long SoftwareMixerBackend_Init(void (*callback)(long *stream, size_t fr
audioInfo.port = AUDIO_SPEAKER;
ioctl(sndfp, AUDIO_SETINFO, &audioInfo);
if(signal(SIGUSR1, threadPark) == SIG_ERR) {
Backend_PrintError("Failed to register thread park signal handler for audio system.\n");
return 0;
}
mainThread = pthread_self();
pthread_t thread;
pthread_attr_t thread_attr;
pthread_attr_init(&thread_attr);