Пример #1
0
void VOX_LoadWord( channel_t *pchan )
{
    if( pchan->words[pchan->wordIndex].sfx )
    {
        wavdata_t	*pSource = S_LoadSound( pchan->words[pchan->wordIndex].sfx );

        if( pSource )
        {
            int start = pchan->words[pchan->wordIndex].start;
            int end = pchan->words[pchan->wordIndex].end;

            // apply mixer
            pchan->currentWord = &pchan->pMixer;
            pchan->currentWord->pData = pSource;

            // don't allow overlapped ranges
            if( end <= start ) end = 0;

            if( start || end )
            {
                int	sampleCount = pSource->samples;

                if( start )
                {
                    S_SetSampleStart( pchan, pSource, (int)(sampleCount * 0.01f * start));
                }

                if( end )
                {
                    S_SetSampleEnd( pchan, pSource, (int)(sampleCount * 0.01f * end));
                }
            }
        }
    }
}
Пример #2
0
void S_StaticSound (sfx_t *sfx, vec3_t origin, float vol, float attenuation)
{
	channel_t *ss;
	sfxcache_t *sc;

	if (!shm || !sfx || s_nosound.value)
		return;

	if (total_channels == MAX_CHANNELS) {
		Com_Printf ("total_channels == MAX_CHANNELS\n");
		return;
	}

	ss = &channels[total_channels];
	total_channels++;

	sc = S_LoadSound (sfx);
	if (!sc)
		return;

	if (sc->loopstart == -1) {
		Com_Printf ("Sound %s not looped\n", sfx->name);
		return;
	}

	ss->sfx = sfx;
	VectorCopy (origin, ss->origin);
	ss->master_vol = (int) vol;
	ss->dist_mult = (attenuation/64) / sound_nominal_clip_dist;
	ss->end = paintedtime + (int) sc->total_length;

	SND_Spatialize (ss);
}
Пример #3
0
void S_EndRegistration(void)
{
	int		i;
	sfx_t	*sfx;

	// free any sounds not from this registration sequence
	for (i = 0, sfx = known_sfx; i < num_sfx; i++, sfx++)
	{
		if (!sfx->Name[0])
			continue;
		if (sfx->registration_sequence != s_registration_sequence)
		{
			// don't need this sound
			if (sfx->cache)	// it is possible to have a leftover
				appFree(sfx->cache);	// from a server that didn't finish loading
			memset(sfx, 0, sizeof(*sfx));
		}
	}

	// load everything in
	for (i = 0, sfx = known_sfx; i < num_sfx; i++, sfx++)
	{
		if (!sfx->Name[0])
			continue;
		S_LoadSound(sfx);
	}

	s_registering = false;
}
Пример #4
0
void S_memoryLoad(sfx_t	*sfx) {
	// load the sound file
	if ( !S_LoadSound ( sfx ) ) {
//		Com_Printf( S_COLOR_YELLOW "WARNING: couldn't load sound: %s\n", sfx->soundName );
		sfx->defaultSound = qtrue;
	}
	sfx->inMemory = qtrue;
}
Пример #5
0
void S_memoryLoad(sfx_t *sfx)
{
	// load the sound file
	if (!S_LoadSound(sfx))
	{
		sfx->defaultSound = qtrue;
	}
	sfx->inMemory = qtrue;
}
Пример #6
0
void
S_memoryLoad(Sfx *sfx)
{
    /* load the sound file */
    if(!S_LoadSound (sfx))
        /*		comprintf( S_COLOR_YELLOW "WARNING: couldn't load sound: %s\n", sfx->soundName ); */
        sfx->defaultSound = qtrue;
    sfx->inMemory = qtrue;
}
Пример #7
0
void S_StartSound (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol, float attenuation)
{
	channel_t *target_chan, *check;
	sfxcache_t *sc;
	int ch_idx, skip;

	if (!shm || !sfx || s_nosound.value)
		return;

	// pick a channel to play on
	target_chan = SND_PickChannel(entnum, entchannel);
	if (!target_chan)
		return;

	// spatialize
	memset (target_chan, 0, sizeof(*target_chan));
	VectorCopy(origin, target_chan->origin);
	target_chan->dist_mult = attenuation / sound_nominal_clip_dist;
	target_chan->master_vol = (int) (fvol * 255);
	target_chan->entnum = entnum;
	target_chan->entchannel = entchannel;
	SND_Spatialize(target_chan);

	if (!target_chan->leftvol && !target_chan->rightvol)
		return; // not audible at all

	// new channel
	sc = S_LoadSound (sfx);
	if (!sc) {
		target_chan->sfx = NULL;
		return; // couldn't load the sound's data
	}

	target_chan->sfx = sfx;
	target_chan->pos = 0.0;
	target_chan->end = paintedtime + (int) sc->total_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++) {
		if (check == target_chan)
			continue;
		if (check->sfx == sfx && !check->pos) {
			skip = rand () % (int)(0.1 * shm->format.speed);
			if (skip >= target_chan->end)
				skip = target_chan->end - 1;
			target_chan->pos += skip;
			target_chan->end -= skip;
			break;
		}
	}
}
Пример #8
0
/*
==================
S_RegisterSound

==================
*/
sfx_t *S_RegisterSound (const char *name)
{
	sfx_t	*sfx;

	if (!sound_started)
		return NULL;

	sfx = S_FindName (name, true);

	if (!s_registering)
		S_LoadSound(sfx);

	return sfx;
}
Пример #9
0
/*
* S_StartSound
*/
static void S_StartSound( sfx_t *sfx, const vec3_t origin, int entnum, int entchannel, float fvol, float attenuation )
{
	sfxcache_t *sc;
	int vol;
	playsound_t *ps, *sort;

	if( !sfx )
		return;

	// make sure the sound is loaded
	sc = S_LoadSound( sfx );
	if( !sc )
		return; // couldn't load the sound's data

	vol = fvol*255;

	// make the playsound_t
	ps = S_AllocPlaysound();
	if( !ps )
		return;

	if( origin )
	{
		VectorCopy( origin, ps->origin );
		ps->fixed_origin = true;
	}
	else
		ps->fixed_origin = false;

	ps->entnum = entnum;
	ps->entchannel = entchannel;
	ps->attenuation = attenuation;
	ps->volume = vol;
	ps->sfx = sfx;

	ps->begin = paintedtime;

	// sort into the pending sound list
	for( sort = s_pendingplays.next;
		sort != &s_pendingplays && sort->begin <= ps->begin;
		sort = sort->next )
		;

	ps->next = sort;
	ps->prev = sort->prev;

	ps->next->prev = ps;
	ps->prev->next = ps;
}
Пример #10
0
/*
==================
S_PrecacheSound

==================
*/
sfx_t *S_PrecacheSound (char *name)
{
	sfx_t	*sfx;

	if (!sound_started || nosound.value)
		return NULL;

	sfx = S_FindName (name);
	
// cache it in
	if (precache.value)
		S_LoadSound (sfx);
	
	return sfx;
}
Пример #11
0
/*
==================
S_RegisterSound

==================
*/
sfx_t *S_RegisterSound (char *name)
{
	sfx_t	*sfx;

	if (!sound_started)
		return NULL;

	sfx = S_FindName (name, true);
	sfx->registration_sequence = s_registration_sequence;

	if (!s_registering)
		S_LoadSound (sfx);

	return sfx;
}
Пример #12
0
sfx_t *S_RegisterSound(const char *name)
{
	if (!sound_started) return NULL;

	sfx_t *sfx = S_FindName(name, true);
	sfx->registration_sequence = s_registration_sequence;

	if (!s_registering)
		S_LoadSound(sfx);
	else
		if (name[0] != '#' && name[0] != '*' && !GFileSystem->FileExists(va("sound/%s", name)))
			sfx->absent = true;

	return sfx;
}
Пример #13
0
/*
==================
S_PrecacheSound

==================
*/
sfx_t *S_PrecacheSound (char *name)
{
	sfx_t	*sfx;

	if (!snd_initialized)
		return NULL;

	sfx = S_FindName (name);
	
// cache it in
	if (!s_nosound.value || s_precache.value)
		S_LoadSound (sfx);
	
	return sfx;
}
Пример #14
0
static void
I_OGGMus_PlayNext (int looping)
{
	const char *track;
	sfx_t      *cd_sfx, *sfx;
	wavinfo_t  *info = 0;

	if (!play_list)
		return;
	if (PL_Type (play_list) == QFString) {
		track = PL_String (play_list);
		play_pos = 0;
	} else {
		play_pos++;
		if (play_pos >= PL_A_NumObjects (play_list))
			play_pos = 0;
		track = PL_String (PL_ObjectAtIndex (play_list, play_pos));
		looping = 0;
	}

	if (cd_channel) {
		S_ChannelStop (cd_channel);
		cd_channel = 0;
	}

	if (!(cd_channel = S_AllocChannel ()))
		return;

	if (!(cd_sfx = S_LoadSound (track)) || !(sfx = cd_sfx->open (cd_sfx))) {
		S_ChannelStop (cd_channel);
		cd_channel = 0;
		return;
	}
	Sys_Printf ("Playing: %s.\n", track);
	if (sfx->wavinfo)
		info = sfx->wavinfo (sfx);
	if (info) {
		if (looping == true)
			info->loopstart = 0;
		else
			info->loopstart = -1;
	}
	cd_channel->sfx = sfx;
	set_volume ();

	playing = true;
}
Пример #15
0
/*
=====================
S_EndRegistration

=====================
*/
void S_EndRegistration (void)
{
	int		i;
	sfx_t	*sfx;

	// load everything in
	for (i=0, sfx=known_sfx ; i < num_sfx ; i++,sfx++)
	{
		if (!sfx->name[0])
			continue;
		S_LoadSound (sfx);
	}

	Hunk_End(&hunk_snd);

	s_registering = false;
}
Пример #16
0
/*
=====================
S_EndRegistration

=====================
*/
void S_EndRegistration (void)
{
	int		i;
	sfx_t	*sfx;
	int		size;

	// free any sounds not from this registration sequence
	for (i=0, sfx=known_sfx ; i < num_sfx ; i++,sfx++)
	{
		if (!sfx->name[0])
			continue;
		if (sfx->registration_sequence != s_registration_sequence)
		{	// don't need this sound
			if (sfx->cache)	// it is possible to have a leftover
				Z_Free (sfx->cache);	// from a server that didn't finish loading
			memset (sfx, 0, sizeof(*sfx));
		}
		else
		{	// make sure it is paged in
			if (sfx->cache)
			{
				size = sfx->cache->length*sfx->cache->width;
				Com_PageInMemory ((byte *)sfx->cache, size);
			}
		}

	}

	// load everything in
	for (i=0, sfx=known_sfx ; i < num_sfx ; i++,sfx++)
	{
		if (!sfx->name[0])
			continue;
		S_LoadSound (sfx);
	}

	s_registering = false;

	// Knightmare added
	// S_EndRegistration is only called while the refresh is prepped
	// during a sound resart, so we can use this to restart the music track
	if (cls.state == ca_active && cl.refresh_prepped && !CDAudio_Active())
		CL_PlayBackgroundTrack ();
}
Пример #17
0
sfx_t *S_PrecacheSound (char *name)
{
	sfx_t *sfx;

	if (!snd_initialized || s_nosound.value)
		return NULL;

	if (name == NULL || name[0] == 0)
		return NULL;

	sfx = S_FindName (name);
	if (sfx == NULL)
		return NULL;

	// cache it in
	if (s_precache.value)
		S_LoadSound (sfx);

	return sfx;
}
Пример #18
0
/*
===============
S_IssuePlaysound

Take the next playsound and begin it on the channel
This is never called directly by S_Play*, but only
by the update loop.
===============
*/
void S_IssuePlaysound (playsound_t *ps)
{
	channel_t	*ch;
	sfxcache_t	*sc;

	if (s_show->integer)
		Com_Printf ("Issue %i\n", ps->begin);
	// pick a channel to play on
	ch = S_PickChannel(ps->entnum, ps->entchannel);
	if (!ch) {
		S_FreePlaysound(ps);
		return;
	}

	sc = S_LoadSound(ps->sfx);
	if (!sc || sc->length <= 0) {
		S_FreePlaysound(ps);
		return;
	}

	// spatialize
	if (ps->attenuation == ATTN_STATIC)
		ch->dist_mult = ps->attenuation * 0.001f;
	else
		ch->dist_mult = ps->attenuation * 0.0005f;
	ch->master_vol = ps->volume;
	ch->entnum = ps->entnum;
	ch->entchannel = ps->entchannel;
	ch->sfx = ps->sfx;
	VectorCopy (ps->origin, ch->origin);
	ch->fixed_origin = ps->fixed_origin;

	S_Spatialize(ch);

	ch->pos = 0;
    ch->end = paintedtime + sc->length;

	// free the playsound
	S_FreePlaysound(ps);
}
Пример #19
0
/*
* SF_RegisterSound
*/
sfx_t *SF_RegisterSound( const char *name )
{
	sfx_t *sfx;
	int sfxnum;

	assert( name );

	sfx = SF_FindName( name );
	if( sfx->registration_sequence != s_registration_sequence ) {
		sfx->registration_sequence = s_registration_sequence;

		// evenly balance the load between two threads during registration
		sfxnum = sfx - known_sfx;
		if( !s_registering || sfxnum & 1 ) {
			S_IssueLoadSfxCmd( s_cmdPipe, sfxnum );
		}
		else {
			S_LoadSound( sfx );
		}
	}
	return sfx;
}
Пример #20
0
/*
=====================
S_EndRegistration

=====================
*/
void S_EndRegistration(void)
{
    int i;
    sfx_t * sfx;
    int size;

    // free any sounds not from this registration sequence
    for (i = 0, sfx = known_sfx; i < num_sfx; i++, sfx++)
    {
        if (!sfx->name[0])
            continue;
        if (sfx->registration_sequence != s_registration_sequence)
        {                           // don't need this sound
            if (sfx->cache)         // it is possible to have a leftover
                Z_Free(sfx->cache); // from a server that didn't finish loading
            memset(sfx, 0, sizeof(*sfx));
        }
        else
        { // make sure it is paged in
            if (sfx->cache)
            {
                size = sfx->cache->length * sfx->cache->width;
                Com_PageInMemory((byte *)sfx->cache, size);
            }
        }
    }

    // load everything in
    for (i = 0, sfx = known_sfx; i < num_sfx; i++, sfx++)
    {
        if (!sfx->name[0])
            continue;
        S_LoadSound(sfx);
    }

    s_registering = false;
}
Пример #21
0
/*
===============
S_IssuePlaysound

Take the next playsound and begin it on the channel
This is never called directly by S_Play*, but only
by the update loop.
===============
*/
void S_IssuePlaysound(playsound_t *ps)
{
	channel_t	*ch;
	sfxcache_t	*sc;

	if (s_show->integer)
		appPrintf("Sound: %s begin:%d ent:%d chn:%d\n", *ps->sfx->Name, ps->begin, ps->entnum, ps->entchannel);
	// pick a channel to play on
	ch = S_PickChannel(ps->entnum, ps->entchannel);
	if (!ch)
	{
		S_FreePlaysound(ps);
		return;
	}

	// spatialize
	if (ps->attenuation == ATTN_STATIC)
		ch->dist_mult = ps->attenuation * 0.001f;		// will be fixed value: 0.003f
	else
		ch->dist_mult = ps->attenuation * 0.0005f;
	ch->master_vol = ps->volume;
	ch->entnum = ps->entnum;
	ch->entchannel = ps->entchannel;
	ch->sfx = ps->sfx;
	ch->origin = ps->origin;
	ch->fixed_origin = ps->fixed_origin;

	S_Spatialize(ch);

	ch->pos = 0;
	sc = S_LoadSound(ch->sfx);
	ch->end = paintedtime + sc->length;

	// free the playsound
	S_FreePlaysound(ps);
}
Пример #22
0
/*
=================
S_StaticSound
=================
*/
void S_StaticSound (sfx_t *sfx, vec3_t origin, float vol, float attenuation)
{
	channel_t	*ss;
	sfxcache_t		*sc;

	if (!sfx)
		return;

	if (total_channels == MAX_CHANNELS)
	{
		Con_Printf ("StaticSound: MAX_CHANNELS reached\n");
		Con_Printf (" failed at (%.2f, %.2f, %.2f)\n",origin[0],origin[1],origin[2]);
		return;
	}

	ss = &channels[total_channels];
	total_channels++;

	sc = S_LoadSound (sfx);
	if (!sc)
		return;

	if (sc->loopstart == -1)
	{
		Con_Printf ("Sound %s not looped\n", sfx->name);
		return;
	}
	
	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;	
	
	SND_Spatialize (ss);
}
Пример #23
0
/*
=====================
S_EndRegistration

=====================
*/
void S_EndRegistration (void)
{
	int		i;
	sfx_t	*sfx, *entry, **back;
	int		size;
	unsigned int hash;

	// free any sounds not from this registration sequence
	for (i=0, sfx=known_sfx ; i < num_sfx ; i++,sfx++)
	{
		if (!sfx->name[0])
			continue;
		if (sfx->registration_sequence == s_registration_sequence) {
#ifdef USE_OPENAL
			if(sfx->cache && !alSound) { // make sure it is paged in
#else
			if(sfx->cache) { // make sure it is paged in
#endif
				size = sfx->cache->length * sfx->cache->width * sfx->cache->channels;
				Com_PageInMemory( (byte *)sfx->cache, size);
			}
			continue;
		}

		hash = Com_HashKey (sfx->name, SND_HASH_SIZE);
		// delete it from hash table
		for( back=&sfx_hash[hash], entry=sfx_hash[hash]; entry; back=&entry->hashNext, entry=entry->hashNext ) {
			if( entry == sfx ) {
				*back = entry->hashNext;
				break;
			}
		}

		if (sfx->cache)	{ // it is possible to have a leftover
#ifdef USE_OPENAL
			if(alSound)
				ALSnd_DeleteBuffer(sfx->cache);
#endif
			Z_Free (sfx->cache);	// from a server that didn't finish loading
		}
		if (sfx->truename)
			Z_Free (sfx->truename);

		memset (sfx, 0, sizeof(*sfx));
	}

	// load everything in
	for (i=0, sfx=known_sfx ; i < num_sfx ; i++,sfx++)
	{
		if (!sfx->name[0])
			continue;
		S_LoadSound (sfx);
	}

	s_registering = false;
}


//=============================================================================

/*
=================
S_PickChannel
=================
*/
static channel_t *S_PickChannel(int entnum, int entchannel)
{
    int			ch_idx;
    int			first_to_die = -1;
    int			life_left = 0x7fffffff;
	channel_t	*ch;

	if (entchannel < 0)
		Com_Error(ERR_DROP, "S_PickChannel: entchannel < 0");

// Check for replacement sound, or find the best one to replace
    for (ch_idx=0 ; ch_idx < MAX_CHANNELS ; ch_idx++)
    {
		if (entchannel != 0		// channel 0 never overrides
		&& channels[ch_idx].entnum == entnum
		&& channels[ch_idx].entchannel == entchannel)
		{	// always override sound from same entity
			first_to_die = ch_idx;
			break;
		}

		// don't let monster sounds override player sounds
		if (channels[ch_idx].entnum == cl.playernum+1 && entnum != cl.playernum+1 && channels[ch_idx].sfx)
			continue;

		if (channels[ch_idx].end - paintedtime < life_left)
		{
			life_left = channels[ch_idx].end - paintedtime;
			first_to_die = ch_idx;
		}
   }

	if (first_to_die == -1)
		return NULL;

	ch = &channels[first_to_die];
	memset (ch, 0, sizeof(*ch));

    return ch;
}       
Пример #24
0
bool S_LoadBuffer( sfx_t *sfx )
{
	ALenum error;
	void *data;
	snd_info_t info;
	ALuint format;

	if( !sfx ) {
		return false;
	}
	if( sfx->filename[0] == '\0' || sfx->inMemory )
		return false;
	if( trap_FS_IsUrl( sfx->filename ) )
		return false;

	data = S_LoadSound( sfx->filename, &info );
	if( !data )
	{
		//Com_DPrintf( "Couldn't load %s\n", sfx->filename );
		return false;
	}

	if( info.channels > 1 )
	{
		void *temp = stereo_mono( data, &info );
		if( temp )
		{
			S_Free( data );
			data = temp;
		}
	}

	format = S_SoundFormat( info.width, info.channels );

	qalGenBuffers( 1, &sfx->buffer );
	if( ( error = qalGetError() ) != AL_NO_ERROR )
	{
		S_Free( data );
		Com_Printf( "Couldn't create a sound buffer for %s (%s)\n", sfx->filename, S_ErrorMessage( error ) );
		return false;
	}

	qalBufferData( sfx->buffer, format, data, info.size, info.rate );
	error = qalGetError();

	// If we ran out of memory, start evicting the least recently used sounds
	while( error == AL_OUT_OF_MEMORY )
	{
		if( !buffer_evict() )
		{
			S_Free( data );
			Com_Printf( "Out of memory loading %s\n", sfx->filename );
			return false;
		}

		// Try load it again
		qalGetError();
		qalBufferData( sfx->buffer, format, data, info.size, info.rate );
		error = qalGetError();
	}

	// Some other error condition
	if( error != AL_NO_ERROR )
	{
		S_Free( data );
		Com_Printf( "Couldn't fill sound buffer for %s (%s)", sfx->filename, S_ErrorMessage( error ) );
		return false;
	}

	S_Free( data );
	sfx->inMemory = true;

	return true;
}
Пример #25
0
/*
====================
S_StartSound

Validates the parms and ques the sound up
if pos is NULL, the sound will be dynamically sourced from the entity
Entchannel 0 will never override a playing sound
====================
*/
void S_StartSound(const CVec3 *origin, int entnum, int entchannel, sfx_t *sfx, float fvol, float attenuation, float timeofs)
{
	if (!sound_started) return;
	if (!sfx) return;

	if (sfx->Name[0] == '*')
		sfx = GetPlayerSound(&cl_entities[entnum].current, sfx->Name);

	// make sure the sound is loaded
	sfxcache_t *sc = S_LoadSound(sfx);
	if (!sc)
		return;		// couldn't load the sound's data

	int vol = appRound(fvol*255);

	// make the playsound_t
	playsound_t *ps = S_AllocPlaysound();
	if (!ps) return;

	if (origin)
	{
		ps->origin = *origin;
		ps->fixed_origin = true;
	}
	else
		ps->fixed_origin = false;

	ps->entnum      = entnum;
	ps->entchannel  = entchannel;
	ps->attenuation = attenuation;
	ps->volume      = vol;
	ps->sfx         = sfx;

	// drift s_beginofs
	int start = appRound(cl.frame.servertime / 1000.0f * dma.speed + s_beginofs);
	if (start < paintedtime)
	{
		start = paintedtime;
		s_beginofs = start - appRound(cl.frame.servertime / 1000.0f * dma.speed);
	}
	else if (start > paintedtime + 0.3 * dma.speed)
	{
		start = appRound(paintedtime + 0.1 * dma.speed);
		s_beginofs = start - appRound(cl.frame.servertime / 1000.0f * dma.speed);
	}
	else
	{
		s_beginofs-=10;
	}

	if (!timeofs)
		ps->begin = paintedtime;
	else
		ps->begin = appRound(start + timeofs * dma.speed);

	// sort into the pending sound list
	playsound_t *sort;
	for (sort = s_pendingplays.next; sort != &s_pendingplays && sort->begin < ps->begin; sort = sort->next)
		; // empty

	ps->next = sort;
	ps->prev = sort->prev;

	ps->next->prev = ps;
	ps->prev->next = ps;
}
Пример #26
0
void S_MixToBuffer(void *stream, unsigned int bufferframes)
{
	int channelindex;
	channel_t *ch;
	int totalmixframes;
	unsigned char *outbytes = (unsigned char *) stream;
	sfx_t *sfx;
	portable_sampleframe_t *paint;
	int wantframes;
	int i;
	int count;
	int fetched;
	int fetch;
	int istartframe;
	int iendframe;
	int ilengthframes;
	int totallength;
	int loopstart;
	int indexfrac;
	int indexfracstep;
#define S_FETCHBUFFERSIZE 4096
	float fetchsampleframes[S_FETCHBUFFERSIZE*2];
	const float *fetchsampleframe;
	float vol[SND_LISTENERS];
	float lerp[2];
	float sample[3];
	double posd;
	double speedd;
	float maxvol;
	qboolean looping;
	qboolean silent;

	// mix as many times as needed to fill the requested buffer
	while (bufferframes)
	{
		// limit to the size of the paint buffer
		totalmixframes = min(bufferframes, PAINTBUFFER_SIZE);

		// clear the paint buffer
		memset(paintbuffer, 0, totalmixframes * sizeof(paintbuffer[0]));

		// paint in the channels.
		// channels with zero volumes still advance in time but don't paint.
		ch = channels; // cppcheck complains here but it is wrong, channels is a channel_t[MAX_CHANNELS] and not an int
		for (channelindex = 0;channelindex < (int)total_channels;channelindex++, ch++)
		{
			sfx = ch->sfx;
			if (sfx == NULL)
				continue;
			if (!S_LoadSound (sfx, true))
				continue;
			if (ch->flags & CHANNELFLAG_PAUSED)
				continue;
			if (!sfx->total_length)
				continue;

			// copy the channel information to the stack for reference, otherwise the
			// values might change during a mix if the spatializer is updating them
			// (note: this still may get some old and some new values!)
			posd = ch->position;
			speedd = ch->mixspeed * sfx->format.speed / snd_renderbuffer->format.speed;
			for (i = 0;i < SND_LISTENERS;i++)
				vol[i] = ch->volume[i];

			// check total volume level, because we can skip some code on silent sounds but other code must still run (position updates mainly)
			maxvol = 0;
			for (i = 0;i < SND_LISTENERS;i++)
				if(vol[i] > maxvol)
					maxvol = vol[i];
			switch(snd_renderbuffer->format.width)
			{
				case 1: // 8bpp
					silent = maxvol < (1.0f / (256.0f));
					// so silent it has zero effect
					break;
				case 2: // 16bpp
					silent = maxvol < (1.0f / (65536.0f));
					// so silent it has zero effect
					break;
				default: // floating point
					silent = maxvol < 1.0e-13f;
					// 130 dB is difference between hearing
					// threshold and a jackhammer from
					// working distance.
					// therefore, anyone who turns up
					// volume so much they notice this
					// cutoff, likely already has their
					// ear-drums blown out anyway.
					break;
			}

			// when doing prologic mixing, some channels invert one side
			if (ch->prologic_invert == -1)
				vol[1] *= -1.0f;

			// get some sfx info in a consistent form
			totallength = sfx->total_length;
			loopstart = (int)sfx->loopstart < totallength ? (int)sfx->loopstart : ((ch->flags & CHANNELFLAG_FORCELOOP) ? 0 : totallength);
			looping = loopstart < totallength;

			// do the actual paint now (may skip work if silent)
			paint = paintbuffer;
			istartframe = 0;
			for (wantframes = totalmixframes;wantframes > 0;posd += count * speedd, wantframes -= count)
			{
				// check if this is a delayed sound
				if (posd < 0)
				{
					// for a delayed sound we have to eat into the delay first
					count = (int)floor(-posd / speedd) + 1;
					count = bound(1, count, wantframes);
					// let the for loop iterator apply the skip
					continue;
				}

				// compute a fetch size that won't overflow our buffer
				count = wantframes;
				for (;;)
				{
					istartframe = (int)floor(posd);
					iendframe = (int)floor(posd + (count-1) * speedd);
					ilengthframes = count > 1 ? (iendframe - istartframe + 2) : 2;
					if (ilengthframes <= S_FETCHBUFFERSIZE)
						break;
					// reduce count by 25% and try again
					count -= count >> 2;
				}

				// zero whole fetch buffer for safety
				// (floating point noise from uninitialized memory = HORRIBLE)
				// otherwise we would only need to clear the excess
				if (!silent)
					memset(fetchsampleframes, 0, ilengthframes*sfx->format.channels*sizeof(fetchsampleframes[0]));

				// if looping, do multiple fetches
				fetched = 0;
				for (;;)
				{
					fetch = min(ilengthframes - fetched, totallength - istartframe);
					if (fetch > 0)
					{
						if (!silent)
							sfx->fetcher->getsamplesfloat(ch, sfx, istartframe, fetch, fetchsampleframes + fetched*sfx->format.channels);
						istartframe += fetch;
						fetched += fetch;
					}
					if (istartframe == totallength && looping && fetched < ilengthframes)
					{
						// loop and fetch some more
						posd += loopstart - totallength;
						istartframe = loopstart;
					}
					else
					{
						break;
					}
				}

				// set up our fixedpoint resampling variables (float to int conversions are expensive so do not do one per sampleframe)
				fetchsampleframe = fetchsampleframes;
				indexfrac = (int)floor((posd - floor(posd)) * 65536.0);
				indexfracstep = (int)floor(speedd * 65536.0);
				if (!silent)
				{
					if (sfx->format.channels == 2)
					{
						// music is stereo
#if SND_LISTENERS != 8
#error the following code only supports up to 8 channels, update it
#endif
						if (snd_speakerlayout.channels > 2)
						{
							// surround mixing
							for (i = 0;i < count;i++, paint++)
							{
								lerp[1] = indexfrac * (1.0f / 65536.0f);
								lerp[0] = 1.0f - lerp[1];
								sample[0] = fetchsampleframe[0] * lerp[0] + fetchsampleframe[2] * lerp[1];
								sample[1] = fetchsampleframe[1] * lerp[0] + fetchsampleframe[3] * lerp[1];
								sample[2] = (sample[0] + sample[1]) * 0.5f;
								paint->sample[0] += sample[0] * vol[0];
								paint->sample[1] += sample[1] * vol[1];
								paint->sample[2] += sample[0] * vol[2];
								paint->sample[3] += sample[1] * vol[3];
								paint->sample[4] += sample[2] * vol[4];
								paint->sample[5] += sample[2] * vol[5];
								paint->sample[6] += sample[0] * vol[6];
								paint->sample[7] += sample[1] * vol[7];
								indexfrac += indexfracstep;
								fetchsampleframe += 2 * (indexfrac >> 16);
								indexfrac &= 0xFFFF;
							}
						}
						else
						{
							// stereo mixing
							for (i = 0;i < count;i++, paint++)
							{
								lerp[1] = indexfrac * (1.0f / 65536.0f);
								lerp[0] = 1.0f - lerp[1];
								sample[0] = fetchsampleframe[0] * lerp[0] + fetchsampleframe[2] * lerp[1];
								sample[1] = fetchsampleframe[1] * lerp[0] + fetchsampleframe[3] * lerp[1];
								paint->sample[0] += sample[0] * vol[0];
								paint->sample[1] += sample[1] * vol[1];
								indexfrac += indexfracstep;
								fetchsampleframe += 2 * (indexfrac >> 16);
								indexfrac &= 0xFFFF;
							}
						}
					}
					else if (sfx->format.channels == 1)
					{
						// most sounds are mono
#if SND_LISTENERS != 8
#error the following code only supports up to 8 channels, update it
#endif
						if (snd_speakerlayout.channels > 2)
						{
							// surround mixing
							for (i = 0;i < count;i++, paint++)
							{
								lerp[1] = indexfrac * (1.0f / 65536.0f);
								lerp[0] = 1.0f - lerp[1];
								sample[0] = fetchsampleframe[0] * lerp[0] + fetchsampleframe[1] * lerp[1];
								paint->sample[0] += sample[0] * vol[0];
								paint->sample[1] += sample[0] * vol[1];
								paint->sample[2] += sample[0] * vol[2];
								paint->sample[3] += sample[0] * vol[3];
								paint->sample[4] += sample[0] * vol[4];
								paint->sample[5] += sample[0] * vol[5];
								paint->sample[6] += sample[0] * vol[6];
								paint->sample[7] += sample[0] * vol[7];
								indexfrac += indexfracstep;
								fetchsampleframe += (indexfrac >> 16);
								indexfrac &= 0xFFFF;
							}
						}
						else
						{
							// stereo mixing
							for (i = 0;i < count;i++, paint++)
							{
								lerp[1] = indexfrac * (1.0f / 65536.0f);
								lerp[0] = 1.0f - lerp[1];
								sample[0] = fetchsampleframe[0] * lerp[0] + fetchsampleframe[1] * lerp[1];
								paint->sample[0] += sample[0] * vol[0];
								paint->sample[1] += sample[0] * vol[1];
								indexfrac += indexfracstep;
								fetchsampleframe += (indexfrac >> 16);
								indexfrac &= 0xFFFF;
							}
						}
					}
				}
			}
Пример #27
0
int32_t S_PlaySound3D(int32_t num, int32_t i, const vec3_t *pos)
{
    int32_t j = VM_OnEventWithReturn(EVENT_SOUND, i, screenpeek, num);

    if (j == -1 && num != -1) // check that the user returned -1, but only if -1 wasn't playing already (in which case, warn)
        return -1;

    num = j;

    const DukePlayer_t *const myps = g_player[myconnectindex].ps;

    if ((unsigned)num > (unsigned)g_maxSoundPos || ((g_sounds[num].m & SF_ADULT) && ud.lockout) ||
        !ud.config.SoundToggle || (unsigned)i >= MAXSPRITES || !FX_VoiceAvailable(g_sounds[num].pr) ||
        (myps->timebeforeexit > 0 && myps->timebeforeexit <= GAMETICSPERSEC * 3) || (myps->gm & MODE_MENU))
        return -1;

    int32_t voice;

    if (g_sounds[num].m & SF_DTAG)  // Duke-Tag sound
    {
        if ((voice = S_PlaySound(num)) <= FX_Ok)
            return -1;

        j = 0;
        while (j < MAXSOUNDINSTANCES && g_sounds[num].SoundOwner[j].voice != voice)
            j++;

        if (EDUKE32_PREDICT_FALSE(j >= MAXSOUNDINSTANCES))
        {
            OSD_Printf(OSD_ERROR "%s %d: WTF?\n", __FILE__, __LINE__);
            return -1;
        }

        g_sounds[num].SoundOwner[j].ow = i;

        return voice;
    }

    // Duke talk
    if (g_sounds[num].m & SF_TALK)
    {
        if ((g_netServer || ud.multimode > 1) && PN == APLAYER && P_Get(i) != screenpeek) // other player sound
        {
            if (!(ud.config.VoiceToggle&4))
                return -1;
        }
        else if (!(ud.config.VoiceToggle&1))
            return -1;

        // don't play if any Duke talk sounds are already playing
        for (j=0; j<g_maxSoundPos; ++j)
            if ((g_sounds[j].m & SF_TALK) && g_sounds[j].num > 0)
                return -1;
    }

    int32_t sndist, sndang;
    int32_t explosionp = S_CalcDistAndAng(i, num, CAMERA(sect), CAMERA(ang), &CAMERA(pos), pos, &sndist, &sndang);
    int32_t pitch = S_GetPitch(num);
    const DukePlayer_t *peekps = g_player[screenpeek].ps;

#ifdef SPLITSCREEN_MOD_HACKS
    if (g_fakeMultiMode==2)
    {
        // splitscreen HACK
        if (g_player[1].ps->i == i)
            peekps = g_player[1].ps;
    }
#endif

    if (peekps->sound_pitch)
        pitch += peekps->sound_pitch;

    if (explosionp)
    {
        if (peekps->cursectnum > -1 && sector[peekps->cursectnum].lotag == ST_2_UNDERWATER)
            pitch -= 1024;
    }
    else
    {
        if (sndist > 32767 && PN != MUSICANDSFX && (g_sounds[num].m & (SF_LOOP|SF_MSFX)) == 0)
            return -1;

        if (peekps->cursectnum > -1 && sector[peekps->cursectnum].lotag == ST_2_UNDERWATER
                && (g_sounds[num].m & SF_TALK) == 0)
            pitch = -768;
    }

    if (g_sounds[num].num > 0 && PN != MUSICANDSFX)
        S_StopEnvSound(num, i);

    if (g_sounds[num].ptr == 0)
    {
        if (S_LoadSound(num) == 0)
            return -1;
    }
    else
    {
        if (g_soundlocks[num] < 200)
            g_soundlocks[num] = 200;
        else g_soundlocks[num]++;
    }

    j = S_GetSlot(num);

    if (j >= MAXSOUNDINSTANCES)
    {
        g_soundlocks[num]--;
        return -1;
    }

    {
        const int32_t repeatp = (g_sounds[num].m & SF_LOOP);
        const int32_t ambsfxp = S_IsAmbientSFX(i);

        if (repeatp && (g_sounds[num].m & SF_ONEINST_INTERNAL) && g_sounds[num].num > 0)
        {
            g_soundlocks[num]--;
            return -1;
        }

        if (repeatp && !ambsfxp)
        {
            voice = FX_PlayLoopedAuto(g_sounds[num].ptr, g_sounds[num].soundsiz, 0, -1,
                                      pitch, FX_VOLUME(sndist>>6), FX_VOLUME(sndist>>6), 0,  // XXX: why is 'right' 0?
                                      g_sounds[num].pr, (num * MAXSOUNDINSTANCES) + j);
        }
        else
        {
Пример #28
0
/*
====================
S_StartSound

Validates the parms and ques the sound up
if pos is NULL, the sound will be dynamically sourced from the entity
Entchannel 0 will never override a playing sound
====================
*/
void S_StartSound(const vec3_t origin, int entnum, int entchannel, sfx_t *sfx, float fvol, float attenuation, float timeofs)
{
	sfxcache_t	*sc;
	playsound_t	*ps, *sort;
	int			start;

	if (!sound_started)
		return;

	if (!sfx)
		return;

	if (sfx->name[0] == '*') {
		if(entnum < 1 || entnum >= MAX_EDICTS ) {
			Com_Error( ERR_DROP, "S_StartSound: bad entnum: %d", entnum );
		}
		sfx = S_RegisterSexedSound(cl_entities[entnum].current.number, sfx->name);
	}

	// make sure the sound is loaded
	sc = S_LoadSound (sfx);
	if (!sc || sc->length <= 0)
		return;		// couldn't load the sound's data

	// make the playsound_t
	ps = S_AllocPlaysound ();
	if (!ps)
		return;

	if (origin) {
		VectorCopy (origin, ps->origin);
		ps->fixed_origin = true;
	}
	else
		ps->fixed_origin = false;

	ps->entnum = entnum;
	ps->entchannel = entchannel;
	ps->attenuation = attenuation;
	ps->sfx = sfx;

#ifdef USE_OPENAL
	if(alSound) {
		ps->volume = fvol*fvol;
		ps->begin = cl.time + (int)(timeofs * 1000);
	}
	else
#endif
	{
		ps->volume = fvol*255;
		// drift s_beginofs
		start = cl.serverTime * 0.001f * dma.speed + s_beginofs;
		if (start < paintedtime)
		{
			start = paintedtime;
			s_beginofs = start - (cl.serverTime * 0.001f * dma.speed);
		}
		else if (start > paintedtime + 0.3f * dma.speed)
		{
			start = paintedtime + 0.1f * dma.speed;
			s_beginofs = start - (cl.serverTime * 0.001f * dma.speed);
		}
		else
		{
			s_beginofs -= 10;
		}

		if (!timeofs)
			ps->begin = paintedtime;
		else
			ps->begin = start + timeofs * dma.speed;
	}

	// sort into the pending sound list
	for (sort = s_pendingplays.next;
		sort != &s_pendingplays && sort->begin < ps->begin ;
		sort = sort->next)
			;

	ps->next = sort;
	ps->prev = sort->prev;

	ps->next->prev = ps;
	ps->prev->next = ps;
}
Пример #29
0
/*
====================
S_StartSound

Validates the parms and ques the sound up
if pos is NULL, the sound will be dynamically sourced from the entity
Entchannel 0 will never override a playing sound
====================
*/
void S_StartSound(vec3_t origin, int entnum, int entchannel, sfx_t *sfx, float fvol, float attenuation, float timeofs)
{
	sfxcache_t	*sc;
	int			vol;
	playsound_t	*ps, *sort;
	int			start;

	if (!sound_started)
		return;

	if (!sfx)
		return;

	if (sfx->name[0] == '*')
		sfx = S_RegisterSexedSound(&cl_entities[entnum].current, sfx->name);

	// make sure the sound is loaded
	sc = S_LoadSound (sfx);
	if (!sc)
		return;		// couldn't load the sound's data

	vol = fvol*255;

	// make the playsound_t
	ps = S_AllocPlaysound ();
	if (!ps)
		return;

	if (origin)
	{
		VectorCopy (origin, ps->origin);
		ps->fixed_origin = true;
	}
	else
		ps->fixed_origin = false;

	ps->entnum = entnum;
	ps->entchannel = entchannel;
	ps->attenuation = attenuation;
	ps->volume = vol;
	ps->sfx = sfx;

	// drift s_beginofs
	start = cl.frame.servertime * 0.001 * dma.speed + s_beginofs;
	if (start < paintedtime)
	{
		start = paintedtime;
		s_beginofs = start - (cl.frame.servertime * 0.001 * dma.speed);
	}
	else if (start > paintedtime + 0.3 * dma.speed)
	{
		start = paintedtime + 0.1 * dma.speed;
		s_beginofs = start - (cl.frame.servertime * 0.001 * dma.speed);
	}
	else
	{
		s_beginofs-=10;
	}

	if (!timeofs)
		ps->begin = paintedtime;
	else
		ps->begin = start + timeofs * dma.speed;

	// sort into the pending sound list
	for (sort = s_pendingplays.next ; 
		sort != &s_pendingplays && sort->begin < ps->begin ;
		sort = sort->next)
			;

	ps->next = sort;
	ps->prev = sort->prev;

	ps->next->prev = ps;
	ps->prev->next = ps;
}