From d4569dbc844cbe2d5f2ccee41ec3aba254f6d40a Mon Sep 17 00:00:00 2001 From: Silent Date: Fri, 13 Jun 2014 02:24:50 +0200 Subject: [PATCH] FLAC decoder optimisations, resulting in bigger file size but fixed stutter --- SilentPatch/AudioHardware.cpp | 385 +++++++++++++++++++++++++++++++--- 1 file changed, 361 insertions(+), 24 deletions(-) diff --git a/SilentPatch/AudioHardware.cpp b/SilentPatch/AudioHardware.cpp index c16cd6a..9e196d4 100644 --- a/SilentPatch/AudioHardware.cpp +++ b/SilentPatch/AudioHardware.cpp @@ -18,8 +18,6 @@ FLAC__StreamDecoderReadStatus CAEFLACDecoder::read_cb(const FLAC__StreamDecoder* 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; auto result = *bytes ? FLAC__STREAM_DECODER_READ_STATUS_CONTINUE : FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM; @@ -28,11 +26,12 @@ FLAC__StreamDecoderReadStatus CAEFLACDecoder::read_cb(const FLAC__StreamDecoder* 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) { + UNREFERENCED_PARAMETER(decoder); + CAEFLACDecoder* pClientData = static_cast(client_data); // Obtain current sample @@ -64,6 +63,8 @@ FLAC__StreamDecoderWriteStatus CAEFLACDecoder::write_cb(const FLAC__StreamDecode void CAEFLACDecoder::meta_cb(const FLAC__StreamDecoder* decoder, const FLAC__StreamMetadata *metadata, void *client_data) { + UNREFERENCED_PARAMETER(decoder); + if ( metadata->type == FLAC__METADATA_TYPE_STREAMINFO ) { // Cache the header @@ -74,6 +75,8 @@ void CAEFLACDecoder::meta_cb(const FLAC__StreamDecoder* decoder, const FLAC__Str FLAC__StreamDecoderSeekStatus CAEFLACDecoder::seek_cb(const FLAC__StreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data) { + UNREFERENCED_PARAMETER(decoder); + CAEFLACDecoder* pClientData = static_cast(client_data); LARGE_INTEGER li; li.QuadPart = absolute_byte_offset; @@ -85,6 +88,8 @@ FLAC__StreamDecoderSeekStatus CAEFLACDecoder::seek_cb(const FLAC__StreamDecoder FLAC__StreamDecoderTellStatus CAEFLACDecoder::tell_cb(const FLAC__StreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data) { + UNREFERENCED_PARAMETER(decoder); + CAEFLACDecoder* pClientData = static_cast(client_data); LARGE_INTEGER li; li.QuadPart = 0; @@ -97,6 +102,8 @@ FLAC__StreamDecoderTellStatus CAEFLACDecoder::tell_cb(const FLAC__StreamDecoder FLAC__StreamDecoderLengthStatus CAEFLACDecoder::length_cb(const FLAC__StreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data) { + UNREFERENCED_PARAMETER(decoder); + CAEFLACDecoder* pClientData = static_cast(client_data); LARGE_INTEGER li; @@ -122,7 +129,6 @@ void CAEFLACDecoder::error_cb(const FLAC__StreamDecoder* decoder, FLAC__StreamDe UNREFERENCED_PARAMETER(client_data); } - bool CAEFLACDecoder::Initialise() { pFLACDecoder = FLAC__stream_decoder_new(); @@ -135,11 +141,13 @@ bool CAEFLACDecoder::Initialise() return false; } -unsigned int CAEFLACDecoder::FillBuffer(void* pBuf, unsigned long nLen) +/*unsigned int CAEFLACDecoder::FillBuffer(void* pBuf, unsigned long nLen) { //unsigned int nSigLen = nLen / 4; unsigned int nBytesDecoded = 0; + unsigned int nSampleRate = pStreamInfo->data.stream_info.bits_per_sample; FLAC__int16* pBuffer = static_cast(pBuf); + bool bStereo = pStreamInfo->data.stream_info.channels > 1; while ( nBytesDecoded < nLen ) { @@ -165,37 +173,75 @@ unsigned int CAEFLACDecoder::FillBuffer(void* pBuf, unsigned long nLen) nToWrite = nSamplesLeftToProcess; // Write channels - if ( pStreamInfo->data.stream_info.bits_per_sample == 8 ) + if ( bStereo ) { - // 8-bit - for ( unsigned int i = 0; i < nToWrite; i++, nSamplesLeftToProcess-- ) + // Stereo + if ( nSampleRate == 8 ) { - pBuffer[0] = pCurrentPtr[0][i] << 8; - pBuffer[1] = pCurrentPtr[pStreamInfo->data.stream_info.channels > 1][i] << 8; + // 8-bit + for ( unsigned int i = 0; i < nToWrite; i++, nSamplesLeftToProcess-- ) + { + pBuffer[0] = *pCurrentPtr[0]++ << 8; + pBuffer[1] = *pCurrentPtr[1]++ << 8; - pBuffer += 2; + pBuffer += 2; + } } - } - else if ( pStreamInfo->data.stream_info.bits_per_sample == 24 ) - { - // 24-bit - for ( unsigned int i = 0; i < nToWrite; i++, nSamplesLeftToProcess-- ) + else if ( nSampleRate == 24 ) { - pBuffer[0] = pCurrentPtr[0][i] >> 8; - pBuffer[1] = pCurrentPtr[pStreamInfo->data.stream_info.channels > 1][i] >> 8; + // 24-bit + for ( unsigned int i = 0; i < nToWrite; i++, nSamplesLeftToProcess-- ) + { + pBuffer[0] = *pCurrentPtr[0]++ >> 8; + pBuffer[1] = *pCurrentPtr[1]++ >> 8; - pBuffer += 2; + pBuffer += 2; + } + } + else + { + // 16-bit + for ( unsigned int i = 0; i < nToWrite; i++, nSamplesLeftToProcess-- ) + { + pBuffer[0] = *pCurrentPtr[0]++; + pBuffer[1] = *pCurrentPtr[1]++; + + pBuffer += 2; + } } } else { - // 16-bit - for ( unsigned int i = 0; i < nToWrite; i++, nSamplesLeftToProcess-- ) + // Mono + if ( nSampleRate == 8 ) { - pBuffer[0] = pCurrentPtr[0][i]; - pBuffer[1] = pCurrentPtr[pStreamInfo->data.stream_info.channels > 1][i]; + // 8-bit + for ( unsigned int i = 0; i < nToWrite; i++, nSamplesLeftToProcess-- ) + { + pBuffer[0] = pBuffer[1] = *pCurrentPtr[0]++ << 8; - pBuffer += 2; + pBuffer += 2; + } + } + else if ( nSampleRate == 24 ) + { + // 24-bit + for ( unsigned int i = 0; i < nToWrite; i++, nSamplesLeftToProcess-- ) + { + pBuffer[0] = pBuffer[1] = *pCurrentPtr[0]++ >> 8; + + pBuffer += 2; + } + } + else + { + // 16-bit + for ( unsigned int i = 0; i < nToWrite; i++, nSamplesLeftToProcess-- ) + { + pBuffer[0] = pBuffer[1] = *pCurrentPtr[0]++; + + pBuffer += 2; + } } } @@ -205,7 +251,298 @@ unsigned int CAEFLACDecoder::FillBuffer(void* pBuf, unsigned long nLen) if ( FLAC__stream_decoder_get_state(pFLACDecoder) == FLAC__STREAM_DECODER_END_OF_STREAM ) break; } + return nBytesDecoded;//nSigLen > 0 ? nLen - nBytesDecoded : nLen; +}*/ + +// Separated functions for maximum decoding performance +static FLAC__int32* pCurrentPtr[2]; + +static unsigned int DecodeMono8bit(FLAC__StreamDecoder* pDecoder, void* pBuf, unsigned long nLen) +{ + unsigned int nBytesDecoded = 0; + FLAC__int16* pBuffer = static_cast(pBuf); + + while ( nBytesDecoded < nLen ) + { + unsigned int nToWrite; + // No samples left from a previous fetch? + if ( !nSamplesLeftToProcess ) + { + FLAC__stream_decoder_process_single(pDecoder); + + 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 + for ( unsigned int i = 0; i < nToWrite; i++, nSamplesLeftToProcess-- ) + { + pBuffer[0] = pBuffer[1] = *pCurrentPtr[0]++ << 8; + + pBuffer += 2; + } + + nBytesDecoded += nToWrite*4; + + if ( FLAC__stream_decoder_get_state(pDecoder) == FLAC__STREAM_DECODER_END_OF_STREAM ) + break; + } + + return nBytesDecoded; +} + +static unsigned int DecodeMono16bit(FLAC__StreamDecoder* pDecoder, void* pBuf, unsigned long nLen) +{ + unsigned int nBytesDecoded = 0; + FLAC__int16* pBuffer = static_cast(pBuf); + + while ( nBytesDecoded < nLen ) + { + unsigned int nToWrite; + // No samples left from a previous fetch? + if ( !nSamplesLeftToProcess ) + { + FLAC__stream_decoder_process_single(pDecoder); + + 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 + for ( unsigned int i = 0; i < nToWrite; i++, nSamplesLeftToProcess-- ) + { + pBuffer[0] = pBuffer[1] = *pCurrentPtr[0]++; + + pBuffer += 2; + } + + nBytesDecoded += nToWrite*4; + + if ( FLAC__stream_decoder_get_state(pDecoder) == FLAC__STREAM_DECODER_END_OF_STREAM ) + break; + } + + return nBytesDecoded; +} + +static unsigned int DecodeMono24bit(FLAC__StreamDecoder* pDecoder, void* pBuf, unsigned long nLen) +{ + unsigned int nBytesDecoded = 0; + FLAC__int16* pBuffer = static_cast(pBuf); + + while ( nBytesDecoded < nLen ) + { + unsigned int nToWrite; + // No samples left from a previous fetch? + if ( !nSamplesLeftToProcess ) + { + FLAC__stream_decoder_process_single(pDecoder); + + 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 + for ( unsigned int i = 0; i < nToWrite; i++, nSamplesLeftToProcess-- ) + { + pBuffer[0] = pBuffer[1] = *pCurrentPtr[0]++ >> 8; + + pBuffer += 2; + } + + nBytesDecoded += nToWrite*4; + + if ( FLAC__stream_decoder_get_state(pDecoder) == FLAC__STREAM_DECODER_END_OF_STREAM ) + break; + } + + return nBytesDecoded; +} + +static unsigned int DecodeStereo8bit(FLAC__StreamDecoder* pDecoder, void* pBuf, unsigned long nLen) +{ + unsigned int nBytesDecoded = 0; + FLAC__int16* pBuffer = static_cast(pBuf); + + while ( nBytesDecoded < nLen ) + { + unsigned int nToWrite; + // No samples left from a previous fetch? + if ( !nSamplesLeftToProcess ) + { + FLAC__stream_decoder_process_single(pDecoder); + + 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 + for ( unsigned int i = 0; i < nToWrite; i++, nSamplesLeftToProcess-- ) + { + pBuffer[0] = *pCurrentPtr[0]++ << 8; + pBuffer[1] = *pCurrentPtr[1]++ << 8; + + pBuffer += 2; + } + + nBytesDecoded += nToWrite*4; + + if ( FLAC__stream_decoder_get_state(pDecoder) == FLAC__STREAM_DECODER_END_OF_STREAM ) + break; + } + + return nBytesDecoded; +} + +static unsigned int DecodeStereo16bit(FLAC__StreamDecoder* pDecoder, void* pBuf, unsigned long nLen) +{ + unsigned int nBytesDecoded = 0; + FLAC__int16* pBuffer = static_cast(pBuf); + + while ( nBytesDecoded < nLen ) + { + unsigned int nToWrite; + // No samples left from a previous fetch? + if ( !nSamplesLeftToProcess ) + { + FLAC__stream_decoder_process_single(pDecoder); + + 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 + for ( unsigned int i = 0; i < nToWrite; i++, nSamplesLeftToProcess-- ) + { + //*pBuffer++ = *pCurrentPtr[0]++ + (*pCurrentPtr[1]++ << 16); + pBuffer[0] = *pCurrentPtr[0]++; + pBuffer[1] = *pCurrentPtr[1]++; + + pBuffer += 2; + } + + nBytesDecoded += nToWrite*4; + + if ( FLAC__stream_decoder_get_state(pDecoder) == FLAC__STREAM_DECODER_END_OF_STREAM ) + break; + } + + return nBytesDecoded; +} + +static unsigned int DecodeStereo24bit(FLAC__StreamDecoder* pDecoder, void* pBuf, unsigned long nLen) +{ + unsigned int nBytesDecoded = 0; + FLAC__int16* pBuffer = static_cast(pBuf); + + while ( nBytesDecoded < nLen ) + { + unsigned int nToWrite; + // No samples left from a previous fetch? + if ( !nSamplesLeftToProcess ) + { + FLAC__stream_decoder_process_single(pDecoder); + + 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 + for ( unsigned int i = 0; i < nToWrite; i++, nSamplesLeftToProcess-- ) + { + pBuffer[0] = *pCurrentPtr[0]++ >> 8; + pBuffer[1] = *pCurrentPtr[1]++ >> 8; + + pBuffer += 2; + } + + nBytesDecoded += nToWrite*4; + + if ( FLAC__stream_decoder_get_state(pDecoder) == FLAC__STREAM_DECODER_END_OF_STREAM ) + break; + } + + return nBytesDecoded; +} + +unsigned int CAEFLACDecoder::FillBuffer(void* pBuf, unsigned long nLen) +{ + unsigned int nSampleRate = pStreamInfo->data.stream_info.bits_per_sample; + bool bStereo = pStreamInfo->data.stream_info.channels > 1; + + if ( bStereo ) + { + if ( nSampleRate == 8 ) + return DecodeStereo8bit(pFLACDecoder, pBuf, nLen); + + if ( nSampleRate == 24 ) + return DecodeStereo24bit(pFLACDecoder, pBuf, nLen); + + return DecodeStereo16bit(pFLACDecoder, pBuf, nLen); + } + + if ( nSampleRate == 8 ) + return DecodeMono8bit(pFLACDecoder, pBuf, nLen); + + if ( nSampleRate == 24 ) + return DecodeMono24bit(pFLACDecoder, pBuf, nLen); + + return DecodeMono16bit(pFLACDecoder, pBuf, nLen); } CAEFLACDecoder::~CAEFLACDecoder()