Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

166
Views
Implement 360 degree rotation audio using Web Audio API

What I'm currently trying to implement is 360 degree rotation audio (I don't know the exact term for it--maybe 8d audio?) using PannerNode.

As far as I think, what I need to do is just rotate the position of PannerNode around y axis, with AudioListener being at (0, 0, 0).

But the result sounds like the audio is not changed at all. The below is my code.

const $fileInput = document.createElement('input');
$fileInput.setAttribute('type', 'file');
document.body.appendChild($fileInput);

const $audio = document.createElement('audio');
$audio.setAttribute('controls', true);
document.body.appendChild($audio);

$fileInput.addEventListener('change', async (e) => {
  const file = $fileInput.files[0];
  const arrayBuffered = await file.arrayBuffer();
  const actx = new (window.AudioContext || window.webkitAudioContext)({ latencyHint: 'interactive', sampleRate: 44100 });
  const decoded = await actx.decodeAudioData(arrayBuffered);
  const oactx = new OfflineAudioContext({ numberOfChannels: 2, length: decoded.length, sampleRate: actx.sampleRate });
  const absn = new AudioBufferSourceNode(oactx, { buffer: decoded });
  const pn = new PannerNode(oactx, {
    panningModel: 'equalpower',
    distanceModel: 'inverse',
    positionX: 0,
    positionY: 0,
    positionZ: 0,
    orientationX: 1,
    orientationY: 0,
    orientationZ: 0,
    refDistance: 1,
    maxDistance: 10000,
    rolloffFactor: 1,
    coneInnerAngle: 360,
    coneOuterAngle: 360,
    coneOuterGain: 0
  });

  oactx.listener.positionX.value = 0;
  oactx.listener.positionY.value = 0;
  oactx.listener.positionZ.value = 0;
  oactx.listener.forwardX.value = 0;
  oactx.listener.forwardY.value = 0;
  oactx.listener.forwardZ.value = -1;
  oactx.listener.upX.value = 0;
  oactx.listener.upY.value = 1;
  oactx.listener.upZ.value = 0;

  // rotation
  for (let t = 0; t < decoded.duration; t++) {
    const rad = t * Math.PI / 180;
    const x = pn.positionX.value * Math.cos(rad) - pn.positionZ.value * Math.sin(rad);
    const z = pn.positionX.value * Math.sin(rad) + pn.positionZ.value * Math.cos(rad);

    pn.positionX.setValueAtTime(x, t);
    pn.positionZ.setValueAtTime(z, t);
  }

  absn.connect(pn);
  pn.connect(oactx.destination);
  absn.start();
  
  const resultBuffer = await oactx.startRendering();
  const test = new AudioBufferSourceNode(actx, { buffer: resultBuffer });
  test.connect(actx.destination);
  test.start();
});
about 4 years ago · Juan Pablo Isaza
1 answers
Answer question

0

// from
PannerNode.positionX: 0
// to
PannerNode.positionX: 1

// from
for (let t = 0; t < decoded.duration; t++) {
  const rad = t * Math.PI / 180;
}
// to
for (let t = 0; t < decoded.duration; t += 0.01) {
  const rad = 100 * t * Math.PI / 180;
}

I set PannerNode.positionX to 1 because in order for PannerNode to rotate around AudioListener, PannerNode needs to be have some distance from AudioListener.

I change for statement because I want a fast, smoothly changing effect.

about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!