2002-06-13 19:15:06 +00:00
|
|
|
/* DirectSound
|
|
|
|
*
|
|
|
|
* Copyright 1998 Marcus Meissner
|
|
|
|
* Copyright 1998 Rob Riggs
|
|
|
|
* Copyright 2000-2001 TransGaming Technologies, Inc.
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Linux does not support better timing than 10ms */
|
|
|
|
#define DS_TIME_RES 10 /* Resolution of multimedia timer */
|
|
|
|
#define DS_TIME_DEL 10 /* Delay of multimedia timer callback, and duration of HEL fragment */
|
|
|
|
|
|
|
|
#define DS_HEL_FRAGS 48 /* HEL only: number of waveOut fragments in primary buffer
|
|
|
|
* (changing this won't help you) */
|
|
|
|
|
|
|
|
extern int ds_emuldriver;
|
|
|
|
extern int ds_hel_margin;
|
|
|
|
extern int ds_hel_queue;
|
|
|
|
extern int ds_snd_queue_max;
|
|
|
|
extern int ds_snd_queue_min;
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
* Predeclare the interface implementation structures
|
|
|
|
*/
|
|
|
|
typedef struct IDirectSoundImpl IDirectSoundImpl;
|
|
|
|
typedef struct IDirectSoundBufferImpl IDirectSoundBufferImpl;
|
2003-02-15 00:01:17 +00:00
|
|
|
typedef struct IDirectSoundCaptureImpl IDirectSoundCaptureImpl;
|
|
|
|
typedef struct IDirectSoundCaptureBufferImpl IDirectSoundCaptureBufferImpl;
|
2002-06-13 19:15:06 +00:00
|
|
|
typedef struct IDirectSoundNotifyImpl IDirectSoundNotifyImpl;
|
|
|
|
typedef struct IDirectSound3DListenerImpl IDirectSound3DListenerImpl;
|
|
|
|
typedef struct IDirectSound3DBufferImpl IDirectSound3DBufferImpl;
|
|
|
|
typedef struct IKsPropertySetImpl IKsPropertySetImpl;
|
|
|
|
typedef struct PrimaryBufferImpl PrimaryBufferImpl;
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
* IDirectSound implementation structure
|
|
|
|
*/
|
|
|
|
struct IDirectSoundImpl
|
|
|
|
{
|
|
|
|
/* IUnknown fields */
|
|
|
|
ICOM_VFIELD(IDirectSound8);
|
|
|
|
DWORD ref;
|
|
|
|
/* IDirectSoundImpl fields */
|
|
|
|
PIDSDRIVER driver;
|
|
|
|
DSDRIVERDESC drvdesc;
|
|
|
|
DSDRIVERCAPS drvcaps;
|
|
|
|
DWORD priolevel;
|
|
|
|
WAVEFORMATEX wfx; /* current main waveformat */
|
|
|
|
HWAVEOUT hwo;
|
|
|
|
LPWAVEHDR pwave[DS_HEL_FRAGS];
|
|
|
|
UINT timerID, pwplay, pwwrite, pwqueue, prebuf, precount;
|
|
|
|
DWORD fraglen;
|
|
|
|
PIDSDRIVERBUFFER hwbuf;
|
|
|
|
LPBYTE buffer;
|
|
|
|
DWORD writelead, buflen, state, playpos, mixpos;
|
|
|
|
BOOL need_remix;
|
|
|
|
int nrofbuffers;
|
|
|
|
IDirectSoundBufferImpl** buffers;
|
|
|
|
IDirectSound3DListenerImpl* listener;
|
2003-02-15 00:01:17 +00:00
|
|
|
RTL_RWLOCK lock;
|
|
|
|
CRITICAL_SECTION mixlock;
|
|
|
|
DSVOLUMEPAN volpan;
|
2002-06-13 19:15:06 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
* IDirectSoundBuffer implementation structure
|
|
|
|
*/
|
|
|
|
struct IDirectSoundBufferImpl
|
|
|
|
{
|
|
|
|
/* FIXME: document */
|
|
|
|
/* IUnknown fields */
|
|
|
|
ICOM_VFIELD(IDirectSoundBuffer8);
|
|
|
|
DWORD ref;
|
|
|
|
/* IDirectSoundBufferImpl fields */
|
|
|
|
IDirectSoundImpl* dsound;
|
|
|
|
IDirectSoundBufferImpl* parent; /* for duplicates */
|
|
|
|
IDirectSound3DBufferImpl* ds3db;
|
|
|
|
IKsPropertySetImpl* iks;
|
|
|
|
CRITICAL_SECTION lock;
|
|
|
|
PIDSDRIVERBUFFER hwbuf;
|
|
|
|
WAVEFORMATEX wfx;
|
|
|
|
LPBYTE buffer;
|
|
|
|
DWORD playflags,state,leadin;
|
|
|
|
DWORD playpos,startpos,writelead,buflen;
|
|
|
|
DWORD nAvgBytesPerSec;
|
|
|
|
DWORD freq;
|
|
|
|
DSVOLUMEPAN volpan, cvolpan;
|
|
|
|
DSBUFFERDESC dsbd;
|
|
|
|
/* used for frequency conversion (PerfectPitch) */
|
|
|
|
ULONG freqAdjust, freqAcc;
|
|
|
|
/* used for intelligent (well, sort of) prebuffering */
|
|
|
|
DWORD probably_valid_to, last_playpos;
|
|
|
|
DWORD primary_mixpos, buf_mixpos;
|
|
|
|
BOOL need_remix;
|
|
|
|
/* IDirectSoundNotifyImpl fields */
|
|
|
|
LPDSBPOSITIONNOTIFY notifies;
|
|
|
|
int nrofnotifies;
|
|
|
|
};
|
|
|
|
|
|
|
|
HRESULT WINAPI SecondaryBuffer_Create(
|
|
|
|
IDirectSoundImpl *This,
|
|
|
|
IDirectSoundBufferImpl **pdsb,
|
|
|
|
LPDSBUFFERDESC dsbd);
|
|
|
|
|
|
|
|
struct PrimaryBufferImpl {
|
|
|
|
ICOM_VFIELD(IDirectSoundBuffer8);
|
|
|
|
DWORD ref;
|
|
|
|
IDirectSoundImpl* dsound;
|
|
|
|
DSBUFFERDESC dsbd;
|
|
|
|
};
|
|
|
|
|
|
|
|
HRESULT WINAPI PrimaryBuffer_Create(
|
|
|
|
IDirectSoundImpl *This,
|
|
|
|
PrimaryBufferImpl **pdsb,
|
|
|
|
LPDSBUFFERDESC dsbd);
|
|
|
|
|
2003-02-15 00:01:17 +00:00
|
|
|
/*****************************************************************************
|
|
|
|
* IDirectSoundCapture implementation structure
|
|
|
|
*/
|
|
|
|
struct IDirectSoundCaptureImpl
|
|
|
|
{
|
|
|
|
/* IUnknown fields */
|
|
|
|
ICOM_VFIELD(IDirectSoundCapture);
|
|
|
|
DWORD ref;
|
|
|
|
|
|
|
|
/* IDirectSoundCaptureImpl fields */
|
|
|
|
GUID guid;
|
|
|
|
BOOL initialized;
|
|
|
|
|
|
|
|
/* DirectSound driver stuff */
|
|
|
|
PIDSCDRIVER driver;
|
|
|
|
DSDRIVERDESC drvdesc;
|
|
|
|
DSDRIVERCAPS drvcaps;
|
|
|
|
PIDSDRIVERBUFFER hwbuf;
|
|
|
|
|
|
|
|
/* wave driver info */
|
|
|
|
HWAVEIN hwi;
|
|
|
|
|
|
|
|
/* more stuff */
|
|
|
|
LPBYTE buffer;
|
|
|
|
DWORD buflen;
|
|
|
|
DWORD read_position;
|
|
|
|
|
|
|
|
/* FIXME: this should be a pointer because it can be bigger */
|
|
|
|
WAVEFORMATEX wfx;
|
|
|
|
|
|
|
|
DWORD formats;
|
|
|
|
DWORD channels;
|
|
|
|
IDirectSoundCaptureBufferImpl* capture_buffer;
|
|
|
|
DWORD state;
|
|
|
|
LPWAVEHDR pwave;
|
|
|
|
int index;
|
|
|
|
CRITICAL_SECTION lock;
|
|
|
|
};
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
* IDirectSoundCaptureBuffer implementation structure
|
|
|
|
*/
|
|
|
|
struct IDirectSoundCaptureBufferImpl
|
|
|
|
{
|
|
|
|
/* IUnknown fields */
|
|
|
|
ICOM_VFIELD(IDirectSoundCaptureBuffer8);
|
|
|
|
DWORD ref;
|
|
|
|
|
|
|
|
/* IDirectSoundCaptureBufferImpl fields */
|
|
|
|
IDirectSoundCaptureImpl* dsound;
|
|
|
|
CRITICAL_SECTION lock;
|
|
|
|
/* FIXME: don't need this */
|
|
|
|
LPDSCBUFFERDESC pdscbd;
|
|
|
|
LPDSBPOSITIONNOTIFY notifies;
|
|
|
|
int nrofnotifies;
|
|
|
|
DWORD flags;
|
|
|
|
};
|
|
|
|
|
2002-06-13 19:15:06 +00:00
|
|
|
/*****************************************************************************
|
|
|
|
* IDirectSoundNotify implementation structure
|
|
|
|
*/
|
|
|
|
struct IDirectSoundNotifyImpl
|
|
|
|
{
|
|
|
|
/* IUnknown fields */
|
|
|
|
ICOM_VFIELD(IDirectSoundNotify);
|
|
|
|
DWORD ref;
|
|
|
|
/* IDirectSoundNotifyImpl fields */
|
2003-02-15 00:01:17 +00:00
|
|
|
IDirectSoundBufferImpl* dsb;
|
|
|
|
IDirectSoundCaptureBufferImpl* dscb;
|
2002-06-13 19:15:06 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
* IDirectSound3DListener implementation structure
|
|
|
|
*/
|
|
|
|
struct IDirectSound3DListenerImpl
|
|
|
|
{
|
|
|
|
/* IUnknown fields */
|
|
|
|
ICOM_VFIELD(IDirectSound3DListener);
|
|
|
|
DWORD ref;
|
|
|
|
/* IDirectSound3DListenerImpl fields */
|
|
|
|
PrimaryBufferImpl* dsb;
|
|
|
|
DS3DLISTENER ds3dl;
|
|
|
|
CRITICAL_SECTION lock;
|
|
|
|
BOOL need_recalc;
|
|
|
|
};
|
|
|
|
|
|
|
|
HRESULT WINAPI IDirectSound3DListenerImpl_Create(
|
|
|
|
PrimaryBufferImpl *This,
|
|
|
|
IDirectSound3DListenerImpl **pdsl);
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
* IKsPropertySet implementation structure
|
|
|
|
*/
|
|
|
|
struct IKsPropertySetImpl
|
|
|
|
{
|
|
|
|
/* IUnknown fields */
|
|
|
|
ICOM_VFIELD(IKsPropertySet);
|
|
|
|
DWORD ref;
|
|
|
|
/* IKsPropertySetImpl fields */
|
|
|
|
IDirectSoundBufferImpl* dsb;
|
|
|
|
};
|
|
|
|
|
|
|
|
HRESULT WINAPI IKsPropertySetImpl_Create(
|
|
|
|
IDirectSoundBufferImpl *This,
|
|
|
|
IKsPropertySetImpl **piks);
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
* IDirectSound3DBuffer implementation structure
|
|
|
|
*/
|
|
|
|
struct IDirectSound3DBufferImpl
|
|
|
|
{
|
|
|
|
/* IUnknown fields */
|
|
|
|
ICOM_VFIELD(IDirectSound3DBuffer);
|
|
|
|
DWORD ref;
|
|
|
|
/* IDirectSound3DBufferImpl fields */
|
|
|
|
IDirectSoundBufferImpl* dsb;
|
|
|
|
DS3DBUFFER ds3db;
|
|
|
|
LONG lVolume;
|
|
|
|
CRITICAL_SECTION lock;
|
|
|
|
BOOL need_recalc;
|
|
|
|
};
|
|
|
|
|
|
|
|
HRESULT WINAPI IDirectSound3DBufferImpl_Create(
|
|
|
|
IDirectSoundBufferImpl *This,
|
|
|
|
IDirectSound3DBufferImpl **pds3db);
|
|
|
|
|
|
|
|
void DSOUND_RecalcVolPan(PDSVOLUMEPAN volpan);
|
|
|
|
void DSOUND_RecalcFormat(IDirectSoundBufferImpl *dsb);
|
|
|
|
|
|
|
|
/* primary.c */
|
|
|
|
|
|
|
|
HRESULT DSOUND_PrimaryCreate(IDirectSoundImpl *This);
|
|
|
|
HRESULT DSOUND_PrimaryDestroy(IDirectSoundImpl *This);
|
|
|
|
HRESULT DSOUND_PrimaryPlay(IDirectSoundImpl *This);
|
|
|
|
HRESULT DSOUND_PrimaryStop(IDirectSoundImpl *This);
|
|
|
|
HRESULT DSOUND_PrimaryGetPosition(IDirectSoundImpl *This, LPDWORD playpos, LPDWORD writepos);
|
|
|
|
|
|
|
|
/* buffer.c */
|
|
|
|
|
|
|
|
DWORD DSOUND_CalcPlayPosition(IDirectSoundBufferImpl *This,
|
|
|
|
DWORD state, DWORD pplay, DWORD pwrite, DWORD pmix, DWORD bmix);
|
|
|
|
|
|
|
|
/* mixer.c */
|
|
|
|
|
|
|
|
void DSOUND_CheckEvent(IDirectSoundBufferImpl *dsb, int len);
|
|
|
|
void DSOUND_ForceRemix(IDirectSoundBufferImpl *dsb);
|
|
|
|
void DSOUND_MixCancelAt(IDirectSoundBufferImpl *dsb, DWORD buf_writepos);
|
|
|
|
void DSOUND_WaveQueue(IDirectSoundImpl *dsound, DWORD mixq);
|
|
|
|
void DSOUND_PerformMix(void);
|
|
|
|
void CALLBACK DSOUND_timer(UINT timerID, UINT msg, DWORD dwUser, DWORD dw1, DWORD dw2);
|
|
|
|
void CALLBACK DSOUND_callback(HWAVEOUT hwo, UINT msg, DWORD dwUser, DWORD dw1, DWORD dw2);
|
|
|
|
|
2003-02-15 00:01:17 +00:00
|
|
|
#define STATE_STOPPED 0
|
|
|
|
#define STATE_STARTING 1
|
|
|
|
#define STATE_PLAYING 2
|
|
|
|
#define STATE_CAPTURING 2
|
|
|
|
#define STATE_STOPPING 3
|
2002-06-13 19:15:06 +00:00
|
|
|
|
|
|
|
#define DSOUND_FREQSHIFT (14)
|
|
|
|
|
|
|
|
extern IDirectSoundImpl* dsound;
|
|
|
|
|
|
|
|
struct PrimaryBuffer {
|
|
|
|
DWORD ref;
|
|
|
|
PIDSDRIVERBUFFER hwbuf;
|
|
|
|
DWORD state;
|
|
|
|
};
|
2003-02-15 00:01:17 +00:00
|
|
|
|
|
|
|
extern ICOM_VTABLE(IDirectSoundNotify) dsnvt;
|
|
|
|
extern HRESULT mmErr(UINT err);
|