Bug Fixes for GAP library version 1.01

IsPlaying() returns incorrect value or crashes (in Sound, Sound3D, and Segment classes).

IsMusic() functions arenot const

Audio manager would call ServiceBuffer() on sounds after they had been destroyed.

Lexer could occasionally read outside the designated line buffer

Crash when attempting to repeatedly unload and asynchronously load a sound buffer.

Sound could return incorrect values in IsPlaying() if asynchronous loading is turned on.

Audio Library crashed if initialized and shut down without loading any sounds.

Play cursor did not move properly in AudioTest sample app

Bug / IsPlaying() returns incorrect value or crashes (in Sound, Sound3D, and Segment classes).
Repro / The IsPlaying() function might return an incorrect value if called while the sound is being loaded by the loading thread. This bug only occurred if asynchronous loading is enabled.
Fix / The check for the queue playback flag is now performed before checking the DirectSound buffer directly. If this is not true, the loading status is check, and returns false if the buffer is loading (but not queued to play). This way, the sound will return the proper values without checking the DirectSound buffer itself if it is still loading.
Changes / The IsLoading() function was also made const to work with this function. The Sound3D and Segment classes were fixed in a similar fashion, although only the Sound class is shown. Changes were made in Sound.h, Sound.cpp, Sound3D.h, Sound3D.cpp, Segment.h, and Segment.cpp.

Original function:

bool Sound::IsPlaying() const

{

FN("Sound::IsPlaying()");

DWORD dwStatus;

if(m_pDSBuffer)

{

m_pDSBuffer->GetStatus(&dwStatus);

if(dwStatus & DSBSTATUS_PLAYING)

return true;

}

return m_bQueuePlayback;

}

Fixed function (Sound3D and Segment classes fixed similarly):

bool Sound::IsPlaying() const

{

FN("Sound::IsPlaying()");

if(m_bQueuePlayback)

return true;

else if(IsLoading())

return false;

else if(m_pDSBuffer)

{

DWORD dwStatus;

m_pDSBuffer->GetStatus(&dwStatus);

if(dwStatus & DSBSTATUS_PLAYING)

return true;

}

}

Bug / IsMusic() functions are not const
Repro / NA
Fix / Made functions const
Changes / Trivial issue affecting Sound, Sound3D, and Segment classes. Changes were made in Sound.h, Sound3D.h, and Segment.h.
Bug / Audio manager would call ServiceBuffer() on sounds after they had been destroyed.
Repro / Releasing and then immediately creating a new streaming sound could expose this bug. The sound would tend to start skipping after several iterations of this. Because of the object-caching scheme employed, this was technically not an access violation, but was problematic nonetheless.
Fix / The order of streaming buffer removal was changed in the audio manager, and streams are now explicitly removed in the Sound::Unload() function.
Changes / Changes were made in AudioManager.cpp and Sound.cpp to fix this issue.

Original function (removal comes after ServiceBuffer()):

void AudioManager::ServiceStreamingBuffers()

{

FN("AudioManager::ServiceStreamingBuffers()");

// Iterate through all streaming buffers and update

// their buffer data

SoundList::iterator itr;

for(itr = m_SoundStreamProcess.begin();

itr != m_SoundStreamProcess.end(); ++itr)

(*itr)->ServiceBuffer();

// Remove any buffers marked for removal after

// we're done iterating through the list

for(itr = m_SoundStreamRemoval.begin();

itr != m_SoundStreamRemoval.end(); ++itr)

{

SoundList::iterator itor =

find(m_SoundStreamProcess.begin(),

m_SoundStreamProcess.end(), *itr);

if(itor != m_SoundStreamProcess.end())

m_SoundStreamProcess.erase(itor);

}

// Clear the removal list

m_SoundStreamRemoval.clear();

}

Fixed function (removal now comes before ServiceBuffer()):

void AudioManager::ServiceStreamingBuffers()

{

FN("AudioManager::ServiceStreamingBuffers()");

// Remove any buffers marked for removal after

// we're done iterating through the list

SoundList::iterator itr;

for(itr = m_SoundStreamRemoval.begin();

itr != m_SoundStreamRemoval.end(); ++itr)

{

SoundList::iterator itor =

find(m_SoundStreamProcess.begin(),

m_SoundStreamProcess.end(), *itr);

if(itor != m_SoundStreamProcess.end())

m_SoundStreamProcess.erase(itor);

}

// Clear the removal list

m_SoundStreamRemoval.clear();

// Iterate through all streaming buffers and update

// their buffer data

for(itr = m_SoundStreamProcess.begin();

itr != m_SoundStreamProcess.end(); ++itr)

(*itr)->ServiceBuffer();

}

Original code (inside Sound::Unload()):

// Release the source if it's a streaming buffer

if(m_Init.m_bStreaming)

{

m_pLoader->Close();

}

Fixed code (inside Sound::Unload()):

// Release the source if it's a streaming buffer

if(m_Init.m_bStreaming)

{

m_pLoader->Close();

// Remove the stream from the update list

DXAudioMgr()->RemoveStream(this);

// Reset streaming variables

m_nBytesPlayed = 0;

m_nLastReadPos = 0;

m_nDataCursor = 0;

}

Bug / Lexer could occasionally read outside the designated line buffer
Repro / The Lexer class could occasionally read outside the line buffer. Usually it was safe, because the line buffer was part of a larger buffer, but it is a bad practice nonetheless.
Fix / The end-of-line flag is checked before the buffer is read by the function IsWhitespace(), so this should no longer occur.
Changes / Change was made inside Lexer.cpp

Original code (inside Lexer::ParseLine(), at line 488):

else if((IsWhitespace(pLineBuffer[iCurrentPosition]) || bEndOfLine)

& !bStringOpened)

Fixed code (inside Lexer::ParseLine(), at line 488):

else if((bEndOfLine || IsWhitespace(pLineBuffer[iCurrentPosition]))

& !bStringOpened)

Bug / Crash when attempting to repeatedly unload and asynchronously load a sound buffer.
Repro / If asynchronous loading is turned on, a potential crash could be generated by repeatedly destroying and recreating and playing a buffer.
Fix / Sounds now explicitly checks to see if any sound is currently being loaded (using the loader's critical section) before attempting to unload.
Changes / Change was both to AudioMgr.h (added a function to access the critical section that is active when loading resources), and to Sound::Unload() in Sound.cpp.
Bug / Sound could return incorrect values in IsPlaying() if asynchronous loading is turned on.
Repro / If asynchronous loading is turned on, the IsPlaying() function might return an incorrect value because of a flag being turned off before the buffer was actually playing.
Fix / Moved the flag clearing code after the buffer actually begins to play.
Changes / Change was made inside Sound::Play() in Sound.cpp
Bug / Audio Library crashed if initialized and shut down without loading any sounds.
Repro / Initialize and termimate the audio manager without loading or playing any sounds. This was introduced by a fix for another issue, and did not appear in the original 1.0 library.
Fix / Added some initialization checks to the Sound
Changes / Changes made to Sound.cpp, Sound3D.cpp, Segment.cpp, and AudioMgr.cpp.
Bug / Play cursor did not move properly in AudioTest sample app
Repro / Cursor would only update properly after switching back and forth between sounds.
Fix / Forced more explicity updating of the control
Changes / Made changes to Sound2D.cpp and Sound3D.cpp