ReactOS  0.4.14-dev-317-g96040ec
mixer.c
Go to the documentation of this file.
1 /* DirectSound
2  *
3  * Copyright 1998 Marcus Meissner
4  * Copyright 1998 Rob Riggs
5  * Copyright 2000-2002 TransGaming Technologies, Inc.
6  * Copyright 2007 Peter Dons Tychsen
7  * Copyright 2007 Maarten Lankhorst
8  * Copyright 2011 Owen Rudge for CodeWeavers
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 2.1 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with this library; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 
25 #include "dsound_private.h"
26 
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 }
45 
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 }
78 
85 {
86  DWORD ret = pos * 32 / device->pwfx->wBitsPerSample;
87  if (device->pwfx->wBitsPerSample == 32)
88  ret *= 2;
89  return ret;
90 }
91 
92 /* NOTE: Not all secpos have to always be mapped to a bufpos, other way around is always the case
93  * DWORD64 is used here because a single DWORD wouldn't be big enough to fit the freqAcc for big buffers
94  */
99 DWORD DSOUND_secpos_to_bufpos(const IDirectSoundBufferImpl *dsb, DWORD secpos, DWORD secmixpos, DWORD* overshot)
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 }
120 
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 }
141 
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 }
152 
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 }
212 
221 void DSOUND_CheckEvent(const IDirectSoundBufferImpl *dsb, DWORD playpos, int len)
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 }
266 
271 static inline void cp_fields(const IDirectSoundBufferImpl *dsb, const BYTE *ibuf, BYTE *obuf,
272  UINT istride, UINT ostride, UINT count, UINT freqAcc, UINT adj)
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 }
303 
308 static inline DWORD DSOUND_BufPtrDiff(DWORD buflen, DWORD ptr1, DWORD ptr2)
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 }
332 void DSOUND_MixToTemporary(const IDirectSoundBufferImpl *dsb, DWORD writepos, DWORD len, BOOL inmixer)
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 }
405 
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 }
485 
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 }
566 
579 static DWORD DSOUND_MixOne(IDirectSoundBufferImpl *dsb, DWORD writepos, DWORD mixlen)
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 }
648 
663 static DWORD DSOUND_MixToPrimary(const DirectSoundDevice *device, DWORD writepos, DWORD mixlen, BOOL recover, BOOL *all_stopped)
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 }
714 
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 }
781 
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 }
983 
984 void CALLBACK DSOUND_timer(UINT timerID, UINT msg, DWORD_PTR dwUser,
985  DWORD_PTR dw1, DWORD_PTR dw2)
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 }
1010 
1011 void CALLBACK DSOUND_callback(HWAVEOUT hwo, UINT msg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2)
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 }
static DWORD DSOUND_MixOne(IDirectSoundBufferImpl *dsb, DWORD writepos, DWORD mixlen)
Definition: mixer.c:579
#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 DSBCAPS_CTRLVOLUME
Definition: dsound.h:213
#define IDsDriverBuffer_Unlock(p, a, b, c, d)
Definition: dsdriver.h:197
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
rwlock_t lock
Definition: tcpcore.h:1163
#define MM_WOM_OPEN
Definition: mmsystem.h:56
NTSYSAPI BOOLEAN NTAPI RtlAcquireResourceShared(_In_ PRTL_RESOURCE Resource, _In_ BOOLEAN Wait)
DWORD DSOUND_secpos_to_bufpos(const IDirectSoundBufferImpl *dsb, DWORD secpos, DWORD secmixpos, DWORD *overshot)
Definition: mixer.c:99
GLuint GLuint GLsizei count
Definition: gl.h:1545
static DWORD DWORD istep
Definition: cursoricon.c:1521
WORD nChannels
Definition: mmreg.h:79
void DSOUND_RecalcFormat(IDirectSoundBufferImpl *dsb)
Definition: mixer.c:162
#define WARN(fmt,...)
Definition: debug.h:111
static void DSOUND_RecalcFreqAcc(IDirectSoundBufferImpl *dsb)
Definition: mixer.c:145
#define STATE_PLAYING
GLintptr offset
Definition: glext.h:5920
#define CALLBACK
Definition: compat.h:27
BOOL todo
Definition: filedlg.c:313
DWORD WINAPI GetTickCount(VOID)
Definition: time.c:445
static void DSOUND_WaveQueue(DirectSoundDevice *device, BOOL force)
Definition: mixer.c:725
MMRESULT WINAPI timeEndPeriod(UINT wPeriod)
Definition: time.c:438
#define assert(x)
Definition: debug.h:53
#define DSBPN_OFFSETSTOP
Definition: dsound.h:876
BOOL WINAPI DECLSPEC_HOTPATCH SetEvent(IN HANDLE hEvent)
Definition: synch.c:733
#define ZeroMemory
Definition: winbase.h:1642
#define DSBCAPS_CTRLPAN
Definition: dsound.h:212
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
GUID KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
int nChannels
Definition: pcmconverter.c:95
#define MM_WOM_DONE
Definition: mmsystem.h:58
#define DS_TIME_RES
void DSOUND_AmpFactorToVolPan(PDSVOLUMEPAN volpan)
Definition: mixer.c:46
#define DWORD
Definition: nt_native.h:44
NTSYSAPI VOID NTAPI RtlReleaseResource(_In_ PRTL_RESOURCE Resource)
int32_t INT
Definition: typedefs.h:56
void DSOUND_RecalcVolPan(PDSVOLUMEPAN volpan)
Definition: mixer.c:27
PWAVEFORMATEX pwfx
static void DSOUND_PerformMix(DirectSoundDevice *device)
Definition: mixer.c:787
#define DSOUND_FREQSHIFT
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
unsigned int BOOL
Definition: ntddk_ex.h:94
Definition: devices.h:37
float pow(float __x, int __y)
Definition: _cmath.h:458
DirectSoundDevice * DSOUND_renderer[MAXWAVEDRIVERS]
Definition: dsound_main.c:40
#define FIXME(fmt,...)
Definition: debug.h:110
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
smooth NULL
Definition: ftsmooth.c:416
MMRESULT WINAPI timeKillEvent(UINT wID)
Definition: time.c:369
void CALLBACK DSOUND_callback(HWAVEOUT hwo, UINT msg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2)
Definition: mixer.c:1011
#define STATE_STOPPED
bitsconvertfunc convert
void CALLBACK DSOUND_timer(UINT timerID, UINT msg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2)
Definition: mixer.c:984
#define DSBCAPS_CTRLPOSITIONNOTIFY
Definition: dsound.h:215
#define DS_OK
Definition: dsound.h:116
#define TRACE(s)
Definition: solgame.cpp:4
GLsizeiptr size
Definition: glext.h:5919
const bitsconvertfunc convertbpp[5][4]
#define GetProcessHeap()
Definition: compat.h:395
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
#define MM_WOM_CLOSE
Definition: mmsystem.h:57
#define DSBPLAY_LOOPING
Definition: dsound.h:189
if(!(yy_init))
Definition: macro.lex.yy.c:714
WAVEFORMATEX Format
Definition: ksmedia.h:538
unsigned long DWORD
Definition: ntddk_ex.h:95
GLint left
Definition: glext.h:7726
#define FillMemory(BUF, SIZ, MASK)
Definition: strucsup.c:31
GLdouble GLdouble right
Definition: glext.h:10859
UINT WINAPI waveOutWrite(HWAVEOUT hWaveOut, LPWAVEHDR lpWaveOutHdr, UINT uSize)
Definition: winmm.c:2344
int ret
#define STATE_STARTING
GLenum GLsizei len
Definition: glext.h:6722
unsigned char BYTE
Definition: mem.h:68
DirectSoundDevice * device
struct _cl_event * event
Definition: glext.h:7739
uint32_t DWORD_PTR
Definition: typedefs.h:63
#define ERR(fmt,...)
Definition: debug.h:109
#define IDsDriverBuffer_GetPosition(p, a, b)
Definition: dsdriver.h:202
uint64_t DWORD64
Definition: typedefs.h:65
static calc_node_t temp
Definition: rpn_ieee.c:38
static char obuf[100]
Definition: i386-dis.c:1266
#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
PIDSDRIVERBUFFER hwbuf
#define DSBCAPS_CTRL3D
Definition: dsound.h:210
#define HeapReAlloc
Definition: compat.h:393
#define DSSCL_WRITEPRIMARY
Definition: dsound.h:250
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
#define IDsDriverBuffer_Lock(p, a, b, c, d, e, f, g)
Definition: dsdriver.h:196
unsigned int UINT
Definition: ndis.h:50
BOOL WINAPI IsEqualGUID(REFGUID rguid1, REFGUID rguid2)
Definition: compobj.c:4112
static DWORD DSOUND_bufpos_to_secpos(const IDirectSoundBufferImpl *dsb, DWORD bufpos)
Definition: mixer.c:125
LPDSBPOSITIONNOTIFY notifies
DWORD nSamplesPerSec
Definition: mmreg.h:80
#define msg(x)
Definition: auth_time.c:54
Definition: mem.c:156
WORD nBlockAlign
Definition: mmreg.h:82
DWORD dwVolAmpFactor
Definition: dsdriver.h:108
WORD wBitsPerSample
Definition: mmreg.h:83
HRESULT DSOUND_PrimaryPlay(DirectSoundDevice *device) DECLSPEC_HIDDEN
Definition: primary.c:345
unsigned int ULONG
Definition: retypes.h:1
DWORD dwTotalLeftAmpFactor
Definition: dsdriver.h:105
void DSOUND_MixToTemporary(const IDirectSoundBufferImpl *dsb, DWORD writepos, DWORD len, BOOL inmixer)
Definition: mixer.c:332
int ds_snd_shadow_maxsize
Definition: dsound_main.c:76
#define STATE_STOPPING
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
DWORD dwFlags
Definition: dsound.h:289
LONG lVolume
Definition: dsdriver.h:107
HRESULT DSOUND_PrimaryStop(DirectSoundDevice *device) DECLSPEC_HIDDEN
Definition: primary.c:363
#define HeapFree(x, y, z)
Definition: compat.h:394
static DWORD DSOUND_MixInBuffer(IDirectSoundBufferImpl *dsb, DWORD writepos, DWORD fraglen)
Definition: mixer.c:499
#define log(outFile, fmt,...)
Definition: util.h:15
static LPBYTE DSOUND_MixerVol(const IDirectSoundBufferImpl *dsb, INT len)
Definition: mixer.c:409
#define WAVE_FORMAT_EXTENSIBLE
Definition: ksmedia.h:551
#define WAVE_FORMAT_IEEE_FLOAT
Definition: mmreg.h:97
signed short INT16