Ability to resize internal sound buffers

This commit is contained in:
Jeffrey Pfau 2014-07-21 00:14:48 -07:00
parent 10fc916425
commit e527220398
5 changed files with 53 additions and 6 deletions

View File

@ -20,9 +20,9 @@ static int32_t _updateChannel4(struct GBAAudioChannel4* ch);
static int _applyBias(struct GBAAudio* audio, int sample); static int _applyBias(struct GBAAudio* audio, int sample);
static void _sample(struct GBAAudio* audio); static void _sample(struct GBAAudio* audio);
void GBAAudioInit(struct GBAAudio* audio) { void GBAAudioInit(struct GBAAudio* audio, size_t samples) {
CircleBufferInit(&audio->left, GBA_AUDIO_SAMPLES * sizeof(int32_t)); CircleBufferInit(&audio->left, samples * sizeof(int32_t));
CircleBufferInit(&audio->right, GBA_AUDIO_SAMPLES * sizeof(int32_t)); CircleBufferInit(&audio->right, samples * sizeof(int32_t));
CircleBufferInit(&audio->chA.fifo, GBA_AUDIO_FIFO_SIZE); CircleBufferInit(&audio->chA.fifo, GBA_AUDIO_FIFO_SIZE);
CircleBufferInit(&audio->chB.fifo, GBA_AUDIO_FIFO_SIZE); CircleBufferInit(&audio->chB.fifo, GBA_AUDIO_FIFO_SIZE);
} }
@ -70,6 +70,40 @@ void GBAAudioDeinit(struct GBAAudio* audio) {
CircleBufferDeinit(&audio->chB.fifo); CircleBufferDeinit(&audio->chB.fifo);
} }
void GBAAudioResizeBuffer(struct GBAAudio* audio, size_t samples) {
if (samples >= GBA_AUDIO_SAMPLES) {
return;
}
GBASyncLockAudio(audio->p->sync);
int32_t buffer[GBA_AUDIO_SAMPLES];
int32_t dummy;
size_t read;
size_t i;
read = CircleBufferDump(&audio->left, buffer, sizeof(buffer));
CircleBufferDeinit(&audio->left);
CircleBufferInit(&audio->left, samples * sizeof(int32_t));
for (i = 0; i * sizeof(int32_t) < read; ++i) {
if (!CircleBufferWrite32(&audio->left, buffer[i])) {
CircleBufferRead32(&audio->left, &dummy);
CircleBufferWrite32(&audio->left, buffer[i]);
}
}
read = CircleBufferDump(&audio->right, buffer, sizeof(buffer));
CircleBufferDeinit(&audio->right);
CircleBufferInit(&audio->right, samples * sizeof(int32_t));
for (i = 0; i * sizeof(int32_t) < read; ++i) {
if (!CircleBufferWrite32(&audio->right, buffer[i])) {
CircleBufferRead32(&audio->right, &dummy);
CircleBufferWrite32(&audio->right, buffer[i]);
}
}
GBASyncUnlockAudio(audio->p->sync);
}
int32_t GBAAudioProcessEvents(struct GBAAudio* audio, int32_t cycles) { int32_t GBAAudioProcessEvents(struct GBAAudio* audio, int32_t cycles) {
audio->nextEvent -= cycles; audio->nextEvent -= cycles;
audio->eventDiff += cycles; audio->eventDiff += cycles;
@ -670,7 +704,7 @@ static void _sample(struct GBAAudio* audio) {
CircleBufferWrite32(&audio->left, sampleLeft); CircleBufferWrite32(&audio->left, sampleLeft);
CircleBufferWrite32(&audio->right, sampleRight); CircleBufferWrite32(&audio->right, sampleRight);
unsigned produced = CircleBufferSize(&audio->left); unsigned produced = CircleBufferSize(&audio->left);
GBASyncProduceAudio(audio->p->sync, produced >= GBA_AUDIO_SAMPLES * 3); GBASyncProduceAudio(audio->p->sync, produced >= CircleBufferCapacity(&audio->left) / sizeof(int32_t) * 3);
} }
void GBAAudioSerialize(const struct GBAAudio* audio, struct GBASerializedState* state) { void GBAAudioSerialize(const struct GBAAudio* audio, struct GBASerializedState* state) {

View File

@ -218,10 +218,12 @@ struct GBAStereoSample {
int16_t right; int16_t right;
}; };
void GBAAudioInit(struct GBAAudio* audio); void GBAAudioInit(struct GBAAudio* audio, size_t samples);
void GBAAudioReset(struct GBAAudio* audio); void GBAAudioReset(struct GBAAudio* audio);
void GBAAudioDeinit(struct GBAAudio* audio); void GBAAudioDeinit(struct GBAAudio* audio);
void GBAAudioResizeBuffer(struct GBAAudio* audio, size_t samples);
int32_t GBAAudioProcessEvents(struct GBAAudio* audio, int32_t cycles); int32_t GBAAudioProcessEvents(struct GBAAudio* audio, int32_t cycles);
void GBAAudioScheduleFifoDma(struct GBAAudio* audio, int number, struct GBADMA* info); void GBAAudioScheduleFifoDma(struct GBAAudio* audio, int number, struct GBADMA* info);

View File

@ -86,6 +86,11 @@ static THREAD_ENTRY _GBAThreadRun(void* context) {
#else #else
TlsSetValue(_contextKey, threadContext); TlsSetValue(_contextKey, threadContext);
#endif #endif
if (threadContext->audioBuffers) {
GBAAudioResizeBuffer(&gba.audio, threadContext->audioBuffers);
}
if (threadContext->renderer) { if (threadContext->renderer) {
GBAVideoAssociateRenderer(&gba.video, threadContext->renderer); GBAVideoAssociateRenderer(&gba.video, threadContext->renderer);
} }
@ -551,6 +556,10 @@ void GBASyncLockAudio(struct GBASync* sync) {
MutexLock(&sync->audioBufferMutex); MutexLock(&sync->audioBufferMutex);
} }
void GBASyncUnlockAudio(struct GBASync* sync) {
MutexUnlock(&sync->audioBufferMutex);
}
void GBASyncConsumeAudio(struct GBASync* sync) { void GBASyncConsumeAudio(struct GBASync* sync) {
ConditionWake(&sync->audioRequiredCond); ConditionWake(&sync->audioRequiredCond);
MutexUnlock(&sync->audioBufferMutex); MutexUnlock(&sync->audioBufferMutex);

View File

@ -57,6 +57,7 @@ struct GBAThread {
int activeKeys; int activeKeys;
int frameskip; int frameskip;
float fpsTarget; float fpsTarget;
size_t audioBuffers;
// Threading state // Threading state
Thread thread; Thread thread;
@ -106,6 +107,7 @@ bool GBASyncDrawingFrame(struct GBASync* sync);
void GBASyncProduceAudio(struct GBASync* sync, int wait); void GBASyncProduceAudio(struct GBASync* sync, int wait);
void GBASyncLockAudio(struct GBASync* sync); void GBASyncLockAudio(struct GBASync* sync);
void GBASyncUnlockAudio(struct GBASync* sync);
void GBASyncConsumeAudio(struct GBASync* sync); void GBASyncConsumeAudio(struct GBASync* sync);
#endif #endif

View File

@ -121,7 +121,7 @@ static void GBAInit(struct ARMCore* cpu, struct ARMComponent* component) {
GBAVideoInit(&gba->video); GBAVideoInit(&gba->video);
gba->audio.p = gba; gba->audio.p = gba;
GBAAudioInit(&gba->audio); GBAAudioInit(&gba->audio, GBA_AUDIO_SAMPLES);
GBAIOInit(gba); GBAIOInit(gba);