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:
parent
faa808e238
commit
e3ce9ae828
1 changed files with 32 additions and 3 deletions
|
@ -2,8 +2,10 @@
|
||||||
// See LICENCE.txt for details.
|
// See LICENCE.txt for details.
|
||||||
|
|
||||||
#include "Backend.h"
|
#include "Backend.h"
|
||||||
|
#include "../../Misc.h"
|
||||||
|
|
||||||
#include <cstdint>
|
#include <csignal>
|
||||||
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
@ -15,8 +17,10 @@
|
||||||
#include <sys/audioio.h>
|
#include <sys/audioio.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
|
||||||
int sndfp;
|
static pthread_t mainThread;
|
||||||
void (*parent_callback)(long *stream, size_t frames_total);
|
static int sndfp;
|
||||||
|
static void (*parent_callback)(long *stream, size_t frames_total);
|
||||||
|
static bool audioDone = false;
|
||||||
|
|
||||||
static void* soundcheckthread(void*) {
|
static void* soundcheckthread(void*) {
|
||||||
unsigned long for_as_long_as_it_seems_we_should = 0;
|
unsigned long for_as_long_as_it_seems_we_should = 0;
|
||||||
|
@ -38,17 +42,35 @@ static void* soundcheckthread(void*) {
|
||||||
|
|
||||||
long mix[0x400 * 2];
|
long mix[0x400 * 2];
|
||||||
memset(mix, 0, 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);
|
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);
|
write(sndfp, mix, 0x400 * 2);
|
||||||
|
|
||||||
for_as_long_as_it_seems_we_should = (0x400 / 48000) * 1000000;
|
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)) {
|
unsigned long SoftwareMixerBackend_Init(void (*callback)(long *stream, size_t frames_total)) {
|
||||||
sndfp = open("/dev/audio", 0, O_WRONLY);
|
sndfp = open("/dev/audio", 0, O_WRONLY);
|
||||||
|
|
||||||
|
if(sndfp == -1) {
|
||||||
|
Backend_PrintError("Failed to open audio device.\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
audio_prinfo_t audioInfo;
|
audio_prinfo_t audioInfo;
|
||||||
ioctl(sndfp, AUDIO_GETINFO, &audioInfo);
|
ioctl(sndfp, AUDIO_GETINFO, &audioInfo);
|
||||||
audioInfo.sample_rate = 48000;
|
audioInfo.sample_rate = 48000;
|
||||||
|
@ -58,6 +80,13 @@ unsigned long SoftwareMixerBackend_Init(void (*callback)(long *stream, size_t fr
|
||||||
audioInfo.port = AUDIO_SPEAKER;
|
audioInfo.port = AUDIO_SPEAKER;
|
||||||
ioctl(sndfp, AUDIO_SETINFO, &audioInfo);
|
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_t thread;
|
||||||
pthread_attr_t thread_attr;
|
pthread_attr_t thread_attr;
|
||||||
pthread_attr_init(&thread_attr);
|
pthread_attr_init(&thread_attr);
|
||||||
|
|
Loading…
Add table
Reference in a new issue