Quake II RTX doxygen  1.0 dev
mix.c File Reference
#include "sound.h"

Go to the source code of this file.

Macros

#define PAINTBUFFER_SIZE   2048
 

Functions

static void WriteLinearBlast (int16_t *out, samplepair_t *samp, int count)
 
static void TransferStereo16 (samplepair_t *samp, int endtime)
 
static void TransferStereo (samplepair_t *samp, int endtime)
 
static void TransferPaintBuffer (samplepair_t *samp, int endtime)
 
static void Paint8 (channel_t *ch, sfxcache_t *sc, int count, samplepair_t *samp)
 
static void Paint16 (channel_t *ch, sfxcache_t *sc, int count, samplepair_t *samp)
 
void S_PaintChannels (int endtime)
 
void S_InitScaletable (void)
 
void S_RawSamples (int samples, int rate, int width, int channels, byte *data, float volume)
 
void S_UnqueueRawSamples ()
 

Variables

static int snd_scaletable [32][256]
 
static int snd_vol
 
samplepair_t s_rawsamples [S_MAX_RAW_SAMPLES]
 
int s_rawend = 0
 

Macro Definition Documentation

◆ PAINTBUFFER_SIZE

#define PAINTBUFFER_SIZE   2048

Definition at line 22 of file mix.c.

Function Documentation

◆ Paint16()

static void Paint16 ( channel_t ch,
sfxcache_t sc,
int  count,
samplepair_t samp 
)
static

Definition at line 156 of file mix.c.

157 {
158  int data;
159  int left, right;
160  int leftvol, rightvol;
161  int16_t *sfx;
162  int i;
163 
164  leftvol = ch->leftvol * snd_vol;
165  rightvol = ch->rightvol * snd_vol;
166  sfx = (int16_t *)sc->data + ch->pos;
167 
168  for (i = 0; i < count; i++, samp++) {
169  data = *sfx++;
170  left = (data * leftvol) >> 8;
171  right = (data * rightvol) >> 8;
172  samp->left += left;
173  samp->right += right;
174  }
175 
176  ch->pos += count;
177 }

Referenced by S_PaintChannels().

◆ Paint8()

static void Paint8 ( channel_t ch,
sfxcache_t sc,
int  count,
samplepair_t samp 
)
static

Definition at line 131 of file mix.c.

132 {
133  int data;
134  int *lscale, *rscale;
135  uint8_t *sfx;
136  int i;
137 
138  if (ch->leftvol > 255)
139  ch->leftvol = 255;
140  if (ch->rightvol > 255)
141  ch->rightvol = 255;
142 
143  lscale = snd_scaletable[ch->leftvol >> 3];
144  rscale = snd_scaletable[ch->rightvol >> 3];
145  sfx = (uint8_t *)sc->data + ch->pos;
146 
147  for (i = 0; i < count; i++, samp++) {
148  data = *sfx++;
149  samp->left += lscale[data];
150  samp->right += rscale[data];
151  }
152 
153  ch->pos += count;
154 }

Referenced by S_PaintChannels().

◆ S_InitScaletable()

void S_InitScaletable ( void  )

Definition at line 281 of file mix.c.

282 {
283  int i, j;
284  int scale;
285 
286  snd_vol = S_GetLinearVolume(s_volume->value) * 256;
287  for (i = 0; i < 32; i++) {
288  scale = i * 8 * snd_vol;
289  for (j = 0; j < 256; j++) {
290  snd_scaletable[i][j] = (j - 128) * scale;
291  }
292  }
293 
294  s_volume->modified = qfalse;
295 }

Referenced by DMA_Init(), and S_Update().

◆ S_PaintChannels()

void S_PaintChannels ( int  endtime)

Definition at line 179 of file mix.c.

180 {
181  samplepair_t paintbuffer[PAINTBUFFER_SIZE];
182  int i;
183  int end;
184  channel_t *ch;
185  sfxcache_t *sc;
186  int ltime, count;
187  playsound_t *ps;
188 
189  while (paintedtime < endtime) {
190  // if paintbuffer is smaller than DMA buffer
191  end = endtime;
192  if (end - paintedtime > PAINTBUFFER_SIZE)
194 
195  // start any playsounds
196  while (1) {
197  ps = s_pendingplays.next;
198  if (ps == &s_pendingplays)
199  break; // no more pending sounds
200  if (ps->begin <= paintedtime) {
201  S_IssuePlaysound(ps);
202  continue;
203  }
204 
205  if (ps->begin < end)
206  end = ps->begin; // stop here
207  break;
208  }
209 
210  // clear the paint buffer
211  memset(paintbuffer, 0, (end - paintedtime) * sizeof(samplepair_t));
212 
213  // paint in the channels.
214  ch = channels;
215  for (i = 0; i < s_numchannels; i++, ch++) {
216  ltime = paintedtime;
217 
218  while (ltime < end) {
219  if (!ch->sfx || (!ch->leftvol && !ch->rightvol))
220  break;
221 
222  // max painting is to the end of the buffer
223  count = end - ltime;
224 
225  // might be stopped by running out of data
226  if (ch->end - ltime < count)
227  count = ch->end - ltime;
228 
229  sc = S_LoadSound(ch->sfx);
230  if (!sc)
231  break;
232 
233  if (count > 0 && ch->sfx) {
234  samplepair_t *samp = &paintbuffer[ltime - paintedtime];
235  if (sc->width == 1)
236  Paint8(ch, sc, count, samp);
237  else
238  Paint16(ch, sc, count, samp);
239 
240  ltime += count;
241  }
242 
243  // if at end of loop, restart
244  if (ltime >= ch->end) {
245  if (ch->autosound) {
246  // autolooping sounds always go back to start
247  ch->pos = 0;
248  ch->end = ltime + sc->length;
249  } else if (sc->loopstart >= 0) {
250  ch->pos = sc->loopstart;
251  ch->end = ltime + sc->length - ch->pos;
252  } else {
253  // channel just stopped
254  ch->sfx = NULL;
255  }
256  }
257  }
258 
259  }
260 
261  if (s_rawend >= paintedtime)
262  {
263  /* add from the streaming sound source */
264  int stop = (end < s_rawend) ? end : s_rawend;
265 
266  for (int i = paintedtime; i < stop; i++)
267  {
268  int s = i & (S_MAX_RAW_SAMPLES - 1);
269  paintbuffer[i - paintedtime].left += s_rawsamples[s].left;
270  paintbuffer[i - paintedtime].right += s_rawsamples[s].right;
271  }
272  }
273 
274  // transfer out according to DMA format
275  TransferPaintBuffer(paintbuffer, end);
276  paintedtime = end;
277  }
278 }

Referenced by DMA_Update().

◆ S_RawSamples()

void S_RawSamples ( int  samples,
int  rate,
int  width,
int  channels,
byte *  data,
float  volume 
)

Definition at line 303 of file mix.c.

305 {
306  if (!s_started) return;
307 
308  if (s_started == SS_OAL)
309  {
310  AL_RawSamples(samples, rate, width, channels, data, volume);
311  return;
312  }
313 
314  if (s_rawend < paintedtime)
316 
317  // mimic the OpenAL behavior: s_volume is master volume
318  volume *= s_volume->value;
319 
320  // rescale because ogg is always 44100 and dma is configurable via s_khz
321  float scale = (float)rate / dma.speed;
322  int intVolume = (int)(256 * volume);
323 
324  if ((channels == 2) && (width == 2))
325  {
326  for (int i = 0; ; i++)
327  {
328  int src = (int)(i * scale);
329 
330  if (src >= samples)
331  {
332  break;
333  }
334 
335  int dst = s_rawend & (S_MAX_RAW_SAMPLES - 1);
336  s_rawend++;
337  s_rawsamples[dst].left = ((short *)data)[src * 2] * intVolume;
338  s_rawsamples[dst].right = ((short *)data)[src * 2 + 1] * intVolume;
339  }
340  }
341  else if ((channels == 1) && (width == 2))
342  {
343  for (int i = 0; ; i++)
344  {
345  int src = (int)(i * scale);
346 
347  if (src >= samples)
348  {
349  break;
350  }
351 
352  int dst = s_rawend & (S_MAX_RAW_SAMPLES - 1);
353  s_rawend++;
354  s_rawsamples[dst].left = ((short *)data)[src] * intVolume;
355  s_rawsamples[dst].right = ((short *)data)[src] * intVolume;
356  }
357  }
358  else if ((channels == 2) && (width == 1))
359  {
360  intVolume *= 256;
361 
362  for (int i = 0; ; i++)
363  {
364  int src = (int)(i * scale);
365 
366  if (src >= samples)
367  {
368  break;
369  }
370 
371  int dst = s_rawend & (S_MAX_RAW_SAMPLES - 1);
372  s_rawend++;
373  s_rawsamples[dst].left =
374  (((byte *)data)[src * 2] - 128) * intVolume;
375  s_rawsamples[dst].right =
376  (((byte *)data)[src * 2 + 1] - 128) * intVolume;
377  }
378  }
379  else if ((channels == 1) && (width == 1))
380  {
381  intVolume *= 256;
382 
383  for (int i = 0; ; i++)
384  {
385  int src = (int)(i * scale);
386 
387  if (src >= samples)
388  {
389  break;
390  }
391 
392  int dst = s_rawend & (S_MAX_RAW_SAMPLES - 1);
393  s_rawend++;
394  s_rawsamples[dst].left = (((byte *)data)[src] - 128) * intVolume;
395  s_rawsamples[dst].right = (((byte *)data)[src] - 128) * intVolume;
396  }
397  }
398 }

Referenced by OGG_Read(), and SCR_ReadNextFrame().

◆ S_UnqueueRawSamples()

void S_UnqueueRawSamples ( )

Definition at line 400 of file mix.c.

401 {
402 #ifdef USE_OPENAL
403  if (s_started == SS_OAL)
404  {
406  }
407 #endif
408 }

Referenced by SCR_RunCinematic(), and SCR_StopCinematic().

◆ TransferPaintBuffer()

static void TransferPaintBuffer ( samplepair_t samp,
int  endtime 
)
static

Definition at line 102 of file mix.c.

103 {
104  if (s_testsound->integer) {
105  int i;
106 
107  // write a fixed sine wave
108  for (i = paintedtime; i < endtime; i++) {
109  samp[i].left = samp[i].right = sin(i * 0.1) * 20000 * 256;
110  }
111  }
112 
113  if (dma.samplebits == 16 && dma.channels == 2) {
114  // optimized case
115  TransferStereo16(samp, endtime);
116  } else {
117  // general case
118  TransferStereo(samp, endtime);
119  }
120 }

Referenced by S_PaintChannels().

◆ TransferStereo()

static void TransferStereo ( samplepair_t samp,
int  endtime 
)
static

Definition at line 68 of file mix.c.

69 {
70  int out_idx, out_mask;
71  int count;
72  int *p, val;
73  int step;
74 
75  p = (int *)samp;
76  count = (endtime - paintedtime) * dma.channels;
77  out_mask = dma.samples - 1;
78  out_idx = paintedtime * dma.channels & out_mask;
79  step = 3 - dma.channels;
80 
81  if (dma.samplebits == 16) {
82  int16_t *out = (int16_t *)dma.buffer;
83  while (count--) {
84  val = *p >> 8;
85  p += step;
86  clamp(val, INT16_MIN, INT16_MAX);
87  out[out_idx] = val;
88  out_idx = (out_idx + 1) & out_mask;
89  }
90  } else if (dma.samplebits == 8) {
91  uint8_t *out = (uint8_t *)dma.buffer;
92  while (count--) {
93  val = *p >> 8;
94  p += step;
95  clamp(val, INT16_MIN, INT16_MAX);
96  out[out_idx] = (val >> 8) + 128;
97  out_idx = (out_idx + 1) & out_mask;
98  }
99  }
100 }

Referenced by TransferPaintBuffer().

◆ TransferStereo16()

static void TransferStereo16 ( samplepair_t samp,
int  endtime 
)
static

Definition at line 43 of file mix.c.

44 {
45  int lpos;
46  int ltime;
47  int16_t *out;
48  int count;
49 
50  for (ltime = paintedtime; ltime < endtime;) {
51  // handle recirculating buffer issues
52  lpos = ltime & ((dma.samples >> 1) - 1);
53 
54  out = (int16_t *)dma.buffer + (lpos << 1);
55 
56  count = (dma.samples >> 1) - lpos;
57  if (ltime + count > endtime)
58  count = endtime - ltime;
59 
60  // write a linear blast of samples
61  WriteLinearBlast(out, samp, count);
62 
63  samp += count;
64  ltime += count;
65  }
66 }

Referenced by TransferPaintBuffer().

◆ WriteLinearBlast()

static void WriteLinearBlast ( int16_t *  out,
samplepair_t samp,
int  count 
)
static

Definition at line 30 of file mix.c.

31 {
32  int i, val;
33 
34  for (i = 0; i < count; i++, samp++, out += 2) {
35  val = samp->left >> 8;
36  out[0] = clamp(val, INT16_MIN, INT16_MAX);
37 
38  val = samp->right >> 8;
39  out[1] = clamp(val, INT16_MIN, INT16_MAX);
40  }
41 }

Referenced by TransferStereo16().

Variable Documentation

◆ s_rawend

int s_rawend = 0

Definition at line 28 of file mix.c.

Referenced by AL_RawSamples(), OGG_Stream(), S_PaintChannels(), and S_RawSamples().

◆ s_rawsamples

Definition at line 27 of file mix.c.

Referenced by S_PaintChannels(), and S_RawSamples().

◆ snd_scaletable

int snd_scaletable[32][256]
static

Definition at line 24 of file mix.c.

Referenced by Paint8(), and S_InitScaletable().

◆ snd_vol

int snd_vol
static

Definition at line 25 of file mix.c.

Referenced by Paint16(), and S_InitScaletable().

edict_s::s
entity_state_t s
Definition: g_local.h:954
edict_s::volume
float volume
Definition: g_local.h:1073
Paint16
static void Paint16(channel_t *ch, sfxcache_t *sc, int count, samplepair_t *samp)
Definition: mix.c:156
dma
dma_t dma
Definition: dma.c:22
edict_s::count
int count
Definition: g_local.h:1057
playsound_s
Definition: sound.h:55
TransferStereo16
static void TransferStereo16(samplepair_t *samp, int endtime)
Definition: mix.c:43
samplepair_s::left
int left
Definition: sound.h:29
channels
channel_t channels[MAX_CHANNELS]
Definition: main.c:29
PAINTBUFFER_SIZE
#define PAINTBUFFER_SIZE
Definition: mix.c:22
snd_vol
static int snd_vol
Definition: mix.c:25
samplepair_s::right
int right
Definition: sound.h:30
channel_s::end
int end
Definition: sound.h:72
TransferPaintBuffer
static void TransferPaintBuffer(samplepair_t *samp, int endtime)
Definition: mix.c:102
sfxcache_s::length
int length
Definition: sound.h:34
paintedtime
int paintedtime
Definition: main.c:43
playsound_s::begin
unsigned begin
Definition: sound.h:64
snd_scaletable
static int snd_scaletable[32][256]
Definition: mix.c:24
s_rawsamples
samplepair_t s_rawsamples[S_MAX_RAW_SAMPLES]
Definition: mix.c:27
width
static int width
Definition: physical_sky.c:38
AL_UnqueueRawSamples
void AL_UnqueueRawSamples()
Definition: al.c:562
s_testsound
cvar_t * s_testsound
Definition: dma.c:25
TransferStereo
static void TransferStereo(samplepair_t *samp, int endtime)
Definition: mix.c:68
channel_s::pos
int pos
Definition: sound.h:73
playsound_s::next
struct playsound_s * next
Definition: sound.h:56
samplepair_s
Definition: sound.h:28
s_numchannels
int s_numchannels
Definition: main.c:30
S_IssuePlaysound
void S_IssuePlaysound(playsound_t *ps)
Definition: main.c:759
channel_s::autosound
qboolean autosound
Definition: sound.h:81
sfxcache_s::data
byte data[1]
Definition: sound.h:41
S_LoadSound
sfxcache_t * S_LoadSound(sfx_t *s)
Definition: mem.c:288
sfxcache_s::loopstart
int loopstart
Definition: sound.h:35
channel_s::sfx
sfx_t * sfx
Definition: sound.h:69
sfxcache_s
Definition: sound.h:33
channel_s::rightvol
int rightvol
Definition: sound.h:71
s_volume
cvar_t * s_volume
Definition: main.c:58
channel_s::leftvol
int leftvol
Definition: sound.h:70
s_pendingplays
playsound_t s_pendingplays
Definition: main.c:56
AL_RawSamples
void AL_RawSamples(int samples, int rate, int width, int channels, byte *data, float volume)
Definition: al.c:505
right
static vec3_t right
Definition: p_view.c:27
s_rawend
int s_rawend
Definition: mix.c:28
channel_s
Definition: sound.h:68
samples
unsigned samples[LAG_WIDTH]
Definition: screen.c:528
S_MAX_RAW_SAMPLES
#define S_MAX_RAW_SAMPLES
Definition: sound.h:154
S_GetLinearVolume
float S_GetLinearVolume(float perceptual)
Definition: main.c:1171
s_started
sndstarted_t s_started
Definition: main.c:32
int
CONST PIXELFORMATDESCRIPTOR int
Definition: wgl.c:26
sfxcache_s::width
int width
Definition: sound.h:36
Paint8
static void Paint8(channel_t *ch, sfxcache_t *sc, int count, samplepair_t *samp)
Definition: mix.c:131
WriteLinearBlast
static void WriteLinearBlast(int16_t *out, samplepair_t *samp, int count)
Definition: mix.c:30