Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

DirectSound Wrapper Classes

0.00/5 (No votes)
6 Aug 2006 1  
An article on multimedia - playing Waves by using the DirectSound component.

Demo Application User Interafce

Introduction

Microsoft DirectX is a heavy stone that cannot be broken without any tools. Each part of DirectX is worth separate attention by a developer. Looking deep inside of those components is too difficult. But to use them properly one must know what he is doing or wants to do...

But nowadays technologies are so developed that they free developers from having to cover much of the 'technical' aspects of their job and let them concentrate on the core issues they have. One of such helpers is the core concept of object-oriented languages, and C++ too, which of course is - the class.

Classes are the very basement on which object-oriented programming is built. The wiser you use them, the more you will sleep at nights. Not going into the depth of C++ notions, I want to introduce a few classes of mine to you that may help you with using MS DirectSound components in your applications. Particularly, I will speak about how to play .wav (wave) files by DirectSound.

What's New in This Update

The major new feature in this article is that CDSoundPlay now supports notification mechanism; it uses IDirectSoundNotify interface to handle that. CWave class's source is available in the source download. Also there are some corrections in the code from previous article.

Background

First, let me say that .wav files may be played not only by DirectSound, but also by MMIO, MCI and so on. The problem is that those machines don't provide immediate attention to a user; the latency to start playing is much. This may be crucial in some situations, for example, in games, where the bomber-man wants his gun to sound (and shoot) as soon as possible. Here DirectSound may help.

DirectSound provides low-latency playback and immediate attention from users.

To minimize the job necessary for using DirectSound at a maximum, I've created four classes: one may say wrapper classes. Two of them are helper classes and are not supposed to be used directly, but you still can use them. Here are the classes:

  • CWave (helper)
  • CDSBuffer (helper)
  • CDSound
  • CDSoundPlay

CWave helps us with opening .wav files. This class is used by CDSBuffer. I have put CWave in a DLL to hide the unnecessary stuff from you (believe in me, there are lots of ugly things). Though the source code of CWave you can find in the download package of this article.

CDSound is the main entity in your system. It represents the DirectSound object. Within a given application there must be only one instance of this class. This class is used by CDSBuffer.

CDSBuffer is a low-level class that represents DirectSound buffers. This class is used by CDSoundPlay.

CDSoundPlay is a high-level class that represents the interface for playing, stopping, ... of Waves.

These classes use MFC and cannot live without it. For example, I've put CWave in a MFC extension DLL; it means that the client application also must be MFC based.

Using The Code

Now let's see how to use them. You can declare the objects of these classes in a view class, dialog class or main frame class; in other words, any window that has HWND (really I haven't seen any window without a HWND). I'll choose a dialog.

Declarations:

#include "DirectSound.h"

using namespace DirectSound;

class CMyDialog : public CDialog
{
    CDSound m_dsound; // only once

    CDsoundPlayer m_player; // any number

    
    // ...

};

Next construct the corresponding DirectSound object in OnInitDialog:

BOOL CMyDialog::OnInitDialog()
{
  // ...


  m_dsound.Create();
  m_dsound.SetCooperativeLevel(GetSafeHwnd());

  return FALSE;
}

Now you may load files. Assume you have a Load method to do it:

BOOL CMyDialog::Load(LPCTSTR lpszFileName)
{
    m_player.Destroy(); // guarantee multiple loads

    BOOL fOk = m_player.Create(&m_dsound, lpszFileName);
    return fOk;
}

Let's play and stop Wave files. Assume you have OnPlay and OnStop handlers to do it:

void CMyDialog::OnPlay()
{
    Load(TEXT("flowers.wav"));
    m_player.Play();
}

void  CMyDialog::OnStop()
{
    m_player.Stop();
}

A couple of new functions has been added to CDSoundPlay which are for handling notifications; CDSounfPlay::SetNotifyFuction and CDSoundPlay::SetNotificationPositions. The former takes a parameter of type PNOTIFYFUNC which is a typedef for callback functions:

typedef LONG (*PNOTIFYFUNC) (LONG );

This means that a callback should take a LONG parameter and return a LONG value. This type was defined by me and you may change it for your convention if needed.

The second function looks like so:

BOOL SetNotificationPositions(DWORD dwOffsets[], SIZE_T nSize);

It takes an array of integer values showing positions to be considered, and an integer value showing how many positions are there in the first parameter.

For example, the demo application calls these functions to be notified when a wave starts and when it ends:

m_player.SetNotifyFunction(CSounderDlg::NotifyCallback);
DWORD dwOffset[] = { 0, DSBPN_OFFSETSTOP };
m_player.SetNotificationPositions(dwOffset, 2);

CSounderDlg::NotifyCallback is a static function which has the type of PNOTIFYFUNC:

LONG CSounderDlg::NotifyCallback(LONG f) // static function

{
    // ...

    return 0;
}

That's all for playing Wave files. But CDSoundPlay has also other features; amongst them: looping, volume setting/getting, panorama setting/getting, frequency setting/getting. I've created a demo application that shows most of these features. It is a simple application and I'll not describe it thoroughly. Just see its interface and you'll understand it yourself.

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