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.
34 #include <sys/types.h>
36 #include <sys/fcntl.h>
40 #include <math.h> /* Insomnia - pow() function */
43 #include "interfaces.h"
50 # include <sys/ioctl.h>
51 # ifdef HAVE_MACHINE_SOUNDCARD_H
52 # include <machine/soundcard.h>
54 # ifdef HAVE_SYS_SOUNDCARD_H
55 # include <sys/soundcard.h>
58 static int audiofd = -1;
59 static LPDIRECTSOUND dsound = NULL;
61 static short playbuf[2048];
65 HRESULT WINAPI DirectSoundEnumerate32A(LPDSENUMCALLBACK32A enumcb,LPVOID context) {
67 enumcb(NULL,"WINE DirectSound using Open Sound System","sound",context);
73 static void _dump_DSBCAPS(DWORD xmask) {
78 #define FE(x) { x, #x },
79 FE(DSBCAPS_PRIMARYBUFFER)
81 FE(DSBCAPS_LOCHARDWARE)
82 FE(DSBCAPS_LOCSOFTWARE)
83 FE(DSBCAPS_CTRLFREQUENCY)
85 FE(DSBCAPS_CTRLVOLUME)
86 FE(DSBCAPS_CTRLDEFAULT)
88 FE(DSBCAPS_STICKYFOCUS)
89 FE(DSBCAPS_GETCURRENTPOSITION2)
93 for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
94 if (flags[i].mask & xmask)
95 fprintf(stderr,"%s ",flags[i].name);
98 /*******************************************************************************
101 static HRESULT WINAPI IDirectSoundNotify_QueryInterface(
102 LPDIRECTSOUNDNOTIFY this,REFIID riid,LPVOID *ppobj
106 WINE_StringFromCLSID(riid,xbuf);
107 TRACE(dsound,"(%p,%s,%p)\n",this,xbuf,ppobj);
111 static ULONG WINAPI IDirectSoundNotify_AddRef(LPDIRECTSOUNDNOTIFY this) {
112 return ++(this->ref);
115 static ULONG WINAPI IDirectSoundNotify_Release(LPDIRECTSOUNDNOTIFY this) {
118 this->dsb->lpvtbl->fnRelease(this->dsb);
119 HeapFree(GetProcessHeap(),0,this);
125 static int _sort_notifies(const void *a,const void *b) {
126 LPDSBPOSITIONNOTIFY na = (LPDSBPOSITIONNOTIFY)a;
127 LPDSBPOSITIONNOTIFY nb = (LPDSBPOSITIONNOTIFY)b;
129 return na->dwOffset-nb->dwOffset;
132 static HRESULT WINAPI IDirectSoundNotify_SetNotificationPositions(
133 LPDIRECTSOUNDNOTIFY this,DWORD howmuch,LPCDSBPOSITIONNOTIFY notify
137 if (TRACE_ON(dsound)) {
138 TRACE(dsound,"(%p,0x%08lx,%p)\n",this,howmuch,notify);
139 for (i=0;i<howmuch;i++)
140 TRACE(dsound,"notify at %ld to 0x%08lx\n",
141 notify[i].dwOffset,(DWORD)notify[i].hEventNotify);
143 this->dsb->notifies = HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,this->dsb->notifies,(this->dsb->nrofnotifies+howmuch)*sizeof(DSBPOSITIONNOTIFY));
144 memcpy( this->dsb->notifies+this->dsb->nrofnotifies,
146 howmuch*sizeof(DSBPOSITIONNOTIFY)
148 this->dsb->nrofnotifies+=howmuch;
149 qsort(this->dsb->notifies,this->dsb->nrofnotifies,sizeof(DSBPOSITIONNOTIFY),_sort_notifies);
153 IDirectSoundNotify_VTable dsnvt = {
154 IDirectSoundNotify_QueryInterface,
155 IDirectSoundNotify_AddRef,
156 IDirectSoundNotify_Release,
157 IDirectSoundNotify_SetNotificationPositions,
160 /*******************************************************************************
163 static HRESULT WINAPI IDirectSoundBuffer_SetFormat(
164 LPDIRECTSOUNDBUFFER this,LPWAVEFORMATEX wfex
167 memcpy(&(this->wfx),wfex,sizeof(this->wfx));
168 TRACE(dsound,"(%p,%p)\n", this,wfex);
169 TRACE(dsound,"(formattag=0x%04x,chans=%d,samplerate=%ld"
170 "bytespersec=%ld,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
171 wfex->wFormatTag, wfex->nChannels, wfex->nSamplesPerSec,
172 wfex->nAvgBytesPerSec, wfex->nBlockAlign,
173 wfex->wBitsPerSample, wfex->cbSize);
178 static HRESULT WINAPI IDirectSoundBuffer_SetVolume(
179 LPDIRECTSOUNDBUFFER this,LONG vol
181 TRACE(dsound,"(%p,%ld)\n",this,vol);
183 this->volfac = ((double)vol+10000.0)/10000.0;
188 static HRESULT WINAPI IDirectSoundBuffer_GetVolume(
189 LPDIRECTSOUNDBUFFER this,LPLONG vol
191 TRACE(dsound,"(%p,%p)\n",this,vol);
196 static HRESULT WINAPI IDirectSoundBuffer_SetFrequency(
197 LPDIRECTSOUNDBUFFER this,DWORD freq
199 TRACE(dsound,"(%p,%ld)\n",this,freq);
200 this->wfx.nSamplesPerSec = freq;
201 this->wfx.nAvgBytesPerSec = freq*this->wfx.nChannels*(this->wfx.wBitsPerSample/8);
205 static HRESULT WINAPI IDirectSoundBuffer_Play(
206 LPDIRECTSOUNDBUFFER this,DWORD reserved1,DWORD reserved2,DWORD flags
208 TRACE(dsound,"(%p,%08lx,%08lx,%08lx)\n",
209 this,reserved1,reserved2,flags
212 this->playflags = flags;
217 static HRESULT WINAPI IDirectSoundBuffer_Stop(LPDIRECTSOUNDBUFFER this) {
218 TRACE(dsound,"(%p)\n",this);
220 this->writepos = 0; /* hmm */
224 static DWORD WINAPI IDirectSoundBuffer_AddRef(LPDIRECTSOUNDBUFFER this) {
225 return ++(this->ref);
227 static DWORD WINAPI IDirectSoundBuffer_Release(LPDIRECTSOUNDBUFFER this) {
232 for (i=0;i<this->dsound->nrofbuffers;i++)
233 if (this->dsound->buffers[i] == this)
235 if (i < this->dsound->nrofbuffers) {
237 this->dsound->buffers+i,
238 this->dsound->buffers+i+1,
239 sizeof(LPDIRECTSOUNDBUFFER)*(this->dsound->nrofbuffers-i-1)
241 this->dsound->buffers = HeapReAlloc(GetProcessHeap(),0,this->dsound->buffers,sizeof(LPDIRECTSOUNDBUFFER)*this->dsound->nrofbuffers);
242 this->dsound->nrofbuffers--;
243 this->dsound->lpvtbl->fnRelease(this->dsound);
245 HeapFree(GetProcessHeap(),0,this->buffer);
246 HeapFree(GetProcessHeap(),0,this);
250 static HRESULT WINAPI IDirectSoundBuffer_GetCurrentPosition(
251 LPDIRECTSOUNDBUFFER this,LPDWORD playpos,LPDWORD writepos
253 TRACE(dsound,"(%p,%p,%p)\n",this,playpos,writepos);
254 if (playpos) *playpos = this->playpos;
255 if (writepos) *writepos = this->writepos;
259 static HRESULT WINAPI IDirectSoundBuffer_GetStatus(
260 LPDIRECTSOUNDBUFFER this,LPDWORD status
262 TRACE(dsound,"(%p,%p)\n",this,status);
265 *status |= DSBSTATUS_PLAYING;
266 if (this->playflags & DSBPLAY_LOOPING)
267 *status |= DSBSTATUS_LOOPING;
271 static HRESULT WINAPI IDirectSoundBuffer_GetFormat(
272 LPDIRECTSOUNDBUFFER this,LPWAVEFORMATEX lpwf,DWORD wfsize,LPDWORD wfwritten
274 TRACE(dsound,"(%p,%p,%ld,%p)\n",this,lpwf,wfsize,wfwritten);
275 if (wfsize>sizeof(this->wfx)) wfsize = sizeof(this->wfx);
276 memcpy(lpwf,&(this->wfx),wfsize);
277 if (wfwritten) *wfwritten = wfsize;
281 static HRESULT WINAPI IDirectSoundBuffer_Lock(
282 LPDIRECTSOUNDBUFFER this,DWORD writecursor,DWORD writebytes,LPVOID lplpaudioptr1,LPDWORD audiobytes1,LPVOID lplpaudioptr2,LPDWORD audiobytes2,DWORD flags
285 TRACE(dsound,"(%p,%ld,%ld,%p,%p,%p,%p,0x%08lx)\n",
295 if (flags & DSBLOCK_FROMWRITECURSOR)
296 writecursor = this->writepos;
297 assert(audiobytes1!=audiobytes2);
298 assert(lplpaudioptr1!=lplpaudioptr2);
299 if (writecursor+writebytes <= this->buflen) {
300 *(LPBYTE*)lplpaudioptr1 = this->buffer+writecursor;
301 *audiobytes1 = writebytes;
303 *(LPBYTE*)lplpaudioptr2 = NULL;
306 TRACE(dsound,"->%ld.0\n",writebytes);
308 *(LPBYTE*)lplpaudioptr1 = this->buffer+writecursor;
309 *audiobytes1 = this->buflen-writecursor;
311 *(LPBYTE*)lplpaudioptr2 = this->buffer;
313 *audiobytes2 = writebytes-(this->buflen-writecursor);
314 TRACE(dsound,"->%ld.%ld\n",*audiobytes1,audiobytes2?*audiobytes2:0);
316 this->writepos=(writecursor+writebytes)%this->buflen;
320 static HRESULT WINAPI IDirectSoundBuffer_SetCurrentPosition(
321 LPDIRECTSOUNDBUFFER this,DWORD newpos
323 TRACE(dsound,"(%p,%ld)\n",this,newpos);
324 this->playpos = newpos;
328 static HRESULT WINAPI IDirectSoundBuffer_SetPan(
329 LPDIRECTSOUNDBUFFER this,LONG newpan
331 TRACE(dsound,"(%p,%ld)\n",this,newpan);
336 static HRESULT WINAPI IDirectSoundBuffer_GetPan(
337 LPDIRECTSOUNDBUFFER this,LPLONG pan
339 TRACE(dsound,"(%p,%p)\n",this,pan);
344 static HRESULT WINAPI IDirectSoundBuffer_Unlock(
345 LPDIRECTSOUNDBUFFER this,LPVOID p1,DWORD x1,LPVOID p2,DWORD x2
347 /* FIXME(dsound,"(%p,%p,%ld,%p,%ld):stub\n", this,p1,x1,p2,x2); */
351 static HRESULT WINAPI IDirectSoundBuffer_GetFrequency(
352 LPDIRECTSOUNDBUFFER this,LPDWORD freq
354 TRACE(dsound,"(%p,%p)\n",this,freq);
355 *freq = this->wfx.nSamplesPerSec;
359 static HRESULT WINAPI IDirectSoundBuffer_Initialize(
360 LPDIRECTSOUNDBUFFER this,LPDIRECTSOUND dsound,LPDSBUFFERDESC dbsd
362 FIXME(dsound,"(%p,%p,%p):stub\n",this,dsound,dbsd);
363 printf("Re-Init!!!\n");
364 return DSERR_ALREADYINITIALIZED;
367 static HRESULT WINAPI IDirectSoundBuffer_GetCaps(
368 LPDIRECTSOUNDBUFFER this,LPDSBCAPS caps
370 caps->dwSize = sizeof(*caps);
371 caps->dwFlags = DSBCAPS_PRIMARYBUFFER|DSBCAPS_STATIC|DSBCAPS_CTRLALL|DSBCAPS_LOCSOFTWARE;
372 caps->dwBufferBytes = 65536;
373 caps->dwUnlockTransferRate = 0;
374 caps->dwPlayCpuOverhead = 0;
378 static HRESULT WINAPI IDirectSoundBuffer_QueryInterface(
379 LPDIRECTSOUNDBUFFER this,REFIID riid,LPVOID *ppobj
383 if (!memcmp(&IID_IDirectSoundNotify,riid,sizeof(*riid))) {
384 IDirectSoundNotify *dsn;
386 dsn = (LPDIRECTSOUNDNOTIFY)HeapAlloc(GetProcessHeap(),0,sizeof(*dsn));
389 this->lpvtbl->fnAddRef(this);
390 dsn->lpvtbl = &dsnvt;
391 *ppobj = (LPVOID)dsn;
394 WINE_StringFromCLSID(riid,xbuf);
395 TRACE(dsound,"(%p,%s,%p)\n",this,xbuf,ppobj);
399 static struct tagLPDIRECTSOUNDBUFFER_VTABLE dsbvt = {
400 IDirectSoundBuffer_QueryInterface,
401 IDirectSoundBuffer_AddRef,
402 IDirectSoundBuffer_Release,
403 IDirectSoundBuffer_GetCaps,
404 IDirectSoundBuffer_GetCurrentPosition,
405 IDirectSoundBuffer_GetFormat,
406 IDirectSoundBuffer_GetVolume,
407 IDirectSoundBuffer_GetPan,
408 IDirectSoundBuffer_GetFrequency,
409 IDirectSoundBuffer_GetStatus,
410 IDirectSoundBuffer_Initialize,
411 IDirectSoundBuffer_Lock,
412 IDirectSoundBuffer_Play,
413 IDirectSoundBuffer_SetCurrentPosition,
414 IDirectSoundBuffer_SetFormat,
415 IDirectSoundBuffer_SetVolume,
416 IDirectSoundBuffer_SetPan,
417 IDirectSoundBuffer_SetFrequency,
418 IDirectSoundBuffer_Stop,
419 IDirectSoundBuffer_Unlock
422 /*******************************************************************************
426 static HRESULT WINAPI IDirectSound_SetCooperativeLevel(
427 LPDIRECTSOUND this,HWND32 hwnd,DWORD level
429 FIXME(dsound,"(%p,%08lx,%ld):stub\n",this,(DWORD)hwnd,level);
434 static HRESULT WINAPI IDirectSound_CreateSoundBuffer(
435 LPDIRECTSOUND this,LPDSBUFFERDESC dsbd,LPLPDIRECTSOUNDBUFFER ppdsb,LPUNKNOWN lpunk
437 if (TRACE_ON(dsound)) {
438 TRACE(dsound,"(%p,%p,%p,%p)\n",this,dsbd,ppdsb,lpunk);
439 TRACE(dsound,"(size=%ld)\n",dsbd->dwSize);
440 TRACE(dsound,"(flags=0x%08lx\n",dsbd->dwFlags);
441 _dump_DSBCAPS(dsbd->dwFlags);
442 TRACE(dsound,"(bufferbytes=%ld)\n",dsbd->dwBufferBytes);
443 TRACE(dsound,"(lpwfxFormat=%p)\n",dsbd->lpwfxFormat);
445 *ppdsb = (LPDIRECTSOUNDBUFFER)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectSoundBuffer));
447 (*ppdsb)->buffer = (LPBYTE)HeapAlloc(GetProcessHeap(),0,dsbd->dwBufferBytes);
448 (*ppdsb)->buflen = dsbd->dwBufferBytes;
449 (*ppdsb)->playpos = 0;
450 (*ppdsb)->writepos = 0;
451 (*ppdsb)->lpvtbl = &dsbvt;
452 (*ppdsb)->dsound = this;
453 (*ppdsb)->playing = 0;
454 (*ppdsb)->volfac = 1.0;
455 memcpy(&((*ppdsb)->dsbd),dsbd,sizeof(*dsbd));
457 /* register buffer */
458 this->buffers = (LPDIRECTSOUNDBUFFER*)HeapReAlloc(GetProcessHeap(),0,this->buffers,sizeof(LPDIRECTSOUNDBUFFER)*(this->nrofbuffers+1));
459 this->buffers[this->nrofbuffers] = *ppdsb;
461 this->lpvtbl->fnAddRef(this);
463 if (dsbd->lpwfxFormat) dsbvt.fnSetFormat(*ppdsb,dsbd->lpwfxFormat);
467 static HRESULT WINAPI IDirectSound_DuplicateSoundBuffer(
468 LPDIRECTSOUND this,LPDIRECTSOUNDBUFFER pdsb,LPLPDIRECTSOUNDBUFFER ppdsb
470 TRACE(dsound,"(%p,%p,%p)\n",this,pdsb,ppdsb);
472 *ppdsb = (LPDIRECTSOUNDBUFFER)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectSoundBuffer));
474 (*ppdsb)->buffer = (LPBYTE)HeapAlloc(GetProcessHeap(),0,pdsb->buflen);
475 memcpy((*ppdsb)->buffer,pdsb->buffer,pdsb->buflen);
476 (*ppdsb)->buflen = pdsb->buflen;
477 (*ppdsb)->playpos = 0;
478 (*ppdsb)->writepos = 0;
479 (*ppdsb)->lpvtbl = &dsbvt;
480 (*ppdsb)->dsound = this;
481 dsbvt.fnSetFormat(*ppdsb,&(pdsb->wfx));
482 /* register buffer */
483 this->buffers = (LPDIRECTSOUNDBUFFER*)HeapReAlloc(GetProcessHeap(),0,this->buffers,sizeof(LPDIRECTSOUNDBUFFER)*(this->nrofbuffers+1));
484 this->buffers[this->nrofbuffers] = *ppdsb;
486 this->lpvtbl->fnAddRef(this);
491 static HRESULT WINAPI IDirectSound_GetCaps(LPDIRECTSOUND this,LPDSCAPS caps) {
492 TRACE(dsound,"(%p,%p)\n",this,caps);
493 TRACE(dsound,"(flags=0x%08lx)\n",caps->dwFlags);
495 caps->dwSize = sizeof(*caps);
496 caps->dwFlags = DSCAPS_PRIMARYSTEREO|DSCAPS_PRIMARY16BIT|DSCAPS_SECONDARYSTEREO|DSCAPS_SECONDARY16BIT;
497 /* FIXME: query OSS */
498 caps->dwMinSecondarySampleRate = 22050;
499 caps->dwMaxSecondarySampleRate = 48000;
500 caps->dwPrimaryBuffers = 1;
501 /* FIXME: set the rest... hmm */
505 static ULONG WINAPI IDirectSound_AddRef(LPDIRECTSOUND this) {
506 TRACE(dsound,"(%p), ref was %d\n",this,this->ref);
507 return ++(this->ref);
510 static ULONG WINAPI IDirectSound_Release(LPDIRECTSOUND this) {
511 TRACE(dsound,"(%p), ref was %d\n",this,this->ref);
512 if (!--(this->ref)) {
513 HeapFree(GetProcessHeap(),0,this);
515 close(audiofd);audiofd = -1;
521 static HRESULT WINAPI IDirectSound_SetSpeakerConfig(
522 LPDIRECTSOUND this,DWORD config
524 FIXME(dsound,"(%p,0x%08lx):stub\n",this,config);
528 static HRESULT WINAPI IDirectSound_QueryInterface(
529 LPDIRECTSOUND this,REFIID riid,LPVOID *ppobj
533 WINE_StringFromCLSID(riid,xbuf);
534 TRACE(dsound,"(%p,%s,%p)\n",this,xbuf,ppobj);
538 static struct tagLPDIRECTSOUND_VTABLE dsvt = {
539 IDirectSound_QueryInterface,
541 IDirectSound_Release,
542 IDirectSound_CreateSoundBuffer,
543 IDirectSound_GetCaps,
544 IDirectSound_DuplicateSoundBuffer,
545 IDirectSound_SetCooperativeLevel,
548 IDirectSound_SetSpeakerConfig,
553 DSOUND_setformat(LPWAVEFORMATEX wfex) {
554 int xx,channels,speed,format,nformat;
557 switch (wfex->wFormatTag) {
559 WARN(dsound,"unknown WAVE_FORMAT tag %d\n",wfex->wFormatTag);
560 return DSERR_BADFORMAT;
561 case WAVE_FORMAT_PCM:
564 if (wfex->wBitsPerSample==8)
567 format = AFMT_S16_LE;
569 if (-1==ioctl(audiofd,SNDCTL_DSP_GETFMTS,&xx)) {
570 perror("ioctl SNDCTL_DSP_GETFMTS");
573 if ((xx&format)!=format) {/* format unsupported */
574 FIXME(dsound,"SNDCTL_DSP_GETFMTS: format not supported\n");
578 if (-1==ioctl(audiofd,SNDCTL_DSP_SETFMT,&nformat)) {
579 perror("ioctl SNDCTL_DSP_SETFMT");
582 if (nformat!=format) {/* didn't work */
583 FIXME(dsound,"SNDCTL_DSP_GETFMTS: format not set\n");
587 channels = wfex->nChannels-1;
588 if (-1==ioctl(audiofd,SNDCTL_DSP_STEREO,&channels)) {
589 perror("ioctl SNDCTL_DSP_STEREO");
592 speed = wfex->nSamplesPerSec;
593 if (-1==ioctl(audiofd,SNDCTL_DSP_SPEED,&speed)) {
594 perror("ioctl SNDCTL_DSP_SPEED");
597 TRACE(dsound,"(freq=%ld,channels=%d,bits=%d)\n",
598 wfex->nSamplesPerSec,wfex->nChannels,wfex->wBitsPerSample
603 static LPDSBPOSITIONNOTIFY
604 DSOUND_nextevent(IDirectSoundBuffer *dsb) {
607 if (dsb->nrofnotifies) {
608 for (i=0;i<dsb->nrofnotifies;i++) {
609 if (dsb->playpos<dsb->notifies[i].dwOffset)
612 if (i==dsb->nrofnotifies)
614 return dsb->notifies+i;
619 #define CHECK_EVENT \
620 if (nextevent && (dsb->playpos == nextevent->dwOffset)) { \
621 SetEvent(nextevent->hEventNotify); \
622 TRACE(dsound,"signalled event %d\n",nextevent->hEventNotify);\
623 nextevent = DSOUND_nextevent(dsb); \
628 DSOUND_MixInBuffer(IDirectSoundBuffer *dsb) {
629 int j,buflen = dsb->buflen;
630 LPDSBPOSITIONNOTIFY nextevent;
631 int xdiff = dsb->wfx.nSamplesPerSec-dsound->wfx.nSamplesPerSec;
632 long Rvoldec, Lvoldec, samp;
636 double tmpr=dsb->volume-500;
638 if(pan>0) tmpl -= (double)pan;
639 else tmpr += (double)pan;
642 tmpl = pow(2.0, tmpl);
643 tmpr = pow(2.0, tmpr);
644 tmpl *= 65536; /* Set to the correct multiple times */
645 tmpr *= 65536; /* 65536 to be convenient for bit shifting */
646 tmpl += 0.5; /* Add .5 for rounding accuracy */
648 Lvoldec = (long)tmpl;
649 Rvoldec = (long)tmpr;
651 /* End Insomnia's mod */
653 if (xdiff<0) xdiff=-xdiff;
655 WARN(dsound,"mixing in buffer of different frequency (%ld vs %ld), argh!\n",
656 dsb->wfx.nSamplesPerSec,dsound->wfx.nSamplesPerSec);
658 nextevent = DSOUND_nextevent(dsb);
659 TRACE(dsound,"(%d.%d.%d.%d)\n",dsound->wfx.wBitsPerSample,dsb->wfx.wBitsPerSample,dsound->wfx.nChannels,dsb->wfx.nChannels);
661 if (dsound->wfx.wBitsPerSample == 8) {
662 char *playbuf8 = (char*)playbuf;
664 if (dsb->wfx.wBitsPerSample == 8) {
665 unsigned char *xbuf = (unsigned char*)(dsb->buffer);
666 if (dsb->wfx.nChannels == 1) {
668 for (j=0;j<sizeof(playbuf)/2;j++) {
670 dsb->playpos=(dsb->playpos+1)%buflen;
671 if (!dsb->playpos && !(dsb->playflags&DSBPLAY_LOOPING)) {
673 dsb->playpos = buflen;
676 /* Insomnia- volume, panning, and correcting against wrap */
678 samp = xbuf[dsb->playpos];
681 samp += playbuf8[(j<<1)];
682 if(samp > 127L) samp = 127L;
683 else if(samp < -128L) samp = -128L;
684 playbuf8[(j<<1)] = (short)samp;
687 samp = xbuf[dsb->playpos];
690 samp += playbuf8[(j<<1)+1];
691 if(samp > 127L) samp = 127L;
692 else if(samp < -128L) samp = -128L;
693 playbuf8[(j<<1)+1] = (short)samp;
694 /* End Insomnia's mod */
700 for (j=0;j<sizeof(playbuf);j++) {
701 dsb->playpos=(dsb->playpos+1)%buflen;
702 if (!dsb->playpos && !(dsb->playflags&DSBPLAY_LOOPING)) {
704 dsb->playpos = buflen;
707 /* Insomnia- volume, panning, and correcting against wrap */
708 samp = xbuf[dsb->playpos];
711 if(j&1) samp *= Rvoldec;
713 else samp *= Lvoldec;
717 if(samp > 127L) samp = 127L;
718 else if(samp < -128L) samp = -128L;
719 playbuf8[j] = (short)samp;
720 /* End Insomnia's mod */
726 short *xbuf = (short*)(dsb->buffer);
727 if (dsb->wfx.nChannels == 1) {
729 for (j=0;j<sizeof(playbuf)/sizeof(playbuf[0])/2;j++) {
730 dsb->playpos=(dsb->playpos+2)%buflen;
731 if (!dsb->playpos && !(dsb->playflags&DSBPLAY_LOOPING)) {
733 dsb->playpos = buflen;
736 /* Insomnia- volume, panning, and correcting against wrap */
738 samp = xbuf[dsb->playpos>>1];
741 samp += playbuf8[(j<<1)];
742 if(samp > 127L) samp = 127L;
743 else if(samp < -128L) samp = -128L;
744 playbuf8[(j<<1)] = (short)samp;
747 samp = xbuf[dsb->playpos>>1];
750 samp += playbuf8[(j<<1)+1];
751 if(samp > 127L) samp = 127L;
752 else if(samp < -128L) samp = -128L;
753 playbuf8[(j<<1)+1] = (short)samp;
754 /* End Insomnia's mod */
760 for (j=0;j<sizeof(playbuf);j++) {
761 dsb->playpos=(dsb->playpos+2)%buflen;
762 if (!dsb->playpos && !(dsb->playflags&DSBPLAY_LOOPING)) {
764 dsb->playpos = buflen;
767 /* Insomnia- volume, panning, and correcting against wrap */
768 samp = xbuf[dsb->playpos>>1];
771 if(j&1) samp *= Rvoldec;
773 else samp *= Lvoldec;
777 if(samp > 127L) samp = 127L;
778 else if(samp < -128L) samp = -128L;
779 playbuf8[j] = (short)samp;
780 /* End Insomnia's mod */
786 } else { /* 16 bit */
787 if (dsb->wfx.wBitsPerSample == 8) {
788 /* unsigned char *xbuf = (unsigned char*)(dsb->buffer); */
789 char *xbuf = dsb->buffer;
790 if (dsb->wfx.nChannels == 1) {
792 WARN(dsound,"Mixing 8-bit stereo into 16!!\n");
793 for (j=0;j<sizeof(playbuf)/sizeof(playbuf[0])/2;j++) {
794 dsb->playpos=(dsb->playpos+1)%buflen;
795 if (!dsb->playpos && !(dsb->playflags&DSBPLAY_LOOPING)) {
797 dsb->playpos = buflen;
800 /* Insomnia- volume, panning, and correcting against wrap */
802 samp = xbuf[dsb->playpos];
805 samp += playbuf[(j<<1)];
806 if(samp > 32767L) samp = 32767L;
807 else if(samp < -32768L) samp = -32768L;
808 playbuf[(j<<1)] = (short)samp;
811 samp = xbuf[dsb->playpos];
814 samp += playbuf[(j<<1)+1];
815 if(samp > 32767L) samp = 32767L;
816 else if(samp < -32768L) samp = -32768L;
817 playbuf[(j<<1)+1] = (short)samp;
818 /* End Insomnia's mod */
824 for (j=0;j<sizeof(playbuf)/sizeof(playbuf[0]);j++) {
825 dsb->playpos=(dsb->playpos+1)%buflen;
826 if (!dsb->playpos && !(dsb->playflags&DSBPLAY_LOOPING)) {
828 dsb->playpos = buflen;
831 /* Insomnia- volume, panning, and correcting against wrap */
832 samp = xbuf[dsb->playpos];
835 if(j&1) samp *= Rvoldec;
837 else samp *= Lvoldec;
841 if(samp > 32767L) samp = 32767L;
842 else if(samp < -32768L) samp = -32768L;
843 playbuf[j] = (short)samp;
844 /* End Insomnia's mod */
851 short *xbuf = (short*)(dsb->buffer);
852 if (dsb->wfx.nChannels == 1) {
853 for (j=0;j<sizeof(playbuf)/sizeof(playbuf[0])/2;j++) {
854 dsb->playpos=(dsb->playpos+2)%buflen;
855 if (!dsb->playpos && !(dsb->playflags&DSBPLAY_LOOPING)) {
857 dsb->playpos = buflen;
860 /* Insomnia- volume, panning, and correcting against wrap */
862 samp = xbuf[dsb->playpos>>1];
865 samp += playbuf[(j<<1)];
866 if(samp > 32767L) samp = 32767L;
867 else if(samp < -32768L) samp = -32768L;
868 playbuf[(j<<1)] = (short)samp;
871 samp = xbuf[dsb->playpos>>1];
874 samp += playbuf[(j<<1)+1];
875 if(samp > 32767L) samp = 32767L;
876 else if(samp < -32768L) samp = -32768L;
877 playbuf[(j<<1)+1] = (short)samp;
878 /* End Insomnia's mod */
883 for (j=0;j<sizeof(playbuf)/sizeof(playbuf[0]);j++) {
884 dsb->playpos=(dsb->playpos+2)%buflen;
885 if (!dsb->playpos && !(dsb->playflags&DSBPLAY_LOOPING)) {
887 dsb->playpos = buflen;
890 /* Insomnia- volume, panning, and correcting against wrap */
891 samp = xbuf[dsb->playpos>>1];
894 if(j&1) samp *= Rvoldec;
896 else samp *= Lvoldec;
900 if(samp > 32767L) samp = 32767L;
901 else if(samp < -32768L) samp = -32768L;
902 playbuf[j] = (short)samp;
903 /* End Insomnia's mod */
913 DSOUND_thread(LPVOID arg) {
914 int res,i,curleft,playing,haveprimary = 0;
916 TRACE(dsound,"dsound is at pid %d\n",getpid());
919 WARN(dsound,"DSOUND thread giving up.\n");
923 WARN(dsound,"DSOUND father died? Giving up.\n");
926 /* RACE: dsound could be deleted */
927 dsound->lpvtbl->fnAddRef(dsound);
928 if (!dsound->nrofbuffers) {
929 /* no soundbuffer yet... wait. */
931 dsound->lpvtbl->fnRelease(dsound);
934 memset(playbuf,0,sizeof(playbuf));
937 for (i=dsound->nrofbuffers;i--;) {
938 IDirectSoundBuffer *dsb = dsound->buffers[i];
940 if (!dsb || !dsb->lpvtbl)
942 dsb->lpvtbl->fnAddRef(dsb);
943 if (dsb->playing && dsb->buflen)
945 if (dsb->dsbd.dwFlags & DSBCAPS_PRIMARYBUFFER) {
947 if (memcmp(&dsound->wfx,&(dsb->wfx),sizeof(dsound->wfx))) {
948 DSOUND_setformat(&(dsb->wfx));
949 memcpy(&dsound->wfx,&(dsb->wfx),sizeof(dsb->wfx));
952 dsb->lpvtbl->fnRelease(dsb);
954 /* We have just one playbuffer, so use its format */
955 if ((playing==1) && !haveprimary) {
956 for (i=dsound->nrofbuffers;i--;) {
957 IDirectSoundBuffer *dsb = dsound->buffers[i];
959 dsb->lpvtbl->fnAddRef(dsb);
960 if (dsb->playing && dsb->buflen) {
961 if (memcmp(&dsound->wfx,&(dsb->wfx),sizeof(dsound->wfx))) {
962 DSOUND_setformat(&(dsb->wfx));
963 memcpy(&dsound->wfx,&(dsb->wfx),sizeof(dsb->wfx));
966 dsb->lpvtbl->fnRelease(dsb);
969 for (i=dsound->nrofbuffers;i--;) {
970 IDirectSoundBuffer *dsb = dsound->buffers[i];
972 if (!dsb || !dsb->lpvtbl)
974 dsb->lpvtbl->fnAddRef(dsb);
975 if (dsb->buflen && dsb->playing)
976 DSOUND_MixInBuffer(dsb);
977 dsb->lpvtbl->fnRelease(dsb);
979 dsound->lpvtbl->fnRelease(dsound);
981 fputc('0'+playing,stderr);
983 while (curleft < sizeof(playbuf)) {
984 res = write(audiofd,(LPBYTE)playbuf+curleft,sizeof(playbuf)-curleft);
988 perror("write audiofd");
998 #endif /* HAVE_OSS */
1000 HRESULT WINAPI DirectSoundCreate(LPGUID lpGUID,LPDIRECTSOUND *ppDS,IUnknown *pUnkOuter ) {
1003 TRACE(dsound,"(%p,%p,%p)\n",lpGUID,ppDS,pUnkOuter);
1006 return DSERR_ALLOCATED;
1007 audiofd = open("/dev/audio",O_WRONLY);
1009 perror("open /dev/audio");
1011 return DSERR_NODRIVER;
1014 if (-1==ioctl(audiofd,SNDCTL_DSP_SETFRAGMENT,&xx))
1015 perror("ioctl SETFRAGMENT");
1017 TRACE(dsound,"SETFRAGMENT. count is now %d, fragsize is %d\n",
1018 (xx>>16)+1,xx&0xffff
1022 *ppDS = (LPDIRECTSOUND)HeapAlloc(GetProcessHeap(),0,sizeof(IDirectSound));
1024 (*ppDS)->lpvtbl = &dsvt;
1025 (*ppDS)->buffers = NULL;
1026 (*ppDS)->nrofbuffers = 0;
1028 (*ppDS)->wfx.wFormatTag = 1;
1029 (*ppDS)->wfx.nChannels = 2;
1030 (*ppDS)->wfx.nSamplesPerSec = 22050;
1031 (*ppDS)->wfx.nAvgBytesPerSec = 44100;
1032 (*ppDS)->wfx.nBlockAlign = 2;
1033 (*ppDS)->wfx.wBitsPerSample = 8;
1035 DSOUND_setformat(&((*ppDS)->wfx));
1042 hnd = CreateThread(NULL,0,DSOUND_thread,0,0,&xid);
1046 MessageBox32A(0,"DirectSound needs the Open Sound System Driver, which has not been found by ./configure.","WINE DirectSound",MB_OK|MB_ICONSTOP);
1047 return DSERR_NODRIVER;
1052 /*******************************************************************************
1053 * DllGetClassObject [DSOUND.4]
1054 * Retrieves class object from a DLL object
1057 * Docs say returns STDAPI
1060 * rclsid [I] CLSID for the class object
1061 * riid [I] Reference to identifier of interface for class object
1062 * ppv [O] Address of variable to receive interface pointer for riid
1066 * Failure: CLASS_E_CLASSNOTAVAILABLE, E_OUTOFMEMORY, E_INVALIDARG,
1069 DWORD WINAPI DllGetClassObject( REFCLSID rclsid, REFIID riid, LPVOID *ppv )
1071 FIXME(dsound, "(%p,%p,%p): stub\n", rclsid, riid, ppv);
1076 /*******************************************************************************
1077 * DllCanUnloadNow [DSOUND.3] Determines whether the DLL is in use.
1083 DWORD WINAPI DllCanUnloadNow(void)
1085 FIXME(dsound, "(void): stub\n");