Example #1
0
 private bool FireUpBuffer(WaveOutBuffer buffer)
 {
     if (buffer.Refill(_source))
     {
         Interlocked.Increment(ref _activeBuffers);
         return(true);
     }
     return(false);
 }
Example #2
0
        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.");
            }
        }
Example #3
0
        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");
            }
        }
Example #4
0
        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);
            }
        }