X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=snd_dma.c;h=cb9e11cf6bf08ef8084b27baf2bc7b1fac28ed38;hp=152a2147ba69f8baa0f78cdee28f6029ce728cc5;hb=a5aa71031ee91b1a82396a56bcaeb151bdfa57d5;hpb=2903081de6c5335d7b64bc5e83db6b9d9aaf2f21 diff --git a/snd_dma.c b/snd_dma.c index 152a2147..cb9e11cf 100644 --- a/snd_dma.c +++ b/snd_dma.c @@ -22,9 +22,16 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "quakedef.h" #ifdef _WIN32 -#include "winquake.h" +#include +#include +extern DWORD gSndBufSize; +extern LPDIRECTSOUND pDS; +extern LPDIRECTSOUNDBUFFER pDSBuf; #endif +#include "ogg.h" + + void S_Play(void); void S_PlayVol(void); void S_Play2(void); @@ -42,16 +49,16 @@ int total_channels; int snd_blocked = 0; static qboolean snd_ambient = 1; -qboolean snd_initialized = false; +cvar_t snd_initialized = { CVAR_READONLY, "snd_initialized", "0"}; // pointer should go away volatile dma_t *shm = 0; volatile dma_t sn; -vec3_t listener_origin; -vec3_t listener_forward; -vec3_t listener_right; -vec3_t listener_up; +vec3_t listener_vieworigin; +vec3_t listener_viewforward; +vec3_t listener_viewleft; +vec3_t listener_viewup; vec_t sound_nominal_clip_dist=1000.0; mempool_t *snd_mempool; @@ -115,7 +122,7 @@ void S_SoundInfo_f(void) { if (!sound_started || !shm) { - Con_Printf ("sound system not started\n"); + Con_Print("sound system not started\n"); return; } @@ -123,38 +130,84 @@ void S_SoundInfo_f(void) Con_Printf("%5d samples\n", shm->samples); Con_Printf("%5d samplepos\n", shm->samplepos); Con_Printf("%5d samplebits\n", shm->samplebits); - Con_Printf("%5d submission_chunk\n", shm->submission_chunk); Con_Printf("%5d speed\n", shm->speed); Con_Printf("0x%x dma buffer\n", shm->buffer); Con_Printf("%5d total_channels\n", total_channels); } +void S_UnloadSounds(void) +{ + int i; + for (i = 0;i < num_sfx;i++) + S_UnloadSound(known_sfx + i); +} -/* -================ -S_Startup -================ -*/ -void S_Startup (void) +void S_LoadSounds(void) { - int rc; + int i; + for (i = 0;i < num_sfx;i++) + S_LoadSound(known_sfx + i, false); +} - if (!snd_initialized) +void S_Startup(void) +{ + if (!snd_initialized.integer) return; - if (!fakedma) - { - rc = SNDDMA_Init(); + shm = &sn; + memset((void *)shm, 0, sizeof(*shm)); + +// create a piece of DMA memory - if (!rc) + if (fakedma) + { + shm->samplebits = 16; + shm->speed = 22050; + shm->channels = 2; + shm->samples = 32768; + shm->samplepos = 0; + shm->buffer = Mem_Alloc(snd_mempool, shm->channels * shm->samples * (shm->samplebits / 8)); + } + else + { + if (!SNDDMA_Init()) { - Con_Printf("S_Startup: SNDDMA_Init failed.\n"); + Con_Print("S_Startup: SNDDMA_Init failed.\n"); sound_started = 0; + shm = NULL; return; } } sound_started = 1; + + Con_DPrintf("Sound sampling rate: %i\n", shm->speed); + + //S_LoadSounds(); + + S_StopAllSounds(true); +} + +void S_Shutdown(void) +{ + if (!sound_started) + return; + + //S_UnloadSounds(); + + if (fakedma) + Mem_Free(shm->buffer); + else + SNDDMA_Shutdown(); + + shm = NULL; + sound_started = 0; +} + +void S_Restart_f(void) +{ + S_Shutdown(); + S_Startup(); } /* @@ -162,9 +215,9 @@ void S_Startup (void) S_Init ================ */ -void S_Init (void) +void S_Init(void) { - Con_DPrintf("\nSound Initialization\n"); + Con_DPrint("\nSound Initialization\n"); S_RawSamples_ClearQueue(); @@ -186,9 +239,11 @@ void S_Init (void) Cmd_AddCommand("stopsound", S_StopAllSoundsC); Cmd_AddCommand("soundlist", S_SoundList); Cmd_AddCommand("soundinfo", S_SoundInfo_f); + Cmd_AddCommand("snd_restart", S_Restart_f); Cvar_RegisterVariable(&nosound); Cvar_RegisterVariable(&snd_precache); + Cvar_RegisterVariable(&snd_initialized); Cvar_RegisterVariable(&bgmbuffer); Cvar_RegisterVariable(&ambient_level); Cvar_RegisterVariable(&ambient_fade); @@ -197,69 +252,52 @@ void S_Init (void) Cvar_RegisterVariable(&_snd_mixahead); Cvar_RegisterVariable(&snd_swapstereo); // LordHavoc: for people with backwards sound wiring - snd_initialized = true; + Cvar_SetValueQuick(&snd_initialized, true); known_sfx = Mem_Alloc(snd_mempool, MAX_SFX*sizeof(sfx_t)); num_sfx = 0; - S_Startup (); - SND_InitScaletable (); -// create a piece of DMA memory - - if (fakedma) - { - shm = (void *) Mem_Alloc(snd_mempool, sizeof(*shm)); - shm->splitbuffer = 0; - shm->samplebits = 16; - shm->speed = 22050; - shm->channels = 2; - shm->samples = 32768; - shm->samplepos = 0; - shm->soundalive = true; - shm->gamealive = true; - shm->submission_chunk = 1; - shm->buffer = Mem_Alloc(snd_mempool, shm->channels * shm->samples * (shm->samplebits / 8)); - } - - if (!sound_started) - return; - - Con_DPrintf ("Sound sampling rate: %i\n", shm->speed); - - // provides a tick sound until washed clean - ambient_sfx[AMBIENT_WATER] = S_PrecacheSound ("ambience/water1.wav", false); ambient_sfx[AMBIENT_SKY] = S_PrecacheSound ("ambience/wind2.wav", false); - S_StopAllSounds (true); + total_channels = MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS; // no statics + memset(channels, 0, MAX_CHANNELS * sizeof(channel_t)); + + OGG_OpenLibrary (); } // ======================================================================= -// Shutdown sound engine +// Load a sound // ======================================================================= -void S_Shutdown(void) +/* +========= +S_GetCached + +========= +*/ +sfx_t *S_GetCached (const char *name) { - if (!sound_started) - return; + int i; - if (shm) - shm->gamealive = 0; + if (!snd_initialized.integer) + return NULL; - shm = 0; - sound_started = 0; + if (!name) + Host_Error("S_IsCached: NULL\n"); - if (!fakedma) - SNDDMA_Shutdown(); -} + if (strlen(name) >= MAX_QPATH) + Host_Error("Sound name too long: %s", name); + for(i = 0;i < num_sfx;i++) + if(!strcmp(known_sfx[i].name, name)) + return &known_sfx[i]; -// ======================================================================= -// Load a sound -// ======================================================================= + return NULL; +} /* ================== @@ -272,11 +310,14 @@ sfx_t *S_FindName (char *name) int i; sfx_t *sfx; + if (!snd_initialized.integer) + return NULL; + if (!name) - Host_Error ("S_FindName: NULL\n"); + Host_Error("S_FindName: NULL\n"); if (strlen(name) >= MAX_QPATH) - Host_Error ("Sound name too long: %s", name); + Host_Error("Sound name too long: %s", name); // see if already loaded for (i = 0;i < num_sfx;i++) @@ -284,14 +325,11 @@ sfx_t *S_FindName (char *name) return &known_sfx[i]; if (num_sfx == MAX_SFX) - Sys_Error ("S_FindName: out of sfx_t"); + Sys_Error("S_FindName: out of sfx_t"); - sfx = &known_sfx[i]; + sfx = &known_sfx[num_sfx++]; memset(sfx, 0, sizeof(*sfx)); - strcpy (sfx->name, name); - - num_sfx++; - + strncpy(sfx->name, name, sizeof(sfx->name)); return sfx; } @@ -304,14 +342,53 @@ S_TouchSound */ void S_TouchSound (char *name) { - sfx_t *sfx; - - if (!sound_started) - return; + sfx_t *sfx; sfx = S_FindName (name); + + // Set the "used" flag for this sound + if (sfx != NULL) + sfx->flags |= SFXFLAG_USED; +} + + +/* +================== +S_ClearUsed + +Reset the "used" flag of all precached sounds +================== +*/ +void S_ClearUsed (void) +{ + int i; + + for (i = 0; i < num_sfx; i++) + known_sfx[i].flags &= ~SFXFLAG_USED; +} + + +/* +================== +S_PurgeUnused + +Free all precached sounds without the "used" flag +================== +*/ +void S_PurgeUnused (void) +{ + int i; + sfx_t *sfx; + + for (i = 0; i < num_sfx; i++) + { + sfx = &known_sfx[i]; + if (! (sfx->flags & SFXFLAG_USED)) + S_UnloadSound (sfx); + } } + /* ================== S_PrecacheSound @@ -322,14 +399,13 @@ sfx_t *S_PrecacheSound (char *name, int complain) { sfx_t *sfx; - if (!sound_started || nosound.integer) + if (!snd_initialized.integer) return NULL; - sfx = S_FindName (name); + sfx = S_FindName(name); -// cache it in - if (snd_precache.integer) - S_LoadSound (sfx, complain); + if (!nosound.integer && snd_precache.integer) + S_LoadSound(sfx, complain); return sfx; } @@ -388,14 +464,11 @@ SND_Spatialize */ void SND_Spatialize(channel_t *ch, int isstatic) { - vec_t dot; - vec_t dist; - vec_t lscale, rscale, scale; + vec_t dist, scale, pan; vec3_t source_vec; - sfx_t *snd; -// anything coming from the view entity will always be full volume -// LordHavoc: make sounds with ATTN_NONE have no spatialization + // anything coming from the view entity will always be full volume + // LordHavoc: make sounds with ATTN_NONE have no spatialization if (ch->entnum == cl.viewentity || ch->dist_mult == 0) { ch->leftvol = ch->master_vol; @@ -403,42 +476,37 @@ void SND_Spatialize(channel_t *ch, int isstatic) } else { - // calculate stereo seperation and distance attenuation - snd = ch->sfx; - VectorSubtract(ch->origin, listener_origin, source_vec); - - dist = VectorNormalizeLength(source_vec) * ch->dist_mult; - - dot = DotProduct(listener_right, source_vec); - - if (shm->channels == 1) - { - rscale = 1.0; - lscale = 1.0; - } - else + // update sound origin if we know about the entity + if (ch->entnum > 0 && cls.state == ca_connected && cl_entities[ch->entnum].state_current.active) { - rscale = 1.0 + dot; - lscale = 1.0 - dot; + //Con_Printf("-- entnum %i origin %f %f %f neworigin %f %f %f\n", ch->entnum, ch->origin[0], ch->origin[1], ch->origin[2], cl_entities[ch->entnum].state_current.origin[0], cl_entities[ch->entnum].state_current.origin[1], cl_entities[ch->entnum].state_current.origin[2]); + VectorCopy(cl_entities[ch->entnum].state_current.origin, ch->origin); + if (cl_entities[ch->entnum].state_current.modelindex && cl.model_precache[cl_entities[ch->entnum].state_current.modelindex]->soundfromcenter) + VectorMAMAM(1.0f, ch->origin, 0.5f, cl.model_precache[cl_entities[ch->entnum].state_current.modelindex]->normalmins, 0.5f, cl.model_precache[cl_entities[ch->entnum].state_current.modelindex]->normalmaxs, ch->origin); } - // add in distance effect - scale = (1.0 - dist) * rscale; - ch->rightvol = (int) (ch->master_vol * scale); - if (ch->rightvol < 0) - ch->rightvol = 0; - - scale = (1.0 - dist) * lscale; - ch->leftvol = (int) (ch->master_vol * scale); - if (ch->leftvol < 0) - ch->leftvol = 0; + // calculate stereo seperation and distance attenuation + VectorSubtract(ch->origin, listener_vieworigin, source_vec); + dist = VectorNormalizeLength(source_vec); + // distance + scale = ch->master_vol * (1.0 - (dist * ch->dist_mult)); + // panning + pan = scale * DotProduct(listener_viewleft, source_vec); + // calculate the volumes + ch->leftvol = (int) (scale + pan); + ch->rightvol = (int) (scale - pan); } + // LordHavoc: allow adjusting volume of static sounds if (isstatic) { ch->leftvol *= snd_staticvolume.value; ch->rightvol *= snd_staticvolume.value; } + + // clamp volumes + ch->leftvol = bound(0, ch->leftvol, 255); + ch->rightvol = bound(0, ch->rightvol, 255); } @@ -454,13 +522,7 @@ void S_StartSound(int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float f int ch_idx; int skip; - if (!sound_started) - return; - - if (!sfx) - return; - - if (nosound.integer) + if (!sound_started || !sfx || !sfx->sfxcache || nosound.integer) return; vol = fvol*255; @@ -479,8 +541,9 @@ void S_StartSound(int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float f target_chan->entchannel = entchannel; SND_Spatialize(target_chan, false); - if (!target_chan->leftvol && !target_chan->rightvol) - return; // not audible at all + // LordHavoc: spawn the sound anyway because the player might teleport to it + //if (!target_chan->leftvol && !target_chan->rightvol) + // return; // not audible at all // new channel sc = S_LoadSound (sfx, true); @@ -504,7 +567,7 @@ void S_StartSound(int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float f if (check->sfx == sfx && !check->pos) { // LordHavoc: fixed skip calculations - skip = 0.1 * shm->speed; + skip = 0.1 * sc->speed; if (skip > sc->length) skip = sc->length; if (skip > 0) @@ -513,7 +576,6 @@ void S_StartSound(int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float f target_chan->end -= skip; break; } - } } @@ -535,37 +597,23 @@ void S_StopSound(int entnum, int entchannel) void S_StopAllSounds(qboolean clear) { - int i; - - if (!sound_started) - return; - total_channels = MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS; // no statics - - for (i=0 ; ibuffer && !pDSBuf)) -#else - if (!sound_started || !shm || !shm->buffer) -#endif + if (!sound_started || !shm) return; if (shm->samplebits == 8) @@ -583,18 +631,18 @@ void S_ClearBuffer (void) reps = 0; - while ((hresult = pDSBuf->lpVtbl->Lock(pDSBuf, 0, gSndBufSize, &pData, &dwSize, NULL, NULL, 0)) != DS_OK) + while ((hresult = pDSBuf->lpVtbl->Lock(pDSBuf, 0, gSndBufSize, (LPVOID*)&pData, &dwSize, NULL, NULL, 0)) != DS_OK) { if (hresult != DSERR_BUFFERLOST) { - Con_Printf ("S_ClearBuffer: DS::Lock Sound Buffer Failed\n"); + Con_Print("S_ClearBuffer: DS::Lock Sound Buffer Failed\n"); S_Shutdown (); return; } if (++reps > 10000) { - Con_Printf ("S_ClearBuffer: DS: couldn't restore buffer\n"); + Con_Print("S_ClearBuffer: DS: couldn't restore buffer\n"); S_Shutdown (); return; } @@ -607,12 +655,13 @@ void S_ClearBuffer (void) } else #endif + if (shm->buffer) { int setsize = shm->samples * shm->samplebits / 8; char *buf = shm->buffer; while (setsize--) - *buf++ = 0; + *buf++ = clear; // on i586/i686 optimized versions of glibc, glibc *wrongly* IMO, // reads the memory area before writing to it causing a seg fault @@ -637,23 +686,20 @@ void S_StaticSound (sfx_t *sfx, vec3_t origin, float vol, float attenuation) if (total_channels == MAX_CHANNELS) { - Con_Printf ("total_channels == MAX_CHANNELS\n"); + Con_Print("total_channels == MAX_CHANNELS\n"); return; } - ss = &channels[total_channels]; - total_channels++; - sc = S_LoadSound (sfx, true); if (!sc) return; if (sc->loopstart == -1) - { - Con_Printf ("Sound %s not looped\n", sfx->name); - return; - } + Con_DPrintf("Quake compatibility warning: Static sound \"%s\" is not looped\n", sfx->name); + ss = &channels[total_channels++]; + memset(ss, 0, sizeof(*ss)); + ss->forceloop = true; ss->sfx = sfx; VectorCopy (origin, ss->origin); ss->master_vol = vol; @@ -673,31 +719,31 @@ S_UpdateAmbientSounds */ void S_UpdateAmbientSounds (void) { - mleaf_t *l; float vol; int ambient_channel; channel_t *chan; + qbyte ambientlevels[NUM_AMBIENTS]; // LordHavoc: kill ambient sounds until proven otherwise for (ambient_channel = 0 ; ambient_channel < NUM_AMBIENTS;ambient_channel++) channels[ambient_channel].sfx = NULL; - if (!snd_ambient || !cl.worldmodel || ambient_level.value <= 0) + if (!snd_ambient || ambient_level.value <= 0 || !cl.worldmodel || !cl.worldmodel->brush.AmbientSoundLevelsForPoint) return; - l = cl.worldmodel->PointInLeaf(cl.worldmodel, listener_origin); - if (!l) - return; + cl.worldmodel->brush.AmbientSoundLevelsForPoint(cl.worldmodel, listener_vieworigin, ambientlevels, sizeof(ambientlevels)); // calc ambient sound levels for (ambient_channel = 0 ; ambient_channel< NUM_AMBIENTS ; ambient_channel++) { - if (ambient_sfx[ambient_channel] && ambient_sfx[ambient_channel]->silentlymissing) + if (ambient_sfx[ambient_channel] && + (ambient_sfx[ambient_channel]->flags & SFXFLAG_SILENTLYMISSING)) continue; chan = &channels[ambient_channel]; + chan->forceloop = true; chan->sfx = ambient_sfx[ambient_channel]; - vol = ambient_level.value * l->ambient_sound_level[ambient_channel]; + vol = ambient_level.value * ambientlevels[ambient_channel]; if (vol < 8) vol = 0; @@ -727,20 +773,20 @@ S_Update Called once each time through the main loop ============ */ -void S_Update(vec3_t origin, vec3_t forward, vec3_t right, vec3_t up) +void S_Update(vec3_t origin, vec3_t forward, vec3_t left, vec3_t up) { int i, j; int total; channel_t *ch; channel_t *combine; - if (!sound_started || (snd_blocked > 0)) + if (!snd_initialized.integer || (snd_blocked > 0)) return; - VectorCopy(origin, listener_origin); - VectorCopy(forward, listener_forward); - VectorCopy(right, listener_right); - VectorCopy(up, listener_up); + VectorCopy(origin, listener_vieworigin); + VectorCopy(forward, listener_viewforward); + VectorCopy(left, listener_viewleft); + VectorCopy(up, listener_viewup); // update general area ambient sound sources S_UpdateAmbientSounds (); @@ -777,9 +823,7 @@ void S_Update(vec3_t origin, vec3_t forward, vec3_t right, vec3_t up) break; if (j == total_channels) - { combine = NULL; - } else { if (combine != ch) @@ -804,7 +848,7 @@ void S_Update(vec3_t origin, vec3_t forward, vec3_t right, vec3_t up) if (ch->sfx && (ch->leftvol || ch->rightvol) ) total++; - Con_Printf ("----(%i)----\n", total); + Con_Printf("----(%i)----\n", total); } // mix some sound @@ -822,12 +866,8 @@ void GetSoundtime(void) // it is possible to miscount buffers if it has wrapped twice between // calls to S_Update. Oh well. -#ifdef __sun__ - soundtime = SNDDMA_GetSamples(); -#else samplepos = SNDDMA_GetDMAPos(); - if (samplepos < oldsamplepos) { buffers++; // buffer wrapped @@ -842,7 +882,6 @@ void GetSoundtime(void) oldsamplepos = samplepos; soundtime = buffers*fullsamples + samplepos/shm->channels; -#endif } void IN_Accumulate (void); @@ -887,8 +926,8 @@ void S_Update_(void) if (pDSBuf) { - if (pDSBuf->lpVtbl->GetStatus (pDSBuf, &dwStatus) != DD_OK) - Con_Printf ("Couldn't get sound buffer status\n"); + if (pDSBuf->lpVtbl->GetStatus (pDSBuf, &dwStatus) != DS_OK) + Con_Print("Couldn't get sound buffer status\n"); if (dwStatus & DSBSTATUS_BUFFERLOST) pDSBuf->lpVtbl->Restore (pDSBuf); @@ -912,9 +951,8 @@ console functions =============================================================================== */ -void S_Play(void) +static void S_Play_Common(float fvol, float attenuation) { - static int hash=345; int i; char name[256]; sfx_t *sfx; @@ -923,64 +961,37 @@ void S_Play(void) while (isfxcache; - if (!sc) - continue; - size = sc->length*sc->width*(sc->stereo+1); - total += size; - if (sc->loopstart >= 0) - Con_Printf ("L"); - else - Con_Printf (" "); - Con_Printf("(%2db) %6i : %s\n",sc->width*8, size, sfx->name); + if (sc) + { + size = sc->length*sc->width*(sc->stereo+1); + total += size; + Con_Printf("%c(%2db) %6i : %s\n", sc->loopstart >= 0 ? 'L' : ' ',sc->width*8, size, sfx->name); + } } - Con_Printf ("Total resident: %i\n", total); + Con_Printf("Total resident: %i\n", total); } @@ -1012,36 +1020,19 @@ void S_LocalSound (char *sound) { sfx_t *sfx; - if (nosound.integer) - return; - if (!sound_started) + if (!snd_initialized.integer || nosound.integer) return; sfx = S_PrecacheSound (sound, true); if (!sfx) { - Con_Printf ("S_LocalSound: can't precache %s\n", sound); + Con_Printf("S_LocalSound: can't precache %s\n", sound); return; } S_StartSound (cl.viewentity, -1, sfx, vec3_origin, 1, 1); } -void S_ClearPrecache (void) -{ -} - - -void S_BeginPrecaching (void) -{ -} - - -void S_EndPrecaching (void) -{ -} - - #define RAWSAMPLESBUFFER 32768 short s_rawsamplesbuffer[RAWSAMPLESBUFFER * 2]; int s_rawsamplesbuffer_start; @@ -1111,7 +1102,7 @@ void S_RawSamples_ClearQueue(void) int S_RawSamples_QueueWantsMore(void) { - if (s_rawsamplesbuffer_count < min(shm->speed >> 1, RAWSAMPLESBUFFER >> 1)) + if (shm != NULL && s_rawsamplesbuffer_count < min(shm->speed >> 1, RAWSAMPLESBUFFER >> 1)) return RAWSAMPLESBUFFER - s_rawsamplesbuffer_count; else return 0; @@ -1151,3 +1142,4 @@ int S_RawSamples_SampleRate(void) { return shm != NULL ? shm->speed : 0; } +