/* * 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 ); }
/* * Performance stereo spatialization * of a channel in the frontends * sense. */ static void AL_Spatialize(channel_t *ch) { vec3_t origin; /* anything coming from the view entity will always be full volume. no attenuation = no spatialization */ if ((ch->entnum == -1) || (ch->entnum == cl.playernum + 1) || !ch->dist_mult) { qalSource3f(ch->srcnum, AL_POSITION, 0,0,0); qalSourcei(ch->srcnum, AL_SOURCE_RELATIVE, AL_TRUE); return; } if (ch->fixed_origin) { VectorCopy(ch->origin, origin); } else { CL_GetEntitySoundOrigin(ch->entnum, origin); } qalSourcei(ch->srcnum, AL_SOURCE_RELATIVE, AL_FALSE); qalSource3f(ch->srcnum, AL_POSITION, AL_UnpackVector(origin)); }
void AL_PlayChannel(channel_t *ch) { sfxcache_t *sc = ch->sfx->cache; #ifdef _DEBUG if (s_show->integer > 1) Com_Printf("%s: %s\n", __func__, ch->sfx->name); #endif ch->srcnum = s_srcnums[ch - channels]; qalGetError(); qalSourcei(ch->srcnum, AL_BUFFER, sc->bufnum); //qalSourcei(ch->srcnum, AL_LOOPING, sc->loopstart == -1 ? AL_FALSE : AL_TRUE); qalSourcei(ch->srcnum, AL_LOOPING, ch->autosound ? AL_TRUE : AL_FALSE); qalSourcef(ch->srcnum, AL_GAIN, ch->master_vol); qalSourcef(ch->srcnum, AL_REFERENCE_DISTANCE, SOUND_FULLVOLUME); qalSourcef(ch->srcnum, AL_MAX_DISTANCE, 8192); qalSourcef(ch->srcnum, AL_ROLLOFF_FACTOR, ch->dist_mult * (8192 - SOUND_FULLVOLUME)); AL_Spatialize(ch); // play it qalSourcePlay(ch->srcnum); if (qalGetError() != AL_NO_ERROR) { AL_StopChannel(ch); } }
static void AL_InitStreamSource() { 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 ); }
/* * Plays a channel (in the frontends * sense) with OpenAL. */ void AL_PlayChannel(channel_t *ch) { sfxcache_t *sc; float vol; /* Debug */ if (s_show->value > 1) { Com_Printf("%s: %s\n", __func__, ch->sfx->name); } /* Clamp volume */ vol = ch->oal_vol; if (vol > 1.0f) { vol = 1.0f; } sc = ch->sfx->cache; ch->srcnum = s_srcnums[ch - channels]; qalGetError(); qalSourcef(ch->srcnum, AL_REFERENCE_DISTANCE, SOUND_FULLVOLUME); qalSourcef(ch->srcnum, AL_MAX_DISTANCE, 8192); qalSourcef(ch->srcnum, AL_ROLLOFF_FACTOR, ch->dist_mult * (8192 - SOUND_FULLVOLUME)); qalSourcef(ch->srcnum, AL_GAIN, vol); qalSourcei(ch->srcnum, AL_BUFFER, sc->bufnum); qalSourcei(ch->srcnum, AL_LOOPING, ch->autosound ? AL_TRUE : AL_FALSE); if ((ch->entnum == -1) || (ch->entnum == cl.playernum + 1) || !ch->dist_mult) { /* anything coming from the view entity will always * be full volume and at the listeners position */ qalSource3f(ch->srcnum, AL_POSITION, 0.0f, 0.0f, 0.0f); qalSourcei(ch->srcnum, AL_SOURCE_RELATIVE, AL_TRUE); } else { /* all other sources are *not* relative */ qalSourcei(ch->srcnum, AL_SOURCE_RELATIVE, AL_FALSE); } /* Spatialize it */ AL_Spatialize(ch); /* Play it */ qalSourcePlay(ch->srcnum); /* Do not play broken channels */ if (qalGetError() != AL_NO_ERROR) { AL_StopChannel(ch); } }
/* ================= S_AL_SrcKill ================= */ static void S_AL_SrcKill(srcHandle_t src) { // I'm not touching it. Unlock it first. if(srcList[src].isLocked) return; // Stop it if it's playing if(srcList[src].isActive) qalSourceStop(srcList[src].alSource); // Remove the entity association if((srcList[src].isLooping) && (srcList[src].entity != -1)) { int ent = srcList[src].entity; entityList[ent].srcAllocated = qfalse; entityList[ent].srcIndex = -1; entityList[ent].loopAddedThisFrame = qfalse; entityList[ent].startLoopingSound = qfalse; } // Remove the buffer qalSourcei(srcList[src].alSource, AL_BUFFER, 0); srcList[src].sfx = 0; srcList[src].lastUsedTime = 0; srcList[src].priority = 0; srcList[src].entity = -1; srcList[src].channel = -1; srcList[src].isActive = qfalse; srcList[src].isLocked = qfalse; srcList[src].isLooping = qfalse; srcList[src].isTracking = qfalse; srcList[src].local = qfalse; }
/* ================= 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_loop */ static void source_loop( int priority, sfx_t *sfx, int entNum, float fvol, float attenuation ) { src_t *src; qboolean new_source = qfalse; if( !sfx ) return; if( entNum < 0 ) return; // Do we need to start a new sound playing? if( !entlist[entNum].src ) { src = S_AllocSource( priority, entNum, 0 ); if( !src ) return; new_source = qtrue; } else if( entlist[entNum].src->sfx != sfx ) { // Need to restart. Just re-use this channel src = entlist[entNum].src; source_kill( src ); new_source = qtrue; } else { src = entlist[entNum].src; } if( new_source ) { source_setup( src, sfx, priority, entNum, -1, fvol, attenuation ); qalSourcei( src->source, AL_LOOPING, AL_TRUE ); src->isLooping = qtrue; entlist[entNum].src = src; } qalSourcef( src->source, AL_GAIN, src->fvol * s_volume->value ); 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 ); if( new_source ) { if( src->attenuation ) src->isTracking = qtrue; source_spatialize( src ); qalSourcePlay( src->source ); } entlist[entNum].touched = qtrue; }
/* * 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 ); }
void AL_Overwater() { int i; // Apply to all sources for (i = 0; i < s_numchannels; i++) { qalSourcei(s_srcnums[i], AL_DIRECT_FILTER, 0); } }
void AL_StopChannel( channel_t *ch ) { if (s_show->value > 1) Com_Printf("%s: %s\n", __func__, ch->sfx->name ); // stop it qalSourceStop( ch->srcnum ); qalSourcei( ch->srcnum, AL_BUFFER, AL_NONE ); memset (ch, 0, sizeof(*ch)); }
/* * Plays a channel (in the frontends * sense) with OpenAL. */ void AL_PlayChannel(channel_t *ch) { sfxcache_t *sc; float vol; /* Debug */ if (s_show->value > 1) { Com_Printf("%s: %s\n", __func__, ch->sfx->name); } /* Clamp volume */ vol = ch->oal_vol + s_volume->value; if (vol > 1.0f) { vol = 1.0f; } sc = ch->sfx->cache; ch->srcnum = s_srcnums[ch - channels]; qalGetError(); qalSourcef(ch->srcnum, AL_REFERENCE_DISTANCE, SOUND_FULLVOLUME); qalSourcef(ch->srcnum, AL_MAX_DISTANCE, 8192); qalSourcef(ch->srcnum, AL_ROLLOFF_FACTOR, ch->dist_mult * (8192 - SOUND_FULLVOLUME)); qalSourcef(ch->srcnum, AL_GAIN, vol); qalSourcei(ch->srcnum, AL_BUFFER, sc->bufnum); qalSourcei(ch->srcnum, AL_LOOPING, ch->autosound ? AL_TRUE : AL_FALSE); /* Spatialize it */ AL_Spatialize(ch); /* Play it */ qalSourcePlay(ch->srcnum); /* Do not play broken channels */ if (qalGetError() != AL_NO_ERROR) { AL_StopChannel(ch); } }
void AL_StopChannel( channel_t *ch ) { #ifdef _DEBUG if (s_show->integer > 1) Com_Printf("%s: %s\n", __func__, ch->sfx->name ); #endif // stop it qalSourceStop( ch->srcnum ); qalSourcei( ch->srcnum, AL_BUFFER, AL_NONE ); memset (ch, 0, sizeof(*ch)); }
/* ================= 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_Underwater() { int i; if(sound_started != SS_OAL) { return; } // Apply to all sources for (i = 0; i < s_numchannels; i++) { qalSourcei(s_srcnums[i], AL_DIRECT_FILTER, underwaterFilter); } }
static void allocate_channel() { // 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 qalSourcei( source, AL_BUFFER, 0 ); qalSourcei( source, AL_LOOPING, AL_FALSE ); 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 ); }
/* * Disables the underwater effect */ void AL_Overwater() { #if !defined (HT_OS_OSX) q_int32_t i; if ( sound_started != SS_OAL ) { return; } /* Apply to all sources */ for ( i = 0; i < s_numchannels; i++ ) { qalSourcei ( s_srcnums[i], AL_DIRECT_FILTER, 0 ); } #endif }
static void music_source_get( void ) { // Allocate a source at high priority src = S_AllocSource( SRCPRI_STREAM, -2, 0 ); if( !src ) return; S_LockSource( src ); source = S_GetALSource( src ); 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 ); qalSourcef( source, AL_GAIN, s_musicvolume->value ); }
/* ================= S_AL_MusicSourceGet ================= */ static void S_AL_MusicSourceGet( void ) { // Allocate a musicSource at high priority musicSourceHandle = S_AL_SrcAlloc(SRCPRI_STREAM, -2, 0); if(musicSourceHandle == -1) return; // Lock the musicSource so nobody else can use it, and get the raw musicSource S_AL_SrcLock(musicSourceHandle); musicSource = S_AL_SrcGet(musicSourceHandle); // Set some musicSource parameters qalSource3f(musicSource, AL_POSITION, 0.0, 0.0, 0.0); qalSource3f(musicSource, AL_VELOCITY, 0.0, 0.0, 0.0); qalSource3f(musicSource, AL_DIRECTION, 0.0, 0.0, 0.0); qalSourcef (musicSource, AL_ROLLOFF_FACTOR, 0.0 ); qalSourcei (musicSource, AL_SOURCE_RELATIVE, AL_TRUE ); }
/* * S_StartLocalSound */ void S_StartLocalSound( const char *name ) { sfx_t *sfx; src_t *src; src = S_AllocSource( SRCPRI_LOCAL, -1, S_CHANNEL_AUTO ); if( !src ) return; sfx = S_RegisterSound( name ); if( !sfx ) return; source_setup( src, sfx, SRCPRI_LOCAL, -1, S_CHANNEL_AUTO, 1.0, ATTN_NONE ); qalSourcei( src->source, AL_SOURCE_RELATIVE, AL_TRUE ); qalSourcePlay( src->source ); }
void AL_Overwater() { int i; if (sound_started != SS_OAL) { return; } /* Apply to all sources */ for (i = 0; i < s_numchannels; i++) { #if !defined (__APPLE__) qalSourcei(s_srcnums[i], AL_DIRECT_FILTER, 0); #endif } }
/* * Disables the underwater effect */ void AL_Overwater() { int i; if (sound_started != SS_OAL) { return; } if (underwaterFilter == 0) return; /* Apply to all sources */ for (i = 0; i < s_numchannels; i++) { qalSourcei(s_srcnums[i], AL_DIRECT_FILTER, 0); } }
void oal_update_underwater() { int i; float gain_hf; qboolean update = false; ALuint filter; if (underwaterFilter == 0) return; if (s_underwater->modified) { update = true; s_underwater->modified = false; snd_is_underwater_enabled = ((int)s_underwater->value != 0); } if (s_underwater_gain_hf->modified) { update = true; s_underwater_gain_hf->modified = false; } if (!update) return; gain_hf = s_underwater_gain_hf->value; if (gain_hf < AL_LOWPASS_MIN_GAINHF) gain_hf = AL_LOWPASS_MIN_GAINHF; if (gain_hf > AL_LOWPASS_MAX_GAINHF) gain_hf = AL_LOWPASS_MAX_GAINHF; qalFilterf(underwaterFilter, AL_LOWPASS_GAINHF, gain_hf); if (snd_is_underwater_enabled && snd_is_underwater) filter = underwaterFilter; else filter = 0; for (i = 0; i < s_numchannels; ++i) qalSourcei(s_srcnums[i], AL_DIRECT_FILTER, filter); }
/* * source_kill */ static void source_kill( src_t *src ) { if( src->isLocked ) return; if( src->isActive ) qalSourceStop( src->source ); qalSourcei( src->source, AL_BUFFER, AL_NONE ); src->sfx = 0; src->lastUse = 0; src->priority = 0; src->entNum = -1; src->channel = -1; src->fvol = 1; src->isActive = qfalse; src->isLocked = qfalse; src->isLooping = qfalse; src->isTracking = qfalse; }
/* * Enables underwater effect */ void AL_Underwater() { #if !defined (__APPLE__) int i; if (sound_started != SS_OAL) { return; } if (underwaterFilter == 0) return; /* Apply to all sources */ for (i = 0; i < s_numchannels; i++) { qalSourcei(s_srcnums[i], AL_DIRECT_FILTER, underwaterFilter); } #endif }
/* ================= 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); } } }