XAudio2 Not Playing

Started by
10 comments, last by Medo Mex 11 years ago

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?

Advertisement

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

Nathan Madsen
Nate (AT) MadsenStudios (DOT) Com
Composer-Sound Designer
Madsen Studios
Austin, TX

@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.

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.

Nathan Madsen
Nate (AT) MadsenStudios (DOT) Com
Composer-Sound Designer
Madsen Studios
Austin, TX

That will load the audio file but not play it, since while(TRUE) { } is a FOREVER loop, it will prevent the program from executing audio->play();

I'll just start a new topic in DirectX and XNA.

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?

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.

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
 

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.

@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?

This topic is closed to new replies.

Advertisement