Search Unity

Master Audio - AAA Sound Solution. #1 audio plugin on Asset Store!

Discussion in 'Assets and Asset Store' started by dark_tonic, Jan 28, 2013.

  1. djfrail

    djfrail

    Joined:
    Jan 16, 2014
    Posts:
    124
    I'm checking out my game with the Profiler on an Android device and I see that MasterAudio has two coroutines going that make 9B GC allocs every 6 or so frames. They show in the profiler as MasterAudio.CoUpdate() and PlaylistController.CoUpdate().

    Is this anything I should be worried about? Trying to keep my gc allocs close to nil like a good sam.
     
    twobob likes this.
  2. twobob

    twobob

    Joined:
    Jun 28, 2014
    Posts:
    2,058
    oh... does this use co-routines? dang.... I thought there was some "garbage free" option...

    InvokeRepeating FTW!!!
     
  3. jerotas

    jerotas

    Joined:
    Sep 4, 2011
    Posts:
    5,572
    I'll see if I can get rid of the CoRoutines. That is pretty dang close to zero GC though, I don't think you should worry about them.
     
  4. jerotas

    jerotas

    Joined:
    Sep 4, 2011
    Posts:
    5,572
    Are you saying changing them to InvokeRepeating will save GC allocation?
     
  5. twobob

    twobob

    Joined:
    Jun 28, 2014
    Posts:
    2,058
    yes sir.

    It is the closure of the co-routines (via their internal delegate IIRC) that causes your garbage.
    InvokeRepeating has all the same functionality (mainly) without this cost.

    Before you do the works double check my facts, but I am pretty confident on this one


    Coroutines
    If you launch a coroutine via StartCoroutine(), you implicitly allocate both an instance of Unity's Coroutine class (21 Bytes on my system) and an Enumerator (16 Bytes). Importantly, no allocation occurs when the coroutine yield's or resumes, so all you have to do to avoid a memory leak is to limit calls to StartCoroutine() while the game is running.

    assuming you are not following that pattern then InvokeRepeating is for you, since it doesn't have this little known caveat
     
    Last edited: Mar 31, 2015
  6. jerotas

    jerotas

    Joined:
    Sep 4, 2011
    Posts:
    5,572
    I did some testing tonight and I don't see the CoRoutines firing at all (zero GC alloc) unless I turn on "Ignore Time Scale". So I assume you have that turned on. Do you need it? If you don't, turn it off and save the GC.

    Anyway, that makes this a lesser priority since most people do not use that option.

    The GC alloc I was seeing with Ignore Time Scale were in the 40 byte range though, not 9 bytes. I tested in Unity 4.5
     
  7. djfrail

    djfrail

    Joined:
    Jan 16, 2014
    Posts:
    124
    Just did some checking and I don't have "Ignore Time Scale" turned on. I'm on Unity 4.6.3p3. This screenshot is from the profiler with my game running on a Kindle Fire:

     
  8. jerotas

    jerotas

    Joined:
    Sep 4, 2011
    Posts:
    5,572
    I looked at the code before I posted. There are no CoRoutines that run regularly in those classes except when Ignore Time Scale is turned on. So I can't reproduce your graph. Not sure how to help if you're on the latest version of MA.

    I don't have a Kindle but in Unity editor I see no GC alloc.
     
  9. twobob

    twobob

    Joined:
    Jun 28, 2014
    Posts:
    2,058
    The thing to do would be to drop in a/some information about the instancing moment; the (logic) reasons for it's running; or it's failure to stop to a StringBuilder that could optionally at that point be pushed to either debug output via console or onscreen UI. Perhaps this type of debug functionality already exists are merely needs pointing at the erring method.

    That's what Chuck Norris would do.
     
  10. jerotas

    jerotas

    Joined:
    Sep 4, 2011
    Posts:
    5,572
    Chuck Norris haha!

    The code only starts a CoRoutine off that one field "Ignore Time Scale". It's quite simple code. Either the user is mistaken about their setting or it somehow changed the setting during export for that platform. I can't really do anything about it unless I can reproduce it. Powerless to help currently.
     
  11. twobob

    twobob

    Joined:
    Jun 28, 2014
    Posts:
    2,058
    I suppose I should really stop pontificating and go look at some code...
    Is this part of the code something I can ogle? or it it in some obfuscated, triple-zip locked dll that I have eat suicide pills if I approach with a debugger?

    And a kindle fire is just an android device. Pure and simple. WIth greebles.
     
  12. jerotas

    jerotas

    Joined:
    Sep 4, 2011
    Posts:
    5,572
    We don't put code into DLL's. People don't like not being able to customize. Here's the code in MasterAudio.cs

    Code (csharp):
    1.  
    2. private IEnumerator CoUpdate() {
    3.      while (true) {
    4.         frames++;
    5.         if (IgnoreTimeScale) {
    6.            yield return StartCoroutine(CoroutineHelper.WaitForActualSeconds(InnerLoopCheckInterval));
    7.         } else {
    8.            yield return InnerLoopDelay;
    9.         }
    10.         // adjust for Inspector realtime slider.
    11.         PerformBusFades();
    12.         PerformGroupFades();
    13.         RefillInactiveGroupPools();
    14.   }
    15. }
    16.  
    Notice that the StartCoroutine part only triggers off IgnoreTimeScale.

    The other yield return is a "defined up front" YieldInstruction. We're not creating that each time and it's not a StartCoroutine either.

    This is the only StartCoroutine that happens after Scene start in MasterAudio.cs. The one in PlaylistController.cs is the same.

    Anyway, I scanned about 50 frames in a row with the editor running and didn't find anything like the screen shot above. All zero bytes.
     
  13. twobob

    twobob

    Joined:
    Jun 28, 2014
    Posts:
    2,058
    Since it is freely changed the OP can easily switch that over to InvokeRepeating()s and test.

    At this point ruling out the elephant would make the room a lot clearer.
     
  14. jerotas

    jerotas

    Joined:
    Sep 4, 2011
    Posts:
    5,572
    No harm in that.
     
    twobob likes this.
  15. djfrail

    djfrail

    Joined:
    Jan 16, 2014
    Posts:
    124
    Well I tested the game on another Android device, a nVidia Shield tablet, and it does the same 9B GC allocs.

    I checked to see if IgnoreTimeScale is true while the game is running on the device with this statement in an update loop:

    Code (CSharp):
    1. testTextMesh.text = string.Format("ignore:{0}", MasterAudio.IgnoreTimeScale);
    2.  
    It's a Tk2dTextMesh that's always on the screen, and it always displayed "ignore:false".

    This post mentions a bit about 9B GC allocs and coroutines:
    http://forum.unity3d.com/threads/c-coroutine-waitforseconds-garbage-collection-tip.224878/

    I'll test the InvokeRepeating thing next.
     
  16. djfrail

    djfrail

    Joined:
    Jan 16, 2014
    Posts:
    124
    Did a quick rewrite of a few things to avoid using a coroutine in MasterAudio. This is some quick sloppy junk code just to test if the GC allocs are coming from the coroutine.. But I did manage to get the 9B GC allocs from MasterAudio.CoUpdate() to go away. :)

    in MasterAudio.cs, I changed Start() to this:

    Code (CSharp):
    1.  
    2. void Start()
    3. {
    4.     // wait for Playlist Controller to initialize!
    5.     if (musicPlaylists.Count > 0
    6.         && musicPlaylists[0].MusicSettings != null
    7.         && musicPlaylists[0].MusicSettings.Count > 0
    8.         && musicPlaylists[0].MusicSettings[0].clip != null
    9.         && PlaylistControllersByName.Count == 0) {
    10.  
    11.         Debug.Log("No Playlist Controllers exist in the Scene. Music will not play.");
    12.     }
    13.  
    14.     // commented out for testing
    15.     //StartCoroutine(CoUpdate());
    16.  
    17.     // NEW - testing GC Allocs.
    18.     if (IgnoreTimeScale == false)
    19.         InvokeRepeating("DoStuffFromCoUpdate", InnerLoopCheckInterval, InnerLoopCheckInterval);
    20. }
    21.  
    And added these two functions:

    Code (CSharp):
    1. void Update()
    2. {
    3.    frames++;
    4. }
    5.  
    6. private void DoStuffFromCoUpdate()
    7. {
    8.    // adjust for Inspector realtime slider.
    9.    PerformBusFades();
    10.    PerformGroupFades();
    11.    RefillInactiveGroupPools();
    12. }

    Dunno if 9B every 0.1 seconds is worth the fuss, but I like finding the culprit.
     
  17. twobob

    twobob

    Joined:
    Jun 28, 2014
    Posts:
    2,058
    Properly curated to a better pattern, as the least "impactful" solution, this would appear to be a more sensible road.

    I do not understand the use of co-routines where repeated Invokes are indicated, it is what they are for. "Untimely demise to all non-essential co-ro's" I say.

    Nice work Sherlock.

    Laterally: It seems a shame that such things as
    1. void Update()
    2. {
    3. frames++;
    4. }
    can't be sucked into oblivion too... in this case the entire update loop overhead to mark the increment of a single value. Hey ho. ♫ Some people say I'm a dreamer.. ♬ But I'm not the only one... ♪

    If such things work, they work :) don't fix it, but these much-overlooked often-used wangles, anti-patterns, and steroid-fueled uber-libs where a simple method would do suck the performance away tiny piece by tiny piece, and I like all of my pieces to be mine to waste :)
     
    Last edited: Apr 2, 2015
  18. jerotas

    jerotas

    Joined:
    Sep 4, 2011
    Posts:
    5,572
    That's cool that it works! I'll make that update in the next version.
     
  19. jerotas

    jerotas

    Joined:
    Sep 4, 2011
    Posts:
    5,572
    That variable increment will go into the InvokeRepeating section as well. Unless I go with Update for the whole shebang instead and refactor it.
     
  20. twobob

    twobob

    Joined:
    Jun 28, 2014
    Posts:
    2,058
    Yeah I wasn't so much pointing the finger at you. more at the repetitive necessary evils of the system.
    An internally provided and reliable http://docs.unity3d.com/ScriptReference/Time-frameCount.html value would put paid to that pattern ever having to grace the guts of every game ever...
    If we all do it because the internal thing is broken.. it needs fixing... and not by us. If it's because we don't know it's there, we are misusing it or we are reinventing the wheel, then that is on us
     
    Last edited: Apr 2, 2015
    jerotas likes this.
  21. djfrail

    djfrail

    Joined:
    Jan 16, 2014
    Posts:
    124
    Cool.

    PlaylistController.CoUpdate() could use some similar rewrite love, too, if it's not too much bother.
     
    twobob likes this.
  22. jerotas

    jerotas

    Joined:
    Sep 4, 2011
    Posts:
    5,572
    I know, I have it up top on the roadmap. Thanks for the research!
     
  23. jerotas

    jerotas

    Joined:
    Sep 4, 2011
    Posts:
    5,572
    These are now both fixed and will be in the next update.

    I couldn't use InvokeRepeating because that stops firing at zero time scale. Instead I added the old Coroutine's code to Update and changed all the calculations to use Time.deltaTime. When timescale is zero that doesn't work so I use Time.fixedDelta time instead. It's not exact, but it pretty well.

    And now Ignore Time Scale is only needed for EventSounds Start event and DelayBetweenSongs scripts. So most people will never need to turn it on.
     
    twobob likes this.
  24. jerotas

    jerotas

    Joined:
    Sep 4, 2011
    Posts:
    5,572
    I tried and failed miserably at the "equal power crossfading" attempt. According to the math I found and used, it only produced a tremolo-like effect and didn't fade at all.

    So this is now removed from the roadmap unless someone can provide the correct math to me.

    -Brian
     
  25. OnePxl

    OnePxl

    Joined:
    Aug 6, 2012
    Posts:
    307
  26. djfrail

    djfrail

    Joined:
    Jan 16, 2014
    Posts:
    124

    Very cool.
     
  27. jerotas

    jerotas

    Joined:
    Sep 4, 2011
    Posts:
    5,572
  28. jerotas

    jerotas

    Joined:
    Sep 4, 2011
    Posts:
    5,572
    Master Audio V 3.5.7.7 has been submitted and we're waiting for approval. Release notes:

    • Changed label of Weight (Instances) to "Voices (Weight)" for less confusion.
    • Changed UndoHelper to AudioUndoHelper to avoid conflicts with our other plugins.
    • Fixed compile errors in optional DF-GUI package.
    • Fixed volume level bug when using "fade in first song" with zero crossfade.
    • Fixed fade in bug where it set volume to zero with no fade in (makes FadeOutNow inaudible).
    • Fixed preview of Sound Group in Dynamic Sound Group Creator. It didn't respect the Group's volume fader.
    • Fixed bug: FadeSoundGroupToVolume and FadeBusToVolume did not execute their callback if you had it fade faster than 0.1 seconds.
    • Fixed bug: Caller Despawned Fade stops suddenly instead of fading when TimeScale is zero.
    • Consolidated all Master Audio menu items under "Window" into a new parent "Master Audio" menu item.
    • Fixed 2D Toolkit package compile errors due to recent changes in main Master Audio code.
    • Breaking change (if you have written code): All classes are now in the DarkTonic.MasterAudio namespace. You will need to add "using DarkTonic.MasterAudio;" at the top of all scripts you've written that use the Master Audio API.
    • Updated Behavior Designer packages to use the new namespace.
    • Updated DF-GUI package to use the new namespace.
    • Updated Playmaker package to use the new namespace.
    • Updated 2D Toolkit package to use the new namespace.
    • Eliminated CoRoutines in MasterAudio and PlaylistController classes. Ignore Time Scale now only used for "DelayBetweenSongs" script and EventSounds Start event.
     
    twobob likes this.
  29. OnePxl

    OnePxl

    Joined:
    Aug 6, 2012
    Posts:
    307
    No, it's just a general logarithmic curve for both channels. Should work anywhere.
     
  30. hike1

    hike1

    Joined:
    Sep 6, 2009
    Posts:
    401
    I'm getting wobbly sounds using master audio, like someone momentarily pressed on a record on a record player.
    Also your darktonic forum doesn't like my password, asked for another one, no reply.
     
  31. jerotas

    jerotas

    Joined:
    Sep 4, 2011
    Posts:
    5,572
    I don't understand what modifications need to be made for Unity...
     
  32. jerotas

    jerotas

    Joined:
    Sep 4, 2011
    Posts:
    5,572
    Unfortunately the forum is a black box to me. You're the 2nd person to have this problem, and hundreds of others have not had any problem.

    Perhaps your Doppler settings need to be adjusted? I never touch them but they may have different defaults in Unity 5.
     
  33. hike1

    hike1

    Joined:
    Sep 6, 2009
    Posts:
    401
    I got back in your forum. Nothing about doppler in the manual, where is it?
     
  34. twobob

    twobob

    Joined:
    Jun 28, 2014
    Posts:
    2,058
    doppler is in the 3d sounds settings of the sample... It's a Unity thing

    upload_2015-4-5_15-52-43.png


    the defaults do not appear to have changed, in addition all sounds are now treated as 2d by default... Thus unless this is an older project... This is unlikely to be the cause
     
    jerotas likes this.
  35. hike1

    hike1

    Joined:
    Sep 6, 2009
    Posts:
    401
    Thanks, twobob, not all of the sound are warbly. Just browsing through my audio 3d sounds, none of them are 2d. 3d is for headphones or speakers spread apart? I guess a doppler setting of 1 means don't mess with the sound.
     
    jerotas likes this.
  36. jerotas

    jerotas

    Joined:
    Sep 4, 2011
    Posts:
    5,572
    Not sure about the answer, but for some of the more esoteric settings, you would be better off posting in the new Audio forum here: http://forum.unity3d.com/forums/audio.74/

    I never use Doppler because it leads to pretty weird sounds.
     
  37. jerotas

    jerotas

    Joined:
    Sep 4, 2011
    Posts:
    5,572
    V 3.5.7.7 is live! Grab them updates.
     
  38. timothyallan

    timothyallan

    Joined:
    May 22, 2013
    Posts:
    72
    I've got a few workflow questions:

    1. I'm not a fan of boostrapper scenes, I like being able to press play on the current scene I'm working on, and have everything work. MA is the only thing giving me grief currently in that respect! I don't want to have to duplicate my MA prefab + 2 playlist prefabs to every scene as that's a maintenance nightmare. Ideally I'd be able to wrap all 3 in a Prefab and drop the Prefab in each scene... but MA cannot be parented to another GO currently.

    2. If I am stuck doing the persistent method with MA and a boostrap scene, how can I use the Event Sounds scripts in other scenes to adjust playlist volumes, play clips etc when the playlists / MA prefab don't currently exist.

    Any suggestions on how to solve/work around any of these issues?
     
  39. jerotas

    jerotas

    Joined:
    Sep 4, 2011
    Posts:
    5,572
    #1. Don't bother with the parenting thing as you said because it's not supported. Just make a Master Audio prefab and Playlist Controller prefab (x2) and drop those in each Scene, the same one for each Scene, not a different one for each. That is not a maintenance nightmare unless there's something I don't understand - you will need to tell me. This is a normal workaround that lots of large studios are using. This is mentioned in the readme near the end (best practices section I believe).

    #2, I am able to use EventSounds in other Scenes without a MA prefab. You won't have a list of Sounds / buses to select from dropdowns (because that gets populated from the MA game object which is missing in the Scene) but you can type the name.
     
  40. timothyallan

    timothyallan

    Joined:
    May 22, 2013
    Posts:
    72
    ahaaaaa, so I can Prefab the MA and Playlists separately, just not together. That's a huge help! I read the readme a while ago, but I guess that part didn't click.

    The Event sounds thing should sort itself out now that I can prefab the MA plugin. With dozens of sounds, it's hard to remember the exact names of them sometimes :)

    Thanks Brian.
     
  41. jerotas

    jerotas

    Joined:
    Sep 4, 2011
    Posts:
    5,572
    Yeah, no problem! I hear you on remembering names of sounds, we have some weird ones!
     
    Last edited: Apr 11, 2015
  42. timothyallan

    timothyallan

    Joined:
    May 22, 2013
    Posts:
    72
    background_music_final_bass_up_final__snarefix_finalfinal_update2.wav
     
    jerotas likes this.
  43. TechiTech

    TechiTech

    Joined:
    Dec 13, 2014
    Posts:
    212
    I've just watched your tutorial


    but when I type Masteraudio.PlaySoundAndForget.. it's not recognized.

    do I need to setup a reference to master audio?

    intellisence not showing any master audio's api.
     
  44. jerotas

    jerotas

    Joined:
    Sep 4, 2011
    Posts:
    5,572
    Since the last version, all classes are in a namespace. You will need to add this line at the top of your scripts that use the API:

    using DarkTonic.MasterAudio;
     
    twobob likes this.
  45. OneShotGG

    OneShotGG

    Joined:
    Nov 16, 2012
    Posts:
    225
    I am having a slight problem. When I build and run my game on Android the sounds play but they are delayed a few ms. Its enough to notice there is a delay. In the editor, running on my pc, there is no sound delay.

    I used to know how to fix this in unity 4.6 but I cannot for the life of me remember how or even figure out how. I have a feeling it has to do with the type or size of the files its trying to load but I am not sure.

    So what is actually causing this delay and how can I fix it in Unity 5.
     
  46. jerotas

    jerotas

    Joined:
    Sep 4, 2011
    Posts:
    5,572
    The only setting that has to do with latency that I used before was the audio "latency" field which people have set to "best latency". I'm not aware that anything has changed in Unity 5 around that. You might want to ask this question on the audio forum here and see if anyone else has more info:
    http://forum.unity3d.com/forums/audio.74/

    Also, if you're using Resource files for some sounds, it's totally expected that there will be a little extra latency as sounds are loaded only when you request them.
     
  47. OneShotGG

    OneShotGG

    Joined:
    Nov 16, 2012
    Posts:
    225
    How do I not use Resource files? Pooling?
     
  48. jerotas

    jerotas

    Joined:
    Sep 4, 2011
    Posts:
    5,572
    There is no pooling needed or used by Master Audio.

    By default you're not using any Resource files. If you click the gear (settings) icon on the Master Audio mixer for one of your Sound Groups, you'll see that each Variation has an Audio Origin field. The choices are Resource file and Audio Clip (default). If you don't know what Resource files are or why you should use them, you can read about them on the Unity documentation. Master Audio makes it possible to use Resource files with no code writing.
     
  49. DirtyHippy

    DirtyHippy

    Joined:
    Jul 17, 2012
    Posts:
    224
    When I start up my game and it loads the bootstrap scene, I have a PlayListController with "start on awake" set to false (all 4 checkboxes are false) However, as my game bootstraps I set the music volume that was last saved (from a deserialized configuration file) and I get the following two messages:

    There are no clips left in this Playlist. Turn on Loop Playlist if you want to loop the entire song selection.
    Coroutine couldn't be started because the the game object 'PlaylistController' is inactive!

    I haven't tested if the music starts later. But this strikes me as a bug. It looks like it is expecting the music to be playing when I set the music volume.

    Edit: 3.5.7.6
     
  50. jerotas

    jerotas

    Joined:
    Sep 4, 2011
    Posts:
    5,572
    I believe that instead of the script you are using and the setting you're storing, you should use the Persistent Settings feature that's built in. It will automatically set the music to the last volume every time it starts up. Let me know if that doesn't work.

    I'm not sure you how got that particular message though. You'd have to send me your script.