예제 #1
0
        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);
        }
예제 #2
0
        /// <summary>
        /// Dispose
        /// </summary>
        public void Dispose()
        {
            if (audioClient != null)
            {
                Stop();

                audioClient.Dispose();
                audioClient  = null;
                renderClient = null;
            }
        }
예제 #3
0
        private bool disposedValue = false;         // To detect redundant calls

        protected virtual void Dispose(bool disposing)
        {
            if (!disposedValue)
            {
                if (disposing)
                {
                    audioClient.Dispose();
                }

                disposedValue = true;
            }
        }
예제 #4
0
        /// <summary>
        /// Dispose
        /// </summary>
        public void Dispose()
        {
            if (audioClient != null)
            {
                Stop();

                audioClient.Dispose();
                audioClient  = null;
                renderClient = null;
                NativeMethods.CloseHandle(frameEventWaitHandle);
            }
        }
예제 #5
0
        public void StopListeningForPeakLevel()
        {
            if (_audioClient == null)
            {
                return;
            }

            _audioClient.Stop();
            _audioClient.Dispose();
            _audioClient = null;

            _audioClient = null;
        }
예제 #6
0
        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.
        }
예제 #7
0
 /// <summary>
 /// Dispose
 /// </summary>
 public void Dispose()
 {
     StopRecording();
     if (captureThread != null)
     {
         captureThread.Join();
         captureThread = null;
     }
     if (audioClient != null)
     {
         audioClient.Dispose();
         audioClient = null;
     }
 }
예제 #8
0
        /// <summary>
        /// Dispose
        /// </summary>
        public void Dispose()
        {
            if (audioClient != null)
            {
                Stop();

                audioClient.Dispose();
                audioClient  = null;
                renderClient = null;
            }
            if (resamplerDmoStream != null)
            {
                resamplerDmoStream.Dispose();
                resamplerDmoStream = null;
            }
        }
예제 #9
0
파일: MainForm.cs 프로젝트: yswenli/GFF
 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;
     }
 }
예제 #10
0
        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;
        }
예제 #12
0
        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;
        }
예제 #13
0
        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;
            }
        }
예제 #14
0
        /// <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;
        }
예제 #15
0
        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;
            }
        }
예제 #16
0
        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();
            }
        }
예제 #17
0
        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);
            }
        }
예제 #18
0
        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();
            }
        }
예제 #19
0
        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();
            }
        }