Question

example code to write to a sound card

Asked by: jdcoburn

hi -- i'm using C#, VS 2008 and .Net 3.5. I want to output to a sound card an arbitrary waveform developed programmatically. I assume that it will need to be in a 1D array containing ampitude values. I'm not sure how frequency will be deterimed -- i assume it will work through some setting to the sound card.
anyway, i've never interfaced to a sound card. The concept of a stream writer seems appropriate but i'm not sure how to set it up.
Jim

This Question has been solved and asker verified All Experts Exchange premium technology solutions are available to subscription members.

Subscribe now for full access to Experts Exchange and get

Instant Access to this Solution

  • Plus...
  • 30 Day FREE access, no risk, no obligation
  • Collaborate with the world's top tech experts
  • Unlimited access to our exclusive solution database
  • Never be left without tech help again

Subscribe Now

Asked On
2009-09-14 at 17:47:50ID24731524
Tags

C#

,

.Net 3.5

Topics

Computer Sound Cards

,

C# Programming Language

Participating Experts
2
Points
500
Comments
4

Trusted by hundreds of thousands everyday for fast, accurate and reliable tech support.

  • "The time we save is the biggest benefit of Experts Exchange to Warner Bros. What could take multiple guys 2 hours or more each to find is accessed in around 15 minutes on Experts Exchange." Mike Kapnisakis, Warner Bros.
  • "Our team likes having a resource that is more secure than just using Google and most experts using this service really know their stuff. It's nice to look here first versus using Google." Dayna Sellner, Lockheed Martin
  • "Anytime that I've been stumped with a problem, 9 out of 10 times Experts Exchange has either the accepted solution or an open discussion of the potential solution to the problem." Kenny Red, eBay Inc.

See what Experts Exchange can do for you.

Got a question?

We've got the answer.

Experts Exchange has been collecting answers to technology questions since 1996…3 million and counting! If you have a question, chances are we already have your answer.

Screenshot of Experts Exchange Knowledgebase

Need individual assistance?

Our experts are ready to help.

If you can't find the exact answer you're looking for, ask our exclusive community of 50,000 experts. You’ll get a personalized answer from a trusted professional.

Screenshot of Experts Exchange Knowledgebase

Want to learn from the best?

Read articles from industry experts.

Thousands of free tech tips, tricks, how-to’s and tutorials are available in our peer reviewed articles section. See for yourself how smart our experts are, no login required.

Screenshot of an Article

Working on a long term project?

Store your work and research.

Save solutions to your questions, answers you’ve discovered through searching plus helpful articles in your personal knowledgebase for easy future access.

Screenshot of Experts Exchange Knowledgebase

Access the answers to your technology questions today.

Subscribe Now

30-day free trial. Register in 60 seconds.

What Makes Experts Exchange Unique?

Members of the expert community talk about why the experience at Experts Exchange is different than what you will find anywhere else.

Trusted by the world's most respected brands.

image of each brand's logo

Faithfully serving IT professionals since 1996.

Experts Exchange Logo

Try it out and discover for yourself.

Subscribe Now

30-day free trial. Register in 60 seconds.

Related Solutions

  1. Sound  frequency
    How do I change the frequency of a wav. file ? I have made a Flight Simulator and wants to be able to change the engine sound.
  2. Beep frequency
    Does anybody know which registry key stores the default tone (frequency) of the system beep in windows nt 4? Is it possible to change it?
  3. java sound frequency
    I am interested in how to access a sound card to play a tone of a specific frequency, Please HELP
  4. Need someone to explain sound programming concepts.
    I know this will come up, so might as well get it out of the way now: I'm using VC++6 and VStudio.net on WindowsXP Now on to my dillema: I've been trying to figure out how sound data stored in a file travels to my speakers. Ultimately, I'd like to create a set of librarie...

Free Tech Articles

  1. WARNING: 5 Reasons why you should NEVER fix a computer for free.
    It is in our nature to love the puzzle. We are obsessed. The lot of us. We love puzzles. We love the challenge. We thrive on finding the answer. We hate disarray. It bothers us deep in our soul. W...
  2. SCCM OSD Basic troubleshooting
    SCCM 2007 OSD is a fantastic way to deploy operating systems, however, like most things SCCM issues can sometimes be difficult to resolve due to the sheer volume of logs to sift through and the dispe...
  3. Migrate Small Business Server 2003 to Exchange 2010 and Windows 2008 R2
    This guide is intended to provide step by step instructions on how to migrate from Small Business Server 2003 to Windows 2008 R2 with Exchange 2010. For this migration to work you will need the fo...
  4. Create a Win7 Gadget
    This article shows you how to create a simple "Gadget" -- a sort of mini-application supported by Windows 7 and Vista. Gadgets can be dropped anywhere on the desktop to provide instant information, ...
  5. Outlook continually prompting for username and password
    There have been a lot of questions recently regarding Outlook prompting for a username and password whilst using Exchange 2007. There are a few reasons why this would happen and I will try to cover t...
  6. Backup Exchange 2010 Information Store using Windows Backup
    There seems to be quite a lot of confusion around the ability to backup Exchange 2010 using the built in Windows Backup feature. This stems from the omission of this feature prior to Exchange 2007 s...

Cloud Class Webinars

  1. Avoiding Bugs in Microsoft Access
    Alison Balter takes and in-depth look at avoiding bugs in Access. In this webinar you will learn about using the immediate window to debug your applications, invoking the debugger, using breakpoints to troubleshoot, stepping through code, setting the next statement to execute, ...
  2. Top 10 Best New Features in Visio 2010
    Scott Helmers gives live demonstrations of the top 10 new features in Visio 2010. This webinar will teach you how to create compelling diagrams by adding shapes to the page with a single click, linking the shapes in a diagram to data in Excel (or SQL Server, or SharePoint), ...
  3. IT Consultant Business Secrets Revealed
    Michael Munger, Experts Exchange tech pro and IT consultant, pulls back the curtain on his very successful businesses and answers question on every IT consultant and business owner should know about. He shares secrets on what he did to solve the 5 most common problems in IT, ...
  4. Disaster Recovery and Business Continuity
    Quest CTO, Mike Billon, gives an overview of the steps involved in building a dunamic disaster recovery plan. Through case studies and an examination of software/hardware tooles for monitoring and testing, you'll gain a better understandin of where you are, where you want ...
  5. Organize Your Visio Diagrams with Containers and Lists
    Scott Helmers uses cross functional flowcharts, wireframe diagrams, data graphic legends and seating charts to teach you: how to ustilize all three new structured diagram components in Visio 2010, the best practices for organizeing shapes in previous version of Visio, how to organize ...
  6. How to Us Objects, Properties, Events and Methods in Microsoft Access
    Alison Dalter gives an in-depbth look at objects, properties, events and methods in Microsoft Access. In this webinar you will learn about using the object browser, referring to objects, working with properties and methods, working with object variables, understanding the ...

Join the Community

Give a Little. Get a Lot.

Join the community of experts here and help other tech pros by answering question in your area of expertise. You can earn FREE access to all Experts Exchange's premium features and resources.

Join the Community

Answers

 

by: mac-willPosted on 2009-09-14 at 18:06:33ID: 25330625

What do you mean write to a sound card?

Here are some classes and structs I once used to wrap winmm.dll.

There is a method to load and play a memorystream.  it is quite easy to make a memory stream from a byte array.

Say you wanted to 'play' a sine wave.  You just create a sine wave in  short array and modify the Winmm player to take a buffer instead of a 'Wavefile'

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Threading;
using System.IO;
 
namespace SoundDB
{
public class WaveFile
    {
 
        #region PRIVATE_FIELDS
 
        private String chunkID;
        private int chunkSize;
        private String format;
        private String subchunk1ID;
        private int subchunk1Size;
        private short audioFormat;
        private short numChannels;
        private int sampleRate;
        private int byteRate;
        private short blockAlign;
        private short bitsPerSample;
        private String subchunk2ID;
        private int subchunk2Size;
 
        private String waveFile;
        private int silentLevel;
 
        public byte[] fullSoundData;
 
        private short[] soundDataCh1;
        private short[] soundDataCh2;
 
        private int startIndex;
        private int playLength;
 
        #endregion
 
        #region PUBLIC_PROPERTIES
 
        public String ChunkID
        {
            get { return chunkID; }
            set { chunkID = value; }
        }
 
        public int ChunkSize
        {
            get { return chunkSize; }
            set { chunkSize = value; }
        }
 
        public String Format
        {
            get { return format; }
            set { format = value; }
        }
 
        public String Subchunk1ID
        {
            get { return subchunk1ID; }
            set { subchunk1ID = value; }
        }
 
        public int Subchunk1Size
        {
            get { return subchunk1Size; }
            set { subchunk1Size = value; }
        }
 
        public short AudioFormat
        {
            get { return audioFormat; }
            set { audioFormat = value; }
        }
 
        public short NumChannels
        {
            get { return numChannels; }
            set { numChannels = value; }
        }
 
        public int SampleRate
        {
            get { return sampleRate; }
            set { sampleRate = value; }
        }
 
        public int ByteRate
        {
            get { return byteRate; }
            set { byteRate = value; }
        }
 
        public short BlockAlign
        {
            get { return blockAlign; }
            set { blockAlign = value; }
        }
 
        public short BitsPerSample
        {
            get { return bitsPerSample; }
        }
 
        public String Subchunk2ID
        {
            get { return subchunk2ID; }
            set { subchunk2ID = value; }
        }
 
        public int Subchunk2Size
        {
            get { return subchunk2Size; }
            set { subchunk2Size = value; }
        }
 
        public String WaveFileName
        {
            get { return waveFile; }
            set { waveFile = value; }
        }
 
        public short[] SoundDataCh1
        {
            get { return soundDataCh1; }
            set { soundDataCh1 = value; }
        }
 
        public short[] SoundDataCh2
        {
            get { return soundDataCh2; }
            set { soundDataCh2 = value; }
        }
 
        public int SilentLevel
        {
            get { return silentLevel; }
            set { silentLevel = value; }
        }
 
        public byte[] FullSoundData
        {
            get { return fullSoundData; }
            set { fullSoundData = value; }
        }
 
 
        public int StartIndex
        {
            get { return startIndex; }
            set { startIndex = value; }
        }
 
 
        public int PlayLength
        {
            get { return playLength; }
            set { playLength = value; }
        }
 
        #endregion
 
       /// <summary>
       /// TODO
       /// </summary>
       /// <param name="theWaveFile"></param>
        public WaveFile(String theWaveFile)
        {
            try
            {
                waveFile = theWaveFile;
 
                using (FileStream fs = new FileStream(waveFile, FileMode.Open, FileAccess.Read))
                {
                    using (BinaryReader br = new BinaryReader(fs))
                    {
                        LoadWaveFileData(br);
                        br.Close();
                        fs.Close();
                    }
                }
            }
            catch (IOException e)
            {
                //TODO handle better...
                System.Windows.Forms.MessageBox.Show(e.Message);
            }
            catch (Exception e)
            {
                System.Windows.Forms.MessageBox.Show(e.Message);
            }
 
        }
 
        /// <summary>
        /// TODO
        /// </summary>
        /// <param name="theWaveFile"></param>
        public WaveFile(byte[] theWaveFile)
        {
            try
            {
                waveFile = "";
 
                using (MemoryStream Ms = new MemoryStream(theWaveFile, 0, theWaveFile.Length))
                {
                    using (BinaryReader br = new BinaryReader(Ms))
                    {
                        LoadWaveFileData(br);
                        br.Close();
                        Ms.Close();
                    }
                }
            }
            catch (IOException e)
            {
                System.Windows.Forms.MessageBox.Show(e.Message);
            }
            catch (Exception e)
            {
                System.Windows.Forms.MessageBox.Show(e.Message);
            }
 
        }
 
        private void LoadWaveFileData(BinaryReader theBR)
        {
            ASCIIEncoding encoding = new ASCIIEncoding();
 
            chunkID = encoding.GetString(theBR.ReadBytes(4));
            chunkSize = theBR.ReadInt32();
            format = encoding.GetString(theBR.ReadBytes(4));
            subchunk1ID = encoding.GetString(theBR.ReadBytes(4));
            subchunk1Size = theBR.ReadInt32();
            audioFormat = theBR.ReadInt16();
            numChannels = theBR.ReadInt16();
            sampleRate = theBR.ReadInt32();
            byteRate = theBR.ReadInt32();
            blockAlign = theBR.ReadInt16();
            bitsPerSample = theBR.ReadInt16();
            subchunk2ID = encoding.GetString(theBR.ReadBytes(4));
            subchunk2Size = theBR.ReadInt32();
 
            startIndex = 0;
            playLength = subchunk2Size;
 
            if (chunkID != "RIFF" || format != "WAVE" || subchunk1ID != "fmt ")
            {
                throw new IOException("Not a valid WAVE file.");
            }
 
            if (bitsPerSample != 8 && bitsPerSample != 16)
            {
                throw new IOException("This WAVE file format is not supported. (8 or 16 bits per sample)");
            }
 
            if (numChannels != 1 && numChannels != 2)
            {
                throw new IOException("This WAVE file format is not supported. (Maximum 2 channels)");
            }
 
            if (audioFormat != 1)
            {
                throw new IOException("This WAVE file format is not supported. (Only PCM data)");
            }
 
            silentLevel = 0;
            if (bitsPerSample == 8)
                silentLevel = 128;
 
            int bytesPerSample = bitsPerSample / 8;
 
            soundDataCh1 = new short[subchunk2Size / bytesPerSample / numChannels];
            soundDataCh2 = null;
            if (numChannels == 2)
                soundDataCh2 = new short[subchunk2Size / bytesPerSample / numChannels];
 
 
            for (int i = 0; i < (subchunk2Size / bytesPerSample / numChannels); i++)
            {
                if (bitsPerSample == 8)
                {
                    soundDataCh1[i] = theBR.ReadByte();
                    if (numChannels == 2)
                    {
                        soundDataCh2[i] = theBR.ReadByte();
                    }
                }
                else
                {
                    soundDataCh1[i] = theBR.ReadInt16();
                    if (numChannels == 2)
                    {
                        soundDataCh2[i] = theBR.ReadInt16();
                    }
                }
            }
 
            theBR.BaseStream.Position = theBR.BaseStream.Position - subchunk2Size;
            fullSoundData = theBR.ReadBytes(subchunk2Size);
        }
 
        /// <summary>
        /// TODO
        /// </summary>
        /// <returns></returns>
        public float GetLengthInBytes()
        {
            return subchunk2Size;
        }
 
        /// <summary>
        /// TODO
        /// </summary>
        /// <returns></returns>
        public float GetLengthInSeconds()
        {
            //TODO  clean up
            float retLength = 0;
            retLength = (float)playLength / (float)bitsPerSample / (float)sampleRate / (float)numChannels * 8;
            return retLength;
        }
 
    }
 
    class WinmmPlayer : IWavePlayer
    {
        #region PRIVATE FIELDS AND CONSTANTS
 
        private WaveFile myWaveFile;
        private IntPtr mWaveOutDeviceHndl;
        private WAVEFORMATEX mWAVEFORMATEX;
        private Thread mPlayThread;
        private bool mCurrentlyPlaying;
        private bool mCurrentlyPaused;
        private bool mCurrentlyStopped;
        private SoundDataBuffer mSoundDataBuffers; // Implements IDispose
        private WinmmWrap.WinProcDelegate mCustomWaveOutProc;
        private const int NUM_OF_BUFFERS = 5;
        private const int BUFFER_SIZE = 8 * 1024; 
 
        #endregion
 
        public WinmmPlayer(WaveFile theWaveFile)
        {
            try
            {
                myWaveFile = theWaveFile;
                mCurrentlyPlaying = false;
                mCurrentlyPaused = false;
                mCurrentlyStopped = false;
                
                mCustomWaveOutProc = new WinmmWrap.WinProcDelegate(this.WaveOutProc);
                mWAVEFORMATEX = new WAVEFORMATEX(myWaveFile.SampleRate, myWaveFile.BitsPerSample, myWaveFile.NumChannels, myWaveFile.AudioFormat);
 
                int retVal = WinmmWrap.waveOutOpen(out mWaveOutDeviceHndl, -1, mWAVEFORMATEX, mCustomWaveOutProc, 0, WinmmWrap.CALLBACK_FUNCTION);
                if (retVal != WinmmWrap.MMSYSERR_NOERROR)
                    throw new Exception("waveOutOpen Error Returened: " + retVal.ToString());
 
                // LOAD BUFFERS IN CIRCULAR QUEU
                mSoundDataBuffers = new SoundDataBuffer(BUFFER_SIZE, mWaveOutDeviceHndl);
                SoundDataBuffer prevBuffer = mSoundDataBuffers;
                for (int i = 1; i < NUM_OF_BUFFERS; i++)
                {
                    SoundDataBuffer tempBuf = new SoundDataBuffer(BUFFER_SIZE, mWaveOutDeviceHndl);
                    prevBuffer.NextBuffer = tempBuf;
                    prevBuffer = tempBuf;
                }
                prevBuffer.NextBuffer = mSoundDataBuffers;
 
            }
            catch (Exception anyE)
            {
                System.Windows.Forms.MessageBox.Show(anyE.Message);
                //throw;
            }
 
        }
 
        public bool Play()
        {
            mCurrentlyStopped = false;
            
            if (mCurrentlyPaused)
            {
                mCurrentlyPaused = !(WinmmWrap.waveOutRestart(mWaveOutDeviceHndl) == WinmmWrap.MMSYSERR_NOERROR);
            }
 
            if (!mCurrentlyPlaying)
            {
                mPlayThread = new Thread(new ThreadStart(ThreadPlay));
                mPlayThread.Start();
                mCurrentlyPlaying = true;
            }
            return mCurrentlyPlaying;
        }
 
        private void ThreadPlay()
        {
            //TODO make more thread safe...
            bool atEndOfSound = false;
            SoundDataBuffer currentBufferToPlay = mSoundDataBuffers;
 
            using (MemoryStream soundDataStream = new MemoryStream(myWaveFile.FullSoundData, myWaveFile.StartIndex, myWaveFile.PlayLength))
            {
                soundDataStream.Position = 0;
 
                while (atEndOfSound == false && mCurrentlyStopped == false)
                {
                    currentBufferToPlay.NextBuffer.WaitForBufferToFinishPlaying();
                    currentBufferToPlay = currentBufferToPlay.NextBuffer;
                    lock (currentBufferToPlay)
                    {
                        int numBytesRead = currentBufferToPlay.LoadAndPlayBuffer(soundDataStream);
                        //Console.Write(numBytesRead.ToString() + "\n");
                        if (numBytesRead != BUFFER_SIZE)
                            atEndOfSound = true;
                    }
                }
 
                if (!mCurrentlyStopped)
                {
                    currentBufferToPlay = mSoundDataBuffers;
                    while (currentBufferToPlay.NextBuffer != mSoundDataBuffers)
                    {
                        currentBufferToPlay.WaitForBufferToFinishPlaying();
                        currentBufferToPlay = currentBufferToPlay.NextBuffer;
                    }
                    mSoundDataBuffers.WaitForBufferToFinishPlaying();
                }
                bool finishedPlaying = !(WinmmWrap.waveOutReset(mWaveOutDeviceHndl) == WinmmWrap.MMSYSERR_NOERROR);
                Thread.Sleep(200); // Allow all painting to finish before sayong we are done playing...
                mCurrentlyPlaying = finishedPlaying;
            }
        }
 
        void WaveOutProc(IntPtr hdrvr, int uMsg, int dwUser, ref WAVEHDR wavhdr, int dwParam2)
        {
            //System.Windows.Forms.MessageBox.Show(uMsg.ToString());
            if (uMsg == WinmmWrap.MM_WOM_DONE)
            {
                try
                {
                    GCHandle h = (GCHandle)wavhdr.dwUser;
                    SoundDataBuffer buf = (SoundDataBuffer)h.Target;
                    buf.FinishedPlaying();
                }
                catch
                {
                }
            }
        }
 
        public bool Pause()
        {
            if (mCurrentlyPlaying)
            {
                if (mCurrentlyPaused)
                {
                    mCurrentlyPaused = !(WinmmWrap.waveOutRestart(mWaveOutDeviceHndl) == WinmmWrap.MMSYSERR_NOERROR);
                }
                else
                {
                    mCurrentlyPaused = WinmmWrap.waveOutPause(mWaveOutDeviceHndl) == WinmmWrap.MMSYSERR_NOERROR;
                }
            }
            return mCurrentlyPaused;
        }
 
        public bool Stop()
        {
            mCurrentlyStopped = true;
            if (mCurrentlyPaused)
            {
                mCurrentlyPaused = !(WinmmWrap.waveOutReset(mWaveOutDeviceHndl) == WinmmWrap.MMSYSERR_NOERROR);
                mCurrentlyPlaying = mCurrentlyPaused;
            }
            return mCurrentlyStopped;
        }
 
        public int GetPositionInBytes()
        {
            //TODO null check...
            MMTIME a = new MMTIME();
            a.wType = WinmmWrap.TIME_BYTES;
            if (mWaveOutDeviceHndl != IntPtr.Zero)
                WinmmWrap.waveOutGetPosition(mWaveOutDeviceHndl, ref a, Marshal.SizeOf(a));
            return a.u;
        }
 
        public bool IsPlaying()
        {
            return !mCurrentlyPaused && mCurrentlyPlaying;
        }
 
        //TODO implement proper dispose patern...
        public void Dispose() { return; }
 
    }
 
    internal class SoundDataBuffer : IDisposable
    {
        //TODO make class more thread safe...
        #region CLASS FIELDS AND PROPERTIES
        
        private byte[] mSoundData;
        private int mBufferSize;
        private AutoResetEvent mCurrentlyInQueu = new AutoResetEvent(false);
        private bool mCurrentlyInQueuB;
        private WAVEHDR mWAVEHDR;
        private GCHandle mWAVEHDR_HNDL;
        private GCHandle mWAVEHDR_DATA_HNDL;
        private IntPtr mWaveOutDeviceHndl;
        private SoundDataBuffer nextBuffer;
        internal SoundDataBuffer NextBuffer
        {
            get { return nextBuffer; }
            set { nextBuffer = value; }
        } 
        #endregion
 
        public SoundDataBuffer(int theBufferSize , IntPtr theWaveOutDeviceHndl)
        {
            //TODO try block...
            mSoundData = new byte[theBufferSize];
            mWAVEHDR = new WAVEHDR();
            mWAVEHDR_HNDL = GCHandle.Alloc(mWAVEHDR, GCHandleType.Pinned);
            mWAVEHDR.dwUser = (IntPtr)GCHandle.Alloc(this);
            mWAVEHDR_DATA_HNDL =GCHandle.Alloc(mSoundData, GCHandleType.Pinned);
            mWAVEHDR.lpData = mWAVEHDR_DATA_HNDL.AddrOfPinnedObject();
            mBufferSize = theBufferSize;
            mWAVEHDR.dwBufferLength = mBufferSize;
            mWaveOutDeviceHndl = theWaveOutDeviceHndl;
            mCurrentlyInQueuB = false;
 
            int headPrepRetVal = WinmmWrap.waveOutPrepareHeader(mWaveOutDeviceHndl, ref mWAVEHDR, Marshal.SizeOf(mWAVEHDR));
            //System.Windows.Forms.MessageBox.Show(headPrepRetVal.ToString());
        }
 
        public void WaitForBufferToFinishPlaying()
        {
            if (mCurrentlyInQueuB)
            {
                mCurrentlyInQueu.WaitOne();
            }
            else
            {
                Thread.Sleep(0);
            }
        }
 
        public int LoadAndPlayBuffer(MemoryStream theDataStream)
        {
            //TODO try block....
            int numBytesRead = 0;
            numBytesRead = theDataStream.Read(mSoundData, 0, mBufferSize);
            Marshal.Copy(mSoundData, 0, mWAVEHDR.lpData, numBytesRead);
            mWAVEHDR.dwBufferLength = numBytesRead;
            mCurrentlyInQueu.Reset();
            int writeRetVal = WinmmWrap.waveOutWrite(mWaveOutDeviceHndl, ref mWAVEHDR, Marshal.SizeOf(mWAVEHDR));
            //System.Windows.Forms.MessageBox.Show(writeRetVal.ToString());
            mCurrentlyInQueuB =  writeRetVal == WinmmWrap.MMSYSERR_NOERROR;
            return numBytesRead;
        }
 
        public void FinishedPlaying()
        {
            mCurrentlyInQueuB = false;
            mCurrentlyInQueu.Set();            
        }
 
        //TODO implement proper dispose patern...
        ~SoundDataBuffer()
        {
            //Dispose();
        }
 
        public void Dispose()
        {
            if (mWAVEHDR.lpData != IntPtr.Zero)
            {
                WinmmWrap.waveOutUnprepareHeader(mWaveOutDeviceHndl, ref mWAVEHDR, Marshal.SizeOf(mWAVEHDR));
                mWAVEHDR_HNDL.Free();
                mWAVEHDR.lpData = IntPtr.Zero;
            }
            mCurrentlyInQueu.Close();
            if (mWAVEHDR_DATA_HNDL.IsAllocated)
                mWAVEHDR_DATA_HNDL.Free();
 
            GC.SuppressFinalize(this);
        }
    }
 
    /////////////////////////////////////////
    //  NATIVE STRUCTURES AND WRAPPER CLASS
    /////////////////////////////////////////
 
    [StructLayout(LayoutKind.Sequential)]
    internal class WAVEFORMATEX
    {
        public short wFormatTag;
        public short nChannels;
        public int nSamplesPerSec;
        public int nAvgBytesPerSec;
        public short nBlockAlign;
        public short wBitsPerSample;
        public short cbSize;
 
        public WAVEFORMATEX(int theSampleRate, int theBitsPerSample, int theNumChannels, short theAudioFormat)
        {
            wFormatTag = theAudioFormat;
            nChannels = (short)theNumChannels;
            nSamplesPerSec = theSampleRate;
            wBitsPerSample = (short)theBitsPerSample;
            cbSize = 0;
 
            nBlockAlign = (short)(theNumChannels * (theBitsPerSample / 8));
            nAvgBytesPerSec = nSamplesPerSec * nBlockAlign;
        }
    }
 
    [StructLayout(LayoutKind.Sequential)]
    internal struct WAVEHDR
    {
        public IntPtr lpData; // pointer to locked data buffer
        public int dwBufferLength; // length of data buffer
        public int dwBytesRecorded; // used for input only
        public IntPtr dwUser; // for client's use
        public int dwFlags; // assorted flags (see defines)
        public int dwLoops; // loop control counter
        public IntPtr lpNext; // PWaveHdr, reserved for driver
        public int reserved; // reserved for driver
    }
 
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    internal struct MMTIME
    {
        public int wType;
        public int u;
        public int x;
    }
 
    internal static class WinmmWrap
    {
        // CONSTANTS
        public const int MMSYSERR_NOERROR = 0; // no error
        public const int MM_WOM_OPEN = 0x3BB;
        public const int MM_WOM_CLOSE = 0x3BC;
        public const int MM_WOM_DONE = 0x3BD;
        public const int CALLBACK_FUNCTION = 0x00030000;    // dwCallback is a FARPROC 
        public const int CALLBACK_NULL = 0x0;
        public const int CALLBACK_TASK = 0x20000;
        public const int CALLBACK_TYPEMASK = 0x70000;
        public const int CALLBACK_WINDOW = 0x10000;
        public const int TIME_MS = 0x0001;      // time in milliseconds 
        public const int TIME_SAMPLES = 0x0002; // number of wave samples 
        public const int TIME_BYTES = 0x0004;   // current byte offset 
 
        // WINPROC DELEGATE
        public delegate void WinProcDelegate(IntPtr hdrvr, int uMsg, int dwUser, ref WAVEHDR wavhdr, int dwParam2);
 
        // NATIVE WINMM METHODS
        [DllImport("winmm.dll")]
        public static extern int waveOutGetNumDevs();
        [DllImport("winmm.dll")]
        public static extern int waveOutPrepareHeader(IntPtr hWaveOut, ref WAVEHDR lpWaveOutHdr, int uSize);
        [DllImport("winmm.dll")]
        public static extern int waveOutUnprepareHeader(IntPtr hWaveOut, ref WAVEHDR lpWaveOutHdr, int uSize);
        [DllImport("winmm.dll")]
        public static extern int waveOutWrite(IntPtr hWaveOut, ref WAVEHDR lpWaveOutHdr, int uSize);
        [DllImport("winmm.dll")]
        public static extern int waveOutOpen(out IntPtr hWaveOut, int uDeviceID, WAVEFORMATEX lpFormat, WinProcDelegate dwCallback, int dwInstance, int dwFlags);
        [DllImport("winmm.dll")]
        public static extern int waveOutReset(IntPtr hWaveOut);
        [DllImport("winmm.dll")]
        public static extern int waveOutClose(IntPtr hWaveOut);
        [DllImport("winmm.dll")]
        public static extern int waveOutPause(IntPtr hWaveOut);
        [DllImport("winmm.dll")]
        public static extern int waveOutRestart(IntPtr hWaveOut);
        [DllImport("winmm.dll")]
        public static extern int waveOutGetPosition(IntPtr hWaveOut, ref MMTIME lpInfo, int uSize);
        [DllImport("winmm.dll")]
        public static extern int waveOutSetVolume(IntPtr hWaveOut, int dwVolume);
        [DllImport("winmm.dll")]
        public static extern int waveOutGetVolume(IntPtr hWaveOut, out int dwVolume);
    }
}
                                              
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
165:
166:
167:
168:
169:
170:
171:
172:
173:
174:
175:
176:
177:
178:
179:
180:
181:
182:
183:
184:
185:
186:
187:
188:
189:
190:
191:
192:
193:
194:
195:
196:
197:
198:
199:
200:
201:
202:
203:
204:
205:
206:
207:
208:
209:
210:
211:
212:
213:
214:
215:
216:
217:
218:
219:
220:
221:
222:
223:
224:
225:
226:
227:
228:
229:
230:
231:
232:
233:
234:
235:
236:
237:
238:
239:
240:
241:
242:
243:
244:
245:
246:
247:
248:
249:
250:
251:
252:
253:
254:
255:
256:
257:
258:
259:
260:
261:
262:
263:
264:
265:
266:
267:
268:
269:
270:
271:
272:
273:
274:
275:
276:
277:
278:
279:
280:
281:
282:
283:
284:
285:
286:
287:
288:
289:
290:
291:
292:
293:
294:
295:
296:
297:
298:
299:
300:
301:
302:
303:
304:
305:
306:
307:
308:
309:
310:
311:
312:
313:
314:
315:
316:
317:
318:
319:
320:
321:
322:
323:
324:
325:
326:
327:
328:
329:
330:
331:
332:
333:
334:
335:
336:
337:
338:
339:
340:
341:
342:
343:
344:
345:
346:
347:
348:
349:
350:
351:
352:
353:
354:
355:
356:
357:
358:
359:
360:
361:
362:
363:
364:
365:
366:
367:
368:
369:
370:
371:
372:
373:
374:
375:
376:
377:
378:
379:
380:
381:
382:
383:
384:
385:
386:
387:
388:
389:
390:
391:
392:
393:
394:
395:
396:
397:
398:
399:
400:
401:
402:
403:
404:
405:
406:
407:
408:
409:
410:
411:
412:
413:
414:
415:
416:
417:
418:
419:
420:
421:
422:
423:
424:
425:
426:
427:
428:
429:
430:
431:
432:
433:
434:
435:
436:
437:
438:
439:
440:
441:
442:
443:
444:
445:
446:
447:
448:
449:
450:
451:
452:
453:
454:
455:
456:
457:
458:
459:
460:
461:
462:
463:
464:
465:
466:
467:
468:
469:
470:
471:
472:
473:
474:
475:
476:
477:
478:
479:
480:
481:
482:
483:
484:
485:
486:
487:
488:
489:
490:
491:
492:
493:
494:
495:
496:
497:
498:
499:
500:
501:
502:
503:
504:
505:
506:
507:
508:
509:
510:
511:
512:
513:
514:
515:
516:
517:
518:
519:
520:
521:
522:
523:
524:
525:
526:
527:
528:
529:
530:
531:
532:
533:
534:
535:
536:
537:
538:
539:
540:
541:
542:
543:
544:
545:
546:
547:
548:
549:
550:
551:
552:
553:
554:
555:
556:
557:
558:
559:
560:
561:
562:
563:
564:
565:
566:
567:
568:
569:
570:
571:
572:
573:
574:
575:
576:
577:
578:
579:
580:
581:
582:
583:
584:
585:
586:
587:
588:
589:
590:
591:
592:
593:
594:
595:
596:
597:
598:
599:
600:
601:
602:
603:
604:
605:
606:
607:
608:
609:
610:
611:
612:
613:
614:
615:
616:
617:
618:
619:
620:
621:
622:
623:
624:
625:
626:
627:
628:
629:
630:
631:
632:
633:
634:
635:
636:
637:
638:
639:
640:
641:
642:
643:
644:
645:
646:
647:
648:
649:
650:
651:
652:
653:
654:
655:
656:
657:
658:
659:
660:
661:
662:
663:
664:
665:
666:
667:
668:
669:
670:
671:
672:
673:
674:
675:
676:
677:
678:
679:
680:
681:
682:
683:
684:
685:
686:
687:
688:
689:
690:
691:
692:

Select allOpen in new window

 

by: jdcoburnPosted on 2009-09-14 at 19:44:51ID: 25331286

I'm building a data acquisition system that's bringing in a non-periodic analog signal. my customer wants the option of "listening" to the signal in addition to displaying it as a graph. i need to output the incoming waveform so that it drives an audio speaker. I'm assuming it would go through a soundcard, as opposed to a system speaker.
the waveform is captured as a 1D array (100 samples) sampled every 100msecs. I can change the sampling freqency if need be.
I haven't tried your code, but it looks like it will work.

 

by: harryscotterPosted on 2009-09-15 at 03:00:19ID: 25333318

Would the open source NAudio .NET library help you?

http://www.codeplex.com/naudio

I've used it in my applications and found it very easy to use. Its used in some big apps as well (like Skype).

 

by: jdcoburnPosted on 2009-09-24 at 13:26:53ID: 31628689

thanks.

20120131-EE-VQP-002

3 Ways to Join

30-Day Free Trial

The Experts

98% positive feedback on 31,087 answers since March 2000. angeliii is a Microsoft Most Valuable Professional for his work with MS SQL Server & Develoment.

He has also proven his knowledge of Visual Basic Programming, PHP Scripting and Oracle Databases.

The Experts

97% positive feedback on 10,752 answers since July 2000. lrmoore has more than 18 years experience in the networking industry.

The six-time Mircosoft MVPs specialties include firewalls, virtual private networking, and network management.

Testimonials

"...and excellent source for support... Kind of like having your very own IT dept." Electriciansnet

Testimonials

"I was apprehensive at signing up at first. However... it has already made my life as an IT administrator much easier." JaCrews

Testimonials

"WOW! You guys have great, active, and knowledgeable people on here." moore50

Business Clients

Business Clients

In the Press

"If you’ve got a question... Experts Exchange can supply an answer.”

In the Press

"...an invaluable aid for both IT professionals and those who require tech support."

In the Press

"where IT professionals provide quick answers on just about any topic"

Business Account Plans

Loading Advertisement...