X-Git-Url: https://de.git.xonotic.org/?a=blobdiff_plain;f=snd_main.c;h=a6db955deaec6e733070436d5b93af411d8257c2;hb=123d759d4e8793229127f44661afe7c1960fae99;hp=11a24406aa5264ccef15509b6b6a9779772fcd5d;hpb=aa33d8f8642530f7f266d6cde1422f95aa74b2be;p=xonotic%2Fdarkplaces.git diff --git a/snd_main.c b/snd_main.c index 11a24406..a6db955d 100644 --- a/snd_main.c +++ b/snd_main.c @@ -24,6 +24,26 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "snd_main.h" #include "snd_ogg.h" +#if SND_LISTENERS != 8 +#error this data only supports up to 8 channel, update it! +#endif +typedef struct listener_s +{ + float yawangle; + float dotscale; + float dotbias; + float ambientvolume; +} +listener_t; +typedef struct speakerlayout_s +{ + const char *name; + unsigned int channels; + listener_t listeners[SND_LISTENERS]; +} +speakerlayout_t; + +static speakerlayout_t snd_speakerlayout; void S_Play(void); void S_PlayVol(void); @@ -40,14 +60,14 @@ channel_t channels[MAX_CHANNELS]; unsigned int total_channels; int snd_blocked = 0; -cvar_t snd_initialized = { CVAR_READONLY, "snd_initialized", "0"}; -cvar_t snd_streaming = { CVAR_SAVE, "snd_streaming", "1"}; +cvar_t snd_initialized = { CVAR_READONLY, "snd_initialized", "0", "indicates the sound subsystem is active"}; +cvar_t snd_streaming = { CVAR_SAVE, "snd_streaming", "1", "enables keeping compressed ogg sound files compressed, decompressing them only as needed, otherwise they will be decompressed completely at load (may use a lot of memory)"}; volatile dma_t *shm = 0; volatile dma_t sn; vec3_t listener_origin; -matrix4x4_t listener_matrix; +matrix4x4_t listener_matrix[SND_LISTENERS]; vec_t sound_nominal_clip_dist=1000.0; mempool_t *snd_mempool; @@ -57,26 +77,25 @@ int paintedtime; // Linked list of known sfx sfx_t *known_sfx = NULL; -qboolean sound_started = false; qboolean sound_spatialized = false; // Fake dma is a synchronous faking of the DMA progress used for // isolating performance in the renderer. qboolean fakedma = false; -cvar_t bgmvolume = {CVAR_SAVE, "bgmvolume", "1"}; -cvar_t volume = {CVAR_SAVE, "volume", "0.7"}; -cvar_t snd_staticvolume = {CVAR_SAVE, "snd_staticvolume", "1"}; +cvar_t bgmvolume = {CVAR_SAVE, "bgmvolume", "1", "volume of background music (such as CD music or replacement files such as sound/cdtracks/track002.ogg)"}; +cvar_t volume = {CVAR_SAVE, "volume", "0.7", "volume of sound effects"}; +cvar_t snd_staticvolume = {CVAR_SAVE, "snd_staticvolume", "1", "volume of ambient sound effects (such as swampy sounds at the start of e1m2)"}; -cvar_t nosound = {0, "nosound", "0"}; -cvar_t snd_precache = {0, "snd_precache", "1"}; -cvar_t bgmbuffer = {0, "bgmbuffer", "4096"}; -cvar_t ambient_level = {0, "ambient_level", "0.3"}; -cvar_t ambient_fade = {0, "ambient_fade", "100"}; -cvar_t snd_noextraupdate = {0, "snd_noextraupdate", "0"}; -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"}; +cvar_t nosound = {0, "nosound", "0", "disables sound"}; +cvar_t snd_precache = {0, "snd_precache", "1", "loads sounds before they are used"}; +//cvar_t bgmbuffer = {0, "bgmbuffer", "4096", "unused quake cvar"}; +cvar_t ambient_level = {0, "ambient_level", "0.3", "volume of environment noises (water and wind)"}; +cvar_t ambient_fade = {0, "ambient_fade", "100", "rate of volume fading when moving from one environment to another"}; +cvar_t snd_noextraupdate = {0, "snd_noextraupdate", "0", "disables extra sound mixer calls that are meant to reduce the chance of sound breakup at very low framerates"}; +cvar_t snd_show = {0, "snd_show", "0", "shows some statistics about sound mixing"}; +cvar_t _snd_mixahead = {CVAR_SAVE, "_snd_mixahead", "0.1", "how much sound to mix ahead of time"}; +cvar_t snd_swapstereo = {CVAR_SAVE, "snd_swapstereo", "0", "swaps left/right speakers for old ISA soundblaster cards"}; // Ambient sounds sfx_t* ambient_sfxs [2] = { NULL, NULL }; @@ -92,13 +111,14 @@ void S_FreeSfx (sfx_t *sfx, qboolean force); void S_SoundInfo_f(void) { - if (!sound_started) + if (!shm) { Con_Print("sound system not started\n"); return; } - Con_Printf("%5d stereo\n", shm->format.channels - 1); + Con_Printf("%5d speakers\n", shm->format.channels); + Con_Printf("%5d frames\n", shm->sampleframes); Con_Printf("%5d samples\n", shm->samples); Con_Printf("%5d samplepos\n", shm->samplepos); Con_Printf("%5d samplebits\n", shm->format.width * 8); @@ -122,9 +142,10 @@ void S_Startup(void) shm->format.width = 2; shm->format.speed = 22050; shm->format.channels = 2; - shm->samples = 32768; + shm->sampleframes = 16384; + shm->samples = shm->sampleframes * shm->format.channels; shm->samplepos = 0; - shm->buffer = (qbyte *)Mem_Alloc(snd_mempool, shm->format.channels * shm->samples * shm->format.width); + shm->buffer = (unsigned char *)Mem_Alloc(snd_mempool, shm->samples * shm->format.width); } else { @@ -132,21 +153,18 @@ void S_Startup(void) { Con_Print("S_Startup: SNDDMA_Init failed.\n"); shm = NULL; - sound_started = false; sound_spatialized = false; return; } } - sound_started = true; - Con_Printf("Sound format: %dHz, %d bit, %d channels\n", shm->format.speed, shm->format.width * 8, shm->format.channels); } void S_Shutdown(void) { - if (!sound_started) + if (!shm) return; if (fakedma) @@ -155,7 +173,6 @@ void S_Shutdown(void) SNDDMA_Shutdown(); shm = NULL; - sound_started = false; sound_spatialized = false; } @@ -188,19 +205,19 @@ void S_Init(void) if (COM_CheckParm("-simsound")) fakedma = true; - Cmd_AddCommand("play", S_Play); - Cmd_AddCommand("play2", S_Play2); - Cmd_AddCommand("playvol", S_PlayVol); - Cmd_AddCommand("stopsound", S_StopAllSounds); - Cmd_AddCommand("soundlist", S_SoundList); - Cmd_AddCommand("soundinfo", S_SoundInfo_f); - Cmd_AddCommand("snd_restart", S_Restart_f); + Cmd_AddCommand("play", S_Play, "play a sound at your current location (not heard by anyone else)"); + Cmd_AddCommand("play2", S_Play2, "play a sound globally throughout the level (not heard by anyone else)"); + Cmd_AddCommand("playvol", S_PlayVol, "play a sound at the specified volume level at your current location (not heard by anyone else)"); + Cmd_AddCommand("stopsound", S_StopAllSounds, "silence"); + Cmd_AddCommand("soundlist", S_SoundList, "list loaded sounds"); + Cmd_AddCommand("soundinfo", S_SoundInfo_f, "print sound system information (such as channels and speed)"); + Cmd_AddCommand("snd_restart", S_Restart_f, "restart sound system"); Cvar_RegisterVariable(&nosound); Cvar_RegisterVariable(&snd_precache); Cvar_RegisterVariable(&snd_initialized); Cvar_RegisterVariable(&snd_streaming); - Cvar_RegisterVariable(&bgmbuffer); + //Cvar_RegisterVariable(&bgmbuffer); Cvar_RegisterVariable(&ambient_level); Cvar_RegisterVariable(&ambient_fade); Cvar_RegisterVariable(&snd_noextraupdate); @@ -259,7 +276,7 @@ sfx_t *S_FindName (const char *name) if (strlen (name) >= sizeof (sfx->name)) { - Con_Printf ("S_FindName: sound name too long (%s)", name); + Con_Printf ("S_FindName: sound name too long (%s)\n", name); return NULL; } @@ -399,6 +416,9 @@ sfx_t *S_PrecacheSound (const char *name, qboolean complain, qboolean lock) if (!snd_initialized.integer) return NULL; + if (name == NULL || name[0] == 0) + return NULL; + sfx = S_FindName (name); if (sfx == NULL) return NULL; @@ -412,6 +432,16 @@ sfx_t *S_PrecacheSound (const char *name, qboolean complain, qboolean lock) return sfx; } +/* +================== +S_IsSoundPrecached +================== +*/ +qboolean S_IsSoundPrecached (const sfx_t *sfx) +{ + return (sfx != NULL && sfx->fetcher != NULL); +} + /* ================== S_LockSfx @@ -459,22 +489,36 @@ channel_t *SND_PickChannel(int entnum, int entchannel) for (ch_idx=NUM_AMBIENTS ; ch_idx < NUM_AMBIENTS + MAX_DYNAMIC_CHANNELS ; ch_idx++) { ch = &channels[ch_idx]; - if (entchannel != 0 // channel 0 never overrides - && ch->entnum == entnum - && (ch->entchannel == entchannel || entchannel == -1) ) - { // always override sound from same entity - first_to_die = ch_idx; - break; + if (entchannel != 0) + { + // try to override an existing channel + if (ch->entnum == entnum && (ch->entchannel == entchannel || entchannel == -1) ) + { + // always override sound from same entity + first_to_die = ch_idx; + break; + } + } + else + { + if (!ch->sfx) + { + // no sound on this channel + first_to_die = ch_idx; + break; + } } - // don't let monster sounds override player sounds - if (ch->entnum == cl.viewentity && entnum != cl.viewentity && ch->sfx) - continue; + if (ch->sfx) + { + // don't let monster sounds override player sounds + if (ch->entnum == cl.viewentity && entnum != cl.viewentity) + continue; - // don't override looped sounds - if ((ch->flags & CHANNELFLAG_FORCELOOP) != 0 || - (ch->sfx != NULL && ch->sfx->loopstart >= 0)) - continue; + // don't override looped sounds + if ((ch->flags & CHANNELFLAG_FORCELOOP) || ch->sfx->loopstart >= 0) + continue; + } if (ch->end - paintedtime < life_left) { @@ -500,48 +544,54 @@ Spatializes a channel */ void SND_Spatialize(channel_t *ch, qboolean isstatic) { - vec_t dist, scale, pan; + int i; + vec_t dist, mastervol, intensity, vol; vec3_t source_vec; + // update sound origin if we know about the entity + if (ch->entnum > 0 && cls.state == ca_connected && cl.entities[ch->entnum].state_current.active) + { + //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] && 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); + } + + mastervol = ch->master_vol; + // Adjust volume of static sounds + if (isstatic) + mastervol *= snd_staticvolume.value; + // 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; - ch->rightvol = ch->master_vol; + for (i = 0;i < SND_LISTENERS;i++) + { + vol = mastervol * snd_speakerlayout.listeners[i].ambientvolume; + ch->listener_volume[i] = bound(0, vol, 255); + } } else { - // update sound origin if we know about the entity - if (ch->entnum > 0 && cls.state == ca_connected && cl_entities[ch->entnum].render.model) + // calculate stereo seperation and distance attenuation + VectorSubtract(listener_origin, ch->origin, source_vec); + dist = VectorLength(source_vec); + intensity = mastervol * (1.0 - dist * ch->dist_mult); + if (intensity > 0) { - //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].persistent.trail_origin[0], cl_entities[ch->entnum].persistent.trail_origin[1], cl_entities[ch->entnum].persistent.trail_origin[2]); - VectorCopy(cl_entities[ch->entnum].persistent.trail_origin, ch->origin); + for (i = 0;i < SND_LISTENERS;i++) + { + Matrix4x4_Transform(&listener_matrix[i], ch->origin, source_vec); + VectorNormalize(source_vec); + vol = intensity * max(0, source_vec[0] * snd_speakerlayout.listeners[i].dotscale + snd_speakerlayout.listeners[i].dotbias); + ch->listener_volume[i] = bound(0, vol, 255); + } } - - // calculate stereo seperation and distance attenuation - Matrix4x4_Transform(&listener_matrix, ch->origin, source_vec); - dist = VectorNormalizeLength(source_vec); - // distance - scale = ch->master_vol * (1.0 - (dist * ch->dist_mult)); - // panning - pan = scale * source_vec[1]; - // calculate the volumes - ch->leftvol = (int) (scale + pan); - ch->rightvol = (int) (scale - pan); - //Con_Printf("%f %f %f:%f %f %f:%f %f:%d %d\n", ch->origin[0], ch->origin[1], ch->origin[2], source_vec[0], source_vec[1], source_vec[2], scale, pan, ch->leftvol, ch->rightvol); - } - - // Adjust volume of static sounds - if (isstatic) - { - ch->leftvol *= snd_staticvolume.value; - ch->rightvol *= snd_staticvolume.value; + else + for (i = 0;i < SND_LISTENERS;i++) + ch->listener_volume[i] = 0; } - - // clamp volumes - ch->leftvol = bound(0, ch->leftvol, 255); - ch->rightvol = bound(0, ch->rightvol, 255); } @@ -581,7 +631,7 @@ int S_StartSound (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float f int ch_idx; int skip; - if (!sound_started || !sfx || nosound.integer) + if (!shm || !sfx || nosound.integer) return -1; if (!sfx->fetcher) { @@ -589,7 +639,7 @@ int S_StartSound (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float f return -1; } - if (entnum && entnum >= cl_max_entities) + if (entnum && entnum >= cl.max_entities) CL_ExpandEntities(entnum); // Pick a channel to play on @@ -689,7 +739,7 @@ void S_StopAllSounds (void) unsigned int i; unsigned char *pbuf; - if (!sound_started) + if (!shm) return; for (i = 0; i < total_channels; i++) @@ -746,7 +796,7 @@ void S_StaticSound (sfx_t *sfx, vec3_t origin, float fvol, float attenuation) { channel_t *target_chan; - if (!sound_started || !sfx || nosound.integer) + if (!shm || !sfx || nosound.integer) return; if (!sfx->fetcher) { @@ -777,15 +827,15 @@ S_UpdateAmbientSounds */ void S_UpdateAmbientSounds (void) { + int i; float vol; int ambient_channel; channel_t *chan; - qbyte ambientlevels[NUM_AMBIENTS]; + unsigned char ambientlevels[NUM_AMBIENTS]; - if (ambient_level.value <= 0 || !cl.worldmodel || !cl.worldmodel->brush.AmbientSoundLevelsForPoint) - return; - - cl.worldmodel->brush.AmbientSoundLevelsForPoint(cl.worldmodel, listener_origin, ambientlevels, sizeof(ambientlevels)); + memset(ambientlevels, 0, sizeof(ambientlevels)); + if (cl.worldmodel && cl.worldmodel->brush.AmbientSoundLevelsForPoint) + cl.worldmodel->brush.AmbientSoundLevelsForPoint(cl.worldmodel, listener_origin, ambientlevels, sizeof(ambientlevels)); // Calc ambient sound levels for (ambient_channel = 0 ; ambient_channel< NUM_AMBIENTS ; ambient_channel++) @@ -794,7 +844,7 @@ void S_UpdateAmbientSounds (void) if (chan->sfx == NULL || chan->sfx->fetcher == NULL) continue; - vol = ambient_level.value * ambientlevels[ambient_channel]; + vol = ambientlevels[ambient_channel]; if (vol < 8) vol = 0; @@ -812,10 +862,84 @@ void S_UpdateAmbientSounds (void) chan->master_vol = vol; } - chan->leftvol = chan->rightvol = chan->master_vol; + for (i = 0;i < SND_LISTENERS;i++) + chan->listener_volume[i] = (int)(chan->master_vol * ambient_level.value * snd_speakerlayout.listeners[i].ambientvolume); } } +#define SND_SPEAKERLAYOUTS 5 +static speakerlayout_t snd_speakerlayouts[SND_SPEAKERLAYOUTS] = +{ + { + "surround71", 8, + { + {45, 0.2, 0.2, 0.5}, // front left + {315, 0.2, 0.2, 0.5}, // front right + {135, 0.2, 0.2, 0.5}, // rear left + {225, 0.2, 0.2, 0.5}, // rear right + {0, 0.2, 0.2, 0.5}, // front center + {0, 0, 0, 0}, // lfe (we don't have any good lfe sound sources and it would take some filtering work to generate them (and they'd probably still be wrong), so... no lfe) + {90, 0.2, 0.2, 0.5}, // side left + {180, 0.2, 0.2, 0.5}, // side right + } + }, + { + "surround51", 6, + { + {45, 0.2, 0.2, 0.5}, // front left + {315, 0.2, 0.2, 0.5}, // front right + {135, 0.2, 0.2, 0.5}, // rear left + {225, 0.2, 0.2, 0.5}, // rear right + {0, 0.2, 0.2, 0.5}, // front center + {0, 0, 0, 0}, // lfe (we don't have any good lfe sound sources and it would take some filtering work to generate them (and they'd probably still be wrong), so... no lfe) + {0, 0, 0, 0}, + {0, 0, 0, 0}, + } + }, + { + // these systems sometimes have a subwoofer as well, but it has no + // channel of its own + "surround40", 4, + { + {45, 0.3, 0.3, 0.8}, // front left + {315, 0.3, 0.3, 0.8}, // front right + {135, 0.3, 0.3, 0.8}, // rear left + {225, 0.3, 0.3, 0.8}, // rear right + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + } + }, + { + // these systems sometimes have a subwoofer as well, but it has no + // channel of its own + "stereo", 2, + { + {90, 0.5, 0.5, 1}, // side left + {270, 0.5, 0.5, 1}, // side right + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + } + }, + { + "mono", 1, + { + {0, 0, 1, 1}, // center + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + } + } +}; /* ============ @@ -828,13 +952,37 @@ void S_Update(const matrix4x4_t *listenermatrix) { unsigned int i, j, total; channel_t *ch, *combine; + matrix4x4_t basematrix, rotatematrix; - if (!snd_initialized.integer || (snd_blocked > 0)) + if (!snd_initialized.integer || (snd_blocked > 0) || !shm) return; - Matrix4x4_Invert_Simple(&listener_matrix, listenermatrix); + Matrix4x4_Invert_Simple(&basematrix, listenermatrix); Matrix4x4_OriginFromMatrix(listenermatrix, listener_origin); + // select speaker layout + for (i = 0;i < SND_SPEAKERLAYOUTS - 1;i++) + if (snd_speakerlayouts[i].channels == shm->format.channels) + break; + snd_speakerlayout = snd_speakerlayouts[i]; + + // calculate the current matrices + for (j = 0;j < SND_LISTENERS;j++) + { + Matrix4x4_CreateFromQuakeEntity(&rotatematrix, 0, 0, 0, 0, -snd_speakerlayout.listeners[j].yawangle, 0, 1); + Matrix4x4_Concat(&listener_matrix[j], &rotatematrix, &basematrix); + // I think this should now do this: + // 1. create a rotation matrix for rotating by e.g. -90 degrees CCW + // (note: the matrix will rotate the OBJECT, not the VIEWER, so its + // angle has to be taken negative) + // 2. create a transform which first rotates and moves its argument + // into the player's view coordinates (using basematrix which is + // an inverted "absolute" listener matrix), then applies the + // rotation matrix for the ear + // Isn't Matrix4x4_CreateFromQuakeEntity a bit misleading because this + // does not actually refer to an entity? + } + // update general area ambient sound sources S_UpdateAmbientSounds (); @@ -846,39 +994,41 @@ void S_Update(const matrix4x4_t *listenermatrix) { if (!ch->sfx) continue; - SND_Spatialize(ch, i >= MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS); // respatialize channel - if (!ch->leftvol && !ch->rightvol) - continue; + + // respatialize channel + SND_Spatialize(ch, i >= MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS); // try to combine static sounds with a previous channel of the same // sound effect so we don't mix five torches every frame if (i > MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS) { - // see if it can just use the last one - if (combine && combine->sfx == ch->sfx) - { - combine->leftvol += ch->leftvol; - combine->rightvol += ch->rightvol; - ch->leftvol = ch->rightvol = 0; - continue; - } - // search for one - combine = channels+MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS; - for (j=MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS ; jsfx == ch->sfx) + // no need to merge silent channels + for (j = 0;j < SND_LISTENERS;j++) + if (ch->listener_volume[j]) break; - - if (j == total_channels) + if (j == SND_LISTENERS) + continue; + // if the last combine chosen isn't suitable, find a new one + if (!(combine && combine != ch && combine->sfx == ch->sfx)) + { + // search for one combine = NULL; - else + for (j = MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS;j < i;j++) + { + if (channels[j].sfx == ch->sfx) + { + combine = channels + j; + break; + } + } + } + if (combine && combine != ch && combine->sfx == ch->sfx) { - if (combine != ch) + for (j = 0;j < SND_LISTENERS;j++) { - combine->leftvol += ch->leftvol; - combine->rightvol += ch->rightvol; - ch->leftvol = ch->rightvol = 0; + combine->listener_volume[j] += ch->listener_volume[j]; + ch->listener_volume[j] = 0; } - continue; } } } @@ -891,8 +1041,16 @@ void S_Update(const matrix4x4_t *listenermatrix) total = 0; ch = channels; for (i=0 ; isfx && (ch->leftvol || ch->rightvol) ) - total++; + { + if (ch->sfx) + { + for (j = 0;j < SND_LISTENERS;j++) + if (ch->listener_volume[j]) + break; + if (j < SND_LISTENERS) + total++; + } + } Con_Printf("----(%u)----\n", total); } @@ -907,7 +1065,7 @@ void GetSoundtime(void) static int oldsamplepos; int fullsamples; - fullsamples = shm->samples / shm->format.channels; + fullsamples = shm->sampleframes; // it is possible to miscount buffers if it has wrapped twice between // calls to S_Update. Oh well. @@ -940,9 +1098,8 @@ void S_ExtraUpdate (void) void S_Update_(void) { unsigned endtime; - int samps; - if (!sound_started || (snd_blocked > 0)) + if (!shm || (snd_blocked > 0)) return; // Updates DMA time @@ -954,9 +1111,7 @@ void S_Update_(void) // mix ahead of current position endtime = soundtime + _snd_mixahead.value * shm->format.speed; - samps = shm->samples >> (shm->format.channels - 1); - if (endtime > (unsigned int)(soundtime + samps)) - endtime = soundtime + samps; + endtime = min(endtime, (unsigned int)(soundtime + shm->sampleframes)); S_PaintChannels (endtime); @@ -974,7 +1129,7 @@ console functions static void S_Play_Common(float fvol, float attenuation) { int i, ch_ind; - char name[256]; + char name[MAX_QPATH]; sfx_t *sfx; i = 1;