X-Git-Url: https://de.git.xonotic.org/?a=blobdiff_plain;f=snd_dma.c;h=6be221abc0b89178702adcba44e22485de8a3abe;hb=8ddb66ffbe37b9fabd2cb30f36b7435deb3e9965;hp=3817ea4cd52650363f3f89ea7cb43e7a5bc3a237;hpb=b47b74389ee3f609d12f738f6038842fbd0d409a;p=xonotic%2Fdarkplaces.git diff --git a/snd_dma.c b/snd_dma.c index 3817ea4c..6be221ab 100644 --- a/snd_dma.c +++ b/snd_dma.c @@ -8,7 +8,7 @@ of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. @@ -27,6 +27,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. void S_Play(void); void S_PlayVol(void); +void S_Play2(void); void S_SoundList(void); void S_Update_(); void S_StopAllSounds(qboolean clear); @@ -36,42 +37,44 @@ void S_StopAllSoundsC(void); // Internal sound data & structures // ======================================================================= -channel_t channels[MAX_CHANNELS]; -int total_channels; +channel_t channels[MAX_CHANNELS]; +int total_channels; -int snd_blocked = 0; -static qboolean snd_ambient = 1; -qboolean snd_initialized = false; +int snd_blocked = 0; +static qboolean snd_ambient = 1; +qboolean snd_initialized = false; // pointer should go away -volatile dma_t *shm = 0; +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; -vec_t sound_nominal_clip_dist=1000.0; +vec3_t listener_origin; +vec3_t listener_forward; +vec3_t listener_right; +vec3_t listener_up; +vec_t sound_nominal_clip_dist=1000.0; +mempool_t *snd_mempool; -int soundtime; // sample PAIRS -int paintedtime; // sample PAIRS +// sample PAIRS +int soundtime; +int paintedtime; //LordHavoc: increased the client sound limit from 512 to 4096 for the Nehahra movie -#define MAX_SFX 4096 -sfx_t *known_sfx; // hunk allocated [MAX_SFX] -int num_sfx; +#define MAX_SFX 4096 +sfx_t *known_sfx; // allocated [MAX_SFX] +int num_sfx; -sfx_t *ambient_sfx[NUM_AMBIENTS]; +sfx_t *ambient_sfx[NUM_AMBIENTS]; int sound_started = 0; 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 nosound = {0, "nosound", "0"}; -cvar_t precache = {0, "precache", "1"}; -//cvar_t loadas8bit = {0, "loadas8bit", "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"}; @@ -115,14 +118,14 @@ void S_SoundInfo_f(void) Con_Printf ("sound system not started\n"); return; } - - Con_Printf("%5d stereo\n", shm->channels - 1); - 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 stereo\n", shm->channels - 1); + 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); } @@ -132,10 +135,9 @@ void S_SoundInfo_f(void) S_Startup ================ */ - void S_Startup (void) { - int rc; + int rc; if (!snd_initialized) return; @@ -155,11 +157,6 @@ void S_Startup (void) sound_started = 1; } - -void S_Play2(void); - -mempool_t *snd_mempool; - /* ================ S_Init @@ -167,12 +164,15 @@ S_Init */ void S_Init (void) { - Con_Printf("\nSound Initialization\n"); + Con_DPrintf("\nSound Initialization\n"); + + S_RawSamples_ClearQueue(); Cvar_RegisterVariable(&volume); Cvar_RegisterVariable(&bgmvolume); + Cvar_RegisterVariable(&snd_staticvolume); - if (COM_CheckParm("-nosound")) + if (COM_CheckParm("-nosound") || COM_CheckParm("-safe")) return; snd_mempool = Mem_AllocPool("sound"); @@ -188,8 +188,7 @@ void S_Init (void) Cmd_AddCommand("soundinfo", S_SoundInfo_f); Cvar_RegisterVariable(&nosound); - Cvar_RegisterVariable(&precache); -// Cvar_RegisterVariable(&loadas8bit); + Cvar_RegisterVariable(&snd_precache); Cvar_RegisterVariable(&bgmbuffer); Cvar_RegisterVariable(&ambient_level); Cvar_RegisterVariable(&ambient_fade); @@ -198,16 +197,6 @@ void S_Init (void) Cvar_RegisterVariable(&_snd_mixahead); Cvar_RegisterVariable(&snd_swapstereo); // LordHavoc: for people with backwards sound wiring - /* - if (host_parms.memsize < 0x800000) - { - Cvar_Set ("loadas8bit", "1"); - Con_Printf ("loading all sounds as 8bit\n"); - } - */ - - - snd_initialized = true; known_sfx = Mem_Alloc(snd_mempool, MAX_SFX*sizeof(sfx_t)); @@ -237,15 +226,12 @@ void S_Init (void) if (!sound_started) return; - Con_Printf ("Sound sampling rate: %i\n", shm->speed); + Con_DPrintf ("Sound sampling rate: %i\n", shm->speed); // provides a tick sound until washed clean -// if (shm->buffer) -// shm->buffer[4] = shm->buffer[5] = 0x7f; // force a pop for debugging - - ambient_sfx[AMBIENT_WATER] = S_PrecacheSound ("ambience/water1.wav"); - ambient_sfx[AMBIENT_SKY] = S_PrecacheSound ("ambience/wind2.wav"); + ambient_sfx[AMBIENT_WATER] = S_PrecacheSound ("ambience/water1.wav", false); + ambient_sfx[AMBIENT_SKY] = S_PrecacheSound ("ambience/wind2.wav", false); S_StopAllSounds (true); } @@ -283,8 +269,8 @@ S_FindName */ sfx_t *S_FindName (char *name) { - int i; - sfx_t *sfx; + int i; + sfx_t *sfx; if (!name) Host_Error ("S_FindName: NULL\n"); @@ -293,20 +279,19 @@ sfx_t *S_FindName (char *name) Host_Error ("Sound name too long: %s", name); // see if already loaded - for (i=0 ; i < num_sfx ; i++) + for (i = 0;i < num_sfx;i++) if (!strcmp(known_sfx[i].name, name)) - { return &known_sfx[i]; - } if (num_sfx == MAX_SFX) Sys_Error ("S_FindName: out of sfx_t"); - + sfx = &known_sfx[i]; + memset(sfx, 0, sizeof(*sfx)); strcpy (sfx->name, name); num_sfx++; - + return sfx; } @@ -320,7 +305,7 @@ S_TouchSound void S_TouchSound (char *name) { sfx_t *sfx; - + if (!sound_started) return; @@ -333,9 +318,9 @@ S_PrecacheSound ================== */ -sfx_t *S_PrecacheSound (char *name) +sfx_t *S_PrecacheSound (char *name, int complain) { - sfx_t *sfx; + sfx_t *sfx; if (!sound_started || nosound.integer) return NULL; @@ -343,8 +328,8 @@ sfx_t *S_PrecacheSound (char *name) sfx = S_FindName (name); // cache it in - if (precache.integer) - S_LoadSound (sfx); + if (snd_precache.integer) + S_LoadSound (sfx, complain); return sfx; } @@ -359,15 +344,15 @@ SND_PickChannel */ channel_t *SND_PickChannel(int entnum, int entchannel) { - int ch_idx; - int first_to_die; - int life_left; + int ch_idx; + int first_to_die; + int life_left; // Check for replacement sound, or find the best one to replace - first_to_die = -1; - life_left = 0x7fffffff; - for (ch_idx=NUM_AMBIENTS ; ch_idx < NUM_AMBIENTS + MAX_DYNAMIC_CHANNELS ; ch_idx++) - { + first_to_die = -1; + life_left = 0x7fffffff; + for (ch_idx=NUM_AMBIENTS ; ch_idx < NUM_AMBIENTS + MAX_DYNAMIC_CHANNELS ; ch_idx++) + { if (entchannel != 0 // channel 0 never overrides && channels[ch_idx].entnum == entnum && (channels[ch_idx].entchannel == entchannel || entchannel == -1) ) @@ -385,7 +370,7 @@ channel_t *SND_PickChannel(int entnum, int entchannel) life_left = channels[ch_idx].end - paintedtime; first_to_die = ch_idx; } - } + } if (first_to_die == -1) return NULL; @@ -393,7 +378,7 @@ channel_t *SND_PickChannel(int entnum, int entchannel) if (channels[first_to_die].sfx) channels[first_to_die].sfx = NULL; - return &channels[first_to_die]; + return &channels[first_to_die]; } /* @@ -401,53 +386,69 @@ channel_t *SND_PickChannel(int entnum, int entchannel) SND_Spatialize ================= */ -void SND_Spatialize(channel_t *ch) +void SND_Spatialize(channel_t *ch, int isstatic) { - vec_t dot; - vec_t dist; - vec_t lscale, rscale, scale; - vec3_t source_vec; + vec_t dot; + vec_t dist; + vec_t lscale, rscale, scale; + 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; ch->rightvol = ch->master_vol; - return; } + 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) + { + //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]->brush.TraceBox) + 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); + } -// calculate stereo seperation and distance attenuation + // calculate stereo seperation and distance attenuation + snd = ch->sfx; + VectorSubtract(ch->origin, listener_origin, source_vec); - snd = ch->sfx; - VectorSubtract(ch->origin, listener_origin, source_vec); + dist = VectorNormalizeLength(source_vec) * ch->dist_mult; - dist = VectorNormalizeLength(source_vec) * ch->dist_mult; + dot = DotProduct(listener_right, source_vec); - dot = DotProduct(listener_right, source_vec); + if (shm->channels == 1) + { + rscale = 1.0; + lscale = 1.0; + } + else + { + rscale = 1.0 + dot; + lscale = 1.0 - dot; + } - if (shm->channels == 1) - { - rscale = 1.0; - lscale = 1.0; + // 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; } - else + + // LordHavoc: allow adjusting volume of static sounds + if (isstatic) { - rscale = 1.0 + dot; - lscale = 1.0 - dot; + ch->leftvol *= snd_staticvolume.value; + ch->rightvol *= snd_staticvolume.value; } - -// 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; } @@ -481,18 +482,25 @@ void S_StartSound(int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float f // spatialize memset (target_chan, 0, sizeof(*target_chan)); + /* + if (cls.state == ca_connected && entnum > 0 && cl_entities[entnum].state_current.active) + { + target_chan.follow = true; + VectorSubtract(origin, cl_entities[entnum].state_current.origin, target_chan.followoriginoffset); + } + */ VectorCopy(origin, target_chan->origin); target_chan->dist_mult = attenuation / sound_nominal_clip_dist; target_chan->master_vol = vol; target_chan->entnum = entnum; target_chan->entchannel = entchannel; - SND_Spatialize(target_chan); + SND_Spatialize(target_chan, false); if (!target_chan->leftvol && !target_chan->rightvol) return; // not audible at all // new channel - sc = S_LoadSound (sfx); + sc = S_LoadSound (sfx, true); if (!sc) { target_chan->sfx = NULL; @@ -501,13 +509,13 @@ void S_StartSound(int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float f target_chan->sfx = sfx; target_chan->pos = 0.0; - target_chan->end = paintedtime + sc->length; + target_chan->end = paintedtime + sc->length; // if an identical sound has also been started this frame, offset the pos // a bit to keep it from just making the first one louder check = &channels[NUM_AMBIENTS]; - for (ch_idx=NUM_AMBIENTS ; ch_idx < NUM_AMBIENTS + MAX_DYNAMIC_CHANNELS ; ch_idx++, check++) - { + for (ch_idx=NUM_AMBIENTS ; ch_idx < NUM_AMBIENTS + MAX_DYNAMIC_CHANNELS ; ch_idx++, check++) + { if (check == target_chan) continue; if (check->sfx == sfx && !check->pos) @@ -544,17 +552,10 @@ 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 ; iloopstart == -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; ss->dist_mult = (attenuation/64) / sound_nominal_clip_dist; - ss->end = paintedtime + sc->length; + ss->end = paintedtime + sc->length; - SND_Spatialize (ss); + SND_Spatialize (ss, true); } @@ -682,29 +680,30 @@ 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 = Mod_PointInLeaf (listener_origin, cl.worldmodel); - if (!l) - return; + 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++) { + if (ambient_sfx[ambient_channel] && ambient_sfx[ambient_channel]->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; @@ -760,7 +759,7 @@ void S_Update(vec3_t origin, vec3_t forward, vec3_t right, vec3_t up) { if (!ch->sfx) continue; - SND_Spatialize(ch); // respatialize channel + SND_Spatialize(ch, i >= MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS); // respatialize channel if (!ch->leftvol && !ch->rightvol) continue; @@ -784,9 +783,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) @@ -798,8 +795,6 @@ void S_Update(vec3_t origin, vec3_t forward, vec3_t right, vec3_t up) continue; } } - - } // @@ -811,10 +806,7 @@ void S_Update(vec3_t origin, vec3_t forward, vec3_t right, vec3_t up) ch = channels; for (i=0 ; isfx && (ch->leftvol || ch->rightvol) ) - { - //Con_Printf ("%3i %3i %s\n", ch->leftvol, ch->rightvol, ch->sfx->name); total++; - } Con_Printf ("----(%i)----\n", total); } @@ -884,15 +876,12 @@ void S_Update_(void) // check to make sure that we haven't overshot if (paintedtime < soundtime) - { - //Con_Printf ("S_Update_ : overflow\n"); paintedtime = soundtime; - } // mix ahead of current position endtime = soundtime + _snd_mixahead.value * shm->speed; samps = shm->samples >> (shm->channels-1); - if (endtime - soundtime > samps) + if (endtime > (unsigned int)(soundtime + samps)) endtime = soundtime + samps; #ifdef _WIN32 @@ -929,7 +918,6 @@ console functions void S_Play(void) { - static int hash=345; int i; char name[256]; sfx_t *sfx; @@ -944,15 +932,14 @@ void S_Play(void) } else strcpy(name, Cmd_Argv(i)); - sfx = S_PrecacheSound(name); - S_StartSound(hash++, 0, sfx, listener_origin, 1.0, 1.0); + sfx = S_PrecacheSound(name, true); + S_StartSound(-1, 0, sfx, listener_origin, 1.0, 1.0); i++; } } void S_Play2(void) { - static int hash=345; int i; char name[256]; sfx_t *sfx; @@ -967,15 +954,14 @@ void S_Play2(void) } else strcpy(name, Cmd_Argv(i)); - sfx = S_PrecacheSound(name); - S_StartSound(hash++, 0, sfx, listener_origin, 1.0, 0.0); + sfx = S_PrecacheSound(name, true); + S_StartSound(-1, 0, sfx, listener_origin, 1.0, 0.0); i++; } } void S_PlayVol(void) { - static int hash=543; int i; float vol; char name[256]; @@ -991,9 +977,9 @@ void S_PlayVol(void) } else strcpy(name, Cmd_Argv(i)); - sfx = S_PrecacheSound(name); + sfx = S_PrecacheSound(name, true); vol = atof(Cmd_Argv(i+1)); - S_StartSound(hash++, 0, sfx, listener_origin, vol, 1.0); + S_StartSound(-1, 0, sfx, listener_origin, vol, 1.0); i+=2; } } @@ -1032,7 +1018,7 @@ void S_LocalSound (char *sound) if (!sound_started) return; - sfx = S_PrecacheSound (sound); + sfx = S_PrecacheSound (sound, true); if (!sfx) { Con_Printf ("S_LocalSound: can't precache %s\n", sound); @@ -1056,3 +1042,113 @@ void S_EndPrecaching (void) { } + +#define RAWSAMPLESBUFFER 32768 +short s_rawsamplesbuffer[RAWSAMPLESBUFFER * 2]; +int s_rawsamplesbuffer_start; +int s_rawsamplesbuffer_count; + +void S_RawSamples_Enqueue(short *samples, unsigned int length) +{ + int b2, b3; + //Con_Printf("S_RawSamples_Enqueue: %i samples\n", length); + if (s_rawsamplesbuffer_count + length > RAWSAMPLESBUFFER) + return; + b2 = (s_rawsamplesbuffer_start + s_rawsamplesbuffer_count) % RAWSAMPLESBUFFER; + if (b2 + length > RAWSAMPLESBUFFER) + { + b3 = (b2 + length) % RAWSAMPLESBUFFER; + memcpy(s_rawsamplesbuffer + b2 * 2, samples, (RAWSAMPLESBUFFER - b2) * sizeof(short[2])); + memcpy(s_rawsamplesbuffer, samples + (RAWSAMPLESBUFFER - b2) * 2, b3 * sizeof(short[2])); + } + else + memcpy(s_rawsamplesbuffer + b2 * 2, samples, length * sizeof(short[2])); + s_rawsamplesbuffer_count += length; +} + +void S_RawSamples_Dequeue(int *samples, unsigned int length) +{ + int b1, b2, l; + int i; + short *in; + int *out; + int count; + l = length; + if (l > s_rawsamplesbuffer_count) + l = s_rawsamplesbuffer_count; + b1 = (s_rawsamplesbuffer_start) % RAWSAMPLESBUFFER; + if (b1 + l > RAWSAMPLESBUFFER) + { + b2 = (b1 + l) % RAWSAMPLESBUFFER; + //memcpy(samples, s_rawsamplesbuffer + b1 * 2, (RAWSAMPLESBUFFER - b1) * sizeof(short[2])); + //memcpy(samples + (RAWSAMPLESBUFFER - b1) * 2, s_rawsamplesbuffer, b2 * sizeof(short[2])); + for (out = samples, in = s_rawsamplesbuffer + b1 * 2, count = (RAWSAMPLESBUFFER - b1) * 2, i = 0;i < count;i++) + out[i] = in[i]; + for (out = samples + (RAWSAMPLESBUFFER - b1) * 2, in = s_rawsamplesbuffer, count = b2 * 2, i = 0;i < count;i++) + out[i] = in[i]; + //Con_Printf("S_RawSamples_Dequeue: buffer wrap %i %i\n", (RAWSAMPLESBUFFER - b1), b2); + } + else + { + //memcpy(samples, s_rawsamplesbuffer + b1 * 2, l * sizeof(short[2])); + for (out = samples, in = s_rawsamplesbuffer + b1 * 2, count = l * 2, i = 0;i < count;i++) + out[i] = in[i]; + //Con_Printf("S_RawSamples_Dequeue: normal %i\n", l); + } + if (l < (int)length) + { + memset(samples + l * 2, 0, (length - l) * sizeof(int[2])); + //Con_Printf("S_RawSamples_Dequeue: padding with %i samples\n", length - l); + } + s_rawsamplesbuffer_start = (s_rawsamplesbuffer_start + l) % RAWSAMPLESBUFFER; + s_rawsamplesbuffer_count -= l; +} + +void S_RawSamples_ClearQueue(void) +{ + s_rawsamplesbuffer_count = 0; + s_rawsamplesbuffer_start = 0; +} + +int S_RawSamples_QueueWantsMore(void) +{ + if (s_rawsamplesbuffer_count < min(shm->speed >> 1, RAWSAMPLESBUFFER >> 1)) + return RAWSAMPLESBUFFER - s_rawsamplesbuffer_count; + else + return 0; +} + +void S_ResampleBuffer16Stereo(short *input, int inputlength, short *output, int outputlength) +{ + if (inputlength != outputlength) + { + int i, position, stopposition, step; + short *in, *out; + step = (float) inputlength * 256.0f / (float) outputlength; + position = 0; + stopposition = (inputlength - 1) << 8; + out = output; + for (i = 0;i < outputlength && position < stopposition;i++, position += step) + { + in = input + ((position >> 8) << 1); + out[0] = (((in[1] - in[0]) * (position & 255)) >> 8) + in[0]; + out[1] = (((in[3] - in[2]) * (position & 255)) >> 8) + in[2]; + out += 2; + } + stopposition = inputlength << 8; + for (i = 0;i < outputlength && position < stopposition;i++, position += step) + { + in = input + ((position >> 8) << 1); + out[0] = in[0]; + out[1] = in[2]; + out += 2; + } + } + else + memcpy(output, input, inputlength * sizeof(short[2])); +} + +int S_RawSamples_SampleRate(void) +{ + return shm != NULL ? shm->speed : 0; +}