Strange Problem with XACT

0bb07e4419ef6018283d9d286066d1c8
0
idreamlovey 101 Aug 07, 2009 at 04:18

I was trying my hand with Directx SDk XACT tutorial(Tut02_Stream). I modified the code a bit and tried to run the program but i cant hear any song and my App exists with exit code 0x3. my StreamingWaveBank file is very big about 120mb as it consists of 4 songs of neararound 30mb each. Songs are in wav file PCM format with 44100 hz, 16bit and stereo. And strange is that when i dont call update() funtion where m_pXACT3Engine->DoWork(); has been called, I dont see my app exiting with 0x3 code. Now i dont understand whats the problem. Does XACT not supports heavy files. Cause while i was debugging i found XACTNotificationCallback function has never passed any XACTNOTIFICATIONTYPE_WAVEBANKPREPARED notification and it means clearly that those files have never been prepared by app to stream. But i dont know where is the fault cause i dont see any error in my coding. In the meantime i can play other short loop clips saved in InMemorywavebank file. Here is part of codes to check out so if u may find any bug there.

// Engine
IXACT3Engine*       m_pXACT3Engine;

// Banks
IXACT3WaveBank      *m_pWaveBank, *m_pStreamingWaveBank;
IXACT3SoundBank     *m_pSoundBank;

//Streaming parameters
XACTINDEX           *m_iSong;
bool                m_bHandleStreamingWaveBankPrepared;
bool                m_bHandleSongStopped;
int             m_nTotalSongs, m_nCurSongPlaying;

// Handles to audio files to be closed upon cleanup
CRITICAL_SECTION    m_cs;
HANDLE          m_hStreamingWaveBankFile;
BYTE                *m_pvWaveBank, *m_pvSoundBank;

//-----------------------------------------------------------------------------------------
// This is the callback for handling XACT notifications.  This callback can be executed on a 
// different thread than the app thread so shared data must be thread safe.  The game 
// also needs to minimize the amount of time spent in this callbacks to avoid glitching, 
// and a limited subset of XACT API can be called from inside the callback so 
// it is sometimes necessary to handle the notification outside of this callback.
//-----------------------------------------------------------------------------------------
void WINAPI XACTNotificationCallback(const XACT_NOTIFICATION* pNotification)
{
    // Here we will respond to a cue stop notification for the song 
    // cues by simply playing another song but its ultimately it's up the application 
    // and sound designer to decide what to do when a notification is received.
    for(int i=0; i<m_nTotalSongs; i++)
    {
        if( pNotification->type == XACTNOTIFICATIONTYPE_CUESTOP && 
            (pNotification->cue.cueIndex == m_iSong[i]) )
        {
            // The previous background song ended, so pick and new song to play it
            EnterCriticalSection( &m_cs );
                m_nCurSongPlaying++; m_nCurSongPlaying %= m_nTotalSongs;
                m_bHandleSongStopped = true;
            LeaveCriticalSection( &m_cs );
            break;
        }
    }

    if( pNotification->type == XACTNOTIFICATIONTYPE_WAVEBANKPREPARED &&             
        pNotification->waveBank.pWaveBank == m_pStreamingWaveBank )
    {
        // Respond to this notification outside of this callback so Prepare() can be called
        EnterCriticalSection( &m_cs );
        m_bHandleStreamingWaveBankPrepared = true;
        LeaveCriticalSection( &m_cs );
    }

    if( pNotification->type == XACTNOTIFICATIONTYPE_SOUNDBANKDESTROYED &&             
        pNotification->soundBank.pSoundBank == m_pSoundBank )
    {
        // Cleanup sound bank memory
        SAFE_DELETE(m_pSoundBank);
        SAFE_DELETE_ARRAY(m_iSong);
    }   
}

//----------------------------------------------------------------------------------------
//      1. Initialize XACT by calling pEngine->Initialize 
//      2. Register for the XACT notification desired
//      3. Create the in memory XACT wave bank(s) you want to use
//      4. Create the streaming XACT wave bank(s) you want to use
//      5. Create the XACT sound bank(s) you want to use
//      6. Store indices to the XACT cue(s) your game uses
//-----------------------------------------------------------------------------------------
HRESULT Initialize(char *szWaveBank, char *szSoundBank, TCHAR *szStreamBank, int nTotalStreamSongs)
{
    HRESULT hr;

    InitializeCriticalSection( &m_cs );
    hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
    
.
.
.
.
.
.


    // Read a streaming XACT wave bank file.  
        m_hStreamingWaveBankFile = CreateFile( szStreamBank, 
                            GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 
                            FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING, NULL );
        if( m_hStreamingWaveBankFile != INVALID_HANDLE_VALUE )
        {
            XACT_WAVEBANK_STREAMING_PARAMETERS wsParams;
            ZeroMemory( &wsParams, sizeof(XACT_WAVEBANK_STREAMING_PARAMETERS) );
            wsParams.file = m_hStreamingWaveBankFile;
            wsParams.offset = 0;

            // 64 means to allocate a 64 * 2k buffer for streaming.  
            // This is a good size for DVD streaming and takes good advantage of the read ahead cache
            wsParams.packetSize = 64; 

            hr = m_pXACT3Engine->CreateStreamingWaveBank( &wsParams, &m_pStreamingWaveBank );
        }
        if( FAILED(hr) ) 
            return E_FAIL; // CleanupXACT() will cleanup state before exiting

         m_nTotalSongs  = nTotalStreamSongs;
         m_iSong        = new XACTINDEX[m_nTotalSongs];
   
         for( int i=0; i<m_nTotalSongs; i++ )
         {
            CHAR sz[256];
            sprintf( sz, "BKGAUDIO_0%d", i+1 ); 
            m_iSong[m_nTotalSongs] = m_pSoundBank->GetCueIndex( sz ); 
         }      
    }

    return S_OK;
}

//-----------------------------------------------------------------------------
// Name: Update()
// Desc:   
//----------------------------------------------------------------------------- 
void    Update()
{
    // Handle these notifications outside of the callback because
    // only a subset of XACT APIs can be called inside the callback.

    // Use the critical section properly to make shared data thread safe while avoiding deadlocks.  
    //
    // To do this follow this advice:
    // 1) Use a specific CS only to protect the specific shared data structures between the callback and the app thread.
    // 2) Don't make any API calls while holding the CS. Use it to access the shared data, make a local copy of the data, release the CS and then make the API call.
    // 3) Spend minimal amount of time in the CS (to prevent the callback thread from waiting too long causing a glitch).   
    // 
    // Instead of using a CS, you can also use a non-blocking queues to keep track of notifications meaning 
    // callback will push never pop only push and the app thread will only pop never push
    
    EnterCriticalSection( &m_cs );
    bool bHandleStreamingWaveBankPrepared = m_bHandleStreamingWaveBankPrepared;
    LeaveCriticalSection( &m_cs );

    if( bHandleStreamingWaveBankPrepared )
    {
        EnterCriticalSection( &m_cs );
        m_bHandleStreamingWaveBankPrepared = false;
        LeaveCriticalSection( &m_cs );

        // Starting playing background music after the streaming wave bank 
        // has been prepared but no sooner.  The background music does not need to be 
        // zero-latency so the cues do not need to be prepared first 
        m_nCurSongPlaying = 0;
        m_pSoundBank->Play( m_iSong[m_nCurSongPlaying], 0, 0, NULL ); 
     }

    if( m_bHandleSongStopped )
    {
        EnterCriticalSection( &m_cs );
        m_bHandleSongStopped = false;
        LeaveCriticalSection( &m_cs );

        m_pSoundBank->Play( m_iSong[m_nCurSongPlaying], 0, 0, NULL ); 
    }


    if(m_pXACT3Engine)
        m_pXACT3Engine->DoWork();
}

2 Replies

Please log in or register to post a reply.

46407cc1bdfbd2db4f6e8876d74f990a
0
Kenneth_Gorking 101 Aug 09, 2009 at 00:34

If you can play smaller files using this code, then I don’t see why it shouldn’t be able to play this big file. Maybe there is some upper limit to the file size?

Have you checked the values returned from the XACT functions? Maybe they can tell you something.

0bb07e4419ef6018283d9d286066d1c8
0
idreamlovey 101 Aug 10, 2009 at 12:57

I found the error in building the XACT files. Coding is perfect and bug is in its the way i have setup the files in XACT :) But still wondering why i havent got any error in the app. anyway its working now.

Error was i didnt had set the audio type to Streaming. It was InMemory Type.