Commit 26d2eea2 authored by rtoy's avatar rtoy Committed by Commit bot

Setting convolver buffer needs to update number of output channels

When the buffer for a ConvolverNode is set, the number of outputs
needs to be reconfigured based on the number of channels in the
response buffer.

BUG=709150
TEST=Convolver/convolver-response-4-chan.html

Review-Url: https://codereview.chromium.org/2799993002
Cr-Commit-Position: refs/heads/master@{#462888}
parent 8a996217
...@@ -96,6 +96,51 @@ ...@@ -96,6 +96,51 @@
.then(() => task.done()); .then(() => task.done());
}); });
audit.define(
{
label: 'delayed buffer set',
description: 'Delayed set of 4-channel response'
},
(task, should) => {
// Don't really care about the output for this test. It's to verify
// we don't crash in a debug build when setting the convolver buffer
// after creating the graph.
let context = new OfflineAudioContext(1, renderFrames, sampleRate);
let src = new OscillatorNode(context);
let convolver = new ConvolverNode(context, {
disableNormalization: true
});
let buffer = new AudioBuffer({
numberOfChannels: 4,
length: 4,
sampleRate: context.sampleRate
});
// Impulse responses for the convolver aren't important, as long as
// it's not all zeroes.
for (let k = 0; k < buffer.numberOfChannels; ++k) {
buffer.getChannelData(k).fill(1);
}
src.connect(convolver).connect(context.destination);
// Set the buffer after a few render quanta have passed. The actual
// value must be least one, but is otherwise arbitrary.
context.suspend(512 / context.sampleRate)
.then(() => convolver.buffer = buffer)
.then(() => context.resume());
src.start();
context.startRendering()
.then(audioBuffer => {
// Just make sure output is not silent.
should(audioBuffer.getChannelData(0),
'Output with delayed setting of convolver buffer')
.notBeConstantValueOf(0);
})
.then(() => task.done());
});
function fourChannelResponseTest(options, should) { function fourChannelResponseTest(options, should) {
// Create an 4-channel offline context. The first two channels are for // Create an 4-channel offline context. The first two channels are for
// the stereo output of the convolver and the next two channels are for // the stereo output of the convolver and the next two channels are for
......
...@@ -141,10 +141,20 @@ void ConvolverHandler::setBuffer(AudioBuffer* buffer, ...@@ -141,10 +141,20 @@ void ConvolverHandler::setBuffer(AudioBuffer* buffer,
context() && context()->hasRealtimeConstraint(), m_normalize)); context() && context()->hasRealtimeConstraint(), m_normalize));
{ {
// The context must be locked since changing the buffer can
// re-configure the number of channels that are output.
BaseAudioContext::AutoLocker contextLocker(context());
// Synchronize with process(). // Synchronize with process().
MutexLocker locker(m_processLock); MutexLocker locker(m_processLock);
m_reverb = std::move(reverb); m_reverb = std::move(reverb);
m_buffer = buffer; m_buffer = buffer;
if (buffer) {
// This will propagate the channel count to any nodes connected further
// downstream in the graph.
output(0).setNumberOfChannels(computeNumberOfOutputChannels(
input(0).numberOfChannels(), m_buffer->numberOfChannels()));
}
} }
} }
...@@ -177,6 +187,15 @@ double ConvolverHandler::latencyTime() const { ...@@ -177,6 +187,15 @@ double ConvolverHandler::latencyTime() const {
return std::numeric_limits<double>::infinity(); return std::numeric_limits<double>::infinity();
} }
unsigned ConvolverHandler::computeNumberOfOutputChannels(
unsigned inputChannels,
unsigned responseChannels) const {
// The number of output channels for a Convolver must be one or two.
// And can only be one if there's a mono source and a mono response
// buffer.
return clampTo(std::max(inputChannels, responseChannels), 1, 2);
}
void ConvolverHandler::setChannelCount(unsigned long channelCount, void ConvolverHandler::setChannelCount(unsigned long channelCount,
ExceptionState& exceptionState) { ExceptionState& exceptionState) {
DCHECK(isMainThread()); DCHECK(isMainThread());
...@@ -215,10 +234,8 @@ void ConvolverHandler::checkNumberOfChannelsForInput(AudioNodeInput* input) { ...@@ -215,10 +234,8 @@ void ConvolverHandler::checkNumberOfChannelsForInput(AudioNodeInput* input) {
return; return;
if (m_buffer) { if (m_buffer) {
unsigned numberOfChannels = input->numberOfChannels(); unsigned numberOfOutputChannels = computeNumberOfOutputChannels(
unsigned numberOfReverbeChannels = m_buffer->numberOfChannels(); input->numberOfChannels(), m_buffer->numberOfChannels());
unsigned numberOfOutputChannels =
std::min(2u, std::max(numberOfChannels, numberOfReverbeChannels));
if (isInitialized() && if (isInitialized() &&
numberOfOutputChannels != output(0).numberOfChannels()) { numberOfOutputChannels != output(0).numberOfChannels()) {
......
...@@ -65,6 +65,12 @@ class MODULES_EXPORT ConvolverHandler final : public AudioHandler { ...@@ -65,6 +65,12 @@ class MODULES_EXPORT ConvolverHandler final : public AudioHandler {
double tailTime() const override; double tailTime() const override;
double latencyTime() const override; double latencyTime() const override;
// Determine how many output channels to use from the number of
// input channels and the number of channels in the impulse response
// buffer.
unsigned computeNumberOfOutputChannels(unsigned inputChannels,
unsigned responseChannels) const;
std::unique_ptr<Reverb> m_reverb; std::unique_ptr<Reverb> m_reverb;
// This Persistent doesn't make a reference cycle including the owner // This Persistent doesn't make a reference cycle including the owner
// ConvolverNode. // ConvolverNode.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment