/// <summary>
        /// Stop recording on the given driver
        /// </summary>
        /// <param name="recordingSound">Driver.</param>
        public static void StopRecording(RecordingSound recordingSound)
        {
            if (recordingSound.channel.hasHandle())
            {
                RESULT result = RESULT.OK;

                // Stop and remove channel
                result = recordingSound.channel.stop();
                Instance.CheckResult(result, "Channel.Stop");
                recordingSound.channel.clearHandle();

                // Stop recording and remove sound
                result = Instance.LowLevelSystem.recordStop(recordingSound.driver.id);
                recordingSound.sound.clearHandle();

                // Reset recording pos
                recordingSound.recordPos = 0;

                // Remove this from dictionary so we don't update it
                Instance.recordingSounds.Remove(recordingSound.driver.id);
            }
            else
            {
                UnityEngine.Debug.Log("FMOD Extensions: Recording Channel is null. Have you begun playback?");
            }
        }
        /// <summary>
        /// Starts to play the sound with the given ID.
        /// Called by RecordingSound struct
        /// </summary>
        /// <param name="id">Identifier.</param>
        public static void PlayRecording(RecordingSound recordingSound)
        {
            if (recordingSound.channel.hasHandle())
            {
                recordingSound.channel.setPaused(false);
            }
            else
            {
                if (recordingSound.sound.hasHandle())
                {
                    if (recordingSound.recordPos >= Settings.Instance.RecordingLatency)
                    {
                        RESULT result = RESULT.OK;

                        if (recordingSound.channelGroup.hasHandle())
                        {
                            result = Instance.LowLevelSystem.playSound(recordingSound.sound, recordingSound.channelGroup, true, out recordingSound.channel);
                            Instance.CheckResult(result, "FMOD.PlaySound");

                            recordingSound.channel.setReverbProperties(0, 0f);

                            recordingSound.channel.setVolume(0f);
                            recordingSound.channel.setPaused(false);

                            recordingSound.channel.setVolume(1f);

                            Instance.StartCoroutine(Instance.VolumeRamp(recordingSound, 1f));
                        }
                        else
                        {
                            result = Instance.LowLevelSystem.getMasterChannelGroup(out recordingSound.channelGroup);
                            Instance.CheckResult(result, "FMOD.GetMasterChannelGroup");

                            result = Instance.LowLevelSystem.playSound(recordingSound.sound, recordingSound.channelGroup, true, out recordingSound.channel);
                            Instance.CheckResult(result, "FMOD.PlaySound");

                            recordingSound.channel.setReverbProperties(0, 0f);

                            recordingSound.channel.setVolume(0f);
                            recordingSound.channel.setPaused(false);

                            recordingSound.channel.setVolume(1f);

                            Instance.StartCoroutine(Instance.VolumeRamp(recordingSound, 1f));
                        }
                    }
                    else
                    {
                        Instance.StartCoroutine(Instance.WaitForBuffer(recordingSound));
                    }
                }
            }
        }
        /// <summary>
        /// Record what is coming in from the given driver
        /// </summary>
        /// <returns>The record.</returns>
        /// <param name="driver">Driver.</param>
        public static RecordingSound StartRecording(RecordDriver driver, ChannelGroup channelgroup = new ChannelGroup())
        {
            if (driver.id == -1)
            {
                return(new RecordingSound());
            }

            RESULT result = RESULT.OK;

            CREATESOUNDEXINFO exInfo = new CREATESOUNDEXINFO();

            exInfo.cbsize           = Marshal.SizeOf(exInfo);
            exInfo.numchannels      = driver.speakerModeChannels;
            exInfo.format           = SOUND_FORMAT.PCM16;
            exInfo.defaultfrequency = driver.systemRate;
            exInfo.length           = (uint)driver.systemRate * (uint)driver.speakerModeChannels * 16; // (FROM FMOD EXAMPLES): nativeRate * sizeof(short) * nativeChannels
                                                                                                       // I'm just saying 16 as that's the size of a short
            Sound sound;

            result = Instance.LowLevelSystem.createSound(IntPtr.Zero, MODE.LOOP_NORMAL | MODE.OPENUSER, ref exInfo, out sound);
            Instance.CheckResult(result, "FMOD.CreateSound");

            result = Instance.LowLevelSystem.recordStart(driver.id, sound, true);
            Instance.CheckResult(result, "FMOD.RecordStart");

            uint soundLength = 0;

            result = sound.getLength(out soundLength, TIMEUNIT.PCM);
            Instance.CheckResult(result, "Sound.GetLength");

            // Add our currently recording sound to our dictionary so we can check its record position and do stuff to it in update
            RecordingSound recordingSound = new RecordingSound
            {
                driver = driver,
                sound  = sound
            };

            if (channelgroup.hasHandle())
            {
                recordingSound.channelGroup = channelgroup;
            }

            RecordingSound temp = new RecordingSound();

            if (Instance.recordingSounds.TryGetValue(driver.id, out temp))
            {
                return(temp);
            }

            Instance.recordingSounds.Add(driver.id, recordingSound);
            return(recordingSound);
        }
        private IEnumerator VolumeRamp(RecordingSound recordingSound, float volume)
        {
            float realVolume = 0f;

            while (realVolume < volume)
            {
                float nextVolume = realVolume + 0.1f;
                recordingSound.channel.setVolume(nextVolume);
                recordingSound.channel.getVolume(out realVolume);
                yield return(null);
            }
            yield return(null);
        }
        private IEnumerator WaitForBuffer(RecordingSound recordingSound)
        {
            RESULT result = RESULT.OK;

            while (recordingSound.recordPos < Settings.Instance.RecordingLatency)
            {
                bool recording = false;
                result = LowLevelSystem.isRecording(recordingSound.driver.id, out recording);

                if (!recording)
                {
                    recordingSound.Stop();
                    continue;
                }
                else
                {
                    result = LowLevelSystem.getRecordPosition(recordingSound.driver.id, out recordingSound.recordPos);
                    CheckResult(result, "FMOD.GetRecordPosition");
                }
                yield return(null);
            }
            PlayRecording(recordingSound);
            yield return(null);
        }