AudioBase.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Speech / Src / Internal / Synthesis / AudioBase.cs / 1 / AudioBase.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.IO; 
using System.Runtime.InteropServices;
 
namespace System.Speech.Internal.Synthesis 
{
    ///  
    /// Encapsulates Waveform Audio Interface playback functions and provides a simple
    /// interface for playing audio.
    /// 
    internal abstract class AudioBase 
    {
        //******************************************************************* 
        // 
        // Constructors
        // 
        //*******************************************************************

        #region Constructors
 
        /// 
        /// Create an instance of AudioBase. 
        ///  
        internal AudioBase ()
        { 
        }

        #endregion
 
        //********************************************************************
        // 
        // Internal Methods 
        //
        //******************************************************************* 

        #region Internal Methods

        #region abstract Members 

        ///  
        /// Play a wave file. 
        /// 
        ///  
        internal abstract void Begin (byte [] wfx);

        /// 
        /// Play a wave file. 
        /// 
        internal abstract void End (); 
 
        /// 
        /// Play a wave file. 
        /// 
        /// 
        /// 
        internal virtual void Play (IntPtr pBuff, int cb) 
        {
            byte [] buffer = new byte [cb]; 
            Marshal.Copy (pBuff, buffer, 0, cb); 
            Play (buffer);
        } 

        /// 
        /// Play a wave file.
        ///  
        /// 
        internal virtual void Play (byte [] buffer) 
        { 
            GCHandle gc = GCHandle.Alloc (buffer);
            Play (gc.AddrOfPinnedObject (), buffer.Length); 
            gc.Free ();
        }

        ///  
        /// Pause the playback of a sound.
        ///  
        /// MMSYSERR.NOERROR if successful 
        internal abstract void Pause ();
 
        /// 
        /// Resume the playback of a paused sound.
        /// 
        /// MMSYSERR.NOERROR if successful 
        internal abstract void Resume ();
 
        ///  
        /// Throw an event synchronized with the audio stream
        ///  
        /// 
        internal abstract void InjectEvent (TTSEvent ttsEvent);

        ///  
        /// File operation are synchonous no wait
        ///  
        internal abstract void WaitUntilDone (); 

        ///  
        /// Wait for all the queued buffers to be played
        /// 
        internal abstract void Abort ();
 
        #endregion
 
        #region helpers 

        internal void PlayWaveFile (AudioData audio) 
        {
            // allocate some memory for the largest header
            try
            { 
                // Fake a header for ALaw and ULaw
                if (!string.IsNullOrEmpty (audio._mimeType)) 
                { 
                    WAVEFORMATEX wfx = new WAVEFORMATEX ();
 
                    wfx.nChannels = 1;
                    wfx.nSamplesPerSec = 8000;
                    wfx.nAvgBytesPerSec = 8000;
                    wfx.nBlockAlign = 1; 
                    wfx.wBitsPerSample = 8;
                    wfx.cbSize = 0; 
 
                    switch (audio._mimeType)
                    { 
                        case "audio/basic":
                            wfx.wFormatTag = (short) AudioFormat.EncodingFormat.ULaw;
                            break;
 
                        case "audio/x-alaw-basic":
                            wfx.wFormatTag = (short) AudioFormat.EncodingFormat.ALaw; 
                            break; 

                        default: 
                            throw new FormatException (SR.Get (SRID.UnknownMimeFormat));
                    }

                    Begin (wfx.ToBytes ()); 
                    try
                    { 
                        byte [] data = new byte [(int) audio._stream.Length]; 
                        audio._stream.Read (data, 0, data.Length);
                        Play (data); 
                    }
                    finally
                    {
                        WaitUntilDone (); 
                        End ();
                    } 
                } 
                else
                { 
                    BinaryReader br = new BinaryReader (audio._stream);

                    try
                    { 
                        byte [] wfx =GetWaveFormat (br);
 
                        if (wfx == null) 
                        {
                            throw new FormatException (SR.Get (SRID.NotValidAudioFile, audio._uri.ToString ())); 
                        }

                        Begin (wfx);
 
                        try
                        { 
                            while (true) 
                            {
                                DATAHDR dataHdr = new DATAHDR (); 

                                // check for the end of file (+8 for the 2 DWORD)
                                if (audio._stream.Position + 8 >= audio._stream.Length)
                                { 
                                    break;
                                } 
                                dataHdr._id = br.ReadUInt32 (); 
                                dataHdr._len = br.ReadInt32 ();
 
                                // Is this the WAVE data?
                                if (dataHdr._id == DATA_MARKER)
                                {
                                    byte [] ab = Helpers.ReadStreamToByteArray (audio._stream, dataHdr._len); 
                                    Play (ab);
                                } 
                                else 
                                {
                                    // Skip this RIFF fragment. 
                                    audio._stream.Seek (dataHdr._len, SeekOrigin.Current);
                                }
                            }
                        } 
                        finally
                        { 
                            WaitUntilDone (); 
                            End ();
                        } 
                    }
                    finally
                    {
                        ((IDisposable) br).Dispose (); 
                    }
                } 
            } 
            finally
            { 
                audio.Dispose ();
            }
        }
 
        internal static byte [] GetWaveFormat (BinaryReader br)
        { 
            // Read the riff Header 
            RIFFHDR riff = new RIFFHDR ();
 
            riff._id = br.ReadUInt32 ();
            riff._len = br.ReadInt32 ();
            riff._type = br.ReadUInt32 ();
 
            if (riff._id != RIFF_MARKER && riff._type != WAVE_MARKER)
            { 
                return null; ; 
            }
 
            BLOCKHDR block = new BLOCKHDR ();
            block._id = br.ReadUInt32 ();
            block._len = br.ReadInt32 ();
 
            if (block._id != FMT_MARKER)
            { 
                return null; ; 
            }
 
            // If the format is of type WAVEFORMAT then fake a cbByte with a length of zero
            byte [] wfx;
            wfx = br.ReadBytes (block._len);
 
            // Hardcode the value of the size for the structure element
            // as the C# compiler pads the structure to the closest 4 or 8 bytes 
            if (block._len == 16) 
            {
                byte [] wfxTemp = new byte [18]; 
                Array.Copy (wfx, wfxTemp, 16);
                wfx = wfxTemp;
            }
            return wfx; 
        }
 
        ///  
        ///
        ///  
        /// 
        /// 
        /// 
        ///  
        /// Position in the stream for the header
        internal static void WriteWaveHeader (Stream stream, WAVEFORMATEX waveEx, long position, int cData) 
        { 
            RIFFHDR riff = new RIFFHDR (0);
            BLOCKHDR block = new BLOCKHDR (0); 
            DATAHDR dataHdr = new DATAHDR (0);

            int cRiff = Marshal.SizeOf (riff);
            int cBlock = Marshal.SizeOf (block); 
            int cWaveEx = waveEx.Length;// Marshal.SizeOf (waveEx); // The CLR automatically pad the waveEx structure to dword boundary. Force 16.
            int cDataHdr = Marshal.SizeOf (dataHdr); 
 
            int total = cRiff + cBlock + cWaveEx + cDataHdr;
 
            using (MemoryStream memStream = new MemoryStream ())
            {
                BinaryWriter bw = new BinaryWriter (memStream);
                try 
                {
                    // Write the RIFF section 
                    riff._len = total + cData - 8/* - cRiff*/; // for the "WAVE" 4 characters 
                    bw.Write (riff._id);
                    bw.Write (riff._len); 
                    bw.Write (riff._type);

                    // Write the wave header section
                    block._len = cWaveEx; 
                    bw.Write (block._id);
                    bw.Write (block._len); 
 
                    // Write the FormatEx structure
                    bw.Write (waveEx.ToBytes ()); 
                    //bw.Write (waveEx.cbSize);

                    // Write the data section
                    dataHdr._len = cData; 
                    bw.Write (dataHdr._id);
                    bw.Write (dataHdr._len); 
 
                    stream.Seek (position, SeekOrigin.Begin);
                    stream.Write (memStream.GetBuffer (), 0, (int) memStream.Length); 
                }
                finally
                {
                    ((IDisposable) bw).Dispose (); 
                }
            } 
        } 

        #endregion 

        #endregion

        //******************************************************************** 
        //
        // Internal Property 
        // 
        //********************************************************************
 
        #region Internal Property

        internal abstract TimeSpan Duration { get; }
 
        internal virtual long Position { get { return 0; } }
 
        internal virtual bool IsAborted 
        {
            set 
            {
                _aborted = false;
            }
            get 
            {
                return _aborted; 
            } 
        }
 
        internal virtual byte [] WaveFormat { get { return null; } }

        #endregion
 
        //*******************************************************************
        // 
        // Protected Property 
        //
        //******************************************************************** 

        #region Protected Property

        protected bool _aborted; 

        #endregion 
 
        //*******************************************************************
        // 
        // Private Types
        //
        //*******************************************************************
 
        #region Private Types
 
        private const UInt32 RIFF_MARKER = 0x46464952; 
        private const UInt32 WAVE_MARKER = 0x45564157;
        private const UInt32 FMT_MARKER = 0x20746d66; 
        private const UInt32 DATA_MARKER = 0x61746164;

        [StructLayout (LayoutKind.Sequential)]
        private struct RIFFHDR 
        {
            internal UInt32 _id; 
            internal Int32 _len;             /* file length less header */ 
            internal UInt32 _type;            /* should be "WAVE" */
 
            internal RIFFHDR (int length)
            {
                _id = RIFF_MARKER;
                _type = WAVE_MARKER; 
                _len = length;
            } 
        } 

        [StructLayout (LayoutKind.Sequential)] 
        private struct BLOCKHDR
        {
            internal UInt32 _id;              /* should be "fmt " or "data" */
            internal Int32 _len;             /* block size less header */ 

            internal BLOCKHDR (int length) 
            { 
                _id = FMT_MARKER;
                _len = length; 
            }

        };
 
        [StructLayout (LayoutKind.Sequential)]
        private struct DATAHDR 
        { 
            internal UInt32 _id;              /* should be "fmt " or "data" */
            internal Int32 _len;              /* block size less header */ 

            internal DATAHDR (int length)
            {
                _id = DATA_MARKER; 
                _len = length;
            } 
        } 

        #endregion 
    }

    //*******************************************************************
    // 
    // Internal Types
    // 
    //******************************************************************** 

    #region Internal Methods 

    [System.Runtime.InteropServices.TypeLibTypeAttribute (16)]
    internal struct WAVEFORMATEX
    { 
#pragma warning disable 649
 
        internal Int16 wFormatTag; 
        internal Int16 nChannels;
        internal int nSamplesPerSec; 
        internal int nAvgBytesPerSec;
        internal Int16 nBlockAlign;
        internal Int16 wBitsPerSample;
        internal Int16 cbSize; 

#pragma warning restore 649 
 
        static internal WAVEFORMATEX ToWaveHeader (byte [] waveHeader)
        { 
            GCHandle gc = GCHandle.Alloc (waveHeader, GCHandleType.Pinned);
            IntPtr ptr = gc.AddrOfPinnedObject ();
            WAVEFORMATEX wfx = new WAVEFORMATEX ();
            wfx.wFormatTag = Marshal.ReadInt16 (ptr); 
            wfx.nChannels = Marshal.ReadInt16 (ptr, 2);
            wfx.nSamplesPerSec = Marshal.ReadInt32 (ptr, 4); 
            wfx.nAvgBytesPerSec = Marshal.ReadInt32 (ptr, 8); 
            wfx.nBlockAlign = Marshal.ReadInt16 (ptr, 12);
            wfx.wBitsPerSample = Marshal.ReadInt16 (ptr, 14); 
            wfx.cbSize = Marshal.ReadInt16 (ptr, 16);

            if (wfx.cbSize != 0)
            { 
                throw new InvalidOperationException ();
            } 
            gc.Free (); 
            return wfx;
        } 

        static internal void AvgBytesPerSec (byte [] waveHeader, out int avgBytesPerSec, out int nBlockAlign)
        {
            // Hardcode the value of the size for the structure element 
            // as the C# compiler pads the structure to the closest 4 or 8 bytes
            GCHandle gc = GCHandle.Alloc (waveHeader, GCHandleType.Pinned); 
            IntPtr ptr = gc.AddrOfPinnedObject (); 
            avgBytesPerSec = Marshal.ReadInt32 (ptr, 8);
            nBlockAlign = Marshal.ReadInt16 (ptr, 12); 
            gc.Free ();
        }

        internal byte [] ToBytes () 
        {
            System.Diagnostics.Debug.Assert (cbSize == 0); 
            GCHandle gc = GCHandle.Alloc (this, GCHandleType.Pinned); 
            byte [] ab = ToBytes (gc.AddrOfPinnedObject ());
            gc.Free (); 
            return ab;
        }

        static internal byte [] ToBytes (IntPtr waveHeader) 
        {
            // Hardcode the value of the size for the structure element 
            // as the C# compiler pads the structure to the closest 4 or 8 bytes 

            int cbSize = Marshal.ReadInt16 (waveHeader, 16); 
            byte [] ab = new byte [18 + cbSize];
            Marshal.Copy (waveHeader, ab, 0, 18 + cbSize);
            return ab;
        } 

        static internal WAVEFORMATEX Default 
        { 
            get
            { 
                WAVEFORMATEX wfx = new WAVEFORMATEX ();
                wfx.wFormatTag = 1;
                wfx.nChannels = 1;
                wfx.nSamplesPerSec = 22050; 
                wfx.nAvgBytesPerSec = 44100;
                wfx.nBlockAlign = 2; 
                wfx.wBitsPerSample = 16; 
                wfx.cbSize = 0;
                return wfx; 
            }
        }

        internal int Length 
        {
            get 
            { 
                return 18 + cbSize;
            } 
        }
    }

    #endregion 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.


                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK