public static string Name(this Audio.Codecs.INetworkChatCodec codec) { string bitRate = codec.BitsPerSecond == -1 ? "VBR" : String.Format("{0:0.#}kbps", codec.BitsPerSecond / 1024.0); string text = String.Format("{0} ({1})", codec.Name, bitRate); return(text); }
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(); }
public void HandleAudio(Audio.Codecs.CodecID codecid, byte[] encoded) { if (isDisposed) { return; } Audio.Codecs.INetworkChatCodec remoteCodec = Codecs.SingleOrDefault(m => m.CodecID == codecid); if (remoteCodec == null) { Console.WriteLine("Bad Audio Packet: Codec ID {0}", codecid); return; } if (codecid != LastCodec) { LastCodec = codecid; CodecName = remoteCodec.Name(); } TimeSpan buffered = waveOut == null ? TimeSpan.Zero : waveProvider.BufferedDuration; bool isPlaying = buffered != TimeSpan.Zero; if (waveOut == null || waveProvider.WaveFormat != remoteCodec.RecordFormat || (!isPlaying && ShouldTryRestartOutput)) { Start(remoteCodec); } else if (!isPlaying) { UnderRuns++; } if (buffered <= FrameDropThresholdMs) { byte[] decoded = remoteCodec.Decode(encoded, encoded.Length); int length = decoded.Length; if (!isPlaying && AudioOutWPF.shouldRampUnderruns) { InputResampler.RampPCM16Volume(ref decoded, length, InputResampler.RampDirection.ZeroToFull); } var volume = LevelManager.LevelScalar; if (volume < 1.0f) { InputResampler.ScalePCM16VolumeDb(ref decoded, length, volume); } if (length > 0 && ShouldDropSilence) { int dropped = DropSilence(silenceThreshhold, ref decoded, ref length); DroppedSilence += dropped; } else if (ShouldAddSilence && length > 5) { bool silent = true; for (int i = 0; i < 5; i += 2) { if (decoded[i + 1] != 0 || decoded[i] > addSilenceThreshold) { silent = false; break; } } if (silent) { var silenceBytes = length / 4; var silence = new byte[silenceBytes]; byte silenceLevel = (byte)(addSilenceThreshold / 2); for (int i = 0; i < silenceBytes - 1; i += 2) { silence[i + 1] = 0; silence[i] = silenceLevel; } waveProvider.AddSamples(silence, 0, silenceBytes); AddedSilence += length; } } waveProvider.AddSamples(decoded, 0, length); } else { DroppedPackets++; } if (shouldUpdateDuration) { BufferedDuration = buffered; shouldUpdateDuration = false; } LastReceived = DateTime.UtcNow; }
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; } }
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; }
private void LoadSettings() { var settings = Settings.Container; string strCodec = settings.Codec; string strInputDevice = settings.InputDevice; var codecs = comboBoxCodecs.Items.OfType<CodecModel>(); if (codecs.Any()) { CodecModel selectCodecItem = null; if (!string.IsNullOrWhiteSpace(strCodec)) { selectCodecItem = codecs.Where(m => m.Text == strCodec).FirstOrDefault(); } SelectedCodec = selectCodecItem ?? codecs.First(); this.codec = SelectedCodec.Codec; } if (!string.IsNullOrWhiteSpace(strInputDevice)) { var selectInputDevice = InputList.Where(m => m.ToString() == strInputDevice).FirstOrDefault(); if (selectInputDevice != null) SelectedInputSource = selectInputDevice; } else { SelectedInputSource = InputList.FirstOrDefault(); if (comboInputGroups.Items.Count > 0) comboInputGroups.SelectedIndex = 0; } BufferTargetMs = settings.InputLatency; UseWaveEvent = settings.UseWaveInEvent; }