XACT Programming Guide

This topic discusses the Microsoft Cross-Platform Audio Creation Tool (XACT) from the programmer's perspective.

XACT Scope

The XACT APIs drive the low-level audio software engine functions to render sound. This is intended to be transparent to both the designer and the programmer.

In most cases, game title developers will find that the XACT and its functions provide a simple and elegant solution for their audio needs. However, developers who prefer to manage their audio data at a lower level will find no obstacle to accessing the functions of their audio engine directly.

Figure 1.  Relationship of XACT to the audio engine

XACT Integration

The game programmer will receive from the audio designer the files that result from the XACT build process. It is then the responsibility of the programmer to initialize the XACT, load the data when it is needed within the game and trigger cues at the appropriate junctures as gameplay progresses. The programmer is also responsible for allocation and management of the memory resources needed by the XACT.

The following sections outline the most common procedures for integrating game audio resources with XACT.

Initialization

To start the XACT audio engine, you must first call IXACTEngine::Initialize. As the following example demonstrates, you may invoke this function with an empty set of initialization parameters, which indicates that default settings are desired. This function needs to be called only once at the beginning of your application.

XACT_RUNTIME_PARAMETERS Params;

memset(&Params, 0, sizeof(Params));

pXACTEngine->Initialize(&Params);

Work Loop

The application must continuously call IXACTEngine::DoWork. This function is typically called during the main title loop that executes once per frame and drives the graphics rendering for the game. For more information, see IXACTEngine::DoWork.

bool fDone = false;

do {
   // update all the game action
   Update();
	
   // render graphic elements to the screen
   Render();

   // drive audio every frame
   pXACTEngine->DoWork();
   Sleep(1);
} while (!fDone)

Creating Wave Banks and Sound Banks

The game title must allocate the memory for the wave and sound bank data, then read the files into that memory. The program must then instantiate the wave and sound bank objects that will control that data. Once these banks are no longer needed, the program is responsible for destroying the objects and freeing the memory.

These procedures will typically occur at the beginning and end of a scene in the game.

The following example illustrates creation of an in-memory wave bank. For streaming wave banks, see XACT Streaming Wave Banks.

IXACTWaveBank * pWaveBank;
IXACTSoundBank * pSoundBank;

// Load Wave Bank file from media into memory, pointed to by pbWaveBank, dwWaveBankSize
// Load Sound Bank file from media into memory, pointed to by pbSoundBank, dwSoundBankSize

 // Ready to create engines for wave banks and sound banks
 if ( SUCCEEDED( pXACTEngine->CreateInMemoryWaveBank( pbWaveBank, dwWaveBankSize, 0, 0, &pWaveBank ) ) )
 {
    if ( SUCCEEDED( pXACTEngine->CreateSoundBank( pbSoundBank, dwSoundBankSize, 0, 0, &pSoundBank ) ) )
    {
      // Ready to do work
    }
}

Playing Cues

Cues in the sound bank are referenced by index. However, the method IXACTSoundBank::GetCueIndex is provided so that the program can look up the cue index from the "friendly name," or text string given the cue by the audio designer (if friendly names were included when built).

In the following example, note the use of GetState and Release to wait until the cue has completed playing before freeing its resources. For further information, see Managing XACT Resources and Notifications

XACTINDEX XCueIndex_gs1;
DWORD dwCueState;

// Look up the cue index from the friendly name
XCueIndex_gs1 = pSoundBank->GetCueIndex("Gunshot1");
// Trigger the cue
hr = pSoundBank->Play(XCueIndex_gs1, 0, &pXCue_gs1);

// Now wait for the cue to finish playing
bool fDone = false;
while (!fDone) {
   if ( SUCCEEDED (pXCue_gs1->GetState(&dwCueState) )
   {
      if (dwCueState & XACT_CUESTATE_STOPPED)
      {
         fDone = true;
         continue;
      }
      pXACTEngine->DoWork();
      Sleep(1);
   }
}

// Since we asked for the cue object pointer, we need to RELEASE it when done
pXCue_gs1->Release();

See Also

XACT Overviews, XACT Reference, XACT Audio Authoring