Click here to Skip to main content
6,822,613 members and growing! (19,904 online)
Email Password   helpLost your password?
Multimedia » DirectX » General     Intermediate

Playing Wave Files using Streaming Buffers

By xsamar

An article on Streaming buffers
VC6, DirectX, Dev
Posted:26 Jul 2003
Views:57,521
Bookmarked:26 times
printPrint   add Share
      Discuss Discuss   Broken Article?Report  
5 votes for this article.
Popularity: 1.95 Rating: 2.79 out of 5
1 vote, 20.0%
1
1 vote, 20.0%
2
1 vote, 20.0%
3
1 vote, 20.0%
4
1 vote, 20.0%
5

Introduction

This project uses DirectSound to play wave files, but using a single static buffer it takes a lot of time and CPU cycles to load sound to buffer. But using streaming buffers is one way to copy data in blocks and playing the same block, also updating the same block from time to time. Thus it is a better way of playing large sound files.

Using the code

This project uses DirectSound in an easy way and most of the manipulation of wave file is done in wavefile class. The most important feature of it is that it uses Streaming Buffers. If you want to play a large wave file, loading it completely into the buffer would take up a lot of time to initialize. A better way would be to load it step by step into a circular buffer in a timely manner. I have used mmio functions defined in mmsystem.h. In this class, simple way of parsing wave header is done by finding the RIFF chunk by setting its type as mmioFOURCC('W','A','V','E') and descending into it to find its FMT chunk. Then wave format is read from this FMT chunk and stored in WAVEFORMATEX structure. After this I dived into data chunk. Data chunk is not read in one go. This is where all the importance comes in. A ServiceBuffer is used to service primary buffer to keep it full most of the time. This is called by timer proc through AudioStream member function TimerCallback. A primary buffer can be used of any size, but it must be serviced quite a number of times while playing one full buffer length. The main aim is to keep this buffer as much full as possible.

class Timer { public: Timer(); ~Timer(); 
BOOL Create (UINT nPeriod, UINT nRes, 
         DWORD dwUser, int (pfnCallback)(DWORD)); 
public: static void CALLBACK TimeProc(UINT uID, 
         UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2); 
int (*m_pfnCallback)(DWORD);
DWORD m_dwUser; UINT m_nPeriod;
UINT m_nRes;
UINT m_nIDTimer;
UINT UID;
void TimerStop(void); };
// Save current time (for elapsed time calculation) 

// This is a part of play function that initialises the timer

m_nTimeStarted = timeGetTime (); // Kick off timer to service buffer 

m_ptimer = new Timer (); 
if (m_ptimer) {
   m_ptimer->
   Create (m_nBufService, m_nBufService, DWORD(this), TimerCallback); 
}

This TimerCallback function calls the service buffer at specified intervals. There are play cursors and write cursors at 15 millisecond difference. DirectSound does not allow you to write data in that position. So better maintain your own variable to keep information about the buffer memory played and to be played.

BOOl AudioStream::SereviceBuffer() { 
//not to disturb while being serviced 

if (InterlockedExchange (&lInService, TRUE) == FALSE) 

{ . . . . . . . . . 
. . . . . . . 
DWORD dwFreeSpace = GetMaxWriteSize(); 
dwDataremaining=m_pwavefile-> GetNumbBytesRemaining(); 
//there will be three cases 

//i)enough data to fill free space;

//ii)data to fill is less than buffer size;

//iii)all data has been send to buffer and are being played.

//Fill free space with silence data.Deal with them accordingly.

Write wave data;
. . . . . . . . .
else fRtn=FALSE; }
else { // Service routine reentered. Do nothing, just return

fRtn = FALSE; } 
return (fRtn); }
<![if !supportEmptyParas]> <![endif]>

Problems I faced

The main problems I faced while making this project was reading the wave files. There was always an error while copying the contents of PCMWAVEFORMAT (16 Bytes) structure to WAVEFORMATEX (18 Bytes) structure. The worst thing that happened was I compiled this part of program in another file and memcpy was working quite well but not here. So I had to allocate 18 bytes to WAVEFORMATEX structure variable and then fill up the structure one by one.

One more strange effect I noticed, when I had put the dsound.h header file before mmsystem.h. So if you get syntax error in header file, try putting mmsystem.h before dsound.h. The original idea I got from the MSDN web site in a tutorial about streaming buffers. There I could not use the TIMERCALLBACK, so I used old C style function passing to another function.

History

  • Version 1.0

License

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

xsamar


Member
I am 20 yrs old and a student at Institute of Technology and Management College (www.itmindia.edu) in India.I am doing electronics and communication engineering. My main interests are in computer programming (DirectX,voice,internet srevers and client. Apart from these I have also interest in electronics. I recently made a project using microcontroller(PSoC) and data transfer mechanism using transistor and also in DTMF. I would like to make projects that use electronics as well as computer programming.
Location: India India

Other popular DirectX articles:

Article Top
You must Sign In to use this message board.
FAQ FAQ 
 
Noise Tolerance  Layout  Per page   
 Msgs 1 to 7 of 7 (Total in Forum: 7) (Refresh)FirstPrevNext
Generalplaying Waves through PSoC PinmemberJagadeesha l2:24 19 Jun '07  
Generalproblem Pinmemberearslan23:20 23 Mar '04  
GeneralRe: problem Pinmemberomershakeel21:58 7 Jun '04  
GeneralAuthor's reply Pinsusssamarjt7:22 1 Nov '04  
GeneralRead from Primary Buffer PinsussRobbBoy8:43 27 Feb '04  
Generalhelp for gettinf sound from MIC and displaying in speaker Pinsussainee20:27 19 Jan '04  
GeneralRe: help for gettinf sound from MIC and displaying in speaker Pinmembermohsen nourian1:55 4 Jul '04  

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

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

PermaLink | Privacy | Terms of Use
Last Updated: 26 Jul 2003
Editor: Smitha Vijayan
Copyright 2003 by xsamar
Everything else Copyright © CodeProject, 1999-2010
Web09 | Advertise on the Code Project