void sound_ShutdownLibrary( void ) { #if !defined(WZ_NOSOUND) AUDIO_STREAM* stream; #endif SAMPLE_LIST * aSample = active_samples, * tmpSample = NULL; if ( !openal_initialized ) { return; } debug(LOG_SOUND, "starting shutdown"); #if !defined(WZ_NOSOUND) // Stop all streams, sound_UpdateStreams() will deallocate all stopped streams for (stream = active_streams; stream != NULL; stream = stream->next) { sound_StopStream(stream); } sound_UpdateStreams(); alcGetError(device); // clear error codes /* On Linux since this caused some versions of OpenAL to hang on exit. - Per */ debug(LOG_SOUND, "make default context NULL"); alcMakeContextCurrent(NULL); sound_GetContextError(device); debug(LOG_SOUND, "destroy previous context"); alcDestroyContext(context); // this gives a long delay on some impl. sound_GetContextError(device); debug(LOG_SOUND, "close device"); if (alcCloseDevice(device) == ALC_FALSE) { debug(LOG_SOUND, "OpenAl could not close the audio device." ); } #endif while( aSample ) { tmpSample = aSample->next; free( aSample ); aSample = tmpSample; } active_samples = NULL; }
void sound_Update() { SAMPLE_LIST *node = active_samples; SAMPLE_LIST *previous = NULL; ALCenum err; ALfloat gain; if (!openal_initialized) { return; } // Update all streaming audio sound_UpdateStreams(); while (node != NULL) { ALenum state, err; // query what the gain is for this sample alGetSourcef(node->curr->iSample, AL_GAIN, &gain); err = sound_GetError(); // if gain is 0, then we can't hear it, so we kill it. if (gain == 0.0f) { sound_DestroyIteratedSample(&previous, &node); continue; } //ASSERT(alIsSource(node->curr->iSample), "Not a valid source!"); alGetSourcei(node->curr->iSample, AL_SOURCE_STATE, &state); // Check whether an error occurred while retrieving the state. // If one did, the state returned is useless. So instead of // using it continue with the next sample. err = sound_GetError(); if (err != AL_NO_ERROR) { // Make sure to invoke the "finished" callback sound_FinishedCallback(node->curr); // Destroy this object and move to the next object sound_DestroyIteratedSample(&previous, &node); continue; } switch (state) { case AL_PLAYING: case AL_PAUSED: // If we haven't finished playing yet, just // continue with the next item in the list. // sound_SetObjectPosition(i->curr->iSample, i->curr->x, i->curr->y, i->curr->z); // Move to the next object previous = node; node = node->next; break; // NOTE: if it isn't playing | paused, then it is most likely either done // or a error. In either case, we want to kill the sample in question. default: sound_DestroyIteratedSample(&previous, &node); break; } } // Reset the current error state alcGetError(device); alcProcessContext(context); err = sound_GetContextError(device); if (err != ALC_NO_ERROR) { debug(LOG_ERROR, "Error while processing audio context: %s", alGetString(err)); } }