Bug 1276483 - Fix WaveShaper when connected from a silent GainNode; r?padenot
MozReview-Commit-ID: CUEO6PDwo5B
--- a/dom/media/webaudio/WaveShaperNode.cpp
+++ b/dom/media/webaudio/WaveShaperNode.cpp
@@ -217,37 +217,58 @@ public:
void ProcessBlock(AudioNodeStream* aStream,
GraphTime aFrom,
const AudioBlock& aInput,
AudioBlock* aOutput,
bool* aFinished) override
{
uint32_t channelCount = aInput.ChannelCount();
- if (!mCurve.Length() || !channelCount) {
- // Optimize the case where we don't have a curve buffer,
- // or the input is null.
+ if (!mCurve.Length()) {
+ // Optimize the case where we don't have a curve buffer
*aOutput = aInput;
return;
}
+ // If the input is null, check to see if non-null output will be produced
+ bool nullInput = false;
+ if (channelCount == 0) {
+ float index = (mCurve.Length() - 1) * 0.5;
+ uint32_t indexLower = index;
+ uint32_t indexHigher = indexLower + 1;
+ float interpolationFactor = index - indexLower;
+ if ((1.0f - interpolationFactor) * mCurve[indexLower] +
+ interpolationFactor * mCurve[indexHigher] == 0.0) {
+ *aOutput = aInput;
+ return;
+ } else {
+ nullInput = true;
+ channelCount = 1;
+ }
+ }
+
aOutput->AllocateChannels(channelCount);
for (uint32_t i = 0; i < channelCount; ++i) {
const float* inputSamples;
float scaledInput[WEBAUDIO_BLOCK_SIZE + 4];
float* alignedScaledInput = ALIGNED16(scaledInput);
ASSERT_ALIGNED16(alignedScaledInput);
- if (aInput.mVolume != 1.0f) {
- AudioBlockCopyChannelWithScale(
- static_cast<const float*>(aInput.mChannelData[i]),
- aInput.mVolume,
- alignedScaledInput);
+ if (!nullInput) {
+ if (aInput.mVolume != 1.0f) {
+ AudioBlockCopyChannelWithScale(
+ static_cast<const float*>(aInput.mChannelData[i]),
+ aInput.mVolume,
+ alignedScaledInput);
+ inputSamples = alignedScaledInput;
+ } else {
+ inputSamples = static_cast<const float*>(aInput.mChannelData[i]);
+ }
+ } else {
+ PodZero(alignedScaledInput);
inputSamples = alignedScaledInput;
- } else {
- inputSamples = static_cast<const float*>(aInput.mChannelData[i]);
}
float* outputBuffer = aOutput->ChannelFloatsForWrite(i);
float* sampleBuffer;
switch (mType) {
case OverSampleType::None:
mResampler.Reset(channelCount, aStream->SampleRate(), OverSampleType::None);
ProcessCurve<1>(inputSamples, outputBuffer);
--- a/dom/media/webaudio/test/test_waveShaperGain.html
+++ b/dom/media/webaudio/test/test_waveShaperGain.html
@@ -37,15 +37,36 @@ for (var i = 0; i < 2; i++) {
dc.connect(gain);
dc.start();
gain.gain.value = 0.5;
context.startRendering().then(buffer => {
document.querySelector("pre").innerHTML = buffer.getChannelData(0)[0];
ok(buffer.getChannelData(0)[0] == 1.0, "Volume was handled properly");
- SimpleTest.finish();
+
+ context = new OfflineAudioContext(1, 100, samplerate);
+ var oscillator = context.createOscillator();
+ var gain = context.createGain();
+ var waveShaper = context.createWaveShaper();
+
+ oscillator.start(0);
+ oscillator.connect(gain);
+
+ // to silence
+ gain.gain.value = 0;
+ gain.connect(waveShaper);
+
+ // convert all signal into 1.0
+ waveShaper.curve = new Float32Array([ 1, 1 ]);
+ waveShaper.connect(context.destination);
+
+ context.startRendering().then((buffer) => {
+ var result = buffer.getChannelData(0);
+ ok(result.every(x => x === 1), "WaveShaper handles zero gain properly");
+ SimpleTest.finish();
+ });
});
</script>
<pre>
</pre>
</body>