private void InitializeInternal() { var defaultFormat = _waveFormat; _audioClient = AudioClient.FromMMDevice(Device); /*if (_shareMode == AudioClientShareMode.Exclusive) * { * _waveFormat = _waveFormat ?? _audioClient.MixFormat; * } * else * { * _waveFormat = _waveFormat ?? _audioClient.MixFormat; * }*/ _waveFormat = _waveFormat ?? _audioClient.MixFormat; _waveFormat = SetupWaveFormat(_waveFormat, _audioClient); if (!_eventSync) { _audioClient.Initialize(_shareMode, AudioClientStreamFlags.None | GetStreamFlags(), _latency * ReftimesPerMillisecond, 0, _waveFormat, Guid.Empty); } else { if (_shareMode == AudioClientShareMode.Exclusive) { try { _audioClient.Initialize(_shareMode, AudioClientStreamFlags.StreamFlagsEventCallback | GetStreamFlags(), _latency * ReftimesPerMillisecond, _latency * ReftimesPerMillisecond, _waveFormat, Guid.Empty); } catch (CoreAudioAPIException e) { if (e.ErrorCode == unchecked ((int)0x88890019)) //AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED { int bufferSize = _audioClient.BufferSize; _audioClient.Dispose(); long hnsRequestedDuration = (long)(((double)ReftimesPerMillisecond * 1000 / _waveFormat.SampleRate * bufferSize) + 0.5); _audioClient = AudioClient.FromMMDevice(Device); if (defaultFormat == null) { _waveFormat = _audioClient.MixFormat; } _audioClient.Initialize(_shareMode, AudioClientStreamFlags.StreamFlagsEventCallback | GetStreamFlags(), hnsRequestedDuration, hnsRequestedDuration, _waveFormat, Guid.Empty); } } } else { _audioClient.Initialize(_shareMode, AudioClientStreamFlags.StreamFlagsEventCallback | GetStreamFlags(), 0, 0, _waveFormat, Guid.Empty); _latency = (int)(_audioClient.StreamLatency / ReftimesPerMillisecond); } _eventWaitHandle = new EventWaitHandle(false, EventResetMode.AutoReset); _audioClient.SetEventHandle(_eventWaitHandle.SafeWaitHandle.DangerousGetHandle()); } _audioCaptureClient = AudioCaptureClient.FromAudioClient(_audioClient); }
/// <summary> /// Dispose /// </summary> public void Dispose() { if (audioClient != null) { Stop(); audioClient.Dispose(); audioClient = null; renderClient = null; } }
private bool disposedValue = false; // To detect redundant calls protected virtual void Dispose(bool disposing) { if (!disposedValue) { if (disposing) { audioClient.Dispose(); } disposedValue = true; } }
/// <summary> /// Dispose /// </summary> public void Dispose() { if (audioClient != null) { Stop(); audioClient.Dispose(); audioClient = null; renderClient = null; NativeMethods.CloseHandle(frameEventWaitHandle); } }
public void StopListeningForPeakLevel() { if (_audioClient == null) { return; } _audioClient.Stop(); _audioClient.Dispose(); _audioClient = null; _audioClient = null; }
public void Dispose() { if (_audioClient == null) { return; } _audioClient.Stop(); _audioClient.Dispose(); _audioClient = null; // Not disposing the device as it may be in use in a recording. }
/// <summary> /// Dispose /// </summary> public void Dispose() { StopRecording(); if (captureThread != null) { captureThread.Join(); captureThread = null; } if (audioClient != null) { audioClient.Dispose(); audioClient = null; } }
/// <summary> /// Dispose /// </summary> public void Dispose() { if (audioClient != null) { Stop(); audioClient.Dispose(); audioClient = null; renderClient = null; } if (resamplerDmoStream != null) { resamplerDmoStream.Dispose(); resamplerDmoStream = null; } }
private void toolStripDropDownButton2_ButtonClick(object sender, EventArgs e) { if (_audioClient == null) { ClientConfig clientConfig = ClientConfig.Instance(); _audioClient = new AudioClient(clientConfig.IP, clientConfig.Port + 2); _audioClient.Start(); _audioClient.Join("audiochat"); } else { _audioClient.Quit(); _audioClient.Dispose(); _audioClient = null; } }
private void CleanupResources() { if (_createdResampler && _source is DmoResampler) { ((DmoResampler)_source).DisposeResamplerOnly(); _source = null; } if (_renderClient != null) { _renderClient.Dispose(); _renderClient = null; } if (_audioClient != null) { try { _audioClient.Reset(); } catch (CoreAudioAPIException ex) { if (ex.ErrorCode != unchecked ((int)0x88890001)) //AUDCLNT_E_NOT_INITIALIZED { throw; } } _audioClient.Dispose(); _audioClient = null; } if (_simpleAudioVolume != null) { _simpleAudioVolume.Dispose(); _simpleAudioVolume = null; } if (_eventWaitHandle != null) { _eventWaitHandle.Close(); _eventWaitHandle = null; } _isInitialized = false; }
public void StopListeningForPeakLevel() { if (_audioClientMic == null) { return; } _audioClientMic.Stop(); _audioClientMic.Dispose(); _audioClientMic = null; if (_audioClientSpeak == null) { return; } _audioClientSpeak.Stop(); _audioClientSpeak.Dispose(); _audioClientSpeak = null; }
private void UninitializeAudioClients() { if (_audioClient != null) { _audioClient.Dispose(); _audioClient = null; } if (_audioCaptureClient != null) { _audioCaptureClient.Dispose(); _audioCaptureClient = null; } if (_eventWaitHandle != null) { _eventWaitHandle.Close(); _eventWaitHandle = null; } _isInitialized = false; }
private void CleanUp() { logger.Debug("AudioSource::CleanUp()"); if (captureDevice != null) { captureDevice.Dispose(); captureDevice = null; } if (audioClient != null) { audioClient.Dispose(); audioClient = null; } if (frameEventWaitHandle != null) { frameEventWaitHandle.Dispose(); frameEventWaitHandle = null; } }
/// <summary> /// Dispose /// </summary> public void Dispose() { if (captureState == WasapiCaptureState.Disposed) { return; } try { StopRecording(); NativeMethods.CloseHandle(hEvent); audioClient?.Dispose(); } catch (Exception ex) { Debug.WriteLine("Exception disposing WasapiCaptureRT: " + ex.ToString()); } hEvent = IntPtr.Zero; audioClient = null; captureState = WasapiCaptureState.Disposed; }
internal async Task <IAudioClient> ConnectAudioAsync(ulong channelId, bool selfDeaf, bool selfMute, bool external) { TaskCompletionSource <AudioClient> promise; await _audioLock.WaitAsync().ConfigureAwait(false); try { await DisconnectAudioInternalAsync().ConfigureAwait(false); promise = new TaskCompletionSource <AudioClient>(); _audioConnectPromise = promise; if (external) { var _ = promise.TrySetResultAsync(null); await Discord.ApiClient.SendVoiceStateUpdateAsync(Id, channelId, selfDeaf, selfMute).ConfigureAwait(false); return(null); } if (_audioClient == null) { var audioClient = new AudioClient(this, Discord.GetAudioId(), channelId); audioClient.Disconnected += async ex => { if (!promise.Task.IsCompleted) { try { audioClient.Dispose(); } catch { } _audioClient = null; if (ex != null) { await promise.TrySetExceptionAsync(ex); } else { await promise.TrySetCanceledAsync(); } return; } }; audioClient.Connected += () => { var _ = promise.TrySetResultAsync(_audioClient); return(Task.Delay(0)); }; _audioClient = audioClient; } await Discord.ApiClient.SendVoiceStateUpdateAsync(Id, channelId, selfDeaf, selfMute).ConfigureAwait(false); } catch (Exception) { await DisconnectAudioInternalAsync().ConfigureAwait(false); throw; } finally { _audioLock.Release(); } try { var timeoutTask = Task.Delay(15000); if (await Task.WhenAny(promise.Task, timeoutTask) == timeoutTask) { throw new TimeoutException(); } return(await promise.Task.ConfigureAwait(false)); } catch (Exception) { await DisconnectAudioAsync().ConfigureAwait(false); throw; } }
public async Task FinishConnectAudio(int id, string url, string token) { var voiceState = GetVoiceState(CurrentUser.Id).Value; await _audioLock.WaitAsync().ConfigureAwait(false); try { if (AudioClient == null) { var audioClient = new AudioClient(this, id); audioClient.Disconnected += async ex => { await _audioLock.WaitAsync().ConfigureAwait(false); try { if (AudioClient == audioClient) //Only reconnect if we're still assigned as this guild's audio client { if (ex != null) { //Reconnect if we still have channel info. //TODO: Is this threadsafe? Could channel data be deleted before we access it? var voiceState2 = GetVoiceState(CurrentUser.Id); if (voiceState2.HasValue) { var voiceChannelId = voiceState2.Value.VoiceChannel?.Id; if (voiceChannelId != null) { await Discord.ApiClient.SendVoiceStateUpdateAsync(Id, voiceChannelId, voiceState2.Value.IsSelfDeafened, voiceState2.Value.IsSelfMuted); } } } else { try { AudioClient.Dispose(); } catch { } AudioClient = null; } } } finally { _audioLock.Release(); } }; AudioClient = audioClient; } await AudioClient.ConnectAsync(url, CurrentUser.Id, voiceState.VoiceSessionId, token).ConfigureAwait(false); await _audioConnectPromise.TrySetResultAsync(AudioClient).ConfigureAwait(false); } catch (OperationCanceledException) { await DisconnectAudioAsync(); } catch (Exception e) { await _audioConnectPromise.SetExceptionAsync(e).ConfigureAwait(false); await DisconnectAudioAsync(); } finally { _audioLock.Release(); } }
private async void PlayThread() { await Activate(); var playbackProvider = Init(); bool isClientRunning = false; try { if (this.resamplerNeeded) { var resampler = new WdlResamplingSampleProvider(playbackProvider.ToSampleProvider(), outputFormat.SampleRate); playbackProvider = new SampleToWaveProvider(resampler); } // fill a whole buffer bufferFrameCount = audioClient.BufferSize; bytesPerFrame = outputFormat.Channels * outputFormat.BitsPerSample / 8; readBuffer = new byte[bufferFrameCount * bytesPerFrame]; FillBuffer(playbackProvider, bufferFrameCount); int timeout = 3 * latencyMilliseconds; while (playbackState != WasapiOutState.Disposed) { if (playbackState != WasapiOutState.Playing) { playThreadEvent.WaitOne(500); } // If still playing and notification is ok if (playbackState == WasapiOutState.Playing) { if (!isClientRunning) { audioClient.Start(); isClientRunning = true; } // If using Event Sync, Wait for notification from AudioClient or Sleep half latency var r = NativeMethods.WaitForSingleObjectEx(frameEventWaitHandle, timeout, true); if (r != 0) { throw new InvalidOperationException("Timed out waiting for event"); } // See how much buffer space is available. int numFramesPadding = 0; // In exclusive mode, always ask the max = bufferFrameCount = audioClient.BufferSize numFramesPadding = (shareMode == AudioClientShareMode.Shared) ? audioClient.CurrentPadding : 0; int numFramesAvailable = bufferFrameCount - numFramesPadding; if (numFramesAvailable > 0) { FillBuffer(playbackProvider, numFramesAvailable); } } if (playbackState == WasapiOutState.Stopping) { // play the buffer out while (audioClient.CurrentPadding > 0) { await Task.Delay(latencyMilliseconds / 2); } audioClient.Stop(); isClientRunning = false; audioClient.Reset(); playbackState = WasapiOutState.Stopped; RaisePlaybackStopped(null); } if (playbackState == WasapiOutState.Disposing) { audioClient.Stop(); isClientRunning = false; audioClient.Reset(); playbackState = WasapiOutState.Disposed; var disposablePlaybackProvider = playbackProvider as IDisposable; if (disposablePlaybackProvider != null) { disposablePlaybackProvider.Dispose(); // do everything on this thread, even dispose in case it is Media Foundation } RaisePlaybackStopped(null); } } } catch (Exception e) { RaisePlaybackStopped(e); } finally { audioClient.Dispose(); audioClient = null; renderClient = null; NativeMethods.CloseHandle(frameEventWaitHandle); } }
internal async Task FinishConnectAudio(int id, string url, string token) { var voiceState = GetVoiceState(Discord.CurrentUser.Id).Value; await _audioLock.WaitAsync().ConfigureAwait(false); try { if (_audioClient == null) { var audioClient = new AudioClient(this, id); var promise = _audioConnectPromise; audioClient.Disconnected += async ex => { //If the initial connection hasn't been made yet, reconnecting will lead to deadlocks if (!promise.Task.IsCompleted) { try { audioClient.Dispose(); } catch { } _audioClient = null; if (ex != null) { await promise.TrySetExceptionAsync(ex); } else { await promise.TrySetCanceledAsync(); } return; } //TODO: Implement reconnect /*await _audioLock.WaitAsync().ConfigureAwait(false); * try * { * if (AudioClient == audioClient) //Only reconnect if we're still assigned as this guild's audio client * { * if (ex != null) * { * //Reconnect if we still have channel info. * //TODO: Is this threadsafe? Could channel data be deleted before we access it? * var voiceState2 = GetVoiceState(Discord.CurrentUser.Id); * if (voiceState2.HasValue) * { * var voiceChannelId = voiceState2.Value.VoiceChannel?.Id; * if (voiceChannelId != null) * { * await Discord.ApiClient.SendVoiceStateUpdateAsync(Id, voiceChannelId, voiceState2.Value.IsSelfDeafened, voiceState2.Value.IsSelfMuted); * return; * } * } * } * try { audioClient.Dispose(); } catch { } * AudioClient = null; * } * } * finally * { * _audioLock.Release(); * }*/ }; _audioClient = audioClient; } await _audioClient.ConnectAsync(url, Discord.CurrentUser.Id, voiceState.VoiceSessionId, token).ConfigureAwait(false); await _audioConnectPromise.TrySetResultAsync(_audioClient).ConfigureAwait(false); } catch (OperationCanceledException) { await DisconnectAudioInternalAsync().ConfigureAwait(false); } catch (Exception e) { await _audioConnectPromise.SetExceptionAsync(e).ConfigureAwait(false); await DisconnectAudioInternalAsync().ConfigureAwait(false); } finally { _audioLock.Release(); } }
private void DoRecording(AudioClient client) { Debug.WriteLine(client.BufferSize); var buf = new Byte[client.BufferSize * bytesPerFrame]; int bufLength = 0; int minPacketSize = waveFormat.AverageBytesPerSecond / 100; //100ms IntPtr hEvent = NativeMethods.CreateEventEx(IntPtr.Zero, IntPtr.Zero, 0, EventAccess.EVENT_ALL_ACCESS); client.SetEventHandle(hEvent); try { AudioCaptureClient capture = client.AudioCaptureClient; client.Start(); int packetSize = capture.GetNextPacketSize(); while (!this.stop) { IntPtr pData = IntPtr.Zero; int numFramesToRead = 0; AudioClientBufferFlags dwFlags = 0; if (packetSize == 0) { if (NativeMethods.WaitForSingleObjectEx(hEvent, 100, true) != 0) { throw new Exception("Capture event timeout"); } } pData = capture.GetBuffer(out numFramesToRead, out dwFlags); if ((int)(dwFlags & AudioClientBufferFlags.Silent) > 0) { pData = IntPtr.Zero; } if (numFramesToRead == 0) { continue; } int capturedBytes = numFramesToRead * bytesPerFrame; System.Runtime.InteropServices.Marshal.Copy(pData, buf, bufLength, capturedBytes); bufLength += capturedBytes; capture.ReleaseBuffer(numFramesToRead); if (bufLength >= minPacketSize) { if (DataAvailable != null) { DataAvailable(this, new WaveInEventArgs(buf, bufLength)); } bufLength = 0; } packetSize = capture.GetNextPacketSize(); } } catch (Exception ex) { RaiseRecordingStopped(ex); Debug.WriteLine("stop wasapi"); } finally { RaiseRecordingStopped(null); NativeMethods.CloseHandle(hEvent); client.Stop(); client.Dispose(); } }