#include "config.h"
#if ENABLE(WEB_AUDIO)
#include "GainNode.h"
#include "AudioBus.h"
#include "AudioNodeInput.h"
#include "AudioNodeOutput.h"
#include "AudioUtilities.h"
#include <wtf/IsoMallocInlines.h>
namespace WebCore {
WTF_MAKE_ISO_ALLOCATED_IMPL(GainNode);
ExceptionOr<Ref<GainNode>> GainNode::create(BaseAudioContext& context, const GainOptions& options)
{
auto gainNode = adoptRef(*new GainNode(context));
auto result = gainNode->handleAudioNodeOptions(options, { 2, ChannelCountMode::Max, ChannelInterpretation::Speakers });
if (result.hasException())
return result.releaseException();
gainNode->gain().setValue(options.gain);
return gainNode;
}
GainNode::GainNode(BaseAudioContext& context)
: AudioNode(context, NodeTypeGain)
, m_sampleAccurateGainValues(AudioUtilities::renderQuantumSize) , m_gain(AudioParam::create(context, "gain"_s, 1.0, -FLT_MAX, FLT_MAX, AutomationRate::ARate))
{
addInput();
addOutput(1);
initialize();
}
void GainNode::process(size_t framesToProcess)
{
AudioBus* outputBus = output(0)->bus();
ASSERT(outputBus);
if (!isInitialized() || !input(0)->isConnected())
outputBus->zero();
else {
AudioBus* inputBus = input(0)->bus();
if (gain().hasSampleAccurateValues() && gain().automationRate() == AutomationRate::ARate) {
ASSERT(framesToProcess <= m_sampleAccurateGainValues.size());
if (framesToProcess <= m_sampleAccurateGainValues.size()) {
float* gainValues = m_sampleAccurateGainValues.data();
gain().calculateSampleAccurateValues(gainValues, framesToProcess);
outputBus->copyWithSampleAccurateGainValuesFrom(*inputBus, gainValues, framesToProcess);
}
} else {
float gain = this->gain().hasSampleAccurateValues() ? this->gain().finalValue() : this->gain().value();
if (!gain) {
outputBus->zero();
} else
outputBus->copyWithGainFrom(*inputBus, gain);
}
}
}
void GainNode::processOnlyAudioParams(size_t framesToProcess)
{
float values[AudioUtilities::renderQuantumSize];
ASSERT(framesToProcess <= AudioUtilities::renderQuantumSize);
m_gain->calculateSampleAccurateValues(values, framesToProcess);
}
void GainNode::checkNumberOfChannelsForInput(AudioNodeInput* input)
{
ASSERT(context().isAudioThread() && context().isGraphOwner());
ASSERT(input && input == this->input(0));
if (input != this->input(0))
return;
unsigned numberOfChannels = input->numberOfChannels();
if (isInitialized() && numberOfChannels != output(0)->numberOfChannels()) {
uninitialize();
}
if (!isInitialized()) {
output(0)->setNumberOfChannels(numberOfChannels);
initialize();
}
AudioNode::checkNumberOfChannelsForInput(input);
}
}
#endif // ENABLE(WEB_AUDIO)