#include "snd_main.h"
-typedef struct portable_samplepair_s
-{
- int sample[SND_LISTENERS];
-} portable_sampleframe_t;
-
-// LordHavoc: was 512, expanded to 2048
-#define PAINTBUFFER_SIZE 2048
-portable_sampleframe_t paintbuffer[PAINTBUFFER_SIZE];
+static portable_sampleframe_t paintbuffer[PAINTBUFFER_SIZE];
+static portable_sampleframe_t paintbuffer_unswapped[PAINTBUFFER_SIZE];
+extern speakerlayout_t snd_speakerlayout; // for querying the listeners
-extern void SCR_CaptureVideo_SoundFrame(unsigned char *bufstereo16le, size_t length, int rate);
+extern void SCR_CaptureVideo_SoundFrame(const portable_sampleframe_t *paintbuffer, size_t length);
static void S_CaptureAVISound(size_t length)
{
size_t i;
- unsigned char out[PAINTBUFFER_SIZE * 4];
- unsigned char* out_ptr;
+ unsigned int j;
- if (!cls.capturevideo_active)
+ if (!cls.capturevideo.active)
return;
- // write the sound buffer as little endian 16bit interleaved stereo
- for(i = 0, out_ptr = out; i < length; i++, out_ptr += 4)
+ // undo whatever swapping the channel layout (swapstereo, ALSA) did
+ for(j = 0; j < snd_speakerlayout.channels; ++j)
{
- int n0, n1;
-
- n0 = paintbuffer[i].sample[0];
- n0 = bound(-32768, n0, 32767);
- out_ptr[0] = (unsigned char)n0;
- out_ptr[1] = (unsigned char)(n0 >> 8);
-
- n1 = paintbuffer[i].sample[1];
- n1 = bound(-32768, n1, 32767);
- out_ptr[2] = (unsigned char)n1;
- out_ptr[3] = (unsigned char)(n1 >> 8);
+ unsigned int j0 = snd_speakerlayout.listeners[j].channel_unswapped;
+ for(i = 0; i < length; ++i)
+ paintbuffer_unswapped[i].sample[j0] = paintbuffer[i].sample[j];
}
- SCR_CaptureVideo_SoundFrame(out, length, snd_renderbuffer->format.speed);
+
+ SCR_CaptureVideo_SoundFrame(paintbuffer_unswapped, length);
}
-static unsigned int S_TransferPaintBuffer(snd_ringbuffer_t* rb, unsigned int starttime, unsigned int endtime)
+static void S_ConvertPaintBuffer(const portable_sampleframe_t *painted_ptr, void *rb_ptr, int nbframes, int width, int channels)
{
- unsigned int partialend;
-
- // Lock submitbuffer
- if (!simsound && !SndSys_LockRenderBuffer())
- return 0;
-
- partialend = starttime;
- while (partialend < endtime) // handle recirculating buffer issues
+ int i, val;
+ if (width == 2) // 16bit
{
- unsigned int startoffset, maxframes, nbframes, i;
- void *rb_ptr;
- portable_sampleframe_t *painted_ptr;
- int val;
-
- startoffset = partialend % rb->maxframes;
- maxframes = rb->maxframes - startoffset;
- nbframes = endtime - partialend;
- if (nbframes > maxframes)
- nbframes = maxframes;
-
- rb_ptr = &rb->ring[startoffset * rb->format.width * rb->format.channels];
- painted_ptr = &paintbuffer[partialend - starttime];
-
- if (rb->format.width == 2) // 16bit
+ short *snd_out = (short*)rb_ptr;
+ if (channels == 8) // 7.1 surround
{
- short *snd_out = (short*)rb_ptr;
- if (rb->format.channels == 8) // 7.1 surround
+ 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[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
+ }
+ else if (channels == 6) // 5.1 surround
+ {
+ 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
+ }
+ else if (channels == 4) // 4.0 surround
+ {
+ 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
+ }
+ else if (channels == 2) // 2.0 stereo
+ {
+ 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[0], 32767);
+ *snd_out++ = bound(-32768, painted_ptr->sample[1], 32767);
}
- else if (rb->format.channels == 1) // 1.0 mono
+ }
+ else if (channels == 1) // 1.0 mono
+ {
+ for (i = 0; i < nbframes; i++, painted_ptr++)
{
- for (i = 0; i < nbframes; i++, painted_ptr++)
- {
- val = (painted_ptr->sample[0] + painted_ptr->sample[1]) >> 1;
- *snd_out++ = bound(-32768, val, 32767);
- }
+ val = (painted_ptr->sample[0] + painted_ptr->sample[1]) >> 1;
+ *snd_out++ = bound(-32768, val, 32767);
}
}
- else // 8bit
+
+ // noise is really really annoying
+ if (cls.timedemo)
+ memset(rb_ptr, 0, nbframes * channels * width);
+ }
+ else // 8bit
+ {
+ unsigned char *snd_out = (unsigned char*)rb_ptr;
+ if (channels == 8) // 7.1 surround
{
- unsigned char *snd_out = (unsigned char*)rb_ptr;
- if (rb->format.channels == 8) // 7.1 surround
+ 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
+ }
+ else if (channels == 6) // 5.1 surround
+ {
+ 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
+ }
+ else if (channels == 4) // 4.0 surround
+ {
+ 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
+ }
+ else if (channels == 2) // 2.0 stereo
+ {
+ 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
+ }
+ else if (channels == 1) // 1.0 mono
+ {
+ for (i = 0;i < nbframes;i++, painted_ptr++)
{
- for (i = 0;i < nbframes;i++, painted_ptr++)
- {
- val = ((painted_ptr->sample[0] + painted_ptr->sample[1]) >> 9) + 128;
- *snd_out++ = bound(0, val, 255);
- }
+ val = ((painted_ptr->sample[0] + painted_ptr->sample[1]) >> 9) + 128;
+ *snd_out++ = bound(0, val, 255);
}
}
- partialend += nbframes;
+ // noise is really really annoying
+ if (cls.timedemo)
+ memset(rb_ptr, 128, nbframes * channels);
}
-
- rb->endframe = endtime;
-
- // Remove outdated samples from the ring buffer, if any
- if (rb->startframe < soundtime)
- rb->startframe = soundtime;
-
- if (!simsound)
- SndSys_UnlockRenderBuffer();
-
- return endtime - starttime;
}
===============================================================================
*/
-static qboolean SND_PaintChannel (channel_t *ch, unsigned int count)
+static qboolean SND_PaintChannel (channel_t *ch, portable_sampleframe_t *paint, unsigned int count)
{
int snd_vol, vol[SND_LISTENERS];
const snd_buffer_t *sb;
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);
+ sb = ch->sfx->fetcher->getsb (ch->sfx->fetcher_data, &ch->fetcher_data, &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
{
{
for (i = 0;i < count;i++)
{
- paintbuffer[i].sample[0] += (samples[0] * vol[0]) >> 8;
- paintbuffer[i].sample[1] += (samples[1] * vol[1]) >> 8;
- paintbuffer[i].sample[2] += (samples[0] * vol[2]) >> 8;
- paintbuffer[i].sample[3] += (samples[1] * vol[3]) >> 8;
- paintbuffer[i].sample[4] += ((samples[0] + samples[1]) * vol[4]) >> 9;
- paintbuffer[i].sample[5] += ((samples[0] + samples[1]) * vol[5]) >> 9;
- paintbuffer[i].sample[6] += (samples[0] * vol[6]) >> 8;
- paintbuffer[i].sample[7] += (samples[1] * vol[7]) >> 8;
+ paint[i].sample[0] += (samples[0] * vol[0]) >> 8;
+ paint[i].sample[1] += (samples[1] * vol[1]) >> 8;
+ paint[i].sample[2] += (samples[0] * vol[2]) >> 8;
+ paint[i].sample[3] += (samples[1] * vol[3]) >> 8;
+ paint[i].sample[4] += ((samples[0] + samples[1]) * vol[4]) >> 9;
+ paint[i].sample[5] += ((samples[0] + samples[1]) * vol[5]) >> 9;
+ paint[i].sample[6] += (samples[0] * vol[6]) >> 8;
+ paint[i].sample[7] += (samples[1] * vol[7]) >> 8;
samples += 2;
}
}
{
for (i = 0;i < count;i++)
{
- paintbuffer[i].sample[0] += (samples[0] * vol[0]) >> 8;
- paintbuffer[i].sample[1] += (samples[1] * vol[1]) >> 8;
- paintbuffer[i].sample[2] += (samples[0] * vol[2]) >> 8;
- paintbuffer[i].sample[3] += (samples[1] * vol[3]) >> 8;
- paintbuffer[i].sample[4] += ((samples[0] + samples[1]) * vol[4]) >> 9;
- paintbuffer[i].sample[5] += ((samples[0] + samples[1]) * vol[5]) >> 9;
+ paint[i].sample[0] += (samples[0] * vol[0]) >> 8;
+ paint[i].sample[1] += (samples[1] * vol[1]) >> 8;
+ paint[i].sample[2] += (samples[0] * vol[2]) >> 8;
+ paint[i].sample[3] += (samples[1] * vol[3]) >> 8;
+ paint[i].sample[4] += ((samples[0] + samples[1]) * vol[4]) >> 9;
+ paint[i].sample[5] += ((samples[0] + samples[1]) * vol[5]) >> 9;
samples += 2;
}
}
{
for (i = 0;i < count;i++)
{
- paintbuffer[i].sample[0] += (samples[0] * vol[0]) >> 8;
- paintbuffer[i].sample[1] += (samples[1] * vol[1]) >> 8;
- paintbuffer[i].sample[2] += (samples[0] * vol[2]) >> 8;
- paintbuffer[i].sample[3] += (samples[1] * vol[3]) >> 8;
+ paint[i].sample[0] += (samples[0] * vol[0]) >> 8;
+ paint[i].sample[1] += (samples[1] * vol[1]) >> 8;
+ paint[i].sample[2] += (samples[0] * vol[2]) >> 8;
+ paint[i].sample[3] += (samples[1] * vol[3]) >> 8;
samples += 2;
}
}
{
for (i = 0;i < count;i++)
{
- paintbuffer[i].sample[0] += (samples[0] * vol[0]) >> 8;
- paintbuffer[i].sample[1] += (samples[1] * vol[1]) >> 8;
+ paint[i].sample[0] += (samples[0] * vol[0]) >> 8;
+ paint[i].sample[1] += (samples[1] * vol[1]) >> 8;
samples += 2;
}
}
{
for (i = 0;i < count;i++)
{
- paintbuffer[i].sample[0] += (samples[0] * vol[0]) >> 8;
- paintbuffer[i].sample[1] += (samples[0] * vol[1]) >> 8;
- paintbuffer[i].sample[2] += (samples[0] * vol[2]) >> 8;
- paintbuffer[i].sample[3] += (samples[0] * vol[3]) >> 8;
- paintbuffer[i].sample[4] += (samples[0] * vol[4]) >> 8;
- paintbuffer[i].sample[5] += (samples[0] * vol[5]) >> 8;
- paintbuffer[i].sample[6] += (samples[0] * vol[6]) >> 8;
- paintbuffer[i].sample[7] += (samples[0] * vol[7]) >> 8;
+ paint[i].sample[0] += (samples[0] * vol[0]) >> 8;
+ paint[i].sample[1] += (samples[0] * vol[1]) >> 8;
+ paint[i].sample[2] += (samples[0] * vol[2]) >> 8;
+ paint[i].sample[3] += (samples[0] * vol[3]) >> 8;
+ paint[i].sample[4] += (samples[0] * vol[4]) >> 8;
+ paint[i].sample[5] += (samples[0] * vol[5]) >> 8;
+ paint[i].sample[6] += (samples[0] * vol[6]) >> 8;
+ paint[i].sample[7] += (samples[0] * vol[7]) >> 8;
samples += 1;
}
}
{
for (i = 0;i < count;i++)
{
- paintbuffer[i].sample[0] += (samples[0] * vol[0]) >> 8;
- paintbuffer[i].sample[1] += (samples[0] * vol[1]) >> 8;
- paintbuffer[i].sample[2] += (samples[0] * vol[2]) >> 8;
- paintbuffer[i].sample[3] += (samples[0] * vol[3]) >> 8;
- paintbuffer[i].sample[4] += (samples[0] * vol[4]) >> 8;
- paintbuffer[i].sample[5] += (samples[0] * vol[5]) >> 8;
+ paint[i].sample[0] += (samples[0] * vol[0]) >> 8;
+ paint[i].sample[1] += (samples[0] * vol[1]) >> 8;
+ paint[i].sample[2] += (samples[0] * vol[2]) >> 8;
+ paint[i].sample[3] += (samples[0] * vol[3]) >> 8;
+ paint[i].sample[4] += (samples[0] * vol[4]) >> 8;
+ paint[i].sample[5] += (samples[0] * vol[5]) >> 8;
samples += 1;
}
}
{
for (i = 0;i < count;i++)
{
- paintbuffer[i].sample[0] += (samples[0] * vol[0]) >> 8;
- paintbuffer[i].sample[1] += (samples[0] * vol[1]) >> 8;
- paintbuffer[i].sample[2] += (samples[0] * vol[2]) >> 8;
- paintbuffer[i].sample[3] += (samples[0] * vol[3]) >> 8;
+ paint[i].sample[0] += (samples[0] * vol[0]) >> 8;
+ paint[i].sample[1] += (samples[0] * vol[1]) >> 8;
+ paint[i].sample[2] += (samples[0] * vol[2]) >> 8;
+ paint[i].sample[3] += (samples[0] * vol[3]) >> 8;
samples += 1;
}
}
{
for (i = 0;i < count;i++)
{
- paintbuffer[i].sample[0] += (samples[0] * vol[0]) >> 8;
- paintbuffer[i].sample[1] += (samples[0] * vol[1]) >> 8;
+ paint[i].sample[0] += (samples[0] * vol[0]) >> 8;
+ paint[i].sample[1] += (samples[0] * vol[1]) >> 8;
samples += 1;
}
}
{
for (i = 0;i < count;i++)
{
- paintbuffer[i].sample[0] += (samples[0] * vol[0]) >> 16;
- paintbuffer[i].sample[1] += (samples[1] * vol[1]) >> 16;
- paintbuffer[i].sample[2] += (samples[0] * vol[2]) >> 16;
- paintbuffer[i].sample[3] += (samples[1] * vol[3]) >> 16;
- paintbuffer[i].sample[4] += ((samples[0] + samples[1]) * vol[4]) >> 17;
- paintbuffer[i].sample[5] += ((samples[0] + samples[1]) * vol[5]) >> 17;
- paintbuffer[i].sample[6] += (samples[0] * vol[6]) >> 16;
- paintbuffer[i].sample[7] += (samples[1] * vol[7]) >> 16;
+ paint[i].sample[0] += (samples[0] * vol[0]) >> 16;
+ paint[i].sample[1] += (samples[1] * vol[1]) >> 16;
+ paint[i].sample[2] += (samples[0] * vol[2]) >> 16;
+ paint[i].sample[3] += (samples[1] * vol[3]) >> 16;
+ paint[i].sample[4] += ((samples[0] + samples[1]) * vol[4]) >> 17;
+ paint[i].sample[5] += ((samples[0] + samples[1]) * vol[5]) >> 17;
+ paint[i].sample[6] += (samples[0] * vol[6]) >> 16;
+ paint[i].sample[7] += (samples[1] * vol[7]) >> 16;
samples += 2;
}
}
{
for (i = 0;i < count;i++)
{
- paintbuffer[i].sample[0] += (samples[0] * vol[0]) >> 16;
- paintbuffer[i].sample[1] += (samples[1] * vol[1]) >> 16;
- paintbuffer[i].sample[2] += (samples[0] * vol[2]) >> 16;
- paintbuffer[i].sample[3] += (samples[1] * vol[3]) >> 16;
- paintbuffer[i].sample[4] += ((samples[0] + samples[1]) * vol[4]) >> 17;
- paintbuffer[i].sample[5] += ((samples[0] + samples[1]) * vol[5]) >> 17;
+ paint[i].sample[0] += (samples[0] * vol[0]) >> 16;
+ paint[i].sample[1] += (samples[1] * vol[1]) >> 16;
+ paint[i].sample[2] += (samples[0] * vol[2]) >> 16;
+ paint[i].sample[3] += (samples[1] * vol[3]) >> 16;
+ paint[i].sample[4] += ((samples[0] + samples[1]) * vol[4]) >> 17;
+ paint[i].sample[5] += ((samples[0] + samples[1]) * vol[5]) >> 17;
samples += 2;
}
}
{
for (i = 0;i < count;i++)
{
- paintbuffer[i].sample[0] += (samples[0] * vol[0]) >> 16;
- paintbuffer[i].sample[1] += (samples[1] * vol[1]) >> 16;
- paintbuffer[i].sample[2] += (samples[0] * vol[2]) >> 16;
- paintbuffer[i].sample[3] += (samples[1] * vol[3]) >> 16;
+ paint[i].sample[0] += (samples[0] * vol[0]) >> 16;
+ paint[i].sample[1] += (samples[1] * vol[1]) >> 16;
+ paint[i].sample[2] += (samples[0] * vol[2]) >> 16;
+ paint[i].sample[3] += (samples[1] * vol[3]) >> 16;
samples += 2;
}
}
{
for (i = 0;i < count;i++)
{
- paintbuffer[i].sample[0] += (samples[0] * vol[0]) >> 16;
- paintbuffer[i].sample[1] += (samples[1] * vol[1]) >> 16;
+ paint[i].sample[0] += (samples[0] * vol[0]) >> 16;
+ paint[i].sample[1] += (samples[1] * vol[1]) >> 16;
samples += 2;
}
}
{
for (i = 0;i < count;i++)
{
- paintbuffer[i].sample[0] += (samples[0] * vol[0]) >> 16;
- paintbuffer[i].sample[1] += (samples[0] * vol[1]) >> 16;
- paintbuffer[i].sample[2] += (samples[0] * vol[2]) >> 16;
- paintbuffer[i].sample[3] += (samples[0] * vol[3]) >> 16;
- paintbuffer[i].sample[4] += (samples[0] * vol[4]) >> 16;
- paintbuffer[i].sample[5] += (samples[0] * vol[5]) >> 16;
- paintbuffer[i].sample[6] += (samples[0] * vol[6]) >> 16;
- paintbuffer[i].sample[7] += (samples[0] * vol[7]) >> 16;
+ paint[i].sample[0] += (samples[0] * vol[0]) >> 16;
+ paint[i].sample[1] += (samples[0] * vol[1]) >> 16;
+ paint[i].sample[2] += (samples[0] * vol[2]) >> 16;
+ paint[i].sample[3] += (samples[0] * vol[3]) >> 16;
+ paint[i].sample[4] += (samples[0] * vol[4]) >> 16;
+ paint[i].sample[5] += (samples[0] * vol[5]) >> 16;
+ paint[i].sample[6] += (samples[0] * vol[6]) >> 16;
+ paint[i].sample[7] += (samples[0] * vol[7]) >> 16;
samples += 1;
}
}
{
for (i = 0;i < count;i++)
{
- paintbuffer[i].sample[0] += (samples[0] * vol[0]) >> 16;
- paintbuffer[i].sample[1] += (samples[0] * vol[1]) >> 16;
- paintbuffer[i].sample[2] += (samples[0] * vol[2]) >> 16;
- paintbuffer[i].sample[3] += (samples[0] * vol[3]) >> 16;
- paintbuffer[i].sample[4] += (samples[0] * vol[4]) >> 16;
- paintbuffer[i].sample[5] += (samples[0] * vol[5]) >> 16;
+ paint[i].sample[0] += (samples[0] * vol[0]) >> 16;
+ paint[i].sample[1] += (samples[0] * vol[1]) >> 16;
+ paint[i].sample[2] += (samples[0] * vol[2]) >> 16;
+ paint[i].sample[3] += (samples[0] * vol[3]) >> 16;
+ paint[i].sample[4] += (samples[0] * vol[4]) >> 16;
+ paint[i].sample[5] += (samples[0] * vol[5]) >> 16;
samples += 1;
}
}
{
for (i = 0;i < count;i++)
{
- paintbuffer[i].sample[0] += (samples[0] * vol[0]) >> 16;
- paintbuffer[i].sample[1] += (samples[0] * vol[1]) >> 16;
- paintbuffer[i].sample[2] += (samples[0] * vol[2]) >> 16;
- paintbuffer[i].sample[3] += (samples[0] * vol[3]) >> 16;
+ paint[i].sample[0] += (samples[0] * vol[0]) >> 16;
+ paint[i].sample[1] += (samples[0] * vol[1]) >> 16;
+ paint[i].sample[2] += (samples[0] * vol[2]) >> 16;
+ paint[i].sample[3] += (samples[0] * vol[3]) >> 16;
samples += 1;
}
}
{
for (i = 0;i < count;i++)
{
- paintbuffer[i].sample[0] += (samples[0] * vol[0]) >> 16;
- paintbuffer[i].sample[1] += (samples[0] * vol[1]) >> 16;
+ paint[i].sample[0] += (samples[0] * vol[0]) >> 16;
+ paint[i].sample[1] += (samples[0] * vol[1]) >> 16;
samples += 1;
}
}
return false; // unsupported number of channels in sound
}
}
-
- ch->pos += count;
return true;
}
-void S_PaintChannels (snd_ringbuffer_t* rb, unsigned int starttime, unsigned int endtime)
+void S_MixToBuffer(void *stream, unsigned int bufferframes)
{
- unsigned int paintedtime;
+ unsigned int i;
+ channel_t *ch;
+ unsigned int frames;
+ unsigned char *outbytes = (unsigned char *) stream;
- paintedtime = starttime;
- while (paintedtime < endtime)
+ // mix as many times as needed to fill the requested buffer
+ while (bufferframes)
{
- unsigned int partialend, i, framecount;
- channel_t *ch;
-
- // if paintbuffer is too small
- if (endtime > paintedtime + PAINTBUFFER_SIZE)
- partialend = paintedtime + PAINTBUFFER_SIZE;
- else
- partialend = endtime;
+ // limit to the size of the paint buffer
+ frames = min(bufferframes, PAINTBUFFER_SIZE);
// clear the paint buffer
- memset (paintbuffer, 0, (partialend - paintedtime) * sizeof (paintbuffer[0]));
+ memset (paintbuffer, 0, frames * 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;
+ int ltime;
+ 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 = 0;
+ 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, (int)frames - ltime);
+ ch->pos += count;
+ ltime += count;
}
- ltime = paintedtime;
- while (ltime < partialend)
+ while (ltime < (int)frames)
{
- 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, (int)frames - 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, paintbuffer + ltime, 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, false);
+ break;
}
- // channel just stopped
- else
- stop_paint = true;
- }
-
- if (stop_paint)
- {
- S_StopChannel (ch - channels);
- break;
}
}
}
- S_CaptureAVISound (partialend - paintedtime);
- framecount = S_TransferPaintBuffer (rb, paintedtime, partialend);
- paintedtime += framecount;
+ if (!snd_usethreadedmixing)
+ S_CaptureAVISound(frames);
- // If there was not enough free space in the sound buffer, stop here
- if (paintedtime != partialend)
- {
- Con_DPrintf(">> S_PaintChannels: Not enough free space in the sound buffer ( %u != %u)\n", paintedtime, partialend);
- break;
- }
+ S_ConvertPaintBuffer(paintbuffer, outbytes, frames, snd_renderbuffer->format.width, snd_renderbuffer->format.channels);
+
+ // advance the output pointer
+ outbytes += frames * snd_renderbuffer->format.width * snd_renderbuffer->format.channels;
+ bufferframes -= frames;
}
}