tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

test_stereoPannerNode.html (9818B)


      1 <!DOCTYPE HTML>
      2 <html>
      3 <head>
      4  <title>Test StereoPannerNode</title>
      5  <script src="/tests/SimpleTest/SimpleTest.js"></script>
      6  <script type="text/javascript" src="webaudio.js"></script>
      7  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
      8 </head>
      9 <body>
     10 <pre id="test">
     11 <script class="testbody" type="text/javascript">
     12 
     13 var SR = 44100;
     14 var BUF_SIZE = 128;
     15 var PANNING = 0.1;
     16 var GAIN = 0.5;
     17 
     18 // Cheap reimplementation of some bits of the spec
     19 function gainForPanningMonoToStereo(panning) {
     20  panning += 1;
     21  panning /= 2;
     22  return [ Math.cos(0.5 * Math.PI * panning),
     23           Math.sin(0.5 * Math.PI * panning) ];
     24 }
     25 
     26 function gainForPanningStereoToStereo(panning) {
     27  if (panning <= 0) {
     28    panning += 1.;
     29  }
     30  return [ Math.cos(0.5 * Math.PI * panning),
     31           Math.sin(0.5 * Math.PI * panning) ];
     32 }
     33 
     34 function applyStereoToStereoPanning(l, r, panningValues, panning) {
     35  var outL, outR;
     36  if (panning <= 0) {
     37    outL = l + r * panningValues[0];
     38    outR = r * panningValues[1];
     39  } else {
     40    outL = l * panningValues[0];
     41    outR = r + l * panningValues[1];
     42  }
     43  return [outL,outR];
     44 }
     45 
     46 function applyMonoToStereoPanning(c, panning) {
     47  return [c * panning[0], c * panning[1]];
     48 }
     49 
     50 // Test the DOM interface
     51 var context = new OfflineAudioContext(1, 1, SR);
     52 var stereoPanner = new StereoPannerNode(context);
     53 ok(stereoPanner.pan, "The AudioParam member must exist");
     54 is(stereoPanner.pan.value, 0.0, "Correct initial value");
     55 is(stereoPanner.pan.defaultValue, 0.0, "Correct default value");
     56 is(stereoPanner.channelCount, 2, "StereoPannerNode node has 2 input channels by default");
     57 is(stereoPanner.channelCountMode, "clamped-max", "Correct channelCountMode for the StereoPannerNode");
     58 is(stereoPanner.channelInterpretation, "speakers", "Correct channelCountInterpretation for the StereoPannerNode");
     59 expectException(function() {
     60  stereoPanner.channelCount = 3;
     61 }, DOMException.NOT_SUPPORTED_ERR);
     62 expectException(function() {
     63  stereoPanner.channelCountMode = "max";
     64 }, DOMException.NOT_SUPPORTED_ERR);
     65 
     66 // A sine to be used to fill the buffers
     67 function sine(t) {
     68  return Math.sin(440 * 2 * Math.PI * t / context.sampleRate);
     69 }
     70 
     71 // A couple mono and stereo buffers: the StereoPannerNode equation is different
     72 // if the input is mono or stereo
     73 var stereoBuffer = new AudioBuffer({ numberOfChannels: 2,
     74                                     length: BUF_SIZE,
     75                                     sampleRate: context.sampleRate });
     76 var monoBuffer = new AudioBuffer({ numberOfChannels: 1,
     77                                   length: BUF_SIZE,
     78                                   sampleRate: context.sampleRate });
     79 for (var i = 0; i < BUF_SIZE; ++i) {
     80  monoBuffer.getChannelData(0)[i]   =
     81  stereoBuffer.getChannelData(0)[i] =
     82  stereoBuffer.getChannelData(1)[i] = sine(i);
     83 }
     84 
     85 // Expected test vectors
     86 function expectedBufferNoop(gain) {
     87  gain = gain || 1.0;
     88  var expectedBuffer = new AudioBuffer({ numberOfChannels: 2,
     89                                         length: BUF_SIZE,
     90                                         sampleRate: SR });
     91  for (var i = 0; i < BUF_SIZE; i++) {
     92    expectedBuffer.getChannelData(0)[i] = gain * sine(i);
     93    expectedBuffer.getChannelData(1)[i] = gain * sine(i);
     94  }
     95  return expectedBuffer;
     96 }
     97 
     98 function expectedBufferForStereo(panning, gain) {
     99  gain = gain || 1.0;
    100  var expectedBuffer = new AudioBuffer({ numberOfChannels: 2,
    101                                         length: BUF_SIZE,
    102                                         sampleRate: SR });
    103  var gainPanning = gainForPanningStereoToStereo(panning);
    104  for (var i = 0; i < BUF_SIZE; i++) {
    105    var values = [ gain * sine(i), gain * sine(i) ];
    106    var processed = applyStereoToStereoPanning(values[0], values[1], gainPanning, PANNING);
    107    expectedBuffer.getChannelData(0)[i] = processed[0];
    108    expectedBuffer.getChannelData(1)[i] = processed[1];
    109  }
    110  return expectedBuffer;
    111 }
    112 
    113 function expectedBufferForMono(panning, gain) {
    114  gain = gain || 1.0;
    115  var expectedBuffer = new AudioBuffer({ numberOfChannels: 2,
    116                                         length: BUF_SIZE,
    117                                         sampleRate: SR });
    118  var gainPanning = gainForPanningMonoToStereo(panning);
    119  gainPanning[0] *= gain;
    120  gainPanning[1] *= gain;
    121  for (var i = 0; i < BUF_SIZE; i++) {
    122    var value = sine(i);
    123    var processed = applyMonoToStereoPanning(value, gainPanning);
    124    expectedBuffer.getChannelData(0)[i] = processed[0];
    125    expectedBuffer.getChannelData(1)[i] = processed[1];
    126  }
    127  return expectedBuffer;
    128 }
    129 
    130 // Actual test cases
    131 var tests = [
    132  function monoPanningNoop(ctx, panner) {
    133    var monoSource = ctx.createBufferSource();
    134    monoSource.connect(panner);
    135    monoSource.buffer = monoBuffer;
    136    monoSource.start(0);
    137    return expectedBufferForMono(0);
    138  },
    139  function stereoPanningNoop(ctx, panner) {
    140    var stereoSource = ctx.createBufferSource();
    141    stereoSource.connect(panner);
    142    stereoSource.buffer = stereoBuffer;
    143    stereoSource.start(0);
    144    return expectedBufferNoop();
    145  },
    146  function monoPanningNoopWithGain(ctx, panner) {
    147    var monoSource = ctx.createBufferSource();
    148    var gain = ctx.createGain();
    149    gain.gain.value = GAIN;
    150    monoSource.connect(gain);
    151    gain.connect(panner);
    152    monoSource.buffer = monoBuffer;
    153    monoSource.start(0);
    154    return expectedBufferForMono(0, GAIN);
    155  },
    156  function stereoPanningNoopWithGain(ctx, panner) {
    157    var stereoSource = ctx.createBufferSource();
    158    var gain = ctx.createGain();
    159    gain.gain.value = GAIN;
    160    stereoSource.connect(gain);
    161    gain.connect(panner);
    162    stereoSource.buffer = stereoBuffer;
    163    stereoSource.start(0);
    164    return expectedBufferNoop(GAIN);
    165  },
    166  function stereoPanningAutomation(ctx, panner) {
    167    var stereoSource = ctx.createBufferSource();
    168    stereoSource.connect(panner);
    169    stereoSource.buffer = stereoBuffer;
    170    panner.pan.setValueAtTime(0.1, 0.0);
    171    stereoSource.start(0);
    172    return expectedBufferForStereo(PANNING);
    173  },
    174  function stereoPanning(ctx, panner) {
    175    var stereoSource = ctx.createBufferSource();
    176    stereoSource.buffer = stereoBuffer;
    177    stereoSource.connect(panner);
    178    panner.pan.value = 0.1;
    179    stereoSource.start(0);
    180    return expectedBufferForStereo(PANNING);
    181  },
    182  function monoPanningAutomation(ctx, panner) {
    183    var monoSource = ctx.createBufferSource();
    184    monoSource.connect(panner);
    185    monoSource.buffer = monoBuffer;
    186    panner.pan.setValueAtTime(PANNING, 0.0);
    187    monoSource.start(0);
    188    return expectedBufferForMono(PANNING);
    189  },
    190  function monoPanning(ctx, panner) {
    191    var monoSource = ctx.createBufferSource();
    192    monoSource.connect(panner);
    193    monoSource.buffer = monoBuffer;
    194    panner.pan.value = 0.1;
    195    monoSource.start(0);
    196    return expectedBufferForMono(PANNING);
    197  },
    198  function monoPanningWithGain(ctx, panner) {
    199    var monoSource = ctx.createBufferSource();
    200    var gain = ctx.createGain();
    201    gain.gain.value = GAIN;
    202    monoSource.connect(gain);
    203    gain.connect(panner);
    204    monoSource.buffer = monoBuffer;
    205    panner.pan.value = 0.1;
    206    monoSource.start(0);
    207    return expectedBufferForMono(PANNING, GAIN);
    208  },
    209  function stereoPanningWithGain(ctx, panner) {
    210    var stereoSource = ctx.createBufferSource();
    211    var gain = ctx.createGain();
    212    gain.gain.value = GAIN;
    213    stereoSource.connect(gain);
    214    gain.connect(panner);
    215    stereoSource.buffer = stereoBuffer;
    216    panner.pan.value = 0.1;
    217    stereoSource.start(0);
    218    return expectedBufferForStereo(PANNING, GAIN);
    219  },
    220  function monoPanningWithGainAndAutomation(ctx, panner) {
    221    var monoSource = ctx.createBufferSource();
    222    var gain = ctx.createGain();
    223    gain.gain.value = GAIN;
    224    monoSource.connect(gain);
    225    gain.connect(panner);
    226    monoSource.buffer = monoBuffer;
    227    panner.pan.setValueAtTime(PANNING, 0);
    228    monoSource.start(0);
    229    return expectedBufferForMono(PANNING, GAIN);
    230  },
    231  function stereoPanningWithGainAndAutomation(ctx, panner) {
    232    var stereoSource = ctx.createBufferSource();
    233    var gain = ctx.createGain();
    234    gain.gain.value = GAIN;
    235    stereoSource.connect(gain);
    236    gain.connect(panner);
    237    stereoSource.buffer = stereoBuffer;
    238    panner.pan.setValueAtTime(PANNING, 0);
    239    stereoSource.start(0);
    240    return expectedBufferForStereo(PANNING, GAIN);
    241  },
    242  function bug_1783181(ctx, panner) {
    243    const length = 128;
    244    const buffer = new AudioBuffer({ length, numberOfChannels: 2, sampleRate: ctx.sampleRate });
    245 
    246    buffer.copyToChannel(new Float32Array([1, 0.5, 0, -0.5, -1]), 0);
    247    buffer.copyToChannel(new Float32Array([-0.5, -0.25, 0, 0.25, 0.5]), 1);
    248 
    249    const audioBufferSourceNode = new AudioBufferSourceNode(ctx, { buffer });
    250 
    251    audioBufferSourceNode.connect(panner);
    252 
    253    panner.pan.setValueAtTime(0.5, 0);
    254    panner.pan.setValueAtTime(0, 2 / ctx.sampleRate);
    255    panner.pan.linearRampToValueAtTime(1, 5 / ctx.sampleRate);
    256    panner.pan.cancelScheduledValues(3 / ctx.sampleRate);
    257 
    258    audioBufferSourceNode.start(0);
    259 
    260    const expected = new AudioBuffer({ length, numberOfChannels: 2, sampleRate: ctx.sampleRate });
    261    expected.copyToChannel(new Float32Array([ 0.7071067690849304, 0.3535533845424652, 0, -0.5, -1 ]), 0);
    262    expected.copyToChannel(new Float32Array([ 0.20710676908493042, 0.10355338454246521, 0, 0.25, 0.5 ]), 1);
    263 
    264    return expected;
    265  }
    266 ];
    267 
    268 var finished = 0;
    269 function finish() {
    270  if (++finished == tests.length) {
    271    SimpleTest.finish();
    272  }
    273 }
    274 
    275 tests.forEach(function(f) {
    276  var ac = new OfflineAudioContext(2, BUF_SIZE, SR);
    277  var panner = ac.createStereoPanner();
    278  panner.connect(ac.destination);
    279  var expected = f(ac, panner);
    280  ac.oncomplete = function(e) {
    281    info(f.name);
    282    compareBuffers(e.renderedBuffer, expected);
    283    finish();
    284  };
    285  ac.startRendering()
    286 });
    287 
    288 SimpleTest.waitForExplicitFinish();
    289 
    290 </script>
    291 </pre>
    292 <pre id=dump>
    293 </pre>
    294 </body>
    295 </html>