Commit 6e3a0a4f authored by David Reid's avatar David Reid

Update extras.

parent 89f8cd70
// FLAC audio decoder. Public domain. See "unlicense" statement at the end of this file. // FLAC audio decoder. Public domain. See "unlicense" statement at the end of this file.
// dr_flac - v0.9.5 - 2018-06-23 // dr_flac - v0.9.6 - 2018-06-29
// //
// David Reid - mackron@gmail.com // David Reid - mackron@gmail.com
...@@ -111,7 +111,7 @@ ...@@ -111,7 +111,7 @@
// - This has not been tested on big-endian architectures. // - This has not been tested on big-endian architectures.
// - Rice codes in unencoded binary form (see https://xiph.org/flac/format.html#rice_partition) has not been tested. If anybody // - Rice codes in unencoded binary form (see https://xiph.org/flac/format.html#rice_partition) has not been tested. If anybody
// knows where I can find some test files for this, let me know. // knows where I can find some test files for this, let me know.
// - dr_flac is not thread-safe, but it's APIs can be called from any thread so long as you do your own synchronization. // - dr_flac is not thread-safe, but its APIs can be called from any thread so long as you do your own synchronization.
// - When using Ogg encapsulation, a corrupted metadata block will result in drflac_open_with_metadata() and drflac_open() // - When using Ogg encapsulation, a corrupted metadata block will result in drflac_open_with_metadata() and drflac_open()
// returning inconsistent samples. // returning inconsistent samples.
...@@ -467,7 +467,7 @@ typedef struct ...@@ -467,7 +467,7 @@ typedef struct
// value specified in the STREAMINFO block. // value specified in the STREAMINFO block.
drflac_uint8 channels; drflac_uint8 channels;
// The bits per sample. Will be set to somthing like 16, 24, etc. // The bits per sample. Will be set to something like 16, 24, etc.
drflac_uint8 bitsPerSample; drflac_uint8 bitsPerSample;
// The maximum block size, in samples. This number represents the number of samples in each channel (not combined). // The maximum block size, in samples. This number represents the number of samples in each channel (not combined).
...@@ -579,7 +579,7 @@ drflac* drflac_open_relaxed(drflac_read_proc onRead, drflac_seek_proc onSeek, dr ...@@ -579,7 +579,7 @@ drflac* drflac_open_relaxed(drflac_read_proc onRead, drflac_seek_proc onSeek, dr
// See also: drflac_open_file_with_metadata(), drflac_open_memory_with_metadata(), drflac_open(), drflac_close() // See also: drflac_open_file_with_metadata(), drflac_open_memory_with_metadata(), drflac_open(), drflac_close()
drflac* drflac_open_with_metadata(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_meta_proc onMeta, void* pUserData); drflac* drflac_open_with_metadata(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_meta_proc onMeta, void* pUserData);
// The same as drflac_open_with_metadata(), except attemps to open the stream even when a header block is not present. // The same as drflac_open_with_metadata(), except attempts to open the stream even when a header block is not present.
// //
// See also: drflac_open_with_metadata(), drflac_open_relaxed() // See also: drflac_open_with_metadata(), drflac_open_relaxed()
drflac* drflac_open_with_metadata_relaxed(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_meta_proc onMeta, drflac_container container, void* pUserData); drflac* drflac_open_with_metadata_relaxed(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_meta_proc onMeta, drflac_container container, void* pUserData);
...@@ -3175,10 +3175,10 @@ static drflac_bool32 drflac__seek_to_sample__brute_force(drflac* pFlac, drflac_u ...@@ -3175,10 +3175,10 @@ static drflac_bool32 drflac__seek_to_sample__brute_force(drflac* pFlac, drflac_u
drflac_bool32 isMidFrame = DRFLAC_FALSE; drflac_bool32 isMidFrame = DRFLAC_FALSE;
// If we are seeking foward we start from the current position. Otherwise we need to start all the way from the start of the file. // If we are seeking forward we start from the current position. Otherwise we need to start all the way from the start of the file.
drflac_uint64 runningSampleCount; drflac_uint64 runningSampleCount;
if (sampleIndex >= pFlac->currentSample) { if (sampleIndex >= pFlac->currentSample) {
// Seeking foward. Need to seek from the current position. // Seeking forward. Need to seek from the current position.
runningSampleCount = pFlac->currentSample; runningSampleCount = pFlac->currentSample;
// The frame header for the first frame may not yet have been read. We need to do that if necessary. // The frame header for the first frame may not yet have been read. We need to do that if necessary.
...@@ -3204,7 +3204,7 @@ static drflac_bool32 drflac__seek_to_sample__brute_force(drflac* pFlac, drflac_u ...@@ -3204,7 +3204,7 @@ static drflac_bool32 drflac__seek_to_sample__brute_force(drflac* pFlac, drflac_u
} }
} }
// We need to as quickly as possible find the frame that contains the target sample. To do this, we iterate over each frame and inspect it's // We need to as quickly as possible find the frame that contains the target sample. To do this, we iterate over each frame and inspect its
// header. If based on the header we can determine that the frame contains the sample, we do a full decode of that frame. // header. If based on the header we can determine that the frame contains the sample, we do a full decode of that frame.
for (;;) { for (;;) {
drflac_uint64 firstSampleInFrame = 0; drflac_uint64 firstSampleInFrame = 0;
...@@ -3657,7 +3657,7 @@ drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, drflac_s ...@@ -3657,7 +3657,7 @@ drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, drflac_s
// Padding doesn't have anything meaningful in it, so just skip over it, but make sure the caller is aware of it by firing the callback. // Padding doesn't have anything meaningful in it, so just skip over it, but make sure the caller is aware of it by firing the callback.
if (!onSeek(pUserData, blockSize, drflac_seek_origin_current)) { if (!onSeek(pUserData, blockSize, drflac_seek_origin_current)) {
isLastBlock = DRFLAC_TRUE; // An error occured while seeking. Attempt to recover by treating this as the last block which will in turn terminate the loop. isLastBlock = DRFLAC_TRUE; // An error occurred while seeking. Attempt to recover by treating this as the last block which will in turn terminate the loop.
} else { } else {
onMeta(pUserDataMD, &metadata); onMeta(pUserDataMD, &metadata);
} }
...@@ -3669,7 +3669,7 @@ drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, drflac_s ...@@ -3669,7 +3669,7 @@ drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, drflac_s
// Invalid chunk. Just skip over this one. // Invalid chunk. Just skip over this one.
if (onMeta) { if (onMeta) {
if (!onSeek(pUserData, blockSize, drflac_seek_origin_current)) { if (!onSeek(pUserData, blockSize, drflac_seek_origin_current)) {
isLastBlock = DRFLAC_TRUE; // An error occured while seeking. Attempt to recover by treating this as the last block which will in turn terminate the loop. isLastBlock = DRFLAC_TRUE; // An error occurred while seeking. Attempt to recover by treating this as the last block which will in turn terminate the loop.
} }
} }
} break; } break;
...@@ -4003,7 +4003,7 @@ drflac_result drflac_ogg__read_page_header(drflac_read_proc onRead, void* pUserD ...@@ -4003,7 +4003,7 @@ drflac_result drflac_ogg__read_page_header(drflac_read_proc onRead, void* pUserD
// The main part of the Ogg encapsulation is the conversion from the physical Ogg bitstream to the native FLAC bitstream. It works // The main part of the Ogg encapsulation is the conversion from the physical Ogg bitstream to the native FLAC bitstream. It works
// in three general stages: Ogg Physical Bitstream -> Ogg/FLAC Logical Bitstream -> FLAC Native Bitstream. dr_flac is architecured // in three general stages: Ogg Physical Bitstream -> Ogg/FLAC Logical Bitstream -> FLAC Native Bitstream. dr_flac is designed
// in such a way that the core sections assume everything is delivered in native format. Therefore, for each encapsulation type // in such a way that the core sections assume everything is delivered in native format. Therefore, for each encapsulation type
// dr_flac is supporting there needs to be a layer sitting on top of the onRead and onSeek callbacks that ensures the bits read from // dr_flac is supporting there needs to be a layer sitting on top of the onRead and onSeek callbacks that ensures the bits read from
// the physical Ogg bitstream are converted and delivered in native FLAC format. // the physical Ogg bitstream are converted and delivered in native FLAC format.
...@@ -4351,13 +4351,13 @@ drflac_bool32 drflac_ogg__seek_to_sample(drflac* pFlac, drflac_uint64 sampleInde ...@@ -4351,13 +4351,13 @@ drflac_bool32 drflac_ogg__seek_to_sample(drflac* pFlac, drflac_uint64 sampleInde
// //
// Another thing to consider is that using the Ogg framing system will perform direct seeking of the physical Ogg // Another thing to consider is that using the Ogg framing system will perform direct seeking of the physical Ogg
// bitstream. This is important to consider because it means we cannot read data from the drflac_bs object using the // bitstream. This is important to consider because it means we cannot read data from the drflac_bs object using the
// standard drflac__*() APIs because that will read in extra data for it's own internal caching which in turn breaks // standard drflac__*() APIs because that will read in extra data for its own internal caching which in turn breaks
// the positioning of the read pointer of the physical Ogg bitstream. Therefore, anything that would normally be read // the positioning of the read pointer of the physical Ogg bitstream. Therefore, anything that would normally be read
// using the native FLAC decoding APIs, such as drflac__read_next_frame_header(), need to be re-implemented so as to // using the native FLAC decoding APIs, such as drflac__read_next_frame_header(), need to be re-implemented so as to
// avoid the use of the drflac_bs object. // avoid the use of the drflac_bs object.
// //
// Considering these issues, I have decided to use the slower native FLAC decoding method for the following reasons: // Considering these issues, I have decided to use the slower native FLAC decoding method for the following reasons:
// 1) Seeking is already partially accellerated using Ogg's paging system in the code block above. // 1) Seeking is already partially accelerated using Ogg's paging system in the code block above.
// 2) Seeking in an Ogg encapsulated FLAC stream is probably quite uncommon. // 2) Seeking in an Ogg encapsulated FLAC stream is probably quite uncommon.
// 3) Simplicity. // 3) Simplicity.
if (!drflac__read_next_frame_header(&pFlac->bs, pFlac->bitsPerSample, &pFlac->currentFrame.header)) { if (!drflac__read_next_frame_header(&pFlac->bs, pFlac->bitsPerSample, &pFlac->currentFrame.header)) {
...@@ -4550,7 +4550,7 @@ drflac_bool32 drflac__init_private__ogg(drflac_init_info* pInit, drflac_read_pro ...@@ -4550,7 +4550,7 @@ drflac_bool32 drflac__init_private__ogg(drflac_init_info* pInit, drflac_read_pro
// If we get here it means we found a FLAC audio stream. We should be sitting on the first byte of the header of the next page. The next // If we get here it means we found a FLAC audio stream. We should be sitting on the first byte of the header of the next page. The next
// packets in the FLAC logical stream contain the metadata. The only thing left to do in the initialiation phase for Ogg is to create the // packets in the FLAC logical stream contain the metadata. The only thing left to do in the initialization phase for Ogg is to create the
// Ogg bistream object. // Ogg bistream object.
pInit->hasMetadataBlocks = DRFLAC_TRUE; // <-- Always have at least VORBIS_COMMENT metadata block. pInit->hasMetadataBlocks = DRFLAC_TRUE; // <-- Always have at least VORBIS_COMMENT metadata block.
return DRFLAC_TRUE; return DRFLAC_TRUE;
...@@ -4758,7 +4758,7 @@ drflac* drflac_open_with_metadata_private(drflac_read_proc onRead, drflac_seek_p ...@@ -4758,7 +4758,7 @@ drflac* drflac_open_with_metadata_private(drflac_read_proc onRead, drflac_seek_p
pFlac->firstFramePos = firstFramePos; pFlac->firstFramePos = firstFramePos;
// NOTE: Seektables are not currently compatible with Ogg encapsulation (Ogg has it's own accelerated seeking system). I may change this later, so I'm leaving this here for now. // NOTE: Seektables are not currently compatible with Ogg encapsulation (Ogg has its own accelerated seeking system). I may change this later, so I'm leaving this here for now.
#ifndef DR_FLAC_NO_OGG #ifndef DR_FLAC_NO_OGG
if (init.container == drflac_container_ogg) if (init.container == drflac_container_ogg)
{ {
...@@ -5719,6 +5719,9 @@ const char* drflac_next_vorbis_comment(drflac_vorbis_comment_iterator* pIter, dr ...@@ -5719,6 +5719,9 @@ const char* drflac_next_vorbis_comment(drflac_vorbis_comment_iterator* pIter, dr
// REVISION HISTORY // REVISION HISTORY
// //
// v0.9.6 - 2018-06-29
// - Fix some typos.
//
// v0.9.5 - 2018-06-23 // v0.9.5 - 2018-06-23
// - Fix some warnings. // - Fix some warnings.
// //
......
// MP3 audio decoder. Public domain. See "unlicense" statement at the end of this file. // MP3 audio decoder. Public domain. See "unlicense" statement at the end of this file.
// dr_mp3 - v0.2.4 - 2018-05-12 // dr_mp3 - v0.2.5 - 2018-06-22
// //
// David Reid - mackron@gmail.com // David Reid - mackron@gmail.com
// //
...@@ -412,10 +412,10 @@ static int drmp3_have_simd() ...@@ -412,10 +412,10 @@ static int drmp3_have_simd()
#ifdef MINIMP3_TEST #ifdef MINIMP3_TEST
static int g_counter; static int g_counter;
if (g_counter++ > 100) if (g_counter++ > 100)
goto test_nosimd; return 0;
#endif #endif
if (g_have_simd) if (g_have_simd)
return g_have_simd - 1; goto end;
drmp3_cpuid(CPUInfo, 0); drmp3_cpuid(CPUInfo, 0);
if (CPUInfo[0] > 0) if (CPUInfo[0] > 0)
{ {
...@@ -423,11 +423,9 @@ static int drmp3_have_simd() ...@@ -423,11 +423,9 @@ static int drmp3_have_simd()
g_have_simd = (CPUInfo[3] & (1 << 26)) + 1; /* SSE2 */ g_have_simd = (CPUInfo[3] & (1 << 26)) + 1; /* SSE2 */
return g_have_simd - 1; return g_have_simd - 1;
} }
#ifdef MINIMP3_TEST
test_nosimd: end:
#endif return g_have_simd - 1;
g_have_simd = 1;
return 0;
#endif #endif
} }
#elif defined(__ARM_NEON) || defined(__aarch64__) #elif defined(__ARM_NEON) || defined(__aarch64__)
...@@ -1017,25 +1015,25 @@ static float drmp3_L3_pow_43(int x) ...@@ -1017,25 +1015,25 @@ static float drmp3_L3_pow_43(int x)
static void drmp3_L3_huffman(float *dst, drmp3_bs *bs, const drmp3_L3_gr_info *gr_info, const float *scf, int layer3gr_limit) static void drmp3_L3_huffman(float *dst, drmp3_bs *bs, const drmp3_L3_gr_info *gr_info, const float *scf, int layer3gr_limit)
{ {
static const float g_pow43_signed[32] = { 0,0,1,-1,2.519842f,-2.519842f,4.326749f,-4.326749f,6.349604f,-6.349604f,8.549880f,-8.549880f,10.902724f,-10.902724f,13.390518f,-13.390518f,16.000000f,-16.000000f,18.720754f,-18.720754f,21.544347f,-21.544347f,24.463781f,-24.463781f,27.473142f,-27.473142f,30.567351f,-30.567351f,33.741992f,-33.741992f,36.993181f,-36.993181f }; static const float g_pow43_signed[32] = { 0,0,1,-1,2.519842f,-2.519842f,4.326749f,-4.326749f,6.349604f,-6.349604f,8.549880f,-8.549880f,10.902724f,-10.902724f,13.390518f,-13.390518f,16.000000f,-16.000000f,18.720754f,-18.720754f,21.544347f,-21.544347f,24.463781f,-24.463781f,27.473142f,-27.473142f,30.567351f,-30.567351f,33.741992f,-33.741992f,36.993181f,-36.993181f };
static const drmp3_int16 tab0[32] = { 0, }; static const drmp3_int16 tabs[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
static const drmp3_int16 tab1[] = { 785,785,785,785,784,784,784,784,513,513,513,513,513,513,513,513,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256 }; 785,785,785,785,784,784,784,784,513,513,513,513,513,513,513,513,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,
static const drmp3_int16 tab2[] = { -255,1313,1298,1282,785,785,785,785,784,784,784,784,769,769,769,769,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,290,288 }; -255,1313,1298,1282,785,785,785,785,784,784,784,784,769,769,769,769,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,290,288,
static const drmp3_int16 tab3[] = { -255,1313,1298,1282,769,769,769,769,529,529,529,529,529,529,529,529,528,528,528,528,528,528,528,528,512,512,512,512,512,512,512,512,290,288 }; -255,1313,1298,1282,769,769,769,769,529,529,529,529,529,529,529,529,528,528,528,528,528,528,528,528,512,512,512,512,512,512,512,512,290,288,
static const drmp3_int16 tab5[] = { -253,-318,-351,-367,785,785,785,785,784,784,784,784,769,769,769,769,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,819,818,547,547,275,275,275,275,561,560,515,546,289,274,288,258 }; -253,-318,-351,-367,785,785,785,785,784,784,784,784,769,769,769,769,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,819,818,547,547,275,275,275,275,561,560,515,546,289,274,288,258,
static const drmp3_int16 tab6[] = { -254,-287,1329,1299,1314,1312,1057,1057,1042,1042,1026,1026,784,784,784,784,529,529,529,529,529,529,529,529,769,769,769,769,768,768,768,768,563,560,306,306,291,259 }; -254,-287,1329,1299,1314,1312,1057,1057,1042,1042,1026,1026,784,784,784,784,529,529,529,529,529,529,529,529,769,769,769,769,768,768,768,768,563,560,306,306,291,259,
static const drmp3_int16 tab7[] = { -252,-413,-477,-542,1298,-575,1041,1041,784,784,784,784,769,769,769,769,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,-383,-399,1107,1092,1106,1061,849,849,789,789,1104,1091,773,773,1076,1075,341,340,325,309,834,804,577,577,532,532,516,516,832,818,803,816,561,561,531,531,515,546,289,289,288,258 }; -252,-413,-477,-542,1298,-575,1041,1041,784,784,784,784,769,769,769,769,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,-383,-399,1107,1092,1106,1061,849,849,789,789,1104,1091,773,773,1076,1075,341,340,325,309,834,804,577,577,532,532,516,516,832,818,803,816,561,561,531,531,515,546,289,289,288,258,
static const drmp3_int16 tab8[] = { -252,-429,-493,-559,1057,1057,1042,1042,529,529,529,529,529,529,529,529,784,784,784,784,769,769,769,769,512,512,512,512,512,512,512,512,-382,1077,-415,1106,1061,1104,849,849,789,789,1091,1076,1029,1075,834,834,597,581,340,340,339,324,804,833,532,532,832,772,818,803,817,787,816,771,290,290,290,290,288,258 }; -252,-429,-493,-559,1057,1057,1042,1042,529,529,529,529,529,529,529,529,784,784,784,784,769,769,769,769,512,512,512,512,512,512,512,512,-382,1077,-415,1106,1061,1104,849,849,789,789,1091,1076,1029,1075,834,834,597,581,340,340,339,324,804,833,532,532,832,772,818,803,817,787,816,771,290,290,290,290,288,258,
static const drmp3_int16 tab9[] = { -253,-349,-414,-447,-463,1329,1299,-479,1314,1312,1057,1057,1042,1042,1026,1026,785,785,785,785,784,784,784,784,769,769,769,769,768,768,768,768,-319,851,821,-335,836,850,805,849,341,340,325,336,533,533,579,579,564,564,773,832,578,548,563,516,321,276,306,291,304,259 }; -253,-349,-414,-447,-463,1329,1299,-479,1314,1312,1057,1057,1042,1042,1026,1026,785,785,785,785,784,784,784,784,769,769,769,769,768,768,768,768,-319,851,821,-335,836,850,805,849,341,340,325,336,533,533,579,579,564,564,773,832,578,548,563,516,321,276,306,291,304,259,
static const drmp3_int16 tab10[] = { -251,-572,-733,-830,-863,-879,1041,1041,784,784,784,784,769,769,769,769,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,-511,-527,-543,1396,1351,1381,1366,1395,1335,1380,-559,1334,1138,1138,1063,1063,1350,1392,1031,1031,1062,1062,1364,1363,1120,1120,1333,1348,881,881,881,881,375,374,359,373,343,358,341,325,791,791,1123,1122,-703,1105,1045,-719,865,865,790,790,774,774,1104,1029,338,293,323,308,-799,-815,833,788,772,818,803,816,322,292,307,320,561,531,515,546,289,274,288,258 }; -251,-572,-733,-830,-863,-879,1041,1041,784,784,784,784,769,769,769,769,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,-511,-527,-543,1396,1351,1381,1366,1395,1335,1380,-559,1334,1138,1138,1063,1063,1350,1392,1031,1031,1062,1062,1364,1363,1120,1120,1333,1348,881,881,881,881,375,374,359,373,343,358,341,325,791,791,1123,1122,-703,1105,1045,-719,865,865,790,790,774,774,1104,1029,338,293,323,308,-799,-815,833,788,772,818,803,816,322,292,307,320,561,531,515,546,289,274,288,258,
static const drmp3_int16 tab11[] = { -251,-525,-605,-685,-765,-831,-846,1298,1057,1057,1312,1282,785,785,785,785,784,784,784,784,769,769,769,769,512,512,512,512,512,512,512,512,1399,1398,1383,1367,1382,1396,1351,-511,1381,1366,1139,1139,1079,1079,1124,1124,1364,1349,1363,1333,882,882,882,882,807,807,807,807,1094,1094,1136,1136,373,341,535,535,881,775,867,822,774,-591,324,338,-671,849,550,550,866,864,609,609,293,336,534,534,789,835,773,-751,834,804,308,307,833,788,832,772,562,562,547,547,305,275,560,515,290,290 }; -251,-525,-605,-685,-765,-831,-846,1298,1057,1057,1312,1282,785,785,785,785,784,784,784,784,769,769,769,769,512,512,512,512,512,512,512,512,1399,1398,1383,1367,1382,1396,1351,-511,1381,1366,1139,1139,1079,1079,1124,1124,1364,1349,1363,1333,882,882,882,882,807,807,807,807,1094,1094,1136,1136,373,341,535,535,881,775,867,822,774,-591,324,338,-671,849,550,550,866,864,609,609,293,336,534,534,789,835,773,-751,834,804,308,307,833,788,832,772,562,562,547,547,305,275,560,515,290,290,
static const drmp3_int16 tab12[] = { -252,-397,-477,-557,-622,-653,-719,-735,-750,1329,1299,1314,1057,1057,1042,1042,1312,1282,1024,1024,785,785,785,785,784,784,784,784,769,769,769,769,-383,1127,1141,1111,1126,1140,1095,1110,869,869,883,883,1079,1109,882,882,375,374,807,868,838,881,791,-463,867,822,368,263,852,837,836,-543,610,610,550,550,352,336,534,534,865,774,851,821,850,805,593,533,579,564,773,832,578,578,548,548,577,577,307,276,306,291,516,560,259,259 }; -252,-397,-477,-557,-622,-653,-719,-735,-750,1329,1299,1314,1057,1057,1042,1042,1312,1282,1024,1024,785,785,785,785,784,784,784,784,769,769,769,769,-383,1127,1141,1111,1126,1140,1095,1110,869,869,883,883,1079,1109,882,882,375,374,807,868,838,881,791,-463,867,822,368,263,852,837,836,-543,610,610,550,550,352,336,534,534,865,774,851,821,850,805,593,533,579,564,773,832,578,578,548,548,577,577,307,276,306,291,516,560,259,259,
static const drmp3_int16 tab13[] = { -250,-2107,-2507,-2764,-2909,-2974,-3007,-3023,1041,1041,1040,1040,769,769,769,769,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,-767,-1052,-1213,-1277,-1358,-1405,-1469,-1535,-1550,-1582,-1614,-1647,-1662,-1694,-1726,-1759,-1774,-1807,-1822,-1854,-1886,1565,-1919,-1935,-1951,-1967,1731,1730,1580,1717,-1983,1729,1564,-1999,1548,-2015,-2031,1715,1595,-2047,1714,-2063,1610,-2079,1609,-2095,1323,1323,1457,1457,1307,1307,1712,1547,1641,1700,1699,1594,1685,1625,1442,1442,1322,1322,-780,-973,-910,1279,1278,1277,1262,1276,1261,1275,1215,1260,1229,-959,974,974,989,989,-943,735,478,478,495,463,506,414,-1039,1003,958,1017,927,942,987,957,431,476,1272,1167,1228,-1183,1256,-1199,895,895,941,941,1242,1227,1212,1135,1014,1014,490,489,503,487,910,1013,985,925,863,894,970,955,1012,847,-1343,831,755,755,984,909,428,366,754,559,-1391,752,486,457,924,997,698,698,983,893,740,740,908,877,739,739,667,667,953,938,497,287,271,271,683,606,590,712,726,574,302,302,738,736,481,286,526,725,605,711,636,724,696,651,589,681,666,710,364,467,573,695,466,466,301,465,379,379,709,604,665,679,316,316,634,633,436,436,464,269,424,394,452,332,438,363,347,408,393,448,331,422,362,407,392,421,346,406,391,376,375,359,1441,1306,-2367,1290,-2383,1337,-2399,-2415,1426,1321,-2431,1411,1336,-2447,-2463,-2479,1169,1169,1049,1049,1424,1289,1412,1352,1319,-2495,1154,1154,1064,1064,1153,1153,416,390,360,404,403,389,344,374,373,343,358,372,327,357,342,311,356,326,1395,1394,1137,1137,1047,1047,1365,1392,1287,1379,1334,1364,1349,1378,1318,1363,792,792,792,792,1152,1152,1032,1032,1121,1121,1046,1046,1120,1120,1030,1030,-2895,1106,1061,1104,849,849,789,789,1091,1076,1029,1090,1060,1075,833,833,309,324,532,532,832,772,818,803,561,561,531,560,515,546,289,274,288,258 }; -250,-2107,-2507,-2764,-2909,-2974,-3007,-3023,1041,1041,1040,1040,769,769,769,769,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,-767,-1052,-1213,-1277,-1358,-1405,-1469,-1535,-1550,-1582,-1614,-1647,-1662,-1694,-1726,-1759,-1774,-1807,-1822,-1854,-1886,1565,-1919,-1935,-1951,-1967,1731,1730,1580,1717,-1983,1729,1564,-1999,1548,-2015,-2031,1715,1595,-2047,1714,-2063,1610,-2079,1609,-2095,1323,1323,1457,1457,1307,1307,1712,1547,1641,1700,1699,1594,1685,1625,1442,1442,1322,1322,-780,-973,-910,1279,1278,1277,1262,1276,1261,1275,1215,1260,1229,-959,974,974,989,989,-943,735,478,478,495,463,506,414,-1039,1003,958,1017,927,942,987,957,431,476,1272,1167,1228,-1183,1256,-1199,895,895,941,941,1242,1227,1212,1135,1014,1014,490,489,503,487,910,1013,985,925,863,894,970,955,1012,847,-1343,831,755,755,984,909,428,366,754,559,-1391,752,486,457,924,997,698,698,983,893,740,740,908,877,739,739,667,667,953,938,497,287,271,271,683,606,590,712,726,574,302,302,738,736,481,286,526,725,605,711,636,724,696,651,589,681,666,710,364,467,573,695,466,466,301,465,379,379,709,604,665,679,316,316,634,633,436,436,464,269,424,394,452,332,438,363,347,408,393,448,331,422,362,407,392,421,346,406,391,376,375,359,1441,1306,-2367,1290,-2383,1337,-2399,-2415,1426,1321,-2431,1411,1336,-2447,-2463,-2479,1169,1169,1049,1049,1424,1289,1412,1352,1319,-2495,1154,1154,1064,1064,1153,1153,416,390,360,404,403,389,344,374,373,343,358,372,327,357,342,311,356,326,1395,1394,1137,1137,1047,1047,1365,1392,1287,1379,1334,1364,1349,1378,1318,1363,792,792,792,792,1152,1152,1032,1032,1121,1121,1046,1046,1120,1120,1030,1030,-2895,1106,1061,1104,849,849,789,789,1091,1076,1029,1090,1060,1075,833,833,309,324,532,532,832,772,818,803,561,561,531,560,515,546,289,274,288,258,
static const drmp3_int16 tab15[] = { -250,-1179,-1579,-1836,-1996,-2124,-2253,-2333,-2413,-2477,-2542,-2574,-2607,-2622,-2655,1314,1313,1298,1312,1282,785,785,785,785,1040,1040,1025,1025,768,768,768,768,-766,-798,-830,-862,-895,-911,-927,-943,-959,-975,-991,-1007,-1023,-1039,-1055,-1070,1724,1647,-1103,-1119,1631,1767,1662,1738,1708,1723,-1135,1780,1615,1779,1599,1677,1646,1778,1583,-1151,1777,1567,1737,1692,1765,1722,1707,1630,1751,1661,1764,1614,1736,1676,1763,1750,1645,1598,1721,1691,1762,1706,1582,1761,1566,-1167,1749,1629,767,766,751,765,494,494,735,764,719,749,734,763,447,447,748,718,477,506,431,491,446,476,461,505,415,430,475,445,504,399,460,489,414,503,383,474,429,459,502,502,746,752,488,398,501,473,413,472,486,271,480,270,-1439,-1455,1357,-1471,-1487,-1503,1341,1325,-1519,1489,1463,1403,1309,-1535,1372,1448,1418,1476,1356,1462,1387,-1551,1475,1340,1447,1402,1386,-1567,1068,1068,1474,1461,455,380,468,440,395,425,410,454,364,467,466,464,453,269,409,448,268,432,1371,1473,1432,1417,1308,1460,1355,1446,1459,1431,1083,1083,1401,1416,1458,1445,1067,1067,1370,1457,1051,1051,1291,1430,1385,1444,1354,1415,1400,1443,1082,1082,1173,1113,1186,1066,1185,1050,-1967,1158,1128,1172,1097,1171,1081,-1983,1157,1112,416,266,375,400,1170,1142,1127,1065,793,793,1169,1033,1156,1096,1141,1111,1155,1080,1126,1140,898,898,808,808,897,897,792,792,1095,1152,1032,1125,1110,1139,1079,1124,882,807,838,881,853,791,-2319,867,368,263,822,852,837,866,806,865,-2399,851,352,262,534,534,821,836,594,594,549,549,593,593,533,533,848,773,579,579,564,578,548,563,276,276,577,576,306,291,516,560,305,305,275,259 }; -250,-1179,-1579,-1836,-1996,-2124,-2253,-2333,-2413,-2477,-2542,-2574,-2607,-2622,-2655,1314,1313,1298,1312,1282,785,785,785,785,1040,1040,1025,1025,768,768,768,768,-766,-798,-830,-862,-895,-911,-927,-943,-959,-975,-991,-1007,-1023,-1039,-1055,-1070,1724,1647,-1103,-1119,1631,1767,1662,1738,1708,1723,-1135,1780,1615,1779,1599,1677,1646,1778,1583,-1151,1777,1567,1737,1692,1765,1722,1707,1630,1751,1661,1764,1614,1736,1676,1763,1750,1645,1598,1721,1691,1762,1706,1582,1761,1566,-1167,1749,1629,767,766,751,765,494,494,735,764,719,749,734,763,447,447,748,718,477,506,431,491,446,476,461,505,415,430,475,445,504,399,460,489,414,503,383,474,429,459,502,502,746,752,488,398,501,473,413,472,486,271,480,270,-1439,-1455,1357,-1471,-1487,-1503,1341,1325,-1519,1489,1463,1403,1309,-1535,1372,1448,1418,1476,1356,1462,1387,-1551,1475,1340,1447,1402,1386,-1567,1068,1068,1474,1461,455,380,468,440,395,425,410,454,364,467,466,464,453,269,409,448,268,432,1371,1473,1432,1417,1308,1460,1355,1446,1459,1431,1083,1083,1401,1416,1458,1445,1067,1067,1370,1457,1051,1051,1291,1430,1385,1444,1354,1415,1400,1443,1082,1082,1173,1113,1186,1066,1185,1050,-1967,1158,1128,1172,1097,1171,1081,-1983,1157,1112,416,266,375,400,1170,1142,1127,1065,793,793,1169,1033,1156,1096,1141,1111,1155,1080,1126,1140,898,898,808,808,897,897,792,792,1095,1152,1032,1125,1110,1139,1079,1124,882,807,838,881,853,791,-2319,867,368,263,822,852,837,866,806,865,-2399,851,352,262,534,534,821,836,594,594,549,549,593,593,533,533,848,773,579,579,564,578,548,563,276,276,577,576,306,291,516,560,305,305,275,259,
static const drmp3_int16 tab16[] = { -251,-892,-2058,-2620,-2828,-2957,-3023,-3039,1041,1041,1040,1040,769,769,769,769,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,-511,-527,-543,-559,1530,-575,-591,1528,1527,1407,1526,1391,1023,1023,1023,1023,1525,1375,1268,1268,1103,1103,1087,1087,1039,1039,1523,-604,815,815,815,815,510,495,509,479,508,463,507,447,431,505,415,399,-734,-782,1262,-815,1259,1244,-831,1258,1228,-847,-863,1196,-879,1253,987,987,748,-767,493,493,462,477,414,414,686,669,478,446,461,445,474,429,487,458,412,471,1266,1264,1009,1009,799,799,-1019,-1276,-1452,-1581,-1677,-1757,-1821,-1886,-1933,-1997,1257,1257,1483,1468,1512,1422,1497,1406,1467,1496,1421,1510,1134,1134,1225,1225,1466,1451,1374,1405,1252,1252,1358,1480,1164,1164,1251,1251,1238,1238,1389,1465,-1407,1054,1101,-1423,1207,-1439,830,830,1248,1038,1237,1117,1223,1148,1236,1208,411,426,395,410,379,269,1193,1222,1132,1235,1221,1116,976,976,1192,1162,1177,1220,1131,1191,963,963,-1647,961,780,-1663,558,558,994,993,437,408,393,407,829,978,813,797,947,-1743,721,721,377,392,844,950,828,890,706,706,812,859,796,960,948,843,934,874,571,571,-1919,690,555,689,421,346,539,539,944,779,918,873,932,842,903,888,570,570,931,917,674,674,-2575,1562,-2591,1609,-2607,1654,1322,1322,1441,1441,1696,1546,1683,1593,1669,1624,1426,1426,1321,1321,1639,1680,1425,1425,1305,1305,1545,1668,1608,1623,1667,1592,1638,1666,1320,1320,1652,1607,1409,1409,1304,1304,1288,1288,1664,1637,1395,1395,1335,1335,1622,1636,1394,1394,1319,1319,1606,1621,1392,1392,1137,1137,1137,1137,345,390,360,375,404,373,1047,-2751,-2767,-2783,1062,1121,1046,-2799,1077,-2815,1106,1061,789,789,1105,1104,263,355,310,340,325,354,352,262,339,324,1091,1076,1029,1090,1060,1075,833,833,788,788,1088,1028,818,818,803,803,561,561,531,531,816,771,546,546,289,274,288,258 }; -251,-892,-2058,-2620,-2828,-2957,-3023,-3039,1041,1041,1040,1040,769,769,769,769,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,-511,-527,-543,-559,1530,-575,-591,1528,1527,1407,1526,1391,1023,1023,1023,1023,1525,1375,1268,1268,1103,1103,1087,1087,1039,1039,1523,-604,815,815,815,815,510,495,509,479,508,463,507,447,431,505,415,399,-734,-782,1262,-815,1259,1244,-831,1258,1228,-847,-863,1196,-879,1253,987,987,748,-767,493,493,462,477,414,414,686,669,478,446,461,445,474,429,487,458,412,471,1266,1264,1009,1009,799,799,-1019,-1276,-1452,-1581,-1677,-1757,-1821,-1886,-1933,-1997,1257,1257,1483,1468,1512,1422,1497,1406,1467,1496,1421,1510,1134,1134,1225,1225,1466,1451,1374,1405,1252,1252,1358,1480,1164,1164,1251,1251,1238,1238,1389,1465,-1407,1054,1101,-1423,1207,-1439,830,830,1248,1038,1237,1117,1223,1148,1236,1208,411,426,395,410,379,269,1193,1222,1132,1235,1221,1116,976,976,1192,1162,1177,1220,1131,1191,963,963,-1647,961,780,-1663,558,558,994,993,437,408,393,407,829,978,813,797,947,-1743,721,721,377,392,844,950,828,890,706,706,812,859,796,960,948,843,934,874,571,571,-1919,690,555,689,421,346,539,539,944,779,918,873,932,842,903,888,570,570,931,917,674,674,-2575,1562,-2591,1609,-2607,1654,1322,1322,1441,1441,1696,1546,1683,1593,1669,1624,1426,1426,1321,1321,1639,1680,1425,1425,1305,1305,1545,1668,1608,1623,1667,1592,1638,1666,1320,1320,1652,1607,1409,1409,1304,1304,1288,1288,1664,1637,1395,1395,1335,1335,1622,1636,1394,1394,1319,1319,1606,1621,1392,1392,1137,1137,1137,1137,345,390,360,375,404,373,1047,-2751,-2767,-2783,1062,1121,1046,-2799,1077,-2815,1106,1061,789,789,1105,1104,263,355,310,340,325,354,352,262,339,324,1091,1076,1029,1090,1060,1075,833,833,788,788,1088,1028,818,818,803,803,561,561,531,531,816,771,546,546,289,274,288,258,
static const drmp3_int16 tab24[] = { -253,-317,-381,-446,-478,-509,1279,1279,-811,-1179,-1451,-1756,-1900,-2028,-2189,-2253,-2333,-2414,-2445,-2511,-2526,1313,1298,-2559,1041,1041,1040,1040,1025,1025,1024,1024,1022,1007,1021,991,1020,975,1019,959,687,687,1018,1017,671,671,655,655,1016,1015,639,639,758,758,623,623,757,607,756,591,755,575,754,559,543,543,1009,783,-575,-621,-685,-749,496,-590,750,749,734,748,974,989,1003,958,988,973,1002,942,987,957,972,1001,926,986,941,971,956,1000,910,985,925,999,894,970,-1071,-1087,-1102,1390,-1135,1436,1509,1451,1374,-1151,1405,1358,1480,1420,-1167,1507,1494,1389,1342,1465,1435,1450,1326,1505,1310,1493,1373,1479,1404,1492,1464,1419,428,443,472,397,736,526,464,464,486,457,442,471,484,482,1357,1449,1434,1478,1388,1491,1341,1490,1325,1489,1463,1403,1309,1477,1372,1448,1418,1433,1476,1356,1462,1387,-1439,1475,1340,1447,1402,1474,1324,1461,1371,1473,269,448,1432,1417,1308,1460,-1711,1459,-1727,1441,1099,1099,1446,1386,1431,1401,-1743,1289,1083,1083,1160,1160,1458,1445,1067,1067,1370,1457,1307,1430,1129,1129,1098,1098,268,432,267,416,266,400,-1887,1144,1187,1082,1173,1113,1186,1066,1050,1158,1128,1143,1172,1097,1171,1081,420,391,1157,1112,1170,1142,1127,1065,1169,1049,1156,1096,1141,1111,1155,1080,1126,1154,1064,1153,1140,1095,1048,-2159,1125,1110,1137,-2175,823,823,1139,1138,807,807,384,264,368,263,868,838,853,791,867,822,852,837,866,806,865,790,-2319,851,821,836,352,262,850,805,849,-2399,533,533,835,820,336,261,578,548,563,577,532,532,832,772,562,562,547,547,305,275,560,515,290,290,288,258 }; -253,-317,-381,-446,-478,-509,1279,1279,-811,-1179,-1451,-1756,-1900,-2028,-2189,-2253,-2333,-2414,-2445,-2511,-2526,1313,1298,-2559,1041,1041,1040,1040,1025,1025,1024,1024,1022,1007,1021,991,1020,975,1019,959,687,687,1018,1017,671,671,655,655,1016,1015,639,639,758,758,623,623,757,607,756,591,755,575,754,559,543,543,1009,783,-575,-621,-685,-749,496,-590,750,749,734,748,974,989,1003,958,988,973,1002,942,987,957,972,1001,926,986,941,971,956,1000,910,985,925,999,894,970,-1071,-1087,-1102,1390,-1135,1436,1509,1451,1374,-1151,1405,1358,1480,1420,-1167,1507,1494,1389,1342,1465,1435,1450,1326,1505,1310,1493,1373,1479,1404,1492,1464,1419,428,443,472,397,736,526,464,464,486,457,442,471,484,482,1357,1449,1434,1478,1388,1491,1341,1490,1325,1489,1463,1403,1309,1477,1372,1448,1418,1433,1476,1356,1462,1387,-1439,1475,1340,1447,1402,1474,1324,1461,1371,1473,269,448,1432,1417,1308,1460,-1711,1459,-1727,1441,1099,1099,1446,1386,1431,1401,-1743,1289,1083,1083,1160,1160,1458,1445,1067,1067,1370,1457,1307,1430,1129,1129,1098,1098,268,432,267,416,266,400,-1887,1144,1187,1082,1173,1113,1186,1066,1050,1158,1128,1143,1172,1097,1171,1081,420,391,1157,1112,1170,1142,1127,1065,1169,1049,1156,1096,1141,1111,1155,1080,1126,1154,1064,1153,1140,1095,1048,-2159,1125,1110,1137,-2175,823,823,1139,1138,807,807,384,264,368,263,868,838,853,791,867,822,852,837,866,806,865,790,-2319,851,821,836,352,262,850,805,849,-2399,533,533,835,820,336,261,578,548,563,577,532,532,832,772,562,562,547,547,305,275,560,515,290,290,288,258 };
static const drmp3_uint8 tab32[] = { 130,162,193,209,44,28,76,140,9,9,9,9,9,9,9,9,190,254,222,238,126,94,157,157,109,61,173,205}; static const drmp3_uint8 tab32[] = { 130,162,193,209,44,28,76,140,9,9,9,9,9,9,9,9,190,254,222,238,126,94,157,157,109,61,173,205};
static const drmp3_uint8 tab33[] = { 252,236,220,204,188,172,156,140,124,108,92,76,60,44,28,12 }; static const drmp3_uint8 tab33[] = { 252,236,220,204,188,172,156,140,124,108,92,76,60,44,28,12 };
static const drmp3_int16 * const tabindex[2*16] = { tab0,tab1,tab2,tab3,tab0,tab5,tab6,tab7,tab8,tab9,tab10,tab11,tab12,tab13,tab0,tab15,tab16,tab16,tab16,tab16,tab16,tab16,tab16,tab16,tab24,tab24,tab24,tab24,tab24,tab24,tab24,tab24 }; static const drmp3_int16 tabindex[2*16] = { 0,32,64,98,0,132,180,218,292,364,426,538,648,746,0,1126,1460,1460,1460,1460,1460,1460,1460,1460,1842,1842,1842,1842,1842,1842,1842,1842 };
static const drmp3_uint8 g_linbits[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,3,4,6,8,10,13,4,5,6,7,8,9,11,13 }; static const drmp3_uint8 g_linbits[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,3,4,6,8,10,13,4,5,6,7,8,9,11,13 };
#define DRMP3_PEEK_BITS(n) (bs_cache >> (32 - n)) #define DRMP3_PEEK_BITS(n) (bs_cache >> (32 - n))
...@@ -1055,7 +1053,7 @@ static void drmp3_L3_huffman(float *dst, drmp3_bs *bs, const drmp3_L3_gr_info *g ...@@ -1055,7 +1053,7 @@ static void drmp3_L3_huffman(float *dst, drmp3_bs *bs, const drmp3_L3_gr_info *g
{ {
int tab_num = gr_info->table_select[ireg]; int tab_num = gr_info->table_select[ireg];
int sfb_cnt = gr_info->region_count[ireg++]; int sfb_cnt = gr_info->region_count[ireg++];
const short *codebook = tabindex[tab_num]; const short *codebook = tabs + tabindex[tab_num];
int linbits = g_linbits[tab_num]; int linbits = g_linbits[tab_num];
do do
{ {
...@@ -2773,6 +2771,9 @@ void drmp3_free(void* p) ...@@ -2773,6 +2771,9 @@ void drmp3_free(void* p)
// REVISION HISTORY // REVISION HISTORY
// =============== // ===============
// //
// v0.2.5 - 2018-06-22
// - Bring up to date with minimp3.
//
// v0.2.4 - 2018-05-12 // v0.2.4 - 2018-05-12
// - Bring up to date with minimp3. // - Bring up to date with minimp3.
// //
......
// WAV audio loader and writer. Public domain. See "unlicense" statement at the end of this file. // WAV audio loader and writer. Public domain. See "unlicense" statement at the end of this file.
// dr_wav - v0.8 - 2018-04-27 // dr_wav - v0.8.1 - 2018-06-29
// //
// David Reid - mackron@gmail.com // David Reid - mackron@gmail.com
...@@ -50,7 +50,7 @@ ...@@ -50,7 +50,7 @@
// drwav_free(pSampleData); // drwav_free(pSampleData);
// //
// The examples above use versions of the API that convert the audio data to a consistent format (32-bit signed PCM, in // The examples above use versions of the API that convert the audio data to a consistent format (32-bit signed PCM, in
// this case), but you can still output the audio data in it's internal format (see notes below for supported formats): // this case), but you can still output the audio data in its internal format (see notes below for supported formats):
// //
// size_t samplesRead = drwav_read(&wav, wav.totalSampleCount, pDecodedInterleavedSamples); // size_t samplesRead = drwav_read(&wav, wav.totalSampleCount, pDecodedInterleavedSamples);
// //
...@@ -246,7 +246,7 @@ typedef struct ...@@ -246,7 +246,7 @@ typedef struct
// Block align. This is equal to the number of channels * bytes per sample. // Block align. This is equal to the number of channels * bytes per sample.
drwav_uint16 blockAlign; drwav_uint16 blockAlign;
// Bit's per sample. // Bits per sample.
drwav_uint16 bitsPerSample; drwav_uint16 bitsPerSample;
// The size of the extended data. Only used internally for validation, but left here for informational purposes. // The size of the extended data. Only used internally for validation, but left here for informational purposes.
...@@ -292,7 +292,7 @@ typedef struct ...@@ -292,7 +292,7 @@ typedef struct
// The number of channels. This will be set to 1 for monaural streams, 2 for stereo, etc. // The number of channels. This will be set to 1 for monaural streams, 2 for stereo, etc.
drwav_uint16 channels; drwav_uint16 channels;
// The bits per sample. Will be set to somthing like 16, 24, etc. // The bits per sample. Will be set to something like 16, 24, etc.
drwav_uint16 bitsPerSample; drwav_uint16 bitsPerSample;
// The number of bytes per sample. // The number of bytes per sample.
...@@ -316,6 +316,14 @@ typedef struct ...@@ -316,6 +316,14 @@ typedef struct
drwav_uint64 bytesRemaining; drwav_uint64 bytesRemaining;
// Only used in sequential write mode. Keeps track of the desired size of the "data" chunk at the point of initialization time. Always
// set to 0 for non-sequential writes and when the drwav object is opened in read mode. Used for validation.
drwav_uint64 dataChunkDataSizeTargetWrite;
// Keeps track of whether or not the wav writer was initialized in sequential mode.
drwav_bool32 isSequentialWrite;
// A hack to avoid a DRWAV_MALLOC() when opening a decoder with drwav_open_memory(). // A hack to avoid a DRWAV_MALLOC() when opening a decoder with drwav_open_memory().
drwav__memory_stream memoryStream; drwav__memory_stream memoryStream;
drwav__memory_stream_write memoryStreamWrite; drwav__memory_stream_write memoryStreamWrite;
...@@ -381,11 +389,15 @@ drwav_bool32 drwav_init(drwav* pWav, drwav_read_proc onRead, drwav_seek_proc onS ...@@ -381,11 +389,15 @@ drwav_bool32 drwav_init(drwav* pWav, drwav_read_proc onRead, drwav_seek_proc onS
// This is the lowest level function for initializing a WAV file. You can also use drwav_init_file() and drwav_init_memory() // This is the lowest level function for initializing a WAV file. You can also use drwav_init_file() and drwav_init_memory()
// to open the stream from a file or from a block of memory respectively. // to open the stream from a file or from a block of memory respectively.
// //
// If the total sample count is known, you can use drwav_init_write_sequential(). This avoids the need for dr_wav to perform
// a post-processing step for storing the total sample count and the size of the data chunk which requires a backwards seek.
//
// If you want dr_wav to manage the memory allocation for you, consider using drwav_open() instead. This will allocate // If you want dr_wav to manage the memory allocation for you, consider using drwav_open() instead. This will allocate
// a drwav object on the heap and return a pointer to it. // a drwav object on the heap and return a pointer to it.
// //
// See also: drwav_init_file_write(), drwav_init_memory_write(), drwav_uninit() // See also: drwav_init_file_write(), drwav_init_memory_write(), drwav_uninit()
drwav_bool32 drwav_init_write(drwav* pWav, const drwav_data_format* pFormat, drwav_write_proc onWrite, drwav_seek_proc onSeek, void* pUserData); drwav_bool32 drwav_init_write(drwav* pWav, const drwav_data_format* pFormat, drwav_write_proc onWrite, drwav_seek_proc onSeek, void* pUserData);
drwav_bool32 drwav_init_write_sequential(drwav* pWav, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount, drwav_write_proc onWrite, void* pUserData);
// Uninitializes the given drwav object. // Uninitializes the given drwav object.
// //
...@@ -403,8 +415,8 @@ void drwav_uninit(drwav* pWav); ...@@ -403,8 +415,8 @@ void drwav_uninit(drwav* pWav);
// //
// Close the loader with drwav_close(). // Close the loader with drwav_close().
// //
// This is the lowest level function for opening a WAV file. You can also use drwav_open_file() and drwav_open_memory() // You can also use drwav_open_file() and drwav_open_memory() to open the stream from a file or from a block of
// to open the stream from a file or from a block of memory respectively. // memory respectively.
// //
// This is different from drwav_init() in that it will allocate the drwav object for you via DRWAV_MALLOC() before // This is different from drwav_init() in that it will allocate the drwav object for you via DRWAV_MALLOC() before
// initializing it. // initializing it.
...@@ -422,14 +434,15 @@ drwav* drwav_open(drwav_read_proc onRead, drwav_seek_proc onSeek, void* pUserDat ...@@ -422,14 +434,15 @@ drwav* drwav_open(drwav_read_proc onRead, drwav_seek_proc onSeek, void* pUserDat
// //
// Close the loader with drwav_close(). // Close the loader with drwav_close().
// //
// This is the lowest level function for opening a WAV file. You can also use drwav_open_file_write() and drwav_open_memory_write() // You can also use drwav_open_file_write() and drwav_open_memory_write() to open the stream from a file or from a block
// to open the stream from a file or from a block of memory respectively. // of memory respectively.
// //
// This is different from drwav_init_write() in that it will allocate the drwav object for you via DRWAV_MALLOC() before // This is different from drwav_init_write() in that it will allocate the drwav object for you via DRWAV_MALLOC() before
// initializing it. // initializing it.
// //
// See also: drwav_open_file_write(), drwav_open_memory_write(), drwav_close() // See also: drwav_open_file_write(), drwav_open_memory_write(), drwav_close()
drwav* drwav_open_write(const drwav_data_format* pFormat, drwav_write_proc onWrite, drwav_seek_proc onSeek, void* pUserData); drwav* drwav_open_write(const drwav_data_format* pFormat, drwav_write_proc onWrite, drwav_seek_proc onSeek, void* pUserData);
drwav* drwav_open_write_sequential(const drwav_data_format* pFormat, drwav_uint64 totalSampleCount, drwav_write_proc onWrite, void* pUserData);
// Uninitializes and deletes the the given drwav object. // Uninitializes and deletes the the given drwav object.
// //
...@@ -478,7 +491,7 @@ drwav_uint64 drwav_write(drwav* pWav, drwav_uint64 samplesToWrite, const void* p ...@@ -478,7 +491,7 @@ drwav_uint64 drwav_write(drwav* pWav, drwav_uint64 samplesToWrite, const void* p
//// Convertion Utilities //// //// Conversion Utilities ////
#ifndef DR_WAV_NO_CONVERSION_API #ifndef DR_WAV_NO_CONVERSION_API
// Reads a chunk of audio data and converts it to signed 16-bit PCM samples. // Reads a chunk of audio data and converts it to signed 16-bit PCM samples.
...@@ -587,6 +600,7 @@ drwav_bool32 drwav_init_file(drwav* pWav, const char* filename); ...@@ -587,6 +600,7 @@ drwav_bool32 drwav_init_file(drwav* pWav, const char* filename);
// objects because the operating system may restrict the number of file handles an application can have open at // objects because the operating system may restrict the number of file handles an application can have open at
// any given time. // any given time.
drwav_bool32 drwav_init_file_write(drwav* pWav, const char* filename, const drwav_data_format* pFormat); drwav_bool32 drwav_init_file_write(drwav* pWav, const char* filename, const drwav_data_format* pFormat);
drwav_bool32 drwav_init_file_write_sequential(drwav* pWav, const char* filename, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount);
// Helper for opening a wave file using stdio. // Helper for opening a wave file using stdio.
// //
...@@ -601,6 +615,7 @@ drwav* drwav_open_file(const char* filename); ...@@ -601,6 +615,7 @@ drwav* drwav_open_file(const char* filename);
// objects because the operating system may restrict the number of file handles an application can have open at // objects because the operating system may restrict the number of file handles an application can have open at
// any given time. // any given time.
drwav* drwav_open_file_write(const char* filename, const drwav_data_format* pFormat); drwav* drwav_open_file_write(const char* filename, const drwav_data_format* pFormat);
drwav* drwav_open_file_write_sequential(const char* filename, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount);
#endif //DR_WAV_NO_STDIO #endif //DR_WAV_NO_STDIO
...@@ -619,6 +634,7 @@ drwav_bool32 drwav_init_memory(drwav* pWav, const void* data, size_t dataSize); ...@@ -619,6 +634,7 @@ drwav_bool32 drwav_init_memory(drwav* pWav, const void* data, size_t dataSize);
// The buffer will remain allocated even after drwav_uninit() is called. Indeed, the buffer should not be // The buffer will remain allocated even after drwav_uninit() is called. Indeed, the buffer should not be
// considered valid until after drwav_uninit() has been called anyway. // considered valid until after drwav_uninit() has been called anyway.
drwav_bool32 drwav_init_memory_write(drwav* pWav, void** ppData, size_t* pDataSize, const drwav_data_format* pFormat); drwav_bool32 drwav_init_memory_write(drwav* pWav, void** ppData, size_t* pDataSize, const drwav_data_format* pFormat);
drwav_bool32 drwav_init_memory_write_sequential(drwav* pWav, void** ppData, size_t* pDataSize, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount);
// Helper for opening a loader from a pre-allocated memory buffer. // Helper for opening a loader from a pre-allocated memory buffer.
// //
...@@ -635,6 +651,7 @@ drwav* drwav_open_memory(const void* data, size_t dataSize); ...@@ -635,6 +651,7 @@ drwav* drwav_open_memory(const void* data, size_t dataSize);
// The buffer will remain allocated even after drwav_close() is called. Indeed, the buffer should not be // The buffer will remain allocated even after drwav_close() is called. Indeed, the buffer should not be
// considered valid until after drwav_close() has been called anyway. // considered valid until after drwav_close() has been called anyway.
drwav* drwav_open_memory_write(void** ppData, size_t* pDataSize, const drwav_data_format* pFormat); drwav* drwav_open_memory_write(void** ppData, size_t* pDataSize, const drwav_data_format* pFormat);
drwav* drwav_open_memory_write_sequential(void** ppData, size_t* pDataSize, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount);
#ifndef DR_WAV_NO_CONVERSION_API #ifndef DR_WAV_NO_CONVERSION_API
...@@ -822,6 +839,8 @@ static DRWAV_INLINE drwav_bool32 drwav__is_compressed_format_tag(drwav_uint16 fo ...@@ -822,6 +839,8 @@ static DRWAV_INLINE drwav_bool32 drwav__is_compressed_format_tag(drwav_uint16 fo
drwav_uint64 drwav_read_s16__msadpcm(drwav* pWav, drwav_uint64 samplesToRead, drwav_int16* pBufferOut); drwav_uint64 drwav_read_s16__msadpcm(drwav* pWav, drwav_uint64 samplesToRead, drwav_int16* pBufferOut);
drwav_uint64 drwav_read_s16__ima(drwav* pWav, drwav_uint64 samplesToRead, drwav_int16* pBufferOut); drwav_uint64 drwav_read_s16__ima(drwav* pWav, drwav_uint64 samplesToRead, drwav_int16* pBufferOut);
drwav_bool32 drwav_init_write__internal(drwav* pWav, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount, drwav_bool32 isSequential, drwav_write_proc onWrite, drwav_seek_proc onSeek, void* pUserData);
drwav* drwav_open_write__internal(const drwav_data_format* pFormat, drwav_uint64 totalSampleCount, drwav_bool32 isSequential, drwav_write_proc onWrite, drwav_seek_proc onSeek, void* pUserData);
typedef struct typedef struct
{ {
...@@ -867,7 +886,7 @@ static drwav_bool32 drwav__read_chunk_header(drwav_read_proc onRead, void* pUser ...@@ -867,7 +886,7 @@ static drwav_bool32 drwav__read_chunk_header(drwav_read_proc onRead, void* pUser
pHeaderOut->sizeInBytes = drwav__bytes_to_u64(sizeInBytes) - 24; // <-- Subtract 24 because w64 includes the size of the header. pHeaderOut->sizeInBytes = drwav__bytes_to_u64(sizeInBytes) - 24; // <-- Subtract 24 because w64 includes the size of the header.
pHeaderOut->paddingSize = (unsigned int)(pHeaderOut->sizeInBytes % 8); pHeaderOut->paddingSize = (unsigned int)(pHeaderOut->sizeInBytes % 8);
pRunningBytesReadOut += 24; *pRunningBytesReadOut += 24;
} }
return DRWAV_TRUE; return DRWAV_TRUE;
...@@ -999,6 +1018,23 @@ static drwav_bool32 drwav__read_fmt(drwav_read_proc onRead, drwav_seek_proc onSe ...@@ -999,6 +1018,23 @@ static drwav_bool32 drwav__read_fmt(drwav_read_proc onRead, drwav_seek_proc onSe
#ifndef DR_WAV_NO_STDIO #ifndef DR_WAV_NO_STDIO
FILE* drwav_fopen(const char* filePath, const char* openMode)
{
FILE* pFile;
#if defined(_MSC_VER) && _MSC_VER >= 1400
if (fopen_s(&pFile, filePath, openMode) != 0) {
return DRWAV_FALSE;
}
#else
pFile = fopen(filePath, openMode);
if (pFile == NULL) {
return DRWAV_FALSE;
}
#endif
return pFile;
}
static size_t drwav__on_read_stdio(void* pUserData, void* pBufferOut, size_t bytesToRead) static size_t drwav__on_read_stdio(void* pUserData, void* pBufferOut, size_t bytesToRead)
{ {
return fread(pBufferOut, 1, bytesToRead, (FILE*)pUserData); return fread(pBufferOut, 1, bytesToRead, (FILE*)pUserData);
...@@ -1016,51 +1052,41 @@ static drwav_bool32 drwav__on_seek_stdio(void* pUserData, int offset, drwav_seek ...@@ -1016,51 +1052,41 @@ static drwav_bool32 drwav__on_seek_stdio(void* pUserData, int offset, drwav_seek
drwav_bool32 drwav_init_file(drwav* pWav, const char* filename) drwav_bool32 drwav_init_file(drwav* pWav, const char* filename)
{ {
FILE* pFile; FILE* pFile = drwav_fopen(filename, "rb");
#if defined(_MSC_VER) && _MSC_VER >= 1400
if (fopen_s(&pFile, filename, "rb") != 0) {
return DRWAV_FALSE;
}
#else
pFile = fopen(filename, "rb");
if (pFile == NULL) { if (pFile == NULL) {
return DRWAV_FALSE; return DRWAV_FALSE;
} }
#endif
return drwav_init(pWav, drwav__on_read_stdio, drwav__on_seek_stdio, (void*)pFile); return drwav_init(pWav, drwav__on_read_stdio, drwav__on_seek_stdio, (void*)pFile);
} }
drwav_bool32 drwav_init_file_write(drwav* pWav, const char* filename, const drwav_data_format* pFormat)
drwav_bool32 drwav_init_file_write__internal(drwav* pWav, const char* filename, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount, drwav_bool32 isSequential)
{ {
FILE* pFile; FILE* pFile = drwav_fopen(filename, "wb");
#if defined(_MSC_VER) && _MSC_VER >= 1400
if (fopen_s(&pFile, filename, "wb") != 0) {
return DRWAV_FALSE;
}
#else
pFile = fopen(filename, "wb");
if (pFile == NULL) { if (pFile == NULL) {
return DRWAV_FALSE; return DRWAV_FALSE;
} }
#endif
return drwav_init_write(pWav, pFormat, drwav__on_write_stdio, drwav__on_seek_stdio, (void*)pFile); return drwav_init_write__internal(pWav, pFormat, totalSampleCount, isSequential, drwav__on_write_stdio, drwav__on_seek_stdio, (void*)pFile);
}
drwav_bool32 drwav_init_file_write(drwav* pWav, const char* filename, const drwav_data_format* pFormat)
{
return drwav_init_file_write__internal(pWav, filename, pFormat, 0, DRWAV_FALSE);
}
drwav_bool32 drwav_init_file_write_sequential(drwav* pWav, const char* filename, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount)
{
return drwav_init_file_write__internal(pWav, filename, pFormat, totalSampleCount, DRWAV_TRUE);
} }
drwav* drwav_open_file(const char* filename) drwav* drwav_open_file(const char* filename)
{ {
FILE* pFile; FILE* pFile = drwav_fopen(filename, "rb");
#if defined(_MSC_VER) && _MSC_VER >= 1400
if (fopen_s(&pFile, filename, "rb") != 0) {
return NULL;
}
#else
pFile = fopen(filename, "rb");
if (pFile == NULL) { if (pFile == NULL) {
return NULL; return DRWAV_FALSE;
} }
#endif
drwav* pWav = drwav_open(drwav__on_read_stdio, drwav__on_seek_stdio, (void*)pFile); drwav* pWav = drwav_open(drwav__on_read_stdio, drwav__on_seek_stdio, (void*)pFile);
if (pWav == NULL) { if (pWav == NULL) {
...@@ -1071,21 +1097,15 @@ drwav* drwav_open_file(const char* filename) ...@@ -1071,21 +1097,15 @@ drwav* drwav_open_file(const char* filename)
return pWav; return pWav;
} }
drwav* drwav_open_file_write(const char* filename, const drwav_data_format* pFormat)
drwav* drwav_open_file_write__internal(const char* filename, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount, drwav_bool32 isSequential)
{ {
FILE* pFile; FILE* pFile = drwav_fopen(filename, "wb");
#if defined(_MSC_VER) && _MSC_VER >= 1400
if (fopen_s(&pFile, filename, "wb") != 0) {
return NULL;
}
#else
pFile = fopen(filename, "wb");
if (pFile == NULL) { if (pFile == NULL) {
return NULL; return DRWAV_FALSE;
} }
#endif
drwav* pWav = drwav_open_write(pFormat, drwav__on_write_stdio, drwav__on_seek_stdio, (void*)pFile); drwav* pWav = drwav_open_write__internal(pFormat, totalSampleCount, isSequential, drwav__on_write_stdio, drwav__on_seek_stdio, (void*)pFile);
if (pWav == NULL) { if (pWav == NULL) {
fclose(pFile); fclose(pFile);
return NULL; return NULL;
...@@ -1093,6 +1113,16 @@ drwav* drwav_open_file_write(const char* filename, const drwav_data_format* pFor ...@@ -1093,6 +1113,16 @@ drwav* drwav_open_file_write(const char* filename, const drwav_data_format* pFor
return pWav; return pWav;
} }
drwav* drwav_open_file_write(const char* filename, const drwav_data_format* pFormat)
{
return drwav_open_file_write__internal(filename, pFormat, 0, DRWAV_FALSE);
}
drwav* drwav_open_file_write_sequential(const char* filename, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount)
{
return drwav_open_file_write__internal(filename, pFormat, totalSampleCount, DRWAV_TRUE);
}
#endif //DR_WAV_NO_STDIO #endif //DR_WAV_NO_STDIO
...@@ -1232,7 +1262,8 @@ drwav_bool32 drwav_init_memory(drwav* pWav, const void* data, size_t dataSize) ...@@ -1232,7 +1262,8 @@ drwav_bool32 drwav_init_memory(drwav* pWav, const void* data, size_t dataSize)
return DRWAV_TRUE; return DRWAV_TRUE;
} }
drwav_bool32 drwav_init_memory_write(drwav* pWav, void** ppData, size_t* pDataSize, const drwav_data_format* pFormat)
drwav_bool32 drwav_init_memory_write__internal(drwav* pWav, void** ppData, size_t* pDataSize, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount, drwav_bool32 isSequential)
{ {
if (ppData == NULL) { if (ppData == NULL) {
return DRWAV_FALSE; return DRWAV_FALSE;
...@@ -1249,7 +1280,7 @@ drwav_bool32 drwav_init_memory_write(drwav* pWav, void** ppData, size_t* pDataSi ...@@ -1249,7 +1280,7 @@ drwav_bool32 drwav_init_memory_write(drwav* pWav, void** ppData, size_t* pDataSi
memoryStreamWrite.dataCapacity = 0; memoryStreamWrite.dataCapacity = 0;
memoryStreamWrite.currentWritePos = 0; memoryStreamWrite.currentWritePos = 0;
if (!drwav_init_write(pWav, pFormat, drwav__on_write_memory, drwav__on_seek_memory_write, (void*)&memoryStreamWrite)) { if (!drwav_init_write__internal(pWav, pFormat, totalSampleCount, isSequential, drwav__on_write_memory, drwav__on_seek_memory_write, (void*)&memoryStreamWrite)) {
return DRWAV_FALSE; return DRWAV_FALSE;
} }
...@@ -1258,6 +1289,17 @@ drwav_bool32 drwav_init_memory_write(drwav* pWav, void** ppData, size_t* pDataSi ...@@ -1258,6 +1289,17 @@ drwav_bool32 drwav_init_memory_write(drwav* pWav, void** ppData, size_t* pDataSi
return DRWAV_TRUE; return DRWAV_TRUE;
} }
drwav_bool32 drwav_init_memory_write(drwav* pWav, void** ppData, size_t* pDataSize, const drwav_data_format* pFormat)
{
return drwav_init_memory_write__internal(pWav, ppData, pDataSize, pFormat, 0, DRWAV_FALSE);
}
drwav_bool32 drwav_init_memory_write_sequential(drwav* pWav, void** ppData, size_t* pDataSize, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount)
{
return drwav_init_memory_write__internal(pWav, ppData, pDataSize, pFormat, totalSampleCount, DRWAV_TRUE);
}
drwav* drwav_open_memory(const void* data, size_t dataSize) drwav* drwav_open_memory(const void* data, size_t dataSize)
{ {
if (data == NULL || dataSize == 0) { if (data == NULL || dataSize == 0) {
...@@ -1280,7 +1322,8 @@ drwav* drwav_open_memory(const void* data, size_t dataSize) ...@@ -1280,7 +1322,8 @@ drwav* drwav_open_memory(const void* data, size_t dataSize)
return pWav; return pWav;
} }
drwav* drwav_open_memory_write(void** ppData, size_t* pDataSize, const drwav_data_format* pFormat)
drwav* drwav_open_memory_write__internal(void** ppData, size_t* pDataSize, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount, drwav_bool32 isSequential)
{ {
if (ppData == NULL) { if (ppData == NULL) {
return NULL; return NULL;
...@@ -1297,7 +1340,7 @@ drwav* drwav_open_memory_write(void** ppData, size_t* pDataSize, const drwav_dat ...@@ -1297,7 +1340,7 @@ drwav* drwav_open_memory_write(void** ppData, size_t* pDataSize, const drwav_dat
memoryStreamWrite.dataCapacity = 0; memoryStreamWrite.dataCapacity = 0;
memoryStreamWrite.currentWritePos = 0; memoryStreamWrite.currentWritePos = 0;
drwav* pWav = drwav_open_write(pFormat, drwav__on_write_memory, drwav__on_seek_memory_write, (void*)&memoryStreamWrite); drwav* pWav = drwav_open_write__internal(pFormat, totalSampleCount, isSequential, drwav__on_write_memory, drwav__on_seek_memory_write, (void*)&memoryStreamWrite);
if (pWav == NULL) { if (pWav == NULL) {
return NULL; return NULL;
} }
...@@ -1307,6 +1350,16 @@ drwav* drwav_open_memory_write(void** ppData, size_t* pDataSize, const drwav_dat ...@@ -1307,6 +1350,16 @@ drwav* drwav_open_memory_write(void** ppData, size_t* pDataSize, const drwav_dat
return pWav; return pWav;
} }
drwav* drwav_open_memory_write(void** ppData, size_t* pDataSize, const drwav_data_format* pFormat)
{
return drwav_open_memory_write__internal(ppData, pDataSize, pFormat, 0, DRWAV_FALSE);
}
drwav* drwav_open_memory_write_sequential(void** ppData, size_t* pDataSize, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount)
{
return drwav_open_memory_write__internal(ppData, pDataSize, pFormat, totalSampleCount, DRWAV_TRUE);
}
drwav_bool32 drwav_init(drwav* pWav, drwav_read_proc onRead, drwav_seek_proc onSeek, void* pUserData) drwav_bool32 drwav_init(drwav* pWav, drwav_read_proc onRead, drwav_seek_proc onSeek, void* pUserData)
{ {
...@@ -1392,7 +1445,7 @@ drwav_bool32 drwav_init(drwav* pWav, drwav_read_proc onRead, drwav_seek_proc onS ...@@ -1392,7 +1445,7 @@ drwav_bool32 drwav_init(drwav* pWav, drwav_read_proc onRead, drwav_seek_proc onS
} }
// The next 24 bytes should be the "fmt " chunk. // The next bytes should be the "fmt " chunk.
drwav_fmt fmt; drwav_fmt fmt;
if (!drwav__read_fmt(onRead, onSeek, pUserData, pWav->container, &pWav->dataChunkDataPos, &fmt)) { if (!drwav__read_fmt(onRead, onSeek, pUserData, pWav->container, &pWav->dataChunkDataPos, &fmt)) {
return DRWAV_FALSE; // Failed to read the "fmt " chunk. return DRWAV_FALSE; // Failed to read the "fmt " chunk.
...@@ -1456,7 +1509,7 @@ drwav_bool32 drwav_init(drwav* pWav, drwav_read_proc onRead, drwav_seek_proc onS ...@@ -1456,7 +1509,7 @@ drwav_bool32 drwav_init(drwav* pWav, drwav_read_proc onRead, drwav_seek_proc onS
if (onRead(pUserData, &sampleCountFromFactChunk, 8) != 8) { if (onRead(pUserData, &sampleCountFromFactChunk, 8) != 8) {
return DRWAV_FALSE; return DRWAV_FALSE;
} }
pWav->dataChunkDataPos += 4; pWav->dataChunkDataPos += 8;
dataSize -= 8; dataSize -= 8;
} }
} }
...@@ -1518,8 +1571,8 @@ drwav_bool32 drwav_init(drwav* pWav, drwav_read_proc onRead, drwav_seek_proc onS ...@@ -1518,8 +1571,8 @@ drwav_bool32 drwav_init(drwav* pWav, drwav_read_proc onRead, drwav_seek_proc onS
#ifdef DR_WAV_LIBSNDFILE_COMPAT #ifdef DR_WAV_LIBSNDFILE_COMPAT
// I use libsndfile as a benchmark for testing, however in the version I'm using (from the Windows installer on the libsndfile website), // I use libsndfile as a benchmark for testing, however in the version I'm using (from the Windows installer on the libsndfile website),
// it appears the total sample count libsndfile uses for MS-ADPCM is incorrect. It would seem they are computing the total sample count // it appears the total sample count libsndfile uses for MS-ADPCM is incorrect. It would seem they are computing the total sample count
// from the number of blocks, however this results in the inclusion of the extra silent samples at the end of the last block. The correct // from the number of blocks, however this results in the inclusion of extra silent samples at the end of the last block. The correct
// way to know the total sample count is to inspect the "fact" chunk which should always be present for compressed formats, and should // way to know the total sample count is to inspect the "fact" chunk, which should always be present for compressed formats, and should
// always include the sample count. This little block of code below is only used to emulate the libsndfile logic so I can properly run my // always include the sample count. This little block of code below is only used to emulate the libsndfile logic so I can properly run my
// correctness tests against libsndfile, and is disabled by default. // correctness tests against libsndfile, and is disabled by default.
if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ADPCM) { if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ADPCM) {
...@@ -1535,12 +1588,51 @@ drwav_bool32 drwav_init(drwav* pWav, drwav_read_proc onRead, drwav_seek_proc onS ...@@ -1535,12 +1588,51 @@ drwav_bool32 drwav_init(drwav* pWav, drwav_read_proc onRead, drwav_seek_proc onS
return DRWAV_TRUE; return DRWAV_TRUE;
} }
drwav_bool32 drwav_init_write(drwav* pWav, const drwav_data_format* pFormat, drwav_write_proc onWrite, drwav_seek_proc onSeek, void* pUserData)
drwav_uint32 drwav_riff_chunk_size_riff(drwav_uint64 dataChunkSize)
{
if (dataChunkSize <= (0xFFFFFFFF - 36)) {
return 36 + (drwav_uint32)dataChunkSize;
} else {
return 0xFFFFFFFF;
}
}
drwav_uint32 drwav_data_chunk_size_riff(drwav_uint64 dataChunkSize)
{
if (dataChunkSize <= 0xFFFFFFFF) {
return (drwav_uint32)dataChunkSize;
} else {
return 0xFFFFFFFF;
}
}
drwav_uint64 drwav_riff_chunk_size_w64(drwav_uint64 dataChunkSize)
{ {
if (onWrite == NULL || onSeek == NULL) { return 80 + 24 + dataChunkSize; // +24 because W64 includes the size of the GUID and size fields.
}
drwav_uint64 drwav_data_chunk_size_w64(drwav_uint64 dataChunkSize)
{
return 24 + dataChunkSize; // +24 because W64 includes the size of the GUID and size fields.
}
drwav_bool32 drwav_init_write__internal(drwav* pWav, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount, drwav_bool32 isSequential, drwav_write_proc onWrite, drwav_seek_proc onSeek, void* pUserData)
{
if (pWav == NULL) {
return DRWAV_FALSE; return DRWAV_FALSE;
} }
if (onWrite == NULL) {
return DRWAV_FALSE;
}
if (!isSequential && onSeek == NULL) {
return DRWAV_FALSE; // <-- onSeek is required when in non-sequential mode.
}
// Not currently supporting compressed formats. Will need to add support for the "fact" chunk before we enable this. // Not currently supporting compressed formats. Will need to add support for the "fact" chunk before we enable this.
if (pFormat->format == DR_WAVE_FORMAT_EXTENSIBLE) { if (pFormat->format == DR_WAVE_FORMAT_EXTENSIBLE) {
return DRWAV_FALSE; return DRWAV_FALSE;
...@@ -1557,20 +1649,42 @@ drwav_bool32 drwav_init_write(drwav* pWav, const drwav_data_format* pFormat, drw ...@@ -1557,20 +1649,42 @@ drwav_bool32 drwav_init_write(drwav* pWav, const drwav_data_format* pFormat, drw
pWav->fmt.formatTag = (drwav_uint16)pFormat->format; pWav->fmt.formatTag = (drwav_uint16)pFormat->format;
pWav->fmt.channels = (drwav_uint16)pFormat->channels; pWav->fmt.channels = (drwav_uint16)pFormat->channels;
pWav->fmt.sampleRate = pFormat->sampleRate; pWav->fmt.sampleRate = pFormat->sampleRate;
pWav->fmt.avgBytesPerSec = (drwav_uint32)((pFormat->bitsPerSample * pFormat->sampleRate * pFormat->channels) >> 3); pWav->fmt.avgBytesPerSec = (drwav_uint32)((pFormat->bitsPerSample * pFormat->sampleRate * pFormat->channels) / 8);
pWav->fmt.blockAlign = (drwav_uint16)((pFormat->channels * pFormat->bitsPerSample) >> 3); pWav->fmt.blockAlign = (drwav_uint16)((pFormat->channels * pFormat->bitsPerSample) / 8);
pWav->fmt.bitsPerSample = (drwav_uint16)pFormat->bitsPerSample; pWav->fmt.bitsPerSample = (drwav_uint16)pFormat->bitsPerSample;
pWav->fmt.extendedSize = 0; pWav->fmt.extendedSize = 0;
pWav->isSequentialWrite = isSequential;
size_t runningPos = 0; size_t runningPos = 0;
// The initial values for the "RIFF" and "data" chunks depends on whether or not we are initializing in sequential mode or not. In
// sequential mode we set this to its final values straight away since they can be calculated from the total sample count. In non-
// sequential mode we initialize it all to zero and fill it out in drwav_uninit() using a backwards seek.
drwav_uint64 initialDataChunkSize = 0;
if (isSequential) {
initialDataChunkSize = (totalSampleCount * pWav->fmt.bitsPerSample) / 8;
// The RIFF container has a limit on the number of samples. drwav is not allowing this. There's no practical limits for Wave64
// so for the sake of simplicity I'm not doing any validation for that.
if (pFormat->container == drwav_container_riff) {
if (initialDataChunkSize > (0xFFFFFFFF - 36)) {
return DRWAV_FALSE; // Not enough room to store every sample.
}
}
}
pWav->dataChunkDataSizeTargetWrite = initialDataChunkSize;
// "RIFF" chunk. // "RIFF" chunk.
drwav_uint64 chunkSizeRIFF = 0;
if (pFormat->container == drwav_container_riff) { if (pFormat->container == drwav_container_riff) {
drwav_uint32 chunkSizeRIFF = 36 + (drwav_uint32)initialDataChunkSize; // +36 = "RIFF"+[RIFF Chunk Size]+"WAVE" + [sizeof "fmt " chunk]
runningPos += pWav->onWrite(pUserData, "RIFF", 4); runningPos += pWav->onWrite(pUserData, "RIFF", 4);
runningPos += pWav->onWrite(pUserData, &chunkSizeRIFF, 4); runningPos += pWav->onWrite(pUserData, &chunkSizeRIFF, 4);
runningPos += pWav->onWrite(pUserData, "WAVE", 4); runningPos += pWav->onWrite(pUserData, "WAVE", 4);
} else { } else {
drwav_uint64 chunkSizeRIFF = 80 + 24 + initialDataChunkSize; // +24 because W64 includes the size of the GUID and size fields.
runningPos += pWav->onWrite(pUserData, drwavGUID_W64_RIFF, 16); runningPos += pWav->onWrite(pUserData, drwavGUID_W64_RIFF, 16);
runningPos += pWav->onWrite(pUserData, &chunkSizeRIFF, 8); runningPos += pWav->onWrite(pUserData, &chunkSizeRIFF, 8);
runningPos += pWav->onWrite(pUserData, drwavGUID_W64_WAVE, 16); runningPos += pWav->onWrite(pUserData, drwavGUID_W64_WAVE, 16);
...@@ -1596,14 +1710,14 @@ drwav_bool32 drwav_init_write(drwav* pWav, const drwav_data_format* pFormat, drw ...@@ -1596,14 +1710,14 @@ drwav_bool32 drwav_init_write(drwav* pWav, const drwav_data_format* pFormat, drw
runningPos += pWav->onWrite(pUserData, &pWav->fmt.bitsPerSample, 2); runningPos += pWav->onWrite(pUserData, &pWav->fmt.bitsPerSample, 2);
pWav->dataChunkDataPos = runningPos; pWav->dataChunkDataPos = runningPos;
pWav->dataChunkDataSize = 0;
// "data" chunk. // "data" chunk.
drwav_uint64 chunkSizeDATA = 0;
if (pFormat->container == drwav_container_riff) { if (pFormat->container == drwav_container_riff) {
drwav_uint32 chunkSizeDATA = (drwav_uint32)initialDataChunkSize;
runningPos += pWav->onWrite(pUserData, "data", 4); runningPos += pWav->onWrite(pUserData, "data", 4);
runningPos += pWav->onWrite(pUserData, &chunkSizeDATA, 4); runningPos += pWav->onWrite(pUserData, &chunkSizeDATA, 4);
} else { } else {
drwav_uint64 chunkSizeDATA = 24 + initialDataChunkSize; // +24 because W64 includes the size of the GUID and size fields.
runningPos += pWav->onWrite(pUserData, drwavGUID_W64_DATA, 16); runningPos += pWav->onWrite(pUserData, drwavGUID_W64_DATA, 16);
runningPos += pWav->onWrite(pUserData, &chunkSizeDATA, 8); runningPos += pWav->onWrite(pUserData, &chunkSizeDATA, 8);
} }
...@@ -1633,16 +1747,32 @@ drwav_bool32 drwav_init_write(drwav* pWav, const drwav_data_format* pFormat, drw ...@@ -1633,16 +1747,32 @@ drwav_bool32 drwav_init_write(drwav* pWav, const drwav_data_format* pFormat, drw
return DRWAV_TRUE; return DRWAV_TRUE;
} }
drwav_bool32 drwav_init_write(drwav* pWav, const drwav_data_format* pFormat, drwav_write_proc onWrite, drwav_seek_proc onSeek, void* pUserData)
{
return drwav_init_write__internal(pWav, pFormat, 0, DRWAV_FALSE, onWrite, onSeek, pUserData); // DRWAV_FALSE = Not Sequential
}
drwav_bool32 drwav_init_write_sequential(drwav* pWav, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount, drwav_write_proc onWrite, void* pUserData)
{
return drwav_init_write__internal(pWav, pFormat, totalSampleCount, DRWAV_TRUE, onWrite, NULL, pUserData); // DRWAV_TRUE = Sequential
}
void drwav_uninit(drwav* pWav) void drwav_uninit(drwav* pWav)
{ {
if (pWav == NULL) { if (pWav == NULL) {
return; return;
} }
// If the drwav object was opened in write mode we'll need to finialize a few things: // If the drwav object was opened in write mode we'll need to finalize a few things:
// - Make sure the "data" chunk is aligned to 16-bits // - Make sure the "data" chunk is aligned to 16-bits for RIFF containers, or 64 bits for W64 containers.
// - Set the size of the "data" chunk. // - Set the size of the "data" chunk.
if (pWav->onWrite != NULL) { if (pWav->onWrite != NULL) {
// Validation for sequential mode.
if (pWav->isSequentialWrite) {
drwav_assert(pWav->dataChunkDataSize == pWav->dataChunkDataSizeTargetWrite);
}
// Padding. Do not adjust pWav->dataChunkDataSize - this should not include the padding. // Padding. Do not adjust pWav->dataChunkDataSize - this should not include the padding.
drwav_uint32 paddingSize = 0; drwav_uint32 paddingSize = 0;
if (pWav->container == drwav_container_riff) { if (pWav->container == drwav_container_riff) {
...@@ -1657,42 +1787,31 @@ void drwav_uninit(drwav* pWav) ...@@ -1657,42 +1787,31 @@ void drwav_uninit(drwav* pWav)
} }
// Chunk sizes. // Chunk sizes. When using sequential mode, these will have been filled in at initialization time. We only need
if (pWav->onSeek) { // to do this when using non-sequential mode.
if (pWav->onSeek && !pWav->isSequentialWrite) {
if (pWav->container == drwav_container_riff) { if (pWav->container == drwav_container_riff) {
// The "RIFF" chunk size. // The "RIFF" chunk size.
if (pWav->onSeek(pWav->pUserData, 4, drwav_seek_origin_start)) { if (pWav->onSeek(pWav->pUserData, 4, drwav_seek_origin_start)) {
drwav_uint32 riffChunkSize = 36; drwav_uint32 riffChunkSize = drwav_riff_chunk_size_riff(pWav->dataChunkDataSize);
if (pWav->dataChunkDataSize <= (0xFFFFFFFF - 36)) {
riffChunkSize = 36 + (drwav_uint32)pWav->dataChunkDataSize;
} else {
riffChunkSize = 0xFFFFFFFF;
}
pWav->onWrite(pWav->pUserData, &riffChunkSize, 4); pWav->onWrite(pWav->pUserData, &riffChunkSize, 4);
} }
// the "data" chunk size. // the "data" chunk size.
if (pWav->onSeek(pWav->pUserData, (int)pWav->dataChunkDataPos + 4, drwav_seek_origin_start)) { if (pWav->onSeek(pWav->pUserData, (int)pWav->dataChunkDataPos + 4, drwav_seek_origin_start)) {
drwav_uint32 dataChunkSize = 0; drwav_uint32 dataChunkSize = drwav_data_chunk_size_riff(pWav->dataChunkDataSize);
if (pWav->dataChunkDataSize <= 0xFFFFFFFF) {
dataChunkSize = (drwav_uint32)pWav->dataChunkDataSize;
} else {
dataChunkSize = 0xFFFFFFFF;
}
pWav->onWrite(pWav->pUserData, &dataChunkSize, 4); pWav->onWrite(pWav->pUserData, &dataChunkSize, 4);
} }
} else { } else {
// The "RIFF" chunk size. // The "RIFF" chunk size.
if (pWav->onSeek(pWav->pUserData, 16, drwav_seek_origin_start)) { if (pWav->onSeek(pWav->pUserData, 16, drwav_seek_origin_start)) {
drwav_uint64 riffChunkSize = 80 + 24 + pWav->dataChunkDataSize; drwav_uint64 riffChunkSize = drwav_riff_chunk_size_w64(pWav->dataChunkDataSize);
pWav->onWrite(pWav->pUserData, &riffChunkSize, 8); pWav->onWrite(pWav->pUserData, &riffChunkSize, 8);
} }
// The "data" chunk size. // The "data" chunk size.
if (pWav->onSeek(pWav->pUserData, (int)pWav->dataChunkDataPos + 16, drwav_seek_origin_start)) { if (pWav->onSeek(pWav->pUserData, (int)pWav->dataChunkDataPos + 16, drwav_seek_origin_start)) {
drwav_uint64 dataChunkSize = 24 + pWav->dataChunkDataSize; // +24 because W64 includes the size of the GUID and size fields. drwav_uint64 dataChunkSize = drwav_data_chunk_size_w64(pWav->dataChunkDataSize);
pWav->onWrite(pWav->pUserData, &dataChunkSize, 8); pWav->onWrite(pWav->pUserData, &dataChunkSize, 8);
} }
} }
...@@ -1724,14 +1843,15 @@ drwav* drwav_open(drwav_read_proc onRead, drwav_seek_proc onSeek, void* pUserDat ...@@ -1724,14 +1843,15 @@ drwav* drwav_open(drwav_read_proc onRead, drwav_seek_proc onSeek, void* pUserDat
return pWav; return pWav;
} }
drwav* drwav_open_write(const drwav_data_format* pFormat, drwav_write_proc onWrite, drwav_seek_proc onSeek, void* pUserData)
drwav* drwav_open_write__internal(const drwav_data_format* pFormat, drwav_uint64 totalSampleCount, drwav_bool32 isSequential, drwav_write_proc onWrite, drwav_seek_proc onSeek, void* pUserData)
{ {
drwav* pWav = (drwav*)DRWAV_MALLOC(sizeof(*pWav)); drwav* pWav = (drwav*)DRWAV_MALLOC(sizeof(*pWav));
if (pWav == NULL) { if (pWav == NULL) {
return NULL; return NULL;
} }
if (!drwav_init_write(pWav, pFormat, onWrite, onSeek, pUserData)) { if (!drwav_init_write__internal(pWav, pFormat, totalSampleCount, isSequential, onWrite, onSeek, pUserData)) {
DRWAV_FREE(pWav); DRWAV_FREE(pWav);
return NULL; return NULL;
} }
...@@ -1739,6 +1859,16 @@ drwav* drwav_open_write(const drwav_data_format* pFormat, drwav_write_proc onWri ...@@ -1739,6 +1859,16 @@ drwav* drwav_open_write(const drwav_data_format* pFormat, drwav_write_proc onWri
return pWav; return pWav;
} }
drwav* drwav_open_write(const drwav_data_format* pFormat, drwav_write_proc onWrite, drwav_seek_proc onSeek, void* pUserData)
{
return drwav_open_write__internal(pFormat, 0, DRWAV_FALSE, onWrite, onSeek, pUserData);
}
drwav* drwav_open_write_sequential(const drwav_data_format* pFormat, drwav_uint64 totalSampleCount, drwav_write_proc onWrite, void* pUserData)
{
return drwav_open_write__internal(pFormat, totalSampleCount, DRWAV_TRUE, onWrite, NULL, pUserData);
}
void drwav_close(drwav* pWav) void drwav_close(drwav* pWav)
{ {
drwav_uninit(pWav); drwav_uninit(pWav);
...@@ -1784,6 +1914,10 @@ drwav_uint64 drwav_read(drwav* pWav, drwav_uint64 samplesToRead, void* pBufferOu ...@@ -1784,6 +1914,10 @@ drwav_uint64 drwav_read(drwav* pWav, drwav_uint64 samplesToRead, void* pBufferOu
drwav_bool32 drwav_seek_to_first_sample(drwav* pWav) drwav_bool32 drwav_seek_to_first_sample(drwav* pWav)
{ {
if (pWav->onWrite != NULL) {
return DRWAV_FALSE; // No seeking in write mode.
}
if (!pWav->onSeek(pWav->pUserData, (int)pWav->dataChunkDataPos, drwav_seek_origin_start)) { if (!pWav->onSeek(pWav->pUserData, (int)pWav->dataChunkDataPos, drwav_seek_origin_start)) {
return DRWAV_FALSE; return DRWAV_FALSE;
} }
...@@ -1800,6 +1934,10 @@ drwav_bool32 drwav_seek_to_sample(drwav* pWav, drwav_uint64 sample) ...@@ -1800,6 +1934,10 @@ drwav_bool32 drwav_seek_to_sample(drwav* pWav, drwav_uint64 sample)
{ {
// Seeking should be compatible with wave files > 2GB. // Seeking should be compatible with wave files > 2GB.
if (pWav->onWrite != NULL) {
return DRWAV_FALSE; // No seeking in write mode.
}
if (pWav == NULL || pWav->onSeek == NULL) { if (pWav == NULL || pWav->onSeek == NULL) {
return DRWAV_FALSE; return DRWAV_FALSE;
} }
...@@ -1911,8 +2049,25 @@ drwav_uint64 drwav_write(drwav* pWav, drwav_uint64 samplesToWrite, const void* p ...@@ -1911,8 +2049,25 @@ drwav_uint64 drwav_write(drwav* pWav, drwav_uint64 samplesToWrite, const void* p
return 0; return 0;
} }
size_t bytesWritten = drwav_write_raw(pWav, (size_t)bytesToWrite, pData); drwav_uint64 bytesWritten = 0;
return ((drwav_uint64)bytesWritten * 8) / pWav->bitsPerSample; const drwav_uint8* pRunningData = (const drwav_uint8*)pData;
while (bytesToWrite > 0) {
drwav_uint64 bytesToWriteThisIteration = bytesToWrite;
if (bytesToWriteThisIteration > SIZE_MAX) {
bytesToWriteThisIteration = SIZE_MAX;
}
size_t bytesJustWritten = drwav_write_raw(pWav, (size_t)bytesToWriteThisIteration, pRunningData);
if (bytesJustWritten == 0) {
break;
}
bytesToWrite -= bytesJustWritten;
bytesWritten += bytesJustWritten;
pRunningData += bytesJustWritten;
}
return (bytesWritten * 8) / pWav->bitsPerSample;
} }
...@@ -3439,6 +3594,12 @@ void drwav_free(void* pDataReturnedByOpenAndRead) ...@@ -3439,6 +3594,12 @@ void drwav_free(void* pDataReturnedByOpenAndRead)
// REVISION HISTORY // REVISION HISTORY
// //
// v0.8.1 - 2018-06-29
// - Add support for sequential writing APIs.
// - Disable seeking in write mode.
// - Fix bugs with Wave64.
// - Fix typos.
//
// v0.8 - 2018-04-27 // v0.8 - 2018-04-27
// - Bug fix. // - Bug fix.
// - Start using major.minor.revision versioning. // - Start using major.minor.revision versioning.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment