zeh/usfxr

No Audio in WebGL Build

thelucre opened this issue · 7 comments

Getting an error and no audio output in a WebGL build. Any ideas?

Only custom filters can be played. Please add a custom filter or 
an audioclip to the audiosource (SfxrGameObject-5.28197).
zeh commented

Hum, I wasn't aware of that - I think a bunch of webgl features are still
experimental. I'll take a look.
On Nov 6, 2015 00:18, "Eric Howard" notifications@github.com wrote:

Getting an error and no audio output in a WebGL build. Any ideas?

Only custom filters can be played. Please add a custom filter or an audioclip to the audiosource (SfxrGameObject-5.28197).


Reply to this email directly or view it on GitHub
#30.

zeh commented

Indeed, OnAudioFilterRead is not supported in WebGL. The error message does hint at the lack of an AudioClip, even though one is generated automatically by usfxr. But even by adding a real AudioClip manually, the filter is never executed.

To test this, I started an empty, usfxr-less project, with this small script attached to a GameObject:

using UnityEngine;
using System.Collections;

public class GameTest : MonoBehaviour {

    private float val;

    void OnAudioFilterRead(float[] data, int channels) {
        for (var i = 0; i < data.Length; ++i) {
            data[i] = Mathf.Sin(val);
            val += 0.02f;
        }
    }
}

Then, I (manually) attached an AudioClip script to play a .wav from that GameObject.

This produces a test tone in any version of the project. The audio filter simply replaces the samples with a sin curve, so the original AudioClip source is ignored; we never hear the .wav.

However, on a WebGL test build using Chrome Canary, it will only play the original .wav audio, completely ignoring the filter. It only plays the audio once, by the way, which seems to be a separate bug.

So, because OnAudioFilterRead is not supported, and that's what usfxr relies on to generate audio samples in a separate thread as needed, usfxr cannot properly run.

Now. With that said, the WebGL Audio support page does point at a potential solution: the AudioClip.Create method, which can be used to generate custom audio clips in real time. This would allow us to create and play a sample as before.

The caveat with this are twofold. First, according to the same WebGL audio support page, "AudioClip.Create is currently not supported in Chrome due to a bug, which is going to be fixed in a future release". And second, and more importantly, the stream parameter of the AudioClip.Create method (which allows the use of a function to generate samples as needed) is not allowed. The samples would have to be generated on the main thread... it's the equivalent of pre-caching them, because it can take some precious miliseconds to generate all samples needed for each audio effect.

So, to summarize:

  • It's a limitation of the current WebGL implementation, maybe a limitation of WebGL as whole.
  • A potential solution exists, but it has limitations:
    • No parallel generation.
    • It likely won't work for a while in Chrome.

I'll still explore that solution though. Considering the current architecture (audio can already be generated in several different ways), it should be fairly simple to just use a separate method to generate the audio using AudioClip.Create when WebGL is detected.

Awesome, thanks for the detailed summary. Here's a link to the chrome bug:
https://code.google.com/p/chromium/issues/detail?id=361859

And it looks like a related fix might be coming through in the 5.3 release this December.
http://forum.unity3d.com/threads/audioclip-create.317032/#post-2331917

zeh commented

Hey Eric, I've pushed a commit that is my initial solution to the problem. It just creates the audio all at once using AudioClip.Create when playing it for the first time. Also, not sure why the documentation says it's not supported in Chrome, because it's working super well in Chrome (Canary)!

I'll probably work on it a bit more to make sure nothing is leaking, and see if there's a way to make it perform better (a big deal since it has to block the UI to generate the audio). But right now things shouldn't be silent anymore, at least.

Thank you! Confirmed working in Chrome 47, too.

Thanks @zeh u rock

zeh commented

A bit late, but closing this. Glad it's fixed!