148 lines
6.1 KiB
C
148 lines
6.1 KiB
C
|
/*==========================================================================
|
||
|
*
|
||
|
* Copyright (C) 1999 Microsoft Corporation. All Rights Reserved.
|
||
|
*
|
||
|
* File: dvsndt.h
|
||
|
* Content: definition of CSoundTarget class
|
||
|
*
|
||
|
* History:
|
||
|
* Date By Reason
|
||
|
* ==== == ======
|
||
|
* 09/02/99 rodtoll Created
|
||
|
* 09/08/99 rodtoll Updated to provide lockup detection
|
||
|
* 09/14/99 rodtoll Added WriteAheadSilence()
|
||
|
* 09/20/99 rodtoll Added handlers for buffer loss
|
||
|
* 11/12/99 rodtoll Updated to use new abstractions for playback (allows use
|
||
|
* of waveOut with this class).
|
||
|
* 01/24/2000 rodtoll Fix: Bug #129427 - Destroying transport before calling Delete3DSound
|
||
|
* 01/27/2000 rodtoll Bug #129934 - Update SoundTargets to take DSBUFFERDESC
|
||
|
* 02/17/2000 rodtoll Bug #133691 - Choppy audio - queue was not adapting
|
||
|
* Added instrumentation
|
||
|
* 04/17/2000 rodtoll Fix: Bug #32215 - Session Lost after resuming from hibernation
|
||
|
* 06/21/2000 rodtoll Fix: Bug #35767 - Must implement ability for dsound effects on voice buffers
|
||
|
* Added new constructor/init that takes pre-built buffers
|
||
|
* 07/09/2000 rodtoll Added signature bytes
|
||
|
*
|
||
|
***************************************************************************/
|
||
|
|
||
|
#ifndef __DVSNDT_H
|
||
|
#define __DVSNDT_H
|
||
|
|
||
|
// CSoundTarget
|
||
|
//
|
||
|
// This class represents a single mixer target within the DirectPlayClient system. Normally there
|
||
|
// is only a single mixer target ("main") for all incoming audio. However, using the CreateUserBuffer and
|
||
|
// DeleteUserBuffer APIs the developer can specify that they wish to seperate a group or a player
|
||
|
// from the main mixer target. In this manner they can control the 3d spatialization of the group/player's
|
||
|
// incoming audio stream.
|
||
|
//
|
||
|
// This class handles all the details related to a mixer target. It encapsulates the mixing of single
|
||
|
// or multiple source audio frames and then commiting them to the corresponding directsound buffer. It also
|
||
|
// handles timing errors in the directsoundbuffer.
|
||
|
//
|
||
|
// For example, if the directsoundbuffer stops running, it will attempt to reset the buffer.
|
||
|
//
|
||
|
// If the directsoundbuffer slows down (because of high CPU), it moves the read pointer forward. In short
|
||
|
// it ensures that there is always 1 or 2 frames of mixed audio present in the buffer in advance of the
|
||
|
// read pointer.
|
||
|
//
|
||
|
// In addition the class provides reference counting to prevent premature deletion of the class. If you
|
||
|
// wish to take a reference to the class, call AddRef and you MUST then call Release when you are done.
|
||
|
//
|
||
|
// Do not destroy the object directly. When the last reference to the object is released the object will
|
||
|
// destroy itself.
|
||
|
//
|
||
|
// This class is not multithread safe (except for AddRef and Release). Only one thread should be
|
||
|
// accessing it.
|
||
|
//
|
||
|
#define VSIG_SOUNDTARGET 'TNSV'
|
||
|
#define VSIG_SOUNDTARGET_FREE 'TNS_'
|
||
|
|
||
|
volatile struct CSoundTarget
|
||
|
{
|
||
|
public:
|
||
|
|
||
|
CSoundTarget( DVID dvidTarget, CAudioPlaybackDevice *lpads, LPDSBUFFERDESC lpdsBufferDesc, DWORD dwPriority, DWORD dwFlags, DWORD dwFrameSize );
|
||
|
CSoundTarget( DVID dvidTarget, CAudioPlaybackDevice *lpads, CAudioPlaybackBuffer *lpdsBuffer, LPDSBUFFERDESC lpdsBufferDesc, DWORD dwPriority, DWORD dwFlags, DWORD dwFrameSize );
|
||
|
CSoundTarget( DVID dvidTarget, CAudioPlaybackDevice *lpads, LPDIRECTSOUNDBUFFER lpdsBuffer, BOOL fEightBit, DWORD dwPriority, DWORD dwFlags, DWORD dwFrameSize );
|
||
|
|
||
|
~CSoundTarget();
|
||
|
|
||
|
HRESULT StartMix();
|
||
|
|
||
|
HRESULT MixInSingle( LPBYTE lpbBuffer );
|
||
|
HRESULT MixIn( LPBYTE lpbBuffer );
|
||
|
|
||
|
HRESULT Commit();
|
||
|
|
||
|
inline HRESULT GetInitResult() { return m_hrInitResult; };
|
||
|
|
||
|
LPDIRECTSOUND3DBUFFER Get3DBuffer();
|
||
|
inline CAudioPlaybackBuffer *GetBuffer() { return m_lpAudioPlaybackBuffer; };
|
||
|
|
||
|
CSoundTarget *m_lpstNext; // Next entry in the list
|
||
|
|
||
|
inline DVID GetTarget() { return m_dvidTarget; };
|
||
|
inline LONG GetRefCount() { return m_lRefCount; };
|
||
|
|
||
|
LONG AddRef();
|
||
|
LONG Release();
|
||
|
|
||
|
void GetStats( PlaybackStats *statPlayback );
|
||
|
|
||
|
HRESULT GetCurrentLead( PDWORD pdwLead );
|
||
|
|
||
|
protected:
|
||
|
|
||
|
HRESULT Initialize( DVID dvidTarget, CAudioPlaybackBuffer *lpdsBuffer, BOOL fEightBit, DWORD dwPriority, DWORD dwFlags, DWORD dwFrameSize );
|
||
|
HRESULT RestoreLostBuffer();
|
||
|
|
||
|
HRESULT AdjustWritePtr();
|
||
|
HRESULT WriteAheadSilence();
|
||
|
|
||
|
void Stats_Init();
|
||
|
void Stats_Begin();
|
||
|
void Stats_End();
|
||
|
|
||
|
public:
|
||
|
|
||
|
DWORD m_dwSignature;
|
||
|
|
||
|
protected:
|
||
|
|
||
|
CAudioPlaybackBuffer *m_lpAudioPlaybackBuffer;
|
||
|
LPDIRECTSOUND3DBUFFER m_lpds3dBuffer; // 3d buffer interface for this sound target
|
||
|
DWORD m_dwNextWritePos; // Next byte position in the directsound buffer we'll
|
||
|
// be writing to.
|
||
|
DWORD m_dwBufferSize; // Size of directsound buffer in bytes
|
||
|
BOOL m_bGroup; // Does this buffer represent a group?
|
||
|
LPLONG m_lpMixBuffer; // High resolution mixing buffer
|
||
|
BOOL m_bCommited; // Has the data in the latest mix been commited to the buffer
|
||
|
BOOL m_fEightBit; // Is the buffer 8-bit?
|
||
|
HRESULT m_hrInitResult; // Contains result of the initializatio of this object
|
||
|
DWORD m_dwMixSize; // # of samples per frame
|
||
|
DWORD m_dwFrameSize; // Size of a frame in bytes
|
||
|
BOOL m_fMixed; // Set to TRUE as soon as a single source has been mixed
|
||
|
// Set to FALSE whenever the mix is commited.
|
||
|
LONG m_lRefCount; // Reference count on the object
|
||
|
DWORD m_dwLastWritePos; // Byte position that the last write occured at.
|
||
|
DWORD m_dwNumResets; // # of times buffer has been reset
|
||
|
BOOL m_fLastFramePushed; // Did the last frame push the read pointer forward?
|
||
|
DWORD m_dwNumSinceMove; // How many frames since no movement was detected?
|
||
|
DWORD m_dwLastWriteTime; // GetTickCount() at last call to AdjustWritePtr
|
||
|
BOOL m_fIgnoreFrame; // This frame will cross the boundary of where the write pointer is.
|
||
|
// Do NOT write to the buffer
|
||
|
DWORD m_dwWritePos;
|
||
|
DNCRITICAL_SECTION m_csGuard; // Guard for reference counts
|
||
|
DWORD m_dwPlayFlags;
|
||
|
DWORD m_dwPriority;
|
||
|
|
||
|
DVID m_dvidTarget; // DVID this buffer is for.
|
||
|
// DVID_REMAINING for the global one
|
||
|
|
||
|
PlaybackStats m_statPlay; // Playback Statistics
|
||
|
LPVOID m_lpDummy;
|
||
|
};
|
||
|
|
||
|
#endif
|