void al_stream_update() { int processed; ALint state; if ( source_handle == -1 ) { return; } // Un-queue any buffers, and delete them qalGetSourcei( source, AL_BUFFERS_PROCESSED, &processed ); if ( processed ) { while ( processed-- ) { ALuint buffer; qalSourceUnqueueBuffers( source, 1, &buffer ); qalDeleteBuffers( 1, &buffer ); } } // If it's stopped, release the source qalGetSourcei( source, AL_SOURCE_STATE, &state ); if ( state == AL_STOPPED ) { is_playing = qfalse; qalSourceStop( source ); free_channel(); } }
/* ================= S_AL_MusicUpdate ================= */ static void S_AL_MusicUpdate( void ) { int numBuffers; ALint state; if(!musicPlaying) return; qalGetSourcei( musicSource, AL_BUFFERS_PROCESSED, &numBuffers ); while( numBuffers-- ) { ALuint b; qalSourceUnqueueBuffers(musicSource, 1, &b); S_AL_MusicProcess(b); qalSourceQueueBuffers(musicSource, 1, &b); } // Hitches can cause OpenAL to be starved of buffers when streaming. // If this happens, it will stop playback. This restarts the source if // it is no longer playing, and if there are buffers available qalGetSourcei( musicSource, AL_SOURCE_STATE, &state ); qalGetSourcei( musicSource, AL_BUFFERS_QUEUED, &numBuffers ); if( state == AL_STOPPED && numBuffers ) { Com_DPrintf( S_COLOR_YELLOW "Restarted OpenAL music\n" ); qalSourcePlay(musicSource); } // Set the gain property qalSourcef(musicSource, AL_GAIN, s_alGain->value * s_musicVolume->value); }
/* * Updates stream sources by removing all played * buffers and restarting playback if necessary. */ static void AL_StreamUpdate(void) { int numBuffers; ALint state; /* Un-queue any buffers, and delete them */ qalGetSourcei(streamSource, AL_BUFFERS_PROCESSED, &numBuffers); while (numBuffers--) { ALuint buffer; qalSourceUnqueueBuffers(streamSource, 1, &buffer); qalDeleteBuffers(1, &buffer); active_buffers--; } /* Start the streamSource playing if necessary */ qalGetSourcei(streamSource, AL_BUFFERS_QUEUED, &numBuffers); qalGetSourcei(streamSource, AL_SOURCE_STATE, &state); if (state == AL_STOPPED) { streamPlaying = false; } if (!streamPlaying && numBuffers) { qalSourcePlay(streamSource); streamPlaying = true; } }
void al_mus_update( void ) { int processed; ALint state; if ( !mus_playing ) { return; } qalGetSourcei( source, AL_BUFFERS_PROCESSED, &processed ); if ( processed ) { while ( processed-- ) { ALuint b; qalSourceUnqueueBuffers( source, 1, &b ); al_mus_process( b ); qalSourceQueueBuffers( source, 1, &b ); } } // If it's not still playing, give it a kick qalGetSourcei( source, AL_SOURCE_STATE, &state ); if ( state == AL_STOPPED ) { si.Printf( PRINT_ALL, "Musical kick\n" ); qalSourcePlay( source ); } // Set the gain property qalSourcef( source, AL_GAIN, s_gain->value * s_musicVolume->value ); }
/* ================= S_StreamRawSamples Cinematic streaming ================= */ void S_StreamRawSamples (const byte *data, int samples, int rate, int width, int channels) { int processed, state, size; unsigned format, buffer; if (!s_initialized) return; if (!s_streamingChannel) return; // Unqueue and delete any processed buffers qalGetSourcei(s_streamingChannel->sourceNum, AL_BUFFERS_PROCESSED, &processed); if (processed > 0){ while (processed--){ qalSourceUnqueueBuffers(s_streamingChannel->sourceNum, 1, &buffer); qalDeleteBuffers(1, &buffer); } } // Calculate buffer size size = samples * width * channels; // Set buffer format if (width == 2) { if (channels == 2) format = AL_FORMAT_STEREO16; else format = AL_FORMAT_MONO16; } else { if (channels == 2) format = AL_FORMAT_STEREO8; else format = AL_FORMAT_MONO8; } // Upload and queue the new buffer qalGenBuffers(1, &buffer); qalBufferData(buffer, format, (byte *)data, size, rate); qalSourceQueueBuffers(s_streamingChannel->sourceNum, 1, &buffer); // Update volume qalSourcef(s_streamingChannel->sourceNum, AL_GAIN, s_sfxVolume->value); // If not playing, then do so qalGetSourcei(s_streamingChannel->sourceNum, AL_SOURCE_STATE, &state); if (state != AL_PLAYING) qalSourcePlay(s_streamingChannel->sourceNum); }
void AL_Update(void) { int i; channel_t *ch; vec_t orientation[6]; if (!s_active) { return; } paintedtime = cl.time; // set listener parameters qalListener3f(AL_POSITION, AL_UnpackVector(listener_origin)); AL_CopyVector(listener_forward, orientation); AL_CopyVector(listener_up, orientation + 3); qalListenerfv(AL_ORIENTATION, orientation); qalListenerf(AL_GAIN, s_volume->value); qalDistanceModel(AL_LINEAR_DISTANCE_CLAMPED); // update spatialization for dynamic sounds ch = channels; for (i = 0; i < s_numchannels; i++, ch++) { if (!ch->sfx) continue; if (ch->autosound) { // autosounds are regenerated fresh each frame if (ch->autoframe != s_framecount) { AL_StopChannel(ch); continue; } } else { ALenum state; qalGetError(); qalGetSourcei(ch->srcnum, AL_SOURCE_STATE, &state); if (qalGetError() != AL_NO_ERROR || state == AL_STOPPED) { AL_StopChannel(ch); continue; } } #ifdef _DEBUG if (s_show->integer) { Com_Printf("%.1f %s\n", ch->master_vol, ch->sfx->name); // total++; } #endif AL_Spatialize(ch); // respatialize channel } s_framecount++; // add loopsounds AL_AddLoopSounds(); AL_IssuePlaysounds(); }
/* ================= S_AL_StopBackgroundTrack ================= */ static void S_AL_StopBackgroundTrack( void ) { int num; if(!musicPlaying) return; // Stop playing qalSourceStop(musicSource); // De-queue the musicBuffers qalGetSourcei(musicSource, AL_BUFFERS_PROCESSED, &num); if(num < NUM_MUSIC_BUFFERS) Com_Printf(S_COLOR_YELLOW "WARNING: fewer than NUM_MUSIC_BUFFERS buffers can be unqueued\n"); qalSourceUnqueueBuffers(musicSource, NUM_MUSIC_BUFFERS, musicBuffers); // Destroy the musicBuffers qalDeleteBuffers(NUM_MUSIC_BUFFERS, musicBuffers); // Free the musicSource S_AL_MusicSourceFree(); // Unload the stream S_AL_CloseMusicFiles(); musicPlaying = qfalse; }
/* * Main update function. Called every frame, * performes all necessary calculations. */ void AL_Update ( void ) { q_int32_t i; channel_t *ch; vec_t orientation[6]; paintedtime = cl.time; /* set listener (player) parameters */ AL_CopyVector ( listener_forward, orientation ); AL_CopyVector ( listener_up, orientation + 3 ); qalListenerf ( AL_GAIN, s_volume->value ); qalListenerf ( AL_MAX_GAIN, s_openal_maxgain->value ); qalDistanceModel ( AL_LINEAR_DISTANCE_CLAMPED ); qalListener3f ( AL_POSITION, AL_UnpackVector ( listener_origin ) ); qalListenerfv ( AL_ORIENTATION, orientation ); /* update spatialization for dynamic sounds */ ch = channels; for ( i = 0; i < s_numchannels; i++, ch++ ) { if ( !ch->sfx ) { continue; } if ( ch->autosound ) { /* autosounds are regenerated fresh each frame */ if ( ch->autoframe != s_framecount ) { AL_StopChannel ( ch ); continue; } } else { ALenum state; qalGetError(); qalGetSourcei ( ch->srcnum, AL_SOURCE_STATE, &state ); if ( ( qalGetError() != AL_NO_ERROR ) || ( state == AL_STOPPED ) ) { AL_StopChannel ( ch ); continue; } } if ( s_show->value ) { Com_Printf ( "%3i %s\n", ch->master_vol, ch->sfx->name ); } /* respatialize channel */ AL_Spatialize ( ch ); } s_framecount++; /* add loopsounds */ AL_AddLoopSounds(); /* add music */ #ifdef HT_WITH_OGG OGG_Stream(); #endif AL_StreamUpdate(); AL_IssuePlaysounds(); }
/* ================= S_AL_StreamUpdate ================= */ static void S_AL_StreamUpdate( int stream ) { int numBuffers; ALint state; if ((stream < 0) || (stream >= MAX_RAW_STREAMS)) return; if(streamSourceHandles[stream] == -1) return; // Un-queue any buffers, and delete them qalGetSourcei( streamSources[stream], AL_BUFFERS_PROCESSED, &numBuffers ); while( numBuffers-- ) { ALuint buffer; qalSourceUnqueueBuffers(streamSources[stream], 1, &buffer); qalDeleteBuffers(1, &buffer); } // Start the streamSource playing if necessary qalGetSourcei( streamSources[stream], AL_BUFFERS_QUEUED, &numBuffers ); qalGetSourcei(streamSources[stream], AL_SOURCE_STATE, &state); if(state == AL_STOPPED) { streamPlaying[stream] = qfalse; // If there are no buffers queued up, release the streamSource if( !numBuffers ) S_AL_FreeStreamChannel( stream ); } if( !streamPlaying[stream] && numBuffers ) { qalSourcePlay( streamSources[stream] ); streamPlaying[stream] = qtrue; } }
/* * Silence / stop all OpenAL streams */ static void AL_StreamDie ( void ) { q_int32_t numBuffers; streamPlaying = false; qalSourceStop ( streamSource ); /* Un-queue any buffers, and delete them */ qalGetSourcei ( streamSource, AL_BUFFERS_QUEUED, &numBuffers ); while ( numBuffers-- ) { ALuint buffer; qalSourceUnqueueBuffers ( streamSource, 1, &buffer ); qalDeleteBuffers ( 1, &buffer ); active_buffers--; } }
/* * S_UpdateSources */ void S_UpdateSources( void ) { int i, entNum; ALint state; for( i = 0; i < src_count; i++ ) { if( srclist[i].isLocked ) continue; if( !srclist[i].isActive ) continue; if( s_volume->modified ) qalSourcef( srclist[i].source, AL_GAIN, srclist[i].fvol * s_volume->value ); // Check if it's done, and flag it qalGetSourcei( srclist[i].source, AL_SOURCE_STATE, &state ); if( state == AL_STOPPED ) { source_kill( &srclist[i] ); continue; } entNum = srclist[i].entNum; if( srclist[i].isLooping ) { // If a looping effect hasn't been touched this frame, kill it if( !entlist[entNum].touched ) { source_kill( &srclist[i] ); entlist[entNum].src = NULL; } else { entlist[entNum].touched = qfalse; } } source_spatialize( &srclist[i] ); } }
/* ================= S_AL_SrcUpdate Update state (move things around, manage sources, and so on) ================= */ static void S_AL_SrcUpdate( void ) { int i; int entityNum; ALint state; src_t *curSource; for(i = 0; i < srcCount; i++) { entityNum = srcList[i].entity; curSource = &srcList[i]; if(curSource->isLocked) continue; if(!curSource->isActive) continue; // Update source parameters if((s_alGain->modified)||(s_volume->modified)) curSource->curGain = s_alGain->value * s_volume->value; if((s_alRolloff->modified)&&(!curSource->local)) qalSourcef(curSource->alSource, AL_ROLLOFF_FACTOR, s_alRolloff->value); if(s_alMinDistance->modified) qalSourcef(curSource->alSource, AL_REFERENCE_DISTANCE, s_alMinDistance->value); if(curSource->isLooping) { sentity_t *sent = &entityList[ entityNum ]; // If a looping effect hasn't been touched this frame, kill it if(sent->loopAddedThisFrame) { // The sound has changed without an intervening removal if(curSource->isActive && !sent->startLoopingSound && curSource->sfx != sent->loopSfx) { qalSourceStop(curSource->alSource); qalSourcei(curSource->alSource, AL_BUFFER, 0); sent->startLoopingSound = qtrue; } // The sound hasn't been started yet if(sent->startLoopingSound) { S_AL_SrcSetup(i, sent->loopSfx, sent->loopPriority, entityNum, -1, curSource->local); curSource->isLooping = qtrue; qalSourcei(curSource->alSource, AL_LOOPING, AL_TRUE); qalSourcePlay(curSource->alSource); sent->startLoopingSound = qfalse; } // Update locality if(curSource->local) { qalSourcei(curSource->alSource, AL_SOURCE_RELATIVE, AL_TRUE); qalSourcef(curSource->alSource, AL_ROLLOFF_FACTOR, 0.0f); } else { qalSourcei(curSource->alSource, AL_SOURCE_RELATIVE, AL_FALSE); qalSourcef(curSource->alSource, AL_ROLLOFF_FACTOR, s_alRolloff->value); } } else S_AL_SrcKill( i ); continue; } // Check if it's done, and flag it qalGetSourcei(curSource->alSource, AL_SOURCE_STATE, &state); if(state == AL_STOPPED) { S_AL_SrcKill(i); continue; } // Query relativity of source, don't move if it's true qalGetSourcei(curSource->alSource, AL_SOURCE_RELATIVE, &state); // See if it needs to be moved if(curSource->isTracking && !state) { qalSourcefv(curSource->alSource, AL_POSITION, entityList[entityNum].origin); S_AL_ScaleGain(curSource, entityList[entityNum].origin); } } }
void SndAl_RawSamples( int stream, int samples, int rate, int width, int channels, const byte *data, float volume, int entityNum ) { ALuint buffer; ALuint format = AL_FORMAT_STEREO16; ALint state; // Work out AL format if ( width == 1 ) { if ( channels == 1 ) { format = AL_FORMAT_MONO8; } else if ( channels == 2 ) { format = AL_FORMAT_STEREO8; } } else if ( width == 2 ) { if ( channels == 1 ) { format = AL_FORMAT_MONO16; } else if ( channels == 2 ) { format = AL_FORMAT_STEREO16; } } // Create the source if necessary if ( source_handle == -1 ) { allocate_channel(); // Failed? if ( source_handle == -1 ) { si.Printf( PRINT_ALL, "Can't allocate streaming source\n" ); return; } } // Create a buffer, and stuff the data into it qalGenBuffers( 1, &buffer ); qalBufferData( buffer, format, data, ( samples * width * channels ), rate ); // Shove the data onto the source qalSourceQueueBuffers( source, 1, &buffer ); // Start the source playing if necessary qalGetSourcei( source, AL_SOURCE_STATE, &state ); // Volume qalSourcef( source, AL_GAIN, volume * s_volume->value * s_gain->value ); if ( !is_playing ) { qalSourcePlay( source ); is_playing = qtrue; } }
void S_UpdateMusic( void ) { int i, processed; ALint state; ALenum error; ALuint b; int num_processed_buffers; ALuint processed_buffers[MUSIC_BUFFERS]; if( !s_bgTrack ) return; if( !s_musicvolume->value && !s_bgTrack->isUrl ) return; if( s_bgTrackPaused || s_bgTrackLocked ) return; if( s_bgTrackBuffering ) { if( S_EoStream( s_bgTrack->stream ) ) { // we should now advance to the next track S_CloseMusicTrack( s_bgTrack ); } else { if( S_FTellSteam( s_bgTrack->stream ) < BACKGROUND_TRACK_BUFFERING_SIZE ) return; // in case we delayed openening to let the stream be cached for a while, // start actually reading from it now if( !S_ContOpenStream( s_bgTrack->stream ) ) { // let music_process do the dirty job of advancing to the next track S_CloseMusicTrack( s_bgTrack ); s_bgTrack->ignore = qtrue; } } s_bgTrackBuffering = qfalse; } if( !queued_buffers ) { // if we haven't queued any buffers yet, do it now num_processed_buffers = MUSIC_BUFFERS; memcpy( processed_buffers, buffers, sizeof( buffers ) ); } else { num_processed_buffers = 0; processed = 0; qalGetSourcei( source, AL_BUFFERS_PROCESSED, &processed ); while( processed-- ) { qalSourceUnqueueBuffers( source, 1, &b ); processed_buffers[num_processed_buffers++] = b; } } for( i = 0; i < num_processed_buffers; i++ ) { b = processed_buffers[i]; if( !music_process( b ) ) { Com_Printf( "Error processing music data\n" ); S_StopBackgroundTrack(); return; } qalSourceQueueBuffers( source, 1, &b ); if( ( error = qalGetError() ) != AL_NO_ERROR ) { Com_Printf( "Couldn't queue music data (%s)\n", S_ErrorMessage( error ) ); S_StopBackgroundTrack(); return; } } // If it's not still playing, give it a kick qalGetSourcei( source, AL_SOURCE_STATE, &state ); if( !queued_buffers || state != AL_PLAYING ) { queued_buffers = qtrue; qalSourcePlay( source ); } if( s_musicvolume->modified ) qalSourcef( source, AL_GAIN, s_musicvolume->value ); }