Help me about "Beginning Game Audio Programming" Book
Hi there,
I have bought the book 'Beginning Game Audio Programming' by Mason McCuskey .
I have some problems in this book,do you have 'Mason McCuskey' email address ?
in "part one ,Chapter 7: MP3 and WMA Playback" i can't change the mp3 volume.
please help me
Thanks
--Mojtaba--
OK, let's take a look to we have until now:
-One hand, there's a CVolume class, which simply is saving the amount of specified volume attenuation, not stablishing it.
-The other hand, there's a performance, segments and audiopaths, and the amount of volume that the CVolume object holds is put into an audiopath, and then, on CSoundInstance::Init, we call PlaySegmentEx method of the performance passing the segment we want to play at the volume attenuation specified by the audiopath passed as well.
So... what's going on here?. Why doesn't work for a .MP3 file?. Because for playing it we're NOT using nor performances, nor segments, nor audiopaths!. Instead of, on Ch7p1_MP3Playback sample we're creating a Graph Filter using DirectShow's Graph Manager interface, and then we push the "virtual Play button" via the Run method of the DirectSound's IMediaControl interface. Where's supposed we're specifying to DirectShow to set a volume attenuation on sample Ch7p1_MP3Playback?. On NONE place!. And just for that reason setting the volume for playing a .MP3 file is not working.
For doing this, we'll need the Graph Builder to query another more interface: IBasicAudio, capable of modifying the balance... and the volume!. ; ) We'll use the put_Volume method of this new interface for doing this, so:
1st) We declare a pointer to IBasicAudio interface as a protected attribute on CDirectShowMusic class (where IGraphBuilder, IMediaControl and IMediaEventEx are declared as well).
protected:
...
IGraphBuilder *m_GraphBuilder;
IMediaControl *m_MediaControl;
IMediaEventEx *m_MediaEventEx;
//¡¡¡!!!
IBasicAudio *m_BasicAudio;
...
2nd) As the above ones mentioned, we we set this pointer to NULL on CDirectShowMusic constructor, and make a SAFE_RELEASE of if on CDirectShowMusic destructor.
...
m_GraphBuilder = NULL;
m_MediaControl = NULL;
m_MediaEventEx = NULL;
//¡¡¡!!!
m_BasicAudio = NULL;
...
...
SAFE_RELEASE(m_MediaControl);
SAFE_RELEASE(m_MediaEventEx);
SAFE_RELEASE(m_GraphBuilder);
//¡¡¡!!!
SAFE_RELEASE(m_BasicAudio);
...
3rd) Until now, CAudioManager was a friend class of CSound; instead of, on Ch7p1_MP3Playback CAudioManager is gonna be a friend class of derived classes of CSound, including CMP3, so CAudioMaganer class will have access to m_GraphBuilder, m_MediaControl, m_MediaEventEx and... m_BasicAudio as well. ; ) We can query an interface to IBasicAudio via Graph Builder on CAudioManager::LoadMP3
CSoundPtr CAudioManager::LoadMP3(std::string filename)
{
...
CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
IID_IGraphBuilder, (void **)&mp3->m_GraphBuilder);
mp3->m_GraphBuilder->QueryInterface(IID_IMediaControl, (void **)&mp3->m_MediaControl);
mp3->m_GraphBuilder->QueryInterface(IID_IMediaEventEx, (void **)&mp3->m_MediaEventEx);
// ¡¡¡!!!
mp3->m_GraphBuilder->QueryInterface(IID_IBasicAudio, (void **)&mp3->m_BasicAudio);
...
}
4th) The code for CDirectShowMusic::Play() would seem like this:
bool CDirectShowMusic::Play()
{
if (m_MediaControl == NULL) return(false);
// ¡¡¡!!!
//////////////
long lVolParaDirectShow = 0;
lVolParaDirectShow = (long)m_Volume.ToDirectMusic();
if (lVolParaDirectShow > 0)
lVolParaDirectShow = 0;
if (lVolParaDirectShow <= -9600)
lVolParaDirectShow = -10000;
m_BasicAudio->put_Volume(lVolParaDirectShow);
///////////////
ThrowIfFailed(m_MediaControl->Run(), "CDirectShowMusic::Play(): Run failed.");
m_IsPlaying = true;
return(true);
}
Due to put_Volume method works on a range of [-10000..0] instead of [-9600..0] I make a little adjustment, however it needs to be more accurate, because right now, if you set an attenuation volume of -60 you'll have yo put your speakers to maximum volume to hear a loooooow trace of the song, (try firstly with -15 or -20, enough for testing if everything is OK), but that's enough fine. ; )
See ya.
-One hand, there's a CVolume class, which simply is saving the amount of specified volume attenuation, not stablishing it.
-The other hand, there's a performance, segments and audiopaths, and the amount of volume that the CVolume object holds is put into an audiopath, and then, on CSoundInstance::Init, we call PlaySegmentEx method of the performance passing the segment we want to play at the volume attenuation specified by the audiopath passed as well.
So... what's going on here?. Why doesn't work for a .MP3 file?. Because for playing it we're NOT using nor performances, nor segments, nor audiopaths!. Instead of, on Ch7p1_MP3Playback sample we're creating a Graph Filter using DirectShow's Graph Manager interface, and then we push the "virtual Play button" via the Run method of the DirectSound's IMediaControl interface. Where's supposed we're specifying to DirectShow to set a volume attenuation on sample Ch7p1_MP3Playback?. On NONE place!. And just for that reason setting the volume for playing a .MP3 file is not working.
For doing this, we'll need the Graph Builder to query another more interface: IBasicAudio, capable of modifying the balance... and the volume!. ; ) We'll use the put_Volume method of this new interface for doing this, so:
1st) We declare a pointer to IBasicAudio interface as a protected attribute on CDirectShowMusic class (where IGraphBuilder, IMediaControl and IMediaEventEx are declared as well).
protected:
...
IGraphBuilder *m_GraphBuilder;
IMediaControl *m_MediaControl;
IMediaEventEx *m_MediaEventEx;
//¡¡¡!!!
IBasicAudio *m_BasicAudio;
...
2nd) As the above ones mentioned, we we set this pointer to NULL on CDirectShowMusic constructor, and make a SAFE_RELEASE of if on CDirectShowMusic destructor.
...
m_GraphBuilder = NULL;
m_MediaControl = NULL;
m_MediaEventEx = NULL;
//¡¡¡!!!
m_BasicAudio = NULL;
...
...
SAFE_RELEASE(m_MediaControl);
SAFE_RELEASE(m_MediaEventEx);
SAFE_RELEASE(m_GraphBuilder);
//¡¡¡!!!
SAFE_RELEASE(m_BasicAudio);
...
3rd) Until now, CAudioManager was a friend class of CSound; instead of, on Ch7p1_MP3Playback CAudioManager is gonna be a friend class of derived classes of CSound, including CMP3, so CAudioMaganer class will have access to m_GraphBuilder, m_MediaControl, m_MediaEventEx and... m_BasicAudio as well. ; ) We can query an interface to IBasicAudio via Graph Builder on CAudioManager::LoadMP3
CSoundPtr CAudioManager::LoadMP3(std::string filename)
{
...
CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
IID_IGraphBuilder, (void **)&mp3->m_GraphBuilder);
mp3->m_GraphBuilder->QueryInterface(IID_IMediaControl, (void **)&mp3->m_MediaControl);
mp3->m_GraphBuilder->QueryInterface(IID_IMediaEventEx, (void **)&mp3->m_MediaEventEx);
// ¡¡¡!!!
mp3->m_GraphBuilder->QueryInterface(IID_IBasicAudio, (void **)&mp3->m_BasicAudio);
...
}
4th) The code for CDirectShowMusic::Play() would seem like this:
bool CDirectShowMusic::Play()
{
if (m_MediaControl == NULL) return(false);
// ¡¡¡!!!
//////////////
long lVolParaDirectShow = 0;
lVolParaDirectShow = (long)m_Volume.ToDirectMusic();
if (lVolParaDirectShow > 0)
lVolParaDirectShow = 0;
if (lVolParaDirectShow <= -9600)
lVolParaDirectShow = -10000;
m_BasicAudio->put_Volume(lVolParaDirectShow);
///////////////
ThrowIfFailed(m_MediaControl->Run(), "CDirectShowMusic::Play(): Run failed.");
m_IsPlaying = true;
return(true);
}
Due to put_Volume method works on a range of [-10000..0] instead of [-9600..0] I make a little adjustment, however it needs to be more accurate, because right now, if you set an attenuation volume of -60 you'll have yo put your speakers to maximum volume to hear a loooooow trace of the song, (try firstly with -15 or -20, enough for testing if everything is OK), but that's enough fine. ; )
See ya.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement