diff options
author | Chris Robinson <[email protected]> | 2020-06-29 12:16:30 -0700 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2020-06-29 12:34:12 -0700 |
commit | 775187788ad6902feafa6ed07e65e2f9ce50e92e (patch) | |
tree | 88e0845455e09f5664502bfc1d9fa79edfae7f38 /alc | |
parent | 88ad84edf674e31b22c1a6410aad47884154b310 (diff) |
Fix SrcBufferSize calculation when downsampling
Diffstat (limited to 'alc')
-rw-r--r-- | alc/voice.cpp | 56 |
1 files changed, 36 insertions, 20 deletions
diff --git a/alc/voice.cpp b/alc/voice.cpp index c17cb4cc..e256d5b4 100644 --- a/alc/voice.cpp +++ b/alc/voice.cpp @@ -631,31 +631,47 @@ void Voice::mix(const State vstate, ALCcontext *Context, const ALuint SamplesToD do { /* Figure out how many buffer samples will be needed */ ALuint DstBufferSize{SamplesToDo - OutPos}; + ALuint SrcBufferSize; - /* Calculate the last written dst sample pos. */ - uint64_t DataSize64{DstBufferSize - 1}; - /* Calculate the last read src sample pos. */ - DataSize64 = (DataSize64*increment + DataPosFrac) >> FRACTIONBITS; - /* +1 to get the src sample count, include padding. */ - DataSize64 += 1 + MAX_RESAMPLER_PADDING; - - auto SrcBufferSize = static_cast<ALuint>( - minu64(DataSize64, BUFFERSIZE + MAX_RESAMPLER_PADDING + 1)); - if(SrcBufferSize > BUFFERSIZE + MAX_RESAMPLER_PADDING) + if(increment <= FRACTIONONE) { - SrcBufferSize = BUFFERSIZE + MAX_RESAMPLER_PADDING; - /* If the source buffer got saturated, we can't fill the desired - * dst size. Figure out how many samples we can actually mix from - * this. + /* Calculate the last written dst sample pos. */ + uint64_t DataSize64{DstBufferSize - 1}; + /* Calculate the last read src sample pos. */ + DataSize64 = (DataSize64*increment + DataPosFrac) >> FRACTIONBITS; + /* +1 to get the src sample count, include padding. */ + DataSize64 += 1 + MAX_RESAMPLER_PADDING; + + /* Result is guaranteed to be <= BUFFERSIZE+MAX_RESAMPLER_PADDING + * since we won't use more src samples than dst samples+padding. */ - DataSize64 = SrcBufferSize - MAX_RESAMPLER_PADDING; - DataSize64 = ((DataSize64<<FRACTIONBITS) - DataPosFrac + increment-1) / increment; - if(DataSize64 < DstBufferSize) + SrcBufferSize = static_cast<ALuint>(DataSize64); + } + else + { + uint64_t DataSize64{DstBufferSize}; + /* Calculate the end src sample pos, include padding. */ + DataSize64 = (DataSize64*increment + DataPosFrac) >> FRACTIONBITS; + DataSize64 += MAX_RESAMPLER_PADDING; + + SrcBufferSize = static_cast<ALuint>(minu64(DataSize64, + BUFFERSIZE + MAX_RESAMPLER_PADDING + 1)); + if(SrcBufferSize > BUFFERSIZE + MAX_RESAMPLER_PADDING) { - /* Some mixers require being 16-byte aligned, so also limit to - * a multiple of 4 samples to maintain alignment. + SrcBufferSize = BUFFERSIZE + MAX_RESAMPLER_PADDING; + /* If the source size got saturated, we can't fill the desired + * dst size. Figure out how many samples we can actually mix + * from this. */ - DstBufferSize = static_cast<ALuint>(DataSize64) & ~3u; + DataSize64 = SrcBufferSize - MAX_RESAMPLER_PADDING; + DataSize64 = ((DataSize64<<FRACTIONBITS) - DataPosFrac + increment-1) / increment; + if(DataSize64 < DstBufferSize) + { + /* Some mixers require being 16-byte aligned, so also limit + * to a multiple of 4 samples to maintain alignment. + */ + DstBufferSize = static_cast<ALuint>(DataSize64) & ~3u; + } } } |