mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
b=956604 optimize inverse FFT scaling during convolution r=padenot
--HG-- extra : transplant_source : %FD%10%CEAnU%98w%15%9D%9E6l%A7Q1%E1V%CDD
This commit is contained in:
parent
3ef01a9b6c
commit
1c1570d60b
@ -46,7 +46,8 @@ FFTBlock* FFTBlock::CreateInterpolatedBlock(const FFTBlock& block0, const FFTBlo
|
||||
int fftSize = newBlock->FFTSize();
|
||||
nsTArray<float> buffer;
|
||||
buffer.SetLength(fftSize);
|
||||
newBlock->PerformInverseFFT(buffer.Elements());
|
||||
newBlock->GetInverseWithoutScaling(buffer.Elements());
|
||||
AudioBufferInPlaceScale(buffer.Elements(), 1.0f / fftSize, fftSize / 2);
|
||||
PodZero(buffer.Elements() + fftSize / 2, fftSize / 2);
|
||||
|
||||
// Put back into frequency domain.
|
||||
|
@ -47,13 +47,18 @@ public:
|
||||
}
|
||||
// Inverse-transform internal data and store the resulting FFTSize()
|
||||
// points in aData.
|
||||
void PerformInverseFFT(float* aData)
|
||||
void GetInverse(float* aDataOut)
|
||||
{
|
||||
GetInverseWithoutScaling(aDataOut);
|
||||
AudioBufferInPlaceScale(aDataOut, 1.0f / mFFTSize, mFFTSize);
|
||||
}
|
||||
// Inverse-transform internal frequency data and store the resulting
|
||||
// FFTSize() points in |aDataOut|. If frequency data has not already been
|
||||
// scaled, then the output will need scaling by 1/FFTSize().
|
||||
void GetInverseWithoutScaling(float* aDataOut)
|
||||
{
|
||||
EnsureIFFT();
|
||||
kiss_fftri(mIFFT, mOutputBuffer.Elements(), aData);
|
||||
for (uint32_t i = 0; i < mFFTSize; ++i) {
|
||||
aData[i] /= mFFTSize;
|
||||
}
|
||||
kiss_fftri(mIFFT, mOutputBuffer.Elements(), aDataOut);
|
||||
}
|
||||
// Inverse-transform the FFTSize()/2+1 points of data in each
|
||||
// of aRealDataIn and aImagDataIn and store the resulting
|
||||
@ -84,12 +89,17 @@ public:
|
||||
mFFTSize / 2 + 1);
|
||||
}
|
||||
|
||||
void PerformPaddedFFT(const float* aData, size_t dataSize)
|
||||
// Perform a forward FFT on |aData|, assuming zeros after dataSize samples,
|
||||
// and pre-scale the generated internal frequency domain coefficients so
|
||||
// that GetInverseWithoutScaling() can be used to transform to the time
|
||||
// domain. This is useful for convolution kernels.
|
||||
void PadAndMakeScaledDFT(const float* aData, size_t dataSize)
|
||||
{
|
||||
MOZ_ASSERT(dataSize <= FFTSize());
|
||||
nsTArray<float> paddedData;
|
||||
paddedData.SetLength(FFTSize());
|
||||
PodCopy(paddedData.Elements(), aData, dataSize);
|
||||
AudioBufferCopyWithScale(aData, 1.0f / FFTSize(),
|
||||
paddedData.Elements(), dataSize);
|
||||
PodZero(paddedData.Elements() + dataSize, mFFTSize - dataSize);
|
||||
PerformFFT(paddedData.Elements());
|
||||
}
|
||||
|
@ -88,7 +88,7 @@ void FFTConvolver::process(FFTBlock* fftKernel, const float* sourceP, float* des
|
||||
// The input buffer is now filled (get frequency-domain version)
|
||||
m_frame.PerformFFT(m_inputBuffer.Elements());
|
||||
m_frame.Multiply(*fftKernel);
|
||||
m_frame.PerformInverseFFT(m_outputBuffer.Elements());
|
||||
m_frame.GetInverseWithoutScaling(m_outputBuffer.Elements());
|
||||
|
||||
// Overlap-add 1st half from previous time
|
||||
AudioBufferAddWithScale(m_lastOverlapBuffer.Elements(), 1.0f,
|
||||
|
@ -42,6 +42,8 @@ public:
|
||||
// fftSize must be a power of two
|
||||
FFTConvolver(size_t fftSize);
|
||||
|
||||
// |fftKernel| must be pre-scaled for FFTBlock::GetInverseWithoutScaling().
|
||||
//
|
||||
// For now, with multiple calls to Process(), framesToProcess MUST add up EXACTLY to fftSize / 2
|
||||
//
|
||||
// FIXME: Later, we can do more sophisticated buffering to relax this requirement...
|
||||
|
@ -42,7 +42,7 @@ static float extractAverageGroupDelay(float* impulseP, size_t length)
|
||||
estimationFrame.PerformFFT(impulseP);
|
||||
|
||||
float frameDelay = static_cast<float>(estimationFrame.ExtractAverageGroupDelay());
|
||||
estimationFrame.PerformInverseFFT(impulseP);
|
||||
estimationFrame.GetInverse(impulseP);
|
||||
|
||||
return frameDelay;
|
||||
}
|
||||
@ -70,7 +70,7 @@ HRTFKernel::HRTFKernel(float* impulseResponse, size_t length, float sampleRate)
|
||||
}
|
||||
|
||||
m_fftFrame = new FFTBlock(fftSize);
|
||||
m_fftFrame->PerformPaddedFFT(impulseResponse, length);
|
||||
m_fftFrame->PadAndMakeScaledDFT(impulseResponse, length);
|
||||
}
|
||||
|
||||
// Interpolates two kernels with x: 0 -> 1 and returns the result.
|
||||
|
@ -49,7 +49,7 @@ ReverbConvolverStage::ReverbConvolverStage(const float* impulseResponse, size_t,
|
||||
|
||||
if (!m_directMode) {
|
||||
m_fftKernel = new FFTBlock(fftSize);
|
||||
m_fftKernel->PerformPaddedFFT(impulseResponse + stageOffset, stageLength);
|
||||
m_fftKernel->PadAndMakeScaledDFT(impulseResponse + stageOffset, stageLength);
|
||||
m_fftConvolver = new FFTConvolver(fftSize);
|
||||
} else {
|
||||
m_directKernel.SetLength(fftSize / 2);
|
||||
|
Loading…
Reference in New Issue
Block a user