/* * 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_AllocateStreamChannel ================= */ static void S_AL_AllocateStreamChannel( void ) { // Allocate a streamSource at high priority streamSourceHandle = S_AL_SrcAlloc(SRCPRI_STREAM, -2, 0); if(streamSourceHandle == -1) return; // Lock the streamSource so nobody else can use it, and get the raw streamSource S_AL_SrcLock(streamSourceHandle); streamSource = S_AL_SrcGet(streamSourceHandle); // Set some streamSource parameters qalSourcei (streamSource, AL_BUFFER, 0 ); qalSourcei (streamSource, AL_LOOPING, AL_FALSE ); qalSource3f(streamSource, AL_POSITION, 0.0, 0.0, 0.0); qalSource3f(streamSource, AL_VELOCITY, 0.0, 0.0, 0.0); qalSource3f(streamSource, AL_DIRECTION, 0.0, 0.0, 0.0); qalSourcef (streamSource, AL_ROLLOFF_FACTOR, 0.0 ); qalSourcei (streamSource, AL_SOURCE_RELATIVE, AL_TRUE ); }
void AL_RawSamples( int samples, int rate, int width, int channels, byte *data, float volume ) { ALuint buffer; ALuint format; format = S_AL_Format( width, channels ); // Create a buffer, and stuff the data into it qalGenBuffers(1, &buffer); qalBufferData(buffer, format, (ALvoid *)data, (samples * width * channels), rate); active_buffers++; // set volume qalSourcef( streamSource, AL_GAIN, volume ); // Shove the data onto the streamSource qalSourceQueueBuffers(streamSource, 1, &buffer); // emulate behavior of S_RawSamples for s_rawend s_rawend += samples; }
/** * Source aquire / release */ static void al_mus_source_get( void ) { // Allocate a source at high priority source_handle = al_src_alloc( SRCPRI_STREAM, -2, 0 ); if ( source_handle == -1 ) { return; } // Lock the source so nobody else can use it, and get the raw source al_src_lock( source_handle ); source = al_src_get( source_handle ); // Set some source parameters qalSource3f( source, AL_POSITION, 0.0, 0.0, 0.0 ); qalSource3f( source, AL_VELOCITY, 0.0, 0.0, 0.0 ); qalSource3f( source, AL_DIRECTION, 0.0, 0.0, 0.0 ); qalSourcef( source, AL_ROLLOFF_FACTOR, 0.0 ); qalSourcei( source, AL_SOURCE_RELATIVE, AL_TRUE ); }
/* * Queues raw samples for playback. Used * by the background music an cinematics. */ void AL_RawSamples ( q_int32_t samples, q_int32_t rate, q_int32_t width, q_int32_t channels, byte *data, float volume ) { ALuint buffer; ALuint format = 0; /* Work out 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 a buffer, and stuff the data into it */ qalGenBuffers ( 1, &buffer ); qalBufferData ( buffer, format, ( ALvoid * ) data, ( samples * width * channels ), rate ); active_buffers++; /* set volume */ if ( volume > 1.0f ) { volume = 1.0f; } qalSourcef ( streamSource, AL_GAIN, volume ); /* Shove the data onto the streamSource */ qalSourceQueueBuffers ( streamSource, 1, &buffer ); /* emulate behavior of S_RawSamples for s_rawend */ s_rawend += samples; }
/* ================= S_AL_StartBackgroundTrack ================= */ static void S_AL_StartBackgroundTrack( const char *intro, const char *loop ) { int i; qboolean issame; // Stop any existing music that might be playing S_AL_StopBackgroundTrack(); if((!intro || !*intro) && (!loop || !*loop)) return; // Allocate a musicSource S_AL_MusicSourceGet(); if(musicSourceHandle == -1) return; if (!loop || !*loop) { loop = intro; issame = qtrue; } else if(intro && *intro && !strcmp(intro, loop)) issame = qtrue; else issame = qfalse; // Copy the loop over strncpy( s_backgroundLoop, loop, sizeof( s_backgroundLoop ) ); if(!issame) { // Open the intro and don't mind whether it succeeds. // The important part is the loop. intro_stream = S_CodecOpenStream(intro); } else intro_stream = NULL; mus_stream = S_CodecOpenStream(s_backgroundLoop); if(!mus_stream) { S_AL_CloseMusicFiles(); S_AL_MusicSourceFree(); return; } // Generate the musicBuffers qalGenBuffers(NUM_MUSIC_BUFFERS, musicBuffers); // Queue the musicBuffers up for(i = 0; i < NUM_MUSIC_BUFFERS; i++) { S_AL_MusicProcess(musicBuffers[i]); } qalSourceQueueBuffers(musicSource, NUM_MUSIC_BUFFERS, musicBuffers); // Set the initial gain property qalSourcef(musicSource, AL_GAIN, s_alGain->value * s_musicVolume->value); // Start playing qalSourcePlay(musicSource); musicPlaying = qtrue; }
/* ================= 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 ); }