JavaScript

Compatible Audio Playing Across All Platforms

It seems like:

  1. With HTML5 audio tag, if the audio is less than 500ms, the volume in Safari might fluctuate with all formats
  2. With HTML5 audio tag, the delay with Safari is obvious with all formats
  3. With flash audio player, the delay with Safari is obvious with *.wav, but it’s fine with *.mp3
  4. IE9 doesn’t support native audio tag
  5. Firefox’s audio sounds terrible when html5 audio tag is used with mp3/ogg format, but is okay with wav.
  6. Firefox is fine with flash audio player

To achieve compatibility across all browsers:

  1. Use flash audio player
  2. Use mp3 and wav format
  3. Put mp3 before wav

So a simplified version with Sound Manager 2 (sometimes the onready event has trouble firing though, in which case a ontimeout reload is needed. See the whole of it at the end of this page):

soundManager.setup
  url:'./swf/'
  flashVersion:9
  preferFlash:true
  onready: ->
    createSound =(id, volume =50, fileName = id)->
      soundManager.createSound
        id: id
        url:["./audio/#{fileName}.mp3","./audio/#{fileName}.wav"]
        autoLoad:true
        autoPlay:false
        volume: volume

    createSound("button")

And play with:

soundManager.play("button")

This should solve the delay issue with OSX Safari. On IOS however, audio is poorly supported. The audio has to be user-initiated, the same way as video, which means that the delay is unavoidable. I haven’t been able to find a good solution yet.

And the whole of my code:

do loadAudio = (useSoundManager = true) ->
  url = (fileName) ->
    if platform.isFirefox
      ["./audio/#{fileName}.wav"]
    else
      ["./audio/#{fileName}.mp3", "./audio/#{fileName}.wav"]

  if useSoundManager
    soundManager.setup
      url: './swf/'
      debugMode: true
      flashVersion: 9
      preferFlash: true
      onready: ->
        console.log 'soundManager ready'
        createSound = (id, volume = 50, fileName = id) ->
          soundManager.createSound
            id: id
            url: url(fileName)
            autoLoad: true
            autoPlay: false
            volume: volume

        createSound("close")
        createSound("button")
        createSound("countdown", 10)
      ontimeout: ->
        console.log "Uh-oh. No HTML5 support, SWF missing, Flash blocked or other issue. Reload." # sometimes when browser is cleared of cache and loads for the first time, this tends to happen, so reload:
        loadAudio(true)
        # or if you want to use html5 audio tag here instead:
        # loadAudio(false)

    else
      addSource = (src, volume = 1) ->
      $audio = $("<audio id='#{src}' />")
      $audio[0].volume = volume
      $audio.append("<source src='./audio/#{src}.wav'>")
      $audio.append("<source src='./audio/#{src}.mp3'>")
      $audio.appendTo('body')
 
      addSource('close', .5)
      addSource('button', .5)
      addSource('countdown', 0.1)
 
    window.playAudio = (id) ->
      return if !platform.isDesktop
      if useSoundManager
        soundManager.play(id)
      else
        audio = $("##{id}")[0]
        return if audio.readyState is 0
        audio.currentTime = 0
        audio.play()
 
    window.stopAudio = (id) ->
      return if !platform.isDesktop
      if useSoundManager
      soundManager.stop(id)
    else
      $("##{id}")[0].pause()
 
# and play with:
$('.button-sound').on 'mouseenter', -> playAudio('button')
$('.close-sound').on 'mouseenter', -> playAudio('close')

Reference:

Standard