ReactOS  0.4.14-dev-376-gaedba84
mixer.c File Reference
#include "dsound_private.h"
Include dependency graph for mixer.c:

Go to the source code of this file.

Functions

void DSOUND_RecalcVolPan (PDSVOLUMEPAN volpan)
 
void DSOUND_AmpFactorToVolPan (PDSVOLUMEPAN volpan)
 
DWORD DSOUND_bufpos_to_mixpos (const DirectSoundDevice *device, DWORD pos)
 
DWORD DSOUND_secpos_to_bufpos (const IDirectSoundBufferImpl *dsb, DWORD secpos, DWORD secmixpos, DWORD *overshot)
 
static DWORD DSOUND_bufpos_to_secpos (const IDirectSoundBufferImpl *dsb, DWORD bufpos)
 
static void DSOUND_RecalcFreqAcc (IDirectSoundBufferImpl *dsb)
 
void DSOUND_RecalcFormat (IDirectSoundBufferImpl *dsb)
 
void DSOUND_CheckEvent (const IDirectSoundBufferImpl *dsb, DWORD playpos, int len)
 
static void cp_fields (const IDirectSoundBufferImpl *dsb, const BYTE *ibuf, BYTE *obuf, UINT istride, UINT ostride, UINT count, UINT freqAcc, UINT adj)
 
static DWORD DSOUND_BufPtrDiff (DWORD buflen, DWORD ptr1, DWORD ptr2)
 
void DSOUND_MixToTemporary (const IDirectSoundBufferImpl *dsb, DWORD writepos, DWORD len, BOOL inmixer)
 
static LPBYTE DSOUND_MixerVol (const IDirectSoundBufferImpl *dsb, INT len)
 
static DWORD DSOUND_MixInBuffer (IDirectSoundBufferImpl *dsb, DWORD writepos, DWORD fraglen)
 
static DWORD DSOUND_MixOne (IDirectSoundBufferImpl *dsb, DWORD writepos, DWORD mixlen)
 
static DWORD DSOUND_MixToPrimary (const DirectSoundDevice *device, DWORD writepos, DWORD mixlen, BOOL recover, BOOL *all_stopped)
 
static void DSOUND_WaveQueue (DirectSoundDevice *device, BOOL force)
 
static void DSOUND_PerformMix (DirectSoundDevice *device)
 
void CALLBACK DSOUND_timer (UINT timerID, UINT msg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2)
 
void CALLBACK DSOUND_callback (HWAVEOUT hwo, UINT msg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2)
 

Function Documentation

◆ cp_fields()

static void cp_fields ( const IDirectSoundBufferImpl dsb,
const BYTE ibuf,
BYTE obuf,
UINT  istride,
UINT  ostride,
UINT  count,
UINT  freqAcc,
UINT  adj 
)
inlinestatic

Copy a single frame from the given input buffer to the given output buffer. Translate 8 <-> 16 bits and mono <-> stereo

Definition at line 271 of file mixer.c.

273 {
275  INT istep = dsb->pwfx->wBitsPerSample / 8, ostep = device->pwfx->wBitsPerSample / 8;
276 
277  if (device->pwfx->nChannels == dsb->pwfx->nChannels ||
278  (device->pwfx->nChannels == 2 && dsb->pwfx->nChannels == 6) ||
279  (device->pwfx->nChannels == 8 && dsb->pwfx->nChannels == 2) ||
280  (device->pwfx->nChannels == 6 && dsb->pwfx->nChannels == 2)) {
281  dsb->convert(ibuf, obuf, istride, ostride, count, freqAcc, adj);
282  if (device->pwfx->nChannels == 2 || dsb->pwfx->nChannels == 2)
283  dsb->convert(ibuf + istep, obuf + ostep, istride, ostride, count, freqAcc, adj);
284  return;
285  }
286 
287  if (device->pwfx->nChannels == 1 && dsb->pwfx->nChannels == 2)
288  {
289  dsb->convert(ibuf, obuf, istride, ostride, count, freqAcc, adj);
290  return;
291  }
292 
293  if (device->pwfx->nChannels == 2 && dsb->pwfx->nChannels == 1)
294  {
295  dsb->convert(ibuf, obuf, istride, ostride, count, freqAcc, adj);
296  dsb->convert(ibuf, obuf + ostep, istride, ostride, count, freqAcc, adj);
297  return;
298  }
299 
300  WARN("Unable to remap channels: device=%u, buffer=%u\n", device->pwfx->nChannels,
301  dsb->pwfx->nChannels);
302 }
GLuint GLuint GLsizei count
Definition: gl.h:1545
static DWORD DWORD istep
Definition: cursoricon.c:1521
WORD nChannels
Definition: mmreg.h:79
#define WARN(fmt,...)
Definition: debug.h:111
int32_t INT
Definition: typedefs.h:56
Definition: devices.h:37
bitsconvertfunc convert
DirectSoundDevice * device
static char obuf[100]
Definition: i386-dis.c:1266
WORD wBitsPerSample
Definition: mmreg.h:83

Referenced by DSOUND_MixToTemporary().

◆ DSOUND_AmpFactorToVolPan()

void DSOUND_AmpFactorToVolPan ( PDSVOLUMEPAN  volpan)

Definition at line 46 of file mixer.c.

47 {
48  double left,right;
49  TRACE("(%p)\n",volpan);
50 
51  TRACE("left=%x, right=%x\n",volpan->dwTotalLeftAmpFactor,volpan->dwTotalRightAmpFactor);
52  if (volpan->dwTotalLeftAmpFactor==0)
53  left=-10000;
54  else
55  left=600 * log(((double)volpan->dwTotalLeftAmpFactor) / 0xffff) / log(2);
56  if (volpan->dwTotalRightAmpFactor==0)
57  right=-10000;
58  else
59  right=600 * log(((double)volpan->dwTotalRightAmpFactor) / 0xffff) / log(2);
60  if (left<right)
61  {
62  volpan->lVolume=right;
63  volpan->dwVolAmpFactor=volpan->dwTotalRightAmpFactor;
64  }
65  else
66  {
67  volpan->lVolume=left;
68  volpan->dwVolAmpFactor=volpan->dwTotalLeftAmpFactor;
69  }
70  if (volpan->lVolume < -10000)
71  volpan->lVolume=-10000;
72  volpan->lPan=right-left;
73  if (volpan->lPan < -10000)
74  volpan->lPan=-10000;
75 
76  TRACE("Vol=%d Pan=%d\n", volpan->lVolume, volpan->lPan);
77 }
DWORD dwTotalRightAmpFactor
Definition: dsdriver.h:106
#define TRACE(s)
Definition: solgame.cpp:4
GLint left
Definition: glext.h:7726
GLdouble GLdouble right
Definition: glext.h:10859
DWORD dwVolAmpFactor
Definition: dsdriver.h:108
DWORD dwTotalLeftAmpFactor
Definition: dsdriver.h:105
LONG lVolume
Definition: dsdriver.h:107
#define log(outFile, fmt,...)
Definition: util.h:15

Referenced by PrimaryBufferImpl_GetPan(), PrimaryBufferImpl_GetVolume(), PrimaryBufferImpl_SetPan(), and PrimaryBufferImpl_SetVolume().

◆ DSOUND_bufpos_to_mixpos()

DWORD DSOUND_bufpos_to_mixpos ( const DirectSoundDevice device,
DWORD  pos 
)

Convert a primary buffer position to a pointer position for device->mix_buffer device: DirectSoundDevice for which to calculate pos: Primary buffer position to converts Returns: Offset for mix_buffer

Definition at line 84 of file mixer.c.

85 {
86  DWORD ret = pos * 32 / device->pwfx->wBitsPerSample;
87  if (device->pwfx->wBitsPerSample == 32)
88  ret *= 2;
89  return ret;
90 }
Definition: devices.h:37
unsigned long DWORD
Definition: ntddk_ex.h:95
int ret

Referenced by DSOUND_MixInBuffer(), DSOUND_PerformMix(), DSOUND_PrimaryOpen(), and primarybuffer_SetFormat().

◆ DSOUND_bufpos_to_secpos()

static DWORD DSOUND_bufpos_to_secpos ( const IDirectSoundBufferImpl dsb,
DWORD  bufpos 
)
static

Convert a resampled pointer that fits for primary to a 'native' sample pointer freqAccNext is used here rather than freqAcc: In case the app wants to fill up to the play position it won't overwrite it

Definition at line 125 of file mixer.c.

126 {
127  DWORD oAdv = dsb->device->pwfx->nBlockAlign, iAdv = dsb->pwfx->nBlockAlign, pos;
128  DWORD64 framelen;
129  DWORD64 acc;
130 
131  framelen = bufpos/oAdv;
132  acc = framelen * (DWORD64)dsb->freqAdjust + (DWORD64)dsb->freqAccNext;
133  acc = acc >> DSOUND_FREQSHIFT;
134  pos = (DWORD)acc * iAdv;
135  if (pos >= dsb->buflen)
136  /* Because of differences between freqAcc and freqAccNext, this might happen */
137  pos = dsb->buflen - iAdv;
138  TRACE("Converted %d/%d to %d/%d\n", bufpos, dsb->tmp_buffer_len, pos, dsb->buflen);
139  return pos;
140 }
#define DWORD
Definition: nt_native.h:44
PWAVEFORMATEX pwfx
#define DSOUND_FREQSHIFT
#define TRACE(s)
Definition: solgame.cpp:4
unsigned long DWORD
Definition: ntddk_ex.h:95
DirectSoundDevice * device
uint64_t DWORD64
Definition: typedefs.h:65
WORD nBlockAlign
Definition: mmreg.h:82

Referenced by DSOUND_MixInBuffer().

◆ DSOUND_BufPtrDiff()

static DWORD DSOUND_BufPtrDiff ( DWORD  buflen,
DWORD  ptr1,
DWORD  ptr2 
)
inlinestatic

Calculate the distance between two buffer offsets, taking wraparound into account.

Definition at line 308 of file mixer.c.

309 {
310 /* If these asserts fail, the problem is not here, but in the underlying code */
311  assert(ptr1 < buflen);
312  assert(ptr2 < buflen);
313  if (ptr1 >= ptr2) {
314  return ptr1 - ptr2;
315  } else {
316  return buflen + ptr1 - ptr2;
317  }
318 }
#define assert(x)
Definition: debug.h:53

Referenced by DSOUND_MixInBuffer(), DSOUND_MixOne(), and DSOUND_PerformMix().

◆ DSOUND_callback()

void CALLBACK DSOUND_callback ( HWAVEOUT  hwo,
UINT  msg,
DWORD_PTR  dwUser,
DWORD_PTR  dw1,
DWORD_PTR  dw2 
)

Definition at line 1011 of file mixer.c.

1012 {
1014  TRACE("(%p,%x,%lx,%lx,%lx)\n",hwo,msg,dwUser,dw1,dw2);
1015  TRACE("entering at %d, msg=%08x(%s)\n", GetTickCount(), msg,
1016  msg==MM_WOM_DONE ? "MM_WOM_DONE" : msg==MM_WOM_CLOSE ? "MM_WOM_CLOSE" :
1017  msg==MM_WOM_OPEN ? "MM_WOM_OPEN" : "UNKNOWN");
1018 
1019  /* check if packet completed from wave driver */
1020  if (msg == MM_WOM_DONE) {
1021 
1022  /* **** */
1023  EnterCriticalSection(&(device->mixlock));
1024 
1025  TRACE("done playing primary pos=%d\n", device->pwplay * device->fraglen);
1026 
1027  /* update playpos */
1028  device->pwplay++;
1029  device->pwplay %= device->helfrags;
1030 
1031  /* sanity */
1032  if(device->pwqueue == 0){
1033  ERR("Wave queue corrupted!\n");
1034  }
1035 
1036  /* update queue */
1037  device->pwqueue--;
1038 
1039  LeaveCriticalSection(&(device->mixlock));
1040  /* **** */
1041  }
1042  TRACE("completed\n");
1043 }
#define MM_WOM_OPEN
Definition: mmsystem.h:56
DWORD WINAPI GetTickCount(VOID)
Definition: time.c:445
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
#define MM_WOM_DONE
Definition: mmsystem.h:58
Definition: devices.h:37
#define TRACE(s)
Definition: solgame.cpp:4
#define MM_WOM_CLOSE
Definition: mmsystem.h:57
#define ERR(fmt,...)
Definition: debug.h:109
#define msg(x)
Definition: auth_time.c:54
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)

Referenced by DSOUND_ReopenDevice().

◆ DSOUND_CheckEvent()

void DSOUND_CheckEvent ( const IDirectSoundBufferImpl dsb,
DWORD  playpos,
int  len 
)

Check for application callback requests for when the play position reaches certain points.

The offsets that will be triggered will be those between the recorded "last played" position for the buffer (i.e. dsb->playpos) and "len" bytes beyond that position.

Definition at line 221 of file mixer.c.

222 {
223  int i;
224  DWORD offset;
226  TRACE("(%p,%d)\n",dsb,len);
227 
228  if (dsb->nrofnotifies == 0)
229  return;
230 
231  TRACE("(%p) buflen = %d, playpos = %d, len = %d\n",
232  dsb, dsb->buflen, playpos, len);
233  for (i = 0; i < dsb->nrofnotifies ; i++) {
234  event = dsb->notifies + i;
235  offset = event->dwOffset;
236  TRACE("checking %d, position %d, event = %p\n",
237  i, offset, event->hEventNotify);
238  /* DSBPN_OFFSETSTOP has to be the last element. So this is */
239  /* OK. [Inside DirectX, p274] */
240  /* Windows does not seem to enforce this, and some apps rely */
241  /* on that, so we can't stop there. */
242  /* */
243  /* This also means we can't sort the entries by offset, */
244  /* because DSBPN_OFFSETSTOP == -1 */
245  if (offset == DSBPN_OFFSETSTOP) {
246  if (dsb->state == STATE_STOPPED) {
247  SetEvent(event->hEventNotify);
248  TRACE("signalled event %p (%d)\n", event->hEventNotify, i);
249  }
250  continue;
251  }
252  if ((playpos + len) >= dsb->buflen) {
253  if ((offset < ((playpos + len) % dsb->buflen)) ||
254  (offset >= playpos)) {
255  TRACE("signalled event %p (%d)\n", event->hEventNotify, i);
256  SetEvent(event->hEventNotify);
257  }
258  } else {
259  if ((offset >= playpos) && (offset < (playpos + len))) {
260  TRACE("signalled event %p (%d)\n", event->hEventNotify, i);
261  SetEvent(event->hEventNotify);
262  }
263  }
264  }
265 }
GLintptr offset
Definition: glext.h:5920
#define DSBPN_OFFSETSTOP
Definition: dsound.h:876
BOOL WINAPI DECLSPEC_HOTPATCH SetEvent(IN HANDLE hEvent)
Definition: synch.c:733
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define STATE_STOPPED
#define TRACE(s)
Definition: solgame.cpp:4
unsigned long DWORD
Definition: ntddk_ex.h:95
GLenum GLsizei len
Definition: glext.h:6722
struct _cl_event * event
Definition: glext.h:7739
LPDSBPOSITIONNOTIFY notifies

Referenced by DSOUND_MixInBuffer(), DSOUND_MixToPrimary(), and IDirectSoundBufferImpl_Stop().

◆ DSOUND_MixerVol()

static LPBYTE DSOUND_MixerVol ( const IDirectSoundBufferImpl dsb,
INT  len 
)
static

Apply volume to the given soundbuffer from (primary) position writepos and length len Returns: NULL if no volume needs to be applied or else a memory handle that holds 'len' volume adjusted buffer

Definition at line 409 of file mixer.c.

410 {
411  INT i;
412  BYTE *bpc;
413  INT16 *bps, *mems;
414  DWORD vLeft, vRight;
415  INT nChannels = dsb->device->pwfx->nChannels;
416  LPBYTE mem = (dsb->tmp_buffer ? dsb->tmp_buffer : dsb->buffer->memory) + dsb->buf_mixpos;
417 
418  if (dsb->resampleinmixer)
419  mem = dsb->device->tmp_buffer;
420 
421  TRACE("(%p,%d)\n",dsb,len);
422  TRACE("left = %x, right = %x\n", dsb->volpan.dwTotalLeftAmpFactor,
424 
425  if ((!(dsb->dsbd.dwFlags & DSBCAPS_CTRLPAN) || (dsb->volpan.lPan == 0)) &&
426  (!(dsb->dsbd.dwFlags & DSBCAPS_CTRLVOLUME) || (dsb->volpan.lVolume == 0)) &&
427  !(dsb->dsbd.dwFlags & DSBCAPS_CTRL3D))
428  return NULL; /* Nothing to do */
429 
430  if (nChannels != 1 && nChannels != 2)
431  {
432  FIXME("There is no support for %d channels\n", nChannels);
433  return NULL;
434  }
435 
436  if (dsb->device->pwfx->wBitsPerSample != 8 && dsb->device->pwfx->wBitsPerSample != 16)
437  {
438  FIXME("There is no support for %d bpp\n", dsb->device->pwfx->wBitsPerSample);
439  return NULL;
440  }
441 
442  if (dsb->device->tmp_buffer_len < len || !dsb->device->tmp_buffer)
443  {
444  /* If we just resampled in DSOUND_MixToTemporary, we shouldn't need to resize here */
445  assert(!dsb->resampleinmixer);
446  dsb->device->tmp_buffer_len = len;
447  if (dsb->device->tmp_buffer)
449  else
451  }
452 
453  bpc = dsb->device->tmp_buffer;
454  bps = (INT16 *)bpc;
455  mems = (INT16 *)mem;
456  vLeft = dsb->volpan.dwTotalLeftAmpFactor;
457  if (nChannels > 1)
458  vRight = dsb->volpan.dwTotalRightAmpFactor;
459  else
460  vRight = vLeft;
461 
462  switch (dsb->device->pwfx->wBitsPerSample) {
463  case 8:
464  /* 8-bit WAV is unsigned, but we need to operate */
465  /* on signed data for this to work properly */
466  for (i = 0; i < len-1; i+=2) {
467  *(bpc++) = (((*(mem++) - 128) * vLeft) >> 16) + 128;
468  *(bpc++) = (((*(mem++) - 128) * vRight) >> 16) + 128;
469  }
470  if (len % 2 == 1 && nChannels == 1)
471  *(bpc++) = (((*(mem++) - 128) * vLeft) >> 16) + 128;
472  break;
473  case 16:
474  /* 16-bit WAV is signed -- much better */
475  for (i = 0; i < len-3; i += 4) {
476  *(bps++) = (*(mems++) * vLeft) >> 16;
477  *(bps++) = (*(mems++) * vRight) >> 16;
478  }
479  if (len % 4 == 2 && nChannels == 1)
480  *(bps++) = ((INT)*(mems++) * vLeft) >> 16;
481  break;
482  }
483  return dsb->device->tmp_buffer;
484 }
#define DSBCAPS_CTRLVOLUME
Definition: dsound.h:213
WORD nChannels
Definition: mmreg.h:79
#define assert(x)
Definition: debug.h:53
#define DSBCAPS_CTRLPAN
Definition: dsound.h:212
int nChannels
Definition: pcmconverter.c:95
int32_t INT
Definition: typedefs.h:56
PWAVEFORMATEX pwfx
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
unsigned char * LPBYTE
Definition: typedefs.h:52
#define FIXME(fmt,...)
Definition: debug.h:110
DWORD dwTotalRightAmpFactor
Definition: dsdriver.h:106
smooth NULL
Definition: ftsmooth.c:416
#define TRACE(s)
Definition: solgame.cpp:4
#define GetProcessHeap()
Definition: compat.h:403
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
if(!(yy_init))
Definition: macro.lex.yy.c:714
unsigned long DWORD
Definition: ntddk_ex.h:95
GLenum GLsizei len
Definition: glext.h:6722
unsigned char BYTE
Definition: mem.h:68
DirectSoundDevice * device
#define DSBCAPS_CTRL3D
Definition: dsound.h:210
#define HeapReAlloc
Definition: compat.h:401
Definition: mem.c:156
WORD wBitsPerSample
Definition: mmreg.h:83
DWORD dwTotalLeftAmpFactor
Definition: dsdriver.h:105
DWORD dwFlags
Definition: dsound.h:289
LONG lVolume
Definition: dsdriver.h:107
signed short INT16

Referenced by DSOUND_MixInBuffer().

◆ DSOUND_MixInBuffer()

static DWORD DSOUND_MixInBuffer ( IDirectSoundBufferImpl dsb,
DWORD  writepos,
DWORD  fraglen 
)
static

Mix (at most) the given number of bytes into the given position of the device buffer, from the secondary buffer "dsb" (starting at the current mix position for that buffer).

Returns the number of bytes actually mixed into the device buffer. This will match fraglen unless the end of the secondary buffer is reached (and it is not looping).

dsb = the secondary buffer to mix from writepos = position (offset) in device buffer to write at fraglen = number of bytes to mix

Definition at line 499 of file mixer.c.

500 {
501  INT len = fraglen, ilen;
502  BYTE *ibuf = (dsb->tmp_buffer ? dsb->tmp_buffer : dsb->buffer->memory) + dsb->buf_mixpos, *volbuf;
503  DWORD oldpos, mixbufpos;
504 
505  TRACE("buf_mixpos=%d/%d sec_mixpos=%d/%d\n", dsb->buf_mixpos, dsb->tmp_buffer_len, dsb->sec_mixpos, dsb->buflen);
506  TRACE("(%p,%d,%d)\n",dsb,writepos,fraglen);
507 
508  assert(dsb->buf_mixpos + len <= dsb->tmp_buffer_len);
509 
510  if (len % dsb->device->pwfx->nBlockAlign) {
511  INT nBlockAlign = dsb->device->pwfx->nBlockAlign;
512  ERR("length not a multiple of block size, len = %d, block size = %d\n", len, nBlockAlign);
513  len -= len % nBlockAlign; /* data alignment */
514  }
515 
516  /* Resample buffer to temporary buffer specifically allocated for this purpose, if needed */
518  if (dsb->resampleinmixer)
519  ibuf = dsb->device->tmp_buffer;
520 
521  /* Apply volume if needed */
522  volbuf = DSOUND_MixerVol(dsb, len);
523  if (volbuf)
524  ibuf = volbuf;
525 
526  mixbufpos = DSOUND_bufpos_to_mixpos(dsb->device, writepos);
527  /* Now mix the temporary buffer into the devices main buffer */
528  if ((writepos + len) <= dsb->device->buflen)
529  dsb->device->mixfunction(ibuf, dsb->device->mix_buffer + mixbufpos, len);
530  else
531  {
532  DWORD todo = dsb->device->buflen - writepos;
533  dsb->device->mixfunction(ibuf, dsb->device->mix_buffer + mixbufpos, todo);
534  dsb->device->mixfunction(ibuf + todo, dsb->device->mix_buffer, len - todo);
535  }
536 
537  oldpos = dsb->sec_mixpos;
538  dsb->buf_mixpos += len;
539 
540  if (dsb->buf_mixpos >= dsb->tmp_buffer_len) {
541  if (dsb->buf_mixpos > dsb->tmp_buffer_len)
542  ERR("Mixpos (%u) past buflen (%u), capping...\n", dsb->buf_mixpos, dsb->tmp_buffer_len);
543  if (dsb->playflags & DSBPLAY_LOOPING) {
544  dsb->buf_mixpos -= dsb->tmp_buffer_len;
545  } else if (dsb->buf_mixpos >= dsb->tmp_buffer_len) {
546  dsb->buf_mixpos = dsb->sec_mixpos = 0;
547  dsb->state = STATE_STOPPED;
548  }
550  }
551 
553  ilen = DSOUND_BufPtrDiff(dsb->buflen, dsb->sec_mixpos, oldpos);
554  /* check for notification positions */
556  dsb->state != STATE_STARTING) {
557  DSOUND_CheckEvent(dsb, oldpos, ilen);
558  }
559 
560  /* increase mix position */
561  dsb->primary_mixpos += len;
562  if (dsb->primary_mixpos >= dsb->device->buflen)
563  dsb->primary_mixpos -= dsb->device->buflen;
564  return len;
565 }
#define TRUE
Definition: types.h:120
static DWORD DSOUND_BufPtrDiff(DWORD buflen, DWORD ptr1, DWORD ptr2)
Definition: mixer.c:308
static void DSOUND_RecalcFreqAcc(IDirectSoundBufferImpl *dsb)
Definition: mixer.c:145
BOOL todo
Definition: filedlg.c:313
#define assert(x)
Definition: debug.h:53
int32_t INT
Definition: typedefs.h:56
PWAVEFORMATEX pwfx
#define STATE_STOPPED
#define DSBCAPS_CTRLPOSITIONNOTIFY
Definition: dsound.h:215
#define TRACE(s)
Definition: solgame.cpp:4
#define DSBPLAY_LOOPING
Definition: dsound.h:189
unsigned long DWORD
Definition: ntddk_ex.h:95
#define STATE_STARTING
GLenum GLsizei len
Definition: glext.h:6722
unsigned char BYTE
Definition: mem.h:68
DirectSoundDevice * device
#define ERR(fmt,...)
Definition: debug.h:109
void DSOUND_CheckEvent(const IDirectSoundBufferImpl *dsb, DWORD playpos, int len)
Definition: mixer.c:221
DWORD DSOUND_bufpos_to_mixpos(const DirectSoundDevice *device, DWORD pos)
Definition: mixer.c:84
static DWORD DSOUND_bufpos_to_secpos(const IDirectSoundBufferImpl *dsb, DWORD bufpos)
Definition: mixer.c:125
WORD nBlockAlign
Definition: mmreg.h:82
void DSOUND_MixToTemporary(const IDirectSoundBufferImpl *dsb, DWORD writepos, DWORD len, BOOL inmixer)
Definition: mixer.c:332
DWORD dwFlags
Definition: dsound.h:289
static LPBYTE DSOUND_MixerVol(const IDirectSoundBufferImpl *dsb, INT len)
Definition: mixer.c:409

Referenced by DSOUND_MixOne().

◆ DSOUND_MixOne()

static DWORD DSOUND_MixOne ( IDirectSoundBufferImpl dsb,
DWORD  writepos,
DWORD  mixlen 
)
static

Mix some frames from the given secondary buffer "dsb" into the device primary buffer.

dsb = the secondary buffer playpos = the current play position in the device buffer (primary buffer) writepos = the current safe-to-write position in the device buffer mixlen = the maximum number of bytes in the primary buffer to mix, from the current writepos.

Returns: the number of bytes beyond the writepos that were mixed.

Definition at line 579 of file mixer.c.

580 {
581  /* The buffer's primary_mixpos may be before or after the device
582  * buffer's mixpos, but both must be ahead of writepos. */
583  DWORD primary_done;
584 
585  TRACE("(%p,%d,%d)\n",dsb,writepos,mixlen);
586  TRACE("writepos=%d, buf_mixpos=%d, primary_mixpos=%d, mixlen=%d\n", writepos, dsb->buf_mixpos, dsb->primary_mixpos, mixlen);
587  TRACE("looping=%d, leadin=%d, buflen=%d\n", dsb->playflags, dsb->leadin, dsb->tmp_buffer_len);
588 
589  /* If leading in, only mix about 20 ms, and 'skip' mixing the rest, for more fluid pointer advancement */
590  if (dsb->leadin && dsb->state == STATE_STARTING)
591  {
592  if (mixlen > 2 * dsb->device->fraglen)
593  {
594  dsb->primary_mixpos += mixlen - 2 * dsb->device->fraglen;
595  dsb->primary_mixpos %= dsb->device->buflen;
596  }
597  }
598  dsb->leadin = FALSE;
599 
600  /* calculate how much pre-buffering has already been done for this buffer */
601  primary_done = DSOUND_BufPtrDiff(dsb->device->buflen, dsb->primary_mixpos, writepos);
602 
603  /* sanity */
604  if(mixlen < primary_done)
605  {
606  /* Should *NEVER* happen */
607  ERR("Fatal error. Under/Overflow? primary_done=%d, mixpos=%d/%d (%d/%d), primary_mixpos=%d, writepos=%d, mixlen=%d\n", primary_done,dsb->buf_mixpos,dsb->tmp_buffer_len,dsb->sec_mixpos, dsb->buflen, dsb->primary_mixpos, writepos, mixlen);
608  dsb->primary_mixpos = writepos + mixlen;
609  dsb->primary_mixpos %= dsb->device->buflen;
610  return mixlen;
611  }
612 
613  /* take into account already mixed data */
614  mixlen -= primary_done;
615 
616  TRACE("primary_done=%d, mixlen (primary) = %i\n", primary_done, mixlen);
617 
618  if (!mixlen)
619  return primary_done;
620 
621  /* First try to mix to the end of the buffer if possible
622  * Theoretically it would allow for better optimization
623  */
624  if (mixlen + dsb->buf_mixpos >= dsb->tmp_buffer_len)
625  {
626  DWORD newmixed, mixfirst = dsb->tmp_buffer_len - dsb->buf_mixpos;
627  newmixed = DSOUND_MixInBuffer(dsb, dsb->primary_mixpos, mixfirst);
628  mixlen -= newmixed;
629 
630  if (dsb->playflags & DSBPLAY_LOOPING)
631  while (newmixed && mixlen)
632  {
633  mixfirst = (dsb->tmp_buffer_len < mixlen ? dsb->tmp_buffer_len : mixlen);
634  newmixed = DSOUND_MixInBuffer(dsb, dsb->primary_mixpos, mixfirst);
635  mixlen -= newmixed;
636  }
637  }
638  else DSOUND_MixInBuffer(dsb, dsb->primary_mixpos, mixlen);
639 
640  /* re-calculate the primary done */
641  primary_done = DSOUND_BufPtrDiff(dsb->device->buflen, dsb->primary_mixpos, writepos);
642 
643  TRACE("new primary_mixpos=%d, total mixed data=%d\n", dsb->primary_mixpos, primary_done);
644 
645  /* Report back the total prebuffered amount for this buffer */
646  return primary_done;
647 }
static DWORD DSOUND_BufPtrDiff(DWORD buflen, DWORD ptr1, DWORD ptr2)
Definition: mixer.c:308
#define TRACE(s)
Definition: solgame.cpp:4
#define DSBPLAY_LOOPING
Definition: dsound.h:189
unsigned long DWORD
Definition: ntddk_ex.h:95
#define STATE_STARTING
DirectSoundDevice * device
#define ERR(fmt,...)
Definition: debug.h:109
static DWORD DSOUND_MixInBuffer(IDirectSoundBufferImpl *dsb, DWORD writepos, DWORD fraglen)
Definition: mixer.c:499

Referenced by DSOUND_MixToPrimary().

◆ DSOUND_MixToPrimary()

static DWORD DSOUND_MixToPrimary ( const DirectSoundDevice device,
DWORD  writepos,
DWORD  mixlen,
BOOL  recover,
BOOL all_stopped 
)
static

For a DirectSoundDevice, go through all the currently playing buffers and mix them in to the device buffer.

writepos = the current safe-to-write position in the primary buffer mixlen = the maximum amount to mix into the primary buffer (beyond the current writepos) recover = true if the sound device may have been reset and the write position in the device buffer changed all_stopped = reports back if all buffers have stopped

Returns: the length beyond the writepos that was mixed to.

Definition at line 663 of file mixer.c.

664 {
665  INT i, len;
666  DWORD minlen = 0;
668 
669  /* unless we find a running buffer, all have stopped */
670  *all_stopped = TRUE;
671 
672  TRACE("(%d,%d,%d)\n", writepos, mixlen, recover);
673  for (i = 0; i < device->nrofbuffers; i++) {
674  dsb = device->buffers[i];
675 
676  TRACE("MixToPrimary for %p, state=%d\n", dsb, dsb->state);
677 
678  if (dsb->buflen && dsb->state && !dsb->hwbuf) {
679  TRACE("Checking %p, mixlen=%d\n", dsb, mixlen);
681  /* if buffer is stopping it is stopped now */
682  if (dsb->state == STATE_STOPPING) {
683  dsb->state = STATE_STOPPED;
684  DSOUND_CheckEvent(dsb, 0, 0);
685  } else if (dsb->state != STATE_STOPPED) {
686 
687  /* if recovering, reset the mix position */
688  if ((dsb->state == STATE_STARTING) || recover) {
689  dsb->primary_mixpos = writepos;
690  }
691 
692  /* if the buffer was starting, it must be playing now */
693  if (dsb->state == STATE_STARTING)
694  dsb->state = STATE_PLAYING;
695 
696  /* mix next buffer into the main buffer */
697  len = DSOUND_MixOne(dsb, writepos, mixlen);
698 
699  if (!minlen) minlen = len;
700 
701  /* record the minimum length mixed from all buffers */
702  /* we only want to return the length which *all* buffers have mixed */
703  else if (len) minlen = (len < minlen) ? len : minlen;
704 
705  *all_stopped = FALSE;
706  }
707  RtlReleaseResource(&dsb->lock);
708  }
709  }
710 
711  TRACE("Mixed at least %d from all buffers\n", minlen);
712  return minlen;
713 }
static DWORD DSOUND_MixOne(IDirectSoundBufferImpl *dsb, DWORD writepos, DWORD mixlen)
Definition: mixer.c:579
#define TRUE
Definition: types.h:120
NTSYSAPI BOOLEAN NTAPI RtlAcquireResourceShared(_In_ PRTL_RESOURCE Resource, _In_ BOOLEAN Wait)
#define STATE_PLAYING
NTSYSAPI VOID NTAPI RtlReleaseResource(_In_ PRTL_RESOURCE Resource)
int32_t INT
Definition: typedefs.h:56
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
Definition: devices.h:37
#define STATE_STOPPED
#define TRACE(s)
Definition: solgame.cpp:4
unsigned long DWORD
Definition: ntddk_ex.h:95
#define STATE_STARTING
GLenum GLsizei len
Definition: glext.h:6722
PIDSDRIVERBUFFER hwbuf
void DSOUND_CheckEvent(const IDirectSoundBufferImpl *dsb, DWORD playpos, int len)
Definition: mixer.c:221
#define STATE_STOPPING

Referenced by DSOUND_PerformMix().

◆ DSOUND_MixToTemporary()

void DSOUND_MixToTemporary ( const IDirectSoundBufferImpl dsb,
DWORD  writepos,
DWORD  len,
BOOL  inmixer 
)

Mix at most the given amount of data into the allocated temporary buffer of the given secondary buffer, starting from the dsb's first currently unsampled frame (writepos), translating frequency (pitch), stereo/mono and bits-per-sample so that it is ideal for the primary buffer. Doesn't perform any mixing - this is a straight copy/convert operation.

dsb = the secondary buffer writepos = Starting position of changed buffer len = number of bytes to resample from writepos

NOTE: writepos + len <= buflen. When called by mixer, MixOne makes sure of this.

Definition at line 332 of file mixer.c.

333 {
334  INT size;
335  BYTE *ibp, *obp, *obp_begin;
336  INT iAdvance = dsb->pwfx->nBlockAlign;
337  INT oAdvance = dsb->device->pwfx->nBlockAlign;
338  DWORD freqAcc, target_writepos = 0, overshot, maxlen;
339 
340  /* We resample only when needed */
341  if ((dsb->tmp_buffer && inmixer) || (!dsb->tmp_buffer && !inmixer) || dsb->resampleinmixer != inmixer)
342  return;
343 
344  assert(writepos + len <= dsb->buflen);
345  if (inmixer && writepos + len < dsb->buflen)
346  len += dsb->pwfx->nBlockAlign;
347 
348  maxlen = DSOUND_secpos_to_bufpos(dsb, len, 0, NULL);
349 
350  ibp = dsb->buffer->memory + writepos;
351  if (!inmixer)
352  obp_begin = dsb->tmp_buffer;
353  else if (dsb->device->tmp_buffer_len < maxlen || !dsb->device->tmp_buffer)
354  {
355  dsb->device->tmp_buffer_len = maxlen;
356  if (dsb->device->tmp_buffer)
357  dsb->device->tmp_buffer = HeapReAlloc(GetProcessHeap(), 0, dsb->device->tmp_buffer, maxlen);
358  else
359  dsb->device->tmp_buffer = HeapAlloc(GetProcessHeap(), 0, maxlen);
360  obp_begin = dsb->device->tmp_buffer;
361  }
362  else
363  obp_begin = dsb->device->tmp_buffer;
364 
365  TRACE("(%p, %p)\n", dsb, ibp);
366  size = len / iAdvance;
367 
368  /* Check for same sample rate */
369  if (dsb->freq == dsb->device->pwfx->nSamplesPerSec) {
370  TRACE("(%p) Same sample rate %d = primary %d\n", dsb,
371  dsb->freq, dsb->device->pwfx->nSamplesPerSec);
372  obp = obp_begin;
373  if (!inmixer)
374  obp += writepos/iAdvance*oAdvance;
375 
376  cp_fields(dsb, ibp, obp, iAdvance, oAdvance, size, 0, 1 << DSOUND_FREQSHIFT);
377  return;
378  }
379 
380  /* Mix in different sample rates */
381  TRACE("(%p) Adjusting frequency: %d -> %d\n", dsb, dsb->freq, dsb->device->pwfx->nSamplesPerSec);
382 
383  target_writepos = DSOUND_secpos_to_bufpos(dsb, writepos, dsb->sec_mixpos, &freqAcc);
384  overshot = freqAcc >> DSOUND_FREQSHIFT;
385  if (overshot)
386  {
387  if (overshot >= size)
388  return;
389  size -= overshot;
390  writepos += overshot * iAdvance;
391  if (writepos >= dsb->buflen)
392  return;
393  ibp = dsb->buffer->memory + writepos;
394  freqAcc &= (1 << DSOUND_FREQSHIFT) - 1;
395  TRACE("Overshot: %d, freqAcc: %04x\n", overshot, freqAcc);
396  }
397 
398  if (!inmixer)
399  obp = obp_begin + target_writepos;
400  else obp = obp_begin;
401 
402  /* FIXME: Small problem here when we're overwriting buf_mixpos, it then STILL uses old freqAcc, not sure if it matters or not */
403  cp_fields(dsb, ibp, obp, iAdvance, oAdvance, size, freqAcc, dsb->freqAdjust);
404 }
static void cp_fields(const IDirectSoundBufferImpl *dsb, const BYTE *ibuf, BYTE *obuf, UINT istride, UINT ostride, UINT count, UINT freqAcc, UINT adj)
Definition: mixer.c:271
DWORD DSOUND_secpos_to_bufpos(const IDirectSoundBufferImpl *dsb, DWORD secpos, DWORD secmixpos, DWORD *overshot)
Definition: mixer.c:99
#define assert(x)
Definition: debug.h:53
int32_t INT
Definition: typedefs.h:56
PWAVEFORMATEX pwfx
#define DSOUND_FREQSHIFT
smooth NULL
Definition: ftsmooth.c:416
#define TRACE(s)
Definition: solgame.cpp:4
GLsizeiptr size
Definition: glext.h:5919
#define GetProcessHeap()
Definition: compat.h:403
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
unsigned long DWORD
Definition: ntddk_ex.h:95
GLenum GLsizei len
Definition: glext.h:6722
unsigned char BYTE
Definition: mem.h:68
DirectSoundDevice * device
#define HeapReAlloc
Definition: compat.h:401
DWORD nSamplesPerSec
Definition: mmreg.h:80
WORD nBlockAlign
Definition: mmreg.h:82

Referenced by DSOUND_Calc3DBuffer(), DSOUND_MixInBuffer(), IDirectSoundBufferImpl_Duplicate(), IDirectSoundBufferImpl_SetFrequency(), IDirectSoundBufferImpl_Unlock(), and primarybuffer_SetFormat().

◆ DSOUND_PerformMix()

static void DSOUND_PerformMix ( DirectSoundDevice device)
static

Perform mixing for a Direct Sound device. That is, go through all the secondary buffers (the sound bites currently playing) and mix them in to the primary buffer (the device buffer).

Definition at line 787 of file mixer.c.

788 {
789  TRACE("(%p)\n", device);
790 
791  /* **** */
792  EnterCriticalSection(&(device->mixlock));
793 
794  if (device->priolevel != DSSCL_WRITEPRIMARY) {
795  BOOL recover = FALSE, all_stopped = FALSE;
796  DWORD playpos, writepos, writelead, maxq, frag, prebuff_max, prebuff_left, size1, size2, mixplaypos, mixplaypos2;
797  LPVOID buf1, buf2;
798  BOOL lock = (device->hwbuf && !(device->drvdesc.dwFlags & DSDDESC_DONTNEEDPRIMARYLOCK));
799  int nfiller;
800 
801  /* the sound of silence */
802  nfiller = device->pwfx->wBitsPerSample == 8 ? 128 : 0;
803 
804  /* get the position in the primary buffer */
805  if (DSOUND_PrimaryGetPosition(device, &playpos, &writepos) != 0){
806  LeaveCriticalSection(&(device->mixlock));
807  return;
808  }
809 
810  TRACE("primary playpos=%d, writepos=%d, clrpos=%d, mixpos=%d, buflen=%d\n",
811  playpos,writepos,device->playpos,device->mixpos,device->buflen);
812  assert(device->playpos < device->buflen);
813 
814  mixplaypos = DSOUND_bufpos_to_mixpos(device, device->playpos);
815  mixplaypos2 = DSOUND_bufpos_to_mixpos(device, playpos);
816 
817  /* calc maximum prebuff */
818  prebuff_max = (device->prebuf * device->fraglen);
819  if (!device->hwbuf && playpos + prebuff_max >= device->helfrags * device->fraglen)
820  prebuff_max += device->buflen - device->helfrags * device->fraglen;
821 
822  /* check how close we are to an underrun. It occurs when the writepos overtakes the mixpos */
823  prebuff_left = DSOUND_BufPtrDiff(device->buflen, device->mixpos, playpos);
824  writelead = DSOUND_BufPtrDiff(device->buflen, writepos, playpos);
825 
826  /* check for underrun. underrun occurs when the write position passes the mix position
827  * also wipe out just-played sound data */
828  if((prebuff_left > prebuff_max) || (device->state == STATE_STOPPED) || (device->state == STATE_STARTING)){
829  if (device->state == STATE_STOPPING || device->state == STATE_PLAYING)
830  WARN("Probable buffer underrun\n");
831  else TRACE("Buffer starting or buffer underrun\n");
832 
833  /* recover mixing for all buffers */
834  recover = TRUE;
835 
836  /* reset mix position to write position */
837  device->mixpos = writepos;
838 
839  ZeroMemory(device->mix_buffer, device->mix_buffer_len);
840  ZeroMemory(device->buffer, device->buflen);
841  } else if (playpos < device->playpos) {
842  buf1 = device->buffer + device->playpos;
843  buf2 = device->buffer;
844  size1 = device->buflen - device->playpos;
845  size2 = playpos;
846  FillMemory(device->mix_buffer + mixplaypos, device->mix_buffer_len - mixplaypos, 0);
847  FillMemory(device->mix_buffer, mixplaypos2, 0);
848  if (lock)
849  IDsDriverBuffer_Lock(device->hwbuf, &buf1, &size1, &buf2, &size2, device->playpos, size1+size2, 0);
850  FillMemory(buf1, size1, nfiller);
851  if (playpos && (!buf2 || !size2))
852  FIXME("%d: (%d, %d)=>(%d, %d) There should be an additional buffer here!!\n", __LINE__, device->playpos, device->mixpos, playpos, writepos);
853  FillMemory(buf2, size2, nfiller);
854  if (lock)
855  IDsDriverBuffer_Unlock(device->hwbuf, buf1, size1, buf2, size2);
856  } else {
857  buf1 = device->buffer + device->playpos;
858  buf2 = NULL;
859  size1 = playpos - device->playpos;
860  size2 = 0;
861  FillMemory(device->mix_buffer + mixplaypos, mixplaypos2 - mixplaypos, 0);
862  if (lock)
863  IDsDriverBuffer_Lock(device->hwbuf, &buf1, &size1, &buf2, &size2, device->playpos, size1+size2, 0);
864  FillMemory(buf1, size1, nfiller);
865  if (buf2 && size2)
866  {
867  FIXME("%d: There should be no additional buffer here!!\n", __LINE__);
868  FillMemory(buf2, size2, nfiller);
869  }
870  if (lock)
871  IDsDriverBuffer_Unlock(device->hwbuf, buf1, size1, buf2, size2);
872  }
873  device->playpos = playpos;
874 
875  /* find the maximum we can prebuffer from current write position */
876  maxq = (writelead < prebuff_max) ? (prebuff_max - writelead) : 0;
877 
878  TRACE("prebuff_left = %d, prebuff_max = %dx%d=%d, writelead=%d\n",
879  prebuff_left, device->prebuf, device->fraglen, prebuff_max, writelead);
880 
881  if (lock)
882  IDsDriverBuffer_Lock(device->hwbuf, &buf1, &size1, &buf2, &size2, writepos, maxq, 0);
883 
884  /* do the mixing */
885  frag = DSOUND_MixToPrimary(device, writepos, maxq, recover, &all_stopped);
886 
887  if (frag + writepos > device->buflen)
888  {
889  DWORD todo = device->buflen - writepos;
890  device->normfunction(device->mix_buffer + DSOUND_bufpos_to_mixpos(device, writepos), device->buffer + writepos, todo);
891  device->normfunction(device->mix_buffer, device->buffer, frag - todo);
892  }
893  else
894  device->normfunction(device->mix_buffer + DSOUND_bufpos_to_mixpos(device, writepos), device->buffer + writepos, frag);
895 
896  /* update the mix position, taking wrap-around into account */
897  device->mixpos = writepos + frag;
898  device->mixpos %= device->buflen;
899 
900  if (lock)
901  {
902  DWORD frag2 = (frag > size1 ? frag - size1 : 0);
903  frag -= frag2;
904  if (frag2 > size2)
905  {
906  FIXME("Buffering too much! (%d, %d, %d, %d)\n", maxq, frag, size2, frag2 - size2);
907  frag2 = size2;
908  }
909  IDsDriverBuffer_Unlock(device->hwbuf, buf1, frag, buf2, frag2);
910  }
911 
912  /* update prebuff left */
913  prebuff_left = DSOUND_BufPtrDiff(device->buflen, device->mixpos, playpos);
914 
915  /* check if have a whole fragment */
916  if (prebuff_left >= device->fraglen){
917 
918  /* update the wave queue if using wave system */
919  if (!device->hwbuf)
921 
922  /* buffers are full. start playing if applicable */
923  if(device->state == STATE_STARTING){
924  TRACE("started primary buffer\n");
926  WARN("DSOUND_PrimaryPlay failed\n");
927  }
928  else{
929  /* we are playing now */
930  device->state = STATE_PLAYING;
931  }
932  }
933 
934  /* buffers are full. start stopping if applicable */
935  if(device->state == STATE_STOPPED){
936  TRACE("restarting primary buffer\n");
938  WARN("DSOUND_PrimaryPlay failed\n");
939  }
940  else{
941  /* start stopping again. as soon as there is no more data, it will stop */
942  device->state = STATE_STOPPING;
943  }
944  }
945  }
946 
947  /* if device was stopping, its for sure stopped when all buffers have stopped */
948  else if((all_stopped != FALSE) && (device->state == STATE_STOPPING)){
949  TRACE("All buffers have stopped. Stopping primary buffer\n");
950  device->state = STATE_STOPPED;
951 
952  /* stop the primary buffer now */
954  }
955 
956  } else {
957 
958  /* update the wave queue if using wave system */
959  if (!device->hwbuf)
961  else
962  /* Keep alsa happy, which needs GetPosition called once every 10 ms */
964 
965  /* in the DSSCL_WRITEPRIMARY mode, the app is totally in charge... */
966  if (device->state == STATE_STARTING) {
968  WARN("DSOUND_PrimaryPlay failed\n");
969  else
970  device->state = STATE_PLAYING;
971  }
972  else if (device->state == STATE_STOPPING) {
974  WARN("DSOUND_PrimaryStop failed\n");
975  else
976  device->state = STATE_STOPPED;
977  }
978  }
979 
980  LeaveCriticalSection(&(device->mixlock));
981  /* **** */
982 }
#define TRUE
Definition: types.h:120
HRESULT DSOUND_PrimaryGetPosition(DirectSoundDevice *device, LPDWORD playpos, LPDWORD writepos) DECLSPEC_HIDDEN
Definition: primary.c:402
static DWORD DSOUND_BufPtrDiff(DWORD buflen, DWORD ptr1, DWORD ptr2)
Definition: mixer.c:308
#define IDsDriverBuffer_Unlock(p, a, b, c, d)
Definition: dsdriver.h:197
rwlock_t lock
Definition: tcpcore.h:1163
#define WARN(fmt,...)
Definition: debug.h:111
#define STATE_PLAYING
BOOL todo
Definition: filedlg.c:313
static void DSOUND_WaveQueue(DirectSoundDevice *device, BOOL force)
Definition: mixer.c:725
#define assert(x)
Definition: debug.h:53
#define ZeroMemory
Definition: winbase.h:1642
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
unsigned int BOOL
Definition: ntddk_ex.h:94
Definition: devices.h:37
#define FIXME(fmt,...)
Definition: debug.h:110
smooth NULL
Definition: ftsmooth.c:416
#define STATE_STOPPED
#define DS_OK
Definition: dsound.h:116
#define TRACE(s)
Definition: solgame.cpp:4
unsigned long DWORD
Definition: ntddk_ex.h:95
#define FillMemory(BUF, SIZ, MASK)
Definition: strucsup.c:31
#define STATE_STARTING
#define IDsDriverBuffer_GetPosition(p, a, b)
Definition: dsdriver.h:202
#define DSDDESC_DONTNEEDPRIMARYLOCK
Definition: dsdriver.h:53
static DWORD DSOUND_MixToPrimary(const DirectSoundDevice *device, DWORD writepos, DWORD mixlen, BOOL recover, BOOL *all_stopped)
Definition: mixer.c:663
#define DSSCL_WRITEPRIMARY
Definition: dsound.h:250
DWORD DSOUND_bufpos_to_mixpos(const DirectSoundDevice *device, DWORD pos)
Definition: mixer.c:84
#define IDsDriverBuffer_Lock(p, a, b, c, d, e, f, g)
Definition: dsdriver.h:196
HRESULT DSOUND_PrimaryPlay(DirectSoundDevice *device) DECLSPEC_HIDDEN
Definition: primary.c:345
#define STATE_STOPPING
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
HRESULT DSOUND_PrimaryStop(DirectSoundDevice *device) DECLSPEC_HIDDEN
Definition: primary.c:363

Referenced by DSOUND_timer().

◆ DSOUND_RecalcFormat()

void DSOUND_RecalcFormat ( IDirectSoundBufferImpl dsb)

Recalculate the size for temporary buffer, and new writelead Should be called when one of the following things occur:

  • Primary buffer format is changed
  • This buffer format (frequency) is changed

After this, DSOUND_MixToTemporary(dsb, 0, dsb->buflen) should be called to refill the temporary buffer with data.

Definition at line 162 of file mixer.c.

163 {
164  BOOL needremix = TRUE, needresample = (dsb->freq != dsb->device->pwfx->nSamplesPerSec);
165  DWORD bAlign = dsb->pwfx->nBlockAlign, pAlign = dsb->device->pwfx->nBlockAlign;
166  WAVEFORMATEXTENSIBLE *pwfxe;
167  BOOL ieee = FALSE;
168 
169  TRACE("(%p)\n",dsb);
170 
171  pwfxe = (WAVEFORMATEXTENSIBLE *) dsb->pwfx;
172 
175  ieee = TRUE;
176 
177  /* calculate the 10ms write lead */
178  dsb->writelead = (dsb->freq / 100) * dsb->pwfx->nBlockAlign;
179 
180  if ((dsb->pwfx->wBitsPerSample == dsb->device->pwfx->wBitsPerSample) &&
181  (dsb->pwfx->nChannels == dsb->device->pwfx->nChannels) && !needresample && !ieee)
182  needremix = FALSE;
183  HeapFree(GetProcessHeap(), 0, dsb->tmp_buffer);
184  dsb->tmp_buffer = NULL;
185  dsb->max_buffer_len = dsb->freqAcc = dsb->freqAccNext = 0;
186  dsb->freqneeded = needresample;
187 
188  if (ieee)
189  dsb->convert = convertbpp[4][dsb->device->pwfx->wBitsPerSample/8 - 1];
190  else
191  dsb->convert = convertbpp[dsb->pwfx->wBitsPerSample/8 - 1][dsb->device->pwfx->wBitsPerSample/8 - 1];
192 
193  dsb->resampleinmixer = FALSE;
194 
195  if (needremix)
196  {
197  if (needresample)
199  else
200  dsb->tmp_buffer_len = dsb->buflen / bAlign * pAlign;
201  dsb->max_buffer_len = dsb->tmp_buffer_len;
202  if ((dsb->max_buffer_len <= dsb->device->buflen || dsb->max_buffer_len < ds_snd_shadow_maxsize * 1024 * 1024) && ds_snd_shadow_maxsize >= 0)
204  if (dsb->tmp_buffer)
205  FillMemory(dsb->tmp_buffer, dsb->tmp_buffer_len, dsb->device->pwfx->wBitsPerSample == 8 ? 128 : 0);
206  else
207  dsb->resampleinmixer = TRUE;
208  }
209  else dsb->max_buffer_len = dsb->tmp_buffer_len = dsb->buflen;
210  dsb->buf_mixpos = DSOUND_secpos_to_bufpos(dsb, dsb->sec_mixpos, 0, NULL);
211 }
#define TRUE
Definition: types.h:120
DWORD DSOUND_secpos_to_bufpos(const IDirectSoundBufferImpl *dsb, DWORD secpos, DWORD secmixpos, DWORD *overshot)
Definition: mixer.c:99
WORD nChannels
Definition: mmreg.h:79
static void DSOUND_RecalcFreqAcc(IDirectSoundBufferImpl *dsb)
Definition: mixer.c:145
GUID KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
PWAVEFORMATEX pwfx
unsigned int BOOL
Definition: ntddk_ex.h:94
smooth NULL
Definition: ftsmooth.c:416
bitsconvertfunc convert
#define TRACE(s)
Definition: solgame.cpp:4
const bitsconvertfunc convertbpp[5][4]
#define GetProcessHeap()
Definition: compat.h:403
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
if(!(yy_init))
Definition: macro.lex.yy.c:714
WAVEFORMATEX Format
Definition: ksmedia.h:538
unsigned long DWORD
Definition: ntddk_ex.h:95
#define FillMemory(BUF, SIZ, MASK)
Definition: strucsup.c:31
DirectSoundDevice * device
BOOL WINAPI IsEqualGUID(REFGUID rguid1, REFGUID rguid2)
Definition: compobj.c:4112
DWORD nSamplesPerSec
Definition: mmreg.h:80
WORD nBlockAlign
Definition: mmreg.h:82
WORD wBitsPerSample
Definition: mmreg.h:83
int ds_snd_shadow_maxsize
Definition: dsound_main.c:76
#define HeapFree(x, y, z)
Definition: compat.h:402
#define WAVE_FORMAT_EXTENSIBLE
Definition: ksmedia.h:551
#define WAVE_FORMAT_IEEE_FLOAT
Definition: mmreg.h:97

Referenced by DSOUND_Calc3DBuffer(), IDirectSoundBufferImpl_Create(), IDirectSoundBufferImpl_Duplicate(), IDirectSoundBufferImpl_SetFrequency(), and primarybuffer_SetFormat().

◆ DSOUND_RecalcFreqAcc()

static void DSOUND_RecalcFreqAcc ( IDirectSoundBufferImpl dsb)
static

Move freqAccNext to freqAcc, and find new values for buffer length and freqAccNext

Definition at line 145 of file mixer.c.

146 {
147  if (!dsb->freqneeded) return;
148  dsb->freqAcc = dsb->freqAccNext;
149  dsb->tmp_buffer_len = DSOUND_secpos_to_bufpos(dsb, dsb->buflen, 0, &dsb->freqAccNext);
150  TRACE("New freqadjust: %04x, new buflen: %d\n", dsb->freqAccNext, dsb->tmp_buffer_len);
151 }
DWORD DSOUND_secpos_to_bufpos(const IDirectSoundBufferImpl *dsb, DWORD secpos, DWORD secmixpos, DWORD *overshot)
Definition: mixer.c:99
#define TRACE(s)
Definition: solgame.cpp:4

Referenced by DSOUND_MixInBuffer(), and DSOUND_RecalcFormat().

◆ DSOUND_RecalcVolPan()

void DSOUND_RecalcVolPan ( PDSVOLUMEPAN  volpan)

Definition at line 27 of file mixer.c.

28 {
29  double temp;
30  TRACE("(%p)\n",volpan);
31 
32  TRACE("Vol=%d Pan=%d\n", volpan->lVolume, volpan->lPan);
33  /* the AmpFactors are expressed in 16.16 fixed point */
34  volpan->dwVolAmpFactor = (ULONG) (pow(2.0, volpan->lVolume / 600.0) * 0xffff);
35  /* FIXME: dwPan{Left|Right}AmpFactor */
36 
37  /* FIXME: use calculated vol and pan ampfactors */
38  temp = (double) (volpan->lVolume - (volpan->lPan > 0 ? volpan->lPan : 0));
39  volpan->dwTotalLeftAmpFactor = (ULONG) (pow(2.0, temp / 600.0) * 0xffff);
40  temp = (double) (volpan->lVolume + (volpan->lPan < 0 ? volpan->lPan : 0));
41  volpan->dwTotalRightAmpFactor = (ULONG) (pow(2.0, temp / 600.0) * 0xffff);
42 
43  TRACE("left = %x, right = %x\n", volpan->dwTotalLeftAmpFactor, volpan->dwTotalRightAmpFactor);
44 }
float pow(float __x, int __y)
Definition: _cmath.h:458
static const char mbstate_t *static wchar_t const char mbstate_t *static const wchar_t int *static double
Definition: string.c:80
DWORD dwTotalRightAmpFactor
Definition: dsdriver.h:106
#define TRACE(s)
Definition: solgame.cpp:4
static calc_node_t temp
Definition: rpn_ieee.c:38
DWORD dwVolAmpFactor
Definition: dsdriver.h:108
unsigned int ULONG
Definition: retypes.h:1
DWORD dwTotalLeftAmpFactor
Definition: dsdriver.h:105
LONG lVolume
Definition: dsdriver.h:107

Referenced by DSOUND_Calc3DBuffer(), IDirectSoundBufferImpl_Create(), IDirectSoundBufferImpl_SetPan(), IDirectSoundBufferImpl_SetVolume(), PrimaryBufferImpl_SetPan(), and PrimaryBufferImpl_SetVolume().

◆ DSOUND_secpos_to_bufpos()

DWORD DSOUND_secpos_to_bufpos ( const IDirectSoundBufferImpl dsb,
DWORD  secpos,
DWORD  secmixpos,
DWORD overshot 
)

This function converts a 'native' sample pointer to a resampled pointer that fits for primary secmixpos is used to decide which freqAcc is needed overshot tells what the 'actual' secpos is now (optional)

Definition at line 99 of file mixer.c.

100 {
101  DWORD64 framelen = secpos / dsb->pwfx->nBlockAlign;
102  DWORD64 freqAdjust = dsb->freqAdjust;
103  DWORD64 acc, freqAcc;
104 
105  if (secpos < secmixpos)
106  freqAcc = dsb->freqAccNext;
107  else freqAcc = dsb->freqAcc;
108  acc = (framelen << DSOUND_FREQSHIFT) + (freqAdjust - 1 - freqAcc);
109  acc /= freqAdjust;
110  if (overshot)
111  {
112  DWORD64 oshot = acc * freqAdjust + freqAcc;
113  assert(oshot >= framelen << DSOUND_FREQSHIFT);
114  oshot -= framelen << DSOUND_FREQSHIFT;
115  *overshot = (DWORD)oshot;
116  assert(*overshot < dsb->freqAdjust);
117  }
118  return (DWORD)acc * dsb->device->pwfx->nBlockAlign;
119 }
#define assert(x)
Definition: debug.h:53
#define DWORD
Definition: nt_native.h:44
PWAVEFORMATEX pwfx
#define DSOUND_FREQSHIFT
unsigned long DWORD
Definition: ntddk_ex.h:95
DirectSoundDevice * device
uint64_t DWORD64
Definition: typedefs.h:65
WORD nBlockAlign
Definition: mmreg.h:82

Referenced by DSOUND_MixToTemporary(), DSOUND_RecalcFormat(), DSOUND_RecalcFreqAcc(), and IDirectSoundBufferImpl_SetCurrentPosition().

◆ DSOUND_timer()

void CALLBACK DSOUND_timer ( UINT  timerID,
UINT  msg,
DWORD_PTR  dwUser,
DWORD_PTR  dw1,
DWORD_PTR  dw2 
)

Definition at line 984 of file mixer.c.

986 {
988  DWORD start_time = GetTickCount();
989  DWORD end_time;
990  TRACE("(%d,%d,0x%lx,0x%lx,0x%lx)\n",timerID,msg,dwUser,dw1,dw2);
991  TRACE("entering at %d\n", start_time);
992 
993  if (DSOUND_renderer[device->drvdesc.dnDevNode] != device) {
994  ERR("dsound died without killing us?\n");
995  timeKillEvent(timerID);
997  return;
998  }
999 
1000  RtlAcquireResourceShared(&(device->buffer_list_lock), TRUE);
1001 
1002  if (device->ref)
1004 
1005  RtlReleaseResource(&(device->buffer_list_lock));
1006 
1007  end_time = GetTickCount();
1008  TRACE("completed processing at %d, duration = %d\n", end_time, end_time - start_time);
1009 }
#define TRUE
Definition: types.h:120
NTSYSAPI BOOLEAN NTAPI RtlAcquireResourceShared(_In_ PRTL_RESOURCE Resource, _In_ BOOLEAN Wait)
DWORD WINAPI GetTickCount(VOID)
Definition: time.c:445
MMRESULT WINAPI timeEndPeriod(UINT wPeriod)
Definition: time.c:438
#define DS_TIME_RES
NTSYSAPI VOID NTAPI RtlReleaseResource(_In_ PRTL_RESOURCE Resource)
static void DSOUND_PerformMix(DirectSoundDevice *device)
Definition: mixer.c:787
Definition: devices.h:37
DirectSoundDevice * DSOUND_renderer[MAXWAVEDRIVERS]
Definition: dsound_main.c:40
MMRESULT WINAPI timeKillEvent(UINT wID)
Definition: time.c:369
#define TRACE(s)
Definition: solgame.cpp:4
unsigned long DWORD
Definition: ntddk_ex.h:95
#define ERR(fmt,...)
Definition: debug.h:109
#define msg(x)
Definition: auth_time.c:54

Referenced by DirectSoundDevice_Initialize().

◆ DSOUND_WaveQueue()

static void DSOUND_WaveQueue ( DirectSoundDevice device,
BOOL  force 
)
static

Add buffers to the emulated wave device system.

device = The current dsound playback device force = If TRUE, the function will buffer up as many frags as possible, even though and will ignore the actual state of the primary buffer.

Returns: None

Definition at line 725 of file mixer.c.

726 {
727  DWORD prebuf_frags, wave_writepos, wave_fragpos, i;
728  TRACE("(%p)\n", device);
729 
730  /* calculate the current wave frag position */
731  wave_fragpos = (device->pwplay + device->pwqueue) % device->helfrags;
732 
733  /* calculate the current wave write position */
734  wave_writepos = wave_fragpos * device->fraglen;
735 
736  TRACE("wave_fragpos = %i, wave_writepos = %i, pwqueue = %i, prebuf = %i\n",
737  wave_fragpos, wave_writepos, device->pwqueue, device->prebuf);
738 
739  if (!force)
740  {
741  /* check remaining prebuffered frags */
742  prebuf_frags = device->mixpos / device->fraglen;
743  if (prebuf_frags == device->helfrags)
744  --prebuf_frags;
745  TRACE("wave_fragpos = %d, mixpos_frags = %d\n", wave_fragpos, prebuf_frags);
746  if (prebuf_frags < wave_fragpos)
747  prebuf_frags += device->helfrags;
748  prebuf_frags -= wave_fragpos;
749  TRACE("wanted prebuf_frags = %d\n", prebuf_frags);
750  }
751  else
752  /* buffer the maximum amount of frags */
753  prebuf_frags = device->prebuf;
754 
755  /* limit to the queue we have left */
756  if ((prebuf_frags + device->pwqueue) > device->prebuf)
757  prebuf_frags = device->prebuf - device->pwqueue;
758 
759  TRACE("prebuf_frags = %i\n", prebuf_frags);
760 
761  /* adjust queue */
762  device->pwqueue += prebuf_frags;
763 
764  /* get out of CS when calling the wave system */
765  LeaveCriticalSection(&(device->mixlock));
766  /* **** */
767 
768  /* queue up the new buffers */
769  for(i=0; i<prebuf_frags; i++){
770  TRACE("queueing wave buffer %i\n", wave_fragpos);
771  waveOutWrite(device->hwo, &device->pwave[wave_fragpos], sizeof(WAVEHDR));
772  wave_fragpos++;
773  wave_fragpos %= device->helfrags;
774  }
775 
776  /* **** */
777  EnterCriticalSection(&(device->mixlock));
778 
779  TRACE("queue now = %i\n", device->pwqueue);
780 }
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
Definition: devices.h:37
#define TRACE(s)
Definition: solgame.cpp:4
unsigned long DWORD
Definition: ntddk_ex.h:95
UINT WINAPI waveOutWrite(HWAVEOUT hWaveOut, LPWAVEHDR lpWaveOutHdr, UINT uSize)
Definition: winmm.c:2344
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)

Referenced by DSOUND_PerformMix().