private void InitializeInternal() { const int reftimesPerMillisecond = 10000; _audioClient = AudioClient.FromMMDevice(Device); _outputFormat = SetupWaveFormat(_source, _audioClient); long latency = _latency * reftimesPerMillisecond; AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED_TRY_AGAIN: try { if (!_eventSync) _audioClient.Initialize(_shareMode, AudioClientStreamFlags.None, latency, 0, _outputFormat, Guid.Empty); else //event sync { if (_shareMode == AudioClientShareMode.Exclusive) //exclusive { _audioClient.Initialize(_shareMode, AudioClientStreamFlags.StreamFlagsEventCallback, latency, latency, _outputFormat, Guid.Empty); } else //shared { _audioClient.Initialize(_shareMode, AudioClientStreamFlags.StreamFlagsEventCallback, 0, 0, _outputFormat, Guid.Empty); //latency = (int)(_audioClient.StreamLatency / reftimesPerMillisecond); } } } catch (CoreAudioAPIException exception) { if (exception.ErrorCode == unchecked((int)0x88890019)) //AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED { const long reftimesPerSec = 10000000; int framesInBuffer = _audioClient.GetBufferSize(); // ReSharper disable once PossibleLossOfFraction latency = (int)(reftimesPerSec * framesInBuffer / _outputFormat.SampleRate + 0.5); goto AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED_TRY_AGAIN; } throw; } if (_audioClient.StreamLatency != 0) //windows 10 returns zero, got no idea why => https://github.com/filoe/cscore/issues/11 { Latency = (int)(_audioClient.StreamLatency / reftimesPerMillisecond); } if (_eventSync) { _eventWaitHandle = new EventWaitHandle(false, EventResetMode.AutoReset); _audioClient.SetEventHandle(_eventWaitHandle.SafeWaitHandle.DangerousGetHandle()); } _renderClient = AudioRenderClient.FromAudioClient(_audioClient); }
private bool FeedBuffer(AudioRenderClient renderClient, byte[] buffer, int numFramesCount, int frameSize) { //calculate the number of bytes to "feed" int count = numFramesCount * frameSize; count -= (count % _source.WaveFormat.BlockAlign); //if the driver did not request enough data, return true to continue playback if (count <= 0) return true; //get the requested data int read = _source.Read(buffer, 0, count); //if the source did not provide enough data, we abort the playback by returning false if (read <= 0) return false; //calculate the number of FRAMES to request int actualNumFramesCount = read / frameSize; //again there are some special requirements for exclusive mode AND eventsync if (_shareMode == AudioClientShareMode.Exclusive && _eventSync && read < count) { /* The caller can request a packet size that is less than or equal to the amount * of available space in the buffer (except in the case of an exclusive-mode stream * that uses event-driven buffering; for more information, see IAudioClient::Initialize). * see https://msdn.microsoft.com/en-us/library/windows/desktop/dd368243%28v=vs.85%29.aspx - remarks*/ //since we have to provide exactly the requested number of frames, we clear the rest of the array Array.Clear(buffer, read, count - read); //set the number of frames to request memory for, to the number of requested frames actualNumFramesCount = numFramesCount; } IntPtr ptr = renderClient.GetBuffer(actualNumFramesCount); //we may should introduce a try-finally statement here, but the Marshal.Copy method should not //throw any relevant exceptions ... so we should be able to always release the packet Marshal.Copy(buffer, 0, ptr, read); renderClient.ReleaseBuffer(actualNumFramesCount, AudioClientBufferFlags.None); return true; }
private void InitializeInternal() { _audioClient = AudioClient.FromMMDevice(Device); _outputFormat = SetupWaveFormat(_source.WaveFormat, _audioClient); long latency = _latency * 10000; if (!_eventSync) { _audioClient.Initialize(_shareMode, AudioClientStreamFlags.None, latency, 0, _outputFormat, Guid.Empty); } else //event sync { if (_shareMode == AudioClientShareMode.Exclusive) //exclusive { _audioClient.Initialize(_shareMode, AudioClientStreamFlags.StreamFlags_EventCallback, latency, latency, _outputFormat, Guid.Empty); } else //shared { _audioClient.Initialize(_shareMode, AudioClientStreamFlags.StreamFlags_EventCallback, 0, 0, _outputFormat, Guid.Empty); _latency = (int)(_audioClient.StreamLatency / 10000); } _eventWaitHandle = new EventWaitHandle(false, EventResetMode.AutoReset); _audioClient.SetEventHandle(_eventWaitHandle.SafeWaitHandle.DangerousGetHandle()); } _renderClient = AudioRenderClient.FromAudioClient(_audioClient); _simpleAudioVolume = SimpleAudioVolume.FromAudioClient(_audioClient); _simpleAudioVolume.MasterVolume = 1f; }
private void CleanupResources() { if (_createdResampler && _source is DmoResampler) { ((DmoResampler)_source).DisposeResamplerOnly(); _source = null; } if (_renderClient != null) { _renderClient.Dispose(); _renderClient = null; } if (_audioClient != null && _audioClient.BasePtr != IntPtr.Zero) { try { _audioClient.StopNative(); _audioClient.Reset(); } catch (CoreAudioAPIException ex) { if (ex.ErrorCode != unchecked((int)0x88890001)) //AUDCLNT_E_NOT_INITIALIZED throw; } _audioClient.Dispose(); _audioClient = null; } if (_eventWaitHandle != null) { _eventWaitHandle.Close(); _eventWaitHandle = null; } _isInitialized = false; }
private bool FeedBuffer(AudioRenderClient renderClient, byte[] buffer, int numFramesCount, int frameSize) { int count = numFramesCount * frameSize; count -= (count % _source.WaveFormat.BlockAlign); if (count <= 0) return true; int read = _source.Read(buffer, 0, count); var ptr = renderClient.GetBuffer(numFramesCount); Marshal.Copy(buffer, 0, ptr, read); renderClient.ReleaseBuffer((int)(read / frameSize), AudioClientBufferFlags.None); return read > 0; }