b=924288 continue producing BiquadFilter sound output after input becomes null r=ehsan

--HG--
extra : transplant_source : %A6%DDf%09%98C%C0%E6%AEy%F8%F6%FF%7E/f%D7%12Ub
This commit is contained in:
Karl Tomlinson 2013-10-25 14:05:42 +13:00
parent 637b876274
commit c0c070d7e0
4 changed files with 113 additions and 10 deletions

View File

@ -8,6 +8,7 @@
#include "AudioNodeEngine.h"
#include "AudioNodeStream.h"
#include "AudioDestinationNode.h"
#include "PlayingRefChangeHandler.h"
#include "WebAudioUtils.h"
#include "blink/Biquad.h"
#include "mozilla/Preferences.h"
@ -141,15 +142,47 @@ public:
AudioChunk* aOutput,
bool* aFinished) MOZ_OVERRIDE
{
float inputBuffer[WEBAUDIO_BLOCK_SIZE];
if (aInput.IsNull()) {
bool hasTail = false;
for (uint32_t i = 0; i < mBiquads.Length(); ++i) {
if (mBiquads[i].hasTail()) {
hasTail = true;
break;
}
}
if (!hasTail) {
if (!mBiquads.IsEmpty()) {
mBiquads.Clear();
nsRefPtr<PlayingRefChangeHandler> refchanged =
new PlayingRefChangeHandler(aStream, PlayingRefChangeHandler::RELEASE);
aStream->Graph()->
DispatchToMainThreadAfterStreamStateUpdate(refchanged.forget());
}
aOutput->SetNull(WEBAUDIO_BLOCK_SIZE);
return;
}
// Adjust the number of biquads based on the number of channels
const uint32_t numberOfChannels = aInput.mChannelData.Length();
mBiquads.SetLength(numberOfChannels);
PodArrayZero(inputBuffer);
} else if(mBiquads.Length() != aInput.mChannelData.Length()){
if (mBiquads.IsEmpty()) {
nsRefPtr<PlayingRefChangeHandler> refchanged =
new PlayingRefChangeHandler(aStream, PlayingRefChangeHandler::ADDREF);
aStream->Graph()->
DispatchToMainThreadAfterStreamStateUpdate(refchanged.forget());
} else { // Help people diagnose bug 924718
NS_WARNING("BiquadFilterNode channel count changes may produce audio glitches");
}
// Adjust the number of biquads based on the number of channels
mBiquads.SetLength(aInput.mChannelData.Length());
}
uint32_t numberOfChannels = mBiquads.Length();
AllocateAudioBlock(numberOfChannels, aOutput);
TrackTicks pos = aStream->GetCurrentPosition();
@ -159,13 +192,17 @@ public:
double gain = mGain.GetValueAtTime(pos);
double detune = mDetune.GetValueAtTime(pos);
float inputBuffer[WEBAUDIO_BLOCK_SIZE];
for (uint32_t i = 0; i < numberOfChannels; ++i) {
auto input = static_cast<const float*>(aInput.mChannelData[i]);
const float* input;
if (aInput.IsNull()) {
input = inputBuffer;
} else {
input = static_cast<const float*>(aInput.mChannelData[i]);
if (aInput.mVolume != 1.0) {
AudioBlockCopyChannelWithScale(input, aInput.mVolume, inputBuffer);
input = inputBuffer;
}
}
SetParamsOnBiquad(mBiquads[i], aStream->SampleRate(), mType, freq, q, gain, detune);
mBiquads[i].process(input,

View File

@ -66,6 +66,10 @@ public:
// (The zeroes will be the inverse of the poles)
void setAllpassPole(const Complex& pole);
// Return true iff the next output block will contain sound even with
// silent input.
bool hasTail() const { return m_y1 || m_y2 || m_x1 || m_x2; }
// Resets filter state
void reset();

View File

@ -47,6 +47,7 @@ support-files =
[test_audioParamTimelineDestinationOffset.html]
[test_badConnect.html]
[test_biquadFilterNode.html]
[test_biquadFilterNodeWithGain.html]
[test_bug808374.html]
[test_bug827541.html]
[test_bug839753.html]

View File

@ -0,0 +1,61 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test BiquadFilterNode after a GainNode and tail - Bugs 924286 and 924288</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<pre id="test">
<script src="webaudio.js" type="text/javascript"></script>
<script class="testbody" type="text/javascript">
const signalLength = 2048;
var gTest = {
length: signalLength,
numberOfChannels: 1,
createGraph: function(context) {
// Two oscillators scheduled sequentially
var signalDuration = signalLength / context.sampleRate;
var osc1 = context.createOscillator();
osc1.type = "square";
osc1.start(0);
osc1.stop(signalDuration / 2);
var osc2 = context.createOscillator();
osc2.start(signalDuration / 2);
osc2.stop(signalDuration);
// Comparing a biquad on each source with one on both sources checks that
// the biquad on the first source doesn't shut down early.
var biquad1 = context.createBiquadFilter();
osc1.connect(biquad1);
var biquad2 = context.createBiquadFilter();
osc2.connect(biquad2);
var gain = context.createGain();
gain.gain.value = -1;
osc1.connect(gain);
osc2.connect(gain);
var biquadWithGain = context.createBiquadFilter();
gain.connect(biquadWithGain);
// The output of biquadWithGain should be the inverse of the sum of the
// outputs of biquad1 and biquad2, so blend them together and expect
// silence.
var blend = context.createGain();
biquad1.connect(blend);
biquad2.connect(blend);
biquadWithGain.connect(blend);
return blend;
},
};
runTest();
</script>
</pre>
</body>
</html>