private bool FireUpBuffer(WaveOutBuffer buffer) { if (buffer.Refill(_source)) { Interlocked.Increment(ref _activeBuffers); return(true); } return(false); }
protected virtual void Callback(IntPtr handle, WaveMsg msg, UIntPtr user, WaveHeader header, UIntPtr reserved) { if (_hWaveOut != handle) { return; //message does not belong to this waveout instance } if (msg == WaveMsg.WOM_DONE) { GCHandle hBuffer = (GCHandle)header.userData; WaveOutBuffer buffer = hBuffer.Target as WaveOutBuffer; System.Threading.Interlocked.Decrement(ref _activeBuffers); if (buffer == null) { return; } if (_playbackState != SoundOut.PlaybackState.Stopped) { lock (_lockObj) { if (buffer.WriteData()) { System.Threading.Interlocked.Increment(ref _activeBuffers); } } } if (_activeBuffers == 0) { _playbackState = SoundOut.PlaybackState.Stopped; RaiseStopped(); } } else if (msg == WaveMsg.WOM_CLOSE) { var state = _playbackState; _playbackState = SoundOut.PlaybackState.Stopped; if (state != SoundOut.PlaybackState.Stopped) { RaiseStopped(); } Debug.WriteLine("WaveOut::Callback: Closing WaveOut."); } }
private void Callback(IntPtr handle, WaveMsg msg, IntPtr user, WaveHeader header, IntPtr reserved) { Debug.WriteLine(Thread.CurrentThread.ManagedThreadId + "|" + msg); if (_waveOutHandle != handle) { return; } if (msg == WaveMsg.WOM_DONE) { if (_callbackThread == null) { _callbackThread = Thread.CurrentThread; Debug.WriteLine("CallbackThread: " + Thread.CurrentThread.ManagedThreadId); } Debug.Assert(_callbackThread == Thread.CurrentThread, "Strange thread?"); var index = (int)header.userData; WaveOutBuffer buffer = _buffers[index]; Interlocked.Decrement(ref _activeBuffers); /* * The Play method starts all buffers. * In order to do that, it calls the waveOutWrite function. * If there is a delay between buffer0 and buffer1 * and buffer0 gets fired through this callback, the * waveOutWrite method for buffer1 can't be called * -> deadlock since the callback method waits until the * Play method releases the lock. * In order to avoid that, we are using a timeout of 10ms. * If the timeout exceeds, the index of the buffer gets * saved and fired within the next callback. * */ if (Monitor.TryEnter(_lockObject, 10)) { try { callback0: if (buffer != null && PlaybackState != PlaybackState.Stopped) { try { FireUpBuffer(buffer); } catch (Exception exception) { StopFromCallback(exception); } } if (_failedBuffers.Count > 0) { //continue until we find a buffer that failed and is not in queue. while (_failedBuffers.Count > 0 && (buffer = _buffers[(index = _failedBuffers.Dequeue())]).IsQueued == false) { Debug.WriteLine("Already queued:" + index); } if (buffer != null && !buffer.IsQueued) { Debug.WriteLine("Failed buffer: " + index); goto callback0; } } } finally { Monitor.Exit(_lockObject); } } else { _failedBuffers.Enqueue(index); } if (_activeBuffers <= 0) { StopFromCallback(null); } } else if (msg == WaveMsg.WOM_CLOSE) { if (PlaybackState != PlaybackState.Stopped) { StopFromCallback(null); } } else if (msg == WaveMsg.WOM_OPEN) { Debug.WriteLine("open"); } }
private void InitializeInternal() { Debug.WriteLine("Initialize, thread id: " + Thread.CurrentThread.ManagedThreadId); _callbackThread = null; var supportedFormats = new Queue <WaveFormat>(Device.SupportedFormats .OrderBy(x => Math.Abs(x.SampleRate - _source.WaveFormat.SampleRate)) .ThenBy(x => Math.Abs(x.BitsPerSample - _source.WaveFormat.BitsPerSample)) .ThenBy(x => Math.Abs(x.Channels - _source.WaveFormat.Channels))); var finalFormat = _source.WaveFormat; do { try { _waveOutHandle = CreateWaveOutHandle(finalFormat); } catch (MmException exception) { if (exception.Result == MmResult.BadFormat && supportedFormats.Count > 0) { finalFormat = supportedFormats.Dequeue(); } else if (exception.Result == MmResult.BadFormat && supportedFormats.Count == 0) { throw new Exception("No valid format could be found.", exception); } else { throw; } } } while (_waveOutHandle == IntPtr.Zero); if (finalFormat != _source.WaveFormat) { //the original format of the source is not supported //we have to convert the source //todo: test channel matrix conversion ChannelMatrix channelMatrix = null; if (UseChannelMixingMatrices) { try { channelMatrix = ChannelMatrix.GetMatrix(_source.WaveFormat, finalFormat); } catch (Exception) { Debug.WriteLine("No channelmatrix was found."); } } DmoResampler resampler = channelMatrix != null ? new DmoChannelResampler(_source, channelMatrix, finalFormat) : new DmoResampler(_source, finalFormat); resampler.Quality = 60; _source = resampler; } _failedBuffers.Clear(); var bufferSize = (int)WaveSource.WaveFormat.MillisecondsToBytes(_latency); _buffers = new WaveOutBuffer[BufferCount]; for (int i = 0; i < _buffers.Length; i++) { _buffers[i] = new WaveOutBuffer(_waveOutHandle, bufferSize, (IntPtr)i); } }