BiquadProcessor.cpp [plain text]
#include "config.h"
#if ENABLE(WEB_AUDIO)
#include "BiquadProcessor.h"
#include "AudioUtilities.h"
#include "BiquadDSPKernel.h"
namespace WebCore {
BiquadProcessor::BiquadProcessor(BaseAudioContext& context, float sampleRate, size_t numberOfChannels, bool autoInitialize)
: AudioDSPKernelProcessor(sampleRate, numberOfChannels)
, m_parameter1(AudioParam::create(context, "frequency", 350.0, 0.0, 0.5 * sampleRate, AutomationRate::ARate))
, m_parameter2(AudioParam::create(context, "Q", 1, -FLT_MAX, FLT_MAX, AutomationRate::ARate))
, m_parameter3(AudioParam::create(context, "gain", 0.0, -FLT_MAX, 40 * std::log10(std::numeric_limits<float>::max()), AutomationRate::ARate))
, m_parameter4(AudioParam::create(context, "detune", 0.0, -153600, 153600, AutomationRate::ARate))
{
if (autoInitialize)
initialize();
}
BiquadProcessor::~BiquadProcessor()
{
if (isInitialized())
uninitialize();
}
std::unique_ptr<AudioDSPKernel> BiquadProcessor::createKernel()
{
return makeUnique<BiquadDSPKernel>(this);
}
void BiquadProcessor::checkForDirtyCoefficients()
{
m_filterCoefficientsDirty = false;
m_hasSampleAccurateValues = false;
if (m_parameter1->hasSampleAccurateValues() || m_parameter2->hasSampleAccurateValues() || m_parameter3->hasSampleAccurateValues() || m_parameter4->hasSampleAccurateValues()) {
m_filterCoefficientsDirty = true;
m_hasSampleAccurateValues = true;
m_shouldUseARate = m_parameter1->automationRate() == AutomationRate::ARate
|| m_parameter2->automationRate() == AutomationRate::ARate
|| m_parameter3->automationRate() == AutomationRate::ARate
|| m_parameter4->automationRate() == AutomationRate::ARate;
} else {
if (m_hasJustReset) {
m_parameter1->resetSmoothedValue();
m_parameter2->resetSmoothedValue();
m_parameter3->resetSmoothedValue();
m_parameter4->resetSmoothedValue();
m_filterCoefficientsDirty = true;
m_hasJustReset = false;
} else {
bool isStable1 = m_parameter1->smooth();
bool isStable2 = m_parameter2->smooth();
bool isStable3 = m_parameter3->smooth();
bool isStable4 = m_parameter4->smooth();
if (!(isStable1 && isStable2 && isStable3 && isStable4))
m_filterCoefficientsDirty = true;
}
}
}
void BiquadProcessor::process(const AudioBus* source, AudioBus* destination, size_t framesToProcess)
{
if (!isInitialized()) {
destination->zero();
return;
}
checkForDirtyCoefficients();
for (unsigned i = 0; i < m_kernels.size(); ++i)
m_kernels[i]->process(source->channel(i)->data(), destination->channel(i)->mutableData(), framesToProcess);
}
void BiquadProcessor::processOnlyAudioParams(size_t framesToProcess)
{
float values[AudioUtilities::renderQuantumSize];
ASSERT(framesToProcess <= AudioUtilities::renderQuantumSize);
m_parameter1->calculateSampleAccurateValues(values, framesToProcess);
m_parameter2->calculateSampleAccurateValues(values, framesToProcess);
m_parameter3->calculateSampleAccurateValues(values, framesToProcess);
m_parameter4->calculateSampleAccurateValues(values, framesToProcess);
}
void BiquadProcessor::setType(BiquadFilterType type)
{
if (type != m_type) {
m_type = type;
reset(); }
}
void BiquadProcessor::getFrequencyResponse(unsigned nFrequencies, const float* frequencyHz, float* magResponse, float* phaseResponse)
{
auto responseKernel = makeUnique<BiquadDSPKernel>(this);
float cutoffFrequency = parameter1().value();
float q = parameter2().value();
float gain = parameter3().value();
float detune = parameter4().value();
responseKernel->updateCoefficients(1, &cutoffFrequency, &q, &gain, &detune);
responseKernel->getFrequencyResponse(nFrequencies, frequencyHz, magResponse, phaseResponse);
}
}
#endif // ENABLE(WEB_AUDIO)