Crash in FMOD5_Thread_SetAttributes

I’m using a test script to test music playback for my game, and I frequently am getting a crash on FMOD::System::playSound on either subsequent playbacks, or when removing the script or gameobject its attached to, or simply stopping the game in the editor. I dunno if I’m releasing things when I shouldn’t, or not releasing things when I should.

here’s the Unity Editor stacktrace: FMOD Ex Unity stacktrace - Pastebin.com
and here’s the script in question: FMOD Ex Unity script - Pastebin.com

I have hit a segfault by commenting back in baseSound.release(); on line 145- that would be because of calling release before trying to access the subsounds.
I couldn’t get any crashes otherwise, but I am seeing errors when playing and stopping the scene:

[FMOD] Sound::release() returned ERR_INVALID_HANDLE for SOUND (0x1B224743028).

Firstly, you do not need to release subsounds when using fsbs, secondly, you are double releasing all of your handles by calling OnDisable() and OnDestroy(). I suggest something like this instead:

    void OnDisable()
    {
        ReloadSound(false);
    }

    void ReloadSound(bool runAwake)
    {
        if (hasLoadedAtLeastOnce)
        {
            ReleaseAll();

            hasInitializedMainSound = false;
            hasInitializedSound2 = false;
            hasInitializedSubSounds = false;
        }
        else
        { 
            hasLoadedAtLeastOnce = true;
        }
        if (runAwake)
            LoadTrack();
    }

    void ReleaseAll()
    {
        dsp01.release();
        dsp02.release();
        dsp01.release();
        dsp02.release();
        //sound01.release();
        //sound02.release();
        baseSound.release();
        baseSound02.release();
    }

I am currently still getting crashes if I disable and then reenable the script with this code. I also still occasionally get freezing when exiting play mode (although that’s much more rare now). Have I missed something again?

using FMOD;
using UnityEngine;

public class fmodlowleveltest : MonoBehaviour
{
    [Range(1, 6)] public int stereoPairs = 6;
    private int stereoPairsPlayback = 6;

    [Range(0.0f, 1.0f)] public float baseVolume = 0.75f;

    [Range(0.0f, 1.0f)] public float channel1Volume = 1.0f;
    [Range(0.0f, 1.0f)] public float channel2Volume;
    [Range(0.0f, 1.0f)] public float channel3Volume;
    [Range(0.0f, 1.0f)] public float channel4Volume;
    [Range(0.0f, 1.0f)] public float channel5Volume;
    [Range(0.0f, 1.0f)] public float channel6Volume;

    private FMOD.System SystemEX;
    private Sound baseSound;
    private Sound baseSound02;
    private Sound sound01;
    private Channel channel01;
    private Sound sound02;
    private Channel channel02;
    private ChannelGroup channelGroup;
    bool hasInitializedMainSound = false;
    bool hasInitializedSubSounds = false;
	bool hasInitializedSound2 = false;
    public string bank = "i_pod.fsb";
    public uint loopStart = 0;
    public bool reloadSound = false;
	private bool hasLoadedAtLeastOnce;
    private bool gotBus = false;
    FMOD.Studio.Bus bus;


    public static bool ERRCHECK(FMOD.RESULT result)
    {
        if (result != FMOD.RESULT.OK)
        {
            Debug.LogError("FMOD Error (" + result.ToString() + "): " + FMOD.Error.String(result));
        }
        
        return (result == FMOD.RESULT.OK);
    }

    void Start()
	{
        SystemEX = FMODUnity.RuntimeManager.CoreSystem;
        stereoPairsPlayback = stereoPairs;
    }

    // Start is called before the first frame update
    void LoadTrack()
    {
        RESULT result;
        stereoPairsPlayback = stereoPairs;
        Debug.Log("set up parameters");

        string bankpath = string.Format("{0}/audio/{1}", Application.streamingAssetsPath, bank);
        MODE modes = MODE.LOOP_NORMAL | MODE._2D | MODE.CREATESTREAM | MODE.NONBLOCKING;

        result = SystemEX.createStream(bankpath, modes, out baseSound);
        ERRCHECK(result);
        if (stereoPairsPlayback > 3)
        {
            result = SystemEX.createStream(bankpath, modes, out baseSound02);
            ERRCHECK(result);
            Debug.Log("Loaded IntMusic with more than 3 stereo pairs!");
        }
    }

    void setVolumes(float track1, float track2, float track3, float track4, float track5, float track6)
	{
        float[] vol = new float[3] { track1 * baseVolume, track2 * baseVolume, track3 * baseVolume };
        float[] vol02 = new float[3] { track4 * baseVolume, track5 * baseVolume, track6 * baseVolume };

        float[] matrix01_1 = new float[System.Math.Min(stereoPairsPlayback, 3) * 2];
        float[] matrix01_2 = new float[System.Math.Min(stereoPairsPlayback, 3) * 2];
        for (int i = 0; i < System.Math.Min(stereoPairsPlayback, 3); i++)
		{
            matrix01_1[i * 2] = vol[i];
            matrix01_2[i * 2] = 0;
            matrix01_1[(i * 2) + 1] = 0;
            matrix01_2[(i * 2) + 1] = vol[i];
        }
        float[] matrix01 = new float[matrix01_1.Length + matrix01_2.Length];
        matrix01_1.CopyTo(matrix01, 0);
        matrix01_2.CopyTo(matrix01, matrix01_1.Length);
        if (hasInitializedSubSounds)
            channel01.setMixMatrix(matrix01, 2, 6, System.Math.Min(stereoPairsPlayback, 3) * 2);
        if (stereoPairsPlayback > 3)
        {
            float[] matrix02_1 = new float[(stereoPairsPlayback - 3) * 2];
            float[] matrix02_2 = new float[(stereoPairsPlayback - 3) * 2];
            for (int i = 0; i < (stereoPairsPlayback - 3); i++)
            {
                matrix02_1[i * 2] = vol02[i];
                matrix02_2[i * 2] = 0;
                matrix02_1[(i * 2) + 1] = 0;
                matrix02_2[(i * 2) + 1] = vol02[i];
            }
            float[] matrix02 = new float[matrix01_1.Length + matrix01_2.Length];
            matrix02_1.CopyTo(matrix02, 0);
            matrix02_2.CopyTo(matrix02, matrix02_1.Length);
            if (hasInitializedSubSounds)
                channel02.setMixMatrix(matrix02, 2, 6, (stereoPairsPlayback - 3) * 2);
        }
    }

    // Update is called once per frame
    void Update()
    {
        RESULT result;
        if (hasLoadedAtLeastOnce)
        {
            OPENSTATE openstate;
            result = baseSound.getOpenState(out openstate, out _, out _, out _);
            ERRCHECK(result);

            if (openstate == FMOD.OPENSTATE.READY && !hasInitializedMainSound)
            {
                hasInitializedMainSound = true;
                result = baseSound.getSubSound(0, out sound01);
                ERRCHECK(result);
                Debug.Log("get sound 1");
            }

            OPENSTATE openstate01 = 0;
            if (stereoPairsPlayback > 3)
            {
                result = baseSound02.getOpenState(out openstate01, out _, out _, out _);
                ERRCHECK(result);
            }

            if (openstate01 == FMOD.OPENSTATE.READY && !hasInitializedSound2 && stereoPairsPlayback > 3)
            {
                hasInitializedSound2 = true;
                result = baseSound02.getSubSound(1, out sound02);
                ERRCHECK(result);
                Debug.Log("get sound 2");
            }

            OPENSTATE openstate02 = 0;
            if (stereoPairsPlayback > 3 && openstate01 == FMOD.OPENSTATE.READY)
            {
                result = sound02.getOpenState(out openstate02, out _, out _, out _);
                ERRCHECK(result);
            }

            if (openstate01 == FMOD.OPENSTATE.READY && (openstate02 == FMOD.OPENSTATE.READY || stereoPairsPlayback <= 3) && !hasInitializedSubSounds)
            {
                hasInitializedSubSounds = true;
                //baseSound.release();                
                if (!gotBus)
                {
                    bus = FMODUnity.RuntimeManager.GetBus("bus:/master/music");
                    ERRCHECK(result);
                    ERRCHECK(bus.lockChannelGroup());
                    ERRCHECK(FMODUnity.RuntimeManager.StudioSystem.flushCommands());
                    ERRCHECK(bus.getChannelGroup(out channelGroup));
                    gotBus = true;
                }

                Debug.Log("get channel group");

                uint sound01loopend;
                sound01.getLoopPoints(out _, TIMEUNIT.MS, out sound01loopend, TIMEUNIT.PCM);
                sound01.setLoopPoints(loopStart, TIMEUNIT.MS, sound01loopend, TIMEUNIT.PCM);

                if (stereoPairsPlayback > 3)
                {
                    uint sound02loopend;
                    sound02.getLoopPoints(out _, TIMEUNIT.MS, out sound02loopend, TIMEUNIT.PCM);
                    sound02.setLoopPoints(loopStart, TIMEUNIT.MS, sound02loopend, TIMEUNIT.PCM);
                    SystemEX.playSound(sound01, channelGroup, false, out channel01);
                    SystemEX.playSound(sound02, channelGroup, false, out channel02);
                }
                else
                {
                    SystemEX.playSound(sound01, channelGroup, false, out channel01);
                }
                setVolumes(channel1Volume, channel2Volume, channel3Volume, channel4Volume, channel5Volume, channel6Volume);
                string name01;
                sound01.getName(out name01, 256);
                if (stereoPairsPlayback > 3)
                {
                    string name02;
                    sound02.getName(out name02, 256);
                    Debug.LogFormat("Now playing {0} and {1}", name01, name02);
                }
                else
                {
                    Debug.LogFormat("Now playing {0}", name01);
                }
            }
        }
        if (reloadSound && FMODUnity.RuntimeManager.IsInitialized)
		{
            reloadSound = false;
            ReloadSound(true);
        }
        setVolumes(channel1Volume, channel2Volume, channel3Volume, channel4Volume, channel5Volume, channel6Volume);
    }

	void OnDisable()
	{
        ReloadSound(false);
    }

    void ReloadSound(bool runAwake)
	{
        if (hasLoadedAtLeastOnce)
        {
            //OnDestroy();
            Reload();
            hasInitializedMainSound = false;
            hasInitializedSound2 = false;
            hasInitializedSubSounds = false;
        }
        else if(runAwake)
		{
            hasLoadedAtLeastOnce = true;
        }
        if (runAwake)
            LoadTrack();
    }

    void Reload()
	{
        if (hasInitializedSubSounds)
        {
            baseSound.release();
            if (stereoPairsPlayback > 3)
                baseSound02.release();
        }
    }

	void OnDestroy()
    {
        //Reload();
        if (gotBus)
        {
            channelGroup.release();
            bus.unlockChannelGroup();
        }
        //SystemEX.release();
    }
}

the crash occurs at line 176

by the way, commented out lines were commented out on purpose due to them no longer being needed in the current iteration of the script, and really old stuff that stayed in a now strange-looking place

In this case it’s because the state when the script starts isn’t the same as when the script is started, disabled and then re-enabled. I suggest you reinitialize some of your variables in OnEnable():

private void OnEnable()
{
    hasLoadedAtLeastOnce = false;
}

exiting playmode still is unstable though. sometimes it works, sometimes it freezes the editor, and sometimes it outright crashes it. The crash log seems to point to releasing the sounds in the Reload() function.

looking at the logs, it’s the Studio API crashing on release while for some reason trying to set a VCA’s volume

0x00000000771E85B8 (ntdll) RtlRaiseStatus
0x00000000771A162B (ntdll) longjmp
0x000000007714D261 (ntdll) RtlEnterCriticalSection
0x000007FEBDBD9C3A (fmodstudiol) FMOD_Thread_SetAttributes
0x000007FEBDC2547C (fmodstudiol) FMOD::SystemI::createMemoryFile
0x000007FEBDC06F24 (fmodstudiol) FMOD::SystemI::setInternalCallback
0x000007FEBDAC6239 (fmodstudiol) FMOD_Studio_VCA_SetVolume
  ERROR: SymGetSymFromAddr64, GetLastError: 'Attempt to access invalid address.' (Address: 000007FEBD9CBA82)
0x000007FEBD9CBA82 (fmodstudiol) (function-name not available)
  ERROR: SymGetSymFromAddr64, GetLastError: 'Attempt to access invalid address.' (Address: 000007FEBDA05352)
0x000007FEBDA05352 (fmodstudiol) (function-name not available)
0x000007FEBDA6E027 (fmodstudiol) FMOD::Studio::System::stopCommandCapture
0x000007FEBDA67D47 (fmodstudiol) FMOD::Studio::System::release
0x00000000471D49EA (Mono JIT Code) (wrapper managed-to-native) FMOD.Studio.System:FMOD_Studio_System_Release (intptr)
0x00000000471D48AB (Mono JIT Code) [...\Assets\Plugins\FMOD\src\Runtime\wrapper\fmod_studio.cs:421] FMOD.Studio.System:release () 
0x00000000471D4663 (Mono JIT Code) [...\Assets\Plugins\FMOD\src\Runtime\RuntimeManager.cs:620] FMODUnity.RuntimeManager:Destroy () 
0x0000000046D89C33 (Mono JIT Code) [...\Assets\Plugins\FMOD\src\Runtime\RuntimeManager.cs:638] FMODUnity.RuntimeManager:HandlePlayModeStateChange (UnityEditor.PlayModeStateChange) 

funnily enough this only happens in my test scene
ingame, where FMOD Studio events are actually used, this doesn’t seem to occur

strange

Ok so here’s the situation right now, the script works, but I need a helper script to run FMODUnity.RuntimeManager.StudioSystem.getCoreSystem() and call release on it in OnDestroy to even have a chance of the editor not completely freezing with high CPU usage

this is the only thing in the log after stopping playback, no errors or anything like that

Refresh: detecting if any assets need to be imported or removed ...

Refresh Completed time: 0.071120s
	Asset Scan time: 0.067765s
	Asset Hashing: 0.000000s [0 B, 0.000000 mb/s]
	Asset Import (Scripting) time: 0.000000s (count: 0)
	Post Processs Assets (Scripting) time: 0.000000s
	Asset Rehashing: 0.000000s [0 B, 0.000000 mb/s]
	Asset Import (Non Scripting) time: 0.000000s (count: 0)
	Post Process Assets (Non Scripting) time: 0.000000s
	Dependent Assets to Import Queue time: 0.000000s

Load scene 'Temp/__Backupscenes/0.backup' time: 0.773826 ms 
Unloading 3 Unused Serialized files (Serialized files now loaded: 0)
System memory in use before: 371.4 MB.
System memory in use after: 348.4 MB.

Unloading 1448 unused Assets to reduce memory usage. Loaded Objects now: 2728.
Total: 14.069682 ms (FindLiveObjects: 0.653955 ms CreateObjectMapping: 0.140808 ms MarkObjects: 10.246939 ms  DeleteObjects: 3.025928 ms)

actually not even that helps anymore

weird