Click here to Skip to main content
11,926,429 members (58,660 online)
Click here to Skip to main content
Add your own
alternative version


62 bookmarked

Using DirectSound to Play Audio Stream Data

, 9 Mar 2005
Rate this:
Please Sign up or sign in to vote.
An article on how to play audio stream data with DirectSound.


This article with its code shows how to play audio stream data with DirectSound. It gives a more flexible method to control the stream data. The demo shows how to play, pause, stop, seek a small or a big WAV file.


Before you read the code, you should know something about DirectSound. You can find the related material in:

MSDN\Graphics and Multimedia\DirectX\SDK Documentation\DiretX8.1(C++)\DirectX Audio

Using the code

The CMyDirectSound has the following public method:

                                                      LPBYTE lpDesBuf,
                                                      const DWORD dwRequiredSamples, 
                                                      DWORD &dwRetSamples, 
                                                      LPVOID lpData);
void Play();
void Pause();
void Stop();
void Release();
DWORD GetSamplesPlayed();

First, you should give the information of the audio data you want to play, with "SetFormat":

m_pWavFile->Open((LPTSTR)(LPCTSTR)m_strFileName, &formatWav, WAVEFILE_READ);
formatWav = *m_pWavFile->GetFormat();

if (NULL == m_pDYDS) {

  m_pDYDS = new CDYDirectSound;

Second, set the callback function which is to get the audio stream data:

m_pMyDS->SetCallback(GetSamples, this);

Certainly, the body of the callback function should be written by yourself. Then you can play, pause, stop the audio data.

The "GetSamplesPlayed" method will give the number of audio samples played after you begin play. You can use this method to give the playing position.

Points of Interest

I think there're two key points in this class.

1. How to control the DirectSound buffer circle?

I create a second DirectSound buffer with two seconds duration:

//Create Second Sound Buffer
dsbd.dwBufferBytes = 2*m_WFE.nAvgBytesPerSec; //2-Second Buffer 
dsbd.lpwfxFormat = &m_WFE;

if ( FAILED(m_lpDS->CreateSoundBuffer(&dsbd, &m_lpDSB, NULL)) ) {

  OutputDebugString(_T("Create Second Sound Buffer Failed!"));
  m_strLastError = _T("MyDirectSound SetFormat Failed!");

And I set two DirectSound notify at 0.5 second and 1.5 second:

               (1st Notify)                          (2nd Notify)
0              0.5Second        1Second              1.5Second         2Second
|                  |               |                     |                 |
|                                  |                                       |
//Set Direct Sound Buffer Notify Position
pPosNotify[0].dwOffset = m_WFE.nAvgBytesPerSec/2 - 1;
pPosNotify[1].dwOffset = 3*m_WFE.nAvgBytesPerSec/2 - 1;  
pPosNotify[0].hEventNotify = m_pHEvent[0];
pPosNotify[1].hEventNotify = m_pHEvent[1];

if ( FAILED(lpDSBNotify->SetNotificationPositions(2, pPosNotify)) ) {

  OutputDebugString(_T("Set NotificationPosition Failed!"));
  m_strLastError = _T("MyDirectSound SetFormat Failed!");

When you call the Play method, a timer will be triggered. The "TimerProcess" function will be called every 300 milliseconds.

//Beging Play
m_lpDSB->Play(0, 0, DSBPLAY_LOOPING);

m_timerID = timeSetEvent(300, 100, TimerProcess, 

In the "TimerProcess" function, the next second audio stream data will be gotten when the current play cursor arrives the 1st or 2nd notify point.

void CALLBACK TimerProcess(UINT uTimerID, UINT uMsg, 
                           DWORD dwUser, DWORD dw1, DWORD dw2)
  CMyDirectSound *pDDS = (CMyDirectSound *)dwUser;

void CMyDirectSound::TimerCallback()
  LPVOID lpvAudio1 = NULL, lpvAudio2 = NULL;
  DWORD dwBytesAudio1 = 0, dwBytesAudio2 = 0;
  DWORD dwRetSamples = 0, dwRetBytes = 0;

  HRESULT hr = WaitForMultipleObjects(2, m_pHEvent, FALSE, 0);
  if(WAIT_OBJECT_0 == hr) {


    //Lock DirectSoundBuffer Second Part
    HRESULT hr = m_lpDSB->Lock(m_WFE.nAvgBytesPerSec, m_WFE.nAvgBytesPerSec,
    &lpvAudio1, &dwBytesAudio1,&lpvAudio2, &dwBytesAudio2, 0);
    if ( FAILED(hr) ) {

      m_strLastError = _T("Lock DirectSoundBuffer Failed!");
  else if (WAIT_OBJECT_0 + 1 == hr) {    


    //Lock DirectSoundBuffer First Part
    HRESULT hr = m_lpDSB->Lock(0, m_WFE.nAvgBytesPerSec, 
    &lpvAudio1, &dwBytesAudio1, &lpvAudio2, &dwBytesAudio2, 0);
    if ( FAILED(hr) ) {

      m_strLastError = _T("Lock DirectSoundBuffer Failed!");
  else {


  //Get 1 Second Audio Buffer 
  m_lpGETAUDIOSAMPLES(m_lpAudioBuf, m_WFE.nSamplesPerSec, dwRetSamples, m_lpData);
  dwRetBytes = dwRetSamples*m_WFE.nBlockAlign;
  //If near the end of the audio data
  if (dwRetSamples < m_WFE.nSamplesPerSec) {

    DWORD dwRetBytes = dwRetSamples*m_WFE.nBlockAlign;
    memset(m_lpAudioBuf+dwRetBytes, 0, m_WFE.nAvgBytesPerSec - dwRetBytes);        
  //Copy AudioBuffer to DirectSoundBuffer
  if (NULL == lpvAudio2) {

    memcpy(lpvAudio1, m_lpAudioBuf, dwBytesAudio1);
  else {

    memcpy(lpvAudio1, m_lpAudioBuf, dwBytesAudio1);
    memcpy(lpvAudio2, m_lpAudioBuf + dwBytesAudio1, dwBytesAudio2);
  //Unlock DirectSoundBuffer
  m_lpDSB->Unlock(lpvAudio1, dwBytesAudio1, lpvAudio2, dwBytesAudio2);

2. How the following callback function works?

//Get Audio Buffer
  m_lpGETAUDIOSAMPLES(m_lpAudioBuf, m_WFE.nSamplesPerSec, dwRetSamples, m_lpData);

Do you remember what you have done when you set the callback function?

void CDYDirectSound::SetCallback(LPGETAUDIOSAMPLES_PROGRESS Function_Callback, 
                                 LPVOID lpData)
  m_lpGETAUDIOSAMPLES = Function_Callback;
  m_lpData = lpData;

Yes, you transfer the GETAUDIOSAMPLES_PROGRESS function's pointer to m_lpGETAUDIOSAMPLES.

m_pMyDS->SetCallback(GetSamples, this);

And the GetSamples is defined as:

                            const DWORD dwRequiredSamples, 
                            DWORD &dwRetSamples, 
                            LPVOID lpData)
  CDirectSoundTestDlg *pDlg = (CDirectSoundTestDlg *)lpData;
  pDlg->GetAudioSamples(lpDesBuf, dwRequiredSamples, dwRetSamples);
  return 0;

HRESULT CDirectSoundTestDlg::GetAudioSamples(LPBYTE lpDesBuf,
                                             const DWORD dwRequiredSamples,
                                             DWORD &dwRetSamples)
  DWORD dwRequiredBytes = 0, dwRetBytes = 0;
  WAVEFORMATEX *pWFE = m_pWavFile->GetFormat();
  dwRequiredBytes = dwRequiredSamples*pWFE->nBlockAlign;
  m_pWavFile->Read(lpDesBuf, dwRequiredBytes, &dwRetBytes);
  dwRetSamples = dwRetBytes/pWFE->nBlockAlign;
  return dwRetBytes;

You can write your own "GetAudioSamples" to get the audio stream data.


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

Cai Tao
China China
No Biography provided

You may also be interested in...

Comments and Discussions

GeneralUsing DirectSound to Play Audio Stream Data Pin
khosrow parizi31-Aug-12 3:52
memberkhosrow parizi31-Aug-12 3:52 
QuestionLarger buffer Pin
rahnz29-May-12 16:17
memberrahnz29-May-12 16:17 
Buga little bug during play/pause switch Pin
tonyjiang8821519-Dec-11 3:17
membertonyjiang8821519-Dec-11 3:17 
Questiona small problem with slider-position Pin
dumbledorehoho25-Jan-10 19:14
memberdumbledorehoho25-Jan-10 19:14 
Hello~ Cai Tao!
I'm a freshman in DirectSound programming~
Your project is really a terrific guide for me.
I find that when I drag the slider to a specific position, it won't stay there but instead move on a few more distance.
I guess the problem lies in
void CDirectSoundTestDlg::TimerCallback()
DWORD dwSamplesPlayed = m_pMyDS->GetSamplesPlayed();

when the slider is dragged to a new place, i see m_iBeginPlayPos is exactly that position. However dwSamplesPlayed is not zero, the slider will "move on a dwSamplesPlayed distance".

I'm now trying to revise the project as a practise.
Thank you, Cai~! Your project helps me a lot^^
Generalit is no good when work with windows media palyer 10 Pin
nofengyu23-Jan-10 21:22
membernofengyu23-Jan-10 21:22 
Generalthanks Pin
gj_code13-Aug-09 5:55
membergj_code13-Aug-09 5:55 
Generala few question about play wave file with DirectSound and display spectrum. Pin
jacky_zz4-Sep-08 16:02
memberjacky_zz4-Sep-08 16:02 
QuestionAbout "GetAudioSamples" Pin
HuangAnbang10-Sep-07 19:16
memberHuangAnbang10-Sep-07 19:16 
GeneralUnresolved Error for Release Build Pin
Seenu Reddi21-Feb-07 16:03
memberSeenu Reddi21-Feb-07 16:03 
QuestionThe Primary buffer is redundant???? Pin
cnxhwy23-Nov-06 17:11
membercnxhwy23-Nov-06 17:11 
QuestionHow do handle block mode audio ? Pin
Musong22-Aug-06 17:54
memberMusong22-Aug-06 17:54 
QuestionCalculation error in GetSamplesPlayed() ? Pin
Azonacun8-May-06 9:38
memberAzonacun8-May-06 9:38 
AnswerRe: Calculation error in GetSamplesPlayed() ? Pin
Kedzo6-Jul-06 12:51
memberKedzo6-Jul-06 12:51 
Question'dmusici.h' missing! Pin
WilliamZhou24-Mar-06 6:29
memberWilliamZhou24-Mar-06 6:29 
AnswerRe: 'dmusici.h' missing! Pin
Sreekanth Muralidharan27-Apr-06 20:49
memberSreekanth Muralidharan27-Apr-06 20:49 
GeneralMeasuring the sound level Pin
msorc24-Feb-06 7:08
membermsorc24-Feb-06 7:08 
QuestionUsing a Stream in stead of of File ? Pin
Yossef1-Dec-05 0:07
memberYossef1-Dec-05 0:07 
GeneralBug report and my fixes Pin
IKedzo25-Oct-05 2:54
sussIKedzo25-Oct-05 2:54 
GeneralConflicts with other applications Pin
StevenDorning6-Oct-05 23:19
memberStevenDorning6-Oct-05 23:19 
GeneralSomething wrong when load different BitsPerSample WAV file! Pin
ikkiu20011-Jul-05 0:51
memberikkiu20011-Jul-05 0:51 
Generalabout mfc42u.lib Pin
caoxiang31-May-05 19:10
membercaoxiang31-May-05 19:10 
GeneralRe: about mfc42u.lib Pin
YesterdayOncemore13-Feb-06 21:13
memberYesterdayOncemore13-Feb-06 21:13 
GeneralRe: about mfc42u.lib Pin
Duncan1234529-Mar-06 22:59
memberDuncan1234529-Mar-06 22:59 
GeneralAudio Format.. Pin
mpallavi28-Apr-05 19:08
membermpallavi28-Apr-05 19:08 
GeneralRe: Audio Format.. Pin
Cai Tao28-Apr-05 22:27
memberCai Tao28-Apr-05 22:27 

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.

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.151126.1 | Last Updated 10 Mar 2005
Article Copyright 2004 by Cai Tao
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid