/// <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();
        }
        void Load()
        {
            // Path on the computer as that is what FMOD understands
            string fullFilePath = Application.dataPath + Settings.Instance.AssetLocation + File;

            // Get the combination of all the modes to pass into the createSound method
            MODE finalMode = ExtensionsUtils.CreateModeForLowLevelEmitter(LoopMode, Position, LoadType);

            // Get the channel group
            channelGroup = ExtensionsManager.GetChannelGroupFromBus(Bus);

            // Finally, create
            ExtensionsManager.Instance.LowLevelSystem.createSound(fullFilePath, finalMode, out sound);
        }
        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();
        }
        // ---------- Low Level Sounds ----------

        #region LowLevel Sounds

        public static RESULT LoadSound(string fileName, MODE mode, out Sound sound)
        {
            RESULT result = RESULT.OK;

            fileName = ExtensionsUtils.FindFile(fileName);
            Sound s;

            result = Instance.LowLevelSystem.createSound(fileName, mode, out s);
            Instance.CheckResult(result, "FMOD.CreateSound");


            sound = s;

            return(result);
        }
        public static void AddPolygon(FMOD.Geometry geometry, Geometry.Polygon[] polygons)
        {
            RESULT result = RESULT.OK;

            for (int i = 0; i < polygons.Length; i++)
            {
                result = geometry.addPolygon(polygons[i].directOcclusion,
                                             polygons[i].reverbOcclusion,
                                             polygons[i].doubleSided,
                                             polygons[i].vertices.Length,
                                             ExtensionsUtils.ToFMODVectorArray(polygons[i].vertices),
                                             out polygons[i].polygonIndex);
                Instance.CheckResult(result, "FMOD.AddPolygon");
            }
        }
        void Update()
        {
            // Get the listener position
            LowLevelSystem.get3DListenerAttributes(0, out pos, out vel, out forward, out up);
            listPos = ExtensionsUtils.ToUnityVector(pos);

            // Update the position of the low level sounds
            for (int i = 0; i < attachedInstances.Count; i++)
            {
                if (!attachedInstances[i].channel.hasHandle() || attachedInstances[i].transform == null)
                {
                    attachedInstances.RemoveAt(i);
                    continue;
                }
                VECTOR instancePos = attachedInstances[i].transform.position.ToFMODVector();
                VECTOR zero        = new VECTOR();
                VECTOR alt         = new VECTOR();

                if (attachedInstances[i].rigidbody)
                {
                    VECTOR instanceVel = attachedInstances[i].rigidbody.velocity.ToFMODVector();
                    attachedInstances[i].channel.set3DAttributes(ref instancePos, ref instanceVel, ref alt);
                }
                attachedInstances[i].channel.set3DAttributes(ref instancePos, ref zero, ref alt);
            }

            // Check currently playing programmer sounds and remove them from the list if they stop playing or are invalid
            for (int i = 0; i < programmerInstances.Count; i++)
            {
                if (!programmerInstances[i].hasHandle() || !programmerInstances[i].isValid())
                {
                    UnityEngine.Debug.Log("Removing programmer sound from list");
                    programmerInstances.RemoveAt(i);
                }
            }
        }