Source code

Revision control

Copy as Markdown

Other Tools

Test Info:

<!DOCTYPE HTML>
<html>
<head>
<title>Test tail time lifetime of DelayNode after input finishes and new input added</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="webaudio.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<pre id="test">
<script class="testbody" type="text/javascript">
SimpleTest.waitForExplicitFinish();
// The buffer source will start on a block boundary, so keeping the signal
// within one block ensures that it will not cross AudioProcessingEvent buffer
// boundaries.
const signalLength = 128;
const bufferSize = 1024;
// Delay should be long enough to allow CC to run
var delayBufferCount = 50;
var delayBufferOffset;
const delayLength = delayBufferCount * bufferSize;
var phase = "initial";
var sourceCount = 0;
var delayCount = 0;
var oscillator;
var delay;
var source;
function applySignal(buffer, offset) {
for (var i = 0; i < signalLength; ++i) {
buffer.getChannelData(0)[offset + i] = Math.cos(Math.PI * i / signalLength);
}
}
function bufferIsSilent(buffer, out) {
for (var i = 0; i < buffer.length; ++i) {
if (buffer.getChannelData(0)[i] != 0) {
if (out) {
out.soundOffset = i;
}
return false;
}
}
return true;
}
function onDelayOutput(e) {
switch(phase) {
case "initial":
// Wait for oscillator sound to exit delay
if (bufferIsSilent(e.inputBuffer))
break;
phase = "played oscillator";
break;
case "played oscillator":
// First tail time has expired. Start second source and remove references
// to the delay and connected second source.
oscillator.disconnect();
source.connect(delay);
source.start();
source = null;
delay = null;
phase = "started second source";
break;
case "second tail time":
if (delayCount == delayBufferCount) {
var ctx = e.target.context;
var expected = ctx.createBuffer(1, bufferSize, ctx.sampleRate);
applySignal(expected, delayBufferOffset);
compareBuffers(e.inputBuffer, expected);
e.target.onaudioprocess = null;
SimpleTest.finish();
}
}
delayCount++;
}
function onSourceOutput(e) {
switch(phase) {
case "started second source":
var out = {};
if (!bufferIsSilent(e.inputBuffer, out)) {
delayBufferCount += sourceCount;
delayBufferOffset = out.soundOffset;
phase = "played second source";
}
break;
case "played second source":
SpecialPowers.forceGC();
SpecialPowers.forceCC();
phase = "second tail time";
e.target.onaudioprocess = null;
}
sourceCount++;
}
function startTest() {
var ctx = new AudioContext();
var delayDuration = delayLength / ctx.sampleRate;
delay = ctx.createDelay(delayDuration);
delay.delayTime.value = delayDuration;
var processor1 = ctx.createScriptProcessor(bufferSize, 1, 0);
delay.connect(processor1);
processor1.onaudioprocess = onDelayOutput;
// Signal to trigger initial tail time reference
oscillator = ctx.createOscillator();
oscillator.start(0);
oscillator.stop(100/ctx.sampleRate);
oscillator.connect(delay);
// Short signal, not started yet, with a ScriptProcessor to detect when it
// starts. It should finish before garbage collection.
var buffer = ctx.createBuffer(1, signalLength, ctx.sampleRate);
applySignal(buffer, 0);
source = ctx.createBufferSource();
source.buffer = buffer;
var processor2 = ctx.createScriptProcessor(bufferSize, 1, 0);
source.connect(processor2);
processor2.onaudioprocess = onSourceOutput;
};
startTest();
</script>
</pre>
</body>
</html>