Click on play3dsound_2005.vcproj file to start Visual Studio 2005.
We got fatal error C1083: Cannot open include file: 'XInput.h': No such file or directory
google search found http://www.gamedev.net/community/forums/topic.asp?topic_id=375845
If you have the December 2005 (and most probably the February 2006) sdk, then xinput.h should be in "C:\Program Files\Microsoft DirectX SDK (December 2005)\Include" ..asumming of course that is where you installed it to So as long as visual c++ has that folder down in the includes (tools>options>projects and solutions>vc++ directories>include files) it should be fine Regards, ViLiO |
This tutorial covers the basics of the Microsoft Cross-Platform Audio Creation Tool (XACT) API, including understanding XACT components and file formats, and basic steps for using XACT, such as loading wave banks, using notifications, and playing cues.
The full working source code for this tutorial is in:
<Installed SDK Location>\Samples\C++\XACT\Tutorials\Tut01_PlayCue
Before we dive into programming, let's cover some of the basic background of XACT.
XACT is composed of three connected parts:
When creating an audio solution for a game, it is important to understand which aspects are in the hands of the programmer and which are the responsibility of the composer or sound designer. To avoid confusion and potential responsibility "clashes," XACT attempts to provide a single way to perform most tasks. Properties and behaviors that are specified in content cannot generally be "overridden" programmatically, and conversely, the composer does not control resource management or dynamic pausing.
When initiating a project, the sound designer and the programmer decide on important cues, also known as "triggers" or "sound cues," in the game. The composer will then create a sound (or perhaps multiple sounds, one of which will be chosen randomly to play) that that cue plays, and the programmer makes the game plays those cues when the proper game events occur. This allows the programmer and the sound designer can go their separate ways.
To summarize, the programmer's responsibilities:
Meanwhile, the sound designer or composer:
XACT relies on two types of files for audio content: wave banks (*.xwb) and sound banks (*.xsb).
Wave banks are just bundled wave data, formatted for optimal playback performance. For in-memory wave banks, waves are DWORD aligned. For streamed wave banks, the individual waves are sector aligned (2048-byte boundaries for DVD streaming). All of this data formatting is managed automatically in the XACT build process, based on settings specified by the content author. These settings can be changed easily enough, but you should communicate with your content creator as to what kind of in-memory budget you have for audio, as well as how much streaming bandwidth you can grant to audio during game play.
Sound banks are where waves are assembled on a timeline into sounds by the content creator. The content creator then assigns a cue to play a sound (or in some cases, pick a random sound from a list). The developer then plays and stops these cues based on game events. Beyond controlling cues, the developer can also manipulate some properties on a category level. Each sound can be assigned to a category by the content creator. The developer can then globally adjust the relative volume of categories as well as pause or resume them.
While we're talking about file formats, let's also mention the XACT project file (*.xap). This is the file that contains all of the instructions for building the sound banks and wave banks for a project-every setting that the content creator has specified in the XACT authoring tool. Typically a developer will never have to actually read or edit this file. However, because the sound bank format could change in a future release, you should make sure to rebuild your sound banks with each new SDK, even if the content is no longer being edited. The command line tool xactbld.exe allows you to rebuild sound banks (and, optionally, wave banks) from the XACT project file without needing to open the editing tool. It's quite common to integrate this into a game's automated build process, rather than needing to remember to manually rebuild.
Here is a quick overview of the basic steps to use XACT, and afterward we'll look each of these steps in detail.
First, to initialize XACT it just requires making this call:
XACT_RUNTIME_PARAMETERS xrParams = {0}; xrParams.fnNotificationCallback = XACTNotificationCallback; hr = pXACTEngine->Initialize( &xrParams );
The XACT_RUNTIME_PARAMETERS structure contains a number of advanced options such as the global settings file and look-ahead time which are out of the scope of this tutorial, but they can all be safely set to 0 to use the default settings. The fnNotificationCallback member is the callback function used to notify the application about XACT notifications. Notifications will be covered in detail later in this tutorial.
Next, you need to create the wave banks and sound banks. In this tutorial, we only create one XACT wave bank and one XACT sound bank. For more complex games that have lots of sounds, they can break their sound effects into multiple wave and sound banks. This allows them to more easily partition the sound data by level, by character, by material, or however they desire to keep only the working set they desire loaded at the same time.
To create XACT wave banks and XACT sound banks you must use the following methods of IXACTEngine:
STDAPI IXACTEngine_CreateInMemoryWaveBank( void *pvBuffer, DWORD dwSize, DWORD dwFlags, DWORD dwAllocAttributes, IXACTWaveBank **ppWaveBank ); STDAPI IXACTEngine_CreateStreamingWaveBank( const XACT_WAVEBANK_STREAMING_PARAMETERS *pParms, IXACTWaveBank **ppWaveBank ); STDAPI IXACTEngine_CreateSoundBank( void *pvBuffer, DWORD dwSize, DWORD dwFlags, DWORD dwAllocAttributes, IXACTSoundBank **ppSoundBank );
IXACTEngine::CreateStreamingWaveBank is slightly more advanced and will be discussed in the next tutorial.
Both IXACTEngine::CreateSoundBank and IXACTEngine::CreateInMemoryWaveBank need a pointer to the data to read and the size of the data in bytes. Typically this data will come from reading an XACT file but this does not have to be the case. For example, the data could be part of an exe resource or contained inside a bundled file format.
When reading a file, there are 2 primary methods of doing so. The most typical is to use ReadFile() to read the file into a buffer like so:
HANDLE hFile = CreateFile(str, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); DWORD dwFileSize = GetFileSize(hFile , NULL); VOID* pSoundBankData = new BYTE [dwFileSize]; ReadFile(hFile, pSoundBankData, dwFileSize, &dwBytesRead, NULL)) HRESULT hr = pXACTEngine->CreateSoundBank(pSoundBankData, dwFileSize, 0, 0, &pSoundBank);
The other method is called memory-mapped files and uses MapViewOfFile to map a view of a file into the address space of the calling process. Memory-mapped files tend to be faster for most situations assuming you have enough virtual address space for a full map of the file thus our examples will use the faster memory mapped file method:
HANDLE hFile = CreateFile( str, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL ); DWORD dwFileSize = GetFileSize( hFile, NULL ); HANDLE hMapFile = CreateFileMapping( hFile, NULL, PAGE_READONLY, 0, dwFileSize, NULL ); VOID* pSoundBankData = MapViewOfFile( hMapFile, FILE_MAP_READ, 0, 0, 0 ); HRESULT hr = pXACTEngine->CreateSoundBank( pSoundBankData, dwFileSize, 0, 0, &pSoundBank );
The most important concept to understand is that you can not free the data block passed to these create functions until XACT has destroyed that wave bank or sound bank. The file data passed to these functions is not cached by XACT and is needed by XACT when sounds are played. Simply calling Release on the bank does not mean the bank is immediately destroyed and the memory can be freed because there could be sound(s) still playing when Release was called.
It is only safe to free the data after calling either IXACTEngine::ShutDown or a XACTNOTIFICATIONTYPE_SOUNDBANKDESTROYED or XACTNOTIFICATIONTYPE_WAVEBANKDESTROYED notification for the bank has been received. We will look at how to create and handle notifications shortly. Alternatively, if you set XACT_FLAG_API_CREATE_MANAGEDATA and do not use the memory-mapped file method then XACT will automatically free the file buffer when the bank is destroyed.
After the wave and sound banks have been created, an XACT cue index is needed used by your game to play a cue event. There are a few methods for retrieving these index cues. The most common method is to use IXACTSoundBank::GetCueIndex like so:
iZapCueIndex = g_audioState.pSoundBank->GetCueIndex( "zap" );
Note that the string "zap" used here is just the friendly string name of the cue as you defined in the XACT project. Also note that if the cue does not exist in the sound bank, the index will be XACTINDEX_INVALID however this is not tragic especially during development as it will simply cause the IXACTCue::Play or IXACTSoundBank::Prepare call to fail.
Another method is to enable the BuildProjectHeader setting in XACT authoring tool. This will make the XACT project create a C style header which can be included by your game. The header will contain something like this depending on the names of your cues:
typedef enum { XACT_CUE_SOUND_BANK_ZAP = 0, } XACT_CUE_SOUND_BANK; #define XACT_CUE_SOUND_BANK_ENTRY_COUNT 1
Now that the XACT is initialized, the wave and sound banks have been created and your engine has indices to all the cues, you are ready to use XACT.
You can optionally register for any number of notifications depending on the game's needs. The process simply involves filling out the XACT_NOTIFICATION_DESCRIPTION structure and calling IXACTEngine::RegisterNotification like so:
XACT_NOTIFICATION_DESCRIPTION desc = {0}; desc.type = XACTNOTIFICATIONTYPE_CUESTOP; desc.pSoundBank = pSoundBank; desc.cueIndex = iZapCueIndex; pXACTEngine->RegisterNotification(&desc);
The structure is described in detail in the docs along with all of the notification types (XACTNOTIFICATIONTYPE) available but it should be noted that you don't have to tie the notification to a one time event or a specific cue or bank. For example, you can setup a persistent notification for all sound banks like so:
XACT_NOTIFICATION_DESCRIPTION desc = {0}; desc.flags = XACT_FLAG_NOTIFICATION_PERSIST; desc.type = XACTNOTIFICATIONTYPE_CUESTOP; desc.cueIndex = XACTINDEX_INVALID; pXACTEngine->RegisterNotification(&desc);
This notification will trigger whenever any cue stops on any sound bank. If you have multiple sound or wave banks and want to swap them in and out as the game progresses, you can use a notification like this:
XACT_NOTIFICATION_DESCRIPTION desc = {0}; desc.flags = XACT_FLAG_NOTIFICATION_PERSIST; desc.type = XACTNOTIFICATIONTYPE_SOUNDBANKDESTROYED; pXACTEngine->RegisterNotification(&desc); desc.flags = XACT_FLAG_NOTIFICATION_PERSIST; desc.type = XACTNOTIFICATIONTYPE_WAVEBANKDESTROYED; pXACTEngine->RegisterNotification(&desc);
So you will be notified whenever a wave or sound bank is destroyed so you can free its associated file memory.
To play sounds using XACT, the game plays a specific XACT cue when a game event occurs. This cue is defined in the XACT project by the sound designer to play a certain set of XACT sounds which in turn play events which trigger the playback of a certain set of wave data with possibly a variation of volumes and pitches. Because of the way XACT is designed, the audio that is heard when a cue is played can be changed without recompiling the game. This allows the audio to be designed and tweaked independently once the game events are defined and the cues are triggered by the game engine.
The simplistic method to play a cue is done by calling IXACTSoundBank::Play with the appropriate cue index when an event happens in the game. We'll look at more complex methods later. For the typical case the code is simply:
pSoundBank->Play( iCueIndex, 0, NULL );
Note that it is often not necessary to retrieve the pointer to the IXACTCue object unless your game needs to stop or pause the cue so NULL can be used as the 3rd parameter.
Notifications are received in a notification callback function that looks like this:
void WINAPI XACTNotificationCallback(const XACT_NOTIFICATION* pNotification) { if( pNotification->type == XACTNOTIFICATIONTYPE_CUESTOP ) { // Handle the cue stop notification } // .... }
This callback is set when calling IXACTEngine::Initialize. This callback can be executed on a different thread than the application thread, so any shared data referenced in this callback must be made thread safe. The application also needs to minimize the amount of time spent in this callback to avoid glitching, and a limited subset of XACT APIs can be called from inside the callback (see XACT_NOTIFICATION_CALLBACK for a list of acceptable APIs) so it is sometimes necessary to handle the notification outside of this callback.
The XACT_NOTIFICATION structure will contain all the information the game needs to process the notification. If in the rare case the game wants to remove all pending notifications from the queue without handling them it can flush them like so:
XACT_NOTIFICATION_DESCRIPTION desc = {0}; desc.type = XACTNOTIFICATIONTYPE_CUESTOP; XACTFlushNotification(&desc);
You can also use IXACTEngine::UnRegisterNotification to stop receiving a certain type of notification.
It is important to allow XACT to do periodic work by calling IXACTEngine::DoWork. However this function must be called often enough. If you call it too infrequently, streaming will suffer and resources will not be managed promptly. On the other hand if you call it too frequently, it will negatively affect performance. Calling it once per frame is usually a good balance as shown below:
while( WM_QUIT != msg.message ) { // Use PeekMessage() so we can use idle time to render the scene and call DoWork() bGotMsg = ( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) != 0 ); if( bGotMsg ) { // Translate and dispatch the message TranslateMessage( &msg ); DispatchMessage( &msg ); } else { RenderFrame(); pXACTEngine->DoWork(); } }
To shut down and clean up XACT, first release all the XACT interfaces and then call IXACTEngine::ShutDown and free the sound and wave bank data like shown below. Be aware that IXACTEngine::ShutDown is synchronous and will take some time to complete if there are still playing cues. Also IXACTEngine::ShutDown is generally only called when a game exits and not the preferred method of changing audio resources. To unload resources while game is running, use notifications.
VOID CleanupXACT() { // Release XACT interfaces if( g_pSoundBank ) g_pSoundBank->Release(); if( g_pWaveBank ) g_pWaveBank->Release(); // Shut down XACT pXACTEngine->ShutDown(); // Release memory mapped files if( g_pbSoundBank ) UnmapViewOfFile( g_pbSoundBank ); if( g_pbWaveBank ) UnmapViewOfFile( g_pbWaveBank ); }
This topic gives a high-level introduction to the DXUT Overview.
DXUT Improvements in the DirectX April 2005 SDK
DXUT Changes from the DirectX Summer 2003 SDK
The framework is designed to help the programmer spend less time worrying about how to create a window, how to create a device, how to process Windows messages, or when to handle device events.
Here is an example main function of an application using the framework:
INT WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, INT ) { // Set the callback functions. These functions allow DXUT // to notify the application about device changes, user input, and window // messages. The callback functions are optional, so you need only set // them for events you are interested in. DXUTSetCallbackDeviceCreated( OnCreateDevice ); DXUTSetCallbackDeviceReset( OnResetDevice ); DXUTSetCallbackDeviceLost( OnLostDevice ); DXUTSetCallbackDeviceDestroyed( OnDestroyDevice ); DXUTSetCallbackFrameRender( OnFrameRender ); DXUTSetCallbackFrameMove( OnFrameMove ); // Initialize DXUT and create the desired Win32 window and // Direct3D device for the application. Calling each of these functions is // optional, but they allow you to set several options which control the // behavior of the framework. DXUTInit( TRUE, TRUE, TRUE ); DXUTCreateWindow( L"BasicHLSL" ); DXUTCreateDevice( D3DADAPTER_DEFAULT, TRUE, 640, 480 ); // Pass control to DXUT for handling the message pump and // dispatching render calls. The framework will call your OnFrameMove and // OnFrameRender callback functions when there is idle time between // handling window messages. DXUTMainLoop(); return DXUTGetExitCode(); }
In the example code above, the framework does most of the work. It creates a window, creates a device, handles the main loop, and uses the application-supplied callback functions when events occur, such as device reset or frame render. The framework is modular, and the application can use all of the framework features or just the parts desired.
The remainder of this programming guide covers each of these steps in detail and looks at the choices the application has available to control or replace each step.
Further details on syntax and usage of functions, callback functions, structures, enumerations, and constants can be found in DXUT Reference.
The framework provides the following services to help you create an application:
Simplified window and device creation.
Notification of device events (created, reset, lost, destroyed) and window events (messages, keyboard, mouse).
Toggling between windowed and full-screen modes, and between hal and reference devices.
High-resolution timer.
Command-line support for automated testing.
Device selection via dialog or API.
Suite of textured GUI controls, including an IME-enabled edit box.
Extra miscellaneous classes, such as simple camera types.
For ease of use, the framework supports only a single window attached to a single device. Advanced applications that need to use multiple devices simultaneously or that need to display multiple Direct3D windows are not supported by the framework. However, most typical applications should be able to use the framework.
The easiest way to start a new Visual Studio .NET development project using DXUT is to do the following:
Launch the sample browser, located in the DirectX SDK in the following location:
(SDK root)\Samples\SampleBrowser\
In the browser, select an existing Direct3D sample project that will be a starting point.
Click on the "Install Project" link next to that project to copy the Visual Studio .NET project files to a new directory location.
You can also optionally rename the project, in which case the sample browser will change the appropriate files and source code to give the project the new name.
Based on customer feedback, the framework was improved in the DirectX April 2005 SDK Update. The following is a list of major differences and improvements.
Callback functions now pass a void* pUserContext from the DXUTSetCallback* function to the callback. This allows the callback functions to receive context from the application such as a class pointer.
The framework's GUI is now separate and optional from the core framework. The creation and interfacing of CDXUTDialogResourceManager is now the responsibility of the application if it wishes to use the framework's GUI.
The framework now allows applications to reject device changes via the PDXUTCALLBACKMODIFYDEVICESETTINGS function which returns a bool. Returning false from this callback will notify the framework to keep using the current device instead of changing to the new device. For example, by default on a multiple monitor configuration dragging the window between monitors will cause the framework to change devices. However if the application can not use the other device, it must be able to reject this change and continue to use the current device. This callback can now be set separate of the CreateDevice function by using XUTSetCallbackDeviceChanging.
Passing 0 as the width and height to the DXUTCreateDevice function now creates a backbuffer of the same size as the client window.
The DXUTGetExitCode function now returns 11 if the last device was a D3DDEVTYPE_REF device type.
The new framework is significantly redesigned from DXUT that shipped in the DirectX Summer 2003 SDK Update. The following is a list of major differences and improvements.
Flat API design. The new framework is a set of global functions that more clearly define how the application interacts with the framework.
Clearer naming. The device, frame, and message events have been renamed to be more easily understood.
Modular. An application can use only parts of the framework if desired. An application can use the framework to create its own window or its own device, or it can use its own main loop.
Better device selection. The application can fully customize the presentation parameters or behavior flags before creating the device. The new framework also has a more advanced algorithm for finding valid device settings.
Toggling between hal and reference devices (see Device Types). Built-in toggling support is available, and toggling can be bound to a keystroke for simplified debugging.
Better error handling. Error handling and macros can be used by the application to display error message boxes immediately if an API is called incorrectly.
Better multiple-monitor support. If this feature is enabled, the new framework will automatically change devices if the window is moved to a different monitor.
GUI controls. A set of textured GUI controls features an IME-enabled edit box for use in samples, prototypes, and professional games.
No dialog dependency onGDI. Unlike the previous framework, the new framework does not require anyGDI dialog resources in the application.
Late binding with DirectX. Late binding verifies that the required DirectX version is installed on the system.
Unicode support. The new framework supports Unicode. Windows NT-based operating systems natively support Unicode, which means that ANSI calls need to be converted to Unicode. With this and better international support, Unicode is the better choice because it will result in better performance on these operating systems. For Windows 98 and Windows Millennium Edition (Windows Me) systems, consider using the Microsoft Layer for Unicode (MSLU).
Documentation. The framework library functions in the Dxut.h header are documented; see DXUT Reference.