Search code examples
javascriptwebrtcweb-audio-api

WEBRTC: Is it possible to control volume per audio track when we have audio streaming?


What is my goal?

To control the volume of each audio track, so I can have a background sound at a lower volume and other sounds at a higher volume.

Scenario

  1. I have a page where I upload audio files and when the upload is done an audio player is created on the DOM.
  2. The audio source is connected to the audioContext.destination and mediaStreamDestination.
  3. The audio streaming works fine.

I added a volume range for each audio player and I am trying to control the volume.

  volumeControlInput.addEventListener("change", (event) => {
    const audioSource = audioSources[index];
    const gainNode = audioContext.createGain();

    // Connect source to a gain node
    audioSource.connect(gainNode);
    // Connect gain node to destination
    gainNode.connect(audioContext.destination);
    gainNode.connect(mediaStreamDestination); //this doesn't seem necessary but I tried with and without it and it doesn't change anything.

    const volume = event.target.value;
    const fraction = parseInt(volume) / parseInt(event.target.max); // max is 100
    // Using an x*x curve (x-squared) since simple linear (x) does not
    // sound as good.
    // I also tried setValueAtTime and there's no difference for me.
    gainNode.gain.value = fraction * fraction;
}

What is the Problem I am trying to solve?

The volume only increases if I drag the volume range input, it never turns the volume down.

The weird thing for me is, this example works fine here https://webaudioapi.com/samples/volume/ source: https://github.com/borismus/webaudioapi.com/blob/master/content/posts/volume/volume-sample.js

I am wondering if this is not possible at all, any ideas?


Solution

  • It looks like you create a new GainNode within the event listener. That way you keep on adding a connection for each new volume but you never remove the previous connections. That explains why your signal only ever gets louder.

    I would recommend to create the GainNode and its connections outside of the event listener. The event listener would then only deal with setting the value on the gain AudioParam.