mirror of
https://github.com/JorjBauer/aiie.git
synced 2024-08-14 19:29:00 +00:00
account for missing cycles auto-filled when speaker is quiescent
This commit is contained in:
parent
d78f0dc8cf
commit
a67cc53bcd
@ -15,8 +15,6 @@ extern "C"
|
|||||||
|
|
||||||
#include "globals.h"
|
#include "globals.h"
|
||||||
|
|
||||||
#include "timeutil.h"
|
|
||||||
|
|
||||||
#define SDLSIZE (4096)
|
#define SDLSIZE (4096)
|
||||||
// But we want to keep more than just that, so we can fill it full every time
|
// But we want to keep more than just that, so we can fill it full every time
|
||||||
#define CACHEMULTIPLIER 2
|
#define CACHEMULTIPLIER 2
|
||||||
@ -25,14 +23,10 @@ extern "C"
|
|||||||
static volatile uint32_t bufIdx = 0;
|
static volatile uint32_t bufIdx = 0;
|
||||||
static volatile uint8_t soundBuf[CACHEMULTIPLIER*SDLSIZE];
|
static volatile uint8_t soundBuf[CACHEMULTIPLIER*SDLSIZE];
|
||||||
static pthread_mutex_t togmutex = PTHREAD_MUTEX_INITIALIZER;
|
static pthread_mutex_t togmutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
static struct timespec sdlEmptyTime, sdlStartTime;
|
static volatile uint32_t skippedSamples = 0;
|
||||||
extern struct timespec startTime; // defined in aiie (main)
|
|
||||||
|
|
||||||
volatile uint8_t audioRunning = 0;
|
volatile uint8_t audioRunning = 0;
|
||||||
|
|
||||||
// How many cpu cycles do we lag "real time"? (Enough to give us a
|
|
||||||
// solid audio buffer fill...)
|
|
||||||
#define PLAYBACK_LAG ((SDLSIZE/44100)*1023000)
|
|
||||||
|
|
||||||
// Debugging by writing a wav file with the sound output...
|
// Debugging by writing a wav file with the sound output...
|
||||||
//#define DEBUG_OUT_WAV
|
//#define DEBUG_OUT_WAV
|
||||||
@ -59,16 +53,10 @@ static void audioCallback(void *unused, Uint8 *stream, int len)
|
|||||||
audioRunning = 2;
|
audioRunning = 2;
|
||||||
} else if (audioRunning==1) {
|
} else if (audioRunning==1) {
|
||||||
// waiting for first fill; return an empty buffer.
|
// waiting for first fill; return an empty buffer.
|
||||||
printf("pre\n");
|
|
||||||
memset(stream, 0x80, len);
|
memset(stream, 0x80, len);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// calculate when the buffer will be empty again
|
|
||||||
do_gettime(&sdlEmptyTime);
|
|
||||||
timespec_add_us(&sdlEmptyTime, ((float)len * (float)1000000)/(float)44100, &sdlEmptyTime);
|
|
||||||
sdlEmptyTime = tsSubtract(sdlEmptyTime, sdlStartTime);
|
|
||||||
|
|
||||||
static uint8_t lastKnownSample = 0; // saved for when the apple is quiescent
|
static uint8_t lastKnownSample = 0; // saved for when the apple is quiescent
|
||||||
|
|
||||||
if (bufIdx >= len) {
|
if (bufIdx >= len) {
|
||||||
@ -84,12 +72,15 @@ static void audioCallback(void *unused, Uint8 *stream, int len)
|
|||||||
if (bufIdx) {
|
if (bufIdx) {
|
||||||
// partial buffer exists
|
// partial buffer exists
|
||||||
memcpy(stream, (void *)soundBuf, bufIdx);
|
memcpy(stream, (void *)soundBuf, bufIdx);
|
||||||
// and it's a partial underrun
|
// and it's a partial underrun. Track the number of samples we skipped
|
||||||
|
// so we can keep the audio buffer in sync.
|
||||||
|
skippedSamples += len-bufIdx;
|
||||||
memset(&stream[bufIdx], lastKnownSample, len-bufIdx);
|
memset(&stream[bufIdx], lastKnownSample, len-bufIdx);
|
||||||
bufIdx = 0;
|
bufIdx = 0;
|
||||||
} else {
|
} else {
|
||||||
// No big deal - buffer underrun might just mean nothing
|
// No big deal - buffer underrun might just mean nothing
|
||||||
// is trying to play audio right now.
|
// is trying to play audio right now.
|
||||||
|
skippedSamples += len;
|
||||||
|
|
||||||
memset(stream, 0x80, len);
|
memset(stream, 0x80, len);
|
||||||
// memset(stream, lastKnownSample, len);
|
// memset(stream, lastKnownSample, len);
|
||||||
@ -131,8 +122,6 @@ SDLSpeaker::SDLSpeaker()
|
|||||||
|
|
||||||
pthread_mutex_init(&togmutex, NULL);
|
pthread_mutex_init(&togmutex, NULL);
|
||||||
|
|
||||||
_init_darwin_shim();
|
|
||||||
|
|
||||||
lastCycleCount = 0;
|
lastCycleCount = 0;
|
||||||
lastSampleCount = 0;
|
lastSampleCount = 0;
|
||||||
}
|
}
|
||||||
@ -143,10 +132,6 @@ SDLSpeaker::~SDLSpeaker()
|
|||||||
|
|
||||||
void SDLSpeaker::begin()
|
void SDLSpeaker::begin()
|
||||||
{
|
{
|
||||||
do_gettime(&sdlStartTime);
|
|
||||||
do_gettime(&sdlEmptyTime);
|
|
||||||
sdlEmptyTime = tsSubtract(sdlEmptyTime, sdlStartTime);
|
|
||||||
|
|
||||||
SDL_AudioSpec audioDevice;
|
SDL_AudioSpec audioDevice;
|
||||||
SDL_AudioSpec audioActual;
|
SDL_AudioSpec audioActual;
|
||||||
SDL_memset(&audioDevice, 0, sizeof(audioDevice));
|
SDL_memset(&audioDevice, 0, sizeof(audioDevice));
|
||||||
@ -176,9 +161,21 @@ void SDLSpeaker::toggle(uint32_t c)
|
|||||||
if (lastFilledTime == 0) {
|
if (lastFilledTime == 0) {
|
||||||
lastFilledTime = expectedCycleNumber;
|
lastFilledTime = expectedCycleNumber;
|
||||||
}
|
}
|
||||||
uint32_t audioBufferSamples = expectedCycleNumber - lastFilledTime;
|
// This subtracts skippedSamples because those were filled automatically
|
||||||
uint32_t newIdx = bufIdx + audioBufferSamples;
|
// by the audioCallback when we had no data.
|
||||||
|
int32_t audioBufferSamples = expectedCycleNumber - lastFilledTime - skippedSamples;
|
||||||
|
// If audioBufferSamples < 0, then we need to keep some
|
||||||
|
// skippedSamples for later; otherwise we can keep moving forward.
|
||||||
|
if (audioBufferSamples < 0) {
|
||||||
|
skippedSamples = -audioBufferSamples;
|
||||||
|
audioBufferSamples = 0;
|
||||||
|
} else {
|
||||||
|
// Otherwise we consumed them and can forget about it.
|
||||||
|
skippedSamples = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t newIdx = bufIdx + audioBufferSamples;
|
||||||
|
|
||||||
if (audioBufferSamples == 0) {
|
if (audioBufferSamples == 0) {
|
||||||
// If the toggle wouldn't result in at least 1 buffer sample change,
|
// If the toggle wouldn't result in at least 1 buffer sample change,
|
||||||
// then we'll blatantly skip it here. If this turns out to be
|
// then we'll blatantly skip it here. If this turns out to be
|
||||||
@ -195,10 +192,8 @@ void SDLSpeaker::toggle(uint32_t c)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (newIdx >= sizeof(soundBuf)) {
|
if (newIdx >= sizeof(soundBuf)) {
|
||||||
printf("Buffer overrun: size %d idx %d\n", sizeof(soundBuf), newIdx);
|
printf("ERROR: buffer overrun: size %lu idx %d\n", sizeof(soundBuf), newIdx);
|
||||||
// printf("ERROR: buffer overrun, dropping data; need to increase buffer\n");
|
|
||||||
newIdx = sizeof(soundBuf)-1;
|
newIdx = sizeof(soundBuf)-1;
|
||||||
}
|
}
|
||||||
lastFilledTime = expectedCycleNumber;
|
lastFilledTime = expectedCycleNumber;
|
||||||
|
Loading…
Reference in New Issue
Block a user