update openal

This commit is contained in:
AzaezelX 2024-06-30 14:35:57 -05:00
parent 62f3b93ff9
commit 6721a6b021
287 changed files with 33851 additions and 27325 deletions

View file

@ -25,22 +25,23 @@
#include <cmath>
#include <complex>
#include <cstdlib>
#include <iterator>
#include <variant>
#include "alc/effects/base.h"
#include "alcomplex.h"
#include "almalloc.h"
#include "alnumbers.h"
#include "alnumeric.h"
#include "alspan.h"
#include "core/ambidefs.h"
#include "core/bufferline.h"
#include "core/devformat.h"
#include "core/device.h"
#include "core/effects/base.h"
#include "core/effectslot.h"
#include "core/mixer.h"
#include "core/mixer/defs.h"
#include "intrusive_ptr.h"
#include "pffft.h"
struct BufferStorage;
struct ContextBase;
@ -58,7 +59,7 @@ constexpr size_t StftStep{StftSize / OversampleFactor};
/* Define a Hann window, used to filter the STFT input and output. */
struct Windower {
alignas(16) std::array<float,StftSize> mData;
alignas(16) std::array<float,StftSize> mData{};
Windower()
{
@ -82,27 +83,29 @@ struct FrequencyBin {
struct PshifterState final : public EffectState {
/* Effect parameters */
size_t mCount;
size_t mPos;
uint mPitchShiftI;
float mPitchShift;
size_t mCount{};
size_t mPos{};
uint mPitchShiftI{};
float mPitchShift{};
/* Effects buffers */
std::array<float,StftSize> mFIFO;
std::array<float,StftHalfSize+1> mLastPhase;
std::array<float,StftHalfSize+1> mSumPhase;
std::array<float,StftSize> mOutputAccum;
std::array<float,StftSize> mFIFO{};
std::array<float,StftHalfSize+1> mLastPhase{};
std::array<float,StftHalfSize+1> mSumPhase{};
std::array<float,StftSize> mOutputAccum{};
std::array<complex_f,StftSize> mFftBuffer;
PFFFTSetup mFft;
alignas(16) std::array<float,StftSize> mFftBuffer{};
alignas(16) std::array<float,StftSize> mFftWorkBuffer{};
std::array<FrequencyBin,StftHalfSize+1> mAnalysisBuffer;
std::array<FrequencyBin,StftHalfSize+1> mSynthesisBuffer;
std::array<FrequencyBin,StftHalfSize+1> mAnalysisBuffer{};
std::array<FrequencyBin,StftHalfSize+1> mSynthesisBuffer{};
alignas(16) FloatBufferLine mBufferOut;
alignas(16) FloatBufferLine mBufferOut{};
/* Effect gains for each output channel */
float mCurrentGains[MaxAmbiChannels];
float mTargetGains[MaxAmbiChannels];
std::array<float,MaxAmbiChannels> mCurrentGains{};
std::array<float,MaxAmbiChannels> mTargetGains{};
void deviceUpdate(const DeviceBase *device, const BufferStorage *buffer) override;
@ -110,8 +113,6 @@ struct PshifterState final : public EffectState {
const EffectTarget target) override;
void process(const size_t samplesToDo, const al::span<const FloatBufferLine> samplesIn,
const al::span<FloatBufferLine> samplesOut) override;
DEF_NEWDEL(PshifterState)
};
void PshifterState::deviceUpdate(const DeviceBase*, const BufferStorage*)
@ -126,26 +127,31 @@ void PshifterState::deviceUpdate(const DeviceBase*, const BufferStorage*)
mLastPhase.fill(0.0f);
mSumPhase.fill(0.0f);
mOutputAccum.fill(0.0f);
mFftBuffer.fill(complex_f{});
mFftBuffer.fill(0.0f);
mAnalysisBuffer.fill(FrequencyBin{});
mSynthesisBuffer.fill(FrequencyBin{});
std::fill(std::begin(mCurrentGains), std::end(mCurrentGains), 0.0f);
std::fill(std::begin(mTargetGains), std::end(mTargetGains), 0.0f);
mCurrentGains.fill(0.0f);
mTargetGains.fill(0.0f);
if(!mFft)
mFft = PFFFTSetup{StftSize, PFFFT_REAL};
}
void PshifterState::update(const ContextBase*, const EffectSlot *slot,
const EffectProps *props, const EffectTarget target)
const EffectProps *props_, const EffectTarget target)
{
const int tune{props->Pshifter.CoarseTune*100 + props->Pshifter.FineTune};
auto &props = std::get<PshifterProps>(*props_);
const int tune{props.CoarseTune*100 + props.FineTune};
const float pitch{std::pow(2.0f, static_cast<float>(tune) / 1200.0f)};
mPitchShiftI = clampu(fastf2u(pitch*MixerFracOne), MixerFracHalf, MixerFracOne*2);
mPitchShiftI = std::clamp(fastf2u(pitch*MixerFracOne), uint{MixerFracHalf},
uint{MixerFracOne}*2u);
mPitchShift = static_cast<float>(mPitchShiftI) * float{1.0f/MixerFracOne};
static constexpr auto coeffs = CalcDirectionCoeffs({0.0f, 0.0f, -1.0f});
static constexpr auto coeffs = CalcDirectionCoeffs(std::array{0.0f, 0.0f, -1.0f});
mOutTarget = target.Main->Buffer;
ComputePanGains(target.Main, coeffs.data(), slot->Gain, mTargetGains);
ComputePanGains(target.Main, coeffs, slot->Gain, mTargetGains);
}
void PshifterState::process(const size_t samplesToDo,
@ -162,7 +168,7 @@ void PshifterState::process(const size_t samplesToDo,
for(size_t base{0u};base < samplesToDo;)
{
const size_t todo{minz(StftStep-mCount, samplesToDo-base)};
const size_t todo{std::min(StftStep-mCount, samplesToDo-base)};
/* Retrieve the output samples from the FIFO and fill in the new input
* samples.
@ -186,15 +192,19 @@ void PshifterState::process(const size_t samplesToDo,
mFftBuffer[k] = mFIFO[src] * gWindow.mData[k];
for(size_t src{0u}, k{StftSize-mPos};src < mPos;++src,++k)
mFftBuffer[k] = mFIFO[src] * gWindow.mData[k];
forward_fft(al::as_span(mFftBuffer));
mFft.transform_ordered(mFftBuffer.data(), mFftBuffer.data(), mFftWorkBuffer.data(),
PFFFT_FORWARD);
/* Analyze the obtained data. Since the real FFT is symmetric, only
* StftHalfSize+1 samples are needed.
*/
for(size_t k{0u};k < StftHalfSize+1;k++)
for(size_t k{0u};k < StftHalfSize+1;++k)
{
const float magnitude{std::abs(mFftBuffer[k])};
const float phase{std::arg(mFftBuffer[k])};
const auto cplx = (k == 0) ? complex_f{mFftBuffer[0]} :
(k == StftHalfSize) ? complex_f{mFftBuffer[1]} :
complex_f{mFftBuffer[k*2], mFftBuffer[k*2 + 1]};
const float magnitude{std::abs(cplx)};
const float phase{std::arg(cplx)};
/* Compute the phase difference from the last update and subtract
* the expected phase difference for this bin.
@ -232,8 +242,8 @@ void PshifterState::process(const size_t samplesToDo,
*/
std::fill(mSynthesisBuffer.begin(), mSynthesisBuffer.end(), FrequencyBin{});
constexpr size_t bin_limit{((StftHalfSize+1)<<MixerFracBits) - MixerFracHalf - 1};
const size_t bin_count{minz(StftHalfSize+1, bin_limit/mPitchShiftI + 1)};
static constexpr size_t bin_limit{((StftHalfSize+1)<<MixerFracBits) - MixerFracHalf - 1};
const size_t bin_count{std::min(StftHalfSize+1, bin_limit/mPitchShiftI + 1)};
for(size_t k{0u};k < bin_count;k++)
{
const size_t j{(k*mPitchShiftI + MixerFracHalf) >> MixerFracBits};
@ -266,21 +276,29 @@ void PshifterState::process(const size_t samplesToDo,
tmp -= static_cast<float>(qpd + (qpd%2));
mSumPhase[k] = tmp * al::numbers::pi_v<float>;
mFftBuffer[k] = std::polar(mSynthesisBuffer[k].Magnitude, mSumPhase[k]);
const complex_f cplx{std::polar(mSynthesisBuffer[k].Magnitude, mSumPhase[k])};
if(k == 0)
mFftBuffer[0] = cplx.real();
else if(k == StftHalfSize)
mFftBuffer[1] = cplx.real();
else
{
mFftBuffer[k*2 + 0] = cplx.real();
mFftBuffer[k*2 + 1] = cplx.imag();
}
}
for(size_t k{StftHalfSize+1};k < StftSize;++k)
mFftBuffer[k] = std::conj(mFftBuffer[StftSize-k]);
/* Apply an inverse FFT to get the time-domain signal, and accumulate
* for the output with windowing.
*/
inverse_fft(al::as_span(mFftBuffer));
mFft.transform_ordered(mFftBuffer.data(), mFftBuffer.data(), mFftWorkBuffer.data(),
PFFFT_BACKWARD);
static constexpr float scale{3.0f / OversampleFactor / StftSize};
for(size_t dst{mPos}, k{0u};dst < StftSize;++dst,++k)
mOutputAccum[dst] += gWindow.mData[k]*mFftBuffer[k].real() * scale;
mOutputAccum[dst] += gWindow.mData[k]*mFftBuffer[k] * scale;
for(size_t dst{0u}, k{StftSize-mPos};dst < mPos;++dst,++k)
mOutputAccum[dst] += gWindow.mData[k]*mFftBuffer[k].real() * scale;
mOutputAccum[dst] += gWindow.mData[k]*mFftBuffer[k] * scale;
/* Copy out the accumulated result, then clear for the next iteration. */
std::copy_n(mOutputAccum.begin() + mPos, StftStep, mFIFO.begin() + mPos);
@ -288,8 +306,8 @@ void PshifterState::process(const size_t samplesToDo,
}
/* Now, mix the processed sound data to the output. */
MixSamples({mBufferOut.data(), samplesToDo}, samplesOut, mCurrentGains, mTargetGains,
maxz(samplesToDo, 512), 0);
MixSamples(al::span{mBufferOut}.first(samplesToDo), samplesOut, mCurrentGains, mTargetGains,
std::max(samplesToDo, 512_uz), 0);
}