MultiChannelResampler.cpp [plain text]
#include "config.h"
#if ENABLE(WEB_AUDIO)
#include "MultiChannelResampler.h"
#include "AudioBus.h"
#include "SincResampler.h"
namespace WebCore {
MultiChannelResampler::MultiChannelResampler(double scaleFactor, unsigned numberOfChannels, unsigned requestFrames, Function<void(AudioBus*, size_t framesToProcess)>&& provideInput)
: m_numberOfChannels(numberOfChannels)
, m_provideInput(WTFMove(provideInput))
, m_multiChannelBus(AudioBus::create(numberOfChannels, requestFrames, false))
{
if (numberOfChannels > 1) {
m_channelsMemory.reserveInitialCapacity(numberOfChannels - 1);
for (unsigned channelIndex = 1; channelIndex < numberOfChannels; ++channelIndex) {
m_channelsMemory.uncheckedAppend(makeUnique<AudioFloatArray>(requestFrames));
m_multiChannelBus->setChannelMemory(channelIndex, m_channelsMemory.last()->data(), requestFrames);
}
}
for (unsigned channelIndex = 0; channelIndex < numberOfChannels; ++channelIndex)
m_kernels.append(makeUnique<SincResampler>(scaleFactor, requestFrames, std::bind(&MultiChannelResampler::provideInputForChannel, this, std::placeholders::_1, std::placeholders::_2, channelIndex)));
}
MultiChannelResampler::~MultiChannelResampler() = default;
void MultiChannelResampler::process(AudioBus* destination, size_t framesToProcess)
{
ASSERT(m_numberOfChannels == destination->numberOfChannels());
if (destination->numberOfChannels() == 1) {
m_kernels[0]->process(destination->channel(0)->mutableData(), framesToProcess);
return;
}
m_outputFramesReady = 0;
while (m_outputFramesReady < framesToProcess) {
size_t chunkSize = m_kernels[0]->chunkSize();
size_t framesThisTime = std::min(framesToProcess - m_outputFramesReady, chunkSize);
for (unsigned channelIndex = 0; channelIndex < m_numberOfChannels; ++channelIndex) {
ASSERT(chunkSize == m_kernels[channelIndex]->chunkSize());
m_kernels[channelIndex]->process(destination->channel(channelIndex)->mutableData() + m_outputFramesReady, framesThisTime);
}
m_outputFramesReady += framesThisTime;
}
}
void MultiChannelResampler::provideInputForChannel(float* buffer, size_t framesToProcess, unsigned channelIndex)
{
ASSERT(channelIndex < m_multiChannelBus->numberOfChannels());
ASSERT(framesToProcess == m_multiChannelBus->length());
if (!channelIndex) {
m_multiChannelBus->setChannelMemory(0, buffer, framesToProcess);
m_provideInput(m_multiChannelBus.get(), framesToProcess);
return;
}
memcpy(buffer, m_multiChannelBus->channel(channelIndex)->data(), sizeof(float) * framesToProcess);
}
}
#endif // ENABLE(WEB_AUDIO)