DirectSound3DListener and DirectSound3DBuffer stubs, new mixer code,
primary buffer is implemented closer to what the SDK docs specify,
other SDK documented behaviour enforced. Completed the devcaps list.
diff --git a/multimedia/dsound.c b/multimedia/dsound.c
index 120b270..ca4790d 100644
--- a/multimedia/dsound.c
+++ b/multimedia/dsound.c
@@ -1,6 +1,7 @@
/* DirectSound
*
* Copyright 1998 Marcus Meissner
+ * Copyright 1998 Rob Riggs
*/
/*
* Note: This file requires multithread ability. It is not possible to
@@ -45,6 +46,7 @@
#include "dsound.h"
#include "thread.h"
#include "debug.h"
+#include "xmalloc.h"
#ifdef HAVE_OSS
# include <sys/ioctl.h>
@@ -55,10 +57,17 @@
# include <sys/soundcard.h>
# endif
+/* #define USE_DSOUND3D 1 */
+
static int audiofd = -1;
+static int audioOK = 0;
+
static LPDIRECTSOUND dsound = NULL;
-static short playbuf[2048];
+static LPDIRECTSOUNDBUFFER primarybuf = NULL;
+
+static int DSOUND_setformat(LPWAVEFORMATEX wfex);
+static void DSOUND_CloseAudio(void);
#endif
@@ -96,6 +105,476 @@
}
/*******************************************************************************
+ * IDirectSound3DBuffer
+ */
+
+// IUnknown methods
+static HRESULT WINAPI IDirectSound3DBuffer_QueryInterface(
+ LPDIRECTSOUND3DBUFFER this, REFIID riid, LPVOID *ppobj)
+{
+ char xbuf[50];
+
+ WINE_StringFromCLSID(riid,xbuf);
+ TRACE(dsound,"(%p,%s,%p)\n",this,xbuf,ppobj);
+ return E_FAIL;
+}
+
+static ULONG WINAPI IDirectSound3DBuffer_AddRef(LPDIRECTSOUND3DBUFFER this)
+{
+ this->ref++;
+ return this->ref;
+}
+
+static ULONG WINAPI IDirectSound3DBuffer_Release(LPDIRECTSOUND3DBUFFER this)
+{
+ if(--this->ref)
+ return this->ref;
+
+ HeapFree(GetProcessHeap(),0,this->buffer);
+ HeapFree(GetProcessHeap(),0,this);
+
+ return 0;
+}
+
+// IDirectSound3DBuffer methods
+static HRESULT WINAPI IDirectSound3DBuffer_GetAllParameters(
+ LPDIRECTSOUND3DBUFFER this,
+ LPDS3DBUFFER lpDs3dBuffer)
+{
+ FIXME(dsound,"stub\n");
+ return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSound3DBuffer_GetConeAngles(
+ LPDIRECTSOUND3DBUFFER this,
+ LPDWORD lpdwInsideConeAngle,
+ LPDWORD lpdwOutsideConeAngle)
+{
+ FIXME(dsound,"stub\n");
+ return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSound3DBuffer_GetConeOrientation(
+ LPDIRECTSOUND3DBUFFER this,
+ LPD3DVECTOR lpvConeOrientation)
+{
+ FIXME(dsound,"stub\n");
+ return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSound3DBuffer_GetConeOutsideVolume(
+ LPDIRECTSOUND3DBUFFER this,
+ LPLONG lplConeOutsideVolume)
+{
+ FIXME(dsound,"stub\n");
+ return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSound3DBuffer_GetMaxDistance(
+ LPDIRECTSOUND3DBUFFER this,
+ LPD3DVALUE lpfMaxDistance)
+{
+ FIXME(dsound,"stub\n");
+ return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSound3DBuffer_GetMinDistance(
+ LPDIRECTSOUND3DBUFFER this,
+ LPD3DVALUE lpfMinDistance)
+{
+ FIXME(dsound,"stub\n");
+ return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSound3DBuffer_GetMode(
+ LPDIRECTSOUND3DBUFFER this,
+ LPDWORD lpdwMode)
+{
+ FIXME(dsound,"stub\n");
+ return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSound3DBuffer_GetPosition(
+ LPDIRECTSOUND3DBUFFER this,
+ LPD3DVECTOR lpvPosition)
+{
+ FIXME(dsound,"stub\n");
+ return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSound3DBuffer_GetVelocity(
+ LPDIRECTSOUND3DBUFFER this,
+ LPD3DVECTOR lpvVelocity)
+{
+ FIXME(dsound,"stub\n");
+ return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSound3DBuffer_SetAllParameters(
+ LPDIRECTSOUND3DBUFFER this,
+ LPCDS3DBUFFER lpcDs3dBuffer,
+ DWORD dwApply)
+{
+ FIXME(dsound,"stub\n");
+ return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSound3DBuffer_SetConeAngles(
+ LPDIRECTSOUND3DBUFFER this,
+ DWORD dwInsideConeAngle,
+ DWORD dwOutsideConeAngle,
+ DWORD dwApply)
+{
+ FIXME(dsound,"stub\n");
+ return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSound3DBuffer_SetConeOrientation(
+ LPDIRECTSOUND3DBUFFER this,
+ D3DVALUE x, D3DVALUE y, D3DVALUE z,
+ DWORD dwApply)
+{
+ FIXME(dsound,"stub\n");
+ return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSound3DBuffer_SetConeOutsideVolume(
+ LPDIRECTSOUND3DBUFFER this,
+ LONG lConeOutsideVolume,
+ DWORD dwApply)
+{
+ FIXME(dsound,"stub\n");
+ return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSound3DBuffer_SetMaxDistance(
+ LPDIRECTSOUND3DBUFFER this,
+ D3DVALUE fMaxDistance,
+ DWORD dwApply)
+{
+ FIXME(dsound,"stub\n");
+ return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSound3DBuffer_SetMinDistance(
+ LPDIRECTSOUND3DBUFFER this,
+ D3DVALUE fMinDistance,
+ DWORD dwApply)
+{
+ FIXME(dsound,"stub\n");
+ return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSound3DBuffer_SetMode(
+ LPDIRECTSOUND3DBUFFER this,
+ DWORD dwMode,
+ DWORD dwApply)
+{
+ TRACE(dsound, "mode = %lx\n", dwMode);
+ this->ds3db.dwMode = dwMode;
+ return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSound3DBuffer_SetPosition(
+ LPDIRECTSOUND3DBUFFER this,
+ D3DVALUE x, D3DVALUE y, D3DVALUE z,
+ DWORD dwApply)
+{
+ FIXME(dsound,"stub\n");
+ return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSound3DBuffer_SetVelocity(
+ LPDIRECTSOUND3DBUFFER this,
+ D3DVALUE x, D3DVALUE y, D3DVALUE z,
+ DWORD dwApply)
+{
+ FIXME(dsound,"stub\n");
+ return DS_OK;
+}
+
+IDirectSound3DBuffer_VTable ds3dbvt = {
+ // IUnknown methods
+ IDirectSound3DBuffer_QueryInterface,
+ IDirectSound3DBuffer_AddRef,
+ IDirectSound3DBuffer_Release,
+ // IDirectSound3DBuffer methods
+ IDirectSound3DBuffer_GetAllParameters,
+ IDirectSound3DBuffer_GetConeAngles,
+ IDirectSound3DBuffer_GetConeOrientation,
+ IDirectSound3DBuffer_GetConeOutsideVolume,
+ IDirectSound3DBuffer_GetMaxDistance,
+ IDirectSound3DBuffer_GetMinDistance,
+ IDirectSound3DBuffer_GetMode,
+ IDirectSound3DBuffer_GetPosition,
+ IDirectSound3DBuffer_GetVelocity,
+ IDirectSound3DBuffer_SetAllParameters,
+ IDirectSound3DBuffer_SetConeAngles,
+ IDirectSound3DBuffer_SetConeOrientation,
+ IDirectSound3DBuffer_SetConeOutsideVolume,
+ IDirectSound3DBuffer_SetMaxDistance,
+ IDirectSound3DBuffer_SetMinDistance,
+ IDirectSound3DBuffer_SetMode,
+ IDirectSound3DBuffer_SetPosition,
+ IDirectSound3DBuffer_SetVelocity,
+};
+
+#ifdef USE_DSOUND3D
+static int DSOUND_Create3DBuffer(LPDIRECTSOUNDBUFFER dsb)
+{
+ DWORD i, temp, iSize, oSize, offset;
+ LPBYTE bIbuf, bObuf, bTbuf = NULL;
+ LPWORD wIbuf, wObuf, wTbuf = NULL;
+
+ // Inside DirectX says it's stupid but allowed
+ if (dsb->wfx.nChannels == 2) {
+ // Convert to mono
+ if (dsb->wfx.wBitsPerSample == 16) {
+ iSize = dsb->buflen / 4;
+ wTbuf = malloc(dsb->buflen / 2);
+ if (wTbuf == NULL)
+ return DSERR_OUTOFMEMORY;
+ for (i = 0; i < iSize; i++)
+ wTbuf[i] = (dsb->buffer[i] + dsb->buffer[(i * 2) + 1]) / 2;
+ wIbuf = wTbuf;
+ } else {
+ iSize = dsb->buflen / 2;
+ bTbuf = malloc(dsb->buflen / 2);
+ if (bTbuf == NULL)
+ return DSERR_OUTOFMEMORY;
+ for (i = 0; i < iSize; i++)
+ bTbuf[i] = (dsb->buffer[i] + dsb->buffer[(i * 2) + 1]) / 2;
+ bIbuf = bTbuf;
+ }
+ } else {
+ if (dsb->wfx.wBitsPerSample == 16) {
+ iSize = dsb->buflen / 2;
+ wIbuf = (LPWORD) dsb->buffer;
+ } else {
+ bIbuf = (LPBYTE) dsb->buffer;
+ iSize = dsb->buflen;
+ }
+ }
+
+ if (primarybuf->wfx.wBitsPerSample == 16) {
+ wObuf = (LPWORD) dsb->ds3db->buffer;
+ oSize = dsb->ds3db->buflen / 2;
+ } else {
+ bObuf = (LPBYTE) dsb->ds3db->buffer;
+ oSize = dsb->ds3db->buflen;
+ }
+
+ offset = primarybuf->wfx.nSamplesPerSec / 100; // 10ms
+ if (primarybuf->wfx.wBitsPerSample == 16 && dsb->wfx.wBitsPerSample == 16)
+ for (i = 0; i < iSize; i++) {
+ temp = wIbuf[i];
+ if (i >= offset)
+ temp += wIbuf[i - offset] >> 9;
+ else
+ temp += wIbuf[i + iSize - offset] >> 9;
+ wObuf[i * 2] = temp;
+ wObuf[(i * 2) + 1] = temp;
+ }
+ else if (primarybuf->wfx.wBitsPerSample == 8 && dsb->wfx.wBitsPerSample == 8)
+ for (i = 0; i < iSize; i++) {
+ temp = bIbuf[i];
+ if (i >= offset)
+ temp += bIbuf[i - offset] >> 5;
+ else
+ temp += bIbuf[i + iSize - offset] >> 5;
+ bObuf[i * 2] = temp;
+ bObuf[(i * 2) + 1] = temp;
+ }
+
+ if (wTbuf)
+ free(wTbuf);
+ if (bTbuf)
+ free(bTbuf);
+
+ return DS_OK;
+}
+#endif
+/*******************************************************************************
+ * IDirectSound3DListener
+ */
+
+// IUnknown methods
+static HRESULT WINAPI IDirectSound3DListener_QueryInterface(
+ LPDIRECTSOUND3DLISTENER this, REFIID riid, LPVOID *ppobj)
+{
+ char xbuf[50];
+
+ WINE_StringFromCLSID(riid,xbuf);
+ TRACE(dsound,"(%p,%s,%p)\n",this,xbuf,ppobj);
+ return E_FAIL;
+}
+
+static ULONG WINAPI IDirectSound3DListener_AddRef(LPDIRECTSOUND3DLISTENER this)
+{
+ this->ref++;
+ return this->ref;
+}
+
+static ULONG WINAPI IDirectSound3DListener_Release(LPDIRECTSOUND3DLISTENER this)
+{
+ this->ref--;
+ return this->ref;
+}
+
+// IDirectSound3DListener methods
+static HRESULT WINAPI IDirectSound3DListener_GetAllParameter(
+ LPDIRECTSOUND3DLISTENER this,
+ LPDS3DLISTENER lpDS3DL)
+{
+ FIXME(dsound,"stub\n");
+ return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSound3DListener_GetDistanceFactor(
+ LPDIRECTSOUND3DLISTENER this,
+ LPD3DVALUE lpfDistanceFactor)
+{
+ FIXME(dsound,"stub\n");
+ return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSound3DListener_GetDopplerFactor(
+ LPDIRECTSOUND3DLISTENER this,
+ LPD3DVALUE lpfDopplerFactor)
+{
+ FIXME(dsound,"stub\n");
+ return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSound3DListener_GetOrientation(
+ LPDIRECTSOUND3DLISTENER this,
+ LPD3DVECTOR lpvOrientFront,
+ LPD3DVECTOR lpvOrientTop)
+{
+ FIXME(dsound,"stub\n");
+ return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSound3DListener_GetPosition(
+ LPDIRECTSOUND3DLISTENER this,
+ LPD3DVECTOR lpvPosition)
+{
+ FIXME(dsound,"stub\n");
+ return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSound3DListener_GetRolloffFactor(
+ LPDIRECTSOUND3DLISTENER this,
+ LPD3DVALUE lpfRolloffFactor)
+{
+ FIXME(dsound,"stub\n");
+ return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSound3DListener_GetVelocity(
+ LPDIRECTSOUND3DLISTENER this,
+ LPD3DVECTOR lpvVelocity)
+{
+ FIXME(dsound,"stub\n");
+ return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSound3DListener_SetAllParameters(
+ LPDIRECTSOUND3DLISTENER this,
+ LPCDS3DLISTENER lpcDS3DL,
+ DWORD dwApply)
+{
+ FIXME(dsound,"stub\n");
+ return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSound3DListener_SetDistanceFactor(
+ LPDIRECTSOUND3DLISTENER this,
+ D3DVALUE fDistanceFactor,
+ DWORD dwApply)
+{
+ FIXME(dsound,"stub\n");
+ return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSound3DListener_SetDopplerFactor(
+ LPDIRECTSOUND3DLISTENER this,
+ D3DVALUE fDopplerFactor,
+ DWORD dwApply)
+{
+ FIXME(dsound,"stub\n");
+ return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSound3DListener_SetOrientation(
+ LPDIRECTSOUND3DLISTENER this,
+ D3DVALUE xFront, D3DVALUE yFront, D3DVALUE zFront,
+ D3DVALUE xTop, D3DVALUE yTop, D3DVALUE zTop,
+ DWORD dwApply)
+{
+ FIXME(dsound,"stub\n");
+ return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSound3DListener_SetPosition(
+ LPDIRECTSOUND3DLISTENER this,
+ D3DVALUE x, D3DVALUE y, D3DVALUE z,
+ DWORD dwApply)
+{
+ FIXME(dsound,"stub\n");
+ return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSound3DListener_SetRolloffFactor(
+ LPDIRECTSOUND3DLISTENER this,
+ D3DVALUE fRolloffFactor,
+ DWORD dwApply)
+{
+ FIXME(dsound,"stub\n");
+ return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSound3DListener_SetVelocity(
+ LPDIRECTSOUND3DLISTENER this,
+ D3DVALUE x, D3DVALUE y, D3DVALUE z,
+ DWORD dwApply)
+{
+ FIXME(dsound,"stub\n");
+ return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSound3DListener_CommitDeferredSettings(
+ LPDIRECTSOUND3DLISTENER this)
+
+{
+ FIXME(dsound,"stub\n");
+ return DS_OK;
+}
+
+IDirectSound3DListener_VTable ds3dlvt = {
+ // IUnknown methods
+ IDirectSound3DListener_QueryInterface,
+ IDirectSound3DListener_AddRef,
+ IDirectSound3DListener_Release,
+ // IDirectSound3DListener methods
+ IDirectSound3DListener_GetAllParameter,
+ IDirectSound3DListener_GetDistanceFactor,
+ IDirectSound3DListener_GetDopplerFactor,
+ IDirectSound3DListener_GetOrientation,
+ IDirectSound3DListener_GetPosition,
+ IDirectSound3DListener_GetRolloffFactor,
+ IDirectSound3DListener_GetVelocity,
+ IDirectSound3DListener_SetAllParameters,
+ IDirectSound3DListener_SetDistanceFactor,
+ IDirectSound3DListener_SetDopplerFactor,
+ IDirectSound3DListener_SetOrientation,
+ IDirectSound3DListener_SetPosition,
+ IDirectSound3DListener_SetRolloffFactor,
+ IDirectSound3DListener_SetVelocity,
+ IDirectSound3DListener_CommitDeferredSettings,
+};
+
+/*******************************************************************************
* IDirectSoundNotify
*/
static HRESULT WINAPI IDirectSoundNotify_QueryInterface(
@@ -160,17 +639,35 @@
/*******************************************************************************
* IDirectSoundBuffer
*/
+
+// This sets this format for the <em>Primary Buffer Only</em>
+// See file:///cdrom/sdk52/docs/worddoc/dsound.doc page 120
static HRESULT WINAPI IDirectSoundBuffer_SetFormat(
LPDIRECTSOUNDBUFFER this,LPWAVEFORMATEX wfex
) {
+ LPDIRECTSOUNDBUFFER *dsb;
+ int i;
- memcpy(&(this->wfx),wfex,sizeof(this->wfx));
+ if (primarybuf->wfx.nSamplesPerSec != wfex->nSamplesPerSec) {
+ dsb = dsound->buffers;
+ for (i = 0; i < dsound->nrofbuffers; i++, dsb++)
+ (*dsb)->freqAdjust = ((*dsb)->freq << 14) / wfex->nSamplesPerSec;
+ }
+
+ memcpy(&(primarybuf->wfx),wfex,sizeof(primarybuf->wfx));
TRACE(dsound,"(%p,%p)\n", this,wfex);
TRACE(dsound,"(formattag=0x%04x,chans=%d,samplerate=%ld"
"bytespersec=%ld,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
wfex->wFormatTag, wfex->nChannels, wfex->nSamplesPerSec,
wfex->nAvgBytesPerSec, wfex->nBlockAlign,
wfex->wBitsPerSample, wfex->cbSize);
+
+ if (this->dsbd.dwFlags & DSBCAPS_PRIMARYBUFFER) {
+ this->wfx.nAvgBytesPerSec =
+ this->wfx.nSamplesPerSec * this->wfx.nBlockAlign;
+ DSOUND_CloseAudio();
+ return DS_OK;
+ }
return 0;
}
@@ -178,11 +675,35 @@
static HRESULT WINAPI IDirectSoundBuffer_SetVolume(
LPDIRECTSOUNDBUFFER this,LONG vol
) {
- TRACE(dsound,"(%p,%ld)\n",this,vol);
- this->volume = vol;
- this->volfac = ((double)vol+10000.0)/10000.0;
+ double temp;
- return 0;
+ TRACE(dsound,"(%p,%ld)\n",this,vol);
+
+ // I'm not sure if we need this for primary buffer
+ if (!(this->dsbd.dwFlags & DSBCAPS_CTRLVOLUME))
+ return DSERR_CONTROLUNAVAIL;
+
+ if ((vol > DSBVOLUME_MAX) || (vol < DSBVOLUME_MIN))
+ return DSERR_INVALIDPARAM;
+
+ // This needs to adjust the soundcard volume when
+ // called for the primary buffer
+ if (this->dsbd.dwFlags & DSBCAPS_PRIMARYBUFFER) {
+ FIXME(dsound, "Volume control of primary unimplemented.\n");
+ this->volume = vol;
+ return DS_OK;
+ }
+
+ this->volume = vol;
+
+ temp = (double) (this->volume + (this->pan < 0 ? this->pan : 0));
+ this->lVolAdjust = (ULONG) (pow(2.0, temp / 600.0) * 65536.0);
+ temp = (double) (this->volume - (this->pan > 0 ? this->pan : 0));
+ this->rVolAdjust = (ULONG) (pow(2.0, temp / 600.0) * 65536.0);
+
+ TRACE(dsound, "left = %lx, right = %lx\n", this->lVolAdjust, this->rVolAdjust);
+
+ return DS_OK;
}
static HRESULT WINAPI IDirectSoundBuffer_GetVolume(
@@ -197,9 +718,20 @@
LPDIRECTSOUNDBUFFER this,DWORD freq
) {
TRACE(dsound,"(%p,%ld)\n",this,freq);
- this->wfx.nSamplesPerSec = freq;
- this->wfx.nAvgBytesPerSec = freq*this->wfx.nChannels*(this->wfx.wBitsPerSample/8);
- return 0;
+
+ // You cannot set the frequency of the primary buffer
+ if (!(this->dsbd.dwFlags & DSBCAPS_CTRLFREQUENCY) ||
+ (this->dsbd.dwFlags & DSBCAPS_PRIMARYBUFFER))
+ return DSERR_CONTROLUNAVAIL;
+
+ if ((freq < DSBFREQUENCY_MIN) || (freq > DSBFREQUENCY_MAX))
+ return DSERR_INVALIDPARAM;
+
+ this->freq = freq;
+ this->freqAdjust = (freq << 14) / primarybuf->wfx.nSamplesPerSec;
+ this->nAvgBytesPerSec = freq * (this->wfx.wBitsPerSample >> 3) * this->wfx.nChannels;
+
+ return DS_OK;
}
static HRESULT WINAPI IDirectSoundBuffer_Play(
@@ -208,7 +740,6 @@
TRACE(dsound,"(%p,%08lx,%08lx,%08lx)\n",
this,reserved1,reserved2,flags
);
- /* this->playpos = 0; */
this->playflags = flags;
this->playing = 1;
return 0;
@@ -217,33 +748,34 @@
static HRESULT WINAPI IDirectSoundBuffer_Stop(LPDIRECTSOUNDBUFFER this) {
TRACE(dsound,"(%p)\n",this);
this->playing = 0;
- /* this->writepos = 0; hmm */
return 0;
}
static DWORD WINAPI IDirectSoundBuffer_AddRef(LPDIRECTSOUNDBUFFER this) {
- TRACE(dsound,"(%p) ref was %ld\n",this, this->ref);
-
+// TRACE(dsound,"(%p) ref was %ld\n",this, this->ref);
+
return ++(this->ref);
}
static DWORD WINAPI IDirectSoundBuffer_Release(LPDIRECTSOUNDBUFFER this) {
int i;
- TRACE(dsound,"(%p) ref was %ld\n",this, this->ref);
-
+// TRACE(dsound,"(%p) ref was %ld\n",this, this->ref);
+
if (--this->ref)
return this->ref;
for (i=0;i<this->dsound->nrofbuffers;i++)
if (this->dsound->buffers[i] == this)
break;
if (i < this->dsound->nrofbuffers) {
- /* Put the last buffer of the list in the (now empty) position */
- this->dsound->buffers[i] = this->dsound->buffers[this->dsound->nrofbuffers - 1];
-
+ /* Put the last buffer of the list in the (now empty) position */
+ this->dsound->buffers[i] = this->dsound->buffers[this->dsound->nrofbuffers - 1];
this->dsound->buffers = HeapReAlloc(GetProcessHeap(),0,this->dsound->buffers,sizeof(LPDIRECTSOUNDBUFFER)*this->dsound->nrofbuffers);
this->dsound->nrofbuffers--;
this->dsound->lpvtbl->fnRelease(this->dsound);
}
+
+ if (this->ds3db && this->ds3db->lpvtbl)
+ this->ds3db->lpvtbl->fnRelease(this->ds3db);
HeapFree(GetProcessHeap(),0,this->buffer);
HeapFree(GetProcessHeap(),0,this);
return 0;
@@ -270,13 +802,23 @@
return 0;
}
+
static HRESULT WINAPI IDirectSoundBuffer_GetFormat(
LPDIRECTSOUNDBUFFER this,LPWAVEFORMATEX lpwf,DWORD wfsize,LPDWORD wfwritten
) {
TRACE(dsound,"(%p,%p,%ld,%p)\n",this,lpwf,wfsize,wfwritten);
- if (wfsize>sizeof(this->wfx)) wfsize = sizeof(this->wfx);
- memcpy(lpwf,&(this->wfx),wfsize);
- if (wfwritten) *wfwritten = wfsize;
+ if (wfsize>sizeof(this->wfx))
+ wfsize = sizeof(this->wfx);
+ if (lpwf) { // NULL is valid
+ memcpy(lpwf,&(this->wfx),wfsize);
+ if (wfwritten)
+ *wfwritten = wfsize;
+ } else
+ if (wfwritten)
+ *wfwritten = sizeof(this->wfx);
+ else
+ return DSERR_INVALIDPARAM;
+
return 0;
}
@@ -296,6 +838,11 @@
);
if (flags & DSBLOCK_FROMWRITECURSOR)
writecursor = this->writepos;
+ if (flags & DSBLOCK_ENTIREBUFFER)
+ writebytes = this->buflen;
+ if (writebytes > this->buflen)
+ writebytes = this->buflen;
+
assert(audiobytes1!=audiobytes2);
assert(lplpaudioptr1!=lplpaudioptr2);
if (writecursor+writebytes <= this->buflen) {
@@ -315,7 +862,8 @@
*audiobytes2 = writebytes-(this->buflen-writecursor);
TRACE(dsound,"->%ld.%ld\n",*audiobytes1,audiobytes2?*audiobytes2:0);
}
- this->writepos=(writecursor+writebytes)%this->buflen;
+ // No. See file:///cdrom/sdk52/docs/worddoc/dsound.doc page 21
+ // this->writepos=(writecursor+writebytes)%this->buflen;
return 0;
}
@@ -328,11 +876,33 @@
}
static HRESULT WINAPI IDirectSoundBuffer_SetPan(
- LPDIRECTSOUNDBUFFER this,LONG newpan
+ LPDIRECTSOUNDBUFFER this,LONG pan
) {
- TRACE(dsound,"(%p,%ld)\n",this,newpan);
- this->pan = newpan;
- return 0;
+ double temp;
+
+ TRACE(dsound,"(%p,%ld)\n",this,pan);
+
+ // What do we do if some moron uses SetPan with
+ // a mono primary buffer?
+
+ // You cannot set the pan of the primary buffer
+ // and you cannot use both pan and 3D controls
+ if (!(this->dsbd.dwFlags & DSBCAPS_CTRLPAN) ||
+ (this->dsbd.dwFlags & DSBCAPS_CTRL3D) ||
+ (this->dsbd.dwFlags & DSBCAPS_PRIMARYBUFFER))
+ return DSERR_CONTROLUNAVAIL;
+
+ if ((pan > DSBPAN_RIGHT) || (pan < DSBPAN_LEFT))
+ return DSERR_INVALIDPARAM;
+
+ this->pan = pan;
+
+ temp = (double) (this->volume + (this->pan < 0 ? this->pan : 0));
+ this->lVolAdjust = (ULONG) (pow(2.0, temp / 600.0) * 65536.0);
+ temp = (double) (this->volume - (this->pan > 0 ? this->pan : 0));
+ this->rVolAdjust = (ULONG) (pow(2.0, temp / 600.0) * 65536.0);
+
+ return DS_OK;
}
static HRESULT WINAPI IDirectSoundBuffer_GetPan(
@@ -346,7 +916,15 @@
static HRESULT WINAPI IDirectSoundBuffer_Unlock(
LPDIRECTSOUNDBUFFER this,LPVOID p1,DWORD x1,LPVOID p2,DWORD x2
) {
-/* FIXME(dsound,"(%p,%p,%ld,%p,%ld):stub\n", this,p1,x1,p2,x2); */
+ FIXME(dsound,"(%p,%p,%ld,%p,%ld):stub\n", this,p1,x1,p2,x2);
+ this->writepos = this->playpos + (this->wfx.nAvgBytesPerSec >> 4);
+ this->writepos %= this->buflen;
+
+#if 0
+ // This is highly experimental and liable to break things
+ if (this->dsbd.dwFlags & DSBCAPS_CTRL3D)
+ DSOUND_Create3DBuffer(this);
+#endif
return 0;
}
@@ -354,7 +932,7 @@
LPDIRECTSOUNDBUFFER this,LPDWORD freq
) {
TRACE(dsound,"(%p,%p)\n",this,freq);
- *freq = this->wfx.nSamplesPerSec;
+ *freq = this->freq;
return 0;
}
@@ -388,7 +966,9 @@
) {
char xbuf[50];
+ WINE_StringFromCLSID(riid,xbuf);
TRACE(dsound,"(%p,%s,%p)\n",this,xbuf,ppobj);
+
if (!memcmp(&IID_IDirectSoundNotify,riid,sizeof(*riid))) {
IDirectSoundNotify *dsn;
@@ -400,7 +980,13 @@
*ppobj = (LPVOID)dsn;
return 0;
}
- WINE_StringFromCLSID(riid,xbuf);
+
+ if (!memcmp(&IID_IDirectSound3DBuffer,riid,sizeof(*riid))) {
+ *ppobj = this->ds3db;
+ if (*ppobj)
+ return DS_OK;
+ }
+
return E_FAIL;
}
@@ -442,6 +1028,8 @@
static HRESULT WINAPI IDirectSound_CreateSoundBuffer(
LPDIRECTSOUND this,LPDSBUFFERDESC dsbd,LPLPDIRECTSOUNDBUFFER ppdsb,LPUNKNOWN lpunk
) {
+ LPWAVEFORMATEX wfex = dsbd->lpwfxFormat;
+
if (TRACE_ON(dsound)) {
TRACE(dsound,"(%p,%p,%p,%p)\n",this,dsbd,ppdsb,lpunk);
TRACE(dsound,"(size=%ld)\n",dsbd->dwSize);
@@ -450,27 +1038,105 @@
TRACE(dsound,"(bufferbytes=%ld)\n",dsbd->dwBufferBytes);
TRACE(dsound,"(lpwfxFormat=%p)\n",dsbd->lpwfxFormat);
}
- *ppdsb = (LPDIRECTSOUNDBUFFER)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectSoundBuffer));
+ if (wfex)
+ TRACE(dsound,"(formattag=0x%04x,chans=%d,samplerate=%ld"
+ "bytespersec=%ld,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
+ wfex->wFormatTag, wfex->nChannels, wfex->nSamplesPerSec,
+ wfex->nAvgBytesPerSec, wfex->nBlockAlign,
+ wfex->wBitsPerSample, wfex->cbSize);
+
+ if (dsbd->dwFlags & DSBCAPS_PRIMARYBUFFER) {
+ if (primarybuf) {
+ *ppdsb = primarybuf;
+ return DS_OK;
+ } // Else create primarybuf
+ }
+
+ *ppdsb = (LPDIRECTSOUNDBUFFER)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectSoundBuffer));
+ if (*ppdsb == NULL)
+ return DSERR_OUTOFMEMORY;
(*ppdsb)->ref =1;
- (*ppdsb)->buffer = (LPBYTE)HeapAlloc(GetProcessHeap(),0,dsbd->dwBufferBytes);
- (*ppdsb)->buflen = dsbd->dwBufferBytes;
+
+ TRACE(dsound, "Created buffer at %p\n", *ppdsb);
+
+ if (dsbd->dwFlags & DSBCAPS_PRIMARYBUFFER)
+ (*ppdsb)->buflen = dsound->wfx.nAvgBytesPerSec;
+ else
+ (*ppdsb)->buflen = dsbd->dwBufferBytes;
+ (*ppdsb)->buffer = (LPBYTE)HeapAlloc(GetProcessHeap(),0,(*ppdsb)->buflen);
+ if ((*ppdsb)->buffer == NULL) {
+ HeapFree(GetProcessHeap(),0,(*ppdsb));
+ *ppdsb = NULL;
+ return DSERR_OUTOFMEMORY;
+ }
(*ppdsb)->playpos = 0;
(*ppdsb)->writepos = 0;
(*ppdsb)->lpvtbl = &dsbvt;
(*ppdsb)->dsound = this;
(*ppdsb)->playing = 0;
- (*ppdsb)->volfac = 1.0;
+ (*ppdsb)->lVolAdjust = (1 << 16);
+ (*ppdsb)->rVolAdjust = (1 << 16);
+ (*ppdsb)->freq = dsbd->lpwfxFormat->nSamplesPerSec;
+
+ if (!(dsbd->dwFlags & DSBCAPS_PRIMARYBUFFER)) {
+ (*ppdsb)->freqAdjust = ((*ppdsb)->freq << 14) /
+ primarybuf->wfx.nSamplesPerSec;
+ (*ppdsb)->nAvgBytesPerSec = (*ppdsb)->freq *
+ (dsbd->lpwfxFormat->wBitsPerSample >> 3) *
+ dsbd->lpwfxFormat->nChannels;
+ }
+
memcpy(&((*ppdsb)->dsbd),dsbd,sizeof(*dsbd));
/* register buffer */
- this->buffers = (LPDIRECTSOUNDBUFFER*)HeapReAlloc(GetProcessHeap(),0,this->buffers,sizeof(LPDIRECTSOUNDBUFFER)*(this->nrofbuffers+1));
- this->buffers[this->nrofbuffers] = *ppdsb;
- this->nrofbuffers++;
- this->lpvtbl->fnAddRef(this);
+ if (!(dsbd->dwFlags & DSBCAPS_PRIMARYBUFFER)) {
+ this->buffers = (LPDIRECTSOUNDBUFFER*)HeapReAlloc(GetProcessHeap(),0,this->buffers,sizeof(LPDIRECTSOUNDBUFFER)*(this->nrofbuffers+1));
+ this->buffers[this->nrofbuffers] = *ppdsb;
+ this->nrofbuffers++;
+ this->lpvtbl->fnAddRef(this);
+ }
- if (dsbd->lpwfxFormat) dsbvt.fnSetFormat(*ppdsb,dsbd->lpwfxFormat);
- return 0;
+ if (dsbd->lpwfxFormat && !(dsbd->dwFlags & DSBCAPS_PRIMARYBUFFER))
+ memcpy(&((*ppdsb)->wfx), dsbd->lpwfxFormat,
+ sizeof((*ppdsb)->wfx));
+
+#if 0
+ if (dsbd->dwFlags & DSBCAPS_CTRL3D) {
+ IDirectSound3DBuffer *ds3db;
+
+ ds3db = (LPDIRECTSOUND3DBUFFER)HeapAlloc(GetProcessHeap(),
+ 0,sizeof(*ds3db));
+ ds3db->ref = 1;
+ ds3db->dsb = (*ppdsb);
+ ds3db->lpvtbl = &ds3dbvt;
+ (*ppdsb)->ds3db = ds3db;
+ ds3db->ds3db.dwSize = sizeof(DS3DBUFFER);
+ ds3db->ds3db.vPosition.x = 0.0;
+ ds3db->ds3db.vPosition.y = 0.0;
+ ds3db->ds3db.vPosition.z = 0.0;
+ ds3db->ds3db.vVelocity.x = 0.0;
+ ds3db->ds3db.vVelocity.y = 0.0;
+ ds3db->ds3db.vVelocity.z = 0.0;
+ ds3db->ds3db.dwInsideConeAngle = DS3D_DEFAULTCONEANGLE;
+ ds3db->ds3db.dwOutsideConeAngle = DS3D_DEFAULTCONEANGLE;
+ ds3db->ds3db.vConeOrientation.x = 0.0;
+ ds3db->ds3db.vConeOrientation.y = 0.0;
+ ds3db->ds3db.vConeOrientation.z = 0.0;
+ ds3db->ds3db.lConeOutsideVolume = DS3D_DEFAULTCONEOUTSIDEVOLUME;
+ ds3db->ds3db.flMinDistance = DS3D_DEFAULTMINDISTANCE;
+ ds3db->ds3db.flMaxDistance = DS3D_DEFAULTMAXDISTANCE;
+ ds3db->ds3db.dwMode = DS3DMODE_NORMAL;
+ ds3db->buflen = ((*ppdsb)->buflen * primarybuf->wfx.nBlockAlign) /
+ (*ppdsb)->wfx.nBlockAlign;
+ ds3db->buffer = HeapAlloc(GetProcessHeap(), 0, ds3db->buflen);
+ if (ds3db->buffer == NULL) {
+ ds3db->buflen = 0;
+ ds3db->ds3db.dwMode = DS3DMODE_DISABLE;
+ }
+ }
+#endif
+ return DS_OK;
}
static HRESULT WINAPI IDirectSound_DuplicateSoundBuffer(
@@ -479,6 +1145,7 @@
TRACE(dsound,"(%p,%p,%p)\n",this,pdsb,ppdsb);
*ppdsb = (LPDIRECTSOUNDBUFFER)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectSoundBuffer));
+
(*ppdsb)->ref =1;
(*ppdsb)->buffer = (LPBYTE)HeapAlloc(GetProcessHeap(),0,pdsb->buflen);
memcpy((*ppdsb)->buffer,pdsb->buffer,pdsb->buflen);
@@ -487,7 +1154,7 @@
(*ppdsb)->writepos = 0;
(*ppdsb)->lpvtbl = &dsbvt;
(*ppdsb)->dsound = this;
- dsbvt.fnSetFormat(*ppdsb,&(pdsb->wfx));
+ memcpy(&((*ppdsb)->wfx), &(pdsb->wfx), sizeof((*ppdsb)->wfx));
/* register buffer */
this->buffers = (LPDIRECTSOUNDBUFFER*)HeapReAlloc(GetProcessHeap(),0,this->buffers,sizeof(LPDIRECTSOUNDBUFFER)*(this->nrofbuffers+1));
this->buffers[this->nrofbuffers] = *ppdsb;
@@ -502,17 +1169,48 @@
TRACE(dsound,"(flags=0x%08lx)\n",caps->dwFlags);
caps->dwSize = sizeof(*caps);
- caps->dwFlags = DSCAPS_PRIMARYSTEREO|DSCAPS_PRIMARY16BIT|DSCAPS_SECONDARYSTEREO|DSCAPS_SECONDARY16BIT;
+ caps->dwFlags =
+ DSCAPS_PRIMARYSTEREO |
+ DSCAPS_PRIMARY16BIT |
+ DSCAPS_SECONDARYSTEREO |
+ DSCAPS_SECONDARY16BIT |
+ DSCAPS_CONTINUOUSRATE;
/* FIXME: query OSS */
- caps->dwMinSecondarySampleRate = 22050;
- caps->dwMaxSecondarySampleRate = 48000;
- caps->dwPrimaryBuffers = 1;
- /* FIXME: set the rest... hmm */
+ caps->dwMinSecondarySampleRate = DSBFREQUENCY_MIN;
+ caps->dwMaxSecondarySampleRate = DSBFREQUENCY_MAX;
+
+ caps->dwPrimaryBuffers = 1;
+
+ caps->dwMaxHwMixingAllBuffers = 0;
+ caps->dwMaxHwMixingStaticBuffers = 0;
+ caps->dwMaxHwMixingStreamingBuffers = 0;
+
+ caps->dwFreeHwMixingAllBuffers = 0;
+ caps->dwFreeHwMixingStaticBuffers = 0;
+ caps->dwFreeHwMixingStreamingBuffers = 0;
+
+ caps->dwMaxHw3DAllBuffers = 0;
+ caps->dwMaxHw3DStaticBuffers = 0;
+ caps->dwMaxHw3DStreamingBuffers = 0;
+
+ caps->dwFreeHw3DAllBuffers = 0;
+ caps->dwFreeHw3DStaticBuffers = 0;
+ caps->dwFreeHw3DStreamingBuffers = 0;
+
+ caps->dwTotalHwMemBytes = 0;
+
+ caps->dwFreeHwMemBytes = 0;
+
+ caps->dwMaxContigFreeHwMemBytes = 0;
+
+ caps->dwUnlockTransferRateHwBuffers = 4096; // But we have none...
+
+ caps->dwPlayCpuOverheadSwBuffers = 1; // 1%
+
return 0;
}
static ULONG WINAPI IDirectSound_AddRef(LPDIRECTSOUND this) {
- TRACE(dsound,"(%p), ref was %ld\n",this,this->ref);
return ++(this->ref);
}
@@ -521,7 +1219,7 @@
if (!--(this->ref)) {
HeapFree(GetProcessHeap(),0,this);
dsound = NULL;
- close(audiofd);audiofd = -1;
+ DSOUND_CloseAudio();
return 0;
}
return this->ref;
@@ -539,6 +1237,37 @@
) {
char xbuf[50];
+ if (!memcmp(&IID_IDirectSound3DListener,riid,sizeof(*riid))) {
+
+ if (this->listener) {
+ *ppobj = this->listener;
+ return DS_OK;
+ }
+ this->listener = (LPDIRECTSOUND3DLISTENER)HeapAlloc(
+ GetProcessHeap(), 0, sizeof(*(this->listener)));
+ this->listener->ref = 1;
+ this->listener->lpvtbl = &ds3dlvt;
+ this->lpvtbl->fnAddRef(this);
+ this->listener->ds3dl.dwSize = sizeof(DS3DLISTENER);
+ this->listener->ds3dl.vPosition.x = 0.0;
+ this->listener->ds3dl.vPosition.y = 0.0;
+ this->listener->ds3dl.vPosition.z = 0.0;
+ this->listener->ds3dl.vVelocity.x = 0.0;
+ this->listener->ds3dl.vVelocity.y = 0.0;
+ this->listener->ds3dl.vVelocity.z = 0.0;
+ this->listener->ds3dl.vOrientFront.x = 0.0;
+ this->listener->ds3dl.vOrientFront.y = 0.0;
+ this->listener->ds3dl.vOrientFront.z = 1.0;
+ this->listener->ds3dl.vOrientTop.x = 0.0;
+ this->listener->ds3dl.vOrientTop.y = 1.0;
+ this->listener->ds3dl.vOrientTop.z = 0.0;
+ this->listener->ds3dl.flDistanceFactor = DS3D_DEFAULTDISTANCEFACTOR;
+ this->listener->ds3dl.flRolloffFactor = DS3D_DEFAULTROLLOFFFACTOR;
+ this->listener->ds3dl.flDopplerFactor = DS3D_DEFAULTDOPPLERFACTOR;
+ *ppobj = (LPVOID)this->listener;
+ return DS_OK;
+ }
+
WINE_StringFromCLSID(riid,xbuf);
TRACE(dsound,"(%p,%s,%p)\n",this,xbuf,ppobj);
return E_FAIL;
@@ -562,7 +1291,11 @@
DSOUND_setformat(LPWAVEFORMATEX wfex) {
int xx,channels,speed,format,nformat;
-
+ // Race condition here... called by DSOUND_thread() and SetFormat()
+ if (!audioOK) {
+ TRACE(dsound, "(%p) deferred\n", wfex);
+ return 0;
+ }
switch (wfex->wFormatTag) {
default:
WARN(dsound,"unknown WAVE_FORMAT tag %d\n",wfex->wFormatTag);
@@ -609,318 +1342,420 @@
return 0;
}
-static LPDSBPOSITIONNOTIFY
-DSOUND_nextevent(IDirectSoundBuffer *dsb) {
+static void DSOUND_CheckEvent(IDirectSoundBuffer *dsb, int len)
+{
+ int i;
+ DWORD offset;
+ LPDSBPOSITIONNOTIFY event;
+
+ if (dsb->nrofnotifies == 0)
+ return;
+
+ TRACE(dsound,"(%p)\n", dsb);
+ for (i = 0; i < dsb->nrofnotifies; i++) {
+ event = dsb->notifies + i;
+ offset = event->dwOffset;
+ if ((dsb->playpos + len) >= dsb->buflen)
+ if ((offset <= (dsb->playpos + len - dsb->buflen)) ||
+ (offset > dsb->playpos)) {
+ SetEvent(event->hEventNotify);
+ TRACE(dsound,"signalled event %d\n", event->hEventNotify);
+ }
+ else
+ if ((offset > dsb->playpos) || (offset <= (dsb->playpos + len))) {
+ SetEvent(event->hEventNotify);
+ TRACE(dsound,"signalled event %d\n", event->hEventNotify);
+ }
+ }
+}
+
+// This should be the correct way to do this.
+// Anyone want to do the optimized assembly?
+static inline short cvt8to16(char byte)
+{
+ short s = 0, sbit = 1;
+ char cbit = 1;
int i;
- if (dsb->nrofnotifies) {
- for (i=0;i<dsb->nrofnotifies;i++) {
- if (dsb->playpos<dsb->notifies[i].dwOffset)
- break;
- }
- if (i==dsb->nrofnotifies)
- i=0;
- return dsb->notifies+i;
+ for (i = 0; i < 8; i++) {
+ if (byte & cbit)
+ s |= sbit;
+ cbit <<= 1;
+ sbit <<= 2;
}
- return NULL;
+ if (byte < 0)
+ s |= 0x8000; // sign bit
+ return s;
}
-#define CHECK_EVENT \
- if (nextevent && (dsb->playpos == nextevent->dwOffset)) { \
- SetEvent(nextevent->hEventNotify); \
- TRACE(dsound,"signalled event %d\n",nextevent->hEventNotify);\
- nextevent = DSOUND_nextevent(dsb); \
+static inline char cvt16to8(short word)
+{
+ char c = 0, cbit = 1;
+ short sbits = 3;
+ int i;
+
+ for (i = 0; i < 7; i++) {
+ if (word & sbits)
+ c |= cbit;
+ cbit <<= 1;
+ sbits <<= 2;
}
-
-
-static void
-DSOUND_MixInBuffer(IDirectSoundBuffer *dsb) {
- int j,buflen = dsb->buflen;
- LPDSBPOSITIONNOTIFY nextevent;
- int xdiff = dsb->wfx.nSamplesPerSec-dsound->wfx.nSamplesPerSec;
- long Rvoldec, Lvoldec, samp;
- long pan = dsb->pan;
-
- {
- double tmpr=dsb->volume-500;
- double tmpl=tmpr;
- if(pan>0) tmpl -= (double)pan;
- else tmpr += (double)pan;
- tmpl /= 1000.0;
- tmpr /= 1000.0;
- tmpl = pow(2.0, tmpl);
- tmpr = pow(2.0, tmpr);
- tmpl *= 65536; /* Set to the correct multiple times */
- tmpr *= 65536; /* 65536 to be convenient for bit shifting */
- tmpl += 0.5; /* Add .5 for rounding accuracy */
- tmpr += 0.5;
- Lvoldec = (long)tmpl;
- Rvoldec = (long)tmpr;
- }
- /* End Insomnia's mod */
-
- if (xdiff<0) xdiff=-xdiff;
- if (xdiff>1500) {
- WARN(dsound,"mixing in buffer of different frequency (%ld vs %ld), argh!\n",
- dsb->wfx.nSamplesPerSec,dsound->wfx.nSamplesPerSec);
- }
- nextevent = DSOUND_nextevent(dsb);
- TRACE(dsound,"(%d.%d.%d.%d)\n",dsound->wfx.wBitsPerSample,dsb->wfx.wBitsPerSample,dsound->wfx.nChannels,dsb->wfx.nChannels);
-
- if (dsound->wfx.wBitsPerSample == 8) {
- char *playbuf8 = (char*)playbuf;
-
- if (dsb->wfx.wBitsPerSample == 8) {
- unsigned char *xbuf = (unsigned char*)(dsb->buffer);
- if (dsb->wfx.nChannels == 1) {
- /* 8.1 -> 8.2 */
- for (j=0;j<sizeof(playbuf)/2;j++) {
-
- dsb->playpos=(dsb->playpos+1)%buflen;
- if (!dsb->playpos && !(dsb->playflags&DSBPLAY_LOOPING)) {
- dsb->playing = 0;
- dsb->playpos = buflen;
- return;
- }
- /* Insomnia- volume, panning, and correcting against wrap */
- /* Left Channel */
- samp = xbuf[dsb->playpos];
- samp *= Lvoldec;
- samp >>= 16;
- samp += playbuf8[(j<<1)];
- if(samp > 127L) samp = 127L;
- else if(samp < -128L) samp = -128L;
- playbuf8[(j<<1)] = (short)samp;
-
- /* Right Channel */
- samp = xbuf[dsb->playpos];
- samp *= Rvoldec;
- samp >>= 16;
- samp += playbuf8[(j<<1)+1];
- if(samp > 127L) samp = 127L;
- else if(samp < -128L) samp = -128L;
- playbuf8[(j<<1)+1] = (short)samp;
- /* End Insomnia's mod */
-
- CHECK_EVENT
- }
- } else {
- /* 8.2 -> 8.2 */
- for (j=0;j<sizeof(playbuf);j++) {
- dsb->playpos=(dsb->playpos+1)%buflen;
- if (!dsb->playpos && !(dsb->playflags&DSBPLAY_LOOPING)) {
- dsb->playing = 0;
- dsb->playpos = buflen;
- return;
- }
- /* Insomnia- volume, panning, and correcting against wrap */
- samp = xbuf[dsb->playpos];
-
- /* Right Channel */
- if(j&1) samp *= Rvoldec;
- /* Left Channel */
- else samp *= Lvoldec;
-
- samp >>= 16;
- samp += playbuf8[j];
- if(samp > 127L) samp = 127L;
- else if(samp < -128L) samp = -128L;
- playbuf8[j] = (short)samp;
- /* End Insomnia's mod */
-
- CHECK_EVENT
- }
- }
- } else { /* 16 */
- short *xbuf = (short*)(dsb->buffer);
- if (dsb->wfx.nChannels == 1) {
- /* 16.1 -> 8.2 */
- for (j=0;j<sizeof(playbuf)/sizeof(playbuf[0])/2;j++) {
- dsb->playpos=(dsb->playpos+2)%buflen;
- if (!dsb->playpos && !(dsb->playflags&DSBPLAY_LOOPING)) {
- dsb->playing = 0;
- dsb->playpos = buflen;
- return;
- }
- /* Insomnia- volume, panning, and correcting against wrap */
- /* Left Channel */
- samp = xbuf[dsb->playpos>>1];
- samp *= Lvoldec;
- samp >>= 24;
- samp += playbuf8[(j<<1)];
- if(samp > 127L) samp = 127L;
- else if(samp < -128L) samp = -128L;
- playbuf8[(j<<1)] = (short)samp;
-
- /* Right Channel */
- samp = xbuf[dsb->playpos>>1];
- samp *= Rvoldec;
- samp >>= 24;
- samp += playbuf8[(j<<1)+1];
- if(samp > 127L) samp = 127L;
- else if(samp < -128L) samp = -128L;
- playbuf8[(j<<1)+1] = (short)samp;
- /* End Insomnia's mod */
-
- CHECK_EVENT
- }
- } else {
- /* 16.2 -> 8.2 */
- for (j=0;j<sizeof(playbuf);j++) {
- dsb->playpos=(dsb->playpos+2)%buflen;
- if (!dsb->playpos && !(dsb->playflags&DSBPLAY_LOOPING)) {
- dsb->playing = 0;
- dsb->playpos = buflen;
- return;
- }
- /* Insomnia- volume, panning, and correcting against wrap */
- samp = xbuf[dsb->playpos>>1];
-
- /* Right Channel */
- if(j&1) samp *= Rvoldec;
- /* Left Channel */
- else samp *= Lvoldec;
-
- samp >>= 24;
- samp += playbuf8[j];
- if(samp > 127L) samp = 127L;
- else if(samp < -128L) samp = -128L;
- playbuf8[j] = (short)samp;
- /* End Insomnia's mod */
-
- CHECK_EVENT
- }
- }
- }
- } else { /* 16 bit */
- if (dsb->wfx.wBitsPerSample == 8) {
-/* unsigned char *xbuf = (unsigned char*)(dsb->buffer); */
- char *xbuf = dsb->buffer;
- if (dsb->wfx.nChannels == 1) {
- /* 8.1 -> 16.2 */
- WARN(dsound,"Mixing 8-bit stereo into 16!!\n");
- for (j=0;j<sizeof(playbuf)/sizeof(playbuf[0])/2;j++) {
- dsb->playpos=(dsb->playpos+1)%buflen;
- if (!dsb->playpos && !(dsb->playflags&DSBPLAY_LOOPING)) {
- dsb->playing = 0;
- dsb->playpos = buflen;
- return;
- }
- /* Insomnia- volume, panning, and correcting against wrap */
- /* Left Channel */
- samp = xbuf[dsb->playpos];
- samp *= Lvoldec;
- samp >>= 8;
- samp += playbuf[(j<<1)];
- if(samp > 32767L) samp = 32767L;
- else if(samp < -32768L) samp = -32768L;
- playbuf[(j<<1)] = (short)samp;
-
- /* Right Channel */
- samp = xbuf[dsb->playpos];
- samp *= Rvoldec;
- samp >>= 8;
- samp += playbuf[(j<<1)+1];
- if(samp > 32767L) samp = 32767L;
- else if(samp < -32768L) samp = -32768L;
- playbuf[(j<<1)+1] = (short)samp;
- /* End Insomnia's mod */
-
- CHECK_EVENT
- }
- } else {
- /* 8.2 -> 16.2 */
- for (j=0;j<sizeof(playbuf)/sizeof(playbuf[0]);j++) {
- dsb->playpos=(dsb->playpos+1)%buflen;
- if (!dsb->playpos && !(dsb->playflags&DSBPLAY_LOOPING)) {
- dsb->playing = 0;
- dsb->playpos = buflen;
- return;
- }
- /* Insomnia- volume, panning, and correcting against wrap */
- samp = xbuf[dsb->playpos];
-
- /* Right Channel */
- if(j&1) samp *= Rvoldec;
- /* Left Channel */
- else samp *= Lvoldec;
-
- samp >>= 8;
- samp += playbuf[j];
- if(samp > 32767L) samp = 32767L;
- else if(samp < -32768L) samp = -32768L;
- playbuf[j] = (short)samp;
- /* End Insomnia's mod */
-
- CHECK_EVENT
- }
- }
- } else { /* 16 */
- /* 16.1 -> 16.2 */
- short *xbuf = (short*)(dsb->buffer);
- if (dsb->wfx.nChannels == 1) {
- for (j=0;j<sizeof(playbuf)/sizeof(playbuf[0])/2;j++) {
- dsb->playpos=(dsb->playpos+2)%buflen;
- if (!dsb->playpos && !(dsb->playflags&DSBPLAY_LOOPING)) {
- dsb->playing = 0;
- dsb->playpos = buflen;
- return;
- }
- /* Insomnia- volume, panning, and correcting against wrap */
- /* Left Channel */
- samp = xbuf[dsb->playpos>>1];
- samp *= Lvoldec;
- samp >>= 16;
- samp += playbuf[(j<<1)];
- if(samp > 32767L) samp = 32767L;
- else if(samp < -32768L) samp = -32768L;
- playbuf[(j<<1)] = (short)samp;
-
- /* Right Channel */
- samp = xbuf[dsb->playpos>>1];
- samp *= Rvoldec;
- samp >>= 16;
- samp += playbuf[(j<<1)+1];
- if(samp > 32767L) samp = 32767L;
- else if(samp < -32768L) samp = -32768L;
- playbuf[(j<<1)+1] = (short)samp;
- /* End Insomnia's mod */
-
- CHECK_EVENT
- }
- } else {
- for (j=0;j<sizeof(playbuf)/sizeof(playbuf[0]);j++) {
- dsb->playpos=(dsb->playpos+2)%buflen;
- if (!dsb->playpos && !(dsb->playflags&DSBPLAY_LOOPING)) {
- dsb->playing = 0;
- dsb->playpos = buflen;
- return;
- }
- /* Insomnia- volume, panning, and correcting against wrap */
- samp = xbuf[dsb->playpos>>1];
-
- /* Right Channel */
- if(j&1) samp *= Rvoldec;
- /* Left Channel */
- else samp *= Lvoldec;
-
- samp >>= 16;
- samp += playbuf[j];
- if(samp > 32767L) samp = 32767L;
- else if(samp < -32768L) samp = -32768L;
- playbuf[j] = (short)samp;
- /* End Insomnia's mod */
-
- CHECK_EVENT
- }
- }
- }
- }
+ if (word < 0)
+ c |= 0x80; // sign bit
+ return c;
}
-static DWORD WINAPI
-DSOUND_thread(LPVOID arg) {
- int res,i,curleft,playing,haveprimary = 0;
+static inline void get_fields(const IDirectSoundBuffer *dsb, char *buf, int *fl, int *fr)
+{
+ short *bufs = (short *) buf;
+
+ // TRACE(dsound, "(%p)", buf);
+ if ((dsb->wfx.wBitsPerSample == 8) && dsb->wfx.nChannels == 2) {
+ *fl = cvt8to16(*buf);
+ *fr = cvt8to16(*(buf + 1));
+ return;
+ }
+
+ if ((dsb->wfx.wBitsPerSample == 16) && dsb->wfx.nChannels == 2) {
+ *fl = *bufs;
+ *fr = *(bufs + 1);
+ return;
+ }
+
+ if ((dsb->wfx.wBitsPerSample == 8) && dsb->wfx.nChannels == 1) {
+ *fr = *fl = cvt8to16(*buf);
+ return;
+ }
+
+ if ((dsb->wfx.wBitsPerSample == 16) && dsb->wfx.nChannels == 1) {
+ *fr = *fl = *bufs;
+ return;
+ }
+
+ FIXME(dsound, "get_fields found an unsupported configuration\n");
+ return;
+}
+
+static inline void set_fields(char *buf, int fl, int fr)
+{
+ short *bufs = (short *) buf;
+
+ if ((primarybuf->wfx.wBitsPerSample == 8) && (primarybuf->wfx.nChannels == 2)) {
+ *buf = cvt16to8(fl);
+ *(buf + 1) = cvt16to8(fr);
+ return;
+ }
+
+ if ((primarybuf->wfx.wBitsPerSample == 16) && (primarybuf->wfx.nChannels == 2)) {
+ *bufs = fl;
+ *(bufs + 1) = fr;
+ return;
+ }
+
+ if ((primarybuf->wfx.wBitsPerSample == 8) && (primarybuf->wfx.nChannels == 1)) {
+ *buf = cvt16to8((fl + fr) / 2);
+ return;
+ }
+
+ if ((primarybuf->wfx.wBitsPerSample == 16) && (primarybuf->wfx.nChannels == 1)) {
+ *bufs = (fl + fr) / 2;
+ return;
+ }
+ FIXME(dsound, "set_fields found an unsupported configuration\n");
+ return;
+}
+
+// Now with PerfectPitch (tm) technology
+static void DSOUND_MixerNorm(IDirectSoundBuffer *dsb, char *buf, int len)
+{
+ int i, ipos, fieldL, fieldR;
+ char *ibp, *obp;
+ int iAdvance = dsb->wfx.nBlockAlign;
+ int oAdvance = primarybuf->wfx.nBlockAlign;
+
+ ibp = dsb->buffer + dsb->playpos;
+ obp = buf;
+
+ TRACE(dsound, "(%p, %p, %p), playpos=%8.8lx\n", dsb, ibp, obp, dsb->playpos);
+ // Check for the best case
+ if ((dsb->freq == primarybuf->wfx.nSamplesPerSec) &&
+ (dsb->wfx.wBitsPerSample == primarybuf->wfx.wBitsPerSample) &&
+ (dsb->wfx.nChannels == primarybuf->wfx.nChannels)) {
+ TRACE(dsound, "(%p) Best case\n", dsb);
+ if ((ibp + len) <= (char *)(dsb->buffer + dsb->buflen))
+ memcpy(obp, ibp, len);
+ else { // wrap
+ memcpy(obp, ibp, dsb->buflen - dsb->playpos);
+ memcpy(obp + (dsb->buflen - dsb->playpos),
+ dsb->buffer,
+ len - (dsb->buflen - dsb->playpos));
+ }
+ return;
+ }
+
+ // Check for same sample rate
+ if (dsb->freq == primarybuf->wfx.nSamplesPerSec) {
+ TRACE(dsound, "(%p) Same sample rate %ld = primary %ld\n", dsb,
+ dsb->freq, primarybuf->wfx.nSamplesPerSec);
+ for (i = 0; i < len; i += oAdvance) {
+ get_fields(dsb, ibp, &fieldL, &fieldR);
+ ibp += iAdvance;
+ set_fields(obp, fieldL, fieldR);
+ obp += oAdvance;
+ if (ibp > (char *)(dsb->buffer + dsb->buflen))
+ ibp = dsb->buffer; // wrap
+ }
+ return;
+ }
+
+ // Mix in different sample rates
+ //
+ // New PerfectPitch(tm) Technology (c) 1998 Rob Riggs
+ // Patent Pending :-]
+ for (i = 0; i < len; i += oAdvance) {
+
+ ipos = (iAdvance * ((i * dsb->freqAdjust) >> 14)) + dsb->playpos;
+
+ if (ipos >= dsb->buflen)
+ ipos %= dsb->buflen; // wrap
+
+ get_fields(dsb, (dsb->buffer + ipos), &fieldL, &fieldR);
+ set_fields(obp, fieldL, fieldR);
+ obp += oAdvance;
+ }
+ return;
+}
+
+static void DSOUND_MixerVol(IDirectSoundBuffer *dsb, char *buf, int len)
+{
+ int i;
+ char *bpc;
+ short *bps;
+
+ TRACE(dsound, "(%p) left = %lx, right = %lx\n", dsb,
+ dsb->lVolAdjust, dsb->rVolAdjust);
+ if ((!(dsb->dsbd.dwFlags & DSBCAPS_CTRLPAN) || (dsb->pan == 0)) &&
+ (!(dsb->dsbd.dwFlags & DSBCAPS_CTRLVOLUME) || (dsb->volume == 0)) &&
+ !(dsb->dsbd.dwFlags & DSBCAPS_CTRL3D))
+ return; // Nothing to do
+
+ // If we end up with some bozo coder using panning or 3D sound
+ // with a mono primary buffer, it could sound very weird using
+ // this method. Oh well, tough patooties.
+
+ for (i = 0; i < len; i += (primarybuf->wfx.wBitsPerSample >> 3)) {
+ register int val;
+
+ switch (primarybuf->wfx.wBitsPerSample) {
+
+ case 8:
+ bpc = buf + i;
+ val = *bpc;
+ val = (val * (i & 1 ? dsb->rVolAdjust : dsb->lVolAdjust)) >> 16;
+ *bpc = (char) val;
+ break;
+ case 16:
+ bps = (short *) (buf + i);
+ val = *bps;
+ val = (val * (i & 1 ? dsb->rVolAdjust : dsb->lVolAdjust)) >> 16;
+ *bps = (short) val;
+ break;
+ default:
+ // Very ugly!
+ FIXME(dsound, "MixerVol had a nasty error\n");
+ }
+ }
+}
+
+#ifdef USE_DSOUND3D
+static void DSOUND_Mixer3D(IDirectSoundBuffer *dsb, char *buf, int len)
+{
+ char *ibp, *obp;
+ DWORD buflen, playpos;
+
+ buflen = dsb->ds3db->buflen;
+ playpos = (dsb->playpos * primarybuf->wfx.nBlockAlign) / dsb->wfx.nBlockAlign;
+ ibp = dsb->ds3db->buffer + playpos;
+ obp = buf;
+
+ if (playpos > buflen) {
+ FIXME(dsound, "Major breakage");
+ return;
+ }
+
+ if (len <= (playpos + buflen))
+ memcpy(obp, ibp, len);
+ else { // wrap
+ memcpy(obp, ibp, buflen - playpos);
+ memcpy(obp + (buflen - playpos),
+ dsb->buffer,
+ len - (buflen - playpos));
+ }
+ return;
+}
+#endif
+
+static DWORD DSOUND_MixInBuffer(IDirectSoundBuffer *dsb)
+{
+ int i, len, ilen, temp, field;
+ int advance = primarybuf->wfx.wBitsPerSample >> 3;
+ char *buf, *ibuf, *obuf;
+ short *ibufs, *obufs;
+
+ // The most we will use
+ len = primarybuf->wfx.nAvgBytesPerSec >> 4; // 60 ms
+ len &= ~3; // 4 byte alignment
+ if (!(dsb->playflags & DSBPLAY_LOOPING)) {
+ temp = ((primarybuf->wfx.nAvgBytesPerSec * dsb->buflen) /
+ dsb->wfx.nAvgBytesPerSec) -
+ ((primarybuf->wfx.nAvgBytesPerSec * dsb->playpos) /
+ dsb->nAvgBytesPerSec);
+ len = (len > temp) ? temp : len;
+ }
+
+ ilen = (len * dsb->nAvgBytesPerSec) / primarybuf->wfx.nAvgBytesPerSec;
+
+ if ((buf = ibuf = (char *) malloc(len)) == NULL)
+ return 0;
+
+ TRACE(dsound, "MixInBuffer (%p) len = %d\n", dsb, len);
+
+ DSOUND_MixerNorm(dsb, ibuf, len);
+ if ((dsb->dsbd.dwFlags & DSBCAPS_CTRLPAN) ||
+ (dsb->dsbd.dwFlags & DSBCAPS_CTRLVOLUME))
+ DSOUND_MixerVol(dsb, ibuf, len);
+
+ TRACE(dsound, "Mixing buffer - advance = %d\n", advance);
+ obuf = primarybuf->buffer + primarybuf->playpos;
+ for (i = 0; i < len; i += advance) {
+ obufs = (short *) obuf;
+ ibufs = (short *) ibuf;
+ if (primarybuf->wfx.wBitsPerSample == 8) {
+ field = (char) *ibuf;
+ field += (char) *obuf;
+ field = field > 127 ? 127 : field;
+ field = field < -128 ? -128 : field;
+ *obuf = (char) field;
+ } else {
+ field = *ibufs;
+ field += *obufs;
+ field = field > 32767 ? 32767 : field;
+ field = field < -32768 ? -32768 : field;
+ *obufs = field;
+ }
+ ibuf += advance;
+ obuf += advance;
+ if (obuf > (char *)(primarybuf->buffer + primarybuf->buflen))
+ obuf = primarybuf->buffer;
+ }
+ free(buf);
+
+ if (dsb->dsbd.dwFlags & DSBCAPS_CTRLPOSITIONNOTIFY)
+ DSOUND_CheckEvent(dsb, len);
+
+ dsb->playpos += ilen;
+ dsb->writepos += ilen;
+
+ if (dsb->playpos >= dsb->buflen) {
+ if (!(dsb->playflags & DSBPLAY_LOOPING)) {
+ dsb->playing = 0;
+ dsb->writepos = 0;
+ dsb->playpos = 0;
+ } else
+ dsb->playpos -= dsb->buflen; // wrap
+ }
+
+ if (dsb->writepos > dsb->buflen)
+ dsb->writepos -= dsb->buflen;
+
+ return len;
+}
+
+static DWORD WINAPI DSOUND_MixPrimary(void)
+{
+ int i, len, maxlen = 0;
+ IDirectSoundBuffer *dsb;
+
+ for (i = dsound->nrofbuffers - 1; i >= 0; i--) {
+ dsb = dsound->buffers[i];
+
+ if (!dsb || !(dsb->lpvtbl))
+ continue;
+ dsb->lpvtbl->fnAddRef(dsb);
+ if (dsb->buflen && dsb->playing) {
+ len = DSOUND_MixInBuffer(dsb);
+ maxlen = len > maxlen ? len : maxlen;
+ }
+ dsb->lpvtbl->fnRelease(dsb);
+ }
+
+ if (maxlen > 0) {
+ primarybuf->writepos += maxlen;
+ if (primarybuf->writepos > primarybuf->buflen)
+ primarybuf->writepos -= primarybuf->buflen;
+ }
+
+ return maxlen;
+}
+
+static int DSOUND_OpenAudio(void)
+{
+ int audioFragment;
+
+ if (primarybuf == NULL)
+ return DSERR_OUTOFMEMORY;
+
+ while (audiofd != -1)
+ sleep(5);
+ audiofd = open("/dev/audio",O_WRONLY);
+ if (audiofd==-1) {
+ perror("open /dev/audio");
+ audiofd = -1;
+ return DSERR_NODRIVER;
+ }
+
+ audioFragment=0x0002000c;
+ if (-1==ioctl(audiofd,SNDCTL_DSP_SETFRAGMENT,&audioFragment))
+ perror("ioctl SETFRAGMENT");
+
+ audioOK = 1;
+ DSOUND_setformat(&(primarybuf->wfx));
+
+ return 0;
+}
+
+static void DSOUND_CloseAudio(void)
+{
+ audioOK = 0; // race condition
+ Sleep(5);
+ close(audiofd);
+ primarybuf->playpos = 0;
+ primarybuf->writepos = primarybuf->wfx.nAvgBytesPerSec >> 4;
+ memset(primarybuf->buffer, 0, primarybuf->buflen);
+ audiofd = -1;
+ TRACE(dsound, "Audio stopped\n");
+}
+
+static int DSOUND_WriteAudio(char *buf, int len)
+{
+ int result, left = 0;
+
+ while (left < len) {
+ result = write(audiofd, buf + left, len - left);
+ if (result == -1)
+ if (errno == EINTR)
+ continue;
+ else
+ return result;
+ left += result;
+ }
+ return 0;
+}
+
+static DWORD WINAPI DSOUND_thread(LPVOID arg)
+{
+ int maxlen = primarybuf->wfx.nAvgBytesPerSec >> 4;
+ int len;
TRACE(dsound,"dsound is at pid %d\n",getpid());
while (1) {
@@ -934,99 +1769,72 @@
}
/* RACE: dsound could be deleted */
dsound->lpvtbl->fnAddRef(dsound);
- if (!dsound->nrofbuffers) {
+ if (primarybuf == NULL) { // Should never happen
/* no soundbuffer yet... wait. */
- Sleep(1000);
+ Sleep(100);
dsound->lpvtbl->fnRelease(dsound);
continue;
}
- memset(playbuf,0,sizeof(playbuf));
- playing = 0;
- haveprimary = 0;
- for (i=dsound->nrofbuffers;i--;) {
- IDirectSoundBuffer *dsb = dsound->buffers[i];
-
- if (!dsb || !dsb->lpvtbl)
- continue;
- dsb->lpvtbl->fnAddRef(dsb);
- if (dsb->playing && dsb->buflen)
- playing++;
- if (dsb->dsbd.dwFlags & DSBCAPS_PRIMARYBUFFER) {
- haveprimary = 1;
- if (memcmp(&dsound->wfx,&(dsb->wfx),sizeof(dsound->wfx))) {
- DSOUND_setformat(&(dsb->wfx));
- memcpy(&dsound->wfx,&(dsb->wfx),sizeof(dsb->wfx));
+ len = DSOUND_MixPrimary();
+ if (primarybuf->playing)
+ len = maxlen > len ? maxlen : len;
+ if (len) {
+ if (audioOK == 0)
+ DSOUND_OpenAudio();
+ if (primarybuf->playpos + len > primarybuf->buflen) {
+ if (DSOUND_WriteAudio(
+ primarybuf->buffer + primarybuf->playpos,
+ primarybuf->buflen - primarybuf->playpos)
+ != 0) {
+ perror("DSOUND_WriteAudio");
+ ExitThread(0);
}
- }
- dsb->lpvtbl->fnRelease(dsb);
- }
- /* We have just one playbuffer, so use its format */
- if ((playing==1) && !haveprimary) {
- for (i=dsound->nrofbuffers;i--;) {
- IDirectSoundBuffer *dsb = dsound->buffers[i];
-
- dsb->lpvtbl->fnAddRef(dsb);
- if (dsb->playing && dsb->buflen) {
- if (memcmp(&dsound->wfx,&(dsb->wfx),sizeof(dsound->wfx))) {
- DSOUND_setformat(&(dsb->wfx));
- memcpy(&dsound->wfx,&(dsb->wfx),sizeof(dsb->wfx));
- }
+ memset(primarybuf->buffer + primarybuf->playpos, 0,
+ primarybuf->buflen - primarybuf->playpos);
+ if (DSOUND_WriteAudio(primarybuf->buffer,
+ len - (primarybuf->buflen - primarybuf->playpos)) != 0) {
+ perror("DSOUND_WriteAudio");
+ ExitThread(0);
}
- dsb->lpvtbl->fnRelease(dsb);
+ memset(primarybuf->buffer, 0,
+ len - (primarybuf->buflen - primarybuf->playpos));
+ } else {
+ if (DSOUND_WriteAudio(
+ primarybuf->buffer + primarybuf->playpos,
+ len) != 0) {
+ perror("DSOUND_WriteAudio");
+ ExitThread(0);
+ }
+ memset(primarybuf->buffer + primarybuf->playpos, 0, len);
}
- }
- for (i=dsound->nrofbuffers;i--;) {
- IDirectSoundBuffer *dsb = dsound->buffers[i];
-
- if (!dsb || !dsb->lpvtbl)
- continue;
- dsb->lpvtbl->fnAddRef(dsb);
- if (dsb->buflen && dsb->playing)
- DSOUND_MixInBuffer(dsb);
- dsb->lpvtbl->fnRelease(dsb);
+ primarybuf->playpos += len;
+ if (primarybuf->playpos >= primarybuf->buflen)
+ primarybuf->playpos -= primarybuf->buflen;
+ primarybuf->writepos = primarybuf->playpos + maxlen;
+ if (primarybuf->writepos >= primarybuf->buflen)
+ primarybuf->writepos -= primarybuf->buflen;
+ } else {
+ /* no soundbuffer. close and wait. */
+ if (audioOK)
+ DSOUND_CloseAudio();
+ Sleep(100);
}
dsound->lpvtbl->fnRelease(dsound);
-
- fputc('0'+playing,stderr);
- curleft = 0;
- while (curleft < sizeof(playbuf)) {
- res = write(audiofd,(LPBYTE)playbuf+curleft,sizeof(playbuf)-curleft);
- if (res==-1) {
- if (errno==EINTR)
- continue;
- perror("write audiofd");
- ExitThread(0);
- break;
- }
- curleft+=res;
- }
}
ExitThread(0);
}
#endif /* HAVE_OSS */
-HRESULT WINAPI DirectSoundCreate(LPGUID lpGUID,LPDIRECTSOUND *ppDS,IUnknown *pUnkOuter ) {
- int xx;
+HRESULT WINAPI DirectSoundCreate(LPGUID lpGUID,LPDIRECTSOUND *ppDS,IUnknown *pUnkOuter )
+{
if (lpGUID)
TRACE(dsound,"(%p,%p,%p)\n",lpGUID,ppDS,pUnkOuter);
+ else
+ TRACE(dsound,"DirectSoundCreate\n");
#ifdef HAVE_OSS
- if (audiofd>=0)
+ if (primarybuf)
return DSERR_ALLOCATED;
- audiofd = open("/dev/audio",O_WRONLY);
- if (audiofd==-1) {
- perror("open /dev/audio");
- audiofd=0;
- return DSERR_NODRIVER;
- }
- xx=0x0002000c;
- if (-1==ioctl(audiofd,SNDCTL_DSP_SETFRAGMENT,&xx))
- perror("ioctl SETFRAGMENT");
-/*
- TRACE(dsound,"SETFRAGMENT. count is now %d, fragsize is %d\n",
- (xx>>16)+1,xx&0xffff
- );
- */
*ppDS = (LPDIRECTSOUND)HeapAlloc(GetProcessHeap(),0,sizeof(IDirectSound));
(*ppDS)->ref = 1;
@@ -1041,13 +1849,26 @@
(*ppDS)->wfx.nBlockAlign = 2;
(*ppDS)->wfx.wBitsPerSample = 8;
- DSOUND_setformat(&((*ppDS)->wfx));
-
if (!dsound) {
HANDLE32 hnd;
DWORD xid;
dsound = (*ppDS);
+ if (primarybuf == NULL) {
+ DSBUFFERDESC dsbd;
+ HRESULT hr;
+
+ dsbd.dwSize = sizeof(DSBUFFERDESC);
+ dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER;
+ dsbd.dwBufferBytes = 0;
+ dsbd.lpwfxFormat = &(dsound->wfx);
+ hr = IDirectSound_CreateSoundBuffer(*ppDS, &dsbd, &primarybuf, NULL);
+ if (hr != DS_OK) {
+ dsound->primary = primarybuf;
+ return hr;
+ }
+ }
+
hnd = CreateThread(NULL,0,DSOUND_thread,0,0,&xid);
}
return 0;