Skip to content

Instantly share code, notes, and snippets.

@searls
Created January 2, 2022 15:44
Show Gist options
  • Save searls/a959295aa616790f57c7494075d92484 to your computer and use it in GitHub Desktop.
Save searls/a959295aa616790f57c7494075d92484 to your computer and use it in GitHub Desktop.

I was having issues with getting my Web Audio effects in KameSame loud enough to be audible when an iOS device was simultaneously playing music in the background. Because I like to listen to music while I study, here's how I increased the volume of the sound effect relative to the music in iOS.

Here's the original function in my app for playing audio in iOS (all other platforms work fine with new window.Audio(url).play()):

function playIos (url) {
  const audioContext = new AudioContext()
  const source = audioContext.createBufferSource()
  const request = new window.XMLHttpRequest()
  request.open('GET', url, true)
  request.responseType = 'arraybuffer'
  request.addEventListener('load', function (e) {
    audioContext.decodeAudioData(request.response).then((buffer) => {
      source.buffer = buffer
      source.connect(audioContext.destination)
      source.start(0)
    })
  }, false)
  request.send()
}

Here's a video of how the sound effect (spoken Japanese generated by AWS Polly sounds relative to a background music. (In the video, the audio sounds pretty balanced, but on the iOS hardware itself, the spoken word is almost inaudible)

To amplify the volume of the web audio, here's how I used a Gain node to set a value greater than 1 to increase the volume. The maximum value is literally the floating point max of JavaScript, but even a modest increase of 2 or 3 will dramatically increase the volume of your web audio track relative to whatever else iOS is playing:

function playIos (url) {
  const audioContext = new AudioContext()
  const gainNode = audioContext.createGain()
  gainNode.gain.value = 3
  const source = audioContext.createBufferSource()
  const request = new window.XMLHttpRequest()
  request.open('GET', url, true)
  request.responseType = 'arraybuffer'
  request.addEventListener('load', function (e) {
    audioContext.decodeAudioData(request.response).then((buffer) => {
      source.buffer = buffer
      source.connect(gainNode).connect(audioContext.destination)
      source.start(0)
    })
  }, false)
  request.send()
}

And here's a video of the amplified audio track (again, note that in the exported video the spoken word now sounds ear-piercingly loud, but on device the mix sounds appropriately balanced and the spoken word can be heard clearly.

Anyway, it'd be neat if iOS let you mix app audio yourself, but until then there's JavaScript hacks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment