SilentPatch/SilentPatchSA/AudioHardwareSA.h

255 lines
7.2 KiB
C++

#ifndef __AUDIOHARDWARE
#define __AUDIOHARDWARE
// libflac
#define FLAC__NO_DLL
#include "FLAC\stream_decoder.h"
#include "FLAC\metadata.h"
// IStream
#include <Objidl.h>
enum eDecoderType
{
DECODER_NULL,
DECODER_VORBIS,
DECODER_WAVE,
DECODER_WINDOWSMEDIA,
DECODER_QUICKTIME,
// Custom
DECODER_FLAC
};
// 1.0/Steam structure
class NOVMT CAEDataStreamOld final : public IStream
{
private:
HANDLE hHandle;
char* pFilename;
bool bOpened;
DWORD dwCurrentPosition, dwStartPosition;
DWORD dwLength;
DWORD dwID;
bool bEncrypted;
LONG nRefCount;
public:
void operator delete(void* data)
{
// Call SA operator delete
GTAdelete(data);
}
CAEDataStreamOld() = delete;
~CAEDataStreamOld()
{
if ( bOpened )
{
CloseHandle(hHandle);
bOpened = false;
}
if ( pFilename != nullptr )
{
GTAdelete(pFilename);
pFilename = nullptr;
}
}
inline DWORD GetID() const
{ return dwID; }
inline HANDLE GetFile() const
{ return hHandle; }
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void ** ppvObject) override = 0;
virtual ULONG STDMETHODCALLTYPE AddRef(void) override = 0;
virtual ULONG STDMETHODCALLTYPE Release(void) override = 0;
// ISequentialStream Interface
public:
virtual HRESULT STDMETHODCALLTYPE Read(void* pv, ULONG cb, ULONG* pcbRead) override = 0;
virtual HRESULT STDMETHODCALLTYPE Write(void const* pv, ULONG cb, ULONG* pcbWritten) override = 0;
// IStream Interface
public:
virtual HRESULT STDMETHODCALLTYPE SetSize(ULARGE_INTEGER) override = 0;
virtual HRESULT STDMETHODCALLTYPE CopyTo(IStream*, ULARGE_INTEGER, ULARGE_INTEGER*, ULARGE_INTEGER*) override = 0;
virtual HRESULT STDMETHODCALLTYPE Commit(DWORD) override = 0;
virtual HRESULT STDMETHODCALLTYPE Revert(void) override = 0;
virtual HRESULT STDMETHODCALLTYPE LockRegion(ULARGE_INTEGER, ULARGE_INTEGER, DWORD) override = 0;
virtual HRESULT STDMETHODCALLTYPE UnlockRegion(ULARGE_INTEGER, ULARGE_INTEGER, DWORD) override = 0;
virtual HRESULT STDMETHODCALLTYPE Clone(IStream **) override = 0;
virtual HRESULT STDMETHODCALLTYPE Seek(LARGE_INTEGER liDistanceToMove, DWORD dwOrigin, ULARGE_INTEGER* lpNewFilePointer) override = 0;
virtual HRESULT STDMETHODCALLTYPE Stat(STATSTG* pStatstg, DWORD grfStatFlag) override = 0;
public:
// Custom methods
DWORD Seek(LONG nToSeek, DWORD nPoint);
DWORD FillBuffer(void* pBuf, DWORD nLen);
DWORD GetCurrentPosition() const
{
LARGE_INTEGER filePointer;
filePointer.QuadPart = 0;
SetFilePointerEx( hHandle, filePointer, &filePointer, FILE_CURRENT );
return DWORD(filePointer.QuadPart - dwStartPosition);
}
};
// 1.01 structure
class NOVMT CAEDataStreamNew final : public IStream
{
private:
void* pUselessMalloc;
HANDLE hHandle;
char* pFilename;
bool bOpened;
DWORD dwCurrentPosition, dwStartPosition;
DWORD dwLength;
DWORD dwID;
bool bEncrypted;
LONG nRefCount;
public:
void operator delete(void* data)
{
// Call SA operator delete
GTAdelete(data);
}
CAEDataStreamNew() = delete;
~CAEDataStreamNew()
{
if ( bOpened )
{
CloseHandle(hHandle);
bOpened = false;
}
if ( pFilename != nullptr )
{
GTAdelete(pFilename);
pFilename = nullptr;
}
}
inline DWORD GetID() const
{ return dwID; }
inline HANDLE GetFile() const
{ return hHandle; }
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void ** ppvObject) override = 0;
virtual ULONG STDMETHODCALLTYPE AddRef(void) override = 0;
virtual ULONG STDMETHODCALLTYPE Release(void) override = 0;
// ISequentialStream Interface
public:
virtual HRESULT STDMETHODCALLTYPE Read(void* pv, ULONG cb, ULONG* pcbRead) override = 0;
virtual HRESULT STDMETHODCALLTYPE Write(void const* pv, ULONG cb, ULONG* pcbWritten) override = 0;
// IStream Interface
public:
virtual HRESULT STDMETHODCALLTYPE SetSize(ULARGE_INTEGER) override = 0;
virtual HRESULT STDMETHODCALLTYPE CopyTo(IStream*, ULARGE_INTEGER, ULARGE_INTEGER*, ULARGE_INTEGER*) override = 0;
virtual HRESULT STDMETHODCALLTYPE Commit(DWORD) override = 0;
virtual HRESULT STDMETHODCALLTYPE Revert(void) override = 0;
virtual HRESULT STDMETHODCALLTYPE LockRegion(ULARGE_INTEGER, ULARGE_INTEGER, DWORD) override = 0;
virtual HRESULT STDMETHODCALLTYPE UnlockRegion(ULARGE_INTEGER, ULARGE_INTEGER, DWORD) override = 0;
virtual HRESULT STDMETHODCALLTYPE Clone(IStream **) override = 0;
virtual HRESULT STDMETHODCALLTYPE Seek(LARGE_INTEGER liDistanceToMove, DWORD dwOrigin, ULARGE_INTEGER* lpNewFilePointer) override = 0;
virtual HRESULT STDMETHODCALLTYPE Stat(STATSTG* pStatstg, DWORD grfStatFlag) override = 0;
public:
// Custom methods
DWORD Seek(LONG nToSeek, DWORD nPoint);
DWORD FillBuffer(void* pBuf, DWORD nLen);
DWORD GetCurrentPosition() const
{
LARGE_INTEGER filePointer;
filePointer.QuadPart = 0;
SetFilePointerEx( hHandle, filePointer, &filePointer, FILE_CURRENT );
return DWORD(filePointer.QuadPart - dwStartPosition);
}
};
class CAEDataStream
{
private:
static bool m_bUseNewStruct;
private:
~CAEDataStream() = delete;
CAEDataStream() = delete;
public:
static void SetStructType(bool bNew)
{ m_bUseNewStruct = bNew; }
static bool IsNew()
{ return m_bUseNewStruct; }
// This is handled by GTA so we can leave it that way
bool Initialise();
unsigned int Seek(long nToSeek, int nPoint)
{ if ( m_bUseNewStruct )
return reinterpret_cast<CAEDataStreamNew*>(this)->Seek(nToSeek, nPoint);
return reinterpret_cast<CAEDataStreamOld*>(this)->Seek(nToSeek, nPoint); }
unsigned int FillBuffer(void* pBuf, unsigned long nLen)
{ if ( m_bUseNewStruct )
return reinterpret_cast<CAEDataStreamNew*>(this)->FillBuffer(pBuf, nLen);
return reinterpret_cast<CAEDataStreamOld*>(this)->FillBuffer(pBuf, nLen); }
unsigned int GetCurrentPosition() const
{ if ( m_bUseNewStruct )
return reinterpret_cast<const CAEDataStreamNew*>(this)->GetCurrentPosition();
return reinterpret_cast<const CAEDataStreamOld*>(this)->GetCurrentPosition(); }
inline DWORD GetID() const
{ if ( m_bUseNewStruct )
return reinterpret_cast<const CAEDataStreamNew*>(this)->GetID();
return reinterpret_cast<const CAEDataStreamOld*>(this)->GetID(); }
inline HANDLE GetFile() const
{ if ( m_bUseNewStruct )
return reinterpret_cast<const CAEDataStreamNew*>(this)->GetFile();
return reinterpret_cast<const CAEDataStreamOld*>(this)->GetFile(); }
};
class CAEStreamingDecoder
{
private:
CAEDataStream* pStream;
public:
CAEStreamingDecoder(CAEDataStream* stream)
: pStream(stream)
{
if ( stream != nullptr )
stream->Initialise();
}
inline CAEDataStream* GetStream()
{ return pStream; }
inline const CAEDataStream* GetStream() const
{ return pStream; }
virtual bool Initialise()=0;
virtual uint32_t FillBuffer(void* pBuf,uint32_t nLen)=0;
virtual uint32_t GetStreamLengthMs() const =0;
virtual uint32_t GetStreamPlayTimeMs() const =0;
virtual void SetCursor(uint32_t nTime)=0;
virtual uint32_t GetSampleRate() const =0;
virtual ~CAEStreamingDecoder();
virtual uint32_t GetStreamID() const =0;
};
static_assert(sizeof(CAEDataStreamOld) == 0x28, "Wrong size: CAEDataStreamOld");
static_assert(sizeof(CAEDataStreamNew) == 0x2C, "Wrong size: CAEDataStreamNew");
#endif