Click here to Skip to main content
15,896,111 members
Articles / Multimedia / DirectX

A DirectX Game: Quadrino

Rate me:
Please Sign up or sign in to vote.
4.89/5 (41 votes)
16 Oct 2008CPOL26 min read 397.8K   6.2K   125  
An interpretation of a popular falling block game implemented with DirectX that attempts to avoid any copyright infringement.
/* DSSoundManager.cpp *********************************************************
Author:		Paul Watt
Date:		10/20/2002
Purpose:	Implementation for a class that manages the DirectX sound system.
******************************************************************************/
#include "stdafx.h"
#include "DSSoundManager.h"
#include "DSSound.h"

 
/* Public *********************************************************************
Author:		Paul Watt
Date:		10/20/2002
Purpose:	Constructor
******************************************************************************/
DSSoundManager::DSSoundManager ()
{
	m_pDS = NULL;
}


/* Public *********************************************************************
Author:		Paul Watt
Date:		10/20/2002
Purpose:	Destructor
******************************************************************************/
DSSoundManager::~DSSoundManager()
{
	SAFE_RELEASE(m_pDS);
}


/* Public *********************************************************************
Author:		Paul Watt
Date:		10/20/2002
Purpose:	Initializes the direct sound system to play sounds.
Parameters:	hWnd[in]: The handle to the application window that this class 
				can send messages to synchronize events.
			dwCoopLevel[in]: Indicates the level of control that this app would
				like over the sound device.  Possible values are:
				DSSCL_EXCLUSIVE:	This app will have exclusive control.
				DSSCL_NORMAL:	Fully cooperative status.
				DSSCL_PRIORITY: (Default)Gives greater access of control to this app over the sound device.
				DSSCL_WRITEPRIMARY: Highest priority level, does not allow 2nd buffers to play.
			dwPrimaryChannels[in]: The number of channels in the data.
				Default = 2
			dwPrimaryFreq[in]: The sample rate that the device will play at.
				Default = 22050
			dwPrimaryBitRate[in]: The number of bits in the samples.
				Default = 16
Return:		HRESULT indicates the status of this function.
******************************************************************************/
HRESULT DSSoundManager::Initialize (HWND hWnd, DWORD dwCoopLevel, DWORD dwPrimaryChannels, DWORD dwPrimaryFreq, DWORD dwPrimaryBitRate)
{
    HRESULT hr;
			//C: Free any previous sound interfaces, and reinitialize DirectSound.
    SAFE_RELEASE( m_pDS );
			//C: Create the direct sound object with the default device.
	hr = DirectSoundCreate8(NULL, &m_pDS, NULL);
    if (FAILED(hr))
	{
        return hr;
	}
			//C: Set the cooperative level.
	hr = m_pDS->SetCooperativeLevel(hWnd, dwCoopLevel);
    if (FAILED(hr))
	{
		return hr;
	}
			//C: Initialize the primary buffer format.
    return SetPrimaryBufferFormat(dwPrimaryChannels, dwPrimaryFreq, dwPrimaryBitRate);
}


/* Public *********************************************************************
Author:		Paul Watt
Date:		10/20/2002
Purpose:	Sets the format parameters for the primary buffer.
Parameters:	dwPrimaryChannels[in]: The number of channels in the data.
				Default = 2
			dwPrimaryFreq[in]: The sample rate that the device will play at.
				Default = 22050
			dwPrimaryBitRate[in]: The number of bits in the samples.
				Default = 16
Return:		HRESULT indicates the status of this function call.	
******************************************************************************/
HRESULT DSSoundManager::SetPrimaryBufferFormat(DWORD dwPrimaryChannels, DWORD dwPrimaryFreq, DWORD dwPrimaryBitRate)
{
    HRESULT             hr;
			//C: Verify that the DirectSound interface has been initialized.
    if (!m_pDS)
	{
        return CO_E_NOTINITIALIZED;
	}
			//C: Get the primary buffer from the sound device.
	IDirectSoundBuffer	*pPrimaryBuffer = NULL;
    DSBUFFERDESC dsbd;
    ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) );
    dsbd.dwSize        = sizeof(DSBUFFERDESC);
    dsbd.dwFlags       = DSBCAPS_PRIMARYBUFFER;
    dsbd.dwBufferBytes = 0;
    dsbd.lpwfxFormat   = NULL;
       
	hr = m_pDS->CreateSoundBuffer(&dsbd, &pPrimaryBuffer, NULL);
    if (FAILED(hr))
	{
		return hr;
	}
			//C: Set the format parameters for the primary buffer.
    WAVEFORMATEX wfx;
    ZeroMemory( &wfx, sizeof(WAVEFORMATEX) ); 
    wfx.wFormatTag      = WAVE_FORMAT_PCM; 
    wfx.nChannels       = (WORD) dwPrimaryChannels; 
    wfx.nSamplesPerSec  = dwPrimaryFreq; 
    wfx.wBitsPerSample  = (WORD) dwPrimaryBitRate; 
    wfx.nBlockAlign     = wfx.wBitsPerSample / 8 * wfx.nChannels;
    wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;

	hr = pPrimaryBuffer->SetFormat(&wfx);
    SAFE_RELEASE(pPrimaryBuffer);

    return hr;	
}


/* Public *********************************************************************
Author:		Paul Watt
Date:		10/20/2002
Purpose:	Creates a new sound object.
Parameters:	pSound[out]: Receives a pointer to the new object.
			szWaveFileName[in]: The name of the file to load into the Sound.
			createionFlags[in]: 
			guid3DAlgorithm[in]:
			bufferCount[in]:
Return:		HRESULT indicates the status of this function.
******************************************************************************/
HRESULT DSSoundManager::CreateSound(DSSound** ppSound, LPTSTR strWaveFileName, DWORD dwCreationFlags, DWORD dwNumBuffers, GUID guid3DAlgorithm)
{
    HRESULT hr;
    HRESULT hrRet = S_OK;
	DWORD	index = 0;

    LPDIRECTSOUNDBUFFER *apDSBuffer     = NULL;
    DSWaveFile          *pWaveFile      = NULL;
    DWORD                dwDSBufferSize = 0;
			//C: Check and intialize the output parameters.
	if(!ppSound)
	{
        return E_INVALIDARG;
	}
	*ppSound = NULL;
			//C: Verify input parameters.
    if (!m_pDS)
	{
        return CO_E_NOTINITIALIZED;
	}
    if (!strWaveFileName || dwNumBuffers < 1)
	{
        return E_INVALIDARG;
	}
			//C: Create and open the new waveFile.
    pWaveFile = new DSWaveFile();
    if (!pWaveFile)
    {
        hr = E_OUTOFMEMORY;
        goto Fail;
    }

    pWaveFile->Open(strWaveFileName, NULL, DSWaveFile::WAVEFILE_READ);

    if( pWaveFile->GetSize() == 0 )
    {
			//C: Wave is blank, so don't create the sound.
        hr = E_FAIL;
        goto Fail;
    }
			//C: Allocate memory to read the sound buffer.
    apDSBuffer = new LPDIRECTSOUNDBUFFER[dwNumBuffers];
    if (!apDSBuffer)
    {
        hr = E_OUTOFMEMORY;
        goto Fail;
    }
			//C: Make the DirectSound buffer the same size as the wav file
    dwDSBufferSize = pWaveFile->GetSize();
			//C: Create the direct sound buffer, and only request the flags needed
			//   since each requires some overhead and limits if the buffer can 
			//   be hardware accelerated
    DSBUFFERDESC dsbd;
    ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) );
    dsbd.dwSize          = sizeof(DSBUFFERDESC);
    dsbd.dwFlags         = dwCreationFlags;
    dsbd.dwBufferBytes   = dwDSBufferSize;
    dsbd.guid3DAlgorithm = guid3DAlgorithm;
    dsbd.lpwfxFormat     = pWaveFile->m_pwfx;

    hr = m_pDS->CreateSoundBuffer(&dsbd, &apDSBuffer[0], NULL);
			//C: Check if the user asked for a 3D algorithm that was not available.
    if(hr == DS_NO_VIRTUALIZATION)
	{
        hrRet = DS_NO_VIRTUALIZATION;
	}
            
    if(FAILED(hr))
    {
        goto Fail;
    }

    for (index = 1; index < dwNumBuffers; index++)
    {
		hr = m_pDS->DuplicateSoundBuffer(apDSBuffer[0], &apDSBuffer[index]);
        if(FAILED(hr))
        {
            goto Fail;
        }
    }

			//C: Create the sound object to return to the caller.
    *ppSound = new DSSound();
	if (*ppSound)
	{
		if (FAILED((*ppSound)->Initialize(apDSBuffer, dwDSBufferSize, dwNumBuffers, pWaveFile)))
		{
			delete *ppSound;
			*ppSound = NULL;
		}
	}

    delete[] apDSBuffer;
    return hrRet;

Fail:
    // Cleanup
    delete pWaveFile;
    delete[] apDSBuffer;
    return hr;
}


By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Engineer
United States United States
I am a software architect and I have been developing software for nearly two decades. Over the years I have learned to value maintainable solutions first. This has allowed me to adapt my projects to meet the challenges that inevitably appear during development. I use the most beneficial short-term achievements to drive the software I develop towards a long-term vision.

C++ is my strongest language. However, I have also used x86 ASM, ARM ASM, C, C#, JAVA, Python, and JavaScript to solve programming problems. I have worked in a variety of industries throughout my career, which include:
• Manufacturing
• Consumer Products
• Virtualization
• Computer Infrastructure Management
• DoD Contracting

My experience spans these hardware types and operating systems:
• Desktop
o Windows (Full-stack: GUI, Application, Service, Kernel Driver)
o Linux (Application, Daemon)
• Mobile Devices
o Windows CE / Windows Phone
o Linux
• Embedded Devices
o VxWorks (RTOS)
o Greenhills Linux
o Embedded Windows XP

I am a Mentor and frequent contributor to CodeProject.com with tutorial articles that teach others about the inner workings of the Windows APIs.

I am the creator of an open source project on GitHub called Alchemy[^], which is an open-source compile-time data serialization library.

I maintain my own repository and blog at CodeOfTheDamned.com/[^], because code maintenance does not have to be a living hell.

Comments and Discussions