Sign in to follow this  
Gerente

Audio on Mobile

Recommended Posts

Hello, Any idea if there is a problem on loading .ogg files on chrome mobile?


Im trying :


PIXI.loader.add('menu', "assets/audio/menu.ogg");

PIXI.loader.load(function (loader, resources) {

     console.log(resources)

     resources['menu'].data.play()

 })

 

It works perfect on PC but on Mobile (CHROME IPHONE) its doesnt reach the console.log line.

Any Idea?.

Thanks

 

Share this post


Link to post
Share on other sites

The first time a sound plays within an user interaction event the WebAudio API gets unlocked completely that's how it works. Some of my apps have an animation at the start with sounds so I detect if the app runs on mobile and NOT play the animation and sounds and display a big START button on top of everything. When user taps the START button I play a silent sound WITHIN THAT EVENT LISTENER > remove the START button > play my animation and sounds. It's annoying but there are no work arounds.

Share this post


Link to post
Share on other sites

Ok, so, if the permission was the reason why PIXI do not load the audio file the PIXI is the issue.

I just created this function to enable audio on any device:

- create a 10 ms fake audio and play it,

- onended event of the audio playing call "AUDIO ENABLED".

-otherwise in 15ms later if onended event is not being called then "AUDIO NOT ENABLED" and print a pretty screen asking to tap screen

- on tap/touchstart play the fake audio again and it will work because it has a user interaction that enable the audio.

 

var enableAudio = function (callback) {
  var bufferLength = 10
  window.AudioContex = window.AudioContext || window.webkitAudioContext;
  var audioCtx = new window.AudioContex();
  var myArrayBuffer = audioCtx.createBuffer(1, bufferLength, audioCtx.sampleRate);
  var source = audioCtx.createBufferSource();  

  var nowBuffering = myArrayBuffer.getChannelData(0);
  for (var i = 0; i < bufferLength; i++) {    
    nowBuffering[i] = Math.random() * 2 - 1;
  }

  source.buffer = myArrayBuffer;  
  source.connect(audioCtx.destination);

  var playFakeAudio = function (cb) {
    var done = false
    source.onended = function (a) {
      done = true
      cb(true)
    }
    source.start(0);
    setTimeout(function () {if (!done) cb(false)}, bufferLength + 5)
  }

  playFakeAudio(function (isAudioEnabled) {    
    if (isAudioEnabled == false) { 
      document.write('<h3>CLICK SCREEN TO START</h3>')
      var onTouch = function () {             
        playFakeAudio(function(){
          document.removeEventListener('touchstart', onTouch)
          callback()
        })
      }
      document.addEventListener('touchstart', onTouch)
    } else {
      callback()
    }
  })
}

window.onload = function(){
   enableAudio(function(){
     alert('audio enable')
   })
}

The problem with PIXI is if i use this:

window.onload = function(){
   enableAudio(function(){
     alert('audio enable') //YOU SHOULD HEAR A SHORT AUDIO BEFORE REACH THIS ALERT

     PIXI.loader.add('menu', "assets/audio/menu.ogg");

     loader.load(function (loader, resources) {
       alert('RESOURCED LOADED') // THIS IS NOT REACH EVEN AFTER ENABLE AUDIO
     })

   })
}

 

 

Share this post


Link to post
Share on other sites
1 hour ago, themoonrat said:

I'd really recommend using Howler or pixi sound for audio, it'll handle this stuff for you

- PIXI-Audio doesnt work for me and still using PIXI loader, where is basically the issue. PIXI Audio seems to manager audio AFTER pixi loader have loaded the resources, and I'm not being able to reach that part.

- Howler doesnt integrate with PIXI Loader that mean I would need to use 2 different loaders and I would like to avoid that.

Thanks for the idea anyway.

 

Share this post


Link to post
Share on other sites

Not only those libs don't handle that stuff at all but handling it yourself is not that a big deal. It is only about playing something (silent or even 0.1 second long) using WebAudio API within an user interaction and that's all that is needed for the entire system to start working. Those 2 libs you mention do assume the WebAudio API is already authorized to run on that system so on mobile this has to be done yourself before using those libs.

That's all that is needed:

 

var audioClass = (window['AudioContext'] || window['webkitAudioContext'] || window['mozAudioContext'] || window['oAudioContext'] || window['msAudioContext']);
if (audioClass)
{
SoundMixer._context = new audioClass();
var oscillator = SoundMixer._context.createOscillator();
oscillator.frequency.value = 400;
var gainControl = SoundMixer.context.createGain();
gainControl.gain.value = 0;
oscillator.connect(gainControl);
gainControl.connect(SoundMixer._context.destination);
oscillator.start(0);
oscillator.stop(1);
}

Share this post


Link to post
Share on other sites
6 hours ago, botmaster said:

Not only those libs don't handle that stuff at all but handling it yourself is not that a big deal. It is only about playing something (silent or even 0.1 second long) using WebAudio API within an user interaction and that's all that is needed for the entire system to start working. Those 2 libs you mention do assume the WebAudio API is already authorized to run on that system so on mobile this has to be done yourself before using those libs.

That's all that is needed:

 

var audioClass = (window['AudioContext'] || window['webkitAudioContext'] || window['mozAudioContext'] || window['oAudioContext'] || window['msAudioContext']);
if (audioClass)
{
SoundMixer._context = new audioClass();
var oscillator = SoundMixer._context.createOscillator();
oscillator.frequency.value = 400;
var gainControl = SoundMixer.context.createGain();
gainControl.gain.value = 0;
oscillator.connect(gainControl);
gainControl.connect(SoundMixer._context.destination);
oscillator.start(0);
oscillator.stop(1);
}

Im 100% agree with you, those libs doesnt work on mobile unless you add a button yourself to enable the sound. I have seen many games using them that fail on mobile because the dev has to add that logic.

Thanks for sharing, that look like a great option. it work as well with a bufferSourceNode. 

Do you have a way to detect if the audio is enable or not? , im just using a setTimeout checking if the audio.onended has been triggered, but I would like a different approach.

By the way, the audio was not playing on IPHONE because Ogg and MP3 doesnt work on HTML5 chrome and safari.

 

Share this post


Link to post
Share on other sites

Something important to note on these tricks to play a fakeaudio to enable the audio is that you only enable that specific AudioContext, so you need to use that context to play any other sound,

The user interaction will only enable the current context to be played, any other context will be blocked by default.

Share this post


Link to post
Share on other sites

Yes you can see I'm saving the context in global reference for later use. That code (typescript) is part of a bigger code but only that little part is used to init the API on mobile. I meant to explore further sound detection and such but honestly I didn't have the time and that little piece of code did seem to do the trick every time without any further checks, the idea was: detect mobile > don't start the app > put a button on top of everything > user clicks button > play silent sound and start everything.

If there's a better way to do it that works across all browsers then I'd like to check it out, for now that's all I could come up with that works same way across any browser on any mobile device.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.