mirror of
https://github.com/CookiePLMonster/SilentPatch.git
synced 2024-11-22 05:22:32 +01:00
199 lines
5.3 KiB
C++
199 lines
5.3 KiB
C++
|
#include "StdAfxSA.h"
|
||
|
#include "WaveDecoderSA.h"
|
||
|
|
||
|
extern void* pMalloc;
|
||
|
extern unsigned int nBlockSize;
|
||
|
extern unsigned int nLastMallocSize;
|
||
|
|
||
|
bool CAEWaveDecoder::Initialise()
|
||
|
{
|
||
|
auto* pTheStream = GetStream();
|
||
|
struct {
|
||
|
char sectionID[4];
|
||
|
unsigned int sectionSize;
|
||
|
} chunkHeader;
|
||
|
|
||
|
// Find fmt section
|
||
|
pTheStream->Seek(12, FILE_BEGIN);
|
||
|
|
||
|
pTheStream->FillBuffer(&chunkHeader, sizeof(chunkHeader));
|
||
|
nOffsetToData = 12 + sizeof(chunkHeader);
|
||
|
|
||
|
while ( chunkHeader.sectionID[0] != 'f' || chunkHeader.sectionID[1] != 'm' || chunkHeader.sectionID[2] != 't' || chunkHeader.sectionID[3] != ' ' )
|
||
|
{
|
||
|
nOffsetToData += sizeof(chunkHeader) + chunkHeader.sectionSize;
|
||
|
|
||
|
pTheStream->Seek(chunkHeader.sectionSize, FILE_CURRENT);
|
||
|
pTheStream->FillBuffer(&chunkHeader, sizeof(chunkHeader));
|
||
|
|
||
|
}
|
||
|
|
||
|
// Read fmt header
|
||
|
pTheStream->FillBuffer(&formatChunk, sizeof(FormatChunk));
|
||
|
nOffsetToData += sizeof(FormatChunk);
|
||
|
|
||
|
// Now skip through the rest of a chunk
|
||
|
if ( chunkHeader.sectionSize - sizeof(FormatChunk) > 0 )
|
||
|
{
|
||
|
nOffsetToData += chunkHeader.sectionSize - sizeof(FormatChunk);
|
||
|
pTheStream->Seek(chunkHeader.sectionSize - sizeof(FormatChunk), FILE_CURRENT);
|
||
|
}
|
||
|
|
||
|
// Find data chunk
|
||
|
nOffsetToData += sizeof(chunkHeader);
|
||
|
pTheStream->FillBuffer(&chunkHeader, sizeof(chunkHeader));
|
||
|
|
||
|
while ( chunkHeader.sectionID[0] != 'd' || chunkHeader.sectionID[1] != 'a' || chunkHeader.sectionID[2] != 't' || chunkHeader.sectionID[3] != 'a' )
|
||
|
{
|
||
|
nOffsetToData += sizeof(chunkHeader) + chunkHeader.sectionSize;
|
||
|
|
||
|
pTheStream->Seek(chunkHeader.sectionSize, FILE_CURRENT);
|
||
|
pTheStream->FillBuffer(&chunkHeader, sizeof(chunkHeader));
|
||
|
}
|
||
|
|
||
|
nDataSize = chunkHeader.sectionSize;
|
||
|
|
||
|
return formatChunk.sampleRate <= 48000 && formatChunk.numChannels <= 2 && (formatChunk.bitsPerSample == 8 || formatChunk.bitsPerSample == 16 || formatChunk.bitsPerSample == 24);
|
||
|
}
|
||
|
|
||
|
unsigned int CAEWaveDecoder::FillBuffer(void* pBuf, unsigned long nLen)
|
||
|
{
|
||
|
if ( formatChunk.bitsPerSample == 8 )
|
||
|
{
|
||
|
if ( formatChunk.numChannels == 2 )
|
||
|
{
|
||
|
// Stereo
|
||
|
if ( nLen / 2 > nLastMallocSize )
|
||
|
{
|
||
|
if ( pMalloc )
|
||
|
operator delete(pMalloc);
|
||
|
|
||
|
nLastMallocSize = nLen / 2;
|
||
|
pMalloc = operator new(nLastMallocSize);
|
||
|
}
|
||
|
|
||
|
unsigned int nBytesWritten = GetStream()->FillBuffer(pMalloc, nLen / 2);
|
||
|
signed short* pOutBuf = static_cast<signed short*>(pBuf);
|
||
|
unsigned char* pInBuf = static_cast<unsigned char*>(pMalloc);
|
||
|
|
||
|
// Convert to 16-bit
|
||
|
for ( unsigned int i = 0; i < nBytesWritten; i++ )
|
||
|
{
|
||
|
pOutBuf[i] = (static_cast<signed char>(pInBuf[i]) - 128) << 8;
|
||
|
}
|
||
|
|
||
|
return nBytesWritten * 2;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Mono
|
||
|
if ( nLen / 4 > nLastMallocSize )
|
||
|
{
|
||
|
if ( pMalloc )
|
||
|
operator delete(pMalloc);
|
||
|
|
||
|
nLastMallocSize = nLen / 4;
|
||
|
pMalloc = operator new(nLastMallocSize);
|
||
|
}
|
||
|
|
||
|
unsigned int nBytesWritten = GetStream()->FillBuffer(pMalloc, nLen / 4);
|
||
|
signed short* pOutBuf = static_cast<signed short*>(pBuf);
|
||
|
unsigned char* pInBuf = static_cast<unsigned char*>(pMalloc);
|
||
|
|
||
|
// Convert to 16-bit
|
||
|
for ( unsigned int i = 0; i < nBytesWritten; i++ )
|
||
|
{
|
||
|
pOutBuf[i * 2] = pOutBuf[i * 2 + 1] = (static_cast<signed char>(pInBuf[i]) - 128) << 8;
|
||
|
}
|
||
|
|
||
|
return nBytesWritten * 4;
|
||
|
}
|
||
|
}
|
||
|
else if ( formatChunk.bitsPerSample == 24 )
|
||
|
{
|
||
|
if ( formatChunk.numChannels == 2 )
|
||
|
{
|
||
|
// Stereo
|
||
|
if ( nLen * 3 / 2 > nLastMallocSize )
|
||
|
{
|
||
|
if ( pMalloc )
|
||
|
operator delete(pMalloc);
|
||
|
|
||
|
nLastMallocSize = nLen * 3 / 2;
|
||
|
pMalloc = operator new(nLastMallocSize);
|
||
|
}
|
||
|
|
||
|
unsigned int nBytesWritten = GetStream()->FillBuffer(pMalloc, nLen * 3 / 2);
|
||
|
unsigned char* pOutBuf = static_cast<unsigned char*>(pBuf);
|
||
|
unsigned char* pInBuf = static_cast<unsigned char*>(pMalloc);
|
||
|
const unsigned int nNumSamples = nBytesWritten / 3;
|
||
|
|
||
|
// Convert to 16-bit
|
||
|
for ( unsigned int i = 0; i < nNumSamples; i++ )
|
||
|
{
|
||
|
pOutBuf[i*2] = pInBuf[i*3 + 1];
|
||
|
pOutBuf[i*2 + 1] = pInBuf[i*3 + 2];
|
||
|
}
|
||
|
|
||
|
return nNumSamples * 2;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if ( nLen * 3 / 4 > nLastMallocSize )
|
||
|
{
|
||
|
if ( pMalloc )
|
||
|
operator delete(pMalloc);
|
||
|
|
||
|
nLastMallocSize = nLen * 3 / 4;
|
||
|
pMalloc = operator new(nLastMallocSize);
|
||
|
}
|
||
|
|
||
|
unsigned int nBytesWritten = GetStream()->FillBuffer(pMalloc, nLen * 3 / 4);
|
||
|
unsigned char* pOutBuf = static_cast<unsigned char*>(pBuf);
|
||
|
unsigned char* pInBuf = static_cast<unsigned char*>(pMalloc);
|
||
|
const unsigned int nNumSamples = nBytesWritten / 3;
|
||
|
|
||
|
// Convert to 16-bit
|
||
|
for ( unsigned int i = 0; i < nNumSamples; i++ )
|
||
|
{
|
||
|
pOutBuf[i*4] = pOutBuf[i*4 + 2] = pInBuf[i*3 + 1];
|
||
|
pOutBuf[i*4 + 1] = pOutBuf[i*4 + 3] = pInBuf[i*3 + 2];
|
||
|
}
|
||
|
|
||
|
return nNumSamples * 4;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// 16-bit
|
||
|
if ( formatChunk.numChannels == 2 )
|
||
|
{
|
||
|
// Stereo, optimised fetch
|
||
|
return GetStream()->FillBuffer(pBuf, nLen);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Mono
|
||
|
if ( nLen / 2 > nLastMallocSize )
|
||
|
{
|
||
|
if ( pMalloc )
|
||
|
operator delete(pMalloc);
|
||
|
|
||
|
nLastMallocSize = nLen / 2;
|
||
|
pMalloc = operator new(nLastMallocSize);
|
||
|
}
|
||
|
|
||
|
unsigned int nBytesWritten = GetStream()->FillBuffer(pMalloc, nLen / 2);
|
||
|
signed short* pOutBuf = static_cast<signed short*>(pBuf);
|
||
|
signed short* pInBuf = static_cast<signed short*>(pMalloc);
|
||
|
const unsigned int nNumSamples = nBytesWritten / 2;
|
||
|
|
||
|
for ( unsigned int i = 0; i < nNumSamples; i++ )
|
||
|
{
|
||
|
pOutBuf[i*2] = pOutBuf[i*2 + 1] = pInBuf[i];
|
||
|
}
|
||
|
|
||
|
return nBytesWritten * 2;
|
||
|
}
|
||
|
}
|
||
|
}
|