/// <summary>
        /// Play an audio file inside an FMOD event. Will play once at a given position
        /// </summary>
        /// <param name="audioFile">Audio file.</param>
        /// <param name="eventName">Event name.</param>
        /// <param name="position">Position.</param>
        public static void PlayOneShotProgrammerSound(string audioFile, string eventName, Vector3 position)
        {
            audioFile = ExtensionsUtils.FindFile(audioFile);

            EVENT_CALLBACK callback = new EVENT_CALLBACK(ProgrammerEventCallback);

            EventDescription eventDescription = RuntimeManager.GetEventDescription(eventName);
            EventInstance    eventInstance;

            eventDescription.createInstance(out eventInstance);

            eventInstance.set3DAttributes(RuntimeUtils.To3DAttributes(position));

            eventInstance.setCallback(callback);

            ProgrammerSoundContext context = new ProgrammerSoundContext();

            context.file = audioFile;
            context.mode = MODE.CREATESAMPLE | MODE._3D_LINEARSQUAREROLLOFF | MODE.LOOP_NORMAL | MODE.NONBLOCKING;

            GCHandle handle = GCHandle.Alloc(context, GCHandleType.Pinned);

            eventInstance.setUserData(GCHandle.ToIntPtr(handle));

            eventInstance.start();
            eventInstance.release();
        }
        /// <summary>
        /// Play an audio file inside an FMOD Event. Will play once without taking in 3D position
        /// </summary>
        /// <param name="audioFile">Audio file.</param>
        /// <param name="eventName">Event name.</param>
        public static void PlayOneShotProgrammerSound(string audioFile, string eventName)
        {
            audioFile = ExtensionsUtils.FindFile(audioFile);

            // Create the callback that will handle creating and destroying the programmer sound
            EVENT_CALLBACK callback = new EVENT_CALLBACK(ProgrammerEventCallback);

            // Create our one time event
            EventDescription eventDescription = RuntimeManager.GetEventDescription(eventName);
            EventInstance    eventInstance;

            eventDescription.createInstance(out eventInstance);

            // Set callback
            eventInstance.setCallback(callback);

            // Create our user data that we'll user later when playing the event
            ProgrammerSoundContext context = new ProgrammerSoundContext
            {
                file = audioFile,
                mode = MODE.CREATESAMPLE | MODE.LOOP_NORMAL | MODE.NONBLOCKING
            };

            // Create our pointer. It is unpinned when we get this data later
            GCHandle handle = GCHandle.Alloc(context, GCHandleType.Pinned);

            eventInstance.setUserData(GCHandle.ToIntPtr(handle));

            eventInstance.start();
            eventInstance.release();
        }
        // Handles creation and destructin of the programmer sound
        static RESULT ProgrammerEventCallback(EVENT_CALLBACK_TYPE type, EventInstance studioEvent, IntPtr parameterPtr)
        {
            EventInstance eventInstance = studioEvent;

            IntPtr pointer;

            eventInstance.getUserData(out pointer);

            // This gets the user data we just gave to the event
            GCHandle handle = GCHandle.FromIntPtr(pointer);
            ProgrammerSoundContext context = handle.Target as ProgrammerSoundContext;

            switch (type)
            {
            case EVENT_CALLBACK_TYPE.CREATE_PROGRAMMER_SOUND:

                UnityEngine.Debug.Log("FMOD Extensions: Creating Programmer Sound");
                PROGRAMMER_SOUND_PROPERTIES props = (PROGRAMMER_SOUND_PROPERTIES)Marshal.PtrToStructure(parameterPtr, typeof(PROGRAMMER_SOUND_PROPERTIES));

                RESULT result = RESULT.OK;

                Sound sound;
                result = Instance.LowLevelSystem.createSound(context.file, context.mode, out sound);
                Instance.CheckResult(result, "FMOD.CreateSound");

                if (result == RESULT.OK)
                {
                    props.sound = sound.handle;
                    Marshal.StructureToPtr(props, parameterPtr, false);
                }
                break;

            case EVENT_CALLBACK_TYPE.DESTROY_PROGRAMMER_SOUND:
                UnityEngine.Debug.Log("FMOD Extensions: Destroying Programmer Sound");
                RESULT resultTwo = RESULT.OK;
                PROGRAMMER_SOUND_PROPERTIES properties = (PROGRAMMER_SOUND_PROPERTIES)Marshal.PtrToStructure(parameterPtr, typeof(PROGRAMMER_SOUND_PROPERTIES));
                Sound destroyingSound = new Sound {
                    handle = properties.sound
                };

                result = destroyingSound.release();
                Instance.CheckResult(resultTwo, "Sound.Release");
                break;

            case EVENT_CALLBACK_TYPE.DESTROYED:
                UnityEngine.Debug.Log("FMOD Extensions: Destroying Event");
                handle.Free();
                break;
            }
            return(RESULT.OK);
        }
        public static void PlayProgrammerSound(string audioFile, EventInstance instance)
        {
            // If we've already played this event and given it user data,
            // we only need to change the user data
            if (programmerInstances.Contains(instance))
            {
                // Get the user data that should be attached to the object
                IntPtr pointer;
                instance.getUserData(out pointer);

                GCHandle handle = GCHandle.FromIntPtr(pointer);
                ProgrammerSoundContext context = handle.Target as ProgrammerSoundContext;

                if (context != null)
                {
                    context.file = ExtensionsUtils.FindFile(audioFile);
                }
                // If there was no user data added, we'll have to add it here
                else
                {
                    context      = new ProgrammerSoundContext();
                    context.file = ExtensionsUtils.FindFile(audioFile);
                    context.mode = MODE.CREATESAMPLE | MODE.LOOP_NORMAL | MODE.NONBLOCKING;

                    handle = GCHandle.Alloc(context, GCHandleType.Pinned);
                    instance.setUserData(GCHandle.ToIntPtr(handle));

                    EVENT_CALLBACK callback = new EVENT_CALLBACK(ProgrammerEventCallback);
                    instance.setCallback(callback);
                }

                UnityEngine.Debug.Log("Changing User Data");
            }
            else
            {
                programmerInstances.Add(instance);

                ProgrammerSoundContext context = new ProgrammerSoundContext();
                context.file = ExtensionsUtils.FindFile(audioFile);
                context.mode = MODE.CREATESAMPLE | MODE.LOOP_NORMAL | MODE.NONBLOCKING;

                GCHandle handle = GCHandle.Alloc(context, GCHandleType.Pinned);
                instance.setUserData(GCHandle.ToIntPtr(handle));

                EVENT_CALLBACK callback = new EVENT_CALLBACK(ProgrammerEventCallback);
                instance.setCallback(callback);
            }
            instance.start();
        }