X-Git-Url: https://de.git.xonotic.org/?a=blobdiff_plain;f=snd_main.c;h=fe18aed74a5791afaec64c7d882190b0aa5261f0;hb=69f3a5b2fdb60c908b57ff0fb14dc1493cc6e0a5;hp=7f01b52e9a9021eaf9d5b423ef2ff7b5f5535cf2;hpb=90a6130a618f72bef104521840169b03d1cc7794;p=xonotic%2Fdarkplaces.git diff --git a/snd_main.c b/snd_main.c index 7f01b52e..fe18aed7 100644 --- a/snd_main.c +++ b/snd_main.c @@ -31,8 +31,6 @@ void S_Play2(void); void S_SoundList(void); void S_Update_(); -void S_ClearBuffer (void); - // ======================================================================= // Internal sound data & structures @@ -53,11 +51,9 @@ matrix4x4_t listener_matrix; vec_t sound_nominal_clip_dist=1000.0; mempool_t *snd_mempool; -// sample PAIRS int soundtime; int paintedtime; - // Linked list of known sfx sfx_t *known_sfx = NULL; @@ -82,14 +78,21 @@ cvar_t snd_show = {0, "snd_show", "0"}; cvar_t _snd_mixahead = {CVAR_SAVE, "_snd_mixahead", "0.1"}; cvar_t snd_swapstereo = {CVAR_SAVE, "snd_swapstereo", "0"}; +// Ambient sounds +sfx_t* ambient_sfxs [2] = { NULL, NULL }; +const char* ambient_names [2] = { "sound/ambience/water1.wav", "sound/ambience/wind2.wav" }; + // ==================================================================== -// User-setable variables +// Functions // ==================================================================== +void S_FreeSfx (sfx_t *sfx, qboolean force); + + void S_SoundInfo_f(void) { - if (!sound_started || !shm) + if (!sound_started) { Con_Print("sound system not started\n"); return; @@ -138,8 +141,6 @@ void S_Startup(void) sound_started = true; Con_DPrintf("Sound sampling rate: %i\n", shm->format.speed); - - S_StopAllSounds (); } void S_Shutdown(void) @@ -217,6 +218,27 @@ void S_Init(void) } +/* +================ +S_Terminate + +Shutdown and free all resources +================ +*/ +void S_Terminate (void) +{ + S_Shutdown (); + OGG_CloseLibrary (); + + // Free all SFXs + while (known_sfx != NULL) + S_FreeSfx (known_sfx, true); + + Cvar_SetValueQuick (&snd_initialized, false); + Mem_FreePool (&snd_mempool); +} + + // ======================================================================= // Load a sound // ======================================================================= @@ -234,7 +256,6 @@ sfx_t *S_FindName (const char *name) if (!snd_initialized.integer) return NULL; - // Add the default sound directory to the path if (strlen (name) >= sizeof (sfx->name)) Host_Error ("S_FindName: sound name too long (%s)", name); @@ -260,10 +281,10 @@ S_FreeSfx ================== */ -void S_FreeSfx (sfx_t *sfx) +void S_FreeSfx (sfx_t *sfx, qboolean force) { - // Never free a locked sfx - if (sfx->locks > 0) + // Never free a locked sfx unless forced + if (!force && (sfx->locks > 0 || (sfx->flags & SFXFLAG_PERMANENTLOCK))) return; Con_DPrintf ("S_FreeSfx: freeing %s\n", sfx->name); @@ -300,19 +321,32 @@ S_ServerSounds void S_ServerSounds (char serversound [][MAX_QPATH], unsigned int numsounds) { sfx_t *sfx; + sfx_t *sfxnext; unsigned int i; // Start the ambient sounds and make them loop - channels[AMBIENT_WATER].sfx = S_PrecacheSound ("sound/ambience/water1.wav", false, true); - channels[AMBIENT_SKY].sfx = S_PrecacheSound ("sound/ambience/wind2.wav", false, true); - for (i = 0; i < NUM_AMBIENTS; i++) - channels[i].flags |= CHANNELFLAG_FORCELOOP; + for (i = 0; i < sizeof (ambient_sfxs) / sizeof (ambient_sfxs[0]); i++) + { + // Precache it if it's not done (request a lock to make sure it will never be freed) + if (ambient_sfxs[i] == NULL) + ambient_sfxs[i] = S_PrecacheSound (ambient_names[i], false, true); + if (ambient_sfxs[i] != NULL) + { + // Add a lock to the SFX while playing. It will be + // removed by S_StopAllSounds at the end of the level + S_LockSfx (ambient_sfxs[i]); + + channels[i].sfx = ambient_sfxs[i]; + channels[i].flags |= CHANNELFLAG_FORCELOOP; + channels[i].master_vol = 0; + } + } // Remove 1 lock from all sfx with the SFXFLAG_SERVERSOUND flag, and remove the flag for (sfx = known_sfx; sfx != NULL; sfx = sfx->next) if (sfx->flags & SFXFLAG_SERVERSOUND) { - sfx->locks--; + S_UnlockSfx (sfx); sfx->flags &= ~SFXFLAG_SERVERSOUND; } @@ -320,24 +354,18 @@ void S_ServerSounds (char serversound [][MAX_QPATH], unsigned int numsounds) for (i = 1; i < numsounds; i++) { sfx = S_FindName (serversound[i]); - if (sfx != NULL && !(sfx->flags & SFXFLAG_SERVERSOUND)) + if (sfx != NULL) { - sfx->locks++; + S_LockSfx (sfx); sfx->flags |= SFXFLAG_SERVERSOUND; } } // Free all unlocked sfx - sfx = known_sfx; - while (sfx != NULL) + for (sfx = known_sfx;sfx;sfx = sfxnext) { - sfx_t* crtsfx; - - // We may lose the "next" pointer after S_FreeSfx - crtsfx = sfx; - sfx = sfx->next; - - S_FreeSfx (crtsfx); + sfxnext = sfx->next; + S_FreeSfx (sfx, false); } } @@ -359,11 +387,8 @@ sfx_t *S_PrecacheSound (const char *name, qboolean complain, qboolean lock) if (sfx == NULL) return NULL; - if (lock && !(sfx->flags & SFXFLAG_PERMANENT)) - { - sfx->flags |= SFXFLAG_PERMANENT; - sfx->locks++; - } + if (lock) + S_LockSfx (sfx); if (!nosound.integer && snd_precache.integer) S_LoadSound(sfx, complain); @@ -371,17 +396,28 @@ sfx_t *S_PrecacheSound (const char *name, qboolean complain, qboolean lock) return sfx; } +/* +================== +S_LockSfx + +Add a lock to a SFX +================== +*/ +void S_LockSfx (sfx_t *sfx) +{ + sfx->locks++; +} + /* ================== S_UnlockSfx -Remove a lock from a SFX and freed it if possible +Remove a lock from a SFX ================== */ void S_UnlockSfx (sfx_t *sfx) { sfx->locks--; - S_FreeSfx (sfx); } @@ -520,7 +556,7 @@ void S_PlaySfxOnChannel (sfx_t *sfx, channel_t *target_chan, unsigned int flags, target_chan->dist_mult = attenuation / sound_nominal_clip_dist; // Lock the SFX during play - sfx->locks++; + S_LockSfx (sfx); } @@ -532,15 +568,17 @@ int S_StartSound (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float f if (!sound_started || !sfx || nosound.integer) return -1; + if (!sfx->fetcher) + { + Con_DPrintf ("S_StartSound: \"%s\" hasn't been precached\n", sfx->name); + return -1; + } // Pick a channel to play on target_chan = SND_PickChannel(entnum, entchannel); if (!target_chan) return -1; - if (!S_LoadSound (sfx, true)) - return -1; // couldn't load the sound's data - S_PlaySfxOnChannel (sfx, target_chan, CHANNELFLAG_NONE, origin, fvol, attenuation, false); target_chan->entnum = entnum; target_chan->entchannel = entchannel; @@ -631,6 +669,10 @@ void S_StopSound(int entnum, int entchannel) void S_StopAllSounds (void) { unsigned int i; + unsigned char *pbuf; + + if (!sound_started) + return; for (i = 0; i < total_channels; i++) S_StopChannel (i); @@ -638,7 +680,23 @@ void S_StopAllSounds (void) total_channels = MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS; // no statics memset(channels, 0, MAX_CHANNELS * sizeof(channel_t)); - S_ClearBuffer (); + // Clear sound buffer + pbuf = S_LockBuffer(); + if (pbuf != NULL) + { + int setsize = shm->samples * shm->format.width; + int clear = (shm->format.width == 1) ? 0x80 : 0; + + // FIXME: is it (still) true? (check with OSS and ALSA) + // on i586/i686 optimized versions of glibc, glibc *wrongly* IMO, + // reads the memory area before writing to it causing a seg fault + // since the memory is PROT_WRITE only and not PROT_READ|PROT_WRITE + //memset(shm->buffer, clear, shm->samples * shm->format.width); + while (setsize--) + *pbuf++ = clear; + + S_UnlockBuffer (); + } } void S_PauseGameSounds (qboolean toggle) @@ -661,37 +719,6 @@ void S_SetChannelVolume (unsigned int ch_ind, float fvol) } -void S_ClearBuffer(void) -{ - int clear; - unsigned char *pbuf; - - if (!sound_started || !shm) - return; - - if (shm->format.width == 1) - clear = 0x80; // 8 bit sound (unsigned) - else - clear = 0; // 16 bit sound (signed) - - pbuf = S_LockBuffer(); - if (pbuf != NULL) - { - int setsize = shm->samples * shm->format.width; - - while (setsize--) - *pbuf++ = clear; - - // on i586/i686 optimized versions of glibc, glibc *wrongly* IMO, - // reads the memory area before writing to it causing a seg fault - // since the memory is PROT_WRITE only and not PROT_READ|PROT_WRITE - //memset(shm->buffer, clear, shm->samples * shm->format.width); - - S_UnlockBuffer (); - } -} - - /* ================= S_StaticSound @@ -701,17 +728,19 @@ void S_StaticSound (sfx_t *sfx, vec3_t origin, float fvol, float attenuation) { channel_t *target_chan; - if (!sfx) + if (!sound_started || !sfx || nosound.integer) return; - - if (total_channels == MAX_CHANNELS) + if (!sfx->fetcher) { - Con_Print("total_channels == MAX_CHANNELS\n"); + Con_DPrintf ("S_StaticSound: \"%s\" hasn't been precached\n", sfx->name); return; } - if (!S_LoadSound (sfx, true)) + if (total_channels == MAX_CHANNELS) + { + Con_Print("S_StaticSound: total_channels == MAX_CHANNELS\n"); return; + } target_chan = &channels[total_channels++]; S_PlaySfxOnChannel (sfx, target_chan, CHANNELFLAG_FORCELOOP, origin, fvol, attenuation, true); @@ -735,10 +764,6 @@ void S_UpdateAmbientSounds (void) channel_t *chan; qbyte ambientlevels[NUM_AMBIENTS]; - // Mute ambient sounds until proven otherwise - for (ambient_channel = 0 ; ambient_channel < NUM_AMBIENTS;ambient_channel++) - channels[ambient_channel].master_vol = 0; - if (ambient_level.value <= 0 || !cl.worldmodel || !cl.worldmodel->brush.AmbientSoundLevelsForPoint) return; @@ -748,7 +773,7 @@ void S_UpdateAmbientSounds (void) for (ambient_channel = 0 ; ambient_channel< NUM_AMBIENTS ; ambient_channel++) { chan = &channels[ambient_channel]; - if (chan->sfx == NULL || (chan->sfx->flags & SFXFLAG_FILEMISSING)) + if (chan->sfx == NULL || chan->sfx->fetcher == NULL) continue; vol = ambient_level.value * ambientlevels[ambient_channel]; @@ -937,19 +962,11 @@ static void S_Play_Common(float fvol, float attenuation) i = 1; while (iflags & SFXFLAG_SERVERSOUND)) - { - sfx->flags |= SFXFLAG_SERVERSOUND; - sfx->locks++; - } - // If we need to get the volume from the command line if (fvol == -1.0f) @@ -958,13 +975,17 @@ static void S_Play_Common(float fvol, float attenuation) i++; } - ch_ind = S_StartSound(-1, 0, sfx, listener_origin, fvol, attenuation); + sfx = S_PrecacheSound (name, true, false); + if (sfx) + { + ch_ind = S_StartSound(-1, 0, sfx, listener_origin, fvol, attenuation); - // Free the sfx if the file didn't exist - if (ch_ind < 0) - S_FreeSfx (sfx); - else - channels[ch_ind].flags |= CHANNELFLAG_LOCALSOUND; + // Free the sfx if the file didn't exist + if (ch_ind < 0) + S_FreeSfx (sfx, false); + else + channels[ch_ind].flags |= CHANNELFLAG_LOCALSOUND; + } } } @@ -996,14 +1017,18 @@ void S_SoundList(void) { size = sfx->mempool->totalsize; total += size; - Con_Printf ("%c%c(%2db, %6s) %8i : %s\n", + Con_Printf ("%c%c%c%c(%2db, %6s) %8i : %s\n", (sfx->loopstart >= 0) ? 'L' : ' ', (sfx->flags & SFXFLAG_STREAMED) ? 'S' : ' ', + (sfx->locks > 0) ? 'K' : ' ', + (sfx->flags & SFXFLAG_PERMANENTLOCK) ? 'P' : ' ', sfx->format.width * 8, (sfx->format.channels == 1) ? "mono" : "stereo", size, sfx->name); } + else + Con_Printf (" ( unknown ) unloaded : %s\n", sfx->name); } Con_Printf("Total resident: %i\n", total); } @@ -1017,13 +1042,16 @@ qboolean S_LocalSound (const char *sound) if (!snd_initialized.integer || nosound.integer) return true; - sfx = S_PrecacheSound (sound, true, true); + sfx = S_PrecacheSound (sound, true, false); if (!sfx) { Con_Printf("S_LocalSound: can't precache %s\n", sound); return false; } + // Local sounds must not be freed + sfx->flags |= SFXFLAG_PERMANENTLOCK; + ch_ind = S_StartSound (cl.viewentity, 0, sfx, vec3_origin, 1, 1); if (ch_ind < 0) return false;