3 * Copyright 1998 Marcus Meissner
6 * Note: This file requires multithread ability. It is not possible to
7 * implement the stuff in a single thread anyway. And most DirectX apps
8 * require threading themselves.
10 * FIXME: This file is full of race conditions and unlocked variable access
11 * from two threads. But we usually don't need to bother.
13 * Tested with a Soundblaster clone and a Gravis UltraSound Classic.
16 * - Wing Commander 4/W95:
17 * The intromovie plays without problems. Nearly lipsynchron.
19 * The sound works, but noticeable chunks are left out (from the sound and
20 * the animation). Don't know why yet.
22 * Sound works, but slows down the movieplayer.
26 * The background sound of the startscreen works ;)
27 * - WingCommander Prophecy Demo:
28 * Sound works for the intromovie.
33 #include <sys/types.h>
35 #include <sys/fcntl.h>
39 #include <math.h> /* Insomnia - pow() function */
42 #include "interfaces.h"
49 # include <sys/ioctl.h>
50 # ifdef HAVE_MACHINE_SOUNDCARD_H
51 # include <machine/soundcard.h>
53 # ifdef HAVE_SYS_SOUNDCARD_H
54 # include <sys/soundcard.h>
57 static int audiofd
= -1;
58 static LPDIRECTSOUND dsound
= NULL
;
60 static short playbuf
[2048];
64 HRESULT WINAPI
DirectSoundEnumerate32A(LPDSENUMCALLBACK32A enumcb
,LPVOID context
) {
66 enumcb(NULL
,"WINE DirectSound using Open Sound System","sound",context
);
72 static void _dump_DSBCAPS(DWORD xmask
) {
77 #define FE(x) { x, #x },
78 FE(DSBCAPS_PRIMARYBUFFER
)
80 FE(DSBCAPS_LOCHARDWARE
)
81 FE(DSBCAPS_LOCSOFTWARE
)
82 FE(DSBCAPS_CTRLFREQUENCY
)
84 FE(DSBCAPS_CTRLVOLUME
)
85 FE(DSBCAPS_CTRLDEFAULT
)
87 FE(DSBCAPS_STICKYFOCUS
)
88 FE(DSBCAPS_GETCURRENTPOSITION2
)
92 for (i
=0;i
<sizeof(flags
)/sizeof(flags
[0]);i
++)
93 if (flags
[i
].mask
& xmask
)
94 fprintf(stderr
,"%s ",flags
[i
].name
);
97 /*******************************************************************************
100 static HRESULT WINAPI
IDirectSoundNotify_QueryInterface(
101 LPDIRECTSOUNDNOTIFY
this,REFIID riid
,LPVOID
*ppobj
105 WINE_StringFromCLSID(riid
,xbuf
);
106 TRACE(dsound
,"(%p,%s,%p)\n",this,xbuf
,ppobj
);
110 static ULONG WINAPI
IDirectSoundNotify_AddRef(LPDIRECTSOUNDNOTIFY
this) {
111 return ++(this->ref
);
114 static ULONG WINAPI
IDirectSoundNotify_Release(LPDIRECTSOUNDNOTIFY
this) {
117 this->dsb
->lpvtbl
->fnRelease(this->dsb
);
118 HeapFree(GetProcessHeap(),0,this);
124 static int _sort_notifies(const void *a
,const void *b
) {
125 LPDSBPOSITIONNOTIFY na
= (LPDSBPOSITIONNOTIFY
)a
;
126 LPDSBPOSITIONNOTIFY nb
= (LPDSBPOSITIONNOTIFY
)b
;
128 return na
->dwOffset
-nb
->dwOffset
;
131 static HRESULT WINAPI
IDirectSoundNotify_SetNotificationPositions(
132 LPDIRECTSOUNDNOTIFY
this,DWORD howmuch
,LPCDSBPOSITIONNOTIFY notify
136 if (TRACE_ON(dsound
)) {
137 TRACE(dsound
,"(%p,0x%08lx,%p)\n",this,howmuch
,notify
);
138 for (i
=0;i
<howmuch
;i
++)
139 TRACE(dsound
,"notify at %ld to 0x%08lx\n",
140 notify
[i
].dwOffset
,(DWORD
)notify
[i
].hEventNotify
);
142 this->dsb
->notifies
= HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,this->dsb
->notifies
,(this->dsb
->nrofnotifies
+howmuch
)*sizeof(DSBPOSITIONNOTIFY
));
143 memcpy( this->dsb
->notifies
+this->dsb
->nrofnotifies
,
145 howmuch
*sizeof(DSBPOSITIONNOTIFY
)
147 this->dsb
->nrofnotifies
+=howmuch
;
148 qsort(this->dsb
->notifies
,this->dsb
->nrofnotifies
,sizeof(DSBPOSITIONNOTIFY
),_sort_notifies
);
152 IDirectSoundNotify_VTable dsnvt
= {
153 IDirectSoundNotify_QueryInterface
,
154 IDirectSoundNotify_AddRef
,
155 IDirectSoundNotify_Release
,
156 IDirectSoundNotify_SetNotificationPositions
,
159 /*******************************************************************************
162 static HRESULT WINAPI
IDirectSoundBuffer_SetFormat(
163 LPDIRECTSOUNDBUFFER
this,LPWAVEFORMATEX wfex
166 memcpy(&(this->wfx
),wfex
,sizeof(this->wfx
));
167 TRACE(dsound
,"(%p,%p)\n", this,wfex
);
168 TRACE(dsound
,"(formattag=0x%04x,chans=%d,samplerate=%ld"
169 "bytespersec=%ld,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
170 wfex
->wFormatTag
, wfex
->nChannels
, wfex
->nSamplesPerSec
,
171 wfex
->nAvgBytesPerSec
, wfex
->nBlockAlign
,
172 wfex
->wBitsPerSample
, wfex
->cbSize
);
177 static HRESULT WINAPI
IDirectSoundBuffer_SetVolume(
178 LPDIRECTSOUNDBUFFER
this,LONG vol
180 TRACE(dsound
,"(%p,%ld)\n",this,vol
);
182 this->volfac
= ((double)vol
+10000.0)/10000.0;
187 static HRESULT WINAPI
IDirectSoundBuffer_GetVolume(
188 LPDIRECTSOUNDBUFFER
this,LPLONG vol
190 TRACE(dsound
,"(%p,%p)\n",this,vol
);
195 static HRESULT WINAPI
IDirectSoundBuffer_SetFrequency(
196 LPDIRECTSOUNDBUFFER
this,DWORD freq
198 TRACE(dsound
,"(%p,%ld)\n",this,freq
);
199 this->wfx
.nSamplesPerSec
= freq
;
200 this->wfx
.nAvgBytesPerSec
= freq
*this->wfx
.nChannels
*(this->wfx
.wBitsPerSample
/8);
204 static HRESULT WINAPI
IDirectSoundBuffer_Play(
205 LPDIRECTSOUNDBUFFER
this,DWORD reserved1
,DWORD reserved2
,DWORD flags
207 TRACE(dsound
,"(%p,%08lx,%08lx,%08lx)\n",
208 this,reserved1
,reserved2
,flags
211 this->playflags
= flags
;
216 static HRESULT WINAPI
IDirectSoundBuffer_Stop(LPDIRECTSOUNDBUFFER
this) {
217 TRACE(dsound
,"(%p)\n",this);
219 this->writepos
= 0; /* hmm */
223 static DWORD WINAPI
IDirectSoundBuffer_AddRef(LPDIRECTSOUNDBUFFER
this) {
224 return ++(this->ref
);
226 static DWORD WINAPI
IDirectSoundBuffer_Release(LPDIRECTSOUNDBUFFER
this) {
231 for (i
=0;i
<this->dsound
->nrofbuffers
;i
++)
232 if (this->dsound
->buffers
[i
] == this)
234 if (i
< this->dsound
->nrofbuffers
) {
236 this->dsound
->buffers
+i
,
237 this->dsound
->buffers
+i
+1,
238 sizeof(LPDIRECTSOUNDBUFFER
)*(this->dsound
->nrofbuffers
-i
-1)
240 this->dsound
->buffers
= HeapReAlloc(GetProcessHeap(),0,this->dsound
->buffers
,sizeof(LPDIRECTSOUNDBUFFER
)*this->dsound
->nrofbuffers
);
241 this->dsound
->nrofbuffers
--;
242 this->dsound
->lpvtbl
->fnRelease(this->dsound
);
244 HeapFree(GetProcessHeap(),0,this);
248 static HRESULT WINAPI
IDirectSoundBuffer_GetCurrentPosition(
249 LPDIRECTSOUNDBUFFER
this,LPDWORD playpos
,LPDWORD writepos
251 TRACE(dsound
,"(%p,%p,%p)\n",this,playpos
,writepos
);
252 if (playpos
) *playpos
= this->playpos
;
253 if (writepos
) *writepos
= this->writepos
;
257 static HRESULT WINAPI
IDirectSoundBuffer_GetStatus(
258 LPDIRECTSOUNDBUFFER
this,LPDWORD status
260 TRACE(dsound
,"(%p,%p)\n",this,status
);
263 *status
|= DSBSTATUS_PLAYING
;
264 if (this->playflags
& DSBPLAY_LOOPING
)
265 *status
|= DSBSTATUS_LOOPING
;
269 static HRESULT WINAPI
IDirectSoundBuffer_GetFormat(
270 LPDIRECTSOUNDBUFFER
this,LPWAVEFORMATEX lpwf
,DWORD wfsize
,LPDWORD wfwritten
272 TRACE(dsound
,"(%p,%p,%ld,%p)\n",this,lpwf
,wfsize
,wfwritten
);
273 if (wfsize
>sizeof(this->wfx
)) wfsize
= sizeof(this->wfx
);
274 memcpy(lpwf
,&(this->wfx
),wfsize
);
275 if (wfwritten
) *wfwritten
= wfsize
;
279 static HRESULT WINAPI
IDirectSoundBuffer_Lock(
280 LPDIRECTSOUNDBUFFER
this,DWORD writecursor
,DWORD writebytes
,LPVOID lplpaudioptr1
,LPDWORD audiobytes1
,LPVOID lplpaudioptr2
,LPDWORD audiobytes2
,DWORD flags
283 TRACE(dsound
,"(%p,%ld,%ld,%p,%p,%p,%p,0x%08lx)\n",
293 if (flags
& DSBLOCK_FROMWRITECURSOR
)
294 writecursor
= this->writepos
;
295 assert(audiobytes1
!=audiobytes2
);
296 assert(lplpaudioptr1
!=lplpaudioptr2
);
297 if (writecursor
+writebytes
<= this->buflen
) {
298 *(LPBYTE
*)lplpaudioptr1
= this->buffer
+writecursor
;
299 *audiobytes1
= writebytes
;
301 *(LPBYTE
*)lplpaudioptr2
= NULL
;
304 TRACE(dsound
,"->%ld.0\n",writebytes
);
306 *(LPBYTE
*)lplpaudioptr1
= this->buffer
+writecursor
;
307 *audiobytes1
= this->buflen
-writecursor
;
309 *(LPBYTE
*)lplpaudioptr2
= this->buffer
;
311 *audiobytes2
= writebytes
-(this->buflen
-writecursor
);
312 TRACE(dsound
,"->%ld.%ld\n",*audiobytes1
,audiobytes2
?*audiobytes2
:0);
314 this->writepos
=(writecursor
+writebytes
)%this->buflen
;
318 static HRESULT WINAPI
IDirectSoundBuffer_SetCurrentPosition(
319 LPDIRECTSOUNDBUFFER
this,DWORD newpos
321 TRACE(dsound
,"(%p,%ld)\n",this,newpos
);
322 this->playpos
= newpos
;
326 static HRESULT WINAPI
IDirectSoundBuffer_SetPan(
327 LPDIRECTSOUNDBUFFER
this,LONG newpan
329 TRACE(dsound
,"(%p,%ld)\n",this,newpan
);
334 static HRESULT WINAPI
IDirectSoundBuffer_GetPan(
335 LPDIRECTSOUNDBUFFER
this,LPLONG pan
337 TRACE(dsound
,"(%p,%p)\n",this,pan
);
342 static HRESULT WINAPI
IDirectSoundBuffer_Unlock(
343 LPDIRECTSOUNDBUFFER
this,LPVOID p1
,DWORD x1
,LPVOID p2
,DWORD x2
345 /* FIXME(dsound,"(%p,%p,%ld,%p,%ld):stub\n", this,p1,x1,p2,x2); */
349 static HRESULT WINAPI
IDirectSoundBuffer_GetFrequency(
350 LPDIRECTSOUNDBUFFER
this,LPDWORD freq
352 TRACE(dsound
,"(%p,%p)\n",this,freq
);
353 *freq
= this->wfx
.nSamplesPerSec
;
357 static HRESULT WINAPI
IDirectSoundBuffer_Initialize(
358 LPDIRECTSOUNDBUFFER
this,LPDIRECTSOUND dsound
,LPDSBUFFERDESC dbsd
360 FIXME(dsound
,"(%p,%p,%p):stub\n",this,dsound
,dbsd
);
361 printf("Re-Init!!!\n");
362 return DSERR_ALREADYINITIALIZED
;
365 static HRESULT WINAPI
IDirectSoundBuffer_GetCaps(
366 LPDIRECTSOUNDBUFFER
this,LPDSBCAPS caps
368 caps
->dwSize
= sizeof(*caps
);
369 caps
->dwFlags
= DSBCAPS_PRIMARYBUFFER
|DSBCAPS_STATIC
|DSBCAPS_CTRLALL
|DSBCAPS_LOCSOFTWARE
;
370 caps
->dwBufferBytes
= 0;
371 caps
->dwUnlockTransferRate
= 0;
372 caps
->dwPlayCpuOverhead
= 0;
376 static HRESULT WINAPI
IDirectSoundBuffer_QueryInterface(
377 LPDIRECTSOUNDBUFFER
this,REFIID riid
,LPVOID
*ppobj
381 if (!memcmp(&IID_IDirectSoundNotify
,riid
,sizeof(*riid
))) {
382 IDirectSoundNotify
*dsn
;
384 dsn
= (LPDIRECTSOUNDNOTIFY
)HeapAlloc(GetProcessHeap(),0,sizeof(*dsn
));
387 this->lpvtbl
->fnAddRef(this);
388 dsn
->lpvtbl
= &dsnvt
;
389 *ppobj
= (LPVOID
)dsn
;
392 WINE_StringFromCLSID(riid
,xbuf
);
393 TRACE(dsound
,"(%p,%s,%p)\n",this,xbuf
,ppobj
);
397 static struct tagLPDIRECTSOUNDBUFFER_VTABLE dsbvt
= {
398 IDirectSoundBuffer_QueryInterface
,
399 IDirectSoundBuffer_AddRef
,
400 IDirectSoundBuffer_Release
,
401 IDirectSoundBuffer_GetCaps
,
402 IDirectSoundBuffer_GetCurrentPosition
,
403 IDirectSoundBuffer_GetFormat
,
404 IDirectSoundBuffer_GetVolume
,
405 IDirectSoundBuffer_GetPan
,
406 IDirectSoundBuffer_GetFrequency
,
407 IDirectSoundBuffer_GetStatus
,
408 IDirectSoundBuffer_Initialize
,
409 IDirectSoundBuffer_Lock
,
410 IDirectSoundBuffer_Play
,
411 IDirectSoundBuffer_SetCurrentPosition
,
412 IDirectSoundBuffer_SetFormat
,
413 IDirectSoundBuffer_SetVolume
,
414 IDirectSoundBuffer_SetPan
,
415 IDirectSoundBuffer_SetFrequency
,
416 IDirectSoundBuffer_Stop
,
417 IDirectSoundBuffer_Unlock
420 /*******************************************************************************
424 static HRESULT WINAPI
IDirectSound_SetCooperativeLevel(
425 LPDIRECTSOUND
this,HWND32 hwnd
,DWORD level
427 FIXME(dsound
,"(%p,%08lx,%ld):stub\n",this,(DWORD
)hwnd
,level
);
432 static HRESULT WINAPI
IDirectSound_CreateSoundBuffer(
433 LPDIRECTSOUND
this,LPDSBUFFERDESC dsbd
,LPLPDIRECTSOUNDBUFFER ppdsb
,LPUNKNOWN lpunk
435 if (TRACE_ON(dsound
)) {
436 TRACE(dsound
,"(%p,%p,%p,%p)\n",this,dsbd
,ppdsb
,lpunk
);
437 TRACE(dsound
,"(size=%ld)\n",dsbd
->dwSize
);
438 TRACE(dsound
,"(flags=0x%08lx\n",dsbd
->dwFlags
);
439 _dump_DSBCAPS(dsbd
->dwFlags
);
440 TRACE(dsound
,"(bufferbytes=%ld)\n",dsbd
->dwBufferBytes
);
441 TRACE(dsound
,"(lpwfxFormat=%p)\n",dsbd
->lpwfxFormat
);
443 *ppdsb
= (LPDIRECTSOUNDBUFFER
)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(IDirectSoundBuffer
));
445 (*ppdsb
)->buffer
= (LPBYTE
)HeapAlloc(GetProcessHeap(),0,dsbd
->dwBufferBytes
);
446 (*ppdsb
)->buflen
= dsbd
->dwBufferBytes
;
447 (*ppdsb
)->playpos
= 0;
448 (*ppdsb
)->writepos
= 0;
449 (*ppdsb
)->lpvtbl
= &dsbvt
;
450 (*ppdsb
)->dsound
= this;
451 (*ppdsb
)->playing
= 0;
452 (*ppdsb
)->volfac
= 1.0;
453 memcpy(&((*ppdsb
)->dsbd
),dsbd
,sizeof(*dsbd
));
455 /* register buffer */
456 this->buffers
= (LPDIRECTSOUNDBUFFER
*)HeapReAlloc(GetProcessHeap(),0,this->buffers
,sizeof(LPDIRECTSOUNDBUFFER
)*(this->nrofbuffers
+1));
457 this->buffers
[this->nrofbuffers
] = *ppdsb
;
459 this->lpvtbl
->fnAddRef(this);
461 if (dsbd
->lpwfxFormat
) dsbvt
.fnSetFormat(*ppdsb
,dsbd
->lpwfxFormat
);
465 static HRESULT WINAPI
IDirectSound_DuplicateSoundBuffer(
466 LPDIRECTSOUND
this,LPDIRECTSOUNDBUFFER pdsb
,LPLPDIRECTSOUNDBUFFER ppdsb
468 TRACE(dsound
,"(%p,%p,%p)\n",this,pdsb
,ppdsb
);
470 *ppdsb
= (LPDIRECTSOUNDBUFFER
)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(IDirectSoundBuffer
));
472 (*ppdsb
)->buffer
= (LPBYTE
)HeapAlloc(GetProcessHeap(),0,pdsb
->buflen
);
473 memcpy((*ppdsb
)->buffer
,pdsb
->buffer
,pdsb
->buflen
);
474 (*ppdsb
)->buflen
= pdsb
->buflen
;
475 (*ppdsb
)->playpos
= 0;
476 (*ppdsb
)->writepos
= 0;
477 (*ppdsb
)->lpvtbl
= &dsbvt
;
478 (*ppdsb
)->dsound
= this;
479 dsbvt
.fnSetFormat(*ppdsb
,&(pdsb
->wfx
));
480 /* register buffer */
481 this->buffers
= (LPDIRECTSOUNDBUFFER
*)HeapReAlloc(GetProcessHeap(),0,this->buffers
,sizeof(LPDIRECTSOUNDBUFFER
)*(this->nrofbuffers
+1));
482 this->buffers
[this->nrofbuffers
] = *ppdsb
;
484 this->lpvtbl
->fnAddRef(this);
489 static HRESULT WINAPI
IDirectSound_GetCaps(LPDIRECTSOUND
this,LPDSCAPS caps
) {
490 TRACE(dsound
,"(%p,%p)\n",this,caps
);
491 TRACE(dsound
,"(flags=0x%08lx)\n",caps
->dwFlags
);
493 caps
->dwSize
= sizeof(*caps
);
494 caps
->dwFlags
= DSCAPS_PRIMARYSTEREO
|DSCAPS_PRIMARY16BIT
|DSCAPS_EMULDRIVER
|DSCAPS_SECONDARYSTEREO
|DSCAPS_SECONDARY16BIT
;
495 /* FIXME: query OSS */
496 caps
->dwMinSecondarySampleRate
= 22050;
497 caps
->dwMaxSecondarySampleRate
= 48000;
498 caps
->dwPrimaryBuffers
= 1;
499 /* FIXME: set the rest... hmm */
503 static ULONG WINAPI
IDirectSound_AddRef(LPDIRECTSOUND
this) {
504 return ++(this->ref
);
507 static ULONG WINAPI
IDirectSound_Release(LPDIRECTSOUND
this) {
508 if (!--(this->ref
)) {
509 HeapFree(GetProcessHeap(),0,this);
511 close(audiofd
);audiofd
= -1;
517 static HRESULT WINAPI
IDirectSound_SetSpeakerConfig(
518 LPDIRECTSOUND
this,DWORD config
520 FIXME(dsound
,"(%p,0x%08lx):stub\n",this,config
);
524 static HRESULT WINAPI
IDirectSound_QueryInterface(
525 LPDIRECTSOUND
this,REFIID riid
,LPVOID
*ppobj
529 WINE_StringFromCLSID(riid
,xbuf
);
530 TRACE(dsound
,"(%p,%s,%p)\n",this,xbuf
,ppobj
);
534 static struct tagLPDIRECTSOUND_VTABLE dsvt
= {
535 IDirectSound_QueryInterface
,
537 IDirectSound_Release
,
538 IDirectSound_CreateSoundBuffer
,
539 IDirectSound_GetCaps
,
540 IDirectSound_DuplicateSoundBuffer
,
541 IDirectSound_SetCooperativeLevel
,
544 IDirectSound_SetSpeakerConfig
,
549 DSOUND_setformat(LPWAVEFORMATEX wfex
) {
550 int xx
,channels
,speed
,format
,nformat
;
553 switch (wfex
->wFormatTag
) {
555 WARN(dsound
,"unknown WAVE_FORMAT tag %d\n",wfex
->wFormatTag
);
556 return DSERR_BADFORMAT
;
557 case WAVE_FORMAT_PCM
:
560 if (wfex
->wBitsPerSample
==8)
563 format
= AFMT_S16_LE
;
565 if (-1==ioctl(audiofd
,SNDCTL_DSP_GETFMTS
,&xx
)) {
566 perror("ioctl SNDCTL_DSP_GETFMTS");
569 if ((xx
&format
)!=format
) {/* format unsupported */
570 WARN(dsound
,"SNDCTL_DSP_GETFMTS: format not supported\n");
574 if (-1==ioctl(audiofd
,SNDCTL_DSP_SETFMT
,&nformat
)) {
575 perror("ioctl SNDCTL_DSP_SETFMT");
578 if (nformat
!=format
) {/* didn't work */
579 WARN(dsound
,"SNDCTL_DSP_GETFMTS: format not set\n");
583 channels
= wfex
->nChannels
-1;
584 if (-1==ioctl(audiofd
,SNDCTL_DSP_STEREO
,&channels
)) {
585 perror("ioctl SNDCTL_DSP_STEREO");
588 speed
= wfex
->nSamplesPerSec
;
589 if (-1==ioctl(audiofd
,SNDCTL_DSP_SPEED
,&speed
)) {
590 perror("ioctl SNDCTL_DSP_SPEED");
593 TRACE(dsound
,"(freq=%ld,channels=%d,bits=%d)\n",
594 wfex
->nSamplesPerSec
,wfex
->nChannels
,wfex
->wBitsPerSample
599 static LPDSBPOSITIONNOTIFY
600 DSOUND_nextevent(IDirectSoundBuffer
*dsb
) {
603 if (dsb
->nrofnotifies
) {
604 for (i
=0;i
<dsb
->nrofnotifies
;i
++) {
605 if (dsb
->playpos
<dsb
->notifies
[i
].dwOffset
)
608 if (i
==dsb
->nrofnotifies
)
610 return dsb
->notifies
+i
;
615 #define CHECK_EVENT \
616 if (nextevent && (dsb->playpos == nextevent->dwOffset)) { \
617 SetEvent(nextevent->hEventNotify); \
618 TRACE(dsound,"signalled event %d\n",nextevent->hEventNotify);\
619 nextevent = DSOUND_nextevent(dsb); \
624 DSOUND_MixInBuffer(IDirectSoundBuffer
*dsb
) {
625 int j
,buflen
= dsb
->buflen
;
626 LPDSBPOSITIONNOTIFY nextevent
;
627 int xdiff
= dsb
->wfx
.nSamplesPerSec
-dsound
->wfx
.nSamplesPerSec
;
629 /* Insomnia - Going along with REAL author's style */
630 long Rvoldec
, Lvoldec
;
632 long samp
; /* temporary sample workspace */
635 double tmpr
=dsb
->volume
-500;
637 if(pan
>0) tmpl
-= (double)pan
;
638 else tmpr
+= (double)pan
;
641 tmpl
= pow(2.0, tmpl
);
642 tmpr
= pow(2.0, tmpr
);
643 tmpl
*= 65536; /* Set to the correct multiple times */
644 tmpr
*= 65536; /* 65536 to be convenient for bit shifting */
645 tmpl
+= 0.5; /* Add .5 for rounding accuracy */
647 Lvoldec
= (long)tmpl
;
648 Rvoldec
= (long)tmpr
;
650 /* End Insomnia's mod */
652 if (xdiff
<0) xdiff
=-xdiff
;
654 WARN(dsound
,"mixing in buffer of different frequency (%ld vs %ld), argh!\n",
655 dsb
->wfx
.nSamplesPerSec
,dsound
->wfx
.nSamplesPerSec
);
657 nextevent
= DSOUND_nextevent(dsb
);
658 /* TRACE(dsound,"(%d.%d.%d.%d)\n",dsound->wfx.wBitsPerSample,dsb->wfx.wBitsPerSample,dsound->wfx.nChannels,dsb->wfx.nChannels);*/
660 if (dsound
->wfx
.wBitsPerSample
== 8) {
661 char *playbuf8
= (char*)playbuf
;
663 if (dsb
->wfx
.wBitsPerSample
== 8) {
664 unsigned char *xbuf
= (unsigned char*)(dsb
->buffer
);
665 if (dsb
->wfx
.nChannels
== 1) {
666 for (j
=0;j
<sizeof(playbuf
)/2;j
++) {
668 dsb
->playpos
=(dsb
->playpos
+1)%buflen
;
669 if (!dsb
->playpos
&& !(dsb
->playflags
&DSBPLAY_LOOPING
)) {
671 dsb
->playpos
= buflen
;
674 /* Insomnia- volume, panning, and correcting against wrap */
676 samp
= xbuf
[dsb
->playpos
>>1];
679 samp
+= playbuf8
[(j
<<1)];
680 if(samp
> 127L) samp
= 127L;
681 else if(samp
< -128L) samp
= -128L;
682 playbuf8
[(j
<<1)] = (short)samp
;
685 samp
= xbuf
[dsb
->playpos
>>1];
688 samp
+= playbuf8
[(j
<<1)+1];
689 if(samp
> 127L) samp
= 127L;
690 else if(samp
< -128L) samp
= -128L;
691 playbuf8
[(j
<<1)+1] = (short)samp
;
692 /* End Insomnia's mod */
697 for (j
=0;j
<sizeof(playbuf
);j
++) {
698 dsb
->playpos
=(dsb
->playpos
+1)%buflen
;
699 if (!dsb
->playpos
&& !(dsb
->playflags
&DSBPLAY_LOOPING
)) {
701 dsb
->playpos
= buflen
;
704 /* Insomnia- volume, panning, and correcting against wrap */
705 samp
= xbuf
[dsb
->playpos
>>1];
708 if(j
&1) samp
*= Rvoldec
;
710 else samp
*= Lvoldec
;
714 if(samp
> 127L) samp
= 127L;
715 else if(samp
< -128L) samp
= -128L;
716 playbuf8
[j
] = (short)samp
;
717 /* End Insomnia's mod */
723 short *xbuf
= (short*)(dsb
->buffer
);
724 if (dsb
->wfx
.nChannels
== 1) {
725 for (j
=0;j
<sizeof(playbuf
)/2;j
++) {
726 dsb
->playpos
=(dsb
->playpos
+2)%buflen
;
727 if (!dsb
->playpos
&& !(dsb
->playflags
&DSBPLAY_LOOPING
)) {
729 dsb
->playpos
= buflen
;
732 /* Insomnia- volume, panning, and correcting against wrap */
734 samp
= xbuf
[dsb
->playpos
>>1];
737 samp
+= playbuf8
[(j
<<1)];
738 if(samp
> 127L) samp
= 127L;
739 else if(samp
< -128L) samp
= -128L;
740 playbuf8
[(j
<<1)] = (short)samp
;
743 samp
= xbuf
[dsb
->playpos
>>1];
746 samp
+= playbuf8
[(j
<<1)+1];
747 if(samp
> 127L) samp
= 127L;
748 else if(samp
< -128L) samp
= -128L;
749 playbuf8
[(j
<<1)+1] = (short)samp
;
750 /* End Insomnia's mod */
755 for (j
=0;j
<sizeof(playbuf
);j
++) {
756 dsb
->playpos
=(dsb
->playpos
+2)%buflen
;
757 if (!dsb
->playpos
&& !(dsb
->playflags
&DSBPLAY_LOOPING
)) {
759 dsb
->playpos
= buflen
;
762 /* Insomnia- volume, panning, and correcting against wrap */
763 samp
= xbuf
[dsb
->playpos
>>1];
766 if(j
&1) samp
*= Rvoldec
;
768 else samp
*= Lvoldec
;
772 if(samp
> 127L) samp
= 127L;
773 else if(samp
< -128L) samp
= -128L;
774 playbuf8
[j
] = (short)samp
;
775 /* End Insomnia's mod */
781 } else { /* 16 bit */
782 if (dsb
->wfx
.wBitsPerSample
== 8) {
783 /* unsigned char *xbuf = (unsigned char*)(dsb->buffer); */
784 char *xbuf
= dsb
->buffer
;
785 if (dsb
->wfx
.nChannels
== 1) {
786 printf("Mixing 8-bit stereo into 16!!\n");
787 for (j
=0;j
<sizeof(playbuf
)/sizeof(playbuf
[0])/2;j
++) {
788 dsb
->playpos
=(dsb
->playpos
+1)%buflen
;
789 if (!dsb
->playpos
&& !(dsb
->playflags
&DSBPLAY_LOOPING
)) {
791 dsb
->playpos
= buflen
;
794 /* Insomnia- volume, panning, and correcting against wrap */
796 samp
= xbuf
[dsb
->playpos
>>1];
799 samp
+= playbuf
[(j
<<1)];
800 if(samp
> 32767L) samp
= 32767L;
801 else if(samp
< -32768L) samp
= -32768L;
802 playbuf
[(j
<<1)] = (short)samp
;
805 samp
= xbuf
[dsb
->playpos
>>1];
808 samp
+= playbuf
[(j
<<1)+1];
809 if(samp
> 32767L) samp
= 32767L;
810 else if(samp
< -32768L) samp
= -32768L;
811 playbuf
[(j
<<1)+1] = (short)samp
;
812 /* End Insomnia's mod */
817 for (j
=0;j
<sizeof(playbuf
)/sizeof(playbuf
[0]);j
++) {
818 dsb
->playpos
=(dsb
->playpos
+1)%buflen
;
819 if (!dsb
->playpos
&& !(dsb
->playflags
&DSBPLAY_LOOPING
)) {
821 dsb
->playpos
= buflen
;
824 /* Insomnia- volume, panning, and correcting against wrap */
825 samp
= xbuf
[dsb
->playpos
>>1];
828 if(j
&1) samp
*= Rvoldec
;
830 else samp
*= Lvoldec
;
834 if(samp
> 32767L) samp
= 32767L;
835 else if(samp
< -32768L) samp
= -32768L;
836 playbuf
[j
] = (short)samp
;
837 /* End Insomnia's mod */
843 short *xbuf
= (short*)(dsb
->buffer
);
844 if (dsb
->wfx
.nChannels
== 1) {
845 for (j
=0;j
<sizeof(playbuf
)/sizeof(playbuf
[0])/2;j
++) {
846 dsb
->playpos
=(dsb
->playpos
+2)%buflen
;
847 if (!dsb
->playpos
&& !(dsb
->playflags
&DSBPLAY_LOOPING
)) {
849 dsb
->playpos
= buflen
;
852 /* Insomnia- volume, panning, and correcting against wrap */
854 samp
= xbuf
[dsb
->playpos
>>1];
857 samp
+= playbuf
[(j
<<1)];
858 if(samp
> 32767L) samp
= 32767L;
859 else if(samp
< -32768L) samp
= -32768L;
860 playbuf
[(j
<<1)] = (short)samp
;
863 samp
= xbuf
[dsb
->playpos
>>1];
866 samp
+= playbuf
[(j
<<1)+1];
867 if(samp
> 32767L) samp
= 32767L;
868 else if(samp
< -32768L) samp
= -32768L;
869 playbuf
[(j
<<1)+1] = (short)samp
;
870 /* End Insomnia's mod */
875 for (j
=0;j
<sizeof(playbuf
)/sizeof(playbuf
[0]);j
++) {
876 dsb
->playpos
=(dsb
->playpos
+2)%buflen
;
877 if (!dsb
->playpos
&& !(dsb
->playflags
&DSBPLAY_LOOPING
)) {
879 dsb
->playpos
= buflen
;
882 /* Insomnia- volume, panning, and correcting against wrap */
883 samp
= xbuf
[dsb
->playpos
>>1];
886 if(j
&1) samp
*= Rvoldec
;
888 else samp
*= Lvoldec
;
892 if(samp
> 32767L) samp
= 32767L;
893 else if(samp
< -32768L) samp
= -32768L;
894 playbuf
[j
] = (short)samp
;
895 /* End Insomnia's mod */
905 DSOUND_thread(LPVOID arg
) {
906 int res
,i
,curleft
,playing
,haveprimary
= 0;
908 TRACE(dsound
,"dsound is at pid %d\n",getpid());
911 WARN(dsound
,"DSOUND thread giving up.\n");
915 WARN(dsound
,"DSOUND father died? Giving up.\n");
918 /* RACE: dsound could be deleted */
919 dsound
->lpvtbl
->fnAddRef(dsound
);
920 if (!dsound
->nrofbuffers
) {
921 /* no soundbuffer yet... wait. */
925 memset(playbuf
,0,sizeof(playbuf
));
927 dsound
->lpvtbl
->fnAddRef(dsound
);
929 for (i
=dsound
->nrofbuffers
;i
--;) {
930 IDirectSoundBuffer
*dsb
= dsound
->buffers
[i
];
932 if (!dsb
|| !dsb
->lpvtbl
)
934 dsb
->lpvtbl
->fnAddRef(dsb
);
935 if (dsb
->playing
&& dsb
->buflen
)
937 if (dsb
->dsbd
.dwFlags
& DSBCAPS_PRIMARYBUFFER
) {
939 if (memcmp(&dsound
->wfx
,&(dsb
->wfx
),sizeof(dsound
->wfx
))) {
940 DSOUND_setformat(&(dsb
->wfx
));
941 memcpy(&dsound
->wfx
,&(dsb
->wfx
),sizeof(dsb
->wfx
));
944 dsb
->lpvtbl
->fnRelease(dsb
);
946 /* We have just one playbuffer, so use its format */
947 if ((playing
==1) && !haveprimary
) {
948 for (i
=dsound
->nrofbuffers
;i
--;) {
949 IDirectSoundBuffer
*dsb
= dsound
->buffers
[i
];
951 dsb
->lpvtbl
->fnAddRef(dsb
);
952 if (dsb
->playing
&& dsb
->buflen
) {
953 if (memcmp(&dsound
->wfx
,&(dsb
->wfx
),sizeof(dsound
->wfx
))) {
954 DSOUND_setformat(&(dsb
->wfx
));
955 memcpy(&dsound
->wfx
,&(dsb
->wfx
),sizeof(dsb
->wfx
));
958 dsb
->lpvtbl
->fnRelease(dsb
);
961 for (i
=dsound
->nrofbuffers
;i
--;) {
962 IDirectSoundBuffer
*dsb
= dsound
->buffers
[i
];
964 if (!dsb
|| !dsb
->lpvtbl
)
966 dsb
->lpvtbl
->fnAddRef(dsb
);
967 if (dsb
->buflen
&& dsb
->playing
) {
969 DSOUND_MixInBuffer(dsb
);
971 dsb
->lpvtbl
->fnRelease(dsb
);
973 dsound
->lpvtbl
->fnRelease(dsound
);
975 /*fputc('0'+playing,stderr);*/
977 while (curleft
< sizeof(playbuf
)) {
978 res
= write(audiofd
,(LPBYTE
)playbuf
+curleft
,sizeof(playbuf
)-curleft
);
980 perror("write audiofd");
990 #endif /* HAVE_OSS */
992 HRESULT WINAPI
DirectSoundCreate(LPGUID lpGUID
,LPDIRECTSOUND
*ppDS
,IUnknown
*pUnkOuter
) {
995 TRACE(dsound
,"(%p,%p,%p)\n",lpGUID
,ppDS
,pUnkOuter
);
998 return DSERR_ALLOCATED
;
999 audiofd
= open("/dev/audio",O_WRONLY
);
1001 perror("open /dev/audio");
1003 return DSERR_NODRIVER
;
1006 if (-1==ioctl(audiofd
,SNDCTL_DSP_SETFRAGMENT
,&xx
))
1007 perror("ioctl SETFRAGMENT");
1009 TRACE(dsound,"SETFRAGMENT. count is now %d, fragsize is %d\n",
1010 (xx>>16)+1,xx&0xffff
1014 *ppDS
= (LPDIRECTSOUND
)HeapAlloc(GetProcessHeap(),0,sizeof(IDirectSound
));
1016 (*ppDS
)->lpvtbl
= &dsvt
;
1017 (*ppDS
)->buffers
= NULL
;
1018 (*ppDS
)->nrofbuffers
= 0;
1020 (*ppDS
)->wfx
.wFormatTag
= 1;
1021 (*ppDS
)->wfx
.nChannels
= 2;
1022 (*ppDS
)->wfx
.nSamplesPerSec
= 22050;
1023 (*ppDS
)->wfx
.nAvgBytesPerSec
= 44100;
1024 (*ppDS
)->wfx
.nBlockAlign
= 2;
1025 (*ppDS
)->wfx
.wBitsPerSample
= 8;
1027 DSOUND_setformat(&((*ppDS
)->wfx
));
1034 hnd
= CreateThread(NULL
,0,DSOUND_thread
,0,0,&xid
);
1038 MessageBox32A(0,"DirectSound needs the Open Sound System Driver, which has not been found by ./configure.","WINE DirectSound",MB_OK
|MB_ICONSTOP
);
1039 return DSERR_NODRIVER
;
1044 /*******************************************************************************
1045 * DllGetClassObject [DSOUND.4]
1046 * Retrieves class object from a DLL object
1049 * Docs say returns STDAPI
1052 * rclsid [I] CLSID for the class object
1053 * riid [I] Reference to identifier of interface for class object
1054 * ppv [O] Address of variable to receive interface pointer for riid
1058 * Failure: CLASS_E_CLASSNOTAVAILABLE, E_OUTOFMEMORY, E_INVALIDARG,
1061 DWORD WINAPI
DllGetClassObject( REFCLSID rclsid
, REFIID riid
, LPVOID
*ppv
)
1063 FIXME(dsound
, "(%p,%p,%p): stub\n", rclsid
, riid
, ppv
);
1068 /*******************************************************************************
1069 * DllCanUnloadNow [DSOUND.3] Determines whether the DLL is in use.
1075 DWORD WINAPI
DllCanUnloadNow(void)
1077 FIXME(dsound
, "(void): stub\n");