diff options
-rw-r--r-- | alc/alu.cpp | 144 | ||||
-rw-r--r-- | alc/alu.h | 9 | ||||
-rw-r--r-- | alc/converter.cpp | 12 | ||||
-rw-r--r-- | alc/mixvoice.cpp | 54 |
4 files changed, 108 insertions, 111 deletions
diff --git a/alc/alu.cpp b/alc/alu.cpp index 5df1c3a2..4e9bf9e0 100644 --- a/alc/alu.cpp +++ b/alc/alu.cpp @@ -147,6 +147,83 @@ inline HrtfDirectMixerFunc SelectHrtfMixer(void) return MixDirectHrtf_<CTag>; } + +inline void BsincPrepare(const ALuint increment, BsincState *state, const BSincTable *table) +{ + size_t si{BSINC_SCALE_COUNT - 1}; + float sf{0.0f}; + + if(increment > FRACTIONONE) + { + sf = FRACTIONONE / static_cast<float>(increment); + sf = maxf(0.0f, (BSINC_SCALE_COUNT-1) * (sf-table->scaleBase) * table->scaleRange); + si = float2uint(sf); + /* The interpolation factor is fit to this diagonally-symmetric curve + * to reduce the transition ripple caused by interpolating different + * scales of the sinc function. + */ + sf = 1.0f - std::cos(std::asin(sf - static_cast<float>(si))); + } + + state->sf = sf; + state->m = table->m[si]; + state->l = (state->m/2) - 1; + state->filter = table->Tab + table->filterOffset[si]; +} + +inline ResamplerFunc SelectResampler(Resampler resampler, ALuint increment) +{ + switch(resampler) + { + case Resampler::Point: + return Resample_<PointTag,CTag>; + case Resampler::Linear: +#ifdef HAVE_NEON + if((CPUCapFlags&CPU_CAP_NEON)) + return Resample_<LerpTag,NEONTag>; +#endif +#ifdef HAVE_SSE4_1 + if((CPUCapFlags&CPU_CAP_SSE4_1)) + return Resample_<LerpTag,SSE4Tag>; +#endif +#ifdef HAVE_SSE2 + if((CPUCapFlags&CPU_CAP_SSE2)) + return Resample_<LerpTag,SSE2Tag>; +#endif + return Resample_<LerpTag,CTag>; + case Resampler::Cubic: + return Resample_<CubicTag,CTag>; + case Resampler::BSinc12: + case Resampler::BSinc24: + if(increment <= FRACTIONONE) + { + /* fall-through */ + case Resampler::FastBSinc12: + case Resampler::FastBSinc24: +#ifdef HAVE_NEON + if((CPUCapFlags&CPU_CAP_NEON)) + return Resample_<FastBSincTag,NEONTag>; +#endif +#ifdef HAVE_SSE + if((CPUCapFlags&CPU_CAP_SSE)) + return Resample_<FastBSincTag,SSETag>; +#endif + return Resample_<FastBSincTag,CTag>; + } +#ifdef HAVE_NEON + if((CPUCapFlags&CPU_CAP_NEON)) + return Resample_<BSincTag,NEONTag>; +#endif +#ifdef HAVE_SSE + if((CPUCapFlags&CPU_CAP_SSE)) + return Resample_<BSincTag,SSETag>; +#endif + return Resample_<BSincTag,CTag>; + } + + return Resample_<PointTag,CTag>; +} + } // namespace void aluInit(void) @@ -155,6 +232,27 @@ void aluInit(void) } +ResamplerFunc PrepareResampler(Resampler resampler, ALuint increment, InterpState *state) +{ + switch(resampler) + { + case Resampler::Point: + case Resampler::Linear: + case Resampler::Cubic: + break; + case Resampler::FastBSinc12: + case Resampler::BSinc12: + BsincPrepare(increment, &state->bsinc, &bsinc12); + break; + case Resampler::FastBSinc24: + case Resampler::BSinc24: + BsincPrepare(increment, &state->bsinc, &bsinc24); + break; + } + return SelectResampler(resampler, increment); +} + + void ALCdevice::ProcessHrtf(const size_t SamplesToDo) { /* HRTF is stereo output only. */ @@ -196,36 +294,6 @@ void ALCdevice::ProcessBs2b(const size_t SamplesToDo) } -/* Prepares the interpolator for a given rate (determined by increment). - * - * With a bit of work, and a trade of memory for CPU cost, this could be - * modified for use with an interpolated increment for buttery-smooth pitch - * changes. - */ -void BsincPrepare(const ALuint increment, BsincState *state, const BSincTable *table) -{ - size_t si{BSINC_SCALE_COUNT - 1}; - float sf{0.0f}; - - if(increment > FRACTIONONE) - { - sf = FRACTIONONE / static_cast<float>(increment); - sf = maxf(0.0f, (BSINC_SCALE_COUNT-1) * (sf-table->scaleBase) * table->scaleRange); - si = float2uint(sf); - /* The interpolation factor is fit to this diagonally-symmetric curve - * to reduce the transition ripple caused by interpolating different - * scales of the sinc function. - */ - sf = 1.0f - std::cos(std::asin(sf - static_cast<float>(si))); - } - - state->sf = sf; - state->m = table->m[si]; - state->l = (state->m/2) - 1; - state->filter = table->Tab + table->filterOffset[si]; -} - - namespace { /* This RNG method was created based on the math found in opusdec. It's quick, @@ -943,15 +1011,11 @@ void CalcNonAttnSourceParams(ALvoice *voice, const ALvoicePropsBase *props, cons /* Calculate the stepping value */ const auto Pitch = static_cast<ALfloat>(voice->mFrequency) / static_cast<ALfloat>(Device->Frequency) * props->Pitch; - if(Pitch > static_cast<ALfloat>(MAX_PITCH)) + if(Pitch > float{MAX_PITCH}) voice->mStep = MAX_PITCH<<FRACTIONBITS; else voice->mStep = maxu(fastf2u(Pitch * FRACTIONONE), 1); - if(props->mResampler == Resampler::BSinc24 || props->mResampler == Resampler::FastBSinc24) - BsincPrepare(voice->mStep, &voice->mResampleState.bsinc, &bsinc24); - else if(props->mResampler == Resampler::BSinc12 || props->mResampler == Resampler::FastBSinc12) - BsincPrepare(voice->mStep, &voice->mResampleState.bsinc, &bsinc12); - voice->mResampler = SelectResampler(props->mResampler, voice->mStep); + voice->mResampler = PrepareResampler(props->mResampler, voice->mStep, &voice->mResampleState); /* Calculate gains */ const ALlistener &Listener = ALContext->mListener; @@ -1273,15 +1337,11 @@ void CalcAttnSourceParams(ALvoice *voice, const ALvoicePropsBase *props, const A * fixed-point stepping value. */ Pitch *= static_cast<ALfloat>(voice->mFrequency)/static_cast<ALfloat>(Device->Frequency); - if(Pitch > static_cast<ALfloat>(MAX_PITCH)) + if(Pitch > float{MAX_PITCH}) voice->mStep = MAX_PITCH<<FRACTIONBITS; else voice->mStep = maxu(fastf2u(Pitch * FRACTIONONE), 1); - if(props->mResampler == Resampler::BSinc24 || props->mResampler == Resampler::FastBSinc24) - BsincPrepare(voice->mStep, &voice->mResampleState.bsinc, &bsinc24); - else if(props->mResampler == Resampler::BSinc12 || props->mResampler == Resampler::FastBSinc12) - BsincPrepare(voice->mStep, &voice->mResampleState.bsinc, &bsinc12); - voice->mResampler = SelectResampler(props->mResampler, voice->mStep); + voice->mResampler = PrepareResampler(props->mResampler, voice->mStep, &voice->mResampleState); ALfloat spread{0.0f}; if(props->Radius > Distance) @@ -85,11 +85,6 @@ union InterpState { using ResamplerFunc = const ALfloat*(*)(const InterpState *state, const ALfloat *RESTRICT src, ALuint frac, ALuint increment, const al::span<float> dst); -void BsincPrepare(const ALuint increment, BsincState *state, const BSincTable *table); - -extern const BSincTable bsinc12; -extern const BSincTable bsinc24; - enum { AF_None = 0, @@ -372,8 +367,6 @@ void aluInit(void); void aluInitMixer(void); -ResamplerFunc SelectResampler(Resampler resampler, ALuint increment); - /* aluInitRenderer * * Set up the appropriate panning method and mixing method given the device @@ -383,6 +376,8 @@ void aluInitRenderer(ALCdevice *device, ALint hrtf_id, HrtfRequestMode hrtf_appr void aluInitEffectPanning(ALeffectslot *slot, ALCdevice *device); +ResamplerFunc PrepareResampler(Resampler resampler, ALuint increment, InterpState *state); + /** * Calculates ambisonic encoder coefficients using the X, Y, and Z direction * components, which must represent a normalized (unit length) vector, and the diff --git a/alc/converter.cpp b/alc/converter.cpp index aff1c353..0e7bd82f 100644 --- a/alc/converter.cpp +++ b/alc/converter.cpp @@ -10,6 +10,7 @@ #include "AL/al.h" #include "albyte.h" +#include "alu.h" #include "fpu_modes.h" #include "mixer/defs.h" @@ -161,18 +162,13 @@ SampleConverterPtr CreateSampleConverter(DevFmtType srcType, DevFmtType dstType, /* Have to set the mixer FPU mode since that's what the resampler code expects. */ FPUCtl mixer_mode{}; auto step = static_cast<ALuint>( - mind(srcRate*ALdouble{FRACTIONONE}/dstRate + 0.5, MAX_PITCH*FRACTIONONE)); + mind(srcRate*double{FRACTIONONE}/dstRate + 0.5, MAX_PITCH*FRACTIONONE)); converter->mIncrement = maxu(step, 1); if(converter->mIncrement == FRACTIONONE) converter->mResample = Resample_<CopyTag,CTag>; else - { - if(resampler == Resampler::BSinc24 || resampler == Resampler::FastBSinc24) - BsincPrepare(converter->mIncrement, &converter->mState.bsinc, &bsinc24); - else if(resampler == Resampler::BSinc12 || resampler == Resampler::FastBSinc12) - BsincPrepare(converter->mIncrement, &converter->mState.bsinc, &bsinc12); - converter->mResample = SelectResampler(resampler, converter->mIncrement); - } + converter->mResample = PrepareResampler(resampler, converter->mIncrement, + &converter->mState); return converter; } diff --git a/alc/mixvoice.cpp b/alc/mixvoice.cpp index e9e0d8df..3e4c73a6 100644 --- a/alc/mixvoice.cpp +++ b/alc/mixvoice.cpp @@ -135,60 +135,6 @@ inline HrtfMixerBlendFunc SelectHrtfBlendMixer() } // namespace -ResamplerFunc SelectResampler(Resampler resampler, ALuint increment) -{ - switch(resampler) - { - case Resampler::Point: - return Resample_<PointTag,CTag>; - case Resampler::Linear: -#ifdef HAVE_NEON - if((CPUCapFlags&CPU_CAP_NEON)) - return Resample_<LerpTag,NEONTag>; -#endif -#ifdef HAVE_SSE4_1 - if((CPUCapFlags&CPU_CAP_SSE4_1)) - return Resample_<LerpTag,SSE4Tag>; -#endif -#ifdef HAVE_SSE2 - if((CPUCapFlags&CPU_CAP_SSE2)) - return Resample_<LerpTag,SSE2Tag>; -#endif - return Resample_<LerpTag,CTag>; - case Resampler::Cubic: - return Resample_<CubicTag,CTag>; - case Resampler::BSinc12: - case Resampler::BSinc24: - if(increment <= FRACTIONONE) - { - /* fall-through */ - case Resampler::FastBSinc12: - case Resampler::FastBSinc24: -#ifdef HAVE_NEON - if((CPUCapFlags&CPU_CAP_NEON)) - return Resample_<FastBSincTag,NEONTag>; -#endif -#ifdef HAVE_SSE - if((CPUCapFlags&CPU_CAP_SSE)) - return Resample_<FastBSincTag,SSETag>; -#endif - return Resample_<FastBSincTag,CTag>; - } -#ifdef HAVE_NEON - if((CPUCapFlags&CPU_CAP_NEON)) - return Resample_<BSincTag,NEONTag>; -#endif -#ifdef HAVE_SSE - if((CPUCapFlags&CPU_CAP_SSE)) - return Resample_<BSincTag,SSETag>; -#endif - return Resample_<BSincTag,CTag>; - } - - return Resample_<PointTag,CTag>; -} - - void aluInitMixer() { if(auto resopt = ConfigValueStr(nullptr, nullptr, "resampler")) |