#include "audio.h" #include #include #include #include extern "C" { #include "../src/libsm64.h" #include "context.h" } static SDL_AudioDeviceID dev; pthread_t gSoundThread; long long timeInMilliseconds(void) { struct timeval tv; gettimeofday(&tv, nullptr); return(((long long)tv.tv_sec)*1000)+(tv.tv_usec/1000); } void* audio_thread(void* keepAlive) { // from https://github.com/ckosmic/libsm64/blob/audio/src/libsm64.c#L535-L555 // except keepAlive is a null pointer here, so don't use it pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,nullptr); pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,nullptr); long long currentTime = timeInMilliseconds(); long long targetTime = 0; while(1) { //if(!*((bool*)keepAlive)) return nullptr; int16_t audioBuffer[544 * 2 * 2]; uint32_t numSamples = sm64_audio_tick(SDL_GetQueuedAudioSize(dev)/4, 1100, audioBuffer); if (SDL_GetQueuedAudioSize(dev)/4 < 6000) SDL_QueueAudio(dev, audioBuffer, numSamples * 2 * 4); targetTime = currentTime + 33; while (timeInMilliseconds() < targetTime) { usleep(100); //if(!*((bool*)keepAlive)) return nullptr; } currentTime = timeInMilliseconds(); } } void audio_init() { if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) { fprintf(stderr, "SDL_InitSubSystem(SDL_INIT_AUDIO) failed: %s\n", SDL_GetError()); return; } SDL_AudioSpec want, have; SDL_zero(want); want.freq = 32000; want.format = AUDIO_S16; want.channels = 2; want.samples = 512; want.callback = nullptr; dev = SDL_OpenAudioDevice(nullptr, 0, &want, &have, 0); if (dev == 0) { fprintf(stderr, "SDL_OpenAudio error: %s\n", SDL_GetError()); return; } SDL_PauseAudioDevice(dev, 0); // it's best to run audio in a separate thread pthread_create(&gSoundThread, nullptr, audio_thread, nullptr); }