Sign in to follow this  
Medo Mex

XAudio2 Not Playing

Recommended Posts

I have Audio class and trying to get XAudio2 to play, it's only playing when I add a while(TRUE) {} inside play() method.

 

The following works:

 

Audio::play()
{
     // Code to initialize XAudio2 and play the sound here...
     while(TRUE) { } // <-- Prevent the program from exiting so we can hear the sound
}

int main()
{
     Audio *audio = new Audio("C:\\audio.wav");
     audio->play();
}

 

The following DOESN'T work (no sound is playing):

 

 

Audio::play()
{
     // Code to initialize XAudio2 and play the sound here...
}

int main()
{
     Audio *audio = new Audio("C:\\audio.wav");
     audio->play();
     while(TRUE) { } // Here I added the while statement inside main() instead of Audio::play(), it doesn't work anymore
}

What's wrong in the second code?

Share this post


Link to post
Share on other sites

Disclaimer - I'm not a programmer. So take my input with a very, very small grain of salt. But to my eyes, it seems like the while(TRUE) statement inside of the int main() function doesn't get called hence the no playing is heard. I may be butchering this explanation but it reads like the first example locks the application and allows the playing to happen but the second doesn't and the application exits before you can hear any playing. Again, not a real programmer, I just dabble in a few things and mainly do implementation via XML, actionscript or middleware like FMOD. So I might be WAY off track here! :P

 

Have you posted this question in the programming forum? You might have better luck. 

 

Thanks, 

 

Nate

Share this post


Link to post
Share on other sites

@nsmadsen: Thanks for trying to help :) I appreciate that, however, in the second code the program doesn't exit, it's just the sound not playing while it's playing in the first code.

 

I guess I didn't post the question in the right forum, so I will re-post it in development forum.

Share this post


Link to post
Share on other sites

What happens if you change it to this:

 

Audio::play()
{
     // Code to initialize XAudio2 and play the sound here...
}

int main()
{
     Audio *audio = new Audio("C:\\audio.wav");

     while(TRUE) { }
     audio->play();

}



Again, I might just be spinning my wheels... but perhaps the context or order of operations matters. I've found that in other instances. Other than that - I'm afraid I cannot really help out. Perhaps someone else here knows.

Share this post


Link to post
Share on other sites

I have Audio class and trying to get XAudio2 to play, it's only playing when I add a while(TRUE) {} inside play() method.

 

The following works:

 

Audio::play()
{
     // Code to initialize XAudio2 and play the sound here...
     while(TRUE) { } // <-- Prevent the program from exiting so we can hear the sound
}

int main()
{
     Audio *audio = new Audio("C:\\audio.wav");
     audio->play();
}
 
The following DOESN'T work (no sound is playing):
Audio::play()
{
     // Code to initialize XAudio2 and play the sound here...
}

int main()
{
     Audio *audio = new Audio("C:\\audio.wav");
     audio->play();
     while(TRUE) { } // Here I added the while statement inside main() instead of Audio::play(), it doesn't work anymore
}

What's wrong in the second code?

Share this post


Link to post
Share on other sites

Nothing is wrong, and the only thing people can do with pseudocode is guessing. Copy/Paste your actual compilable code in its entirety so we can analyze it and run it if needed, and I'm sure someone will spot the error.

Share this post


Link to post
Share on other sites

main.cpp:

#include "Wave.h"

IXAudio2 *pXAudio2;
IXAudio2MasteringVoice *pMasterVoice;
IXAudio2SourceVoice *pSourceVoice;
XAUDIO2_BUFFER *fBuffer;


int playAudio()
{
       //must call this for COM
        CoInitializeEx( NULL, COINIT_MULTITHREADED ); // This line can be added in the constructor of SoundManager instead of here


        //create the engine
if( FAILED( XAudio2Create( &pXAudio2 ) ) )
        {
                CoUninitialize();
                return -1;
        }


        //create the mastering voice
        if( FAILED( pXAudio2->CreateMasteringVoice( &pMasterVoice ) ) )
        {
                pXAudio2->Release();
                CoUninitialize();
                return -2;
        }


        //helper class to load wave files; trust me, this makes it MUCH easier
        Wave buffer;


        //load a wave file
if( !buffer.load("G:\\test.wav") )
        {
                pXAudio2->Release();
                CoUninitialize();
                return -3;
        }


        //create the source voice, based on loaded wave format
if( FAILED( pXAudio2->CreateSourceVoice( &pSourceVoice, buffer.wf() ) ) )
        {
                pXAudio2->Release();
                CoUninitialize();
                return -4;
        }

fBuffer = (XAUDIO2_BUFFER*)buffer.xaBuffer();
fBuffer->LoopCount = XAUDIO2_LOOP_INFINITE; // XAUDIO2_LOOP_INFINITE
fBuffer->Flags = XAUDIO2_END_OF_STREAM;

pSourceVoice->SubmitSourceBuffer( fBuffer );
pSourceVoice->Start();
// while(TRUE) { } // The audio only play if I uncommented this line
}

int main()
{
     playAudio();
     while(TRUE) { }
}

Wave.h:

 

 

//wave.h
//by Jay Tennant 3/4/12
//Wave helper class, to load simple wave files
//win32developer.com
//this code provided free, as in public domain; score!


#ifndef WAVE_H
#define WAVE_H


#include <windows.h>
#include <xaudio2.h>
#include <fstream>


class Wave
{
private:
        WAVEFORMATEX m_wf;
        XAUDIO2_BUFFER m_xa;
        BYTE* m_waveData;
public:
        Wave(const char* szFile = NULL) : m_waveData(NULL) {
                ZeroMemory(&m_wf, sizeof(m_wf));
                ZeroMemory(&m_xa, sizeof(m_xa));


                load(szFile);
        }
        Wave(const Wave& c) : m_waveData(NULL) {
                m_wf = c.m_wf;
                m_xa = c.m_xa;
                if(c.m_waveData)
                {
                        m_waveData = new BYTE[m_xa.AudioBytes];
                        memcpy( m_waveData, c.m_waveData, m_xa.AudioBytes );
                        m_xa.pAudioData = m_waveData;
                }
        }
        ~Wave() {
                if(m_waveData)
                        delete [] m_waveData;
                m_waveData = NULL;
        }


        const XAUDIO2_BUFFER* xaBuffer() const {return &m_xa;}
        const WAVEFORMATEX* wf() const {return &m_wf;}
        bool load(const char* szFile) {
                if(szFile == NULL)
                        return false;


                std::ifstream inFile(szFile, std::ios::binary | std::ios::in);
                if(inFile.bad())
                        return false;
                
                DWORD dwChunkId = 0, dwFileSize = 0, dwChunkSize = 0, dwExtra = 0;


                //look for 'RIFF' chunk identifier
                inFile.seekg(0, std::ios::beg);
                inFile.read(reinterpret_cast<char*>(&dwChunkId), sizeof(dwChunkId));
                if(dwChunkId != 'FFIR')
                {
                        inFile.close();
                        return false;
                }
                inFile.seekg(4, std::ios::beg); //get file size
                inFile.read(reinterpret_cast<char*>(&dwFileSize), sizeof(dwFileSize));
                if(dwFileSize <= 16)
                {
                        inFile.close();
                        return false;
                }
                inFile.seekg(8, std::ios::beg); //get file format
                inFile.read(reinterpret_cast<char*>(&dwExtra), sizeof(dwExtra));
                if(dwExtra != 'EVAW')
                {
                        inFile.close();
                        return false;
                }


                //look for 'fmt ' chunk id
                bool bFilledFormat = false;
                for(unsigned int i = 12; i < dwFileSize; )
                {
                        inFile.seekg(i, std::ios::beg);
                        inFile.read(reinterpret_cast<char*>(&dwChunkId), sizeof(dwChunkId));
                        inFile.seekg(i + 4, std::ios::beg);
                        inFile.read(reinterpret_cast<char*>(&dwChunkSize), sizeof(dwChunkSize));
                        if(dwChunkId == ' tmf')
                        {
                                //I don't know what I was thinking with the following code, but I
                                //never did solve it back 6 months, and didn't touch it since; oh well... :S


                                //switch(dwChunkSize)
                                //{
                                //case sizeof(WAVEFORMATEX):
                                //      {
                                //              inFile.seekg(i + 8, std::ios::beg);
                                //              inFile.read(reinterpret_cast<char*>(&m_wf), sizeof(m_wf));
                                //      }
                                //      break;
                                //case sizeof(WAVEFORMATEXTENSIBLE):
                                //      {
                                //              WAVEFORMATEXTENSIBLE wfe;
                                //              inFile.seekg(i + 8, std::ios::beg);
                                //              inFile.read(reinterpret_cast<char*>(&wfe), sizeof(wfe));
                                //              m_wf = wfe.Format;
                                //      }
                                //      break;
                                //default:
                                //      inFile.close();
                                //      return;
                                //}
                                inFile.seekg(i + 8, std::ios::beg);
                                inFile.read(reinterpret_cast<char*>(&m_wf), sizeof(m_wf));
                                bFilledFormat = true;
                                break;
                        }
                        dwChunkSize += 8; //add offsets of the chunk id, and chunk size data entries
                        dwChunkSize += 1;
                        dwChunkSize &= 0xfffffffe; //guarantees WORD padding alignment
                        i += dwChunkSize;
                }
                if(!bFilledFormat)
                {
                        inFile.close();
                        return false;
                }


                //look for 'data' chunk id
                bool bFilledData = false;
                for(unsigned int i = 12; i < dwFileSize; )
                {
                        inFile.seekg(i, std::ios::beg);
                        inFile.read(reinterpret_cast<char*>(&dwChunkId), sizeof(dwChunkId));
                        inFile.seekg(i + 4, std::ios::beg);
                        inFile.read(reinterpret_cast<char*>(&dwChunkSize), sizeof(dwChunkSize));
                        if(dwChunkId == 'atad')
                        {
                                m_waveData = new BYTE[dwChunkSize];
                                inFile.seekg(i + 8, std::ios::beg);
                                inFile.read(reinterpret_cast<char*>(m_waveData), dwChunkSize);
                                m_xa.AudioBytes = dwChunkSize;
                                m_xa.pAudioData = m_waveData;
                                m_xa.PlayBegin = 0;
                                m_xa.PlayLength = 0;
                                bFilledData = true;
                                break;
                        }
                        dwChunkSize += 8; //add offsets of the chunk id, and chunk size data entries
                        dwChunkSize += 1;
                        dwChunkSize &= 0xfffffffe; //guarantees WORD padding alignment
                        i += dwChunkSize;
                }
                if(!bFilledData)
                {
                        inFile.close();
                        return false;
                }


                inFile.close();
                return true;
        }
};


#endif
 

 

Share this post


Link to post
Share on other sites

Basicly the only difference between the running and the not running version is the 'playAudio' function ends, and THEN the sound is not playing anymore. That suggest that something on the stack gets freed what is not supposed to.
My tip is the "Wave buffer" object's destructor is the culprit. I think you must store your sound data until you playing it.
Try making 'buffer' global for example, see if it works.

Share this post


Link to post
Share on other sites

@hunpro: Thank you! I got it, "Wave buffer" was supposed to be global.

 

One more question:

I'm creating 2 classes for sound, one will be "AudioManager" and the other one will be "Audio", "class Audio" will store single sound buffer and can play single sound file, so I will be creating vector<Audio> audioList; inside audio manager.

 

class AudioManager
{
     private:
          vector<Audio> audioList;
      public:
          void add(Audio audio); // Push a new "Audio class" to audioList
          void delete();
};

 

class Audio
{
      private:
            IXAudio2SourceVoice *pSourceVoice;
            XAUDIO2_BUFFER *fBuffer;
      public:

            void loadFile();
            void play();
            void pause();
            // etc...

}; 

 

 

Is that the way it's supposed to be done in FPS game? or should I create a single class and do it differently?

Edited by Medo3337

Share this post


Link to post
Share on other sites

Because you can play one sound buffer more than one at a time (ie. many ppl shooting with the same gun), i would separate the storage and the sounds playing in the 3d/2d space. Basicly i would add an extra class with 3d position etc. and a pointer/index to an 'Audio' class. This would represent a playing sound instance in the game.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this