From 18df4a80c8bfed451a7d8778ee83ea65a391b14c Mon Sep 17 00:00:00 2001 From: David Reid Date: Sun, 16 Feb 2020 12:46:58 +1000 Subject: [PATCH] Bug fix for ma_decoder_get_length_in_pcm_frames(). This previously returned the frame count based on the internal sample rate of the underlying stream, whereas it should have instead returned a frame count based on the output sample rate. This commit fixes this. This commit commit also changes the implementation of ma_calculate_frame_count_after_src() to use the ma_resampler API which should make it a bit more robust and easier to maintain. --- miniaudio.h | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/miniaudio.h b/miniaudio.h index 233fd9af..f56ef46b 100644 --- a/miniaudio.h +++ b/miniaudio.h @@ -6068,15 +6068,21 @@ static ma_result ma_allocation_callbacks_init_copy(ma_allocation_callbacks* pDst ma_uint64 ma_calculate_frame_count_after_src(ma_uint32 sampleRateOut, ma_uint32 sampleRateIn, ma_uint64 frameCountIn) { - double srcRatio = (double)sampleRateOut / sampleRateIn; - double frameCountOutF = (ma_int64)frameCountIn * srcRatio; /* Cast to int64 required for VC6. */ - ma_uint64 frameCountOut = (ma_uint64)frameCountOutF; + /* For robustness we're going to use a resampler object to calculate this since that already has a way of calculating this. */ + ma_result result; + ma_uint64 frameCountOut; + ma_resampler_config config; + ma_resampler resampler; - /* If the output frame count is fractional, make sure we add an extra frame to ensure there's enough room for that last sample. */ - if ((frameCountOutF - (ma_int64)frameCountOut) > 0.0) { - frameCountOut += 1; + config = ma_resampler_config_init(ma_format_s16, 1, sampleRateIn, sampleRateOut, ma_resample_algorithm_linear); + result = ma_resampler_init(&config, &resampler); + if (result != MA_SUCCESS) { + return 0; } + frameCountOut = ma_resampler_get_expected_output_frame_count(&resampler, frameCountIn); + + ma_resampler_uninit(&resampler); return frameCountOut; } @@ -37619,7 +37625,12 @@ ma_uint64 ma_decoder_get_length_in_pcm_frames(ma_decoder* pDecoder) } if (pDecoder->onGetLengthInPCMFrames) { - return pDecoder->onGetLengthInPCMFrames(pDecoder); + ma_uint64 nativeLengthInPCMFrames = pDecoder->onGetLengthInPCMFrames(pDecoder); + if (pDecoder->internalSampleRate == pDecoder->outputSampleRate) { + return nativeLengthInPCMFrames; + } else { + return ma_calculate_frame_count_after_src(pDecoder->outputSampleRate, pDecoder->internalSampleRate, nativeLengthInPCMFrames); + } } return 0;