Home > Mobile >  Protect users from accidental extremely loud volume in the browser
Protect users from accidental extremely loud volume in the browser

Time:09-27

I'm building a flexible audio application where users can accidentally make things too loud. What are best practices to prevent extremely loud volume?

It looks like I can try using Analyser Node from Web Audio API to detect the loudness, and then reduce the volume based on that. Is there a more standard way?

CodePudding user response:

I've managed to solve this reasonably well by using Analyser Node to detect the loud volume, and GainNode to decrease the volume. Followed code from visualizer examples:


const safety = audioContext.createGain()
const safetyAnalyser = audioContext.createAnalyser()

safetyAnalyser.connect(audioContext.destination)
safety.connect(safetyAnalyser)
protectEars(safetyAnalyser, safety)

applicationOutput.connect(safety)


function protectEars(analyser: AnalyserNode, gain: GainNode) {
  analyser.fftSize = 2048
  analyser.minDecibels = -90

  const bufferLength = analyser.frequencyBinCount
  const fbc_array = new Uint8Array(bufferLength)

  analyser.getByteTimeDomainData(fbc_array)
  const dataArray = new Uint8Array(fbc_array.buffer)

  let timesHit255 = 0

  for (let i = 0; i < bufferLength;   i) {
    if (dataArray[i] === 255) timesHit255  
  }

  // Magic number found with casual experimentation
  if (timesHit255 > 200) {
    gain.gain.value /= 2
    sendNotificationBox('VOLUME REDUCED BECAUSE IT WAS TOO LOUD!')
  } else {
    // Slowly restore? They can also deal with it and just keep making it "louder" on their side
  }

  setTimeout(protectEars.bind(null, analyser, gain), 100)
}

The reason it uses setTimeout as opposed to requestAnimationFrame is because RAF does not get executed when the user switches tabs (while setTimeout does), and the audio may still be unpredictable so you'll still want to watch it.

  • Related