for what its worth, i came up with this fix to at least stop the exception in chrome when using the NON streaming overloads of AudioClip.Create with a PCMReaderCallback. ( trying to catch the exception around AudioClip.Create didn’t seem to help any in regards to not completely crashing the game in browser )
So again, This will not make chrome play audio clips made with AudioClip.Create, nor will it make any browser that i know of work with the streaming parameter set as true work.
Basically, the error is like this ( in chrome )
exception thrown: TypeError: undefined is not a function,TypeError: undefined is not a function
at _JS_Sound_Load_PCM
at __ZN4FMOD7SystemI11createSoundEPKcjP22FMOD_CREATESOUNDEXINFOPPNS_5SoundE
at __ZN4FMOD6System11createSoundEPKcjP22FMOD_CREATESOUNDEXINFOPPNS_5SoundE
at __ZN12SoundManager11createSoundEPKcjP22FMOD_CREATESOUNDEXINFOR11SoundHandlej4PPtrI10SampleClipE
at __ZN9AudioClip11CreateSoundEv
at __ZN9AudioClip15CreateUserSoundERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEjsjb
at Array.__Z30AudioClip_CUSTOM_Init_InternalP15ScriptingObjectP15ScriptingStringiiih
at __Z29AudioClip_Init_Internal_m7185P13AudioClip_t54P8String_tiiibP10MethodInfo
at __Z22AudioClip_Create_m7181P8Object_tP8String_tiiibP22PCMReaderCallback_t226P28PCMSetPositionCallback_t1231P10MethodInfo
at __Z22AudioClip_Create_m1030P8Object_tP8String_tiiibP22PCMReaderCallback_t226P10MethodInfo
ultimately, in _JS_Sound_Load_PCM a variable (sound) is missing a function member copyToChannel on chrome. So as a temporary fix i use whats listed here to mimic the behaviour and check for that member being defined or not. To do so I took notes from
WebGL: Interacting with browser scripting
This is likely the first time i’ve ever written javascript outside of unity, so I do not know of any repercussions in calling WEBAudio.audioContext.createBuffer and doing nothing with the result. I do not know if it has to be disposed or whatever else, if it leaks each time the function gets called or anything like that. So use at your own risk.
BPJSUtil.jslib ( goes in “Assets/Plugins/WebGL/BPJSUtil.jslib” )
var BPJSUtilPlugin = {
WillPCMLoad : function()
{
return !(!WEBAudio||WEBAudio.audioWebEnabled==0||!WEBAudio.audioContext.createBuffer(2,40,44100).copyToChannel);
}
};
mergeInto(LibraryManager.library, BPJSUtilPlugin);
BPJSUtil.cs ( goes in “Assets/Plugins/BPJSUtil.cs” )
using UnityEngine;
using System.Collections;
#if UNITY_WEBGL
internal static class BPJSUtil
{
[System.Runtime.InteropServices.DllImport("__Internal")]
public extern static bool WillPCMLoad();
}
#endif
public static class WebGLAudio
{
/// <summary>
/// returns true if AudioClip.Create will work or not given context.
/// </summary>
/// <param name="Streaming">is this going to be a streaming audio clip? ( afaik, no browsers support streaming audio clips. )</param>
/// <param name="FailIfExceptionInJS">if you want an unknown exception (likely coming from the jslib code) to return false, set this as true.</param>
/// <returns>true if AudioClip.Create will likely not kill the game.</returns>
public static bool CanCreateAudioClip(bool Streaming = false, bool FailIfExceptionInJS=false)
{
#if !UNITY_WEBGL
return true;
#else
// i don't know that any browser supports streaming, and unsure of what to look for.
// returning false mimics the right response in browser i suppose.
if( Streaming )
return false;
// try to invoke the js.
try
{
return BPJSUtil.WillPCMLoad();
}
#if UNITY_EDITOR
catch( System.EntryPointNotFoundException )
{
// yea. in editor this will happen. because its not going to be running the jslib.
// we'll assume firefox in editor.
return true;
}
#endif
catch(System.Exception e)
{
// likely, something wrong in the js function..
Debug.LogException(e);
return !FailIfExceptionInJS;
}
#endif
}
}
Then before you use AudioClip.Create check that WebGLAudio.CanCreateAudioClip returns true before calling Create, otherwise never call AudioClip.Create.
Notes:
again, I do not know if the call is going to leak memory each time its made. While the result could be cached on the first call to the function, I do not know if that would work at runtime or if any of that could change and thus why i do not cache the value. If it never changes then the call to WillPCMLoad should occur once and the return cached. Either way, i would limit calling this function.
This does not explicitly check what browser is being used, but rather if the undefined member is defined or not. Which may or may not be better long term as if it’s fixed by unity, who knows if the function names will remain the same, and if its fixed by chrome then the check is likely unnecessary.
If the streaming argument of CanCreateAudioClip is true, right now false is always returned ( when WEBGL ), because it seems streaming audio works on no platform at all at the moment. So, if streaming clips made with AudioClip.Create ever do work, this will still report they will not.
Any tips on improving the javascript, as again i am very unfamiliar with it, would be greatly welcome.