X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=snd_main.c;h=9dc5df8ffe2f52b67b2e7967debf6e678a5c22fa;hp=a7b8d022d3873a1cbfdb17f2e26e199cc17b7cb0;hb=66ba61eab96c3f91e48a2768238c4096efbdb063;hpb=89b6d5e9a9c90426a7defdd8947e83cfd0ae2550 diff --git a/snd_main.c b/snd_main.c index a7b8d022..9dc5df8f 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); @@ -31,8 +51,6 @@ void S_Play2(void); void S_SoundList(void); void S_Update_(); -void S_ClearBuffer (void); - // ======================================================================= // Internal sound data & structures @@ -49,19 +67,16 @@ 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; -// sample PAIRS int soundtime; 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 @@ -91,15 +106,19 @@ const char* ambient_names [2] = { "sound/ambience/water1.wav", "sound/ambience/w // Functions // ==================================================================== +void S_FreeSfx (sfx_t *sfx, qboolean force); + + void S_SoundInfo_f(void) { - if (!sound_started || !shm) + 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); @@ -123,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 = 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 { @@ -133,22 +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_DPrintf("Sound sampling rate: %i\n", shm->format.speed); - - S_StopAllSounds (); + 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) @@ -157,7 +173,6 @@ void S_Shutdown(void) SNDDMA_Shutdown(); shm = NULL; - sound_started = false; sound_spatialized = false; } @@ -221,6 +236,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 // ======================================================================= @@ -238,9 +274,11 @@ 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); + { + Con_Printf ("S_FindName: sound name too long (%s)\n", name); + return NULL; + } // Look for this sound in the list of known sfx for (sfx = known_sfx; sfx != NULL; sfx = sfx->next) @@ -248,9 +286,10 @@ sfx_t *S_FindName (const char *name) return sfx; // Add a sfx_t struct for this sound - sfx = Mem_Alloc (snd_mempool, sizeof (*sfx)); + sfx = (sfx_t *)Mem_Alloc (snd_mempool, sizeof (*sfx)); memset (sfx, 0, sizeof(*sfx)); strlcpy (sfx->name, name, sizeof (sfx->name)); + sfx->memsize = sizeof(*sfx); sfx->next = known_sfx; known_sfx = sfx; @@ -264,10 +303,12 @@ 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 || (sfx->flags & SFXFLAG_PERMANENTLOCK)) + unsigned int i; + + // 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); @@ -286,11 +327,20 @@ void S_FreeSfx (sfx_t *sfx) break; } if (prev_sfx == NULL) - Sys_Error ("S_FreeSfx: Can't find SFX %s in the list!\n", sfx->name); + { + Con_Printf ("S_FreeSfx: Can't find SFX %s in the list!\n", sfx->name); + return; + } } + // Stop all channels using this sfx + for (i = 0; i < total_channels; i++) + if (channels[i].sfx == sfx) + S_StopChannel (i); + // Free it - Mem_FreePool (&sfx->mempool); + if (sfx->fetcher != NULL && sfx->fetcher->free != NULL) + sfx->fetcher->free (sfx); Mem_Free (sfx); } @@ -304,6 +354,7 @@ 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 @@ -344,16 +395,10 @@ void S_ServerSounds (char serversound [][MAX_QPATH], unsigned int numsounds) } // 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); } } @@ -431,22 +476,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) { @@ -472,49 +531,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].state_current.active) + // 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].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); + 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); - } - - // 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); } @@ -552,9 +616,9 @@ int S_StartSound (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float f { channel_t *target_chan, *check; int ch_idx; - size_t skip; + int skip; - if (!sound_started || !sfx || nosound.integer) + if (!shm || !sfx || nosound.integer) return -1; if (!sfx->fetcher) { @@ -562,6 +626,9 @@ int S_StartSound (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float f return -1; } + if (entnum && entnum >= cl_max_entities) + CL_ExpandEntities(entnum); + // Pick a channel to play on target_chan = SND_PickChannel(entnum, entchannel); if (!target_chan) @@ -583,8 +650,8 @@ int S_StartSound (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float f if (check->sfx == sfx && !check->pos) { skip = 0.1 * sfx->format.speed; - if (skip > sfx->total_length) - skip = sfx->total_length; + if (skip > (int)sfx->total_length) + skip = (int)sfx->total_length; if (skip > 0) skip = rand() % skip; target_chan->pos += skip; @@ -610,9 +677,9 @@ void S_StopChannel (unsigned int channel_ind) if (sfx->fetcher != NULL) { - snd_fetcher_end_t fetcher_end = sfx->fetcher->end; - if (fetcher_end != NULL) - fetcher_end (ch); + snd_fetcher_endsb_t fetcher_endsb = sfx->fetcher->endsb; + if (fetcher_endsb != NULL) + fetcher_endsb (ch); } // Remove the lock it holds @@ -657,6 +724,10 @@ void S_StopSound(int entnum, int entchannel) void S_StopAllSounds (void) { unsigned int i; + unsigned char *pbuf; + + if (!shm) + return; for (i = 0; i < total_channels; i++) S_StopChannel (i); @@ -664,7 +735,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 = (unsigned char *)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) @@ -687,37 +774,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 @@ -727,7 +783,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) { @@ -758,24 +814,24 @@ S_UpdateAmbientSounds */ void S_UpdateAmbientSounds (void) { + int i; float vol; int ambient_channel; channel_t *chan; - qbyte ambientlevels[NUM_AMBIENTS]; - - if (ambient_level.value <= 0 || !cl.worldmodel || !cl.worldmodel->brush.AmbientSoundLevelsForPoint) - return; + unsigned char ambientlevels[NUM_AMBIENTS]; - 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++) { 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]; + vol = ambientlevels[ambient_channel]; if (vol < 8) vol = 0; @@ -793,10 +849,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}, + } + } +}; /* ============ @@ -809,13 +939,27 @@ 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], &basematrix, &rotatematrix); + } + // update general area ambient sound sources S_UpdateAmbientSounds (); @@ -827,39 +971,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; } } } @@ -872,8 +1018,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); } @@ -888,7 +1042,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. @@ -921,9 +1075,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 @@ -935,9 +1088,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); @@ -955,7 +1106,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; @@ -981,7 +1132,7 @@ static void S_Play_Common(float fvol, float attenuation) // Free the sfx if the file didn't exist if (ch_ind < 0) - S_FreeSfx (sfx); + S_FreeSfx (sfx, false); else channels[ch_ind].flags |= CHANNELFLAG_LOCALSOUND; } @@ -1014,7 +1165,7 @@ void S_SoundList(void) { if (sfx->fetcher != NULL) { - size = sfx->mempool->totalsize; + size = (int)sfx->memsize; total += size; Con_Printf ("%c%c%c%c(%2db, %6s) %8i : %s\n", (sfx->loopstart >= 0) ? 'L' : ' ', @@ -1051,7 +1202,7 @@ qboolean S_LocalSound (const char *sound) // Local sounds must not be freed sfx->flags |= SFXFLAG_PERMANENTLOCK; - ch_ind = S_StartSound (cl.viewentity, 0, sfx, vec3_origin, 1, 1); + ch_ind = S_StartSound (cl.viewentity, 0, sfx, vec3_origin, 1, 0); if (ch_ind < 0) return false;