diff --git a/CHANGES b/CHANGES index e9557e508..ff777dc60 100644 --- a/CHANGES +++ b/CHANGES @@ -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 diff --git a/src/gba/gba-audio.c b/src/gba/gba-audio.c index c3dd9a074..f441cca77 100644 --- a/src/gba/gba-audio.c +++ b/src/gba/gba-audio.c @@ -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); } diff --git a/src/gba/gba-audio.h b/src/gba/gba-audio.h index 0e3366296..1f937faf7 100644 --- a/src/gba/gba-audio.h +++ b/src/gba/gba-audio.h @@ -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 diff --git a/src/platform/ffmpeg/ffmpeg-resample.c b/src/platform/ffmpeg/ffmpeg-resample.c index 14293e301..30719ed8a 100644 --- a/src/platform/ffmpeg/ffmpeg-resample.c +++ b/src/platform/ffmpeg/ffmpeg-resample.c @@ -10,11 +10,11 @@ #include #include -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]; diff --git a/src/platform/ffmpeg/ffmpeg-resample.h b/src/platform/ffmpeg/ffmpeg-resample.h index ee8970bf8..4514c76cd 100644 --- a/src/platform/ffmpeg/ffmpeg-resample.h +++ b/src/platform/ffmpeg/ffmpeg-resample.h @@ -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 diff --git a/src/platform/qt/AudioDevice.cpp b/src/platform/qt/AudioDevice.cpp index ed68242d4..64a4572b8 100644 --- a/src/platform/qt/AudioDevice.cpp +++ b/src/platform/qt/AudioDevice.cpp @@ -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); } diff --git a/src/platform/qt/GameController.cpp b/src/platform/qt/GameController.cpp index aa5970e73..420a2a054 100644 --- a/src/platform/qt/GameController.cpp +++ b/src/platform/qt/GameController.cpp @@ -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)); diff --git a/src/platform/sdl/sdl-audio.c b/src/platform/sdl/sdl-audio.c index 96daff575..a24b164e3 100644 --- a/src/platform/sdl/sdl-audio.c +++ b/src/platform/sdl/sdl-audio.c @@ -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; diff --git a/src/platform/sdl/sdl-audio.h b/src/platform/sdl/sdl-audio.h index f5be051b9..333503383 100644 --- a/src/platform/sdl/sdl-audio.h +++ b/src/platform/sdl/sdl-audio.h @@ -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