254 lines
9.9 KiB
C
254 lines
9.9 KiB
C
|
// 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_
|