Skip to content

Commit

Permalink
Bug 1882685 test both panning models in test_pannerNode_maxDistance.h…
Browse files Browse the repository at this point in the history
…tml r=padenot

Depends on D203083

Differential Revision: https://phabricator.services.mozilla.com/D203084
  • Loading branch information
karlt committed Feb 29, 2024
1 parent 018b081 commit 43567d0
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 78 deletions.
1 change: 0 additions & 1 deletion dom/media/webaudio/test/test_delayNodeCycles.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
</head>
<body>
<pre id="test">
<script src="webaudio.js" type="text/javascript"></script>
<script class="testbody" type="text/javascript">

SimpleTest.waitForExplicitFinish();
Expand Down
33 changes: 1 addition & 32 deletions dom/media/webaudio/test/test_pannerNodeHRTFSymmetry.html
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,6 @@

var ctx = new AudioContext();

function isChannelSilent(channel) {
for (var i = 0; i < channel.length; ++i) {
if (channel[i] != 0.0) {
return false;
}
}
return true;
}

function startTest() {
var leftPanner = ctx.createPanner();
var rightPanner = ctx.createPanner();
Expand Down Expand Up @@ -78,29 +69,7 @@
}
}

function prepareTest() {
// A PannerNode will produce no output until it has loaded its HRIR
// database. Wait for this to load before starting the test.
var processor = ctx.createScriptProcessor(bufferSize, 2, 0);
var panner = ctx.createPanner();
panner.panningModel = "HRTF";
panner.connect(processor);
var oscillator = ctx.createOscillator();
oscillator.connect(panner);
oscillator.start(0);

processor.onaudioprocess =
function(e) {
if (isChannelSilent(e.inputBuffer.getChannelData(0)))
return;

oscillator.stop(0);
panner.disconnect();
e.target.onaudioprocess = null;
startTest();
};
}
prepareTest();
promiseHRTFReady(ctx.sampleRate).then(startTest);
</script>
</pre>
</body>
Expand Down
46 changes: 7 additions & 39 deletions dom/media/webaudio/test/test_pannerNodeTail.html
Original file line number Diff line number Diff line change
Expand Up @@ -48,24 +48,15 @@
var ccDelayBufferCount = 20;
const ccDelayLength = ccDelayBufferCount * bufferSize;

var ctx;
var ctx = new AudioContext();
var testPanners = [];
var referencePanner;
var referencePanner = new PannerNode(ctx, {panningModel: "HRTF"});
var referenceProcessCount = 0;
var referenceOutput = [new Float32Array(bufferSize),
new Float32Array(bufferSize)];
var testProcessor;
var testProcessCount = 0;

function isChannelSilent(channel) {
for (var i = 0; i < channel.length; ++i) {
if (channel[i] != 0.0) {
return false;
}
}
return true;
}

function onReferenceOutput(e) {
switch(referenceProcessCount) {

Expand Down Expand Up @@ -142,6 +133,10 @@
// and 512 is fftSize() at 48 kHz.
const expectedPannerTailTime = 0.002 * ctx.sampleRate + 512;

// Place the listener to the side of the origin, where the panners are
// positioned, to maximize delay in one ear.
ctx.listener.setPosition(1,0,0);

// Create some PannerNodes downstream from DelayNodes with delays long
// enough for their source to finish, dispatch its "ended" event
// and release its playing reference. The DelayNodes should expire their
Expand Down Expand Up @@ -198,34 +193,7 @@
testProcessor.connect(ctx.destination);
}

function prepareTest() {
ctx = new AudioContext();
// Place the listener to the side of the origin, where the panners are
// positioned, to maximize delay in one ear.
ctx.listener.setPosition(1,0,0);

// A PannerNode will produce no output until it has loaded its HRIR
// database. Wait for this to load before starting the test.
var processor = ctx.createScriptProcessor(bufferSize, 2, 0);
referencePanner = ctx.createPanner();
referencePanner.panningModel = "HRTF";
referencePanner.connect(processor);
var oscillator = ctx.createOscillator();
oscillator.connect(referencePanner);
oscillator.start(0);

processor.onaudioprocess = function(e) {
if (isChannelSilent(e.inputBuffer.getChannelData(0)))
return;

oscillator.stop(0);
oscillator.disconnect();
referencePanner.disconnect();
e.target.onaudioprocess = null;
SimpleTest.executeSoon(startTest);
};
}
prepareTest();
promiseHRTFReady(ctx.sampleRate).then(startTest);
</script>
</pre>
</body>
Expand Down
19 changes: 13 additions & 6 deletions dom/media/webaudio/test/test_pannerNode_maxDistance.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,31 @@
<head>
<title>Test PannerNode outputs silence when the distance is greater than maxDist</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<script 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">

// BUF_SIZE must be greater than HRTF delay.
const BUF_SIZE = 1024;
const sampleRate = 44100;
var types = [
"equalpower",
"HRTF"
]

async function test(type) {
var ac = new OfflineAudioContext(1, 128, 44100);
async function test(panningModel) {
var ac = new OfflineAudioContext(1, 1024, sampleRate);
var osc = ac.createOscillator();
var panner = ac.createPanner();
var panner = new PannerNode(ac, {
panningModel,
distanceModel: "linear",
maxDistance: 100,
positionY: 200,
});

panner.distanceModel = "linear";
panner.maxDistance = 100;
panner.positionY.value = 200;
ac.listener.setPosition(0, 0, 0);

osc.connect(panner);
Expand All @@ -43,6 +49,7 @@
}

add_task(async function() {
await promiseHRTFReady(sampleRate);
for (const panningModel of types) {
await test(panningModel);
}
Expand Down
45 changes: 45 additions & 0 deletions dom/media/webaudio/test/webaudio.js
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,51 @@ function getEmptyBuffer(context, length) {
);
}

function isChannelSilent(channel) {
for (var i = 0; i < channel.length; ++i) {
if (channel[i] != 0.0) {
return false;
}
}
return true;
}

const HRTFPannersByRate = new Map();
/**
* Return a promise that resolves when PannerNodes with HRTF panningModel in
* an AudioContext of the specified sample rate will be ready to produce
* non-zero output. Before the HRIR database is loaded, such PannerNodes
* produce zero output.
*/
async function promiseHRTFReady(sampleRate) {
if (HRTFPannersByRate.has(sampleRate)) {
return;
}

const ctx = new AudioContext({ sampleRate });
const processor = ctx.createScriptProcessor(4096, 2, 0);
const panner = new PannerNode(ctx, { panningModel: "HRTF" });
panner.connect(processor);
const oscillator = ctx.createOscillator();
oscillator.connect(panner);
oscillator.start(0);

await new Promise(r => {
processor.onaudioprocess = e => {
if (!isChannelSilent(e.inputBuffer.getChannelData(0))) {
r();
}
};
});

ctx.suspend();
oscillator.disconnect();
panner.disconnect();
processor.onaudioprocess = null;
// Keep a reference to the panner so that the database is not unloaded.
HRTFPannersByRate.set(sampleRate, panner);
}

/**
* This function assumes that the test file defines a single gTest variable with
* the following properties and methods:
Expand Down

0 comments on commit 43567d0

Please sign in to comment.