bool AnalyserNode::FFTAnalysis() { float* inputBuffer; AlignedFallibleTArray<float> tmpBuffer; if (mWriteIndex == 0) { inputBuffer = mBuffer.Elements(); } else { if (!tmpBuffer.SetLength(FftSize())) { return false; } inputBuffer = tmpBuffer.Elements(); memcpy(inputBuffer, mBuffer.Elements() + mWriteIndex, sizeof(float) * (FftSize() - mWriteIndex)); memcpy(inputBuffer + FftSize() - mWriteIndex, mBuffer.Elements(), sizeof(float) * mWriteIndex); } ApplyBlackmanWindow(inputBuffer, FftSize()); mAnalysisBlock.PerformFFT(inputBuffer); // Normalize so than an input sine wave at 0dBfs registers as 0dBfs (undo FFT scaling factor). const double magnitudeScale = 1.0 / FftSize(); for (uint32_t i = 0; i < mOutputBuffer.Length(); ++i) { double scalarMagnitude = NS_hypot(mAnalysisBlock.RealData(i), mAnalysisBlock.ImagData(i)) * magnitudeScale; mOutputBuffer[i] = mSmoothingTimeConstant * mOutputBuffer[i] + (1.0 - mSmoothingTimeConstant) * scalarMagnitude; } return true; }
bool AnalyserNode::AllocateBuffer() { bool result = true; if (mBuffer.Length() != FftSize()) { if (!mBuffer.SetLength(FftSize())) { return false; } memset(mBuffer.Elements(), 0, sizeof(float) * FftSize()); mWriteIndex = 0; if (!mOutputBuffer.SetLength(FrequencyBinCount())) { return false; } memset(mOutputBuffer.Elements(), 0, sizeof(float) * FrequencyBinCount()); } return result; }
void AnalyserNode::SetFftSize(uint32_t aValue, ErrorResult& aRv) { // Disallow values that are not a power of 2 and outside the [32,2048] range if (aValue < 32 || aValue > 2048 || (aValue & (aValue - 1)) != 0) { aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR); return; } if (FftSize() != aValue) { mAnalysisBlock.SetFFTSize(aValue); AllocateBuffer(); } }