|
|
// dswave.h
// (c) 1999-2000 Microsoft Corp.
#ifndef _DSWAVE_H_
#define _DSWAVE_H_
#include <mmsystem.h>
#include <mmreg.h>
#include <msacm.h>
#include "dsoundp.h" // For IDirectSoundWave and IDirectSoundSource
#include "dmusicc.h"
#include "dmusici.h"
#include "riff.h"
extern long g_cComponent;
#define REF_PER_MIL 10000 // For converting from reference time to mils
#define CONVERTLENGTH 250
// #define DSWCS_F_DEINTERLEAVED 0x00000001 // Multi-channel data as multiple buffers
// FIXME: unimplemented so far?
typedef struct tCREATEVIEWPORT { IStream *pStream; DWORD cSamples; DWORD dwDecompressedStart; DWORD cbStream; LPWAVEFORMATEX pwfxSource; LPWAVEFORMATEX pwfxTarget; DWORD fdwOptions; } CREATEVIEWPORT, *PCREATEVIEWPORT;
// Private interface for getting the length of a wave
interface IPrivateWave : IUnknown { virtual HRESULT STDMETHODCALLTYPE GetLength(REFERENCE_TIME *prtLength)=0; };
DEFINE_GUID(IID_IPrivateWave, 0xce6ae366, 0x9d61, 0x420a, 0xad, 0x53, 0xe5, 0xe5, 0xf6, 0xa8, 0x4a, 0xe4);
// Flags for SetWaveBehavior()
#define DSOUND_WAVEF_ONESHOT 1 /* The wave will be played as a one shot */
#define DSOUND_WAVEF_PORT 2 /* The wave will be played via a DMusic port. */
#define DSOUND_WAVEF_SINK 4 /* The wave will be played via a streamed sink interface. */
#define DSOUND_WAVEF_CREATEMASK 0x00000001 /* Currently only ONESHOT is define for CreateSource */
#define DSOUND_WVP_NOCONVERT 0x80000000 /* The viewport data is the same format as the wave */
#define DSOUND_WVP_STREAMEND 0x40000000 /* The viewport data is the same format as the wave */
#define DSOUND_WVP_CONVERTSTATE_01 0x01000000
#define DSOUND_WVP_CONVERTSTATE_02 0x02000000
#define DSOUND_WVP_CONVERTSTATE_03 0x04000000
#define DSOUND_WVP_CONVERTMASK 0x0f000000
/* The CWaveViewPort structure represents one instance, or "view", of the
wave object. It manages the reading of the wave data, ACM decompression, and demultiplexing into mono buffers. If a wave object is being streamed, each playback instance gets a unique CWaveViewPort. However, in the more typical case where the wave object is being played as a one shot, each playback instance uses the same CWaveViewPort. Each additional CWaveViewPort owns a cloned instance of the IStream. */
class CWaveViewPort : public IDirectSoundSource // Used by a port or sink to pull data.
{ public: CWaveViewPort(); // Constructor receives stream.
~CWaveViewPort(); // Destructor releases memory, streams, etc.
// IUnknown
STDMETHODIMP QueryInterface(const IID &iid, void **ppv); STDMETHODIMP_(ULONG) AddRef(); STDMETHODIMP_(ULONG) Release();
// IDirectSoundSource
STDMETHODIMP SetSink(IDirectSoundConnect *pSinkConnect); STDMETHODIMP GetFormat(LPWAVEFORMATEX pwfx, DWORD dwSizeAllocated, LPDWORD pdwSizeWritten); STDMETHODIMP Seek(ULONGLONG sp); STDMETHODIMP Read(LPVOID *ppvBuffer, LPDWORD pdwBusIds, LPDWORD pdwFuncIds, LPLONG plPitchShifts, DWORD cpvBuffer, ULONGLONG *pcb); STDMETHODIMP GetSize(ULONGLONG *pcb);
// Misc
HRESULT Create(PCREATEVIEWPORT pCreate);
private:
HRESULT acmRead();
// General stuff...
CRITICAL_SECTION m_CriticalSection; // Used to ensure thread safe
long m_cRef; // COM reference counter.
// Details about original data stream...
IStream * m_pStream; // IStream pointer which is connected to IPersistStream
// interface to pull data from file.
DWORD m_cSamples; // Number of samples (if available)
DWORD m_cbStream; // Number of bytes in stream.
DWORD m_dwStart; // Offset into stream where data starts
//LPWAVEFORMATEX m_pwfxSource; // Do we need to hold on to this?
// Details needed for this viewport.
DWORD m_dwOffset; // Current byte offset into data stream
DWORD m_dwStartPos; // Initial Start Offset
LPWAVEFORMATEX m_pwfxTarget; // Target destination format.
ACMSTREAMHEADER m_ash; // ACM Stream header (used for conversion)
HACMSTREAM m_hStream; // ACM Stream handle for conversion
LPBYTE m_pDst; // Pointer to (decompressed) destination
LPBYTE m_pRaw; // Pointer to compressed source buffer
DWORD m_fdwOptions; // Options for viewport
DWORD m_dwDecompressedStart; // Actual start for the data after decompression in Samples
// This is important for MP3 and WMA codecs that
// insert some amount of silence in the beginning
DWORD m_dwDecompStartOffset; // Byte Offset in the compressed stream to the block which
// needs to be decompressed to get to the right start value
DWORD m_dwDecompStartOffsetPCM;// Byte offset in the decompressed stream...corresponds to
// m_dwDecompressedStart samples
DWORD m_dwDecompStartDelta; // The delta (in bytes) to add when we decompress the block starting
// from m_dwDecompStartOffset
// Only used to accurately get data after precached data for DirectSoundWave in DMusic
DWORD m_dwPreCacheFilePos; DWORD m_dwFirstPCMSample; DWORD m_dwPCMSampleOut; };
/* The CWave class represents one instance of a wave object. It
supports the IDirectSoundWave interface, which the application uses to access the wave. It also support IPersistStream and IDirectMusicObject, which are used by the loader to load the wave data from a stream into the wave object. And, the IDirectSoundSource interface manages the direct transfer of the wave data from the object to the synth or DirectSound. This is for internal use, not by the application (though it represents an easy way for an app to load wave data and then extract it.) CWave maintains a list of CWaveViewPorts, though typically there is only one. */
class CWave : public IDirectSoundWave, // Standard interface.
public IPersistStream, // For file io
public IDirectMusicObject, // For DirectMusic loader
public IPrivateWave // For GetLength
{ public: CWave(); ~CWave();
// IUnknown
STDMETHODIMP QueryInterface(const IID &iid, void **ppv); STDMETHODIMP_(ULONG) AddRef(); STDMETHODIMP_(ULONG) Release();
// IDirectSoundWave
STDMETHODIMP GetFormat(LPWAVEFORMATEX pWaveFormatEx, DWORD dwSizeAllocated, LPDWORD pdwSizeWritten); STDMETHODIMP CreateSource(IDirectSoundSource **ppSource, LPWAVEFORMATEX pwfx, DWORD dwFlags); STDMETHODIMP GetStreamingParms(LPDWORD pdwFlags, LPREFERENCE_TIME prtReadahread);
// IPersist functions (base class for IPersistStream)
STDMETHODIMP GetClassID( CLSID* pClsId );
// IPersistStream functions
STDMETHODIMP IsDirty(); STDMETHODIMP Load( IStream* pIStream ); STDMETHODIMP Save( IStream* pIStream, BOOL fClearDirty ); STDMETHODIMP GetSizeMax( ULARGE_INTEGER FAR* pcbSize );
// IDirectMusicObject
STDMETHODIMP GetDescriptor(LPDMUS_OBJECTDESC pDesc); STDMETHODIMP SetDescriptor(LPDMUS_OBJECTDESC pDesc); STDMETHODIMP ParseDescriptor(LPSTREAM pStream, LPDMUS_OBJECTDESC pDesc);
// IPrivateWave
STDMETHODIMP GetLength(REFERENCE_TIME *prtLength);
private: // Internal methods.
BOOL ParseHeader(IStream *pIStream, IRIFFStream* pIRiffStream, LPMMCKINFO pckMain);
void FallbackStreamingBehavior() { REFERENCE_TIME rtLength = 0; if (SUCCEEDED(GetLength(&rtLength))) { // if > 5000 milliseconds, set to streaming with a 500 ms readahead
if (rtLength > 5000) { m_rtReadAheadTime = 500 * REF_PER_MIL; m_fdwFlags &= ~DSOUND_WAVEF_ONESHOT; } else { m_rtReadAheadTime = 0; m_fdwFlags |= DSOUND_WAVEF_ONESHOT; } } }
CRITICAL_SECTION m_CriticalSection; // Used to ensure thread safe
LPWAVEFORMATEX m_pwfxDst; // Destination format, if compressed
REFERENCE_TIME m_rtReadAheadTime; // Readahead for streaming.
DWORD m_fdwFlags; // Various flags, including whether this is a one-shot.
long m_cRef; // COM reference counter.
IStream * m_pStream; // IStream pointer which is connected to IPersistStream
DWORD m_fdwOptions; // Flags set by call to SetWaveBehavior().
LPWAVEFORMATEX m_pwfx; // File's format
DWORD m_cbStream; DWORD m_cSamples; GUID m_guid; FILETIME m_ftDate; DMUS_VERSION m_vVersion; WCHAR m_wszFilename[DMUS_MAX_FILENAME]; DWORD m_dwDecompressedStart; };
class CDirectSoundWaveFactory : public IClassFactory { public: // IUnknown
//
virtual STDMETHODIMP QueryInterface(const IID &iid, void **ppv); virtual STDMETHODIMP_(ULONG) AddRef(); virtual STDMETHODIMP_(ULONG) Release();
// Interface IClassFactory
//
virtual STDMETHODIMP CreateInstance(IUnknown* pUnknownOuter, const IID& iid, void** ppv); virtual STDMETHODIMP LockServer(BOOL bLock);
// Constructor
//
CDirectSoundWaveFactory();
// Destructor
~CDirectSoundWaveFactory();
private: long m_cRef; };
#endif // _DSWAVE_H_
|