/* * source_setup */ static void source_setup( src_t *src, sfx_t *sfx, int priority, int entNum, int channel, float fvol, float attenuation ) { ALuint buffer; // Mark the SFX as used, and grab the raw AL buffer S_UseBuffer( sfx ); buffer = S_GetALBuffer( sfx ); clamp_low( attenuation, 0.0f ); src->lastUse = trap_Milliseconds(); src->sfx = sfx; src->priority = priority; src->entNum = entNum; src->channel = channel; src->fvol = fvol; src->attenuation = attenuation; src->isActive = qtrue; src->isLocked = qfalse; src->isLooping = qfalse; src->isTracking = qfalse; VectorClear( src->origin ); VectorClear( src->velocity ); qalSourcefv( src->source, AL_POSITION, vec3_origin ); qalSourcefv( src->source, AL_VELOCITY, vec3_origin ); qalSourcef( src->source, AL_GAIN, fvol * s_volume->value ); qalSourcei( src->source, AL_SOURCE_RELATIVE, AL_FALSE ); qalSourcei( src->source, AL_LOOPING, AL_FALSE ); qalSourcei( src->source, AL_BUFFER, buffer ); qalSourcef( src->source, AL_REFERENCE_DISTANCE, s_attenuation_refdistance ); qalSourcef( src->source, AL_MAX_DISTANCE, s_attenuation_maxdistance ); qalSourcef( src->source, AL_ROLLOFF_FACTOR, attenuation ); }
/* ================= S_AL_SrcSetup ================= */ static void S_AL_SrcSetup(srcHandle_t src, sfxHandle_t sfx, alSrcPriority_t priority, int entity, int channel, qboolean local) { ALuint buffer; src_t *curSource; // Mark the SFX as used, and grab the raw AL buffer S_AL_BufferUse(sfx); buffer = S_AL_BufferGet(sfx); // Set up src struct curSource = &srcList[src]; curSource->lastUsedTime = Sys_Milliseconds(); curSource->sfx = sfx; curSource->priority = priority; curSource->entity = entity; curSource->channel = channel; curSource->isActive = qtrue; curSource->isLocked = qfalse; curSource->isLooping = qfalse; curSource->isTracking = qfalse; curSource->curGain = s_alGain->value * s_volume->value; curSource->scaleGain = curSource->curGain; curSource->local = local; // Set up OpenAL source qalSourcei(curSource->alSource, AL_BUFFER, buffer); qalSourcef(curSource->alSource, AL_PITCH, 1.0f); qalSourcef(curSource->alSource, AL_GAIN, curSource->curGain); qalSourcefv(curSource->alSource, AL_POSITION, vec3_origin); qalSourcefv(curSource->alSource, AL_VELOCITY, vec3_origin); qalSourcei(curSource->alSource, AL_LOOPING, AL_FALSE); qalSourcef(curSource->alSource, AL_REFERENCE_DISTANCE, s_alMinDistance->value); if(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); } }
/* * source_spatialize */ static void source_spatialize( src_t *src ) { if( !src->attenuation ) { qalSourcei( src->source, AL_SOURCE_RELATIVE, AL_TRUE ); // this was set at source_setup, no need to redo every frame //qalSourcefv( src->source, AL_POSITION, vec3_origin ); //qalSourcefv( src->source, AL_VELOCITY, vec3_origin ); return; } if( src->isTracking ) trap_GetEntitySpatilization( src->entNum, src->origin, src->velocity ); qalSourcei( src->source, AL_SOURCE_RELATIVE, AL_FALSE ); qalSourcefv( src->source, AL_POSITION, src->origin ); qalSourcefv( src->source, AL_VELOCITY, src->velocity ); }
/* ================= S_AL_StartSound Play a one-shot sound effect ================= */ static void S_AL_StartSound( vec3_t origin, int entnum, int entchannel, sfxHandle_t sfx ) { vec3_t sorigin; srcHandle_t src; if(S_AL_CheckInput(origin ? 0 : entnum, sfx)) return; // Try to grab a source src = S_AL_SrcAlloc(SRCPRI_ONESHOT, entnum, entchannel); if(src == -1) return; // Set up the effect if( origin == NULL ) { if( S_AL_HearingThroughEntity( entnum ) ) { // Where the entity is the local player, play a local sound S_AL_SrcSetup( src, sfx, SRCPRI_ONESHOT, entnum, entchannel, qtrue ); VectorClear( sorigin ); } else { S_AL_SrcSetup( src, sfx, SRCPRI_ONESHOT, entnum, entchannel, qfalse ); VectorCopy( entityList[ entnum ].origin, sorigin ); } srcList[ src ].isTracking = qtrue; } else { S_AL_SrcSetup( src, sfx, SRCPRI_ONESHOT, entnum, entchannel, qfalse ); VectorCopy( origin, sorigin ); } S_AL_SanitiseVector( sorigin ); qalSourcefv( srcList[ src ].alSource, AL_POSITION, sorigin ); S_AL_ScaleGain(&srcList[src], sorigin); // Start it playing qalSourcePlay(srcList[src].alSource); }
/* ================= 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); } } }
/* ================= S_AL_SrcLoop ================= */ static void S_AL_SrcLoop( alSrcPriority_t priority, sfxHandle_t sfx, const vec3_t origin, const vec3_t velocity, int entityNum ) { int src; sentity_t *sent = &entityList[ entityNum ]; src_t *curSource; // Do we need to allocate a new source for this entity if( !sent->srcAllocated ) { // Try to get a channel src = S_AL_SrcAlloc( priority, entityNum, -1 ); if( src == -1 ) { Com_DPrintf( S_COLOR_YELLOW "WARNING: Failed to allocate source " "for loop sfx %d on entity %d\n", sfx, entityNum ); return; } sent->startLoopingSound = qtrue; } else src = sent->srcIndex; sent->srcAllocated = qtrue; sent->srcIndex = src; sent->loopPriority = priority; sent->loopSfx = sfx; // If this is not set then the looping sound is removed sent->loopAddedThisFrame = qtrue; curSource = &srcList[src]; // UGH // These lines should be called via S_AL_SrcSetup, but we // can't call that yet as it buffers sfxes that may change // with subsequent calls to S_AL_SrcLoop curSource->entity = entityNum; curSource->isLooping = qtrue; curSource->isActive = qtrue; if( S_AL_HearingThroughEntity( entityNum ) ) { curSource->local = qtrue; qalSourcefv( curSource->alSource, AL_POSITION, vec3_origin ); qalSourcefv( curSource->alSource, AL_VELOCITY, vec3_origin ); } else { curSource->local = qfalse; qalSourcefv( curSource->alSource, AL_POSITION, (ALfloat *)sent->origin ); qalSourcefv( curSource->alSource, AL_VELOCITY, (ALfloat *)velocity ); } S_AL_ScaleGain(curSource, sent->origin); }