示例#1
0
        /// <summary>
        /// Initialises the WaveOut device
        /// </summary>
        /// <param name="waveProvider">WaveProvider to play</param>
        public void Init(IWaveProvider waveProvider)
        {
            if (playbackState != PlaybackState.Stopped)
            {
                throw new InvalidOperationException("Can't re-initialize during playback");
            }
            if (hWaveOut != IntPtr.Zero)
            {
                // normally we don't allow calling Init twice, but as experiment, see if we can clean up and go again
                // try to allow reuse of this waveOut device
                // n.b. risky if Playback thread has not exited
                DisposeBuffers();
                CloseWaveOut();
            }

            this.callbackEvent = new AutoResetEvent(false);

            this.waveStream = waveProvider;
            int bufferSize = waveProvider.WaveFormat.ConvertLatencyToByteSize((DesiredLatency + NumberOfBuffers - 1) / NumberOfBuffers);

            MmResult result;

            lock (waveOutLock)
            {
                result = WaveInterop.waveOutOpenWindow(out hWaveOut, (IntPtr)DeviceNumber, waveStream.WaveFormat, callbackEvent.SafeWaitHandle.DangerousGetHandle(), IntPtr.Zero, WaveInterop.WaveInOutOpenFlags.CallbackEvent);
            }
            MmException.Try(result, "waveOutOpen");

            buffers       = new WaveOutBuffer[NumberOfBuffers];
            playbackState = PlaybackState.Stopped;
            for (int n = 0; n < NumberOfBuffers; n++)
            {
                buffers[n] = new WaveOutBuffer(hWaveOut, bufferSize, waveStream, waveOutLock);
            }
        }
示例#2
0
        /// <summary>
        /// Initialises the WaveOut device
        /// </summary>
        /// <param name="waveProvider">Wave provider to play</param>
        public void Init(IWaveProvider waveProvider)
        {
            if (Thread.CurrentThread.ManagedThreadId != waveOutThread.ManagedThreadId)
            {
                lock (actionQueue)
                {
                    actionQueue.Enqueue(new WaveOutAction(WaveOutFunction.Init, waveStream));
                    workAvailable.Set();
                }
                return;
            }

            waveStream = waveProvider;
            int bufferSize = waveProvider.WaveFormat.ConvertLatencyToByteSize(desiredLatency);

            //waveStream.GetReadSize((desiredLatency + 2) / 3);
            numBuffers = 3;

            MmException.Try(
                WaveInterop.waveOutOpen(out hWaveOut, (IntPtr)devNumber, waveStream.WaveFormat, callback, IntPtr.Zero,
                                        WaveInterop.CallbackFunction), "waveOutOpen");

            buffers       = new WaveOutBuffer[numBuffers];
            playbackState = PlaybackState.Stopped;
            var waveOutLock = new object();

            for (int n = 0; n < numBuffers; n++)
            {
                buffers[n] = new WaveOutBuffer(hWaveOut, bufferSize, waveStream, waveOutLock);
            }
        }
示例#3
0
        /// <summary>
        /// Init the wave provider.
        /// </summary>
        private void Init()
        {
            // Create the channels
            SampleChannel          channel  = new SampleChannel(_audioReader, true);
            MeteringSampleProvider provider = new MeteringSampleProvider(channel);

            // Create the wave provider.
            _waveProvider = new SampleToWaveProvider(provider);

            // calculate the buffer size.
            int bufferSize = _waveProvider.WaveFormat.ConvertLatencyToByteSize((DesiredLatency + NumberOfBuffers - 1) / NumberOfBuffers);

            MmResult result;

            lock (_waveOutLock)
            {
                result = _callbackInfo.WaveOutOpen(out _hWaveOut, _device.Index, _waveProvider.WaveFormat, _callback);
            }
            MmException.Try(result, "waveOutOpen");

            _buffers       = new WaveOutBuffer[NumberOfBuffers];
            _playbackState = PlaybackState.Stopped;

            for (int n = 0; n < NumberOfBuffers; n++)
            {
                _buffers[n] = new WaveOutBuffer(_hWaveOut, bufferSize, _waveProvider, _waveOutLock);
            }
        }
示例#4
0
 private void OnBufferDone(WaveOutBuffer buffer)
 {
     if (playbackState == PlaybackState.Playing)
     {
         if (!buffer.OnDone())
         {
             playbackState = PlaybackState.Stopped;
             RaisePlaybackStopped();
         }
     }
 }
        void CreateBuffers(int buffersCount, int bufferLength)
        {
            for (int i = 0; i < buffersCount; i++)
            {
                WaveOutBuffer buffer = new WaveOutBuffer(bufferLength);
                buffer._hdr.dwBufferLength = bufferLength;

                int result = Native.waveOutPrepareHeader(_hWaveout, buffer._gchHdr.AddrOfPinnedObject(), Marshal.SizeOf(buffer._hdr));
                System.Diagnostics.Debug.Assert(result == Native.MMSYSERR_NOERROR);

                _buffers.Add(buffer);
            }
        }
        void ReleaseBuffers()
        {
            for (int i = 0; i < _buffers.Count; i++)
            {
                WaveOutBuffer buffer = _buffers[i];

                int result = Native.waveOutUnprepareHeader(_hWaveout, buffer._gchHdr.AddrOfPinnedObject(), Marshal.SizeOf(buffer._hdr));
                System.Diagnostics.Debug.Assert(result == Native.MMSYSERR_NOERROR);

                buffer.Dispose();
            }

            _buffers.Clear();
        }
示例#7
0
 /// <summary>
 /// Made non-static so that playing can be stopped here
 /// </summary>
 /// <param name="hWaveOut"></param>
 /// <param name="uMsg"></param>
 /// <param name="dwInstance"></param>
 /// <param name="wavhdr"></param>
 /// <param name="dwReserved"></param>
 private void Callback(IntPtr hWaveOut, WaveMessage uMsg, IntPtr dwInstance, WaveHeader wavhdr, IntPtr dwReserved)
 {
     if (uMsg == WaveMessage.WaveOutDone)
     {
         GCHandle      hBuffer = (GCHandle)wavhdr.userData;
         WaveOutBuffer buffer  = (WaveOutBuffer)hBuffer.Target;
         Interlocked.Decrement(ref _queuedBuffers);
         Exception exception = null;
         // check that we're not here through pressing stop
         if (PlaybackState == PlaybackState.Playing)
         {
             // to avoid deadlocks in Function callback mode,
             // we lock round this whole thing, which will include the
             // reading from the stream.
             // this protects us from calling waveOutReset on another
             // thread while a WaveOutWrite is in progress
             lock (_waveOutLock)
             {
                 try
                 {
                     if (buffer.OnDone())
                     {
                         Interlocked.Increment(ref _queuedBuffers);
                     }
                 }
                 catch (Exception e)
                 {
                     // one likely cause is soundcard being unplugged
                     exception = e;
                 }
             }
         }
         if (_queuedBuffers == 0)
         {
             if (_callbackInfo.Strategy == WaveCallbackStrategy.FunctionCallback && _playbackState == PlaybackState.Stopped)
             {
                 // the user has pressed stop
                 // DO NOT raise the playback stopped event from here
                 // since on the main thread we are still in the waveOutReset function
                 // Playback stopped will be raised elsewhere
             }
             else
             {
                 // set explicitly for when we reach the end of the audio.
                 _playbackState = PlaybackState.Stopped;
                 RaisePlaybackStoppedEvent(exception, (_pressStop ? false : true));
             }
         }
     }
 }
        internal static void WaveOutProc(IntPtr hdrvr, int uMsg, IntPtr dwInstance, IntPtr dwParam1, IntPtr dwParam2)
        {
            if (uMsg == Native.MM_WOM_DONE)
            {
                try
                {
                    System.Diagnostics.Debug.Assert(dwInstance != IntPtr.Zero);
                    WinMMAudioRender instance = (WinMMAudioRender)((GCHandle)dwInstance).Target;

                    System.Diagnostics.Debug.Assert(dwParam1 != IntPtr.Zero);
                    Native.WAVEHDR hdr = (Native.WAVEHDR)Marshal.PtrToStructure(dwParam1, typeof(Native.WAVEHDR));

                    System.Diagnostics.Debug.Assert(hdr.dwUser != IntPtr.Zero);
                    WaveOutBuffer waveOutBuffer = (WaveOutBuffer)((GCHandle)hdr.dwUser).Target;

                    if (hdr.dwBufferLength > 0)
                    {
                        instance._totalDuration += hdr.dwBufferLength;
                        instance._callback.PlaybackProgress(instance._totalDuration, hdr.dwBufferLength, instance._fmt.nAvgBytesPerSec);
                    }

                    // if we are still playing get a new audio buffer
                    if (instance._started)
                    {
                        int length = 0;

                        if (instance._callback.NextAudioBuffer(waveOutBuffer._data, ref length))
                        {
                            System.Diagnostics.Debug.Assert(length <= waveOutBuffer._data.Length);

                            waveOutBuffer._hdr.dwBufferLength = length;

                            int result = Native.waveOutWrite(instance._hWaveout, waveOutBuffer._gchHdr.AddrOfPinnedObject(), Marshal.SizeOf(waveOutBuffer._hdr));
                            System.Diagnostics.Debug.Assert(result == Native.MMSYSERR_NOERROR);
                        }
                        else
                        {
                            // end of stream read
                            instance._started = false;
                        }
                    }
                }
                catch (Exception ex)
                {
                    System.Diagnostics.Debug.WriteLine(ex.ToString());
                }
            }
        }
示例#9
0
        /// <summary>
        /// Initialises the WaveOut device
        /// </summary>
        /// <param name="waveProvider">WaveProvider to play</param>
        public void Init(IWaveProvider waveProvider)
        {
            this.waveStream = waveProvider;
            int bufferSize = waveProvider.WaveFormat.ConvertLatencyToByteSize((DesiredLatency + NumberOfBuffers - 1) / NumberOfBuffers);

            MmResult result;

            lock (waveOutLock)
            {
                result = callbackInfo.WaveOutOpen(out hWaveOut, DeviceNumber, waveStream.WaveFormat, callback);
            }
            MmException.Try(result, "waveOutOpen");

            buffers       = new WaveOutBuffer[NumberOfBuffers];
            playbackState = PlaybackState.Stopped;
            for (int n = 0; n < NumberOfBuffers; n++)
            {
                buffers[n] = new WaveOutBuffer(hWaveOut, bufferSize, waveStream, waveOutLock);
            }
        }
示例#10
0
        /// <summary>
        /// Initialises the WaveOut device
        /// </summary>
        /// <param name="waveProvider">WaveProvider to play</param>
        public void Init(IWaveProvider waveProvider)
        {
            this.waveStream = waveProvider;
            int bufferSize = waveProvider.WaveFormat.ConvertLatencyToByteSize((DesiredLatency + NumberOfBuffers - 1) / NumberOfBuffers);

            MmResult result;
            lock (waveOutLock)
            {
                result = callbackInfo.WaveOutOpen(out hWaveOut, DeviceNumber, waveStream.WaveFormat, callback);
            }
            MmException.Try(result, "waveOutOpen");

            buffers = new WaveOutBuffer[NumberOfBuffers];
            playbackState = PlaybackState.Stopped;
            for (int n = 0; n < NumberOfBuffers; n++)
            {
                buffers[n] = new WaveOutBuffer(hWaveOut, bufferSize, waveStream, waveOutLock);
            }
        }
        public bool Start(WinMMAudioRenderCallback callback, int sampleRate, int channels, int bitsPerSample)
        {
            if (null == callback)
            {
                return(false);
            }

            if ((0 == sampleRate) || (0 == channels) || (0 == bitsPerSample))
            {
                return(false);
            }

            // only mono and stereo are supported
            if (channels > 2)
            {
                return(false);
            }

            Stop();

            _callback = callback;

            _fmt = new Native.WAVEFORMATEX();

            _fmt.wFormatTag      = Native.WAVE_FORMAT_PCM;
            _fmt.nChannels       = (short)channels;
            _fmt.nSamplesPerSec  = sampleRate;
            _fmt.nBlockAlign     = (short)((bitsPerSample >> 3) * channels);
            _fmt.nAvgBytesPerSec = _fmt.nBlockAlign * sampleRate;
            _fmt.wBitsPerSample  = (short)bitsPerSample;
            _fmt.cbSize          = (short)Marshal.SizeOf(_fmt);

            _gchThis = GCHandle.Alloc(this);

            int result = Native.waveOutOpen(out _hWaveout, Native.WAVE_MAPPER, _fmt, _waveOutProc, (IntPtr)_gchThis, Native.CALLBACK_FUNCTION);

            if (result != Native.MMSYSERR_NOERROR)
            {
                _gchThis.Free();
                _hWaveout = IntPtr.Zero;
                return(false);
            }

            _started       = true;
            _totalDuration = 0;

            CreateBuffers(5, _fmt.nBlockAlign * (_fmt.nSamplesPerSec / 50));     // 5 buffers, 20ms each buffer

            result = Native.waveOutPause(_hWaveout);
            System.Diagnostics.Debug.Assert(result == Native.MMSYSERR_NOERROR);

            // write the empty buffers
            for (int i = 0; i < _buffers.Count; i++)
            {
                WaveOutBuffer buffer = _buffers[i];
                buffer._hdr.dwBufferLength = 0;

                result = Native.waveOutWrite(_hWaveout, buffer._gchHdr.AddrOfPinnedObject(), Marshal.SizeOf(buffer._hdr));
                System.Diagnostics.Debug.Assert(Native.MMSYSERR_NOERROR == result);
            }

            result = Native.waveOutRestart(_hWaveout);
            System.Diagnostics.Debug.Assert(result == Native.MMSYSERR_NOERROR);

            return(true);
        }
示例#12
0
        /// <summary>
        /// Initialises the WaveOut device
        /// </summary>
        /// <param name="waveProvider">WaveProvider to play</param>
        public void Init(IWaveProvider waveProvider)
        {
            if (playbackState != PlaybackState.Stopped)
            {
                throw new InvalidOperationException("Can't re-initialize during playback");
            }
            if (hWaveOut != IntPtr.Zero)
            {
                // normally we don't allow calling Init twice, but as experiment, see if we can clean up and go again
                // try to allow reuse of this waveOut device
                // n.b. risky if Playback thread has not exited
                DisposeBuffers();
                CloseWaveOut();
            }

            this.callbackEvent = new AutoResetEvent(false);

            this.waveStream = waveProvider;
            int bufferSize = waveProvider.WaveFormat.ConvertLatencyToByteSize((DesiredLatency + NumberOfBuffers - 1) / NumberOfBuffers);

            MmResult result;
            lock (waveOutLock)
            {
                result = WaveInterop.waveOutOpenWindow(out hWaveOut, (IntPtr)DeviceNumber, waveStream.WaveFormat, callbackEvent.SafeWaitHandle.DangerousGetHandle(), IntPtr.Zero, WaveInterop.WaveInOutOpenFlags.CallbackEvent);
            }
            MmException.Try(result, "waveOutOpen");

            buffers = new WaveOutBuffer[NumberOfBuffers];
            playbackState = PlaybackState.Stopped;
            for (int n = 0; n < NumberOfBuffers; n++)
            {
                buffers[n] = new WaveOutBuffer(hWaveOut, bufferSize, waveStream, waveOutLock);
            }
        }