GBA Audio: Audio buffer sizes are now correct sizes for both sample rates

This commit is contained in:
Jeffrey Pfau 2014-12-21 21:30:59 -08:00
parent 892a5e5d5e
commit c91c46ce97
9 changed files with 35 additions and 13 deletions

View File

@ -22,6 +22,7 @@ Bugfixes:
- GBA Memory: Properly initialize 1 Mb flash, and add debug logging
- Qt: Properly set default video recording settings
- GBA Audio: Make larger buffer sizes than 2048 actually work properly
- GBA Audio: Audio buffer sizes are now correct sizes for both sample rates
Misc:
- Qt: Disable sync to video by default
- GBA: Exit cleanly on FATAL if the port supports it

View File

@ -861,6 +861,6 @@ void GBAAudioDeserialize(struct GBAAudio* audio, const struct GBASerializedState
audio->nextSample = state->audio.nextSample;
}
float GBAAudioCalculateRatio(struct GBAAudio* audio, float desiredFPS, float desiredSampleRate) {
return desiredSampleRate * GBA_ARM7TDMI_FREQUENCY / (VIDEO_TOTAL_LENGTH * desiredFPS * audio->sampleRate);
float GBAAudioCalculateRatio(float inputSampleRate, float desiredFPS, float desiredSampleRate) {
return desiredSampleRate * GBA_ARM7TDMI_FREQUENCY / (VIDEO_TOTAL_LENGTH * desiredFPS * inputSampleRate);
}

View File

@ -263,6 +263,6 @@ struct GBASerializedState;
void GBAAudioSerialize(const struct GBAAudio* audio, struct GBASerializedState* state);
void GBAAudioDeserialize(struct GBAAudio* audio, const struct GBASerializedState* state);
float GBAAudioCalculateRatio(struct GBAAudio* audio, float desiredFPS, float desiredSampleRatio);
float GBAAudioCalculateRatio(float inputSampleRate, float desiredFPS, float desiredSampleRatio);
#endif

View File

@ -10,11 +10,11 @@
#include <libavresample/avresample.h>
#include <libavutil/opt.h>
struct AVAudioResampleContext* GBAAudioOpenLAVR(struct GBAAudio* audio, unsigned outputRate) {
struct AVAudioResampleContext* GBAAudioOpenLAVR(unsigned inputRate, unsigned outputRate) {
AVAudioResampleContext *avr = avresample_alloc_context();
av_opt_set_int(avr, "in_channel_layout", AV_CH_LAYOUT_STEREO, 0);
av_opt_set_int(avr, "out_channel_layout", AV_CH_LAYOUT_STEREO, 0);
av_opt_set_int(avr, "in_sample_rate", audio->sampleRate, 0);
av_opt_set_int(avr, "in_sample_rate", inputRate, 0);
av_opt_set_int(avr, "out_sample_rate", outputRate, 0);
av_opt_set_int(avr, "in_sample_fmt", AV_SAMPLE_FMT_S16P, 0);
av_opt_set_int(avr, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0);
@ -25,6 +25,17 @@ struct AVAudioResampleContext* GBAAudioOpenLAVR(struct GBAAudio* audio, unsigned
return avr;
}
struct AVAudioResampleContext* GBAAudioReopenLAVR(struct AVAudioResampleContext* avr, unsigned inputRate, unsigned outputRate) {
avresample_close(avr);
av_opt_set_int(avr, "in_sample_rate", inputRate, 0);
av_opt_set_int(avr, "out_sample_rate", outputRate, 0);
if (avresample_open(avr)) {
avresample_free(&avr);
return 0;
}
return avr;
}
unsigned GBAAudioResampleLAVR(struct GBAAudio* audio, struct AVAudioResampleContext* avr, struct GBAStereoSample* output, unsigned nSamples) {
int16_t left[GBA_AUDIO_SAMPLES];
int16_t right[GBA_AUDIO_SAMPLES];

View File

@ -10,7 +10,8 @@ struct AVAudioResampleContext;
struct GBAAudio;
struct GBAStereoSample;
struct AVAudioResampleContext* GBAAudioOpenLAVR(struct GBAAudio* audio, unsigned outputRate);
struct AVAudioResampleContext* GBAAudioOpenLAVR(unsigned inputRate, unsigned outputRate);
struct AVAudioResampleContext* GBAAudioReopenLAVR(struct AVAudioResampleContext* avr, unsigned inputRate, unsigned outputRate);
unsigned GBAAudioResampleLAVR(struct GBAAudio* audio, struct AVAudioResampleContext* avr, struct GBAStereoSample* output, unsigned nSamples);
#endif

View File

@ -26,7 +26,7 @@ void AudioDevice::setFormat(const QAudioFormat& format) {
return;
}
GBAThreadInterrupt(m_context);
m_ratio = GBAAudioCalculateRatio(&m_context->gba->audio, m_context->fpsTarget, format.sampleRate());
m_ratio = GBAAudioCalculateRatio(m_context->gba->audio.sampleRate, m_context->fpsTarget, format.sampleRate());
GBAThreadContinue(m_context);
}

View File

@ -278,11 +278,13 @@ void GameController::keyReleased(int key) {
void GameController::setAudioBufferSamples(int samples) {
if (m_gameOpen) {
threadInterrupt();
m_threadContext.audioBuffers = samples;
GBAAudioResizeBuffer(&m_threadContext.gba->audio, samples);
float ratio = GBAAudioCalculateRatio(m_threadContext.gba->audio.sampleRate, m_threadContext.fpsTarget, 44100);
m_threadContext.audioBuffers = samples / ratio;
GBAAudioResizeBuffer(&m_threadContext.gba->audio, samples / ratio);
threadContinue();
} else {
m_threadContext.audioBuffers = samples;
float ratio = GBAAudioCalculateRatio(0x8000, m_threadContext.fpsTarget, 44100);
m_threadContext.audioBuffers = samples / ratio;
}
QMetaObject::invokeMethod(m_audioProcessor, "setBufferSamples", Q_ARG(int, samples));

View File

@ -38,6 +38,8 @@ bool GBASDLInitAudio(struct GBASDLAudio* context, struct GBAThread* threadContex
}
context->thread = threadContext;
context->samples = context->obtainedSpec.samples;
float ratio = GBAAudioCalculateRatio(0x8000, threadContext->fpsTarget, 44100);
threadContext->audioBuffers = context->samples / ratio;
if (context->samples > threadContext->audioBuffers) {
threadContext->audioBuffers = context->samples * 2;
}
@ -77,7 +79,7 @@ static void _GBASDLAudioCallback(void* context, Uint8* data, int len) {
return;
}
#ifndef USE_FFMPEG
audioContext->ratio = GBAAudioCalculateRatio(&audioContext->thread->gba->audio, audioContext->thread->fpsTarget, audioContext->obtainedSpec.freq);
audioContext->ratio = GBAAudioCalculateRatio(audioContext->thread->gba->audio.sampleRate, audioContext->thread->fpsTarget, audioContext->obtainedSpec.freq);
if (audioContext->ratio == INFINITY) {
memset(data, 0, len);
return;
@ -88,12 +90,17 @@ static void _GBASDLAudioCallback(void* context, Uint8* data, int len) {
GBAAudioResampleNN(&audioContext->thread->gba->audio, audioContext->ratio, &audioContext->drift, ssamples, len);
}
#else
float ratio = GBAAudioCalculateRatio(audioContext->thread->gba->audio.sampleRate, audioContext->thread->fpsTarget, audioContext->thread->gba->audio.sampleRate);
if (!audioContext->avr) {
if (!audioContext->thread->gba->audio.sampleRate) {
memset(data, 0, len);
return;
}
audioContext->avr = GBAAudioOpenLAVR(&audioContext->thread->gba->audio, audioContext->obtainedSpec.freq);
audioContext->ratio = ratio;
audioContext->avr = GBAAudioOpenLAVR(audioContext->thread->gba->audio.sampleRate / ratio, audioContext->obtainedSpec.freq);
} else if (ratio != audioContext->ratio) {
audioContext->ratio = ratio;
audioContext->avr = GBAAudioReopenLAVR(audioContext->avr, audioContext->thread->gba->audio.sampleRate / ratio, audioContext->obtainedSpec.freq);
}
struct GBAStereoSample* ssamples = (struct GBAStereoSample*) data;
len /= 2 * audioContext->obtainedSpec.channels;

View File

@ -17,9 +17,9 @@ struct GBASDLAudio {
// State
SDL_AudioSpec desiredSpec;
SDL_AudioSpec obtainedSpec;
float ratio;
#ifndef USE_FFMPEG
float drift;
float ratio;
#else
struct AVAudioResampleContext* avr;
#endif