protected virtual void Dispose(bool disposing)
        {
            if (!disposedValue)
            {
                if (disposing)
                {
                    recordingStream?.Dispose();
                    recordingStream = null;

                    fileRecordingStream?.Dispose();
                    fileRecordingStream = null;

                    outputDevice?.Dispose();
                    outputDevice = null;

                    targetOutputDevice?.Dispose();
                    targetOutputDevice = null;

                    targetInputDevice?.Dispose();
                    targetInputDevice = null;
                }

                disposedValue = true;
            }
        }
        public void RecordVoiceStream(string filePath)
        {
            if (targetInputDevice is null)
            {
                //Set up device
                targetInputDevice = GetInputDevice(botConfig.VoiceInputDevice);
                if (targetInputDevice is null)
                {
                    targetInputDevice = GetDefaultInputDevice();

                    if (targetInputDevice is null)
                    {
                        //Failed to get a device
                        communication.SendErrorMessage("Unable to initialize voice input device.");
                        return;
                    }
                    else
                    {
                        communication.SendWarningMessage($"Audio input device {botConfig.VoiceInputDevice} not found. " +
                                                         $"Fell back to default audio input device: {targetInputDevice.DeviceFriendlyName}");
                    }
                }
            }

            if (fileRecordingStream is not null)
            {
                fileRecordingStream.StopRecording();
                fileRecordingStream.Dispose();
                fileRecordingStream = null;
            }

            fileRecordingPath   = filePath;
            fileRecordingStream = new BufferedWasapiQueuer(targetInputDevice, 10000);
        }
        private void CleanUpActiveStream()
        {
            if (recordingStream is not null)
            {
                //Clean up last effect
                recordingStream.StopRecording();
                recordingStream.Dispose();
                recordingStream = null;
            }

            if (fileRecordingStream is not null)
            {
                //Clean up last effect
                fileRecordingStream.StopRecording();
                fileRecordingStream.Dispose();
                fileRecordingStream = null;
            }

            if (outputDevice is not null)
            {
                outputDevice.Stop();
                outputDevice.Dispose();
                outputDevice = null;
            }
        }
        public void StopRecordingVoiceStream()
        {
            if (fileRecordingStream is null)
            {
                return;
            }

            fileRecordingStream.StopRecording();

            MediaFoundationApi.Startup();

            MediaFoundationEncoder.EncodeToMp3(
                fileRecordingStream.ApplyMicrophoneEffects(botConfig.MicConfiguration, new Effects.NoEffect()).ToWaveProvider(),
                fileRecordingPath);

            MediaFoundationApi.Shutdown();

            fileRecordingStream.Dispose();
            fileRecordingStream = null;
        }
        public void ResetVoiceStream()
        {
            if (targetOutputDevice is null)
            {
                //Set up device
#if DEBUG && USE_STANDARD_DEBUG_OUTPUT
                targetOutputDevice = GetDefaultOutputDevice();
#else
                targetOutputDevice = GetOutputDevice(botConfig.VoiceOutputDevice);
#endif
                if (targetOutputDevice is null)
                {
                    targetOutputDevice = GetDefaultOutputDevice();

                    if (targetOutputDevice is null)
                    {
                        //Failed to get a device
                        communication.SendErrorMessage("Unable to initialize voice output device.");
                        return;
                    }
                    else
                    {
                        communication.SendWarningMessage($"Audio output device {botConfig.VoiceOutputDevice} not found. " +
                                                         $"Fell back to default audio output device: {targetOutputDevice.DeviceFriendlyName}");
                    }
                }
            }

            if (targetInputDevice is null)
            {
                //Set up device
                targetInputDevice = GetInputDevice(botConfig.VoiceInputDevice);
                if (targetInputDevice is null)
                {
                    targetInputDevice = GetDefaultInputDevice();

                    if (targetInputDevice is null)
                    {
                        //Failed to get a device
                        communication.SendErrorMessage("Unable to initialize voice input device.");
                        return;
                    }
                    else
                    {
                        communication.SendWarningMessage($"Audio input device {botConfig.VoiceInputDevice} not found. " +
                                                         $"Fell back to default audio input device: {targetInputDevice.DeviceFriendlyName}");
                    }
                }
            }

            CleanUpActiveStream();

            if (botConfig.MicConfiguration.Enabled)
            {
                outputDevice = new WasapiOut(targetOutputDevice, AudioClientShareMode.Shared, true, 10);

                recordingStream = new BufferedWasapiQueuer(targetInputDevice, 1000);
                outputDevice.Init(recordingStream.ApplyMicrophoneEffects(botConfig.MicConfiguration, currentEffect));
                outputDevice.Play();
            }
        }