X-Git-Url: https://de.git.xonotic.org/?a=blobdiff_plain;f=snd_mix.c;h=43bca9d9dfdd8de6cf1165219ea8905ddea66f81;hb=2f70889e776978ab1746211afc7723e04140fe4b;hp=0e4dada06e3248d9f37a835ca326d6a907389f2c;hpb=da29a8beeb35293e2fd38b51883c91b5cf4cf4ad;p=xonotic%2Fdarkplaces.git diff --git a/snd_mix.c b/snd_mix.c index 0e4dada0..43bca9d9 100644 --- a/snd_mix.c +++ b/snd_mix.c @@ -32,7 +32,6 @@ typedef struct portable_samplepair_s portable_sampleframe_t paintbuffer[PAINTBUFFER_SIZE]; -// FIXME: this desyncs with the video too easily extern void SCR_CaptureVideo_SoundFrame(unsigned char *bufstereo16le, size_t length, int rate); static void S_CaptureAVISound(size_t length) { @@ -40,7 +39,7 @@ static void S_CaptureAVISound(size_t length) unsigned char out[PAINTBUFFER_SIZE * 4]; unsigned char* out_ptr; - if (!cls.capturevideo_active) + if (!cls.capturevideo.active) return; // write the sound buffer as little endian 16bit interleaved stereo @@ -68,7 +67,7 @@ static unsigned int S_TransferPaintBuffer(snd_ringbuffer_t* rb, unsigned int sta // Lock submitbuffer if (!simsound && !SndSys_LockRenderBuffer()) return 0; - + partialend = starttime; while (partialend < endtime) // handle recirculating buffer issues { @@ -91,102 +90,46 @@ static unsigned int S_TransferPaintBuffer(snd_ringbuffer_t* rb, unsigned int sta short *snd_out = (short*)rb_ptr; if (rb->format.channels == 8) // 7.1 surround { - if (snd_swapstereo.value) + for (i = 0;i < nbframes;i++, painted_ptr++) { - for (i = 0; i < nbframes; i++, painted_ptr++) - { - *snd_out++ = bound(-32768, painted_ptr->sample[1], 32767); - *snd_out++ = bound(-32768, painted_ptr->sample[0], 32767); - *snd_out++ = bound(-32768, painted_ptr->sample[3], 32767); - *snd_out++ = bound(-32768, painted_ptr->sample[2], 32767); - *snd_out++ = bound(-32768, painted_ptr->sample[4], 32767); - *snd_out++ = bound(-32768, painted_ptr->sample[5], 32767); - *snd_out++ = bound(-32768, painted_ptr->sample[6], 32767); - *snd_out++ = bound(-32768, painted_ptr->sample[7], 32767); - } - } - else - { - for (i = 0;i < nbframes;i++, painted_ptr++) - { - *snd_out++ = bound(-32768, painted_ptr->sample[0], 32767); - *snd_out++ = bound(-32768, painted_ptr->sample[1], 32767); - *snd_out++ = bound(-32768, painted_ptr->sample[2], 32767); - *snd_out++ = bound(-32768, painted_ptr->sample[3], 32767); - *snd_out++ = bound(-32768, painted_ptr->sample[4], 32767); - *snd_out++ = bound(-32768, painted_ptr->sample[5], 32767); - *snd_out++ = bound(-32768, painted_ptr->sample[6], 32767); - *snd_out++ = bound(-32768, painted_ptr->sample[7], 32767); - } + *snd_out++ = bound(-32768, painted_ptr->sample[0], 32767); + *snd_out++ = bound(-32768, painted_ptr->sample[1], 32767); + *snd_out++ = bound(-32768, painted_ptr->sample[2], 32767); + *snd_out++ = bound(-32768, painted_ptr->sample[3], 32767); + *snd_out++ = bound(-32768, painted_ptr->sample[4], 32767); + *snd_out++ = bound(-32768, painted_ptr->sample[5], 32767); + *snd_out++ = bound(-32768, painted_ptr->sample[6], 32767); + *snd_out++ = bound(-32768, painted_ptr->sample[7], 32767); } } else if (rb->format.channels == 6) // 5.1 surround { - if (snd_swapstereo.value) - { - for (i = 0; i < nbframes; i++, painted_ptr++) - { - *snd_out++ = bound(-32768, painted_ptr->sample[1], 32767); - *snd_out++ = bound(-32768, painted_ptr->sample[0], 32767); - *snd_out++ = bound(-32768, painted_ptr->sample[3], 32767); - *snd_out++ = bound(-32768, painted_ptr->sample[2], 32767); - *snd_out++ = bound(-32768, painted_ptr->sample[4], 32767); - *snd_out++ = bound(-32768, painted_ptr->sample[5], 32767); - } - } - else + for (i = 0; i < nbframes; i++, painted_ptr++) { - for (i = 0; i < nbframes; i++, painted_ptr++) - { - *snd_out++ = bound(-32768, painted_ptr->sample[0], 32767); - *snd_out++ = bound(-32768, painted_ptr->sample[1], 32767); - *snd_out++ = bound(-32768, painted_ptr->sample[2], 32767); - *snd_out++ = bound(-32768, painted_ptr->sample[3], 32767); - *snd_out++ = bound(-32768, painted_ptr->sample[4], 32767); - *snd_out++ = bound(-32768, painted_ptr->sample[5], 32767); - } + *snd_out++ = bound(-32768, painted_ptr->sample[0], 32767); + *snd_out++ = bound(-32768, painted_ptr->sample[1], 32767); + *snd_out++ = bound(-32768, painted_ptr->sample[2], 32767); + *snd_out++ = bound(-32768, painted_ptr->sample[3], 32767); + *snd_out++ = bound(-32768, painted_ptr->sample[4], 32767); + *snd_out++ = bound(-32768, painted_ptr->sample[5], 32767); } } else if (rb->format.channels == 4) // 4.0 surround { - if (snd_swapstereo.value) - { - for (i = 0; i < nbframes; i++, painted_ptr++) - { - *snd_out++ = bound(-32768, painted_ptr->sample[1], 32767); - *snd_out++ = bound(-32768, painted_ptr->sample[0], 32767); - *snd_out++ = bound(-32768, painted_ptr->sample[3], 32767); - *snd_out++ = bound(-32768, painted_ptr->sample[2], 32767); - } - } - else + for (i = 0; i < nbframes; i++, painted_ptr++) { - for (i = 0; i < nbframes; i++, painted_ptr++) - { - *snd_out++ = bound(-32768, painted_ptr->sample[0], 32767); - *snd_out++ = bound(-32768, painted_ptr->sample[1], 32767); - *snd_out++ = bound(-32768, painted_ptr->sample[2], 32767); - *snd_out++ = bound(-32768, painted_ptr->sample[3], 32767); - } + *snd_out++ = bound(-32768, painted_ptr->sample[0], 32767); + *snd_out++ = bound(-32768, painted_ptr->sample[1], 32767); + *snd_out++ = bound(-32768, painted_ptr->sample[2], 32767); + *snd_out++ = bound(-32768, painted_ptr->sample[3], 32767); } } else if (rb->format.channels == 2) // 2.0 stereo { - if (snd_swapstereo.value) + for (i = 0; i < nbframes; i++, painted_ptr++) { - for (i = 0; i < nbframes; i++, painted_ptr++) - { - *snd_out++ = bound(-32768, painted_ptr->sample[1], 32767); - *snd_out++ = bound(-32768, painted_ptr->sample[0], 32767); - } - } - else - { - for (i = 0; i < nbframes; i++, painted_ptr++) - { - *snd_out++ = bound(-32768, painted_ptr->sample[0], 32767); - *snd_out++ = bound(-32768, painted_ptr->sample[1], 32767); - } + *snd_out++ = bound(-32768, painted_ptr->sample[0], 32767); + *snd_out++ = bound(-32768, painted_ptr->sample[1], 32767); } } else if (rb->format.channels == 1) // 1.0 mono @@ -203,102 +146,46 @@ static unsigned int S_TransferPaintBuffer(snd_ringbuffer_t* rb, unsigned int sta unsigned char *snd_out = (unsigned char*)rb_ptr; if (rb->format.channels == 8) // 7.1 surround { - if (snd_swapstereo.value) - { - for (i = 0; i < nbframes; i++, painted_ptr++) - { - val = (painted_ptr->sample[1] >> 8) + 128; *snd_out++ = bound(0, val, 255); - val = (painted_ptr->sample[0] >> 8) + 128; *snd_out++ = bound(0, val, 255); - val = (painted_ptr->sample[3] >> 8) + 128; *snd_out++ = bound(0, val, 255); - val = (painted_ptr->sample[2] >> 8) + 128; *snd_out++ = bound(0, val, 255); - val = (painted_ptr->sample[4] >> 8) + 128; *snd_out++ = bound(0, val, 255); - val = (painted_ptr->sample[5] >> 8) + 128; *snd_out++ = bound(0, val, 255); - val = (painted_ptr->sample[6] >> 8) + 128; *snd_out++ = bound(0, val, 255); - val = (painted_ptr->sample[7] >> 8) + 128; *snd_out++ = bound(0, val, 255); - } - } - else + for (i = 0; i < nbframes; i++, painted_ptr++) { - for (i = 0; i < nbframes; i++, painted_ptr++) - { - val = (painted_ptr->sample[0] >> 8) + 128; *snd_out++ = bound(0, val, 255); - val = (painted_ptr->sample[1] >> 8) + 128; *snd_out++ = bound(0, val, 255); - val = (painted_ptr->sample[2] >> 8) + 128; *snd_out++ = bound(0, val, 255); - val = (painted_ptr->sample[3] >> 8) + 128; *snd_out++ = bound(0, val, 255); - val = (painted_ptr->sample[4] >> 8) + 128; *snd_out++ = bound(0, val, 255); - val = (painted_ptr->sample[5] >> 8) + 128; *snd_out++ = bound(0, val, 255); - val = (painted_ptr->sample[6] >> 8) + 128; *snd_out++ = bound(0, val, 255); - val = (painted_ptr->sample[7] >> 8) + 128; *snd_out++ = bound(0, val, 255); - } + val = (painted_ptr->sample[0] >> 8) + 128; *snd_out++ = bound(0, val, 255); + val = (painted_ptr->sample[1] >> 8) + 128; *snd_out++ = bound(0, val, 255); + val = (painted_ptr->sample[2] >> 8) + 128; *snd_out++ = bound(0, val, 255); + val = (painted_ptr->sample[3] >> 8) + 128; *snd_out++ = bound(0, val, 255); + val = (painted_ptr->sample[4] >> 8) + 128; *snd_out++ = bound(0, val, 255); + val = (painted_ptr->sample[5] >> 8) + 128; *snd_out++ = bound(0, val, 255); + val = (painted_ptr->sample[6] >> 8) + 128; *snd_out++ = bound(0, val, 255); + val = (painted_ptr->sample[7] >> 8) + 128; *snd_out++ = bound(0, val, 255); } } else if (rb->format.channels == 6) // 5.1 surround { - if (snd_swapstereo.value) - { - for (i = 0; i < nbframes; i++, painted_ptr++) - { - val = (painted_ptr->sample[1] >> 8) + 128; *snd_out++ = bound(0, val, 255); - val = (painted_ptr->sample[0] >> 8) + 128; *snd_out++ = bound(0, val, 255); - val = (painted_ptr->sample[3] >> 8) + 128; *snd_out++ = bound(0, val, 255); - val = (painted_ptr->sample[2] >> 8) + 128; *snd_out++ = bound(0, val, 255); - val = (painted_ptr->sample[4] >> 8) + 128; *snd_out++ = bound(0, val, 255); - val = (painted_ptr->sample[5] >> 8) + 128; *snd_out++ = bound(0, val, 255); - } - } - else + for (i = 0; i < nbframes; i++, painted_ptr++) { - for (i = 0; i < nbframes; i++, painted_ptr++) - { - val = (painted_ptr->sample[0] >> 8) + 128; *snd_out++ = bound(0, val, 255); - val = (painted_ptr->sample[1] >> 8) + 128; *snd_out++ = bound(0, val, 255); - val = (painted_ptr->sample[2] >> 8) + 128; *snd_out++ = bound(0, val, 255); - val = (painted_ptr->sample[3] >> 8) + 128; *snd_out++ = bound(0, val, 255); - val = (painted_ptr->sample[4] >> 8) + 128; *snd_out++ = bound(0, val, 255); - val = (painted_ptr->sample[5] >> 8) + 128; *snd_out++ = bound(0, val, 255); - } + val = (painted_ptr->sample[0] >> 8) + 128; *snd_out++ = bound(0, val, 255); + val = (painted_ptr->sample[1] >> 8) + 128; *snd_out++ = bound(0, val, 255); + val = (painted_ptr->sample[2] >> 8) + 128; *snd_out++ = bound(0, val, 255); + val = (painted_ptr->sample[3] >> 8) + 128; *snd_out++ = bound(0, val, 255); + val = (painted_ptr->sample[4] >> 8) + 128; *snd_out++ = bound(0, val, 255); + val = (painted_ptr->sample[5] >> 8) + 128; *snd_out++ = bound(0, val, 255); } } else if (rb->format.channels == 4) // 4.0 surround { - if (snd_swapstereo.value) - { - for (i = 0; i < nbframes; i++, painted_ptr++) - { - val = (painted_ptr->sample[1] >> 8) + 128; *snd_out++ = bound(0, val, 255); - val = (painted_ptr->sample[0] >> 8) + 128; *snd_out++ = bound(0, val, 255); - val = (painted_ptr->sample[3] >> 8) + 128; *snd_out++ = bound(0, val, 255); - val = (painted_ptr->sample[2] >> 8) + 128; *snd_out++ = bound(0, val, 255); - } - } - else + for (i = 0; i < nbframes; i++, painted_ptr++) { - for (i = 0; i < nbframes; i++, painted_ptr++) - { - val = (painted_ptr->sample[0] >> 8) + 128; *snd_out++ = bound(0, val, 255); - val = (painted_ptr->sample[1] >> 8) + 128; *snd_out++ = bound(0, val, 255); - val = (painted_ptr->sample[2] >> 8) + 128; *snd_out++ = bound(0, val, 255); - val = (painted_ptr->sample[3] >> 8) + 128; *snd_out++ = bound(0, val, 255); - } + val = (painted_ptr->sample[0] >> 8) + 128; *snd_out++ = bound(0, val, 255); + val = (painted_ptr->sample[1] >> 8) + 128; *snd_out++ = bound(0, val, 255); + val = (painted_ptr->sample[2] >> 8) + 128; *snd_out++ = bound(0, val, 255); + val = (painted_ptr->sample[3] >> 8) + 128; *snd_out++ = bound(0, val, 255); } } else if (rb->format.channels == 2) // 2.0 stereo { - if (snd_swapstereo.value) - { - for (i = 0; i < nbframes; i++, painted_ptr++) - { - val = (painted_ptr->sample[1] >> 8) + 128; *snd_out++ = bound(0, val, 255); - val = (painted_ptr->sample[0] >> 8) + 128; *snd_out++ = bound(0, val, 255); - } - } - else + for (i = 0; i < nbframes; i++, painted_ptr++) { - for (i = 0; i < nbframes; i++, painted_ptr++) - { - val = (painted_ptr->sample[0] >> 8) + 128; *snd_out++ = bound(0, val, 255); - val = (painted_ptr->sample[1] >> 8) + 128; *snd_out++ = bound(0, val, 255); - } + val = (painted_ptr->sample[0] >> 8) + 128; *snd_out++ = bound(0, val, 255); + val = (painted_ptr->sample[1] >> 8) + 128; *snd_out++ = bound(0, val, 255); } } else if (rb->format.channels == 1) // 1.0 mono @@ -347,15 +234,28 @@ static qboolean SND_PaintChannel (channel_t *ch, unsigned int count) else snd_vol = (int)(volume.value * 256); + // calculate mixing volumes based on channel volumes and volume cvar + // also limit the volumes to values that won't clip for (i = 0;i < SND_LISTENERS;i++) + { vol[i] = ch->listener_volume[i] * snd_vol; + vol[i] = bound(0, vol[i], 65536); + } + + // if volumes are all zero, just return + for (i = 0;i < SND_LISTENERS;i++) + if (vol[i]) + break; + if (i == SND_LISTENERS) + return false; sb_offset = ch->pos; sb = ch->sfx->fetcher->getsb (ch, &sb_offset, count); if (sb == NULL) { Con_DPrintf("SND_PaintChannel: ERROR: can't get sound buffer from sfx \"%s\"\n", - ch->sfx->name, count); + ch->sfx->name); // , count); // or add this? FIXME + return false; } else { @@ -583,8 +483,6 @@ static qboolean SND_PaintChannel (channel_t *ch, unsigned int count) return false; // unsupported number of channels in sound } } - - ch->pos += count; return true; } @@ -608,105 +506,55 @@ void S_PaintChannels (snd_ringbuffer_t* rb, unsigned int starttime, unsigned int memset (paintbuffer, 0, (partialend - paintedtime) * sizeof (paintbuffer[0])); // paint in the channels. + // channels with zero volumes still advance in time but don't paint. ch = channels; for (i = 0; i < total_channels ; i++, ch++) { sfx_t *sfx; - unsigned int ltime, j; + unsigned int ltime; + unsigned int count; sfx = ch->sfx; if (sfx == NULL) continue; - for (j = 0;j < SND_LISTENERS;j++) - if (ch->listener_volume[j]) - break; - if (j == SND_LISTENERS) - continue; if (!S_LoadSound (sfx, true)) continue; - - // if the channel is paused if (ch->flags & CHANNELFLAG_PAUSED) - { - int pausedtime = partialend - paintedtime; - ch->lastptime += pausedtime; - ch->end += pausedtime; continue; - } - // if the sound hasn't been painted last time, update his position - if (ch->lastptime < paintedtime) + ltime = paintedtime; + if (ch->pos < 0) { - ch->pos += paintedtime - ch->lastptime; - - // If the sound should have ended by then - if ((unsigned int)ch->pos > sfx->total_length) - { - int loopstart; - - if (sfx->loopstart >= 0) - loopstart = bound(0, sfx->loopstart, (int)sfx->total_length - 1); - else - { - if (ch->flags & CHANNELFLAG_FORCELOOP) - loopstart = 0; - else - loopstart = -1; - } - - // If the sound is looped - if (loopstart >= 0) - ch->pos = (ch->pos - sfx->total_length) % (sfx->total_length - loopstart) + loopstart; - else - ch->pos = sfx->total_length; - ch->end = paintedtime + sfx->total_length - ch->pos; - } + count = -ch->pos; + count = min(count, partialend - ltime); + ch->pos += count; + ltime += count; } - ltime = paintedtime; while (ltime < partialend) { - int count; - qboolean stop_paint; - - // paint up to end - if (ch->end < partialend) - count = ch->end - ltime; - else - count = partialend - ltime; - - if (count > 0) + // paint up to end of buffer or of input, whichever is lower + count = sfx->total_length - ch->pos; + count = bound(0, count, partialend - ltime); + if (count) { - for (j = 0; j < SND_LISTENERS; j++) - ch->listener_volume[j] = bound(0, ch->listener_volume[j], 255); - - stop_paint = !SND_PaintChannel (ch, (unsigned int)count); - if (!stop_paint) - { - ltime += count; - ch->lastptime = ltime; - } + SND_PaintChannel (ch, count); + ch->pos += count; + ltime += count; } - else - stop_paint = false; - if (ltime >= ch->end) + // if at end of sfx, loop or stop the channel + if (ch->pos >= (int)sfx->total_length) { - // if at end of loop, restart - if ((sfx->loopstart >= 0 || (ch->flags & CHANNELFLAG_FORCELOOP)) && !stop_paint) + if (sfx->loopstart < sfx->total_length) + ch->pos = sfx->loopstart; + else if (ch->flags & CHANNELFLAG_FORCELOOP) + ch->pos = 0; + else { - ch->pos = bound(0, sfx->loopstart, (int)sfx->total_length - 1); - ch->end = ltime + sfx->total_length - ch->pos; + S_StopChannel (ch - channels); + break; } - // channel just stopped - else - stop_paint = true; - } - - if (stop_paint) - { - S_StopChannel (ch - channels); - break; } } }