content/media/webaudio/test/webaudio.js

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 // Helpers for Web Audio tests
     3 function expectException(func, exceptionCode) {
     4   var threw = false;
     5   try {
     6     func();
     7   } catch (ex) {
     8     threw = true;
     9     ok(ex instanceof DOMException, "Expect a DOM exception");
    10     is(ex.code, exceptionCode, "Expect the correct exception code");
    11   }
    12   ok(threw, "The exception was thrown");
    13 }
    15 function expectNoException(func) {
    16   var threw = false;
    17   try {
    18     func();
    19   } catch (ex) {
    20     threw = true;
    21   }
    22   ok(!threw, "An exception was not thrown");
    23 }
    25 function expectTypeError(func) {
    26   var threw = false;
    27   try {
    28     func();
    29   } catch (ex) {
    30     threw = true;
    31     ok(ex instanceof TypeError, "Expect a TypeError");
    32   }
    33   ok(threw, "The exception was thrown");
    34 }
    36 function fuzzyCompare(a, b) {
    37   return Math.abs(a - b) < 9e-3;
    38 }
    40 function compareChannels(buf1, buf2,
    41                         /*optional*/ length,
    42                         /*optional*/ sourceOffset,
    43                         /*optional*/ destOffset,
    44                         /*optional*/ skipLengthCheck) {
    45   if (!skipLengthCheck) {
    46     is(buf1.length, buf2.length, "Channels must have the same length");
    47   }
    48   sourceOffset = sourceOffset || 0;
    49   destOffset = destOffset || 0;
    50   if (length == undefined) {
    51     length = buf1.length - sourceOffset;
    52   }
    53   var difference = 0;
    54   var maxDifference = 0;
    55   var firstBadIndex = -1;
    56   for (var i = 0; i < length; ++i) {
    57     if (!fuzzyCompare(buf1[i + sourceOffset], buf2[i + destOffset])) {
    58       difference++;
    59       maxDifference = Math.max(maxDifference, Math.abs(buf1[i + sourceOffset] - buf2[i + destOffset]));
    60       if (firstBadIndex == -1) {
    61         firstBadIndex = i;
    62       }
    63     }
    64   };
    66   is(difference, 0, "maxDifference: " + maxDifference +
    67      ", first bad index: " + firstBadIndex +
    68      " with test-data offset " + sourceOffset + " and expected-data offset " +
    69      destOffset + "; corresponding values " + buf1[firstBadIndex + sourceOffset] +
    70      " and " + buf2[firstBadIndex + destOffset] + " --- differences");
    71 }
    73 function compareBuffers(got, expected) {
    74   if (got.numberOfChannels != expected.numberOfChannels) {
    75     is(got.numberOfChannels, expected.numberOfChannels,
    76        "Correct number of buffer channels");
    77     return;
    78   }
    79   if (got.length != expected.length) {
    80     is(got.length, expected.length,
    81        "Correct buffer length");
    82     return;
    83   }
    84   if (got.sampleRate != expected.sampleRate) {
    85     is(got.sampleRate, expected.sampleRate,
    86        "Correct sample rate");
    87     return;
    88   }
    90   for (var i = 0; i < got.numberOfChannels; ++i) {
    91     compareChannels(got.getChannelData(i), expected.getChannelData(i),
    92                     got.length, 0, 0, true);
    93   }
    94 }
    96 function getEmptyBuffer(context, length) {
    97   return context.createBuffer(gTest.numberOfChannels, length, context.sampleRate);
    98 }
   100 /**
   101  * This function assumes that the test file defines a single gTest variable with
   102  * the following properties and methods:
   103  *
   104  * + numberOfChannels: optional property which specifies the number of channels
   105  *                     in the output.  The default value is 2.
   106  * + createGraph: mandatory method which takes a context object and does
   107  *                everything needed in order to set up the Web Audio graph.
   108  *                This function returns the node to be inspected.
   109  * + createGraphAsync: async version of createGraph.  This function takes
   110  *                     a callback which should be called with an argument
   111  *                     set to the node to be inspected when the callee is
   112  *                     ready to proceed with the test.  Either this function
   113  *                     or createGraph must be provided.
   114  * + createExpectedBuffers: optional method which takes a context object and
   115  *                          returns either one expected buffer or an array of
   116  *                          them, designating what is expected to be observed
   117  *                          in the output.  If omitted, the output is expected
   118  *                          to be silence.  All buffers must have the same
   119  *                          length, which must be a bufferSize supported by
   120  *                          ScriptProcessorNode.  This function is guaranteed
   121  *                          to be called before createGraph.
   122  * + length: property equal to the total number of frames which we are waiting
   123  *           to see in the output, mandatory if createExpectedBuffers is not
   124  *           provided, in which case it must be a bufferSize supported by
   125  *           ScriptProcessorNode (256, 512, 1024, 2048, 4096, 8192, or 16384).
   126  *           If createExpectedBuffers is provided then this must be equal to
   127  *           the number of expected buffers * the expected buffer length.
   128  *
   129  * + skipOfflineContextTests: optional. when true, skips running tests on an offline
   130  *                            context by circumventing testOnOfflineContext.
   131  */
   132 function runTest()
   133 {
   134   function done() {
   135     SimpleTest.finish();
   136   }
   138   SimpleTest.waitForExplicitFinish();
   139   function runTestFunction () {
   140     if (!gTest.numberOfChannels) {
   141       gTest.numberOfChannels = 2; // default
   142     }
   144     var testLength;
   146     function runTestOnContext(context, callback, testOutput) {
   147       if (!gTest.createExpectedBuffers) {
   148         // Assume that the output is silence
   149         var expectedBuffers = getEmptyBuffer(context, gTest.length);
   150       } else {
   151         var expectedBuffers = gTest.createExpectedBuffers(context);
   152       }
   153       if (!(expectedBuffers instanceof Array)) {
   154         expectedBuffers = [expectedBuffers];
   155       }
   156       var expectedFrames = 0;
   157       for (var i = 0; i < expectedBuffers.length; ++i) {
   158         is(expectedBuffers[i].numberOfChannels, gTest.numberOfChannels,
   159            "Correct number of channels for expected buffer " + i);
   160         expectedFrames += expectedBuffers[i].length;
   161       }
   162       if (gTest.length && gTest.createExpectedBuffers) {
   163         is(expectedFrames, gTest.length, "Correct number of expected frames");
   164       }
   166       if (gTest.createGraphAsync) {
   167         gTest.createGraphAsync(context, function(nodeToInspect) {
   168           testOutput(nodeToInspect, expectedBuffers, callback);
   169         });
   170       } else {
   171         testOutput(gTest.createGraph(context), expectedBuffers, callback);
   172       }
   173     }
   175     function testOnNormalContext(callback) {
   176       function testOutput(nodeToInspect, expectedBuffers, callback) {
   177         testLength = 0;
   178         var sp = context.createScriptProcessor(expectedBuffers[0].length, gTest.numberOfChannels);
   179         nodeToInspect.connect(sp);
   180         sp.connect(context.destination);
   181         sp.onaudioprocess = function(e) {
   182           var expectedBuffer = expectedBuffers.shift();
   183           testLength += expectedBuffer.length;
   184           compareBuffers(e.inputBuffer, expectedBuffer);
   185           if (expectedBuffers.length == 0) {
   186             sp.onaudioprocess = null;
   187             callback();
   188           }
   189         };
   190       }
   191       var context = new AudioContext();
   192       runTestOnContext(context, callback, testOutput);
   193     }
   195     function testOnOfflineContext(callback, sampleRate) {
   196       function testOutput(nodeToInspect, expectedBuffers, callback) {
   197         nodeToInspect.connect(context.destination);
   198         context.oncomplete = function(e) {
   199           var samplesSeen = 0;
   200           while (expectedBuffers.length) {
   201             var expectedBuffer = expectedBuffers.shift();
   202             is(e.renderedBuffer.numberOfChannels, expectedBuffer.numberOfChannels,
   203                "Correct number of input buffer channels");
   204             for (var i = 0; i < e.renderedBuffer.numberOfChannels; ++i) {
   205               compareChannels(e.renderedBuffer.getChannelData(i),
   206                              expectedBuffer.getChannelData(i),
   207                              expectedBuffer.length,
   208                              samplesSeen,
   209                              undefined,
   210                              true);
   211             }
   212             samplesSeen += expectedBuffer.length;
   213           }
   214           callback();
   215         };
   216         context.startRendering();
   217       }
   219       var context = new OfflineAudioContext(gTest.numberOfChannels, testLength, sampleRate);
   220       runTestOnContext(context, callback, testOutput);
   221     }
   223     testOnNormalContext(function() {
   224       if (!gTest.skipOfflineContextTests) {
   225         testOnOfflineContext(function() {
   226           testOnOfflineContext(done, 44100);
   227         }, 48000);
   228       } else {
   229         done();
   230       }
   231     });
   232   };
   234   if (document.readyState !== 'complete') {
   235     addLoadEvent(runTestFunction);
   236   } else {
   237     runTestFunction();
   238   }
   239 }

mercurial