Skip to content

Commit

Permalink
Handle audio thread properly
Browse files Browse the repository at this point in the history
  • Loading branch information
GaryOderNichts authored and louist103 committed Aug 7, 2022
1 parent b2ac01b commit cb2410d
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 71 deletions.
6 changes: 4 additions & 2 deletions libultraship/libultraship/Lib/Fast3D/gfx_dxgi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -239,8 +239,8 @@ static LRESULT CALLBACK gfx_dxgi_wnd_proc(HWND h_wnd, UINT message, WPARAM w_par
dxgi.current_height = (uint32_t)(l_param >> 16);
break;
case WM_DESTROY:
Ship::ExecuteHooks<Ship::ExitGame>();
exit(0);
PostQuitMessage(0);
break;
case WM_PAINT:
if (dxgi.in_paint) {
dxgi.recursive_paint_detected = true;
Expand Down Expand Up @@ -378,6 +378,8 @@ static void gfx_dxgi_main_loop(void (*run_one_game_iter)(void)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}

Ship::ExecuteHooks<Ship::ExitGame>();
}

static void gfx_dxgi_get_dimensions(uint32_t *width, uint32_t *height) {
Expand Down
7 changes: 4 additions & 3 deletions libultraship/libultraship/Lib/Fast3D/gfx_sdl2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,8 @@ static void gfx_sdl_main_loop(void (*run_one_game_iter)(void)) {
Ship::Switch::Exit();
#endif
Ship::ExecuteHooks<Ship::ExitGame>();

SDL_Quit();
}

static void gfx_sdl_get_dimensions(uint32_t *width, uint32_t *height) {
Expand Down Expand Up @@ -307,9 +309,8 @@ static void gfx_sdl_handle_events(void) {
CVar_Save();
break;
case SDL_QUIT:
Ship::ExecuteHooks<Ship::ExitGame>();
SDL_Quit(); // bandaid fix for linux window closing issue
exit(0);
is_running = false;
break;
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion soh/soh/OTRAudio.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
#pragma once

static struct {
std::thread thread;
std::condition_variable cv_to_thread, cv_from_thread;
std::mutex mutex;
bool initialized;
bool running;
bool processing;
} audio;
114 changes: 66 additions & 48 deletions soh/soh/OTRGlobals.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,73 @@ extern "C" void ResourceMgr_CacheDirectory(const char* resName);
extern "C" SequenceData ResourceMgr_LoadSeqByName(const char* path);
std::unordered_map<std::string, ExtensionEntry> ExtensionCache;

void OTRAudio_Thread() {
while (audio.running) {
{
std::unique_lock<std::mutex> Lock(audio.mutex);
while (!audio.processing && audio.running) {
audio.cv_to_thread.wait(Lock);
}

if (!audio.running) {
break;
}
}
std::unique_lock<std::mutex> Lock(audio.mutex);
//AudioMgr_ThreadEntry(&gAudioMgr);
// 528 and 544 relate to 60 fps at 32 kHz 32000/60 = 533.333..
// in an ideal world, one third of the calls should use num_samples=544 and two thirds num_samples=528
//#define SAMPLES_HIGH 560
//#define SAMPLES_LOW 528
// PAL values
//#define SAMPLES_HIGH 656
//#define SAMPLES_LOW 624

// 44KHZ values
#define SAMPLES_HIGH 752
#define SAMPLES_LOW 720

#define AUDIO_FRAMES_PER_UPDATE (R_UPDATE_RATE > 0 ? R_UPDATE_RATE : 1 )
#define NUM_AUDIO_CHANNELS 2

int samples_left = AudioPlayer_Buffered();
u32 num_audio_samples = samples_left < AudioPlayer_GetDesiredBuffered() ? SAMPLES_HIGH : SAMPLES_LOW;

// 3 is the maximum authentic frame divisor.
s16 audio_buffer[SAMPLES_HIGH * NUM_AUDIO_CHANNELS * 3];
for (int i = 0; i < AUDIO_FRAMES_PER_UPDATE; i++) {
AudioMgr_CreateNextAudioBuffer(audio_buffer + i * (num_audio_samples * NUM_AUDIO_CHANNELS), num_audio_samples);
}

AudioPlayer_Play((u8*)audio_buffer, num_audio_samples * (sizeof(int16_t) * NUM_AUDIO_CHANNELS * AUDIO_FRAMES_PER_UPDATE));

audio.processing = false;
audio.cv_from_thread.notify_one();
}
}

// C->C++ Bridge
extern "C" void OTRAudio_Init()
{
// Precache all our samples, sequences, etc...
ResourceMgr_CacheDirectory("audio");

if (!audio.running) {
audio.running = true;
audio.thread = std::thread(OTRAudio_Thread);
}
}

extern "C" void OTRAudio_Exit() {
// Tell the audio thread to stop
{
std::unique_lock<std::mutex> Lock(audio.mutex);
audio.running = false;
}
audio.cv_to_thread.notify_all();

// Wait until the audio thread quit
audio.thread.join();
}

extern "C" void OTRExtScanner() {
Expand Down Expand Up @@ -128,6 +190,10 @@ extern "C" void InitOTR() {
OTRExtScanner();
}

extern "C" void DeinitOTR() {
OTRAudio_Exit();
}

#ifdef _WIN32
extern "C" uint64_t GetFrequency() {
LARGE_INTEGER nFreq;
Expand Down Expand Up @@ -227,56 +293,10 @@ extern "C" void Graph_StartFrame() {

// C->C++ Bridge
extern "C" void Graph_ProcessGfxCommands(Gfx* commands) {
#ifndef __SWITCH__
if (!audio.initialized) {
audio.initialized = true;
std::thread([]() {
for (;;) {
{
std::unique_lock<std::mutex> Lock(audio.mutex);
while (!audio.processing) {
audio.cv_to_thread.wait(Lock);
}
}
std::unique_lock<std::mutex> Lock(audio.mutex);
//AudioMgr_ThreadEntry(&gAudioMgr);
// 528 and 544 relate to 60 fps at 32 kHz 32000/60 = 533.333..
// in an ideal world, one third of the calls should use num_samples=544 and two thirds num_samples=528
//#define SAMPLES_HIGH 560
//#define SAMPLES_LOW 528
// PAL values
//#define SAMPLES_HIGH 656
//#define SAMPLES_LOW 624

// 44KHZ values
#define SAMPLES_HIGH 752
#define SAMPLES_LOW 720

#define AUDIO_FRAMES_PER_UPDATE (R_UPDATE_RATE > 0 ? R_UPDATE_RATE : 1 )
#define NUM_AUDIO_CHANNELS 2

int samples_left = AudioPlayer_Buffered();
u32 num_audio_samples = samples_left < AudioPlayer_GetDesiredBuffered() ? SAMPLES_HIGH : SAMPLES_LOW;

// 3 is the maximum authentic frame divisor.
s16 audio_buffer[SAMPLES_HIGH * NUM_AUDIO_CHANNELS * 3];
for (int i = 0; i < AUDIO_FRAMES_PER_UPDATE; i++) {
AudioMgr_CreateNextAudioBuffer(audio_buffer + i * (num_audio_samples * NUM_AUDIO_CHANNELS), num_audio_samples);
}

AudioPlayer_Play((u8*)audio_buffer, num_audio_samples * (sizeof(int16_t) * NUM_AUDIO_CHANNELS * AUDIO_FRAMES_PER_UPDATE));

audio.processing = false;
audio.cv_from_thread.notify_one();
}
}).detach();
}

{
std::unique_lock<std::mutex> Lock(audio.mutex);
audio.processing = true;
}
#endif

audio.cv_to_thread.notify_one();
std::vector<std::unordered_map<Mtx*, MtxF>> mtx_replacements;
Expand Down Expand Up @@ -319,14 +339,12 @@ extern "C" void Graph_ProcessGfxCommands(Gfx* commands) {
last_fps = fps;
last_update_rate = R_UPDATE_RATE;

#ifndef __SWITCH__
{
std::unique_lock<std::mutex> Lock(audio.mutex);
while (audio.processing) {
audio.cv_from_thread.wait(Lock);
}
}
#endif

// OTRTODO: FIGURE OUT END FRAME POINT
/* if (OTRGlobals::Instance->context->GetWindow()->lastScancode != -1)
Expand Down
16 changes: 0 additions & 16 deletions soh/src/code/graph.c
Original file line number Diff line number Diff line change
Expand Up @@ -481,22 +481,6 @@ static void RunFrame()
uint64_t ticksA, ticksB;
ticksA = GetPerfCounter();

#ifdef __SWITCH__
#define SAMPLES_HIGH 752
#define SAMPLES_LOW 720

#define AUDIO_FRAMES_PER_UPDATE (R_UPDATE_RATE > 0 ? R_UPDATE_RATE : 1 )
#define NUM_AUDIO_CHANNELS 2
int samples_left = AudioPlayer_Buffered();
u32 num_audio_samples = samples_left < AudioPlayer_GetDesiredBuffered() ? SAMPLES_HIGH : SAMPLES_LOW;

s16 audio_buffer[SAMPLES_HIGH * NUM_AUDIO_CHANNELS * 3];
for (int i = 0; i < AUDIO_FRAMES_PER_UPDATE; i++) {
AudioMgr_CreateNextAudioBuffer(audio_buffer + i * (num_audio_samples * NUM_AUDIO_CHANNELS), num_audio_samples);
}

AudioPlayer_Play((u8*)audio_buffer, num_audio_samples * (sizeof(int16_t) * NUM_AUDIO_CHANNELS * AUDIO_FRAMES_PER_UPDATE));
#endif
Graph_StartFrame();

// TODO: Workaround for rumble being too long. Implement os thread functions.
Expand Down
4 changes: 3 additions & 1 deletion soh/src/code/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,14 @@ void Main_LogSystemHeap(void) {
osSyncPrintf(VT_RST);
}

void main(int argc, char** argv)
int main(int argc, char** argv)
{
GameConsole_Init();
InitOTR();
BootCommands_Init();
Main(0);
DeinitOTR();
return 0;
}

void Main(void* arg) {
Expand Down

0 comments on commit cb2410d

Please sign in to comment.