ChannelMergerNode.cpp [plain text]
#include "config.h"
#if ENABLE(WEB_AUDIO)
#include "ChannelMergerNode.h"
#include "AudioContext.h"
#include "AudioNodeInput.h"
#include "AudioNodeOutput.h"
#include <wtf/IsoMallocInlines.h>
const unsigned DefaultNumberOfOutputChannels = 1;
namespace WebCore {
WTF_MAKE_ISO_ALLOCATED_IMPL(ChannelMergerNode);
ExceptionOr<Ref<ChannelMergerNode>> ChannelMergerNode::create(BaseAudioContext& context, const ChannelMergerOptions& options)
{
if (context.isStopped())
return Exception { InvalidStateError };
context.lazyInitialize();
if (options.numberOfInputs > AudioContext::maxNumberOfChannels() || !options.numberOfInputs)
return Exception { IndexSizeError, "Number of inputs is not in the allowed range."_s };
auto merger = adoptRef(*new ChannelMergerNode(context, context.sampleRate(), options.numberOfInputs));
auto result = merger->setChannelCount(options.channelCount.valueOr(1));
if (result.hasException())
return result.releaseException();
result = merger->setChannelCountMode(options.channelCountMode.valueOr(ChannelCountMode::Explicit));
if (result.hasException())
return result.releaseException();
result = merger->setChannelInterpretation(options.channelInterpretation.valueOr(ChannelInterpretation::Speakers));
if (result.hasException())
return result.releaseException();
return merger;
}
ChannelMergerNode::ChannelMergerNode(BaseAudioContext& context, float sampleRate, unsigned numberOfInputs)
: AudioNode(context, sampleRate)
, m_desiredNumberOfOutputChannels(DefaultNumberOfOutputChannels)
{
setNodeType(NodeTypeChannelMerger);
for (unsigned i = 0; i < numberOfInputs; ++i)
addInput(makeUnique<AudioNodeInput>(this));
addOutput(makeUnique<AudioNodeOutput>(this, 1));
initialize();
}
void ChannelMergerNode::process(size_t framesToProcess)
{
AudioNodeOutput* output = this->output(0);
ASSERT(output);
ASSERT_UNUSED(framesToProcess, framesToProcess == output->bus()->length());
if (m_desiredNumberOfOutputChannels != output->numberOfChannels()) {
output->bus()->zero();
return;
}
unsigned outputChannelIndex = 0;
for (unsigned i = 0; i < numberOfInputs(); ++i) {
AudioNodeInput* input = this->input(i);
if (input->isConnected()) {
unsigned numberOfInputChannels = input->bus()->numberOfChannels();
for (unsigned j = 0; j < numberOfInputChannels; ++j) {
AudioChannel* inputChannel = input->bus()->channel(j);
AudioChannel* outputChannel = output->bus()->channel(outputChannelIndex);
outputChannel->copyFrom(inputChannel);
++outputChannelIndex;
}
}
}
ASSERT(outputChannelIndex == output->numberOfChannels());
}
void ChannelMergerNode::reset()
{
}
void ChannelMergerNode::checkNumberOfChannelsForInput(AudioNodeInput* input)
{
ASSERT(context().isAudioThread() && context().isGraphOwner());
unsigned numberOfOutputChannels = 0;
for (unsigned i = 0; i < numberOfInputs(); ++i) {
AudioNodeInput* input = this->input(i);
if (input->isConnected())
numberOfOutputChannels += input->numberOfChannels();
}
AudioNodeOutput* output = this->output(0);
ASSERT(output);
output->setNumberOfChannels(numberOfOutputChannels);
m_desiredNumberOfOutputChannels = numberOfOutputChannels;
AudioNode::checkNumberOfChannelsForInput(input);
}
ExceptionOr<void> ChannelMergerNode::setChannelCount(unsigned channelCount)
{
if (channelCount != 1)
return Exception { InvalidStateError, "Channel count cannot be changed from 1."_s };
return AudioNode::setChannelCount(channelCount);
}
ExceptionOr<void> ChannelMergerNode::setChannelCountMode(ChannelCountMode mode)
{
if (mode != ChannelCountMode::Explicit)
return Exception { InvalidStateError, "Channel count mode cannot be changed from explicit."_s };
return AudioNode::setChannelCountMode(mode);
}
}
#endif // ENABLE(WEB_AUDIO)