danprince / midas

🫅 Traditional roguelike where everything you touch turns to gold.
https://danprince.itch.io/midas
2 stars 0 forks source link

Spatial Audio #23

Open danprince opened 4 years ago

danprince commented 4 years ago

Sounds are currently triggered and played at full volume, regardless of where in the level they originated.

Should probably send the coordinates of the sound to the audio system so that it can figure out the volume and panning relative to the player.

danprince commented 4 years ago

Got a very simple version of this working, but needs a decent overhaul to work properly.

Need a way to queue/dedupe sounds so that we don't get phase interference or extreme volume. I think that's going to involve a frame-by-frame queue that can average the volume/pan of each duplicate sound that's requested.

  /**
   * @param {number} x
   * @param {number} y
   * @param {keyof typeof AudioSystem["sounds"]} name
   */
  playAt(x, y, name) {
    let audio = AudioSystem.sounds[name].cloneNode(true);

    let source = this.ctx.createMediaElementSource(audio);
    let gainNode = this.ctx.createGain();
    let panNode = this.ctx.createStereoPanner();

    source.connect(gainNode);
    gainNode.connect(panNode);
    panNode.connect(this.masterGain);

    let dx = x - game.camera.x;
    let dy = y - game.camera.y;
    let distance = Math.hypot(dx, dy);

    let volume = scale(distance, 0, 10, 1, 0);
    let pan = scale(dx, -10, 10, -1, 1);

    gainNode.gain.value = volume;
    panNode.pan.value = pan;

    audio.currentTime = 0;
    audio.play();
    audio.onended = () => panNode.disconnect();
  }