Code:
/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Speech / Src / Internal / Synthesis / AudioDeviceOut.cs / 1 / AudioDeviceOut.cs
//------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // // // This class defines the header used to identify a waveform-audio // buffer. // // History: // 2/1/2005 [....] Created from the Sapi Managed code //----------------------------------------------------------------- using System; using System.Collections.Generic; using System.Runtime.InteropServices; using System.Threading; using System.Diagnostics; namespace System.Speech.Internal.Synthesis { ////// Encapsulates Waveform Audio Interface playback functions and provides a simple /// interface for playing audio. /// internal class AudioDeviceOut : AudioBase, IDisposable { //******************************************************************* // // Constructors // //******************************************************************* #region Constructors ////// Create an instance of AudioDeviceOut. /// internal AudioDeviceOut (int curDevice, IAsyncDispatch asyncDispatch) { _delegate = new SafeNativeMethods.WaveOutProc (CallBackProc); _asyncDispatch = asyncDispatch; _curDevice = curDevice; } ~AudioDeviceOut () { Dispose (false); } ////// TODOC /// public void Dispose () { Dispose (true); GC.SuppressFinalize (this); } private void Dispose (bool disposing) { if (_deviceOpen && _hwo != IntPtr.Zero) { SafeNativeMethods.waveOutClose (_hwo); _deviceOpen = false; } if (disposing) { ((IDisposable) _evt).Dispose (); } } #endregion //******************************************************************** // // Internal Methods // //******************************************************************* #region Internal Methods #region AudioDevice implementation ////// Begin to play /// /// override internal void Begin (byte [] wfx) { if (_deviceOpen) { System.Diagnostics.Debug.Assert (false); throw new InvalidOperationException (); } // Get the alignments values WAVEFORMATEX.AvgBytesPerSec (wfx, out _nAvgBytesPerSec, out _blockAlign); MMSYSERR result; lock (_noWriteOutLock) { result = SafeNativeMethods.waveOutOpen (ref _hwo, _curDevice, wfx, _delegate, IntPtr.Zero, SafeNativeMethods.CALLBACK_FUNCTION); if (_fPaused && result == MMSYSERR.NOERROR) { result = SafeNativeMethods.waveOutPause (_hwo); } // set the flags _aborted = false; _deviceOpen = true; } if (result != MMSYSERR.NOERROR) { throw new AudioException (result); } // Reset the counter for the number of bytes written so far _bytesWritten = 0; // Nothing in the queue _evt.Set (); } ////// Begin to play /// override internal void End () { if (!_deviceOpen) { System.Diagnostics.Debug.Assert (false); throw new InvalidOperationException (); } lock (_noWriteOutLock) { _deviceOpen = false; MMSYSERR result; CheckForAbort (); if (_queueIn.Count != 0) { SafeNativeMethods.waveOutReset (_hwo); } // Close it; no point in returning errors if this fails result = SafeNativeMethods.waveOutClose (_hwo); if (result != MMSYSERR.NOERROR) { // This may create a dead lock System.Diagnostics.Debug.Assert (false); } } } ////// Play a wave file. /// /// override internal void Play (byte [] buffer) { if (!_deviceOpen) { System.Diagnostics.Debug.Assert (false); } else { int bufferSize = buffer.Length; _bytesWritten += bufferSize; System.Diagnostics.Debug.Assert (bufferSize % _blockAlign == 0); WaveHeader waveHeader = new WaveHeader (buffer); GCHandle waveHdr = waveHeader.WAVEHDR; MMSYSERR result = SafeNativeMethods.waveOutPrepareHeader (_hwo, waveHdr.AddrOfPinnedObject (), waveHeader.SizeHDR); if (result != MMSYSERR.NOERROR) { throw new AudioException (result); } lock (_noWriteOutLock) { if (!_aborted) { lock (_queueIn) { InItem item = new InItem (waveHeader); _queueIn.Add (item); // Something in the queue cannot exit anymore _evt.Reset (); } // Start playback of the first buffer result = SafeNativeMethods.waveOutWrite (_hwo, waveHdr.AddrOfPinnedObject (), waveHeader.SizeHDR); if (result != MMSYSERR.NOERROR) { lock (_queueIn) { _queueIn.RemoveAt (_queueIn.Count - 1); throw new AudioException (result); } } } } } } ////// Pause the playback of a sound. /// ///MMSYSERR.NOERROR if successful override internal void Pause () { lock (_noWriteOutLock) { if (!_aborted && !_fPaused) { if (_deviceOpen) { MMSYSERR result = SafeNativeMethods.waveOutPause (_hwo); if (result != MMSYSERR.NOERROR) { System.Diagnostics.Debug.Assert (false, ((int) result).ToString (System.Globalization.CultureInfo.InvariantCulture)); } } _fPaused = true; } } } ////// Resume the playback of a paused sound. /// ///MMSYSERR.NOERROR if successful override internal void Resume () { lock (_noWriteOutLock) { if (!_aborted && _fPaused) { if (_deviceOpen) { MMSYSERR result = SafeNativeMethods.waveOutRestart (_hwo); if (result != MMSYSERR.NOERROR) { System.Diagnostics.Debug.Assert (false); } } } } _fPaused = false; } ////// Wait for all the queued buffers to be played /// override internal void Abort () { lock (_noWriteOutLock) { _aborted = true; if (_queueIn.Count > 0) { SafeNativeMethods.waveOutReset (_hwo); _evt.WaitOne (); } } } override internal void InjectEvent (TTSEvent ttsEvent) { if (_asyncDispatch != null && !_aborted) { lock (_queueIn) { // Throw immediately if the queue is empty if (_queueIn.Count == 0) { _asyncDispatch.Post (ttsEvent); } else { // Will be thrown before the next write to the audio device _queueIn.Add (new InItem (ttsEvent)); } } } } ////// Wait for all the queued buffers to be played /// override internal void WaitUntilDone () { if (!_deviceOpen) { System.Diagnostics.Debug.Assert (false); throw new InvalidOperationException (); } _evt.WaitOne (); } #endregion #region Audio device specific methods #if unused_yet ////// Get the volume of this sound. /// /// Left channel volume level /// Right channel volume level ///MMSYSERR.NOERROR if successful internal MMSYSERR GetVolume (ref ushort volLeft, ref ushort volRight) { uint vol = 0; MMSYSERR result = SafeNativeMethods.waveOutGetVolume (_hwo, ref vol); if (result != MMSYSERR.NOERROR) { throw new AudioException (result); } volLeft = (ushort) (vol & 0x0000ffff); volRight = (ushort) (vol >> 16); return MMSYSERR.NOERROR; } ////// Sets the volume of this sound. /// /// Left channel volume level /// Right channel volume level ///MMSYSERR.NOERROR if successful internal void SetVolume (ushort volLeft, ushort volRight) { uint vol = ((uint) volLeft & 0x0000ffff) | ((uint) volRight << 16); MMSYSERR result = SafeNativeMethods.waveOutSetVolume (_hwo, vol); { throw new AudioException (result); } } #endif ////// Determine the number of available playback devices. /// ///Number of output devices internal static int NumDevices () { return SafeNativeMethods.waveOutGetNumDevs (); } internal static int GetDevicedId (string name) { for (int iDevice = 0; iDevice < NumDevices (); iDevice++) { string device; if (GetDeviceName (iDevice, out device) == MMSYSERR.NOERROR && string.Compare (device, name, StringComparison.OrdinalIgnoreCase) == 0) { return iDevice; } } return -1; } ////// Get the name of the specified playback device. /// /// ID of the device /// Destination string assigned the name ///MMSYSERR.NOERROR if successful internal static MMSYSERR GetDeviceName (int deviceId, [MarshalAs (UnmanagedType.LPWStr)] out string prodName) { prodName = string.Empty; SafeNativeMethods.WAVEOUTCAPS caps = new SafeNativeMethods.WAVEOUTCAPS (); MMSYSERR result = SafeNativeMethods.waveOutGetDevCaps ((IntPtr) deviceId, ref caps, Marshal.SizeOf (caps)); if (result != MMSYSERR.NOERROR) { return result; } prodName = caps.szPname; return MMSYSERR.NOERROR; } #endregion #endregion //******************************************************************** // // Internal Fields // //******************************************************************** #region Internal Fields override internal TimeSpan Duration { get { if (_nAvgBytesPerSec == 0) { return new TimeSpan (0); } return new TimeSpan ((_bytesWritten * TimeSpan.TicksPerSecond) / _nAvgBytesPerSec); } } #endregion //******************************************************************* // // Private Methods // //******************************************************************** #region Private Methods private void CallBackProc (IntPtr hwo, MM_MSG uMsg, IntPtr dwInstance, IntPtr dwParam1, IntPtr dwParam2) { if (uMsg == MM_MSG.MM_WOM_DONE) { InItem inItem; lock (_queueIn) { inItem = _queueIn [0]; inItem.ReleaseData (); _queueIn.RemoveAt (0); _queueOut.Add (inItem); // look for the next elements in the queue if they are events to throw! while (_queueIn.Count > 0) { inItem = _queueIn [0]; // Do we have an event or a sound buffer if (inItem._waveHeader == null) { if (_asyncDispatch != null && !_aborted) { _asyncDispatch.Post (inItem._userData); } _queueIn.RemoveAt (0); } else { break; } } } // if the queue is empty, then restart the callers thread if (_queueIn.Count == 0) { _evt.Set (); } } } private void ClearBuffers () { foreach (InItem item in _queueOut) { WaveHeader waveHeader = item._waveHeader; MMSYSERR result; result = SafeNativeMethods.waveOutUnprepareHeader (_hwo, waveHeader.WAVEHDR. AddrOfPinnedObject (), waveHeader.SizeHDR); if (result != MMSYSERR.NOERROR) { //System.Diagnostics.Debug.Assert (false); } } } private void CheckForAbort () { if (_aborted) { // Synchronous operation lock (_queueIn) { foreach (InItem inItem in _queueIn) { // Do we have an event or a sound buffer if (inItem._waveHeader != null) { WaveHeader waveHeader = inItem._waveHeader; SafeNativeMethods.waveOutUnprepareHeader (_hwo, waveHeader.WAVEHDR.AddrOfPinnedObject (), waveHeader.SizeHDR); } else { _asyncDispatch.Post (inItem._userData); } } _queueIn.Clear (); // if the queue is empty, then restart the callers thread _evt.Set (); } } ClearBuffers (); } #endregion //******************************************************************* // // Private Types // //******************************************************************* #region Private Types ////// This object must keet a reference to the waveHeader object /// so that the pinned buffer containing the data is not /// released before it is finished being played /// private class InItem : IDisposable { internal InItem (WaveHeader waveHeader) { _waveHeader = waveHeader; } internal InItem (object userData) { _userData = userData; } ////// TODOC /// public void Dispose () { if (_waveHeader != null) { _waveHeader.Dispose (); } } internal void ReleaseData () { if (_waveHeader != null) { _waveHeader.ReleaseData (); } } internal WaveHeader _waveHeader; internal object _userData; } #endregion //******************************************************************* // // Private Fields // //******************************************************************** #region Private Fields private List_queueIn = new List (); private List _queueOut = new List (); private int _blockAlign; private int _bytesWritten; private int _nAvgBytesPerSec; private IntPtr _hwo; private int _curDevice; private ManualResetEvent _evt = new ManualResetEvent (false); private SafeNativeMethods.WaveOutProc _delegate; private IAsyncDispatch _asyncDispatch; private bool _deviceOpen; private object _noWriteOutLock = new object (); private bool _fPaused; #endregion } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- ResourcePropertyMemberCodeDomSerializer.cs
- CryptoStream.cs
- DBNull.cs
- EncoderReplacementFallback.cs
- ContentIterators.cs
- SettingsProperty.cs
- SafeJobHandle.cs
- ProcessHost.cs
- BaseCodeDomTreeGenerator.cs
- TripleDESCryptoServiceProvider.cs
- DocumentApplicationJournalEntry.cs
- Rijndael.cs
- AttachedPropertyBrowsableAttribute.cs
- SqlDataSourceSelectingEventArgs.cs
- StateWorkerRequest.cs
- SystemIdentity.cs
- HandlerBase.cs
- ProgressBar.cs
- Bind.cs
- CngKeyCreationParameters.cs
- ProcessInputEventArgs.cs
- TabControlCancelEvent.cs
- XamlGridLengthSerializer.cs
- DataTableReaderListener.cs
- DataGridViewCellValidatingEventArgs.cs
- WebBrowserBase.cs
- FlowDecision.cs
- SimpleType.cs
- dataobject.cs
- FormViewPageEventArgs.cs
- X509CertificateRecipientServiceCredential.cs
- XamlVector3DCollectionSerializer.cs
- Container.cs
- XmlQueryStaticData.cs
- LambdaCompiler.Expressions.cs
- CompilerErrorCollection.cs
- BitmapEffectGroup.cs
- Blend.cs
- DefaultAuthorizationContext.cs
- EmissiveMaterial.cs
- Brush.cs
- CallSiteOps.cs
- XsltArgumentList.cs
- SqlDataAdapter.cs
- InvokePattern.cs
- AsnEncodedData.cs
- ErrorStyle.cs
- WebPartDisplayMode.cs
- _Rfc2616CacheValidators.cs
- ImageSourceConverter.cs
- ConstructorNeedsTagAttribute.cs
- InspectionWorker.cs
- ObjectDataSourceEventArgs.cs
- GrammarBuilderPhrase.cs
- ListViewItemSelectionChangedEvent.cs
- XPathPatternParser.cs
- XPathDescendantIterator.cs
- XmlSchemaImport.cs
- ParameterReplacerVisitor.cs
- NegatedCellConstant.cs
- DiagnosticTraceSource.cs
- ValidationErrorCollection.cs
- TextDecorationCollection.cs
- DisplayMemberTemplateSelector.cs
- XsltContext.cs
- LoginCancelEventArgs.cs
- DataGridViewCheckBoxColumn.cs
- Rect3D.cs
- TraceHwndHost.cs
- ConfigurationStrings.cs
- EpmContentSerializer.cs
- ArglessEventHandlerProxy.cs
- BooleanToSelectiveScrollingOrientationConverter.cs
- BinaryObjectInfo.cs
- GlyphCache.cs
- CompositeKey.cs
- PrinterSettings.cs
- WebZone.cs
- FunctionImportElement.cs
- FunctionCommandText.cs
- RuleSetBrowserDialog.cs
- GeneratedContractType.cs
- TargetConverter.cs
- AppDomainUnloadedException.cs
- GroupedContextMenuStrip.cs
- MessageDesigner.cs
- WebPartConnection.cs
- SrgsRulesCollection.cs
- FixedNode.cs
- KeyboardEventArgs.cs
- FunctionMappingTranslator.cs
- Geometry.cs
- HttpGetProtocolReflector.cs
- GroupStyle.cs
- XslException.cs
- KeyPressEvent.cs
- ContentType.cs
- DatePickerDateValidationErrorEventArgs.cs
- StringExpressionSet.cs
- ProvidersHelper.cs