RSX  Contents  Interfaces  Data Structures  Previous  Next

Code Sample

The code shown here is adapted from the cppmin sample. Excerpts from cppmin and other samples are used throughout the documentation to demonstrate RSX 3D features and functions.

The sample shows:

The RSX 3D installation copies source for RSX 3D samples onto your hard disk at installation time. Running these samples and examining the source code can help you learn how to use RSX 3D.


Sample Code Demonstrating How to Create Audio Objects

The following sample contains C++ code showing how to go through these basic steps:

Initializing RSX 3D

As part of the initialization process, before you use the RSX 3D library, you must call the COM initialization function CoInitialize.

HRESULT m_coResult;               // result of initializing COM libs
IRSX* m_lpRSX;                    // RSX
IRSXDirectListener* m_lpDL;       // Direct listener
IRSXCachedEmitter* m_lpCE;        // Cached sound emitter

// on creation initialize COM libraries and post a message to
// initialize RSX
int CMainWindow::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
   if (CFrameWnd ::OnCreate(lpCreateStruct) == -1) {
           return -1;
   } // if  

A call to CoInitialize, initializes the COM libraries.

   m_coResult = CoInitialize(NULL);

   // A failure may indicate a system configuration problem.
   if(FAILED(m_coResult) ) {
           AfxMessageBox("Failed to load COM libraries");
           return -1;
   } 

/*

The following message allows for the audio initialization to be performed in a different message callback. You could do this initialization in any of the creation message callbacks - like WM_CREATE

*/

   PostMessage(WM_USER+1000);
   return 0;
}


// This handles WM_USER+1000 message and it creates
// 1 listener and 1 emitter in an audio environment

LRESULT CMainWindow::InitializeAudio(WPARAM w, LPARAM l)
{
   HRESULT hr;
   
   RSXVECTOR3D v3d;
   RSXVECTOR3D v3d2;
   RSXVECTOR3D v3dOrient;
   RSXVECTOR3D v3dUpOrient;


	//Create the RSX20 object and get a pointer to the IUnknown interface. 
	hr = CoCreateInstance(
		CLSID_RSX20,
		NULL,
		CLSCTX_INPROC_SERVER,
		IID_IUnknown,
		(void ** ) &m_lpUnk);
  
	// make sure it was created
	// if it wasn't created either the registry doesn't contain the
	// CLSID for RSX or the directory mentioned in the registry
	// doesn't contain rsx.dll.  The easy fix for this problem
	// is to run the RSX setup again.
	if( (FAILED(hr)) || (!m_lpUnk) ) {
		AfxMessageBox("Failed to Create RSX Object.\nCoCreateInstanceFailed - Please run RSX Setup\n");
		PostMessage(WM_CLOSE);
		return 0;
	} // endif

	//
	// ask the RSX20 object for an IRSX2 interface
	// this interface contains the environment settings functions 
	//		(SetEnvironment, GetEnvironment)
	// and the reverb settings functions (SetReverb, GetReverb)
	// 
	// Note: You can also get an IRSX20 interface which contains
	// the same functions as IRSX2 and it also contains the
	// older Create...() calls like CreateCachedEmitter
	// This interface still works but it is highly recommended
	// that you use the newer IRSX2 interface and create
	// your emitters and listeners using CoCreateInstance
	// as demonstrated in this sample.  For more info see the
	// documentation
	//
	// Don't forget to release m_lpRSX and m_lpUnk to be
	// COM-friendly
	hr = m_lpUnk->QueryInterface(IID_IRSX2, (void**)&m_lpRSX);

	// make sure it worked
	if(FAILED(hr)) {
		AfxMessageBox("Error getting IRSX2 Interface from RSX 3D object\n");
		m_lpUnk->Release();
		m_lpUnk = NULL;
		return 0;			
	}

Configuring the Audio Environment

This example uses the reverberation settings from a sound absorption model of a stage. The decay time, 1.5, is a mid-range value (decay time ranges between 0 and 3 seconds) and the value for sound intensity, 0.1, is very low (valid values for intensity range between 0.0 and 1.0). See the RSXREVERBMODEL data structure for further information about modeling reverberation.

    // reverb settings
    RSXREVERBMODEL rsxRvb;

    rsxRvb.cbSize = sizeof(RSXREVERBMODEL);
    rsxRvb.bUseReverb = TRUE;
    rsxRvb.fDecayTime = 1.5f;
    rsxRvb.fIntensity = 0.1f;

    m_lpRSX->SetReverb(&rsxRvb);

Creating a Direct Listener

This sample code shows you how to create a Direct Listener. Note that we provide the application's main window handle so RSX 3D can attempt to use DirectSound. If DirectSound rejects the window handle, RSX 3D uses the higher latency Wave API. By specifying NULL for the lpwf field, we direct RSX 3D to use the default wave format.

	// Create a Direct Listener object and get the IRSXDirectListener interface
	hr = CoCreateInstance(
		CLSID_RSXDIRECTLISTENER,
		NULL,
		CLSCTX_INPROC_SERVER,
		IID_IRSXDirectListener,
		(void ** ) &m_lpDL);

	RSXDIRECTLISTENERDESC rsxDL;            // listener description

	if(SUCCEEDED(hr)) {

		// fill up the directlistener settings for the initialize call
		rsxDL.cbSize = sizeof(RSXDIRECTLISTENERDESC);
		rsxDL.hMainWnd = AfxGetMainWnd()->GetSafeHwnd();
		rsxDL.dwUser = 0;
		rsxDL.lpwf = NULL;

		// All emmiter and listener objects have an initialize function
		// This function MUST be called before calling any other
		// functions on the interface and it may be called
		// ONCE and ONLY ONCE.  Subsequent calls to initialize 
		// will fail. Calls to any other function before initializing
		// will also fail.
		// The second parameter to the initialize call is always
		// an IUnknown* to an RSX20 object.
		// The first parameter in the directlistener call is
		// the address of an RSXDIRECTLISTENERDESC
		hr = m_lpDL->Initialize(&rsxDL, m_lpUnk);

		// initialize can fail if you pass bad params or
		// in the case of a DirectListener it may fail
		// because another application is using the audio device
		// or another instance of RSX has already grabbed the audio device.
		// Each instance of the RSX20 object may have ONE and ONLY ONE listener
		// (Either streaming or direct).
		if(SUCCEEDED(hr)) {
	
			// This is how to retrieve your user data.
			// User data is useful for storing pointers to other data
			// structures useful in your application
       
			DWORD dwUser;
			m_lpDL->GetUserData(&dwUser);
			.....

Positioning and Orienting a Direct Listener

This code shows positioning the listener at the origin and orienting the listener facing into the screen.

	// Set the DirectListener's position
	v3d.x = 0.0f;
	v3d.y = 0.0f;
	v3d.z = 0.0f;
	m_lpDL->SetPosition(&v3d);

	//
	// Listener orientation settings
	//
	// This vector is the direction the listener is facing
	v3dOrient.x = 0.0f;
	v3dOrient.y = 0.0f;
	v3dOrient.z = 1.0f;
           
	// 
	// "up" vector - perpendicular to orientation vector
	// This vector points to which direction is up
	// for the listener - it can not be parallel to the 
	// listener orientation vector
	v3dUpOrient.x = 0.0f;
	v3dUpOrient.y = 1.0f;
	v3dUpOrient.z = 0.0f;

	// Set the orientation of the listener
	m_lpDL->SetOrientation(&v3dOrient, &v3dUpOrient);

Creating a Cached Emitter

This code shows creating a cached emitter whose sound source is a wave file named cppmin.wav.

	/*
	// Create a Cachedemitter - a cached emitter is an emitter
	// based on a wave file found either on a local or networked
	// hard drive, as a resource in an .exe or .dll or 
	// it can be based on an Internet URL.
	*/

	hr = CoCreateInstance(
		CLSID_RSXCACHEDEMITTER,
		NULL,
		CLSCTX_INPROC_SERVER,
		IID_IRSXCachedEmitter,
		(void ** ) &m_lpCE);

	// see if it passed
	//
	if(SUCCEEDED(hr)) {

		RSXCACHEDEMITTERDESC rsxCE;             // emitter description
		
		ZeroMemory(&rsxCE, sizeof(RSXCACHEDEMITTERDESC));
		rsxCE.cbSize = sizeof(RSXCACHEDEMITTERDESC);
		rsxCE.dwFlags = 0;
		rsxCE.dwUser = 50;

		// If you want to use a wave file embedded as a resource 
		// instead of a file replace "cppmin.wav" with "cppmin.exe RESOURCE_ID"
		// i.e. "cppmin.exe 15" or try this:
		// sprintf(aeDesc.szFilename,"cppmin.exe %d", IDR_WAVE1);
		//
		// OR if you have installed Microsoft Internet Explorer 3.0
		// and it is configured correctly you
		// can use an URL-based emitter like:
		// http://www.junk.com/mywaves/cppmin.wav
		// or
		// ftp:://ftp.junk.com/waves/cppmin.wav
		//
		strcpy(rsxCE.szFilename,"cppmin.wav");

		// initialize the CachedEmitter and 'attach' it to 
		// the same RSX20 object as the DirectListener
		// otherwise we won't hear anything
		hr = m_lpCE->Initialize(&rsxCE, m_lpUnk);

		if(SUCCEEDED(hr)) {
			.....
	

Figure 1 shows the sound model for this emitter. RSX 3D defines the model as two concentric ellipsoids. These two ellipsoids describe an ambient region and an attenuation region.

In this example, the ambient region's minimum front and minimum back ranges are the same, causing it to have a spherical shape. Within this region, the sound level has a constant intensity. The attenuation region is also spherical (its maximum front and maximum back ranges are the same).

The sound intensity decreases logarithmically from a maximum within the ambient region to -20db at the boundary of the attenuation region. Beyond the outer boundary of the attenuation region, the sound level has an intensity of 0. Because the ratio of front to back ranges for both regions is 1, the regions are non-directional (graphically depicted as spheres).

Figure 1. Sound Emitter Model for Sample

Defining Ambient and Attenuation Regions

The following code shows how to create the emitter and define its ambient and attenuation regions.

               /*
               // Now set the emitter model
               */
               RSXEMITTERMODEL rsxEModel;
           
               rsxEModel.cbSize = sizeof(RSXEMITTERMODEL);

               // This defines the inner ellipsoid of the 
               // emitter.  Sound is ambient in this region.
               rsxEModel.fMinFront = 1.0f;
               rsxEModel.fMinBack = 1.0f;
                   
               // This defines the outer ellipsoid of the emitter
               // Sound is localized between the edge of the inner
               // ellipsoid and the outer ellipse. If the listener
               // position is outside of this ellipsoid the emitter 
               // cannot be heard.  Figure A-1 shows the sound model
               // for this emitter.
               rsxEModel.fMaxFront = 20.0f;
               rsxEModel.fMaxBack = 20.0f;

               // The intensity (volume) of the emitter
               // Generally between 0.00f and 1.00f
               rsxEModel.fIntensity = 0.7f;                

               // Actually set the model
               m_lpCE->SetModel(&rsxEModel);
                           
               /*
               // Place the emitter at the origin
               */
               v3d.x = 0.0f;
               v3d.y = 0.0f;
               v3d.z = 0.0f;
               m_lpCE->SetPosition(&v3d);
                   
               // Point the emitter along the Z axis.
               v3d.x = 0.0f;
               v3d.y = 0.0f;
               v3d.z = 1.0f;
               m_lpCE->SetOrientation(&v3d);

               /*
               // Start playing
               */
               m_lpCE->ControlMedia(RSX_PLAY, dlg.m_nLoops,
               dlg.m_fInitStart);
                          

Retrieving Information about Audio Objects

This code demonstrates some of the Get methods you can use to retrieve information about your audio objects. Data types for each retrieved item must be previously defined.

		// This is how you can retrieve the emitter's
		// position, orientation, your user data and the 
		// emitter's sound model.
		m_lpCE->GetPosition(&v3d);
		m_lpCE->GetOrientation(&v3d);
		m_lpCE->GetUserData(&dwUser);
		m_lpCE->GetModel(&rsxEModel);
	}
	else {
        	// This is commonly caused by the wave file
		// not being found.
		AfxMessageBox("Failed to Create Emitter. Make sure
                             cppmin.wav is in the current directory\n");
	} /* if */
	} else {
        // This may occur if another application currently has control
        // of the sound device - so close Media Player, Sound Recorder,  
        // and all other applications that play audio.
	AfxMessageBox("Failed to Create Listener\n");
    } // if
    return 0;
} /* InitializeAudio */

Copyright ©1996, 1997 Intel Corporation. All rights reserved