Click here to Skip to main content
13,191,877 members (30,690 online)
Click here to Skip to main content
Add your own
alternative version


235 bookmarked
Posted 11 Dec 2002

A low-level audio player in C#

, 27 Aug 2003
Rate this:
Please Sign up or sign in to vote.
This article describes a sample application that uses the waveout API in C#.

Sample Image - cswavplay.gif


It is no news that the .NET framework does not include any classes for dealing with sound. Some people have worked around this limitation by wrapping high-level system components, such as Windows Media Player or DirectShow, into .NET-friendly libraries. However, most of these libraries are designed in such a way that they cannot be used to manipulate audio samples on the fly because they do not give you access to the actual sound data.

When developing applications that deal with such low-level issues, the most commonly used technologies are DirectSound and the waveout API. This article describes a sample application that uses the waveout API in C# through Interop to play a WAV file in a continuous loop.

Using the code

Most of the work in the sample application is carried out by two classes: WaveStream and WaveOutPlayer.

The WaveStream class extends System.IO.Stream and implements the necessary code to read audio samples from a WAV file. The constructor reads the file header and extracts all the relevant information including the actual length of the stream and the format of the audio samples, which is exposed through the Format property.

One important thing to note is that seeking operations in the WaveStream class are relative to the sound data stream. This way you don't have to care about the length of the header or about those extra bytes at the end of the stream that don't belong to the audio data chunk. Seeking to 0 will cause the next read operation to start at the beginning of the audio data.

The WaveOutPlayer class is where the most interesting things happen. For the sake of simplicity, the interface of this class has been reduced to the strict minimum. There are no Start, Stop or Pause methods. Creating an instance of WaveOutPlayer will cause the system to start streaming immediately.

Let's have a look at the code that creates the WaveOutPlayer instance. As you can see, the constructor takes five parameters:

private void Play()
    if (m_AudioStream != null)
        m_AudioStream.Position = 0;
        m_Player = new WaveLib.WaveOutPlayer(-1, m_Format, 16384, 3, 
            new WaveLib.BufferFillEventHandler(Filler));

The first parameter is the ID of the wave device that you want to use. The value -1 represents the default system device, but if your system has more than one sound card, then you can pass any number from 0 to the number of installed sound cards minus one to select a particular device.

The second parameter is the format of the audio samples. In this example, the format is taken directly from the wave stream.

The third and forth parameters are the size of the internal wave buffers and the number of buffers to allocate. You should set these to reasonable values. Smaller buffers will give you less latency, but the audio may stutter if your computer is not fast enough.

The fifth and last parameter is a delegate that will be called periodically as internal audio buffers finish playing, so that you can feed them with new sound data. In the sample application we just read audio data from the wave stream, like this:

private void Filler(IntPtr data, int size)
    byte[] b = new byte[size];
    if (m_AudioStream != null)
        int pos = 0;
        while (pos < size)
            int toget = size - pos;
            int got = m_AudioStream.Read(b, pos, toget);
            if (got < toget)
                m_AudioStream.Position = 0; // loop if the file ends
            pos += got;
        for (int i = 0; i < b.Length; i++)
            b[i] = 0;
    System.Runtime.InteropServices.Marshal.Copy(b, 0, data, size);

Please note that this delegate may be called from any internal thread created by the WaveOutPlayer object, so if you want to call into your Windows Forms objects you should use the Invoke mechanism.

To stop playing, just call Dispose on the player object, like this:

private void Stop()
    if (m_Player != null)
        m_Player = null;


This sample demonstrates how to use the waveout API from C#. This is useful for applications that require more control on the audio stream compared to what other higher level libraries offer. Typical examples are applications that generate or modify audio samples on the fly, such as digital effect processors.

A modified version of this sample that implements support for DirectX plug-ins is included in the Adapt-X SDK, which is a commercial product that can be found at


Update 28 Aug 03 - Fixed a bug related to reading the WAV file header.


This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


About the Author

Ianier Munoz
Web Developer
Luxembourg Luxembourg
Ianier Munoz lives in France and works as a senior consultant and analyst for an international consulting firm. His specialty is in multimedia applications, and he has authored some popular software, such as American DJ's Pro-Mix, Chronotron and Adapt-X.

You may also be interested in...

Comments and Discussions

GeneralArgumentException -> Windows Mobile 5.0 Pin
user1403787-May-07 3:51
memberuser1403787-May-07 3:51 
GeneralRe: ArgumentException -> Windows Mobile 5.0 Pin
eelioss20-May-07 8:21
membereelioss20-May-07 8:21 
GeneralRe: ArgumentException -> Windows Mobile 5.0 Pin
wimpos3-Sep-07 1:47
memberwimpos3-Sep-07 1:47 
GeneralMagic number Pin
Gilesb28-Apr-07 2:30
memberGilesb28-Apr-07 2:30 
GeneralRe: Magic number Pin
Ianier Munoz30-Apr-07 19:01
memberIanier Munoz30-Apr-07 19:01 
GeneralRe: Magic number Pin
k06a8-Apr-10 10:36
memberk06a8-Apr-10 10:36 
Generalnoise filterring system Pin
hassan053116-Mar-07 23:29
memberhassan053116-Mar-07 23:29 
QuestionQBasic Music Support? Pin
Vasudevan Deepak Kumar12-Dec-06 3:16
memberVasudevan Deepak Kumar12-Dec-06 3:16 
GeneralA question plz Pin
AdyXP29-Oct-06 5:27
memberAdyXP29-Oct-06 5:27 
QuestionWaveform (Audio Signal) Pin
Erakis22-Jul-06 12:16
memberErakis22-Jul-06 12:16 
AnswerRe: Waveform (Audio Signal) Pin
eelioss14-May-07 5:47
membereelioss14-May-07 5:47 
AnswerThe way for getting the current play position Pin
eelioss9-Jun-07 8:49
membereelioss9-Jun-07 8:49 
GeneralRe: The way for getting the current play position Pin
eelioss9-Jun-07 9:48
membereelioss9-Jun-07 9:48 
GeneralIt's an advertisement for a commercial product. Pin
tekHedd4-Jun-06 12:41
membertekHedd4-Jun-06 12:41 
I hate to complain..well, the truth is that I love to complain. Doesn't everybody? But nobody wants to be perceived as a complainer. However, I do have some problems with this article.

1) The code is licensed thusly: you can play with it, but you can't use it in open or closed source projects. Because of the license, I can't even look at the source, or I am then in danger of writing a similar API and violating copyright. And how many ways can you write a streaming audio API? This makes the code sample useless.

2) The article itself does NOT explain how to use streaming audio api's to play audio on windows. It explains how to use the proprietary API that is being promoted here. This makes the article useless, unless you have cash to kick down. Which I wouldn't, even if I wasn't working on free software. Smile | :)

The only people this benefits are people who are willing to steal code. Of which there are plenty, but still... Smile | :) Sorry.
GeneralRe: It's an advertisement for a commercial product. - not really Pin
graymon18-Aug-06 5:03
membergraymon18-Aug-06 5:03 
GeneralRe: It's an advertisement for a commercial product. - not really Pin
Ianier Munoz30-Apr-07 19:18
memberIanier Munoz30-Apr-07 19:18 
GeneralRe: It's an advertisement for a commercial product. Pin
mlavenne13-Jan-07 18:06
membermlavenne13-Jan-07 18:06 
GeneralRe: It's an advertisement for a commercial product. Pin
Ianier Munoz30-Apr-07 19:11
memberIanier Munoz30-Apr-07 19:11 
QuestionCD locked Pin
gajatko25-May-06 6:04
membergajatko25-May-06 6:04 
Generalcan't play byte array Pin
gongozozzozorilla22-Apr-06 1:08
membergongozozzozorilla22-Apr-06 1:08 
GeneralRe: can't play byte array Pin
gongozozzozorilla23-Apr-06 23:26
membergongozozzozorilla23-Apr-06 23:26 
GeneralWaveFormatExtensible 24 bits 48KHz problem with full-duplex audio player Pin
barreJ2-Mar-06 8:30
memberbarreJ2-Mar-06 8:30 
GeneralRe: WaveFormatExtensible 24 bits 48KHz problem with full-duplex audio player Pin
Ianier Munoz24-Mar-06 17:17
memberIanier Munoz24-Mar-06 17:17 
GeneralDocumentation of Full duplex project Pin
Mubii6-Jan-06 23:08
memberMubii6-Jan-06 23:08 
GeneralMemory leak Pin
makmak9-Nov-05 18:18
membermakmak9-Nov-05 18:18 
GeneralRe: Memory leak Pin
Ianier Munoz24-Mar-06 17:28
memberIanier Munoz24-Mar-06 17:28 
GeneralRe: Memory leak Pin
kwats1-Oct-06 10:52
memberkwats1-Oct-06 10:52 
GeneralWaveform audio interface component for .NET Pin
AdamSlosarski4-Nov-05 0:39
memberAdamSlosarski4-Nov-05 0:39 
GeneralImproving Performance Pin
venugopal.10@indiatimes.com18-Oct-05 0:27
membervenugopal.10@indiatimes.com18-Oct-05 0:27 
GeneralRe: Improving Performance Pin
tomschuring22-May-07 15:21
membertomschuring22-May-07 15:21 
GeneralNice article, one question Pin
smesser23-Aug-05 2:41
membersmesser23-Aug-05 2:41 
GeneralRe: Nice article, one question Pin
Ianier Munoz24-Mar-06 17:31
memberIanier Munoz24-Mar-06 17:31 
QuestionHow to play from a byte array chunks Pin
yaron99927-Jul-05 2:59
memberyaron99927-Jul-05 2:59 
QuestionHow to play A_Law wave Pin
WantDrunk23-May-05 20:07
memberWantDrunk23-May-05 20:07 
AnswerRe: How to play A_Law wave Pin
Member 367416513-Apr-08 5:54
memberMember 367416513-Apr-08 5:54 
GeneralReal-time C# waveout Pin
Ho-Sheng Hsiao12-May-05 17:00
sussHo-Sheng Hsiao12-May-05 17:00 
GeneralConverting the byte[] into an int[] for processing audio Pin
papahabla14-Apr-05 9:31
memberpapahabla14-Apr-05 9:31 
GeneralRe: Converting the byte[] into an int[] for processing audio Pin
papahabla14-Apr-05 15:11
memberpapahabla14-Apr-05 15:11 
GeneralRe: Converting the byte[] into an int[] for processing audio Pin
Ianier Munoz16-Apr-05 19:09
memberIanier Munoz16-Apr-05 19:09 
GeneralRe: Converting the byte[] into an int[] for processing audio Pin
papahabla24-May-05 19:45
memberpapahabla24-May-05 19:45 
Generalmistake using callback function Pin
giorget21-Mar-05 7:03
membergiorget21-Mar-05 7:03 
GeneralRe: mistake using callback function Pin
Ianier Munoz21-Mar-05 8:01
memberIanier Munoz21-Mar-05 8:01 
Generalplaying sync stopping async Pin
memo3725-Jan-05 17:12
membermemo3725-Jan-05 17:12 
GeneralRe: playing sync stopping async Pin
Ianier Munoz28-Jan-05 19:06
memberIanier Munoz28-Jan-05 19:06 
Generalnon looping wav Pin
SGarratt22-Dec-04 12:51
memberSGarratt22-Dec-04 12:51 
GeneralRe: non looping wav Pin
Ianier Munoz1-Jan-05 2:13
memberIanier Munoz1-Jan-05 2:13 
GeneralRe: non looping wav Pin
hennier20-Mar-05 23:46
memberhennier20-Mar-05 23:46 
GeneralRe: non looping wav Pin
Ianier Munoz20-Mar-05 23:57
memberIanier Munoz20-Mar-05 23:57 
GeneralRe: non looping wav Pin
hennier21-Mar-05 0:23
memberhennier21-Mar-05 0:23 
QuestionCan we play streaming data... Pin
Jigar Mehta20-Jul-04 18:17
memberJigar Mehta20-Jul-04 18:17 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.171017.2 | Last Updated 28 Aug 2003
Article Copyright 2002 by Ianier Munoz
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid