/* ======================== S_ScanChannelStarts Returns qtrue if any new sounds were started since the last mix ======================== */ qboolean S_ScanChannelStarts( void ) { channel_t *ch; int i; qboolean newSamples; newSamples = qfalse; ch = s_channels; for (i=0; i<MAX_CHANNELS ; i++, ch++) { if ( !ch->thesfx ) { continue; } // if this channel was just started this frame, // set the sample count to it begins mixing // into the very first sample if ( ch->startSample == START_SAMPLE_IMMEDIATE ) { ch->startSample = s_paintedtime; newSamples = qtrue; continue; } // if it is completely finished by now, clear it if ( ch->startSample + (ch->thesfx->soundLength) <= s_paintedtime ) { S_ChannelFree(ch); } } return newSamples; }
/* ======================== S_ScanChannelStarts Returns qtrue if any new sounds were started since the last mix ======================== */ static qboolean S_ScanChannelStarts( void ) { channel_t *ch; int i; qboolean newSamples; float scale; newSamples = qfalse; ch = s_channels; if (s_useTimescale->integer) { scale = com_timescale->value; } else if (s_forceScale->value > 0.0) { scale = s_forceScale->value; } else { scale = 1; } for (i=0; i<MAX_CHANNELS ; i++, ch++) { if ( !ch->thesfx ) { continue; } // if this channel was just started this frame, // set the sample count to it begins mixing // into the very first sample if ( ch->startSample == START_SAMPLE_IMMEDIATE ) { ch->startSample = s_paintedtime; newSamples = qtrue; continue; } // if it is completely finished by now, clear it if ( ch->startSample + (ceil((float)ch->thesfx->soundLength / scale)) <= s_paintedtime ) { //Com_Printf("freeing %p\n", ch); S_ChannelFree(ch); } } return newSamples; }
void S_Base_ClearSounds(qboolean clearStreaming, qboolean clearMusic) { if (!s_soundStarted) { return; } // stop looping sounds Com_Memset(loopSounds, 0, MAX_LOOP_SOUNDS * sizeof(loopSound_t)); Com_Memset(loop_channels, 0, MAX_CHANNELS * sizeof(channel_t)); numLoopChannels = 0; numLoopSounds = 0; // moved this up so streaming sounds dont get updated with the music, below, // and leave us with a snippet off streaming sounds after we reload if (clearStreaming) { int i; streamingSound_t *ss; channel_t *ch; for (i = 0, ss = streamingSounds; i < MAX_STREAMING_SOUNDS; i++, ss++) { if (i > 0 || clearMusic) { S_StopStreamingSound(i); } } // we should also kill all channels, since we are killing streaming sounds anyway // (fixes siren in forest playing after a map_restart/loadgame ch = s_channels; for (i = 0; i < MAX_CHANNELS; i++, ch++) { if (ch->thesfx) { S_ChannelFree(ch); } } } if (!clearMusic) { S_UpdateStreamingSounds(); } if (clearStreaming && clearMusic) { int clear; if (dma.samplebits == 8) { clear = 0x80; } else { clear = 0; } SNDDMA_BeginPainting(); if (dma.buffer) { Com_Memset(dma.buffer, clear, dma.samples * dma.samplebits / 8); } SNDDMA_Submit(); // clear out channels so they don't finish playing when audio restarts S_ChannelSetup(); } }
/* ==================== S_StartSoundEx 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_Base_StartSoundEx(vec3_t origin, int entnum, int entchannel, sfxHandle_t sfxHandle, int flags, int volume) { channel_t *ch; sfx_t *sfx; int i, time; if (!s_soundStarted || s_soundMuted) { //Com_Printf(S_COLOR_YELLOW "S_Base_StartSoundEx: sound not started or muted\n"); return; } if (!origin && (entnum < 0 || entnum >= MAX_GENTITIES)) { Com_Error(ERR_DROP, "S_Base_StartSoundEx: bad entitynum %i", entnum); } if (sfxHandle < 0 || sfxHandle >= numSfx) { Com_Printf(S_COLOR_YELLOW "S_Base_StartSoundEx: handle %i out of range", sfxHandle); return; } sfx = &knownSfx[sfxHandle]; if (sfx->inMemory == qfalse) { S_memoryLoad(sfx); } if (s_show->integer == 1) { Com_Printf("S_Base_StartSoundEx: %i : %s\n", s_paintedtime, sfx->soundName); } time = Sys_Milliseconds(); ch = s_channels; for (i = 0; i < MAX_CHANNELS ; i++, ch++) { if (ch->entnum == entnum && ch->thesfx) { if (ch->thesfx == sfx && time - ch->allocTime < 50) // double played in one frame { return; } else if (ch->entchannel == entchannel && (flags & SND_CUTOFF_ALL)) // cut the sounds that are flagged to be cut { S_ChannelFree(ch); } } } sfx->lastTimeUsed = time; ch = S_ChannelMalloc(); if (!ch) { int oldest = sfx->lastTimeUsed; int chosen = -1; ch = s_channels; for (i = 0 ; i < MAX_CHANNELS ; i++, ch++) { if (ch->entnum != listener_number && ch->entnum == entnum && ch->allocTime < oldest && ch->entchannel != CHAN_ANNOUNCER) { oldest = ch->allocTime; chosen = i; } } if (chosen == -1) { ch = s_channels; for (i = 0 ; i < MAX_CHANNELS ; i++, ch++) { if (ch->entnum != listener_number && ch->allocTime < oldest && ch->entchannel != CHAN_ANNOUNCER) { oldest = ch->allocTime; chosen = i; } } if (chosen == -1) { ch = s_channels; if (ch->entnum == listener_number) { for (i = 0 ; i < MAX_CHANNELS ; i++, ch++) { if (ch->allocTime < oldest) { oldest = ch->allocTime; chosen = i; } } } if (chosen == -1) { Com_Printf("S_Base_StartSoundEx WARNING: dropping sound\n"); return; } } } ch = &s_channels[chosen]; ch->allocTime = sfx->lastTimeUsed; } if (origin) { VectorCopy(origin, ch->origin); ch->fixed_origin = qtrue; } else { ch->fixed_origin = qfalse; } ch->flags = flags; ch->master_vol = volume; ch->entnum = entnum; ch->thesfx = sfx; ch->startSample = START_SAMPLE_IMMEDIATE; ch->entchannel = entchannel; ch->leftvol = ch->master_vol; // these will get calced at next spatialize ch->rightvol = ch->master_vol; // unless the game isn't running ch->doppler = qfalse; }