From d71e048691940d0c11d9643ff17035e6312c04a9 Mon Sep 17 00:00:00 2001 From: Silent Date: Wed, 11 Jun 2014 00:40:08 +0200 Subject: [PATCH] Fixes for FLAC support --- SilentPatch/AudioHardware.cpp | 81 ++++++++++++++++++++++++++--------- SilentPatch/AudioHardware.h | 19 +++----- 2 files changed, 65 insertions(+), 35 deletions(-) diff --git a/SilentPatch/AudioHardware.cpp b/SilentPatch/AudioHardware.cpp index 997e389..b29c99e 100644 --- a/SilentPatch/AudioHardware.cpp +++ b/SilentPatch/AudioHardware.cpp @@ -8,21 +8,27 @@ //WRAPPER unsigned int CAEDataStream::FillBuffer(void* pBuf, unsigned long nLen) { EAXJMP(0x4DC1C0); } WRAPPER bool CAEDataStream::Initialise() { EAXJMP(0x4DC2B0); } +//static bool bEOFFlag = false; + FLAC__StreamDecoderReadStatus CAEFLACDecoder::read_cb(const FLAC__StreamDecoder* decoder, FLAC__byte buffer[], size_t* bytes, void* client_data) { + UNREFERENCED_PARAMETER(decoder); CAEFLACDecoder* pClientData = static_cast(client_data); ReadFile(pClientData->GetStream()->GetFile(), buffer, *bytes, reinterpret_cast(bytes), nullptr); //*bytes = pClientData->GetStream()->FillBuffer(buffer, *bytes); //*bytes = pClientData->GetStream()->FillBuffer(buffer, *bytes); + //bEOFFlag = GetLastError() == ERROR_HANDLE_EOF; - FLAC__StreamDecoderReadStatus bResult = *bytes ? FLAC__STREAM_DECODER_READ_STATUS_CONTINUE : FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM; + auto result = *bytes ? FLAC__STREAM_DECODER_READ_STATUS_CONTINUE : FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM; - return bResult; + return result; } static FLAC__int32* pMalloc = nullptr; static unsigned int nBlockSize = 0; +static unsigned int nSamplesLeftToProcess = 0; + FLAC__StreamDecoderWriteStatus CAEFLACDecoder::write_cb(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 *const buffer[], void *client_data) { CAEFLACDecoder* pClientData = static_cast(client_data); @@ -32,17 +38,23 @@ FLAC__StreamDecoderWriteStatus CAEFLACDecoder::write_cb(const FLAC__StreamDecode frame->header.number.sample_number : frame->header.number.frame_number * frame->header.blocksize; - if ( frame->header.blocksize > nBlockSize ) + // Mono/stereo? + unsigned int nNumChannelsToAlloc = pClientData->pStreamInfo->data.stream_info.channels > 1 ? 2 : 1; + static unsigned int nLastMallocSize = 0; + + if ( frame->header.blocksize * sizeof(FLAC__int32) * nNumChannelsToAlloc > nLastMallocSize ) { // Realloc needed operator delete(pMalloc); - pMalloc = static_cast(operator new(frame->header.blocksize * sizeof(FLAC__int32) * 2)); // TODO: More channels? + nLastMallocSize = frame->header.blocksize * sizeof(FLAC__int32) * nNumChannelsToAlloc; + pMalloc = static_cast(operator new(nLastMallocSize)); // TODO: More channels? } nBlockSize = frame->header.blocksize; memcpy(pMalloc, buffer[0], nBlockSize * sizeof(FLAC__int32)); - memcpy(pMalloc+nBlockSize, buffer[1], nBlockSize * sizeof(FLAC__int32)); + if ( nNumChannelsToAlloc > 1 ) + memcpy(pMalloc+nBlockSize, buffer[1], nBlockSize * sizeof(FLAC__int32)); return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; } @@ -91,10 +103,11 @@ FLAC__StreamDecoderLengthStatus CAEFLACDecoder::length_cb(const FLAC__StreamDeco return bResult ? FLAC__STREAM_DECODER_LENGTH_STATUS_OK: FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR; } -FLAC__bool CAEFLACDecoder::eof_cb(const FLAC__StreamDecoder *decoder, void *client_data) +FLAC__bool CAEFLACDecoder::eof_cb(const FLAC__StreamDecoder* decoder, void* client_data) { - - // TODO: DO + // Not implemented + UNREFERENCED_PARAMETER(decoder); + UNREFERENCED_PARAMETER(client_data); return false; } @@ -117,38 +130,64 @@ bool CAEFLACDecoder::Initialise() return result; } -#include - unsigned int CAEFLACDecoder::FillBuffer(void* pBuf, unsigned long nLen) { - signed int nSigLen = nLen / 4; + //unsigned int nSigLen = nLen / 4; unsigned int nBytesDecoded = 0; FLAC__int16* pBuffer = static_cast(pBuf); - while ( nSigLen > 0 ) + while ( nBytesDecoded < nLen ) { - FLAC__stream_decoder_process_single(pFLACDecoder); + static FLAC__int32* pCurrentPtr[2]; - FLAC__int32* pCurrentPtr[2]; + unsigned int nToWrite; + // No samples left from a previous fetch? + if ( !nSamplesLeftToProcess ) + { + FLAC__stream_decoder_process_single(pFLACDecoder); - pCurrentPtr[0] = pMalloc; - pCurrentPtr[1] = pMalloc+nBlockSize; + pCurrentPtr[0] = pMalloc; + pCurrentPtr[1] = pMalloc+nBlockSize; + + if ( (nLen - nBytesDecoded) / 4 >= nBlockSize ) + nToWrite = nBlockSize; + else + nToWrite = (nLen - nBytesDecoded) / 4; + + nSamplesLeftToProcess = nBlockSize; + } + else + nToWrite = nSamplesLeftToProcess; // Write channels - unsigned int nToWrite = min(nLen / 4, nBlockSize); - for ( unsigned int i = 0; i < nToWrite; i++ ) + // = min((nLen - nBytesDecoded) / 4, nBlockSize); + + for ( unsigned int i = 0; i < nToWrite; i++, nSamplesLeftToProcess-- ) { pBuffer[0] = pCurrentPtr[0][i]; - pBuffer[1] = pCurrentPtr[1][i]; + pBuffer[1] = pCurrentPtr[pStreamInfo->data.stream_info.channels > 1][i]; pBuffer += 2; } - nSigLen -= nToWrite; + //nSigLen -= nToWrite; nBytesDecoded += nToWrite*4; if ( FLAC__stream_decoder_get_state(pFLACDecoder) == FLAC__STREAM_DECODER_END_OF_STREAM ) break; } - return nSigLen > 0 ? nLen - nBytesDecoded : nLen; + return nBytesDecoded;//nSigLen > 0 ? nLen - nBytesDecoded : nLen; +} + +CAEFLACDecoder::~CAEFLACDecoder() +{ + nSamplesLeftToProcess = 0; + if ( pFLACDecoder ) + { + FLAC__stream_decoder_finish(pFLACDecoder); + FLAC__stream_decoder_delete(pFLACDecoder); + + FLAC__metadata_object_delete(pStreamInfo); + pFLACDecoder = nullptr; + } } \ No newline at end of file diff --git a/SilentPatch/AudioHardware.h b/SilentPatch/AudioHardware.h index 1ea9ea4..a58f8b8 100644 --- a/SilentPatch/AudioHardware.h +++ b/SilentPatch/AudioHardware.h @@ -144,18 +144,7 @@ public: : CAEStreamingDecoder(stream), pFLACDecoder(nullptr) {} - virtual ~CAEFLACDecoder() - { - if ( pFLACDecoder ) - { - FLAC__stream_decoder_finish(pFLACDecoder); - FLAC__stream_decoder_delete(pFLACDecoder); - - FLAC__metadata_object_delete(pStreamInfo); - pFLACDecoder = nullptr; - } - } - + virtual ~CAEFLACDecoder(); virtual bool Initialise() override; @@ -163,12 +152,14 @@ public: virtual unsigned int GetStreamLengthMs() override { - return pStreamInfo->data.stream_info.total_samples * 1000 / pStreamInfo->data.stream_info.sample_rate; + unsigned int nTime = pStreamInfo->data.stream_info.total_samples * 1000 / pStreamInfo->data.stream_info.sample_rate; + return nTime; } virtual unsigned int GetStreamPlayTimeMs() override { - return nCurrentSample * 1000 / pStreamInfo->data.stream_info.sample_rate; + unsigned int nTime = nCurrentSample * 1000 / pStreamInfo->data.stream_info.sample_rate; + return nTime; } virtual void SetCursor(unsigned int nTime) override