mirror of
https://git.rip/DMCA_FUCKER/re3.git
synced 2024-12-22 21:20:01 +00:00
Cleanup and fixes for new decoders
This commit is contained in:
parent
36996af82b
commit
02a28996f4
|
@ -174,35 +174,45 @@ class CWavFile : public IDecoder
|
||||||
tFormatHeader() { memset(this, 0, sizeof(*this)); }
|
tFormatHeader() { memset(this, 0, sizeof(*this)); }
|
||||||
};
|
};
|
||||||
|
|
||||||
FILE* pFile;
|
FILE *m_pFile;
|
||||||
bool bIsOpen;
|
bool m_bIsOpen;
|
||||||
tFormatHeader FormatHeader;
|
|
||||||
|
|
||||||
uint32 DataStartOffset;
|
tFormatHeader m_FormatHeader;
|
||||||
uint32 SampleCount;
|
|
||||||
uint32 SamplesPerBlock;
|
uint32 m_DataStartOffset; // TODO: 64 bit?
|
||||||
|
uint32 m_nSampleCount;
|
||||||
|
uint32 m_nSamplesPerBlock;
|
||||||
|
|
||||||
// ADPCM things
|
// ADPCM things
|
||||||
uint8 *AdpcmBlock;
|
uint8 *m_pAdpcmBuffer;
|
||||||
int16 **buffers;
|
int16 **m_ppPcmBuffers;
|
||||||
CImaADPCMDecoder* decoders;
|
CImaADPCMDecoder *m_pAdpcmDecoders;
|
||||||
|
|
||||||
void Close()
|
void Close()
|
||||||
{
|
{
|
||||||
if (pFile) {
|
if (m_pFile) {
|
||||||
fclose(pFile);
|
fclose(m_pFile);
|
||||||
pFile = nil;
|
m_pFile = nil;
|
||||||
}
|
}
|
||||||
if (AdpcmBlock) delete[] AdpcmBlock;
|
delete[] m_pAdpcmBuffer;
|
||||||
if (buffers) delete[] buffers;
|
delete[] m_ppPcmBuffers;
|
||||||
if (decoders) delete[] decoders;
|
delete[] m_pAdpcmDecoders;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 GetCurrentSample() const
|
||||||
|
{
|
||||||
|
// TODO: 64 bit?
|
||||||
|
uint32 FilePos = ftell(m_pFile);
|
||||||
|
if (FilePos <= m_DataStartOffset)
|
||||||
|
return 0;
|
||||||
|
return (FilePos - m_DataStartOffset) / m_FormatHeader.BlockAlign * m_nSamplesPerBlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CWavFile(const char* path) : bIsOpen(false), DataStartOffset(0), SampleCount(0), SamplesPerBlock(0), AdpcmBlock(nil), buffers(nil), decoders(nil)
|
CWavFile(const char* path) : m_bIsOpen(false), m_DataStartOffset(0), m_nSampleCount(0), m_nSamplesPerBlock(0), m_pAdpcmBuffer(nil), m_ppPcmBuffers(nil), m_pAdpcmDecoders(nil)
|
||||||
{
|
{
|
||||||
pFile = fopen(path, "rb");
|
m_pFile = fopen(path, "rb");
|
||||||
if (!pFile) return;
|
if (!m_pFile) return;
|
||||||
|
|
||||||
#define CLOSE_ON_ERROR(op)\
|
#define CLOSE_ON_ERROR(op)\
|
||||||
if (op) { \
|
if (op) { \
|
||||||
|
@ -212,52 +222,58 @@ public:
|
||||||
|
|
||||||
tDataHeader DataHeader;
|
tDataHeader DataHeader;
|
||||||
|
|
||||||
CLOSE_ON_ERROR(fread(&DataHeader, sizeof(DataHeader), 1, pFile) == 0);
|
CLOSE_ON_ERROR(fread(&DataHeader, sizeof(DataHeader), 1, m_pFile) == 0);
|
||||||
CLOSE_ON_ERROR(DataHeader.ID != 'FFIR');
|
CLOSE_ON_ERROR(DataHeader.ID != 'FFIR');
|
||||||
|
|
||||||
|
// TODO? validate filesizes
|
||||||
|
|
||||||
int WAVE;
|
int WAVE;
|
||||||
CLOSE_ON_ERROR(fread(&WAVE, 4, 1, pFile) == 0);
|
CLOSE_ON_ERROR(fread(&WAVE, 4, 1, m_pFile) == 0);
|
||||||
CLOSE_ON_ERROR(WAVE != 'EVAW')
|
CLOSE_ON_ERROR(WAVE != 'EVAW')
|
||||||
CLOSE_ON_ERROR(fread(&DataHeader, sizeof(DataHeader), 1, pFile) == 0);
|
CLOSE_ON_ERROR(fread(&DataHeader, sizeof(DataHeader), 1, m_pFile) == 0);
|
||||||
CLOSE_ON_ERROR(DataHeader.ID != ' tmf');
|
CLOSE_ON_ERROR(DataHeader.ID != ' tmf');
|
||||||
|
|
||||||
CLOSE_ON_ERROR(fread(&FormatHeader, Min(DataHeader.Size, sizeof(tFormatHeader)), 1, pFile) == 0);
|
CLOSE_ON_ERROR(fread(&m_FormatHeader, Min(DataHeader.Size, sizeof(tFormatHeader)), 1, m_pFile) == 0);
|
||||||
CLOSE_ON_ERROR(DataHeader.Size > sizeof(tFormatHeader));
|
CLOSE_ON_ERROR(DataHeader.Size > sizeof(tFormatHeader));
|
||||||
|
|
||||||
switch (FormatHeader.AudioFormat)
|
switch (m_FormatHeader.AudioFormat)
|
||||||
{
|
{
|
||||||
case WAVEFMT_XBOX_ADPCM:
|
case WAVEFMT_XBOX_ADPCM:
|
||||||
FormatHeader.AudioFormat = WAVEFMT_IMA_ADPCM;
|
m_FormatHeader.AudioFormat = WAVEFMT_IMA_ADPCM;
|
||||||
case WAVEFMT_IMA_ADPCM:
|
case WAVEFMT_IMA_ADPCM:
|
||||||
SamplesPerBlock = (FormatHeader.BlockAlign / FormatHeader.NumChannels - 4) * 2 + 1;
|
m_nSamplesPerBlock = (m_FormatHeader.BlockAlign / m_FormatHeader.NumChannels - 4) * 2 + 1;
|
||||||
AdpcmBlock = new uint8[FormatHeader.BlockAlign];
|
m_pAdpcmBuffer = new uint8[m_FormatHeader.BlockAlign];
|
||||||
buffers = new int16*[FormatHeader.NumChannels];
|
m_ppPcmBuffers = new int16*[m_FormatHeader.NumChannels];
|
||||||
decoders = new CImaADPCMDecoder[FormatHeader.NumChannels];
|
m_pAdpcmDecoders = new CImaADPCMDecoder[m_FormatHeader.NumChannels];
|
||||||
break;
|
break;
|
||||||
case WAVEFMT_PCM:
|
case WAVEFMT_PCM:
|
||||||
SamplesPerBlock = 1;
|
m_nSamplesPerBlock = 1;
|
||||||
if (FormatHeader.BitsPerSample != 16)
|
if (m_FormatHeader.BitsPerSample != 16)
|
||||||
{
|
{
|
||||||
debug("Unsupported PCM (%d bits), only signed 16-bit is supported (%s)\n", FormatHeader.BitsPerSample, path);
|
debug("Unsupported PCM (%d bits), only signed 16-bit is supported (%s)\n", m_FormatHeader.BitsPerSample, path);
|
||||||
|
Close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
debug("Unsupported wav format 0x%x (%s)\n", FormatHeader.AudioFormat, path);
|
debug("Unsupported wav format 0x%x (%s)\n", m_FormatHeader.AudioFormat, path);
|
||||||
|
Close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
CLOSE_ON_ERROR(fread(&DataHeader, sizeof(DataHeader), 1, pFile) == 0);
|
CLOSE_ON_ERROR(fread(&DataHeader, sizeof(DataHeader), 1, m_pFile) == 0);
|
||||||
if (DataHeader.ID == 'atad')
|
if (DataHeader.ID == 'atad')
|
||||||
break;
|
break;
|
||||||
fseek(pFile, DataHeader.Size, SEEK_CUR);
|
fseek(m_pFile, DataHeader.Size, SEEK_CUR);
|
||||||
|
// TODO? validate data size
|
||||||
|
// maybe check if there no extreme custom headers that might break this
|
||||||
}
|
}
|
||||||
|
|
||||||
DataStartOffset = ftell(pFile);
|
m_DataStartOffset = ftell(m_pFile);
|
||||||
SampleCount = DataHeader.Size / FormatHeader.BlockAlign * SamplesPerBlock;
|
m_nSampleCount = DataHeader.Size / m_FormatHeader.BlockAlign * m_nSamplesPerBlock;
|
||||||
|
|
||||||
bIsOpen = true;
|
m_bIsOpen = true;
|
||||||
#undef CLOSE_ON_ERROR
|
#undef CLOSE_ON_ERROR
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -268,7 +284,7 @@ public:
|
||||||
|
|
||||||
bool IsOpened()
|
bool IsOpened()
|
||||||
{
|
{
|
||||||
return bIsOpen;
|
return m_bIsOpen;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 GetSampleSize()
|
uint32 GetSampleSize()
|
||||||
|
@ -278,29 +294,29 @@ public:
|
||||||
|
|
||||||
uint32 GetSampleCount()
|
uint32 GetSampleCount()
|
||||||
{
|
{
|
||||||
return SampleCount;
|
return m_nSampleCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 GetSampleRate()
|
uint32 GetSampleRate()
|
||||||
{
|
{
|
||||||
return FormatHeader.SampleRate;
|
return m_FormatHeader.SampleRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 GetChannels()
|
uint32 GetChannels()
|
||||||
{
|
{
|
||||||
return FormatHeader.NumChannels;
|
return m_FormatHeader.NumChannels;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Seek(uint32 milliseconds)
|
void Seek(uint32 milliseconds)
|
||||||
{
|
{
|
||||||
if (!IsOpened()) return;
|
if (!IsOpened()) return;
|
||||||
fseek(pFile, DataStartOffset + ms2samples(milliseconds) / SamplesPerBlock * FormatHeader.BlockAlign, SEEK_SET);
|
fseek(m_pFile, m_DataStartOffset + ms2samples(milliseconds) / m_nSamplesPerBlock * m_FormatHeader.BlockAlign, SEEK_SET);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 Tell()
|
uint32 Tell()
|
||||||
{
|
{
|
||||||
if (!IsOpened()) return 0;
|
if (!IsOpened()) return 0;
|
||||||
return samples2ms((ftell(pFile) - DataStartOffset) / FormatHeader.BlockAlign * SamplesPerBlock);
|
return samples2ms(GetCurrentSample());
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SAMPLES_IN_LINE (8)
|
#define SAMPLES_IN_LINE (8)
|
||||||
|
@ -309,52 +325,61 @@ public:
|
||||||
{
|
{
|
||||||
if (!IsOpened()) return 0;
|
if (!IsOpened()) return 0;
|
||||||
|
|
||||||
if (FormatHeader.AudioFormat == WAVEFMT_PCM)
|
if (m_FormatHeader.AudioFormat == WAVEFMT_PCM)
|
||||||
{
|
{
|
||||||
uint32 size = fread(buffer, 1, GetBufferSize(), pFile);
|
// just read the file and sort the samples
|
||||||
if (FormatHeader.NumChannels == 2)
|
uint32 size = fread(buffer, 1, GetBufferSize(), m_pFile);
|
||||||
|
if (m_FormatHeader.NumChannels == 2)
|
||||||
SortStereoBuffer.SortStereo(buffer, size);
|
SortStereoBuffer.SortStereo(buffer, size);
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
else if (FormatHeader.AudioFormat == WAVEFMT_IMA_ADPCM)
|
else if (m_FormatHeader.AudioFormat == WAVEFMT_IMA_ADPCM)
|
||||||
{
|
{
|
||||||
uint32 MaxSamples = GetBufferSamples() / FormatHeader.NumChannels;
|
// trim the buffer size if we're at the end of our file
|
||||||
uint32 CurSample = (ftell(pFile) - DataStartOffset) / FormatHeader.BlockAlign * SamplesPerBlock;
|
uint32 nMaxSamples = GetBufferSamples() / m_FormatHeader.NumChannels;
|
||||||
|
uint32 nSamplesLeft = m_nSampleCount - GetCurrentSample();
|
||||||
|
nMaxSamples = Min(nMaxSamples, nSamplesLeft);
|
||||||
|
|
||||||
MaxSamples = Min(MaxSamples, SampleCount - CurSample);
|
// align sample count to our block
|
||||||
MaxSamples = MaxSamples / SamplesPerBlock * SamplesPerBlock;
|
nMaxSamples = nMaxSamples / m_nSamplesPerBlock * m_nSamplesPerBlock;
|
||||||
uint32 OutBufSizePerChannel = MaxSamples * GetSampleSize();
|
|
||||||
uint32 OutBufSize = OutBufSizePerChannel * FormatHeader.NumChannels;
|
// count the size of output buffer
|
||||||
int16** buffers = new int16*[FormatHeader.NumChannels];
|
uint32 OutBufSizePerChannel = nMaxSamples * GetSampleSize();
|
||||||
CImaADPCMDecoder* decoders = new CImaADPCMDecoder[FormatHeader.NumChannels];
|
uint32 OutBufSize = OutBufSizePerChannel * m_FormatHeader.NumChannels;
|
||||||
for (uint32 i = 0; i < FormatHeader.NumChannels; i++)
|
|
||||||
buffers[i] = (int16*)((int8*)buffer + OutBufSizePerChannel * i);
|
// calculate the pointers to individual channel buffers
|
||||||
|
for (uint32 i = 0; i < m_FormatHeader.NumChannels; i++)
|
||||||
|
m_ppPcmBuffers[i] = (int16*)((int8*)buffer + OutBufSizePerChannel * i);
|
||||||
|
|
||||||
uint32 samplesRead = 0;
|
uint32 samplesRead = 0;
|
||||||
while (samplesRead < MaxSamples)
|
while (samplesRead < nMaxSamples)
|
||||||
{
|
{
|
||||||
uint8* AdpcmBuf = AdpcmBlock;
|
// read the file
|
||||||
if (fread(AdpcmBlock, 1, FormatHeader.BlockAlign, pFile) == 0)
|
uint8 *pAdpcmBuf = m_pAdpcmBuffer;
|
||||||
|
if (fread(m_pAdpcmBuffer, 1, m_FormatHeader.BlockAlign, m_pFile) == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
for (uint32 i = 0; i < FormatHeader.NumChannels; i++)
|
// get the first sample in adpcm block and initialise the decoder(s)
|
||||||
|
for (uint32 i = 0; i < m_FormatHeader.NumChannels; i++)
|
||||||
{
|
{
|
||||||
int16 Sample = *(int16*)AdpcmBuf;
|
int16 Sample = *(int16*)pAdpcmBuf;
|
||||||
AdpcmBuf += sizeof(int16);
|
pAdpcmBuf += sizeof(int16);
|
||||||
int16 Step = *(int16*)AdpcmBuf;
|
int16 Step = *(int16*)pAdpcmBuf;
|
||||||
AdpcmBuf += sizeof(int16);
|
pAdpcmBuf += sizeof(int16);
|
||||||
decoders[i].Init(Sample, Step);
|
m_pAdpcmDecoders[i].Init(Sample, Step);
|
||||||
*(buffers[i]) = Sample;
|
*(m_ppPcmBuffers[i]) = Sample;
|
||||||
buffers[i]++;
|
m_ppPcmBuffers[i]++;
|
||||||
}
|
}
|
||||||
samplesRead++;
|
samplesRead++;
|
||||||
for (uint32 s = 1; s < SamplesPerBlock; s += SAMPLES_IN_LINE)
|
|
||||||
|
// decode the rest of the block
|
||||||
|
for (uint32 s = 1; s < m_nSamplesPerBlock; s += SAMPLES_IN_LINE)
|
||||||
{
|
{
|
||||||
for (uint32 i = 0; i < FormatHeader.NumChannels; i++)
|
for (uint32 i = 0; i < m_FormatHeader.NumChannels; i++)
|
||||||
{
|
{
|
||||||
decoders[i].Decode(AdpcmBuf, buffers[i], SAMPLES_IN_LINE / 2);
|
m_pAdpcmDecoders[i].Decode(pAdpcmBuf, m_ppPcmBuffers[i], SAMPLES_IN_LINE / 2);
|
||||||
AdpcmBuf += SAMPLES_IN_LINE / 2;
|
pAdpcmBuf += SAMPLES_IN_LINE / 2;
|
||||||
buffers[i] += SAMPLES_IN_LINE;
|
m_ppPcmBuffers[i] += SAMPLES_IN_LINE;
|
||||||
}
|
}
|
||||||
samplesRead += SAMPLES_IN_LINE;
|
samplesRead += SAMPLES_IN_LINE;
|
||||||
}
|
}
|
||||||
|
@ -613,68 +638,68 @@ public:
|
||||||
|
|
||||||
class CVbFile : public IDecoder
|
class CVbFile : public IDecoder
|
||||||
{
|
{
|
||||||
FILE* pFile;
|
FILE *m_pFile;
|
||||||
size_t m_FileSize;
|
CVagDecoder *m_pVagDecoders;
|
||||||
size_t m_nNumberOfBlocks;
|
|
||||||
CVagDecoder* decoders;
|
|
||||||
|
|
||||||
uint32 m_nSampleRate;
|
size_t m_FileSize;
|
||||||
uint8 m_nChannels;
|
size_t m_nNumberOfBlocks;
|
||||||
bool m_bBlockRead;
|
|
||||||
uint16 m_LineInBlock;
|
|
||||||
size_t m_CurrentBlock;
|
|
||||||
|
|
||||||
uint8** ppTempBuffers;
|
uint32 m_nSampleRate;
|
||||||
int16** buffers;
|
uint8 m_nChannels;
|
||||||
|
bool m_bBlockRead;
|
||||||
|
uint16 m_LineInBlock;
|
||||||
|
size_t m_CurrentBlock;
|
||||||
|
|
||||||
|
uint8 **m_ppVagBuffers; // buffers that cache actual ADPCM file data
|
||||||
|
int16 **m_ppPcmBuffers;
|
||||||
|
|
||||||
void ReadBlock(int32 block = -1)
|
void ReadBlock(int32 block = -1)
|
||||||
{
|
{
|
||||||
// just read next block if -1
|
// just read next block if -1
|
||||||
if (block != -1)
|
if (block != -1)
|
||||||
fseek(pFile, block * m_nChannels * VB_BLOCK_SIZE, SEEK_SET);
|
fseek(m_pFile, block * m_nChannels * VB_BLOCK_SIZE, SEEK_SET);
|
||||||
|
|
||||||
for (int i = 0; i < m_nChannels; i++)
|
for (int i = 0; i < m_nChannels; i++)
|
||||||
fread(ppTempBuffers[i], VB_BLOCK_SIZE, 1, pFile);
|
fread(m_ppVagBuffers[i], VB_BLOCK_SIZE, 1, m_pFile);
|
||||||
m_bBlockRead = true;
|
m_bBlockRead = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CVbFile(const char* path, uint32 nSampleRate = 32000, uint8 nChannels = 2) : m_nSampleRate(nSampleRate), m_nChannels(nChannels), decoders(nil), ppTempBuffers(nil), buffers(nil),
|
CVbFile(const char* path, uint32 nSampleRate = 32000, uint8 nChannels = 2) : m_nSampleRate(nSampleRate), m_nChannels(nChannels), m_pVagDecoders(nil), m_ppVagBuffers(nil), m_ppPcmBuffers(nil),
|
||||||
m_FileSize(0), m_nNumberOfBlocks(0), m_bBlockRead(false), m_LineInBlock(0), m_CurrentBlock(0)
|
m_FileSize(0), m_nNumberOfBlocks(0), m_bBlockRead(false), m_LineInBlock(0), m_CurrentBlock(0)
|
||||||
{
|
{
|
||||||
pFile = fopen(path, "rb");
|
m_pFile = fopen(path, "rb");
|
||||||
if (!pFile) return;
|
if (!m_pFile) return;
|
||||||
|
|
||||||
|
fseek(m_pFile, 0, SEEK_END);
|
||||||
|
m_FileSize = ftell(m_pFile);
|
||||||
|
fseek(m_pFile, 0, SEEK_SET);
|
||||||
|
|
||||||
fseek(pFile, 0, SEEK_END);
|
|
||||||
m_FileSize = ftell(pFile);
|
|
||||||
fseek(pFile, 0, SEEK_SET);
|
|
||||||
m_nNumberOfBlocks = m_FileSize / (nChannels * VB_BLOCK_SIZE);
|
m_nNumberOfBlocks = m_FileSize / (nChannels * VB_BLOCK_SIZE);
|
||||||
decoders = new CVagDecoder[nChannels];
|
m_pVagDecoders = new CVagDecoder[nChannels];
|
||||||
m_CurrentBlock = 0;
|
m_ppVagBuffers = new uint8*[nChannels];
|
||||||
m_LineInBlock = 0;
|
m_ppPcmBuffers = new int16*[nChannels];
|
||||||
m_bBlockRead = false;
|
|
||||||
ppTempBuffers = new uint8*[nChannels];
|
|
||||||
buffers = new int16*[nChannels];
|
|
||||||
for (uint8 i = 0; i < nChannels; i++)
|
for (uint8 i = 0; i < nChannels; i++)
|
||||||
ppTempBuffers[i] = new uint8[VB_BLOCK_SIZE];
|
m_ppVagBuffers[i] = new uint8[VB_BLOCK_SIZE];
|
||||||
}
|
}
|
||||||
|
|
||||||
~CVbFile()
|
~CVbFile()
|
||||||
{
|
{
|
||||||
if (pFile)
|
if (m_pFile)
|
||||||
{
|
{
|
||||||
fclose(pFile);
|
fclose(m_pFile);
|
||||||
delete[] decoders;
|
|
||||||
|
delete[] m_pVagDecoders;
|
||||||
for (int i = 0; i < m_nChannels; i++)
|
for (int i = 0; i < m_nChannels; i++)
|
||||||
delete[] ppTempBuffers[i];
|
delete[] m_ppVagBuffers[i];
|
||||||
delete[] ppTempBuffers;
|
delete[] m_ppVagBuffers;
|
||||||
delete[] buffers;
|
delete[] m_ppPcmBuffers;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsOpened()
|
bool IsOpened()
|
||||||
{
|
{
|
||||||
return pFile != nil;
|
return m_pFile != nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 GetSampleSize()
|
uint32 GetSampleSize()
|
||||||
|
@ -702,6 +727,8 @@ public:
|
||||||
{
|
{
|
||||||
if (!IsOpened()) return;
|
if (!IsOpened()) return;
|
||||||
uint32 samples = ms2samples(milliseconds);
|
uint32 samples = ms2samples(milliseconds);
|
||||||
|
|
||||||
|
// find the block of our sample
|
||||||
uint32 block = samples / NUM_VAG_SAMPLES_IN_BLOCK;
|
uint32 block = samples / NUM_VAG_SAMPLES_IN_BLOCK;
|
||||||
if (block > m_nNumberOfBlocks)
|
if (block > m_nNumberOfBlocks)
|
||||||
{
|
{
|
||||||
|
@ -711,6 +738,7 @@ public:
|
||||||
if (block != m_CurrentBlock)
|
if (block != m_CurrentBlock)
|
||||||
m_bBlockRead = false;
|
m_bBlockRead = false;
|
||||||
|
|
||||||
|
// find a line of our sample within our block
|
||||||
uint32 remainingSamples = samples - block * NUM_VAG_SAMPLES_IN_BLOCK;
|
uint32 remainingSamples = samples - block * NUM_VAG_SAMPLES_IN_BLOCK;
|
||||||
uint32 newLine = remainingSamples / VAG_SAMPLES_IN_LINE / VAG_LINE_SIZE;
|
uint32 newLine = remainingSamples / VAG_SAMPLES_IN_LINE / VAG_LINE_SIZE;
|
||||||
|
|
||||||
|
@ -719,7 +747,7 @@ public:
|
||||||
m_CurrentBlock = block;
|
m_CurrentBlock = block;
|
||||||
m_LineInBlock = newLine;
|
m_LineInBlock = newLine;
|
||||||
for (uint32 i = 0; i < GetChannels(); i++)
|
for (uint32 i = 0; i < GetChannels(); i++)
|
||||||
decoders[i].ResetState();
|
m_pVagDecoders[i].ResetState();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -735,35 +763,38 @@ public:
|
||||||
{
|
{
|
||||||
if (!IsOpened()) return 0;
|
if (!IsOpened()) return 0;
|
||||||
|
|
||||||
|
if (m_CurrentBlock >= m_nNumberOfBlocks) return 0;
|
||||||
|
|
||||||
|
// cache current ADPCM block
|
||||||
if (!m_bBlockRead)
|
if (!m_bBlockRead)
|
||||||
ReadBlock(m_CurrentBlock);
|
ReadBlock(m_CurrentBlock);
|
||||||
|
|
||||||
if (m_CurrentBlock == m_nNumberOfBlocks) return 0;
|
// trim the buffer size if we're at the end of our file
|
||||||
int size = 0;
|
|
||||||
|
|
||||||
int numberOfRequiredLines = GetBufferSamples() / m_nChannels / VAG_SAMPLES_IN_LINE;
|
int numberOfRequiredLines = GetBufferSamples() / m_nChannels / VAG_SAMPLES_IN_LINE;
|
||||||
int numberOfRemainingLines = (m_nNumberOfBlocks - m_CurrentBlock) * NUM_VAG_LINES_IN_BLOCK - m_LineInBlock;
|
int numberOfRemainingLines = (m_nNumberOfBlocks - m_CurrentBlock) * NUM_VAG_LINES_IN_BLOCK - m_LineInBlock;
|
||||||
int bufSizePerChannel = Min(numberOfRequiredLines, numberOfRemainingLines) * VAG_SAMPLES_IN_LINE * GetSampleSize();
|
int bufSizePerChannel = Min(numberOfRequiredLines, numberOfRemainingLines) * VAG_SAMPLES_IN_LINE * GetSampleSize();
|
||||||
|
|
||||||
if (numberOfRequiredLines > numberOfRemainingLines)
|
// calculate the pointers to individual channel buffers
|
||||||
numberOfRemainingLines = numberOfRemainingLines;
|
|
||||||
|
|
||||||
for (uint32 i = 0; i < m_nChannels; i++)
|
for (uint32 i = 0; i < m_nChannels; i++)
|
||||||
buffers[i] = (int16*)((int8*)buffer + bufSizePerChannel * i);
|
m_ppPcmBuffers[i] = (int16*)((int8*)buffer + bufSizePerChannel * i);
|
||||||
|
|
||||||
|
int size = 0;
|
||||||
while (size < bufSizePerChannel)
|
while (size < bufSizePerChannel)
|
||||||
{
|
{
|
||||||
|
// decode the VAG lines
|
||||||
for (uint32 i = 0; i < m_nChannels; i++)
|
for (uint32 i = 0; i < m_nChannels; i++)
|
||||||
{
|
{
|
||||||
decoders[i].Decode(ppTempBuffers[i] + m_LineInBlock * VAG_LINE_SIZE, buffers[i], VAG_LINE_SIZE);
|
m_pVagDecoders[i].Decode(m_ppVagBuffers[i] + m_LineInBlock * VAG_LINE_SIZE, m_ppPcmBuffers[i], VAG_LINE_SIZE);
|
||||||
buffers[i] += VAG_SAMPLES_IN_LINE;
|
m_ppPcmBuffers[i] += VAG_SAMPLES_IN_LINE;
|
||||||
}
|
}
|
||||||
size += VAG_SAMPLES_IN_LINE * GetSampleSize();
|
size += VAG_SAMPLES_IN_LINE * GetSampleSize();
|
||||||
m_LineInBlock++;
|
m_LineInBlock++;
|
||||||
|
|
||||||
|
// block is over, read the next block
|
||||||
if (m_LineInBlock >= NUM_VAG_LINES_IN_BLOCK)
|
if (m_LineInBlock >= NUM_VAG_LINES_IN_BLOCK)
|
||||||
{
|
{
|
||||||
m_CurrentBlock++;
|
m_CurrentBlock++;
|
||||||
if (m_CurrentBlock >= m_nNumberOfBlocks)
|
if (m_CurrentBlock >= m_nNumberOfBlocks) // end of file
|
||||||
break;
|
break;
|
||||||
m_LineInBlock = 0;
|
m_LineInBlock = 0;
|
||||||
ReadBlock();
|
ReadBlock();
|
||||||
|
|
Loading…
Reference in a new issue