diff --git a/examples/resources/audio/tanatana.flac b/examples/resources/audio/tanatana.flac new file mode 100644 index 000000000..dfe735cd6 Binary files /dev/null and b/examples/resources/audio/tanatana.flac differ diff --git a/src/audio.c b/src/audio.c index 04ff90da4..3a4ca3dfa 100644 --- a/src/audio.c +++ b/src/audio.c @@ -593,6 +593,7 @@ Music LoadMusicStream(const char *fileName) music->ctxType = MUSIC_AUDIO_OGG; music->loop = true; // We loop by default + TraceLog(DEBUG, "[%s] FLAC total samples: %i", fileName, music->totalSamples); TraceLog(DEBUG, "[%s] OGG sample rate: %i", fileName, info.sample_rate); TraceLog(DEBUG, "[%s] OGG channels: %i", fileName, info.channels); TraceLog(DEBUG, "[%s] OGG memory required: %i", fileName, info.temp_memory_required); @@ -606,11 +607,12 @@ Music LoadMusicStream(const char *fileName) else { music->stream = InitAudioStream(music->ctxFlac->sampleRate, music->ctxFlac->bitsPerSample, music->ctxFlac->channels); - music->totalSamples = (unsigned int)music->ctxFlac->totalSampleCount; + music->totalSamples = (unsigned int)music->ctxFlac->totalSampleCount/music->ctxFlac->channels; music->samplesLeft = music->totalSamples; music->ctxType = MUSIC_AUDIO_FLAC; music->loop = true; // We loop by default + TraceLog(DEBUG, "[%s] FLAC total samples: %i", fileName, music->totalSamples); TraceLog(DEBUG, "[%s] FLAC sample rate: %i", fileName, music->ctxFlac->sampleRate); TraceLog(DEBUG, "[%s] FLAC bits per sample: %i", fileName, music->ctxFlac->bitsPerSample); TraceLog(DEBUG, "[%s] FLAC channels: %i", fileName, music->ctxFlac->channels); @@ -745,9 +747,7 @@ void UpdateMusicStream(Music music) case MUSIC_AUDIO_FLAC: { // NOTE: Returns the number of samples to process - unsigned int numSamplesFlac = (unsigned int)drflac_read_s32(music->ctxFlac, numSamples/2, (int *)pcm); - - // TODO: Samples should be provided as 16 bit instead of 32 bit! + unsigned int numSamplesFlac = (unsigned int)drflac_read_s16(music->ctxFlac, numSamples*music->stream.channels, (short *)pcm); } break; case MUSIC_MODULE_XM: jar_xm_generate_samples_16bit(music->ctxXm, pcm, numSamples); break; @@ -1145,21 +1145,14 @@ static Wave LoadFLAC(const char *fileName) // Decode an entire FLAC file in one go uint64_t totalSampleCount; - wave.data = drflac_open_and_decode_file_s32(fileName, &wave.channels, &wave.sampleRate, &totalSampleCount); + wave.data = drflac_open_and_decode_file_s16(fileName, &wave.channels, &wave.sampleRate, &totalSampleCount); - wave.sampleCount = (int)totalSampleCount; - wave.sampleSize = 32; // 32 bit per sample (float) - - // NOTE: By default, dr_flac returns 32bit float samples, needs to be converted to 16bit - WaveFormat(&wave, wave.sampleRate, 16, wave.channels); + wave.sampleCount = (int)totalSampleCount/wave.channels; + wave.sampleSize = 16; // NOTE: Only support up to 2 channels (mono, stereo) - if (wave.channels > 2) - { - WaveFormat(&wave, wave.sampleRate, wave.sampleSize, 2); - TraceLog(WARNING, "[%s] FLAC channels number (%i) not supported, converted to 2 channels", fileName, wave.channels); - } - + if (wave.channels > 2) TraceLog(WARNING, "[%s] FLAC channels number (%i) not supported", fileName, wave.channels); + if (wave.data == NULL) TraceLog(WARNING, "[%s] FLAC data could not be loaded", fileName); else TraceLog(INFO, "[%s] FLAC file loaded successfully (%i Hz, %i bit, %s)", fileName, wave.sampleRate, wave.sampleSize, (wave.channels == 1) ? "Mono" : "Stereo"); diff --git a/src/external/dr_flac.h b/src/external/dr_flac.h index d7b66f206..d2bebea5e 100644 --- a/src/external/dr_flac.h +++ b/src/external/dr_flac.h @@ -1,5 +1,5 @@ // FLAC audio decoder. Public domain. See "unlicense" statement at the end of this file. -// dr_flac - v0.4 - 2016-09-29 +// dr_flac - v0.4c - 2016-12-26 // // David Reid - mackron@gmail.com @@ -105,18 +105,32 @@ #include #include -#ifndef DR_BOOL_DEFINED -#define DR_BOOL_DEFINED -#ifdef _WIN32 -typedef char drBool8; -typedef int drBool32; +#ifndef DR_SIZED_TYPES_DEFINED +#define DR_SIZED_TYPES_DEFINED +#if defined(_MSC_VER) && _MSC_VER < 1600 +typedef signed char dr_int8; +typedef unsigned char dr_uint8; +typedef signed short dr_int16; +typedef unsigned short dr_uint16; +typedef signed int dr_int32; +typedef unsigned int dr_uint32; +typedef signed __int64 dr_int64; +typedef unsigned __int64 dr_uint64; #else #include -typedef int8_t drBool8; -typedef int32_t drBool32; +typedef int8_t dr_int8; +typedef uint8_t dr_uint8; +typedef int16_t dr_int16; +typedef uint16_t dr_uint16; +typedef int32_t dr_int32; +typedef uint32_t dr_uint32; +typedef int64_t dr_int64; +typedef uint64_t dr_uint64; #endif -#define DR_TRUE 1 -#define DR_FALSE 0 +typedef dr_int8 dr_bool8; +typedef dr_int32 dr_bool32; +#define DR_TRUE 1 +#define DR_FALSE 0 #endif // As data is read from the client it is placed into an internal buffer for fast access. This controls the @@ -262,7 +276,7 @@ typedef struct { char catalog[128]; uint64_t leadInSampleCount; - drBool32 isCD; + dr_bool32 isCD; uint8_t trackCount; const uint8_t* pTrackData; } cuesheet; @@ -305,7 +319,7 @@ typedef size_t (* drflac_read_proc)(void* pUserData, void* pBufferOut, size_t by // // The offset will never be negative. Whether or not it is relative to the beginning or current position is determined // by the "origin" parameter which will be either drflac_seek_origin_start or drflac_seek_origin_current. -typedef drBool32 (* drflac_seek_proc)(void* pUserData, int offset, drflac_seek_origin origin); +typedef dr_bool32 (* drflac_seek_proc)(void* pUserData, int offset, drflac_seek_origin origin); // Callback for when a metadata block is read. // @@ -546,6 +560,10 @@ void drflac_close(drflac* pFlac); // seeked. uint64_t drflac_read_s32(drflac* pFlac, uint64_t samplesToRead, int32_t* pBufferOut); +// Same as drflac_read_s32(), except outputs samples as 16-bit integer PCM rather than 32-bit. Note +// that this is lossey. +uint64_t drflac_read_s16(drflac* pFlac, uint64_t samplesToRead, int16_t* pBufferOut); + // Seeks to the sample at the given index. // // pFlac [in] The decoder. @@ -558,7 +576,7 @@ uint64_t drflac_read_s32(drflac* pFlac, uint64_t samplesToRead, int32_t* pBuffer // // When seeking, you will likely want to ensure it's rounded to a multiple of the channel count. You can do this with // something like drflac_seek_to_sample(pFlac, (mySampleIndex + (mySampleIndex % pFlac->channels))) -drBool32 drflac_seek_to_sample(drflac* pFlac, uint64_t sampleIndex); +dr_bool32 drflac_seek_to_sample(drflac* pFlac, uint64_t sampleIndex); @@ -607,14 +625,17 @@ drflac* drflac_open_memory_with_metadata(const void* data, size_t dataSize, drfl // // Do not call this function on a broadcast type of stream (like internet radio streams and whatnot). int32_t* drflac_open_and_decode_s32(drflac_read_proc onRead, drflac_seek_proc onSeek, void* pUserData, unsigned int* channels, unsigned int* sampleRate, uint64_t* totalSampleCount); +int16_t* drflac_open_and_decode_s16(drflac_read_proc onRead, drflac_seek_proc onSeek, void* pUserData, unsigned int* channels, unsigned int* sampleRate, uint64_t* totalSampleCount); #ifndef DR_FLAC_NO_STDIO // Same as drflac_open_and_decode_s32() except opens the decoder from a file. int32_t* drflac_open_and_decode_file_s32(const char* filename, unsigned int* channels, unsigned int* sampleRate, uint64_t* totalSampleCount); +int16_t* drflac_open_and_decode_file_s16(const char* filename, unsigned int* channels, unsigned int* sampleRate, uint64_t* totalSampleCount); #endif // Same as drflac_open_and_decode_s32() except opens the decoder from a block of memory. int32_t* drflac_open_and_decode_memory_s32(const void* data, size_t dataSize, unsigned int* channels, unsigned int* sampleRate, uint64_t* totalSampleCount); +int16_t* drflac_open_and_decode_memory_s16(const void* data, size_t dataSize, unsigned int* channels, unsigned int* sampleRate, uint64_t* totalSampleCount); // Frees data returned by drflac_open_and_decode_*(). void drflac_free(void* pSampleDataReturnedByOpenAndDecode); @@ -684,7 +705,7 @@ const char* drflac_next_vorbis_comment(drflac_vorbis_comment_iterator* pIter, ui //// Endian Management //// -static DRFLAC_INLINE drBool32 drflac__is_little_endian() +static DRFLAC_INLINE dr_bool32 drflac__is_little_endian() { int n = 1; return (*(char*)&n) == 1; @@ -817,7 +838,7 @@ static DRFLAC_INLINE uint32_t drflac__le2host_32(uint32_t n) #define DRFLAC_CACHE_L2_LINE_COUNT(bs) (DRFLAC_CACHE_L2_SIZE_BYTES(bs) / sizeof((bs)->cacheL2[0])) #define DRFLAC_CACHE_L2_LINES_REMAINING(bs) (DRFLAC_CACHE_L2_LINE_COUNT(bs) - (bs)->nextL2Line) -static DRFLAC_INLINE drBool32 drflac__reload_l1_cache_from_l2(drflac_bs* bs) +static DRFLAC_INLINE dr_bool32 drflac__reload_l1_cache_from_l2(drflac_bs* bs) { // Fast path. Try loading straight from L2. if (bs->nextL2Line < DRFLAC_CACHE_L2_LINE_COUNT(bs)) { @@ -871,7 +892,7 @@ static DRFLAC_INLINE drBool32 drflac__reload_l1_cache_from_l2(drflac_bs* bs) } } -static drBool32 drflac__reload_cache(drflac_bs* bs) +static dr_bool32 drflac__reload_cache(drflac_bs* bs) { // Fast path. Try just moving the next value in the L2 cache to the L1 cache. if (drflac__reload_l1_cache_from_l2(bs)) { @@ -907,7 +928,7 @@ static void drflac__reset_cache(drflac_bs* bs) bs->unalignedCache = 0; } -static drBool32 drflac__seek_bits(drflac_bs* bs, size_t bitsToSeek) +static dr_bool32 drflac__seek_bits(drflac_bs* bs, size_t bitsToSeek) { if (bitsToSeek <= DRFLAC_CACHE_L1_BITS_REMAINING(bs)) { bs->consumedBits += bitsToSeek; @@ -958,7 +979,7 @@ static drBool32 drflac__seek_bits(drflac_bs* bs, size_t bitsToSeek) } } -static drBool32 drflac__read_uint32(drflac_bs* bs, unsigned int bitCount, uint32_t* pResultOut) +static dr_bool32 drflac__read_uint32(drflac_bs* bs, unsigned int bitCount, uint32_t* pResultOut) { assert(bs != NULL); assert(pResultOut != NULL); @@ -999,7 +1020,7 @@ static drBool32 drflac__read_uint32(drflac_bs* bs, unsigned int bitCount, uint32 } } -static drBool32 drflac__read_int32(drflac_bs* bs, unsigned int bitCount, int32_t* pResult) +static dr_bool32 drflac__read_int32(drflac_bs* bs, unsigned int bitCount, int32_t* pResult) { assert(bs != NULL); assert(pResult != NULL); @@ -1018,7 +1039,7 @@ static drBool32 drflac__read_int32(drflac_bs* bs, unsigned int bitCount, int32_t return DR_TRUE; } -static drBool32 drflac__read_uint64(drflac_bs* bs, unsigned int bitCount, uint64_t* pResultOut) +static dr_bool32 drflac__read_uint64(drflac_bs* bs, unsigned int bitCount, uint64_t* pResultOut) { assert(bitCount <= 64); assert(bitCount > 32); @@ -1039,7 +1060,7 @@ static drBool32 drflac__read_uint64(drflac_bs* bs, unsigned int bitCount, uint64 // Function below is unused, but leaving it here in case I need to quickly add it again. #if 0 -static drBool32 drflac__read_int64(drflac_bs* bs, unsigned int bitCount, int64_t* pResultOut) +static dr_bool32 drflac__read_int64(drflac_bs* bs, unsigned int bitCount, int64_t* pResultOut) { assert(bitCount <= 64); @@ -1056,7 +1077,7 @@ static drBool32 drflac__read_int64(drflac_bs* bs, unsigned int bitCount, int64_t } #endif -static drBool32 drflac__read_uint16(drflac_bs* bs, unsigned int bitCount, uint16_t* pResult) +static dr_bool32 drflac__read_uint16(drflac_bs* bs, unsigned int bitCount, uint16_t* pResult) { assert(bs != NULL); assert(pResult != NULL); @@ -1072,7 +1093,7 @@ static drBool32 drflac__read_uint16(drflac_bs* bs, unsigned int bitCount, uint16 return DR_TRUE; } -static drBool32 drflac__read_int16(drflac_bs* bs, unsigned int bitCount, int16_t* pResult) +static dr_bool32 drflac__read_int16(drflac_bs* bs, unsigned int bitCount, int16_t* pResult) { assert(bs != NULL); assert(pResult != NULL); @@ -1088,7 +1109,7 @@ static drBool32 drflac__read_int16(drflac_bs* bs, unsigned int bitCount, int16_t return DR_TRUE; } -static drBool32 drflac__read_uint8(drflac_bs* bs, unsigned int bitCount, uint8_t* pResult) +static dr_bool32 drflac__read_uint8(drflac_bs* bs, unsigned int bitCount, uint8_t* pResult) { assert(bs != NULL); assert(pResult != NULL); @@ -1104,7 +1125,7 @@ static drBool32 drflac__read_uint8(drflac_bs* bs, unsigned int bitCount, uint8_t return DR_TRUE; } -static drBool32 drflac__read_int8(drflac_bs* bs, unsigned int bitCount, int8_t* pResult) +static dr_bool32 drflac__read_int8(drflac_bs* bs, unsigned int bitCount, int8_t* pResult) { assert(bs != NULL); assert(pResult != NULL); @@ -1121,7 +1142,7 @@ static drBool32 drflac__read_int8(drflac_bs* bs, unsigned int bitCount, int8_t* } -static inline drBool32 drflac__seek_past_next_set_bit(drflac_bs* bs, unsigned int* pOffsetOut) +static inline dr_bool32 drflac__seek_past_next_set_bit(drflac_bs* bs, unsigned int* pOffsetOut) { unsigned int zeroCounter = 0; while (bs->cache == 0) { @@ -1169,7 +1190,7 @@ static inline drBool32 drflac__seek_past_next_set_bit(drflac_bs* bs, unsigned in -static drBool32 drflac__seek_to_byte(drflac_bs* bs, uint64_t offsetFromStart) +static dr_bool32 drflac__seek_to_byte(drflac_bs* bs, uint64_t offsetFromStart) { assert(bs != NULL); assert(offsetFromStart > 0); @@ -1214,7 +1235,7 @@ static drBool32 drflac__seek_to_byte(drflac_bs* bs, uint64_t offsetFromStart) } -static drBool32 drflac__read_utf8_coded_number(drflac_bs* bs, uint64_t* pNumberOut) +static dr_bool32 drflac__read_utf8_coded_number(drflac_bs* bs, uint64_t* pNumberOut) { assert(bs != NULL); assert(pNumberOut != NULL); @@ -1267,7 +1288,7 @@ static drBool32 drflac__read_utf8_coded_number(drflac_bs* bs, uint64_t* pNumberO -static DRFLAC_INLINE drBool32 drflac__read_and_seek_rice(drflac_bs* bs, uint8_t m) +static DRFLAC_INLINE dr_bool32 drflac__read_and_seek_rice(drflac_bs* bs, uint8_t m) { unsigned int unused; if (!drflac__seek_past_next_set_bit(bs, &unused)) { @@ -1520,7 +1541,7 @@ static DRFLAC_INLINE int32_t drflac__calculate_prediction_64(uint32_t order, int // iteration. The prediction is done at the end, and there's an annoying branch I'd like to avoid so the main function is defined // as a #define - sue me! #define DRFLAC__DECODE_SAMPLES_WITH_RESIDULE__RICE__PROC(funcName, predictionFunc) \ -static drBool32 funcName (drflac_bs* bs, uint32_t count, uint8_t riceParam, uint32_t order, int32_t shift, const int16_t* coefficients, int32_t* pSamplesOut) \ +static dr_bool32 funcName (drflac_bs* bs, uint32_t count, uint8_t riceParam, uint32_t order, int32_t shift, const int16_t* coefficients, int32_t* pSamplesOut) \ { \ assert(bs != NULL); \ assert(count > 0); \ @@ -1630,7 +1651,7 @@ DRFLAC__DECODE_SAMPLES_WITH_RESIDULE__RICE__PROC(drflac__decode_samples_with_res // Reads and seeks past a string of residual values as Rice codes. The decoder should be sitting on the first bit of the Rice codes. -static drBool32 drflac__read_and_seek_residual__rice(drflac_bs* bs, uint32_t count, uint8_t riceParam) +static dr_bool32 drflac__read_and_seek_residual__rice(drflac_bs* bs, uint32_t count, uint8_t riceParam) { assert(bs != NULL); assert(count > 0); @@ -1644,7 +1665,7 @@ static drBool32 drflac__read_and_seek_residual__rice(drflac_bs* bs, uint32_t cou return DR_TRUE; } -static drBool32 drflac__decode_samples_with_residual__unencoded(drflac_bs* bs, uint32_t bitsPerSample, uint32_t count, uint8_t unencodedBitsPerSample, uint32_t order, int32_t shift, const int16_t* coefficients, int32_t* pSamplesOut) +static dr_bool32 drflac__decode_samples_with_residual__unencoded(drflac_bs* bs, uint32_t bitsPerSample, uint32_t count, uint8_t unencodedBitsPerSample, uint32_t order, int32_t shift, const int16_t* coefficients, int32_t* pSamplesOut) { assert(bs != NULL); assert(count > 0); @@ -1671,7 +1692,7 @@ static drBool32 drflac__decode_samples_with_residual__unencoded(drflac_bs* bs, u // Reads and decodes the residual for the sub-frame the decoder is currently sitting on. This function should be called // when the decoder is sitting at the very start of the RESIDUAL block. The first residuals will be ignored. The // and parameters are used to determine how many residual values need to be decoded. -static drBool32 drflac__decode_samples_with_residual(drflac_bs* bs, uint32_t bitsPerSample, uint32_t blockSize, uint32_t order, int32_t shift, const int16_t* coefficients, int32_t* pDecodedSamples) +static dr_bool32 drflac__decode_samples_with_residual(drflac_bs* bs, uint32_t bitsPerSample, uint32_t blockSize, uint32_t order, int32_t shift, const int16_t* coefficients, int32_t* pDecodedSamples) { assert(bs != NULL); assert(blockSize != 0); @@ -1755,7 +1776,7 @@ static drBool32 drflac__decode_samples_with_residual(drflac_bs* bs, uint32_t bit // Reads and seeks past the residual for the sub-frame the decoder is currently sitting on. This function should be called // when the decoder is sitting at the very start of the RESIDUAL block. The first residuals will be set to 0. The // and parameters are used to determine how many residual values need to be decoded. -static drBool32 drflac__read_and_seek_residual(drflac_bs* bs, uint32_t blockSize, uint32_t order) +static dr_bool32 drflac__read_and_seek_residual(drflac_bs* bs, uint32_t blockSize, uint32_t order) { assert(bs != NULL); assert(blockSize != 0); @@ -1823,7 +1844,7 @@ static drBool32 drflac__read_and_seek_residual(drflac_bs* bs, uint32_t blockSize } -static drBool32 drflac__decode_samples__constant(drflac_bs* bs, uint32_t blockSize, uint32_t bitsPerSample, int32_t* pDecodedSamples) +static dr_bool32 drflac__decode_samples__constant(drflac_bs* bs, uint32_t blockSize, uint32_t bitsPerSample, int32_t* pDecodedSamples) { // Only a single sample needs to be decoded here. int32_t sample; @@ -1840,7 +1861,7 @@ static drBool32 drflac__decode_samples__constant(drflac_bs* bs, uint32_t blockSi return DR_TRUE; } -static drBool32 drflac__decode_samples__verbatim(drflac_bs* bs, uint32_t blockSize, uint32_t bitsPerSample, int32_t* pDecodedSamples) +static dr_bool32 drflac__decode_samples__verbatim(drflac_bs* bs, uint32_t blockSize, uint32_t bitsPerSample, int32_t* pDecodedSamples) { for (uint32_t i = 0; i < blockSize; ++i) { int32_t sample; @@ -1854,7 +1875,7 @@ static drBool32 drflac__decode_samples__verbatim(drflac_bs* bs, uint32_t blockSi return DR_TRUE; } -static drBool32 drflac__decode_samples__fixed(drflac_bs* bs, uint32_t blockSize, uint32_t bitsPerSample, uint8_t lpcOrder, int32_t* pDecodedSamples) +static dr_bool32 drflac__decode_samples__fixed(drflac_bs* bs, uint32_t blockSize, uint32_t bitsPerSample, uint8_t lpcOrder, int32_t* pDecodedSamples) { short lpcCoefficientsTable[5][4] = { {0, 0, 0, 0}, @@ -1882,7 +1903,7 @@ static drBool32 drflac__decode_samples__fixed(drflac_bs* bs, uint32_t blockSize, return DR_TRUE; } -static drBool32 drflac__decode_samples__lpc(drflac_bs* bs, uint32_t blockSize, uint32_t bitsPerSample, uint8_t lpcOrder, int32_t* pDecodedSamples) +static dr_bool32 drflac__decode_samples__lpc(drflac_bs* bs, uint32_t blockSize, uint32_t bitsPerSample, uint8_t lpcOrder, int32_t* pDecodedSamples) { // Warm up samples. for (uint8_t i = 0; i < lpcOrder; ++i) { @@ -1925,7 +1946,7 @@ static drBool32 drflac__decode_samples__lpc(drflac_bs* bs, uint32_t blockSize, u } -static drBool32 drflac__read_next_frame_header(drflac_bs* bs, uint8_t streaminfoBitsPerSample, drflac_frame_header* header) +static dr_bool32 drflac__read_next_frame_header(drflac_bs* bs, uint8_t streaminfoBitsPerSample, drflac_frame_header* header) { assert(bs != NULL); assert(header != NULL); @@ -1983,7 +2004,7 @@ static drBool32 drflac__read_next_frame_header(drflac_bs* bs, uint8_t streaminfo } - drBool32 isVariableBlockSize = blockingStrategy == 1; + dr_bool32 isVariableBlockSize = blockingStrategy == 1; if (isVariableBlockSize) { uint64_t sampleNumber; if (!drflac__read_utf8_coded_number(bs, &sampleNumber)) { @@ -2055,7 +2076,7 @@ static drBool32 drflac__read_next_frame_header(drflac_bs* bs, uint8_t streaminfo return DR_TRUE; } -static drBool32 drflac__read_subframe_header(drflac_bs* bs, drflac_subframe* pSubframe) +static dr_bool32 drflac__read_subframe_header(drflac_bs* bs, drflac_subframe* pSubframe) { uint8_t header; if (!drflac__read_uint8(bs, 8, &header)) { @@ -2105,7 +2126,7 @@ static drBool32 drflac__read_subframe_header(drflac_bs* bs, drflac_subframe* pSu return DR_TRUE; } -static drBool32 drflac__decode_subframe(drflac_bs* bs, drflac_frame* frame, int subframeIndex, int32_t* pDecodedSamplesOut) +static dr_bool32 drflac__decode_subframe(drflac_bs* bs, drflac_frame* frame, int subframeIndex, int32_t* pDecodedSamplesOut) { assert(bs != NULL); assert(frame != NULL); @@ -2155,7 +2176,7 @@ static drBool32 drflac__decode_subframe(drflac_bs* bs, drflac_frame* frame, int return DR_TRUE; } -static drBool32 drflac__seek_subframe(drflac_bs* bs, drflac_frame* frame, int subframeIndex) +static dr_bool32 drflac__seek_subframe(drflac_bs* bs, drflac_frame* frame, int subframeIndex) { assert(bs != NULL); assert(frame != NULL); @@ -2249,7 +2270,7 @@ static DRFLAC_INLINE uint8_t drflac__get_channel_count_from_channel_assignment(i return lookup[channelAssignment]; } -static drBool32 drflac__decode_frame(drflac* pFlac) +static dr_bool32 drflac__decode_frame(drflac* pFlac) { // This function should be called while the stream is sitting on the first byte after the frame header. memset(pFlac->currentFrame.subframes, 0, sizeof(pFlac->currentFrame.subframes)); @@ -2273,7 +2294,7 @@ static drBool32 drflac__decode_frame(drflac* pFlac) return DR_TRUE; } -static drBool32 drflac__seek_frame(drflac* pFlac) +static dr_bool32 drflac__seek_frame(drflac* pFlac) { int channelCount = drflac__get_channel_count_from_channel_assignment(pFlac->currentFrame.header.channelAssignment); for (int i = 0; i < channelCount; ++i) @@ -2287,7 +2308,7 @@ static drBool32 drflac__seek_frame(drflac* pFlac) return drflac__seek_bits(&pFlac->bs, (DRFLAC_CACHE_L1_BITS_REMAINING(&pFlac->bs) & 7) + 16); } -static drBool32 drflac__read_and_decode_next_frame(drflac* pFlac) +static dr_bool32 drflac__read_and_decode_next_frame(drflac* pFlac) { assert(pFlac != NULL); @@ -2324,24 +2345,24 @@ static void drflac__get_current_frame_sample_range(drflac* pFlac, uint64_t* pFir } } -static drBool32 drflac__seek_to_first_frame(drflac* pFlac) +static dr_bool32 drflac__seek_to_first_frame(drflac* pFlac) { assert(pFlac != NULL); - drBool32 result = drflac__seek_to_byte(&pFlac->bs, pFlac->firstFramePos); + dr_bool32 result = drflac__seek_to_byte(&pFlac->bs, pFlac->firstFramePos); memset(&pFlac->currentFrame, 0, sizeof(pFlac->currentFrame)); return result; } -static DRFLAC_INLINE drBool32 drflac__seek_to_next_frame(drflac* pFlac) +static DRFLAC_INLINE dr_bool32 drflac__seek_to_next_frame(drflac* pFlac) { // This function should only ever be called while the decoder is sitting on the first byte past the FRAME_HEADER section. assert(pFlac != NULL); return drflac__seek_frame(pFlac); } -static drBool32 drflac__seek_to_frame_containing_sample(drflac* pFlac, uint64_t sampleIndex) +static dr_bool32 drflac__seek_to_frame_containing_sample(drflac* pFlac, uint64_t sampleIndex) { assert(pFlac != NULL); @@ -2372,7 +2393,7 @@ static drBool32 drflac__seek_to_frame_containing_sample(drflac* pFlac, uint64_t return DR_TRUE; } -static drBool32 drflac__seek_to_sample__brute_force(drflac* pFlac, uint64_t sampleIndex) +static dr_bool32 drflac__seek_to_sample__brute_force(drflac* pFlac, uint64_t sampleIndex) { if (!drflac__seek_to_frame_containing_sample(pFlac, sampleIndex)) { return DR_FALSE; @@ -2398,7 +2419,7 @@ static drBool32 drflac__seek_to_sample__brute_force(drflac* pFlac, uint64_t samp } -static drBool32 drflac__seek_to_sample__seek_table(drflac* pFlac, uint64_t sampleIndex) +static dr_bool32 drflac__seek_to_sample__seek_table(drflac* pFlac, uint64_t sampleIndex) { assert(pFlac != NULL); @@ -2508,7 +2529,7 @@ typedef struct uint64_t totalSampleCount; uint16_t maxBlockSize; uint64_t runningFilePos; - drBool32 hasMetadataBlocks; + dr_bool32 hasMetadataBlocks; #ifndef DR_FLAC_NO_OGG uint32_t oggSerial; @@ -2525,7 +2546,7 @@ static DRFLAC_INLINE void drflac__decode_block_header(uint32_t blockHeader, uint *blockSize = (blockHeader & 0xFFFFFF); } -static DRFLAC_INLINE drBool32 drflac__read_and_decode_block_header(drflac_read_proc onRead, void* pUserData, uint8_t* isLastBlock, uint8_t* blockType, uint32_t* blockSize) +static DRFLAC_INLINE dr_bool32 drflac__read_and_decode_block_header(drflac_read_proc onRead, void* pUserData, uint8_t* isLastBlock, uint8_t* blockType, uint32_t* blockSize) { uint32_t blockHeader; if (onRead(pUserData, &blockHeader, 4) != 4) { @@ -2536,7 +2557,7 @@ static DRFLAC_INLINE drBool32 drflac__read_and_decode_block_header(drflac_read_p return DR_TRUE; } -drBool32 drflac__read_streaminfo(drflac_read_proc onRead, void* pUserData, drflac_streaminfo* pStreamInfo) +dr_bool32 drflac__read_streaminfo(drflac_read_proc onRead, void* pUserData, drflac_streaminfo* pStreamInfo) { // min/max block size. uint32_t blockSizes; @@ -2579,7 +2600,7 @@ drBool32 drflac__read_streaminfo(drflac_read_proc onRead, void* pUserData, drfla return DR_TRUE; } -drBool32 drflac__read_and_decode_metadata(drflac* pFlac) +dr_bool32 drflac__read_and_decode_metadata(drflac* pFlac) { assert(pFlac != NULL); @@ -2823,7 +2844,7 @@ drBool32 drflac__read_and_decode_metadata(drflac* pFlac) return DR_TRUE; } -drBool32 drflac__init_private__native(drflac_init_info* pInit, drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_meta_proc onMeta, void* pUserData, void* pUserDataMD) +dr_bool32 drflac__init_private__native(drflac_init_info* pInit, drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_meta_proc onMeta, void* pUserData, void* pUserDataMD) { (void)onSeek; @@ -2869,7 +2890,7 @@ drBool32 drflac__init_private__native(drflac_init_info* pInit, drflac_read_proc } #ifndef DR_FLAC_NO_OGG -static DRFLAC_INLINE drBool32 drflac_ogg__is_capture_pattern(uint8_t pattern[4]) +static DRFLAC_INLINE dr_bool32 drflac_ogg__is_capture_pattern(uint8_t pattern[4]) { return pattern[0] == 'O' && pattern[1] == 'g' && pattern[2] == 'g' && pattern[3] == 'S'; } @@ -2889,7 +2910,7 @@ static DRFLAC_INLINE uint32_t drflac_ogg__get_page_body_size(drflac_ogg_page_hea return pageBodySize; } -drBool32 drflac_ogg__read_page_header_after_capture_pattern(drflac_read_proc onRead, void* pUserData, drflac_ogg_page_header* pHeader, uint32_t* pHeaderSize) +dr_bool32 drflac_ogg__read_page_header_after_capture_pattern(drflac_read_proc onRead, void* pUserData, drflac_ogg_page_header* pHeader, uint32_t* pHeaderSize) { if (onRead(pUserData, &pHeader->structureVersion, 1) != 1 || pHeader->structureVersion != 0) { return DR_FALSE; // Unknown structure version. Possibly corrupt stream. @@ -2920,7 +2941,7 @@ drBool32 drflac_ogg__read_page_header_after_capture_pattern(drflac_read_proc onR return DR_TRUE; } -drBool32 drflac_ogg__read_page_header(drflac_read_proc onRead, void* pUserData, drflac_ogg_page_header* pHeader, uint32_t* pHeaderSize) +dr_bool32 drflac_ogg__read_page_header(drflac_read_proc onRead, void* pUserData, drflac_ogg_page_header* pHeader, uint32_t* pHeaderSize) { uint8_t id[4]; if (onRead(pUserData, id, 4) != 4) { @@ -2961,7 +2982,7 @@ static size_t drflac_oggbs__read_physical(drflac_oggbs* oggbs, void* bufferOut, return bytesActuallyRead; } -static drBool32 drflac_oggbs__seek_physical(drflac_oggbs* oggbs, uint64_t offset, drflac_seek_origin origin) +static dr_bool32 drflac_oggbs__seek_physical(drflac_oggbs* oggbs, uint64_t offset, drflac_seek_origin origin) { if (origin == drflac_seek_origin_start) { @@ -3000,7 +3021,7 @@ static drBool32 drflac_oggbs__seek_physical(drflac_oggbs* oggbs, uint64_t offset } } -static drBool32 drflac_oggbs__goto_next_page(drflac_oggbs* oggbs) +static dr_bool32 drflac_oggbs__goto_next_page(drflac_oggbs* oggbs) { drflac_ogg_page_header header; for (;;) @@ -3049,12 +3070,12 @@ static uint8_t drflac_oggbs__get_current_segment_index(drflac_oggbs* oggbs, uint return iSeg; } -static drBool32 drflac_oggbs__seek_to_next_packet(drflac_oggbs* oggbs) +static dr_bool32 drflac_oggbs__seek_to_next_packet(drflac_oggbs* oggbs) { // The current packet ends when we get to the segment with a lacing value of < 255 which is not at the end of a page. for (;;) // <-- Loop over pages. { - drBool32 atEndOfPage = DR_FALSE; + dr_bool32 atEndOfPage = DR_FALSE; uint8_t bytesRemainingInSeg; uint8_t iFirstSeg = drflac_oggbs__get_current_segment_index(oggbs, &bytesRemainingInSeg); @@ -3099,7 +3120,7 @@ static drBool32 drflac_oggbs__seek_to_next_packet(drflac_oggbs* oggbs) } } -static drBool32 drflac_oggbs__seek_to_next_frame(drflac_oggbs* oggbs) +static dr_bool32 drflac_oggbs__seek_to_next_frame(drflac_oggbs* oggbs) { // The bitstream should be sitting on the first byte just after the header of the frame. @@ -3148,7 +3169,7 @@ static size_t drflac__on_read_ogg(void* pUserData, void* bufferOut, size_t bytes return bytesRead; } -static drBool32 drflac__on_seek_ogg(void* pUserData, int offset, drflac_seek_origin origin) +static dr_bool32 drflac__on_seek_ogg(void* pUserData, int offset, drflac_seek_origin origin) { drflac_oggbs* oggbs = (drflac_oggbs*)pUserData; assert(oggbs != NULL); @@ -3204,7 +3225,7 @@ static drBool32 drflac__on_seek_ogg(void* pUserData, int offset, drflac_seek_ori return DR_TRUE; } -drBool32 drflac_ogg__seek_to_sample(drflac* pFlac, uint64_t sample) +dr_bool32 drflac_ogg__seek_to_sample(drflac* pFlac, uint64_t sample) { drflac_oggbs* oggbs = (drflac_oggbs*)(((int32_t*)pFlac->pExtraData) + pFlac->maxBlockSize*pFlac->channels); @@ -3327,7 +3348,7 @@ drBool32 drflac_ogg__seek_to_sample(drflac* pFlac, uint64_t sample) } -drBool32 drflac__init_private__ogg(drflac_init_info* pInit, drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_meta_proc onMeta, void* pUserData, void* pUserDataMD) +dr_bool32 drflac__init_private__ogg(drflac_init_info* pInit, drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_meta_proc onMeta, void* pUserData, void* pUserDataMD) { // Pre: The bit stream should be sitting just past the 4-byte OggS capture pattern. @@ -3491,7 +3512,7 @@ drBool32 drflac__init_private__ogg(drflac_init_info* pInit, drflac_read_proc onR } #endif -drBool32 drflac__init_private(drflac_init_info* pInit, drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_meta_proc onMeta, void* pUserData, void* pUserDataMD) +dr_bool32 drflac__init_private(drflac_init_info* pInit, drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_meta_proc onMeta, void* pUserData, void* pUserDataMD) { if (pInit == NULL || onRead == NULL || onSeek == NULL) { return DR_FALSE; @@ -3610,7 +3631,7 @@ static size_t drflac__on_read_stdio(void* pUserData, void* bufferOut, size_t byt return fread(bufferOut, 1, bytesToRead, (FILE*)pUserData); } -static drBool32 drflac__on_seek_stdio(void* pUserData, int offset, drflac_seek_origin origin) +static dr_bool32 drflac__on_seek_stdio(void* pUserData, int offset, drflac_seek_origin origin) { assert(offset > 0 || (offset == 0 && origin == drflac_seek_origin_start)); @@ -3651,7 +3672,7 @@ static size_t drflac__on_read_stdio(void* pUserData, void* bufferOut, size_t byt return (size_t)bytesRead; } -static drBool32 drflac__on_seek_stdio(void* pUserData, int offset, drflac_seek_origin origin) +static dr_bool32 drflac__on_seek_stdio(void* pUserData, int offset, drflac_seek_origin origin) { assert(offset > 0 || (offset == 0 && origin == drflac_seek_origin_start)); @@ -3727,7 +3748,7 @@ static size_t drflac__on_read_memory(void* pUserData, void* bufferOut, size_t by return bytesToRead; } -static drBool32 drflac__on_seek_memory(void* pUserData, int offset, drflac_seek_origin origin) +static dr_bool32 drflac__on_seek_memory(void* pUserData, int offset, drflac_seek_origin origin) { drflac__memory_stream* memoryStream = (drflac__memory_stream*)pUserData; assert(memoryStream != NULL); @@ -4107,7 +4128,32 @@ uint64_t drflac_read_s32(drflac* pFlac, uint64_t samplesToRead, int32_t* bufferO return samplesRead; } -drBool32 drflac_seek_to_sample(drflac* pFlac, uint64_t sampleIndex) +uint64_t drflac_read_s16(drflac* pFlac, uint64_t samplesToRead, int16_t* pBufferOut) +{ + // This reads samples in 2 passes and can probably be optimized. + uint64_t samplesRead = 0; + + while (samplesToRead > 0) { + int32_t samples32[4096]; + uint64_t samplesJustRead = drflac_read_s32(pFlac, samplesToRead > 4096 ? 4096 : samplesToRead, samples32); + if (samplesJustRead == 0) { + break; // Reached the end. + } + + // s32 -> s16 + for (uint64_t i = 0; i < samplesJustRead; ++i) { + pBufferOut[i] = (int16_t)(samples32[i] >> 16); + } + + samplesRead += samplesJustRead; + samplesToRead -= samplesJustRead; + pBufferOut += samplesJustRead; + } + + return samplesRead; +} + +dr_bool32 drflac_seek_to_sample(drflac* pFlac, uint64_t sampleIndex) { if (pFlac == NULL) { return DR_FALSE; @@ -4147,7 +4193,7 @@ drBool32 drflac_seek_to_sample(drflac* pFlac, uint64_t sampleIndex) //// High Level APIs //// -int32_t* drflac__full_decode_and_close(drflac* pFlac, unsigned int* channelsOut, unsigned int* sampleRateOut, uint64_t* totalSampleCountOut) +int32_t* drflac__full_decode_and_close_s32(drflac* pFlac, unsigned int* channelsOut, unsigned int* sampleRateOut, uint64_t* totalSampleCountOut) { assert(pFlac != NULL); @@ -4218,6 +4264,77 @@ on_error: return NULL; } +int16_t* drflac__full_decode_and_close_s16(drflac* pFlac, unsigned int* channelsOut, unsigned int* sampleRateOut, uint64_t* totalSampleCountOut) +{ + assert(pFlac != NULL); + + int16_t* pSampleData = NULL; + uint64_t totalSampleCount = pFlac->totalSampleCount; + + if (totalSampleCount == 0) + { + int16_t buffer[4096]; + + size_t sampleDataBufferSize = sizeof(buffer); + pSampleData = (int16_t*)malloc(sampleDataBufferSize); + if (pSampleData == NULL) { + goto on_error; + } + + uint64_t samplesRead; + while ((samplesRead = (uint64_t)drflac_read_s16(pFlac, sizeof(buffer)/sizeof(buffer[0]), buffer)) > 0) + { + if (((totalSampleCount + samplesRead) * sizeof(int16_t)) > sampleDataBufferSize) { + sampleDataBufferSize *= 2; + int16_t* pNewSampleData = (int16_t*)realloc(pSampleData, sampleDataBufferSize); + if (pNewSampleData == NULL) { + free(pSampleData); + goto on_error; + } + + pSampleData = pNewSampleData; + } + + memcpy(pSampleData + totalSampleCount, buffer, (size_t)(samplesRead*sizeof(int16_t))); + totalSampleCount += samplesRead; + } + + // At this point everything should be decoded, but we just want to fill the unused part buffer with silence - need to + // protect those ears from random noise! + memset(pSampleData + totalSampleCount, 0, (size_t)(sampleDataBufferSize - totalSampleCount*sizeof(int16_t))); + } + else + { + uint64_t dataSize = totalSampleCount * sizeof(int16_t); + if (dataSize > SIZE_MAX) { + goto on_error; // The decoded data is too big. + } + + pSampleData = (int16_t*)malloc((size_t)dataSize); // <-- Safe cast as per the check above. + if (pSampleData == NULL) { + goto on_error; + } + + uint64_t samplesDecoded = drflac_read_s16(pFlac, pFlac->totalSampleCount, pSampleData); + if (samplesDecoded != pFlac->totalSampleCount) { + free(pSampleData); + goto on_error; // Something went wrong when decoding the FLAC stream. + } + } + + + if (sampleRateOut) *sampleRateOut = pFlac->sampleRate; + if (channelsOut) *channelsOut = pFlac->channels; + if (totalSampleCountOut) *totalSampleCountOut = totalSampleCount; + + drflac_close(pFlac); + return pSampleData; + +on_error: + drflac_close(pFlac); + return NULL; +} + int32_t* drflac_open_and_decode_s32(drflac_read_proc onRead, drflac_seek_proc onSeek, void* pUserData, unsigned int* channels, unsigned int* sampleRate, uint64_t* totalSampleCount) { // Safety. @@ -4230,7 +4347,22 @@ int32_t* drflac_open_and_decode_s32(drflac_read_proc onRead, drflac_seek_proc on return NULL; } - return drflac__full_decode_and_close(pFlac, channels, sampleRate, totalSampleCount); + return drflac__full_decode_and_close_s32(pFlac, channels, sampleRate, totalSampleCount); +} + +int16_t* drflac_open_and_decode_s16(drflac_read_proc onRead, drflac_seek_proc onSeek, void* pUserData, unsigned int* channels, unsigned int* sampleRate, uint64_t* totalSampleCount) +{ + // Safety. + if (sampleRate) *sampleRate = 0; + if (channels) *channels = 0; + if (totalSampleCount) *totalSampleCount = 0; + + drflac* pFlac = drflac_open(onRead, onSeek, pUserData); + if (pFlac == NULL) { + return NULL; + } + + return drflac__full_decode_and_close_s16(pFlac, channels, sampleRate, totalSampleCount); } #ifndef DR_FLAC_NO_STDIO @@ -4245,7 +4377,21 @@ int32_t* drflac_open_and_decode_file_s32(const char* filename, unsigned int* cha return NULL; } - return drflac__full_decode_and_close(pFlac, channels, sampleRate, totalSampleCount); + return drflac__full_decode_and_close_s32(pFlac, channels, sampleRate, totalSampleCount); +} + +int16_t* drflac_open_and_decode_file_s16(const char* filename, unsigned int* channels, unsigned int* sampleRate, uint64_t* totalSampleCount) +{ + if (sampleRate) *sampleRate = 0; + if (channels) *channels = 0; + if (totalSampleCount) *totalSampleCount = 0; + + drflac* pFlac = drflac_open_file(filename); + if (pFlac == NULL) { + return NULL; + } + + return drflac__full_decode_and_close_s16(pFlac, channels, sampleRate, totalSampleCount); } #endif @@ -4260,7 +4406,21 @@ int32_t* drflac_open_and_decode_memory_s32(const void* data, size_t dataSize, un return NULL; } - return drflac__full_decode_and_close(pFlac, channels, sampleRate, totalSampleCount); + return drflac__full_decode_and_close_s32(pFlac, channels, sampleRate, totalSampleCount); +} + +int16_t* drflac_open_and_decode_memory_s16(const void* data, size_t dataSize, unsigned int* channels, unsigned int* sampleRate, uint64_t* totalSampleCount) +{ + if (sampleRate) *sampleRate = 0; + if (channels) *channels = 0; + if (totalSampleCount) *totalSampleCount = 0; + + drflac* pFlac = drflac_open_memory(data, dataSize); + if (pFlac == NULL) { + return NULL; + } + + return drflac__full_decode_and_close_s16(pFlac, channels, sampleRate, totalSampleCount); } void drflac_free(void* pSampleDataReturnedByOpenAndDecode) @@ -4305,6 +4465,15 @@ const char* drflac_next_vorbis_comment(drflac_vorbis_comment_iterator* pIter, ui // REVISION HISTORY // +// v0.4c - 2016-12-26 +// - Add support for signed 16-bit integer PCM decoding. +// +// v0.4b - 2016-10-23 +// - A minor change to dr_bool8 and dr_bool32 types. +// +// v0.4a - 2016-10-11 +// - Rename drBool32 to dr_bool32 for styling consistency. +// // v0.4 - 2016-09-29 // - API/ABI CHANGE: Use fixed size 32-bit booleans instead of the built-in bool type. // - API CHANGE: Rename drflac_open_and_decode*() to drflac_open_and_decode*_s32()