169 lines
3.6 KiB
C++
169 lines
3.6 KiB
C++
#include <SDL.h>
|
|
#include "../System.h"
|
|
#include "../Sound.h"
|
|
#include "../Globals.h"
|
|
|
|
extern int emulating;
|
|
|
|
const int sdlSoundSamples = 4096;
|
|
const int sdlSoundAlign = 4;
|
|
const int sdlSoundCapacity = sdlSoundSamples * 2;
|
|
const int sdlSoundTotalLen = sdlSoundCapacity + sdlSoundAlign;
|
|
static u8 sdlSoundBuffer[sdlSoundTotalLen];
|
|
static int sdlSoundRPos;
|
|
static int sdlSoundWPos;
|
|
static SDL_cond *sdlSoundCond;
|
|
static SDL_mutex *sdlSoundMutex;
|
|
|
|
static inline int soundBufferFree()
|
|
{
|
|
int ret = sdlSoundRPos - sdlSoundWPos - sdlSoundAlign;
|
|
if (ret < 0)
|
|
ret += sdlSoundTotalLen;
|
|
return ret;
|
|
}
|
|
|
|
static inline int soundBufferUsed()
|
|
{
|
|
int ret = sdlSoundWPos - sdlSoundRPos;
|
|
if (ret < 0)
|
|
ret += sdlSoundTotalLen;
|
|
return ret;
|
|
}
|
|
|
|
static void soundCallback(void *,u8 *stream,int len)
|
|
{
|
|
if (len <= 0 || !emulating)
|
|
return;
|
|
|
|
SDL_mutexP(sdlSoundMutex);
|
|
const int nAvail = soundBufferUsed();
|
|
if (len > nAvail)
|
|
len = nAvail;
|
|
const int nAvail2 = sdlSoundTotalLen - sdlSoundRPos;
|
|
if (len >= nAvail2) {
|
|
memcpy(stream, &sdlSoundBuffer[sdlSoundRPos], nAvail2);
|
|
sdlSoundRPos = 0;
|
|
stream += nAvail2;
|
|
len -= nAvail2;
|
|
}
|
|
if (len > 0) {
|
|
memcpy(stream, &sdlSoundBuffer[sdlSoundRPos], len);
|
|
sdlSoundRPos = (sdlSoundRPos + len) % sdlSoundTotalLen;
|
|
stream += len;
|
|
}
|
|
SDL_CondSignal(sdlSoundCond);
|
|
SDL_mutexV(sdlSoundMutex);
|
|
}
|
|
|
|
void systemWriteDataToSoundBuffer()
|
|
{
|
|
if (SDL_GetAudioStatus() != SDL_AUDIO_PLAYING)
|
|
{
|
|
SDL_PauseAudio(0);
|
|
}
|
|
|
|
int remain = soundBufferLen;
|
|
const u8 *wave = reinterpret_cast<const u8 *>(soundFinalWave);
|
|
|
|
SDL_mutexP(sdlSoundMutex);
|
|
|
|
int n;
|
|
while (remain >= (n = soundBufferFree())) {
|
|
const int nAvail = (sdlSoundTotalLen - sdlSoundWPos) < n ? (sdlSoundTotalLen - sdlSoundWPos) : n;
|
|
memcpy(&sdlSoundBuffer[sdlSoundWPos], wave, nAvail);
|
|
sdlSoundWPos = (sdlSoundWPos + nAvail) % sdlSoundTotalLen;
|
|
wave += nAvail;
|
|
remain -= nAvail;
|
|
|
|
if (!emulating || speedup || systemThrottle) {
|
|
SDL_mutexV(sdlSoundMutex);
|
|
return;
|
|
}
|
|
SDL_CondWait(sdlSoundCond, sdlSoundMutex);
|
|
}
|
|
|
|
const int nAvail = sdlSoundTotalLen - sdlSoundWPos;
|
|
if (remain >= nAvail) {
|
|
memcpy(&sdlSoundBuffer[sdlSoundWPos], wave, nAvail);
|
|
sdlSoundWPos = 0;
|
|
wave += nAvail;
|
|
remain -= nAvail;
|
|
}
|
|
if (remain > 0) {
|
|
memcpy(&sdlSoundBuffer[sdlSoundWPos], wave, remain);
|
|
sdlSoundWPos = (sdlSoundWPos + remain) % sdlSoundTotalLen;
|
|
}
|
|
SDL_mutexV(sdlSoundMutex);
|
|
}
|
|
|
|
bool systemSoundInit()
|
|
{
|
|
SDL_AudioSpec audio;
|
|
|
|
switch(soundQuality) {
|
|
case 1:
|
|
audio.freq = 44100;
|
|
soundBufferLen = 1470*2;
|
|
break;
|
|
case 2:
|
|
audio.freq = 22050;
|
|
soundBufferLen = 736*2;
|
|
break;
|
|
case 4:
|
|
audio.freq = 11025;
|
|
soundBufferLen = 368*2;
|
|
break;
|
|
}
|
|
audio.format=AUDIO_S16SYS;
|
|
audio.channels = 2;
|
|
audio.samples = 1024;
|
|
audio.callback = soundCallback;
|
|
audio.userdata = NULL;
|
|
if(SDL_OpenAudio(&audio, NULL)) {
|
|
fprintf(stderr,"Failed to open audio: %s\n", SDL_GetError());
|
|
return false;
|
|
}
|
|
|
|
sdlSoundCond = SDL_CreateCond();
|
|
sdlSoundMutex = SDL_CreateMutex();
|
|
|
|
sdlSoundRPos = sdlSoundWPos = 0;
|
|
return true;
|
|
|
|
}
|
|
|
|
void systemSoundShutdown()
|
|
{
|
|
SDL_mutexP(sdlSoundMutex);
|
|
int iSave = emulating;
|
|
emulating = 0;
|
|
SDL_CondSignal(sdlSoundCond);
|
|
SDL_mutexV(sdlSoundMutex);
|
|
|
|
SDL_DestroyCond(sdlSoundCond);
|
|
sdlSoundCond = NULL;
|
|
|
|
SDL_DestroyMutex(sdlSoundMutex);
|
|
sdlSoundMutex = NULL;
|
|
|
|
SDL_CloseAudio();
|
|
|
|
emulating = iSave;
|
|
}
|
|
|
|
void systemSoundPause()
|
|
{
|
|
SDL_PauseAudio(1);
|
|
}
|
|
|
|
void systemSoundResume()
|
|
{
|
|
SDL_PauseAudio(0);
|
|
}
|
|
|
|
void systemSoundReset()
|
|
{
|
|
}
|
|
|