<!DOCTYPE HTML> <html> <head> <title>Test the support of cycles.</title> <script type="text/javascript" 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 src="webaudio.js" type="text/javascript"></script> <script class="testbody" type="text/javascript"> SimpleTest.waitForExplicitFinish(); const sampleRate = 48000; const inputLength = 2048; addLoadEvent(function() { function addSine(b) { for (var i = 0; i < b.length; i++) { b[i] += Math.sin(440 * 2 * Math.PI * i / sampleRate); } } function getSineBuffer(ctx) { var buffer = ctx.createBuffer(1, inputLength, ctx.sampleRate); addSine(buffer.getChannelData(0)); return buffer; } function createAndPlayWithCycleAndDelayNode(ctx, delayFrames) { var source = ctx.createBufferSource(); source.buffer = getSineBuffer(ctx); var gain = ctx.createGain(); var delay = ctx.createDelay(); delay.delayTime.value = delayFrames/ctx.sampleRate; source.connect(gain); gain.connect(delay); delay.connect(ctx.destination); // cycle delay.connect(gain); source.start(0); } function createAndPlayWithCycleAndNoDelayNode(ctx) { var source = ctx.createBufferSource(); source.loop = true; source.buffer = getSineBuffer(ctx); var gain = ctx.createGain(); var gain2 = ctx.createGain(); source.connect(gain); gain.connect(gain2); // cycle gain2.connect(gain); gain2.connect(ctx.destination); source.start(0); } function createAndPlayWithCycleAndNoDelayNodeInCycle(ctx) { var source = ctx.createBufferSource(); source.loop = true; source.buffer = getSineBuffer(ctx); var delay = ctx.createDelay(); var gain = ctx.createGain(); var gain2 = ctx.createGain(); // Their is a cycle, a delay, but the delay is not in the cycle. source.connect(delay); delay.connect(gain); gain.connect(gain2); // cycle gain2.connect(gain); gain2.connect(ctx.destination); source.start(0); } var remainingTests = 0; function finish() { if (--remainingTests == 0) { SimpleTest.finish(); } } function getOfflineContext(oncomplete) { var ctx = new OfflineAudioContext(1, sampleRate, sampleRate); ctx.oncomplete = oncomplete; return ctx; } function checkSilentBuffer(e) { var buffer = e.renderedBuffer.getChannelData(0); for (var i = 0; i < buffer.length; i++) { if (buffer[i] != 0.0) { ok(false, "buffer should be silent."); finish(); return; } } ok(true, "buffer should be silent."); finish(); } function checkNoisyBuffer(e, aDelayFrames) { delayFrames = Math.max(128, aDelayFrames); var expected = new Float32Array(e.renderedBuffer.length); for (var i = delayFrames; i < expected.length; i += delayFrames) { addSine(expected.subarray(i, i + inputLength)); } compareChannels(e.renderedBuffer.getChannelData(0), expected); finish(); } function expectSilentOutput(f) { remainingTests++; var ctx = getOfflineContext(checkSilentBuffer); f(ctx); ctx.startRendering(); } function expectNoisyOutput(delayFrames) { remainingTests++; var ctx = getOfflineContext(); ctx.oncomplete = function(e) { checkNoisyBuffer(e, delayFrames); }; createAndPlayWithCycleAndDelayNode(ctx, delayFrames); ctx.startRendering(); } // This is trying to make a graph with a cycle and no DelayNode in the graph. // The cycle subgraph should be muted, in this graph the output should be silent. expectSilentOutput(createAndPlayWithCycleAndNoDelayNode); // This is trying to make a graph with a cycle and a DelayNode in the graph, but // not part of the cycle. // The cycle subgraph should be muted, in this graph the output should be silent. expectSilentOutput(createAndPlayWithCycleAndNoDelayNodeInCycle); // Those are making legal graphs, with at least one DelayNode in the cycle. // There should be some non-silent output. expectNoisyOutput(sampleRate/4); // DelayNode.delayTime will be clamped to 128/ctx.sampleRate. // There should be some non-silent output. expectNoisyOutput(0); }); </script> </pre> </body> </html>