private void Start(Audio.Codecs.INetworkChatCodec codec)
        {
            ShouldTryRestartOutput = false;

            Stop();

            waveOut = GetWavePlayer();

            waveProvider = new BufferedWaveProvider(codec.RecordFormat);

            sampleChannel = new SampleChannel(waveProvider, false);
            sampleStream = new NotifyingSampleProvider(sampleChannel);
            sampleStream.Sample += (s, e) => aggregator.Add(e.Left);
            waveOut.Init(sampleStream);
            waveOut.Play();

            if (LevelManager == null)
                LevelManager = new AudioLevelManagerDisconnected();

            OutputFormat = codec.RecordFormat.ToString();
        }
        private void StopRecording()
        {
            if (waveIn != null)
            {
                if (waveIn is WasapiCapture)
                    ((WasapiCapture)waveIn).RecordingStopped -= wasapi_RecordingStopped;

                waveIn.DataAvailable -= waveIn_DataAvailable;
                try
                {
                    waveIn.StopRecording();
                }
                catch (NAudio.MmException ex)
                {
                    Console.WriteLine(ex.Message);
                }
                try
                {
                    Trace.WriteLine("Disposing waveIn");
                    waveIn.Dispose();
                    Trace.WriteLine("waveIn disposed");
                }
                catch
                {
                    Trace.WriteLine("waveIn NOT disposed");
                }
                waveIn = null;
            }
            if (LevelManager != null)
            {
                LevelManager.Dispose();
                LevelManager = null;
            }
            ControlsEnabled = true;
        }
 private void InitLevelManager()
 {
     var output = SelectedOutput;
     if (output != null)
     {
         switch (output.Provider)
         {
             case DeviceProvider.Wasapi:
                 LevelManager = new AudioOutLevelManager(output.MMDevice);
                 break;
             default:
                 LevelManager = null;
                 break;
         }
     }
     else
         LevelManager = null;
 }
        private void StartRecording(bool shouldTryUseExclusive = true)
        {
            if (waveIn != null)
                StopRecording();
            if (SelectedInputSource != null)
            {
                this.codec = SelectedCodec.Codec;

                var deviceFormat = WaveFormat.CreateIeeeFloatWaveFormat(codec.RecordFormat.SampleRate, codec.RecordFormat.Channels);
                bool canUseExclusive = false;

                if (SelectedInputSource.Provider == DeviceProvider.Wasapi)
                {
                    var mmdevice = SelectedInputSource.MMDevice;

                    WaveFormatExtensible bestMatch;
                    canUseExclusive = mmdevice.AudioClient.IsFormatSupported(AudioClientShareMode.Exclusive, deviceFormat, out bestMatch);
                    if (canUseExclusive && shouldTryUseExclusive)
                    {
                        if (bestMatch != null)
                            deviceFormat = bestMatch;
                    }
                    else
                    {
                        mmdevice.AudioClient.IsFormatSupported(AudioClientShareMode.Shared, deviceFormat, out bestMatch);
                        if (bestMatch != null)
                            deviceFormat = bestMatch;
                    }

                    if (deviceFormat.Encoding != WaveFormatEncoding.IeeeFloat && deviceFormat.BitsPerSample != 16)
                    {
                        deviceFormat = mmdevice.AudioClient.MixFormat;

                        if (mmdevice.AudioClient.IsFormatSupported(AudioClientShareMode.Exclusive, codec.RecordFormat))
                        {
                            canUseExclusive = true;
                            deviceFormat = codec.RecordFormat;
                        }
                        else if (mmdevice.AudioClient.IsFormatSupported(AudioClientShareMode.Shared, codec.RecordFormat))
                        {
                            canUseExclusive = false;
                            deviceFormat = codec.RecordFormat;
                        }
                        else
                        {
                            WaveFormat newFormat;
                            WaveFormat altWaveFormat = new WaveFormat(deviceFormat.SampleRate, 16, deviceFormat.Channels);
                            WaveFormat altFloatFormat = WaveFormat.CreateIeeeFloatWaveFormat(mmdevice.AudioClient.MixFormat.SampleRate, mmdevice.AudioClient.MixFormat.Channels);

                            if (mmdevice.AudioClient.IsFormatSupported(AudioClientShareMode.Exclusive, altFloatFormat))
                            {
                                canUseExclusive = true;
                                newFormat = altFloatFormat;
                            }
                            else if (mmdevice.AudioClient.IsFormatSupported(AudioClientShareMode.Exclusive, altWaveFormat))
                            {
                                canUseExclusive = true;
                                newFormat = altWaveFormat;
                            }
                            else if (mmdevice.AudioClient.IsFormatSupported(AudioClientShareMode.Shared, altFloatFormat))
                            {
                                canUseExclusive = false;
                                newFormat = altFloatFormat;
                            }
                            else if (mmdevice.AudioClient.IsFormatSupported(AudioClientShareMode.Shared, altWaveFormat))
                            {
                                canUseExclusive = false;
                                newFormat = altWaveFormat;
                            }
                            else
                                throw new Exception("Device does not support 16bit PCM, or device is in use");

                            deviceFormat = newFormat;

                            Console.WriteLine("Initializing Wasapi\n  Device: {0}\n  Format: {1}\n  Mode: {2}\n  Resampling: {3}",
                                mmdevice.FriendlyName,
                                deviceFormat,
                                canUseExclusive ? "Exclusive" : "Shared",
                                deviceFormat.Equals(codec.RecordFormat) ? "NO" : "YES");
                        }
                    }

                    AudioClientShareMode shareMode;
                    if (canUseExclusive && shouldTryUseExclusive)
                        shareMode = AudioClientShareMode.Exclusive;
                    else
                        shareMode = AudioClientShareMode.Shared;

                    Guid audioSessionGuid = Guid.NewGuid();
                    try
                    {
                        mmdevice.AudioClient.Reset();
                    }
                    catch { }

                    BufferTargetMs = Math.Max(BufferTargetMs, mmdevice.MinBufferDurationMs);
                    var w = new WasapiCapture(mmdevice, BufferTargetMs);
                    w.RecordingStopped += wasapi_RecordingStopped;
                    waveIn = w;
                    waveIn.WaveFormat = deviceFormat;
                    w.ShareMode = shareMode;

                    LevelManager = new AudioInLevelManager(w, mmdevice);
                }
                else
                {
                    Console.WriteLine("Initializing WaveIn{0}. Buffer:{1}ms Device:{2} Format:{3}", UseWaveEvent ? "Event" : "", BufferTargetMs, SelectedInputSource.WavDeviceNumber, deviceFormat);
                    if (UseWaveEvent)
                    {
                        var w = new WaveInEvent();
                        w.BufferMilliseconds = BufferTargetMs;
                        w.DeviceNumber = SelectedInputSource.WavDeviceNumber;
                        LevelManager = new AudioInLevelManager(w);
                        waveIn = w;
                    }
                    else
                    {
                        var w = new WaveIn();
                        w.BufferMilliseconds = BufferTargetMs;
                        w.DeviceNumber = SelectedInputSource.WavDeviceNumber;
                        LevelManager = new AudioInLevelManager(w);
                        waveIn = w;
                    }
                    waveIn.WaveFormat = deviceFormat;
                    canUseExclusive = false;
                }

                waveIn.DataAvailable += waveIn_DataAvailable;
                waveIn.RecordingStopped += waveIn_RecordingStopped;

                try
                {
                    waveIn.StartRecording();
                    ControlsEnabled = false;
                }
                catch (NAudio.MmException ex)
                {
                    Console.WriteLine("Audio Error: Couldn't open recording device\n{0}", ex.Message);
                    waveIn = null;
                    IsRecording = false;
                }
                catch (ArgumentException ex)
                {
                    Console.WriteLine("Couldn't start recording: {0}", ex.Message);
                    IsRecording = false;
                    return;
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Couldn't start recording: {0}", ex);
                    IsRecording = false;
                    return;
                }
            }
            else
                IsRecording = false;
        }