diff options
author | Chris Robinson <[email protected]> | 2020-10-05 22:30:23 -0700 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2020-10-05 22:30:23 -0700 |
commit | 7fb6d64ca81d68f74a254c097d511d8863453000 (patch) | |
tree | 7393463f07febc1fd0d31c50bc62d18b90774518 /alc/converter.cpp | |
parent | e7a44d3b7063553fa54e743a4fac116d130fbe1d (diff) |
Be more robust with to-mono channel conversions
Diffstat (limited to 'alc/converter.cpp')
-rw-r--r-- | alc/converter.cpp | 25 |
1 files changed, 17 insertions, 8 deletions
diff --git a/alc/converter.cpp b/alc/converter.cpp index ead0c2f6..b07e8619 100644 --- a/alc/converter.cpp +++ b/alc/converter.cpp @@ -135,14 +135,24 @@ void Mono2Stereo(float *RESTRICT dst, const void *src, const size_t frames) noex } template<DevFmtType T> -void Stereo2Mono(float *RESTRICT dst, const void *src, const size_t frames) noexcept +void Multi2Mono(ALuint chanmask, const size_t step, const float scale, float *RESTRICT dst, + const void *src, const size_t frames) noexcept { using SampleType = typename DevFmtTypeTraits<T>::Type; const SampleType *ssrc = static_cast<const SampleType*>(src); + std::fill_n(dst, frames, 0.0f); + for(size_t c{0};chanmask;++c) + { + if LIKELY((chanmask&1)) + { + for(size_t i{0u};i < frames;i++) + dst[i] += LoadSample<T>(ssrc[i*step + c]); + } + chanmask >>= 1; + } for(size_t i{0u};i < frames;i++) - dst[i] = (LoadSample<T>(ssrc[i*2 + 0])+LoadSample<T>(ssrc[i*2 + 1])) * - 0.707106781187f; + dst[i] *= scale; } } // namespace @@ -328,11 +338,12 @@ ALuint SampleConverter::convert(const void **src, ALuint *srcframes, void *dst, void ChannelConverter::convert(const void *src, float *dst, ALuint frames) const { - if(mSrcChans == DevFmtStereo && mDstChans == DevFmtMono) + if(mDstChans == DevFmtMono) { + const float scale{std::sqrt(1.0f / static_cast<float>(POPCNT32(mChanMask)))}; switch(mSrcType) { -#define HANDLE_FMT(T) case T: Stereo2Mono<T>(dst, src, frames); break +#define HANDLE_FMT(T) case T: Multi2Mono<T>(mChanMask, mSrcStep, scale, dst, src, frames); break HANDLE_FMT(DevFmtByte); HANDLE_FMT(DevFmtUByte); HANDLE_FMT(DevFmtShort); @@ -343,7 +354,7 @@ void ChannelConverter::convert(const void *src, float *dst, ALuint frames) const #undef HANDLE_FMT } } - else if(mSrcChans == DevFmtMono && mDstChans == DevFmtStereo) + else if(mChanMask == 0x1 && mDstChans == DevFmtStereo) { switch(mSrcType) { @@ -358,6 +369,4 @@ void ChannelConverter::convert(const void *src, float *dst, ALuint frames) const #undef HANDLE_FMT } } - else - LoadSamples(dst, src, 1u, mSrcType, frames * ChannelsFromDevFmt(mSrcChans, 0)); } |