]> git.sesse.net Git - pistorm/blob - raylib/external/dr_wav.h
Update raylib files and Makefile for Pi 4 testing
[pistorm] / raylib / external / dr_wav.h
1 /*
2 WAV audio loader and writer. Choice of public domain or MIT-0. See license statements at the end of this file.
3 dr_wav - v0.12.19 - 2021-02-21
4
5 David Reid - mackron@gmail.com
6
7 GitHub: https://github.com/mackron/dr_libs
8 */
9
10 /*
11 RELEASE NOTES - VERSION 0.12
12 ============================
13 Version 0.12 includes breaking changes to custom chunk handling.
14
15
16 Changes to Chunk Callback
17 -------------------------
18 dr_wav supports the ability to fire a callback when a chunk is encounted (except for WAVE and FMT chunks). The callback has been updated to include both the
19 container (RIFF or Wave64) and the FMT chunk which contains information about the format of the data in the wave file.
20
21 Previously, there was no direct way to determine the container, and therefore no way to discriminate against the different IDs in the chunk header (RIFF and
22 Wave64 containers encode chunk ID's differently). The `container` parameter can be used to know which ID to use.
23
24 Sometimes it can be useful to know the data format at the time the chunk callback is fired. A pointer to a `drwav_fmt` object is now passed into the chunk
25 callback which will give you information about the data format. To determine the sample format, use `drwav_fmt_get_format()`. This will return one of the
26 `DR_WAVE_FORMAT_*` tokens.
27 */
28
29 /*
30 Introduction
31 ============
32 This is a single file library. To use it, do something like the following in one .c file.
33     
34     ```c
35     #define DR_WAV_IMPLEMENTATION
36     #include "dr_wav.h"
37     ```
38
39 You can then #include this file in other parts of the program as you would with any other header file. Do something like the following to read audio data:
40
41     ```c
42     drwav wav;
43     if (!drwav_init_file(&wav, "my_song.wav", NULL)) {
44         // Error opening WAV file.
45     }
46
47     drwav_int32* pDecodedInterleavedPCMFrames = malloc(wav.totalPCMFrameCount * wav.channels * sizeof(drwav_int32));
48     size_t numberOfSamplesActuallyDecoded = drwav_read_pcm_frames_s32(&wav, wav.totalPCMFrameCount, pDecodedInterleavedPCMFrames);
49
50     ...
51
52     drwav_uninit(&wav);
53     ```
54
55 If you just want to quickly open and read the audio data in a single operation you can do something like this:
56
57     ```c
58     unsigned int channels;
59     unsigned int sampleRate;
60     drwav_uint64 totalPCMFrameCount;
61     float* pSampleData = drwav_open_file_and_read_pcm_frames_f32("my_song.wav", &channels, &sampleRate, &totalPCMFrameCount, NULL);
62     if (pSampleData == NULL) {
63         // Error opening and reading WAV file.
64     }
65
66     ...
67
68     drwav_free(pSampleData, NULL);
69     ```
70
71 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
72 audio data in its internal format (see notes below for supported formats):
73
74     ```c
75     size_t framesRead = drwav_read_pcm_frames(&wav, wav.totalPCMFrameCount, pDecodedInterleavedPCMFrames);
76     ```
77
78 You can also read the raw bytes of audio data, which could be useful if dr_wav does not have native support for a particular data format:
79
80     ```c
81     size_t bytesRead = drwav_read_raw(&wav, bytesToRead, pRawDataBuffer);
82     ```
83
84 dr_wav can also be used to output WAV files. This does not currently support compressed formats. To use this, look at `drwav_init_write()`,
85 `drwav_init_file_write()`, etc. Use `drwav_write_pcm_frames()` to write samples, or `drwav_write_raw()` to write raw data in the "data" chunk.
86
87     ```c
88     drwav_data_format format;
89     format.container = drwav_container_riff;     // <-- drwav_container_riff = normal WAV files, drwav_container_w64 = Sony Wave64.
90     format.format = DR_WAVE_FORMAT_PCM;          // <-- Any of the DR_WAVE_FORMAT_* codes.
91     format.channels = 2;
92     format.sampleRate = 44100;
93     format.bitsPerSample = 16;
94     drwav_init_file_write(&wav, "data/recording.wav", &format, NULL);
95
96     ...
97
98     drwav_uint64 framesWritten = drwav_write_pcm_frames(pWav, frameCount, pSamples);
99     ```
100
101 dr_wav has seamless support the Sony Wave64 format. The decoder will automatically detect it and it should Just Work without any manual intervention.
102
103
104 Build Options
105 =============
106 #define these options before including this file.
107
108 #define DR_WAV_NO_CONVERSION_API
109   Disables conversion APIs such as `drwav_read_pcm_frames_f32()` and `drwav_s16_to_f32()`.
110
111 #define DR_WAV_NO_STDIO
112   Disables APIs that initialize a decoder from a file such as `drwav_init_file()`, `drwav_init_file_write()`, etc.
113
114
115
116 Notes
117 =====
118 - Samples are always interleaved.
119 - The default read function does not do any data conversion. Use `drwav_read_pcm_frames_f32()`, `drwav_read_pcm_frames_s32()` and `drwav_read_pcm_frames_s16()`
120   to read and convert audio data to 32-bit floating point, signed 32-bit integer and signed 16-bit integer samples respectively. Tested and supported internal
121   formats include the following:
122   - Unsigned 8-bit PCM
123   - Signed 12-bit PCM
124   - Signed 16-bit PCM
125   - Signed 24-bit PCM
126   - Signed 32-bit PCM
127   - IEEE 32-bit floating point
128   - IEEE 64-bit floating point
129   - A-law and u-law
130   - Microsoft ADPCM
131   - IMA ADPCM (DVI, format code 0x11)
132 - dr_wav will try to read the WAV file as best it can, even if it's not strictly conformant to the WAV format.
133 */
134
135 #ifndef dr_wav_h
136 #define dr_wav_h
137
138 #ifdef __cplusplus
139 extern "C" {
140 #endif
141
142 #define DRWAV_STRINGIFY(x)      #x
143 #define DRWAV_XSTRINGIFY(x)     DRWAV_STRINGIFY(x)
144
145 #define DRWAV_VERSION_MAJOR     0
146 #define DRWAV_VERSION_MINOR     12
147 #define DRWAV_VERSION_REVISION  19
148 #define DRWAV_VERSION_STRING    DRWAV_XSTRINGIFY(DRWAV_VERSION_MAJOR) "." DRWAV_XSTRINGIFY(DRWAV_VERSION_MINOR) "." DRWAV_XSTRINGIFY(DRWAV_VERSION_REVISION)
149
150 #include <stddef.h> /* For size_t. */
151
152 /* Sized types. */
153 typedef   signed char           drwav_int8;
154 typedef unsigned char           drwav_uint8;
155 typedef   signed short          drwav_int16;
156 typedef unsigned short          drwav_uint16;
157 typedef   signed int            drwav_int32;
158 typedef unsigned int            drwav_uint32;
159 #if defined(_MSC_VER)
160     typedef   signed __int64    drwav_int64;
161     typedef unsigned __int64    drwav_uint64;
162 #else
163     #if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))
164         #pragma GCC diagnostic push
165         #pragma GCC diagnostic ignored "-Wlong-long"
166         #if defined(__clang__)
167             #pragma GCC diagnostic ignored "-Wc++11-long-long"
168         #endif
169     #endif
170     typedef   signed long long  drwav_int64;
171     typedef unsigned long long  drwav_uint64;
172     #if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))
173         #pragma GCC diagnostic pop
174     #endif
175 #endif
176 #if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__)) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__)
177     typedef drwav_uint64        drwav_uintptr;
178 #else
179     typedef drwav_uint32        drwav_uintptr;
180 #endif
181 typedef drwav_uint8             drwav_bool8;
182 typedef drwav_uint32            drwav_bool32;
183 #define DRWAV_TRUE              1
184 #define DRWAV_FALSE             0
185
186 #if !defined(DRWAV_API)
187     #if defined(DRWAV_DLL)
188         #if defined(_WIN32)
189             #define DRWAV_DLL_IMPORT  __declspec(dllimport)
190             #define DRWAV_DLL_EXPORT  __declspec(dllexport)
191             #define DRWAV_DLL_PRIVATE static
192         #else
193             #if defined(__GNUC__) && __GNUC__ >= 4
194                 #define DRWAV_DLL_IMPORT  __attribute__((visibility("default")))
195                 #define DRWAV_DLL_EXPORT  __attribute__((visibility("default")))
196                 #define DRWAV_DLL_PRIVATE __attribute__((visibility("hidden")))
197             #else
198                 #define DRWAV_DLL_IMPORT
199                 #define DRWAV_DLL_EXPORT
200                 #define DRWAV_DLL_PRIVATE static
201             #endif
202         #endif
203
204         #if defined(DR_WAV_IMPLEMENTATION) || defined(DRWAV_IMPLEMENTATION)
205             #define DRWAV_API  DRWAV_DLL_EXPORT
206         #else
207             #define DRWAV_API  DRWAV_DLL_IMPORT
208         #endif
209         #define DRWAV_PRIVATE DRWAV_DLL_PRIVATE
210     #else
211         #define DRWAV_API extern
212         #define DRWAV_PRIVATE static
213     #endif
214 #endif
215
216 typedef drwav_int32 drwav_result;
217 #define DRWAV_SUCCESS                        0
218 #define DRWAV_ERROR                         -1   /* A generic error. */
219 #define DRWAV_INVALID_ARGS                  -2
220 #define DRWAV_INVALID_OPERATION             -3
221 #define DRWAV_OUT_OF_MEMORY                 -4
222 #define DRWAV_OUT_OF_RANGE                  -5
223 #define DRWAV_ACCESS_DENIED                 -6
224 #define DRWAV_DOES_NOT_EXIST                -7
225 #define DRWAV_ALREADY_EXISTS                -8
226 #define DRWAV_TOO_MANY_OPEN_FILES           -9
227 #define DRWAV_INVALID_FILE                  -10
228 #define DRWAV_TOO_BIG                       -11
229 #define DRWAV_PATH_TOO_LONG                 -12
230 #define DRWAV_NAME_TOO_LONG                 -13
231 #define DRWAV_NOT_DIRECTORY                 -14
232 #define DRWAV_IS_DIRECTORY                  -15
233 #define DRWAV_DIRECTORY_NOT_EMPTY           -16
234 #define DRWAV_END_OF_FILE                   -17
235 #define DRWAV_NO_SPACE                      -18
236 #define DRWAV_BUSY                          -19
237 #define DRWAV_IO_ERROR                      -20
238 #define DRWAV_INTERRUPT                     -21
239 #define DRWAV_UNAVAILABLE                   -22
240 #define DRWAV_ALREADY_IN_USE                -23
241 #define DRWAV_BAD_ADDRESS                   -24
242 #define DRWAV_BAD_SEEK                      -25
243 #define DRWAV_BAD_PIPE                      -26
244 #define DRWAV_DEADLOCK                      -27
245 #define DRWAV_TOO_MANY_LINKS                -28
246 #define DRWAV_NOT_IMPLEMENTED               -29
247 #define DRWAV_NO_MESSAGE                    -30
248 #define DRWAV_BAD_MESSAGE                   -31
249 #define DRWAV_NO_DATA_AVAILABLE             -32
250 #define DRWAV_INVALID_DATA                  -33
251 #define DRWAV_TIMEOUT                       -34
252 #define DRWAV_NO_NETWORK                    -35
253 #define DRWAV_NOT_UNIQUE                    -36
254 #define DRWAV_NOT_SOCKET                    -37
255 #define DRWAV_NO_ADDRESS                    -38
256 #define DRWAV_BAD_PROTOCOL                  -39
257 #define DRWAV_PROTOCOL_UNAVAILABLE          -40
258 #define DRWAV_PROTOCOL_NOT_SUPPORTED        -41
259 #define DRWAV_PROTOCOL_FAMILY_NOT_SUPPORTED -42
260 #define DRWAV_ADDRESS_FAMILY_NOT_SUPPORTED  -43
261 #define DRWAV_SOCKET_NOT_SUPPORTED          -44
262 #define DRWAV_CONNECTION_RESET              -45
263 #define DRWAV_ALREADY_CONNECTED             -46
264 #define DRWAV_NOT_CONNECTED                 -47
265 #define DRWAV_CONNECTION_REFUSED            -48
266 #define DRWAV_NO_HOST                       -49
267 #define DRWAV_IN_PROGRESS                   -50
268 #define DRWAV_CANCELLED                     -51
269 #define DRWAV_MEMORY_ALREADY_MAPPED         -52
270 #define DRWAV_AT_END                        -53
271
272 /* Common data formats. */
273 #define DR_WAVE_FORMAT_PCM          0x1
274 #define DR_WAVE_FORMAT_ADPCM        0x2
275 #define DR_WAVE_FORMAT_IEEE_FLOAT   0x3
276 #define DR_WAVE_FORMAT_ALAW         0x6
277 #define DR_WAVE_FORMAT_MULAW        0x7
278 #define DR_WAVE_FORMAT_DVI_ADPCM    0x11
279 #define DR_WAVE_FORMAT_EXTENSIBLE   0xFFFE
280
281 /* Constants. */
282 #ifndef DRWAV_MAX_SMPL_LOOPS
283 #define DRWAV_MAX_SMPL_LOOPS        1
284 #endif
285
286 /* Flags to pass into drwav_init_ex(), etc. */
287 #define DRWAV_SEQUENTIAL            0x00000001
288
289 DRWAV_API void drwav_version(drwav_uint32* pMajor, drwav_uint32* pMinor, drwav_uint32* pRevision);
290 DRWAV_API const char* drwav_version_string(void);
291
292 typedef enum
293 {
294     drwav_seek_origin_start,
295     drwav_seek_origin_current
296 } drwav_seek_origin;
297
298 typedef enum
299 {
300     drwav_container_riff,
301     drwav_container_w64,
302     drwav_container_rf64
303 } drwav_container;
304
305 typedef struct
306 {
307     union
308     {
309         drwav_uint8 fourcc[4];
310         drwav_uint8 guid[16];
311     } id;
312
313     /* The size in bytes of the chunk. */
314     drwav_uint64 sizeInBytes;
315
316     /*
317     RIFF = 2 byte alignment.
318     W64  = 8 byte alignment.
319     */
320     unsigned int paddingSize;
321 } drwav_chunk_header;
322
323 typedef struct
324 {
325     /*
326     The format tag exactly as specified in the wave file's "fmt" chunk. This can be used by applications
327     that require support for data formats not natively supported by dr_wav.
328     */
329     drwav_uint16 formatTag;
330
331     /* The number of channels making up the audio data. When this is set to 1 it is mono, 2 is stereo, etc. */
332     drwav_uint16 channels;
333
334     /* The sample rate. Usually set to something like 44100. */
335     drwav_uint32 sampleRate;
336
337     /* Average bytes per second. You probably don't need this, but it's left here for informational purposes. */
338     drwav_uint32 avgBytesPerSec;
339
340     /* Block align. This is equal to the number of channels * bytes per sample. */
341     drwav_uint16 blockAlign;
342
343     /* Bits per sample. */
344     drwav_uint16 bitsPerSample;
345
346     /* The size of the extended data. Only used internally for validation, but left here for informational purposes. */
347     drwav_uint16 extendedSize;
348
349     /*
350     The number of valid bits per sample. When <formatTag> is equal to WAVE_FORMAT_EXTENSIBLE, <bitsPerSample>
351     is always rounded up to the nearest multiple of 8. This variable contains information about exactly how
352     many bits are valid per sample. Mainly used for informational purposes.
353     */
354     drwav_uint16 validBitsPerSample;
355
356     /* The channel mask. Not used at the moment. */
357     drwav_uint32 channelMask;
358
359     /* The sub-format, exactly as specified by the wave file. */
360     drwav_uint8 subFormat[16];
361 } drwav_fmt;
362
363 DRWAV_API drwav_uint16 drwav_fmt_get_format(const drwav_fmt* pFMT);
364
365
366 /*
367 Callback for when data is read. Return value is the number of bytes actually read.
368
369 pUserData   [in]  The user data that was passed to drwav_init() and family.
370 pBufferOut  [out] The output buffer.
371 bytesToRead [in]  The number of bytes to read.
372
373 Returns the number of bytes actually read.
374
375 A return value of less than bytesToRead indicates the end of the stream. Do _not_ return from this callback until
376 either the entire bytesToRead is filled or you have reached the end of the stream.
377 */
378 typedef size_t (* drwav_read_proc)(void* pUserData, void* pBufferOut, size_t bytesToRead);
379
380 /*
381 Callback for when data is written. Returns value is the number of bytes actually written.
382
383 pUserData    [in]  The user data that was passed to drwav_init_write() and family.
384 pData        [out] A pointer to the data to write.
385 bytesToWrite [in]  The number of bytes to write.
386
387 Returns the number of bytes actually written.
388
389 If the return value differs from bytesToWrite, it indicates an error.
390 */
391 typedef size_t (* drwav_write_proc)(void* pUserData, const void* pData, size_t bytesToWrite);
392
393 /*
394 Callback for when data needs to be seeked.
395
396 pUserData [in] The user data that was passed to drwav_init() and family.
397 offset    [in] The number of bytes to move, relative to the origin. Will never be negative.
398 origin    [in] The origin of the seek - the current position or the start of the stream.
399
400 Returns whether or not the seek was successful.
401
402 Whether or not it is relative to the beginning or current position is determined by the "origin" parameter which will be either drwav_seek_origin_start or
403 drwav_seek_origin_current.
404 */
405 typedef drwav_bool32 (* drwav_seek_proc)(void* pUserData, int offset, drwav_seek_origin origin);
406
407 /*
408 Callback for when drwav_init_ex() finds a chunk.
409
410 pChunkUserData    [in] The user data that was passed to the pChunkUserData parameter of drwav_init_ex() and family.
411 onRead            [in] A pointer to the function to call when reading.
412 onSeek            [in] A pointer to the function to call when seeking.
413 pReadSeekUserData [in] The user data that was passed to the pReadSeekUserData parameter of drwav_init_ex() and family.
414 pChunkHeader      [in] A pointer to an object containing basic header information about the chunk. Use this to identify the chunk.
415 container         [in] Whether or not the WAV file is a RIFF or Wave64 container. If you're unsure of the difference, assume RIFF.
416 pFMT              [in] A pointer to the object containing the contents of the "fmt" chunk.
417
418 Returns the number of bytes read + seeked.
419
420 To read data from the chunk, call onRead(), passing in pReadSeekUserData as the first parameter. Do the same for seeking with onSeek(). The return value must
421 be the total number of bytes you have read _plus_ seeked.
422
423 Use the `container` argument to discriminate the fields in `pChunkHeader->id`. If the container is `drwav_container_riff` or `drwav_container_rf64` you should
424 use `id.fourcc`, otherwise you should use `id.guid`.
425
426 The `pFMT` parameter can be used to determine the data format of the wave file. Use `drwav_fmt_get_format()` to get the sample format, which will be one of the
427 `DR_WAVE_FORMAT_*` identifiers. 
428
429 The read pointer will be sitting on the first byte after the chunk's header. You must not attempt to read beyond the boundary of the chunk.
430 */
431 typedef drwav_uint64 (* drwav_chunk_proc)(void* pChunkUserData, drwav_read_proc onRead, drwav_seek_proc onSeek, void* pReadSeekUserData, const drwav_chunk_header* pChunkHeader, drwav_container container, const drwav_fmt* pFMT);
432
433 typedef struct
434 {
435     void* pUserData;
436     void* (* onMalloc)(size_t sz, void* pUserData);
437     void* (* onRealloc)(void* p, size_t sz, void* pUserData);
438     void  (* onFree)(void* p, void* pUserData);
439 } drwav_allocation_callbacks;
440
441 /* Structure for internal use. Only used for loaders opened with drwav_init_memory(). */
442 typedef struct
443 {
444     const drwav_uint8* data;
445     size_t dataSize;
446     size_t currentReadPos;
447 } drwav__memory_stream;
448
449 /* Structure for internal use. Only used for writers opened with drwav_init_memory_write(). */
450 typedef struct
451 {
452     void** ppData;
453     size_t* pDataSize;
454     size_t dataSize;
455     size_t dataCapacity;
456     size_t currentWritePos;
457 } drwav__memory_stream_write;
458
459 typedef struct
460 {
461     drwav_container container;  /* RIFF, W64. */
462     drwav_uint32 format;        /* DR_WAVE_FORMAT_* */
463     drwav_uint32 channels;
464     drwav_uint32 sampleRate;
465     drwav_uint32 bitsPerSample;
466 } drwav_data_format;
467
468
469 /* See the following for details on the 'smpl' chunk: https://sites.google.com/site/musicgapi/technical-documents/wav-file-format#smpl */
470 typedef struct
471 {
472     drwav_uint32 cuePointId;
473     drwav_uint32 type;
474     drwav_uint32 start;
475     drwav_uint32 end;
476     drwav_uint32 fraction;
477     drwav_uint32 playCount;
478 } drwav_smpl_loop;
479
480  typedef struct
481 {
482     drwav_uint32 manufacturer;
483     drwav_uint32 product;
484     drwav_uint32 samplePeriod;
485     drwav_uint32 midiUnityNotes;
486     drwav_uint32 midiPitchFraction;
487     drwav_uint32 smpteFormat;
488     drwav_uint32 smpteOffset;
489     drwav_uint32 numSampleLoops;
490     drwav_uint32 samplerData;
491     drwav_smpl_loop loops[DRWAV_MAX_SMPL_LOOPS];
492 } drwav_smpl;
493
494 typedef struct
495 {
496     /* A pointer to the function to call when more data is needed. */
497     drwav_read_proc onRead;
498
499     /* A pointer to the function to call when data needs to be written. Only used when the drwav object is opened in write mode. */
500     drwav_write_proc onWrite;
501
502     /* A pointer to the function to call when the wav file needs to be seeked. */
503     drwav_seek_proc onSeek;
504
505     /* The user data to pass to callbacks. */
506     void* pUserData;
507
508     /* Allocation callbacks. */
509     drwav_allocation_callbacks allocationCallbacks;
510
511
512     /* Whether or not the WAV file is formatted as a standard RIFF file or W64. */
513     drwav_container container;
514
515
516     /* Structure containing format information exactly as specified by the wav file. */
517     drwav_fmt fmt;
518
519     /* The sample rate. Will be set to something like 44100. */
520     drwav_uint32 sampleRate;
521
522     /* The number of channels. This will be set to 1 for monaural streams, 2 for stereo, etc. */
523     drwav_uint16 channels;
524
525     /* The bits per sample. Will be set to something like 16, 24, etc. */
526     drwav_uint16 bitsPerSample;
527
528     /* Equal to fmt.formatTag, or the value specified by fmt.subFormat if fmt.formatTag is equal to 65534 (WAVE_FORMAT_EXTENSIBLE). */
529     drwav_uint16 translatedFormatTag;
530
531     /* The total number of PCM frames making up the audio data. */
532     drwav_uint64 totalPCMFrameCount;
533
534
535     /* The size in bytes of the data chunk. */
536     drwav_uint64 dataChunkDataSize;
537     
538     /* The position in the stream of the first data byte of the data chunk. This is used for seeking. */
539     drwav_uint64 dataChunkDataPos;
540
541     /* The number of bytes remaining in the data chunk. */
542     drwav_uint64 bytesRemaining;
543
544
545     /*
546     Only used in sequential write mode. Keeps track of the desired size of the "data" chunk at the point of initialization time. Always
547     set to 0 for non-sequential writes and when the drwav object is opened in read mode. Used for validation.
548     */
549     drwav_uint64 dataChunkDataSizeTargetWrite;
550
551     /* Keeps track of whether or not the wav writer was initialized in sequential mode. */
552     drwav_bool32 isSequentialWrite;
553
554
555     /* smpl chunk. */
556     drwav_smpl smpl;
557
558
559     /* A hack to avoid a DRWAV_MALLOC() when opening a decoder with drwav_init_memory(). */
560     drwav__memory_stream memoryStream;
561     drwav__memory_stream_write memoryStreamWrite;
562
563     /* Generic data for compressed formats. This data is shared across all block-compressed formats. */
564     struct
565     {
566         drwav_uint64 iCurrentPCMFrame;  /* The index of the next PCM frame that will be read by drwav_read_*(). This is used with "totalPCMFrameCount" to ensure we don't read excess samples at the end of the last block. */
567     } compressed;
568     
569     /* Microsoft ADPCM specific data. */
570     struct
571     {
572         drwav_uint32 bytesRemainingInBlock;
573         drwav_uint16 predictor[2];
574         drwav_int32  delta[2];
575         drwav_int32  cachedFrames[4];  /* Samples are stored in this cache during decoding. */
576         drwav_uint32 cachedFrameCount;
577         drwav_int32  prevFrames[2][2]; /* The previous 2 samples for each channel (2 channels at most). */
578     } msadpcm;
579
580     /* IMA ADPCM specific data. */
581     struct
582     {
583         drwav_uint32 bytesRemainingInBlock;
584         drwav_int32  predictor[2];
585         drwav_int32  stepIndex[2];
586         drwav_int32  cachedFrames[16]; /* Samples are stored in this cache during decoding. */
587         drwav_uint32 cachedFrameCount;
588     } ima;
589 } drwav;
590
591
592 /*
593 Initializes a pre-allocated drwav object for reading.
594
595 pWav                         [out]          A pointer to the drwav object being initialized.
596 onRead                       [in]           The function to call when data needs to be read from the client.
597 onSeek                       [in]           The function to call when the read position of the client data needs to move.
598 onChunk                      [in, optional] The function to call when a chunk is enumerated at initialized time.
599 pUserData, pReadSeekUserData [in, optional] A pointer to application defined data that will be passed to onRead and onSeek.
600 pChunkUserData               [in, optional] A pointer to application defined data that will be passed to onChunk.
601 flags                        [in, optional] A set of flags for controlling how things are loaded.
602
603 Returns true if successful; false otherwise.
604
605 Close the loader with drwav_uninit().
606
607 This is the lowest level function for initializing a WAV file. You can also use drwav_init_file() and drwav_init_memory()
608 to open the stream from a file or from a block of memory respectively.
609
610 Possible values for flags:
611   DRWAV_SEQUENTIAL: Never perform a backwards seek while loading. This disables the chunk callback and will cause this function
612                     to return as soon as the data chunk is found. Any chunks after the data chunk will be ignored.
613
614 drwav_init() is equivalent to "drwav_init_ex(pWav, onRead, onSeek, NULL, pUserData, NULL, 0);".
615
616 The onChunk callback is not called for the WAVE or FMT chunks. The contents of the FMT chunk can be read from pWav->fmt
617 after the function returns.
618
619 See also: drwav_init_file(), drwav_init_memory(), drwav_uninit()
620 */
621 DRWAV_API drwav_bool32 drwav_init(drwav* pWav, drwav_read_proc onRead, drwav_seek_proc onSeek, void* pUserData, const drwav_allocation_callbacks* pAllocationCallbacks);
622 DRWAV_API drwav_bool32 drwav_init_ex(drwav* pWav, drwav_read_proc onRead, drwav_seek_proc onSeek, drwav_chunk_proc onChunk, void* pReadSeekUserData, void* pChunkUserData, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks);
623
624 /*
625 Initializes a pre-allocated drwav object for writing.
626
627 onWrite   [in]           The function to call when data needs to be written.
628 onSeek    [in]           The function to call when the write position needs to move.
629 pUserData [in, optional] A pointer to application defined data that will be passed to onWrite and onSeek.
630
631 Returns true if successful; false otherwise.
632
633 Close the writer with drwav_uninit().
634
635 This is the lowest level function for initializing a WAV file. You can also use drwav_init_file_write() and drwav_init_memory_write()
636 to open the stream from a file or from a block of memory respectively.
637
638 If the total sample count is known, you can use drwav_init_write_sequential(). This avoids the need for dr_wav to perform
639 a post-processing step for storing the total sample count and the size of the data chunk which requires a backwards seek.
640
641 See also: drwav_init_file_write(), drwav_init_memory_write(), drwav_uninit()
642 */
643 DRWAV_API drwav_bool32 drwav_init_write(drwav* pWav, const drwav_data_format* pFormat, drwav_write_proc onWrite, drwav_seek_proc onSeek, void* pUserData, const drwav_allocation_callbacks* pAllocationCallbacks);
644 DRWAV_API drwav_bool32 drwav_init_write_sequential(drwav* pWav, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount, drwav_write_proc onWrite, void* pUserData, const drwav_allocation_callbacks* pAllocationCallbacks);
645 DRWAV_API drwav_bool32 drwav_init_write_sequential_pcm_frames(drwav* pWav, const drwav_data_format* pFormat, drwav_uint64 totalPCMFrameCount, drwav_write_proc onWrite, void* pUserData, const drwav_allocation_callbacks* pAllocationCallbacks);
646
647 /*
648 Utility function to determine the target size of the entire data to be written (including all headers and chunks).
649
650 Returns the target size in bytes.
651
652 Useful if the application needs to know the size to allocate.
653
654 Only writing to the RIFF chunk and one data chunk is currently supported.
655
656 See also: drwav_init_write(), drwav_init_file_write(), drwav_init_memory_write()
657 */
658 DRWAV_API drwav_uint64 drwav_target_write_size_bytes(const drwav_data_format* pFormat, drwav_uint64 totalSampleCount);
659
660 /*
661 Uninitializes the given drwav object.
662
663 Use this only for objects initialized with drwav_init*() functions (drwav_init(), drwav_init_ex(), drwav_init_write(), drwav_init_write_sequential()).
664 */
665 DRWAV_API drwav_result drwav_uninit(drwav* pWav);
666
667
668 /*
669 Reads raw audio data.
670
671 This is the lowest level function for reading audio data. It simply reads the given number of
672 bytes of the raw internal sample data.
673
674 Consider using drwav_read_pcm_frames_s16(), drwav_read_pcm_frames_s32() or drwav_read_pcm_frames_f32() for
675 reading sample data in a consistent format.
676
677 pBufferOut can be NULL in which case a seek will be performed.
678
679 Returns the number of bytes actually read.
680 */
681 DRWAV_API size_t drwav_read_raw(drwav* pWav, size_t bytesToRead, void* pBufferOut);
682
683 /*
684 Reads up to the specified number of PCM frames from the WAV file.
685
686 The output data will be in the file's internal format, converted to native-endian byte order. Use
687 drwav_read_pcm_frames_s16/f32/s32() to read data in a specific format.
688
689 If the return value is less than <framesToRead> it means the end of the file has been reached or
690 you have requested more PCM frames than can possibly fit in the output buffer.
691
692 This function will only work when sample data is of a fixed size and uncompressed. If you are
693 using a compressed format consider using drwav_read_raw() or drwav_read_pcm_frames_s16/s32/f32().
694
695 pBufferOut can be NULL in which case a seek will be performed.
696 */
697 DRWAV_API drwav_uint64 drwav_read_pcm_frames(drwav* pWav, drwav_uint64 framesToRead, void* pBufferOut);
698 DRWAV_API drwav_uint64 drwav_read_pcm_frames_le(drwav* pWav, drwav_uint64 framesToRead, void* pBufferOut);
699 DRWAV_API drwav_uint64 drwav_read_pcm_frames_be(drwav* pWav, drwav_uint64 framesToRead, void* pBufferOut);
700
701 /*
702 Seeks to the given PCM frame.
703
704 Returns true if successful; false otherwise.
705 */
706 DRWAV_API drwav_bool32 drwav_seek_to_pcm_frame(drwav* pWav, drwav_uint64 targetFrameIndex);
707
708
709 /*
710 Writes raw audio data.
711
712 Returns the number of bytes actually written. If this differs from bytesToWrite, it indicates an error.
713 */
714 DRWAV_API size_t drwav_write_raw(drwav* pWav, size_t bytesToWrite, const void* pData);
715
716 /*
717 Writes PCM frames.
718
719 Returns the number of PCM frames written.
720
721 Input samples need to be in native-endian byte order. On big-endian architectures the input data will be converted to
722 little-endian. Use drwav_write_raw() to write raw audio data without performing any conversion.
723 */
724 DRWAV_API drwav_uint64 drwav_write_pcm_frames(drwav* pWav, drwav_uint64 framesToWrite, const void* pData);
725 DRWAV_API drwav_uint64 drwav_write_pcm_frames_le(drwav* pWav, drwav_uint64 framesToWrite, const void* pData);
726 DRWAV_API drwav_uint64 drwav_write_pcm_frames_be(drwav* pWav, drwav_uint64 framesToWrite, const void* pData);
727
728
729 /* Conversion Utilities */
730 #ifndef DR_WAV_NO_CONVERSION_API
731
732 /*
733 Reads a chunk of audio data and converts it to signed 16-bit PCM samples.
734
735 pBufferOut can be NULL in which case a seek will be performed.
736
737 Returns the number of PCM frames actually read.
738
739 If the return value is less than <framesToRead> it means the end of the file has been reached.
740 */
741 DRWAV_API drwav_uint64 drwav_read_pcm_frames_s16(drwav* pWav, drwav_uint64 framesToRead, drwav_int16* pBufferOut);
742 DRWAV_API drwav_uint64 drwav_read_pcm_frames_s16le(drwav* pWav, drwav_uint64 framesToRead, drwav_int16* pBufferOut);
743 DRWAV_API drwav_uint64 drwav_read_pcm_frames_s16be(drwav* pWav, drwav_uint64 framesToRead, drwav_int16* pBufferOut);
744
745 /* Low-level function for converting unsigned 8-bit PCM samples to signed 16-bit PCM samples. */
746 DRWAV_API void drwav_u8_to_s16(drwav_int16* pOut, const drwav_uint8* pIn, size_t sampleCount);
747
748 /* Low-level function for converting signed 24-bit PCM samples to signed 16-bit PCM samples. */
749 DRWAV_API void drwav_s24_to_s16(drwav_int16* pOut, const drwav_uint8* pIn, size_t sampleCount);
750
751 /* Low-level function for converting signed 32-bit PCM samples to signed 16-bit PCM samples. */
752 DRWAV_API void drwav_s32_to_s16(drwav_int16* pOut, const drwav_int32* pIn, size_t sampleCount);
753
754 /* Low-level function for converting IEEE 32-bit floating point samples to signed 16-bit PCM samples. */
755 DRWAV_API void drwav_f32_to_s16(drwav_int16* pOut, const float* pIn, size_t sampleCount);
756
757 /* Low-level function for converting IEEE 64-bit floating point samples to signed 16-bit PCM samples. */
758 DRWAV_API void drwav_f64_to_s16(drwav_int16* pOut, const double* pIn, size_t sampleCount);
759
760 /* Low-level function for converting A-law samples to signed 16-bit PCM samples. */
761 DRWAV_API void drwav_alaw_to_s16(drwav_int16* pOut, const drwav_uint8* pIn, size_t sampleCount);
762
763 /* Low-level function for converting u-law samples to signed 16-bit PCM samples. */
764 DRWAV_API void drwav_mulaw_to_s16(drwav_int16* pOut, const drwav_uint8* pIn, size_t sampleCount);
765
766
767 /*
768 Reads a chunk of audio data and converts it to IEEE 32-bit floating point samples.
769
770 pBufferOut can be NULL in which case a seek will be performed.
771
772 Returns the number of PCM frames actually read.
773
774 If the return value is less than <framesToRead> it means the end of the file has been reached.
775 */
776 DRWAV_API drwav_uint64 drwav_read_pcm_frames_f32(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut);
777 DRWAV_API drwav_uint64 drwav_read_pcm_frames_f32le(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut);
778 DRWAV_API drwav_uint64 drwav_read_pcm_frames_f32be(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut);
779
780 /* Low-level function for converting unsigned 8-bit PCM samples to IEEE 32-bit floating point samples. */
781 DRWAV_API void drwav_u8_to_f32(float* pOut, const drwav_uint8* pIn, size_t sampleCount);
782
783 /* Low-level function for converting signed 16-bit PCM samples to IEEE 32-bit floating point samples. */
784 DRWAV_API void drwav_s16_to_f32(float* pOut, const drwav_int16* pIn, size_t sampleCount);
785
786 /* Low-level function for converting signed 24-bit PCM samples to IEEE 32-bit floating point samples. */
787 DRWAV_API void drwav_s24_to_f32(float* pOut, const drwav_uint8* pIn, size_t sampleCount);
788
789 /* Low-level function for converting signed 32-bit PCM samples to IEEE 32-bit floating point samples. */
790 DRWAV_API void drwav_s32_to_f32(float* pOut, const drwav_int32* pIn, size_t sampleCount);
791
792 /* Low-level function for converting IEEE 64-bit floating point samples to IEEE 32-bit floating point samples. */
793 DRWAV_API void drwav_f64_to_f32(float* pOut, const double* pIn, size_t sampleCount);
794
795 /* Low-level function for converting A-law samples to IEEE 32-bit floating point samples. */
796 DRWAV_API void drwav_alaw_to_f32(float* pOut, const drwav_uint8* pIn, size_t sampleCount);
797
798 /* Low-level function for converting u-law samples to IEEE 32-bit floating point samples. */
799 DRWAV_API void drwav_mulaw_to_f32(float* pOut, const drwav_uint8* pIn, size_t sampleCount);
800
801
802 /*
803 Reads a chunk of audio data and converts it to signed 32-bit PCM samples.
804
805 pBufferOut can be NULL in which case a seek will be performed.
806
807 Returns the number of PCM frames actually read.
808
809 If the return value is less than <framesToRead> it means the end of the file has been reached.
810 */
811 DRWAV_API drwav_uint64 drwav_read_pcm_frames_s32(drwav* pWav, drwav_uint64 framesToRead, drwav_int32* pBufferOut);
812 DRWAV_API drwav_uint64 drwav_read_pcm_frames_s32le(drwav* pWav, drwav_uint64 framesToRead, drwav_int32* pBufferOut);
813 DRWAV_API drwav_uint64 drwav_read_pcm_frames_s32be(drwav* pWav, drwav_uint64 framesToRead, drwav_int32* pBufferOut);
814
815 /* Low-level function for converting unsigned 8-bit PCM samples to signed 32-bit PCM samples. */
816 DRWAV_API void drwav_u8_to_s32(drwav_int32* pOut, const drwav_uint8* pIn, size_t sampleCount);
817
818 /* Low-level function for converting signed 16-bit PCM samples to signed 32-bit PCM samples. */
819 DRWAV_API void drwav_s16_to_s32(drwav_int32* pOut, const drwav_int16* pIn, size_t sampleCount);
820
821 /* Low-level function for converting signed 24-bit PCM samples to signed 32-bit PCM samples. */
822 DRWAV_API void drwav_s24_to_s32(drwav_int32* pOut, const drwav_uint8* pIn, size_t sampleCount);
823
824 /* Low-level function for converting IEEE 32-bit floating point samples to signed 32-bit PCM samples. */
825 DRWAV_API void drwav_f32_to_s32(drwav_int32* pOut, const float* pIn, size_t sampleCount);
826
827 /* Low-level function for converting IEEE 64-bit floating point samples to signed 32-bit PCM samples. */
828 DRWAV_API void drwav_f64_to_s32(drwav_int32* pOut, const double* pIn, size_t sampleCount);
829
830 /* Low-level function for converting A-law samples to signed 32-bit PCM samples. */
831 DRWAV_API void drwav_alaw_to_s32(drwav_int32* pOut, const drwav_uint8* pIn, size_t sampleCount);
832
833 /* Low-level function for converting u-law samples to signed 32-bit PCM samples. */
834 DRWAV_API void drwav_mulaw_to_s32(drwav_int32* pOut, const drwav_uint8* pIn, size_t sampleCount);
835
836 #endif  /* DR_WAV_NO_CONVERSION_API */
837
838
839 /* High-Level Convenience Helpers */
840
841 #ifndef DR_WAV_NO_STDIO
842 /*
843 Helper for initializing a wave file for reading using stdio.
844
845 This holds the internal FILE object until drwav_uninit() is called. Keep this in mind if you're caching drwav
846 objects because the operating system may restrict the number of file handles an application can have open at
847 any given time.
848 */
849 DRWAV_API drwav_bool32 drwav_init_file(drwav* pWav, const char* filename, const drwav_allocation_callbacks* pAllocationCallbacks);
850 DRWAV_API drwav_bool32 drwav_init_file_ex(drwav* pWav, const char* filename, drwav_chunk_proc onChunk, void* pChunkUserData, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks);
851 DRWAV_API drwav_bool32 drwav_init_file_w(drwav* pWav, const wchar_t* filename, const drwav_allocation_callbacks* pAllocationCallbacks);
852 DRWAV_API drwav_bool32 drwav_init_file_ex_w(drwav* pWav, const wchar_t* filename, drwav_chunk_proc onChunk, void* pChunkUserData, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks);
853
854 /*
855 Helper for initializing a wave file for writing using stdio.
856
857 This holds the internal FILE object until drwav_uninit() is called. Keep this in mind if you're caching drwav
858 objects because the operating system may restrict the number of file handles an application can have open at
859 any given time.
860 */
861 DRWAV_API drwav_bool32 drwav_init_file_write(drwav* pWav, const char* filename, const drwav_data_format* pFormat, const drwav_allocation_callbacks* pAllocationCallbacks);
862 DRWAV_API drwav_bool32 drwav_init_file_write_sequential(drwav* pWav, const char* filename, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount, const drwav_allocation_callbacks* pAllocationCallbacks);
863 DRWAV_API drwav_bool32 drwav_init_file_write_sequential_pcm_frames(drwav* pWav, const char* filename, const drwav_data_format* pFormat, drwav_uint64 totalPCMFrameCount, const drwav_allocation_callbacks* pAllocationCallbacks);
864 DRWAV_API drwav_bool32 drwav_init_file_write_w(drwav* pWav, const wchar_t* filename, const drwav_data_format* pFormat, const drwav_allocation_callbacks* pAllocationCallbacks);
865 DRWAV_API drwav_bool32 drwav_init_file_write_sequential_w(drwav* pWav, const wchar_t* filename, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount, const drwav_allocation_callbacks* pAllocationCallbacks);
866 DRWAV_API drwav_bool32 drwav_init_file_write_sequential_pcm_frames_w(drwav* pWav, const wchar_t* filename, const drwav_data_format* pFormat, drwav_uint64 totalPCMFrameCount, const drwav_allocation_callbacks* pAllocationCallbacks);
867 #endif  /* DR_WAV_NO_STDIO */
868
869 /*
870 Helper for initializing a loader from a pre-allocated memory buffer.
871
872 This does not create a copy of the data. It is up to the application to ensure the buffer remains valid for
873 the lifetime of the drwav object.
874
875 The buffer should contain the contents of the entire wave file, not just the sample data.
876 */
877 DRWAV_API drwav_bool32 drwav_init_memory(drwav* pWav, const void* data, size_t dataSize, const drwav_allocation_callbacks* pAllocationCallbacks);
878 DRWAV_API drwav_bool32 drwav_init_memory_ex(drwav* pWav, const void* data, size_t dataSize, drwav_chunk_proc onChunk, void* pChunkUserData, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks);
879
880 /*
881 Helper for initializing a writer which outputs data to a memory buffer.
882
883 dr_wav will manage the memory allocations, however it is up to the caller to free the data with drwav_free().
884
885 The buffer will remain allocated even after drwav_uninit() is called. The buffer should not be considered valid
886 until after drwav_uninit() has been called.
887 */
888 DRWAV_API drwav_bool32 drwav_init_memory_write(drwav* pWav, void** ppData, size_t* pDataSize, const drwav_data_format* pFormat, const drwav_allocation_callbacks* pAllocationCallbacks);
889 DRWAV_API drwav_bool32 drwav_init_memory_write_sequential(drwav* pWav, void** ppData, size_t* pDataSize, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount, const drwav_allocation_callbacks* pAllocationCallbacks);
890 DRWAV_API drwav_bool32 drwav_init_memory_write_sequential_pcm_frames(drwav* pWav, void** ppData, size_t* pDataSize, const drwav_data_format* pFormat, drwav_uint64 totalPCMFrameCount, const drwav_allocation_callbacks* pAllocationCallbacks);
891
892
893 #ifndef DR_WAV_NO_CONVERSION_API
894 /*
895 Opens and reads an entire wav file in a single operation.
896
897 The return value is a heap-allocated buffer containing the audio data. Use drwav_free() to free the buffer.
898 */
899 DRWAV_API drwav_int16* drwav_open_and_read_pcm_frames_s16(drwav_read_proc onRead, drwav_seek_proc onSeek, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks);
900 DRWAV_API float* drwav_open_and_read_pcm_frames_f32(drwav_read_proc onRead, drwav_seek_proc onSeek, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks);
901 DRWAV_API drwav_int32* drwav_open_and_read_pcm_frames_s32(drwav_read_proc onRead, drwav_seek_proc onSeek, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks);
902 #ifndef DR_WAV_NO_STDIO
903 /*
904 Opens and decodes an entire wav file in a single operation.
905
906 The return value is a heap-allocated buffer containing the audio data. Use drwav_free() to free the buffer.
907 */
908 DRWAV_API drwav_int16* drwav_open_file_and_read_pcm_frames_s16(const char* filename, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks);
909 DRWAV_API float* drwav_open_file_and_read_pcm_frames_f32(const char* filename, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks);
910 DRWAV_API drwav_int32* drwav_open_file_and_read_pcm_frames_s32(const char* filename, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks);
911 DRWAV_API drwav_int16* drwav_open_file_and_read_pcm_frames_s16_w(const wchar_t* filename, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks);
912 DRWAV_API float* drwav_open_file_and_read_pcm_frames_f32_w(const wchar_t* filename, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks);
913 DRWAV_API drwav_int32* drwav_open_file_and_read_pcm_frames_s32_w(const wchar_t* filename, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks);
914 #endif
915 /*
916 Opens and decodes an entire wav file from a block of memory in a single operation.
917
918 The return value is a heap-allocated buffer containing the audio data. Use drwav_free() to free the buffer.
919 */
920 DRWAV_API drwav_int16* drwav_open_memory_and_read_pcm_frames_s16(const void* data, size_t dataSize, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks);
921 DRWAV_API float* drwav_open_memory_and_read_pcm_frames_f32(const void* data, size_t dataSize, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks);
922 DRWAV_API drwav_int32* drwav_open_memory_and_read_pcm_frames_s32(const void* data, size_t dataSize, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks);
923 #endif
924
925 /* Frees data that was allocated internally by dr_wav. */
926 DRWAV_API void drwav_free(void* p, const drwav_allocation_callbacks* pAllocationCallbacks);
927
928 /* Converts bytes from a wav stream to a sized type of native endian. */
929 DRWAV_API drwav_uint16 drwav_bytes_to_u16(const drwav_uint8* data);
930 DRWAV_API drwav_int16 drwav_bytes_to_s16(const drwav_uint8* data);
931 DRWAV_API drwav_uint32 drwav_bytes_to_u32(const drwav_uint8* data);
932 DRWAV_API drwav_int32 drwav_bytes_to_s32(const drwav_uint8* data);
933 DRWAV_API drwav_uint64 drwav_bytes_to_u64(const drwav_uint8* data);
934 DRWAV_API drwav_int64 drwav_bytes_to_s64(const drwav_uint8* data);
935
936 /* Compares a GUID for the purpose of checking the type of a Wave64 chunk. */
937 DRWAV_API drwav_bool32 drwav_guid_equal(const drwav_uint8 a[16], const drwav_uint8 b[16]);
938
939 /* Compares a four-character-code for the purpose of checking the type of a RIFF chunk. */
940 DRWAV_API drwav_bool32 drwav_fourcc_equal(const drwav_uint8* a, const char* b);
941
942 #ifdef __cplusplus
943 }
944 #endif
945 #endif  /* dr_wav_h */
946
947
948 /************************************************************************************************************************************************************
949  ************************************************************************************************************************************************************
950
951  IMPLEMENTATION
952
953  ************************************************************************************************************************************************************
954  ************************************************************************************************************************************************************/
955 #if defined(DR_WAV_IMPLEMENTATION) || defined(DRWAV_IMPLEMENTATION)
956 #ifndef dr_wav_c
957 #define dr_wav_c
958
959 #include <stdlib.h>
960 #include <string.h> /* For memcpy(), memset() */
961 #include <limits.h> /* For INT_MAX */
962
963 #ifndef DR_WAV_NO_STDIO
964 #include <stdio.h>
965 #include <wchar.h>
966 #endif
967
968 /* Standard library stuff. */
969 #ifndef DRWAV_ASSERT
970 #include <assert.h>
971 #define DRWAV_ASSERT(expression)           assert(expression)
972 #endif
973 #ifndef DRWAV_MALLOC
974 #define DRWAV_MALLOC(sz)                   malloc((sz))
975 #endif
976 #ifndef DRWAV_REALLOC
977 #define DRWAV_REALLOC(p, sz)               realloc((p), (sz))
978 #endif
979 #ifndef DRWAV_FREE
980 #define DRWAV_FREE(p)                      free((p))
981 #endif
982 #ifndef DRWAV_COPY_MEMORY
983 #define DRWAV_COPY_MEMORY(dst, src, sz)    memcpy((dst), (src), (sz))
984 #endif
985 #ifndef DRWAV_ZERO_MEMORY
986 #define DRWAV_ZERO_MEMORY(p, sz)           memset((p), 0, (sz))
987 #endif
988 #ifndef DRWAV_ZERO_OBJECT
989 #define DRWAV_ZERO_OBJECT(p)               DRWAV_ZERO_MEMORY((p), sizeof(*p))
990 #endif
991
992 #define drwav_countof(x)                   (sizeof(x) / sizeof(x[0]))
993 #define drwav_align(x, a)                  ((((x) + (a) - 1) / (a)) * (a))
994 #define drwav_min(a, b)                    (((a) < (b)) ? (a) : (b))
995 #define drwav_max(a, b)                    (((a) > (b)) ? (a) : (b))
996 #define drwav_clamp(x, lo, hi)             (drwav_max((lo), drwav_min((hi), (x))))
997
998 #define DRWAV_MAX_SIMD_VECTOR_SIZE         64  /* 64 for AVX-512 in the future. */
999
1000 /* CPU architecture. */
1001 #if defined(__x86_64__) || defined(_M_X64)
1002     #define DRWAV_X64
1003 #elif defined(__i386) || defined(_M_IX86)
1004     #define DRWAV_X86
1005 #elif defined(__arm__) || defined(_M_ARM)
1006     #define DRWAV_ARM
1007 #endif
1008
1009 #ifdef _MSC_VER
1010     #define DRWAV_INLINE __forceinline
1011 #elif defined(__GNUC__)
1012     /*
1013     I've had a bug report where GCC is emitting warnings about functions possibly not being inlineable. This warning happens when
1014     the __attribute__((always_inline)) attribute is defined without an "inline" statement. I think therefore there must be some
1015     case where "__inline__" is not always defined, thus the compiler emitting these warnings. When using -std=c89 or -ansi on the
1016     command line, we cannot use the "inline" keyword and instead need to use "__inline__". In an attempt to work around this issue
1017     I am using "__inline__" only when we're compiling in strict ANSI mode.
1018     */
1019     #if defined(__STRICT_ANSI__)
1020         #define DRWAV_INLINE __inline__ __attribute__((always_inline))
1021     #else
1022         #define DRWAV_INLINE inline __attribute__((always_inline))
1023     #endif
1024 #elif defined(__WATCOMC__)
1025     #define DRWAV_INLINE __inline
1026 #else
1027     #define DRWAV_INLINE
1028 #endif
1029
1030 #if defined(SIZE_MAX)
1031     #define DRWAV_SIZE_MAX  SIZE_MAX
1032 #else
1033     #if defined(_WIN64) || defined(_LP64) || defined(__LP64__)
1034         #define DRWAV_SIZE_MAX  ((drwav_uint64)0xFFFFFFFFFFFFFFFF)
1035     #else
1036         #define DRWAV_SIZE_MAX  0xFFFFFFFF
1037     #endif
1038 #endif
1039
1040 #if defined(_MSC_VER) && _MSC_VER >= 1400
1041     #define DRWAV_HAS_BYTESWAP16_INTRINSIC
1042     #define DRWAV_HAS_BYTESWAP32_INTRINSIC
1043     #define DRWAV_HAS_BYTESWAP64_INTRINSIC
1044 #elif defined(__clang__)
1045     #if defined(__has_builtin)
1046         #if __has_builtin(__builtin_bswap16)
1047             #define DRWAV_HAS_BYTESWAP16_INTRINSIC
1048         #endif
1049         #if __has_builtin(__builtin_bswap32)
1050             #define DRWAV_HAS_BYTESWAP32_INTRINSIC
1051         #endif
1052         #if __has_builtin(__builtin_bswap64)
1053             #define DRWAV_HAS_BYTESWAP64_INTRINSIC
1054         #endif
1055     #endif
1056 #elif defined(__GNUC__)
1057     #if ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
1058         #define DRWAV_HAS_BYTESWAP32_INTRINSIC
1059         #define DRWAV_HAS_BYTESWAP64_INTRINSIC
1060     #endif
1061     #if ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))
1062         #define DRWAV_HAS_BYTESWAP16_INTRINSIC
1063     #endif
1064 #endif
1065
1066 DRWAV_API void drwav_version(drwav_uint32* pMajor, drwav_uint32* pMinor, drwav_uint32* pRevision)
1067 {
1068     if (pMajor) {
1069         *pMajor = DRWAV_VERSION_MAJOR;
1070     }
1071
1072     if (pMinor) {
1073         *pMinor = DRWAV_VERSION_MINOR;
1074     }
1075
1076     if (pRevision) {
1077         *pRevision = DRWAV_VERSION_REVISION;
1078     }
1079 }
1080
1081 DRWAV_API const char* drwav_version_string(void)
1082 {
1083     return DRWAV_VERSION_STRING;
1084 }
1085
1086 /*
1087 These limits are used for basic validation when initializing the decoder. If you exceed these limits, first of all: what on Earth are
1088 you doing?! (Let me know, I'd be curious!) Second, you can adjust these by #define-ing them before the dr_wav implementation.
1089 */
1090 #ifndef DRWAV_MAX_SAMPLE_RATE
1091 #define DRWAV_MAX_SAMPLE_RATE       384000
1092 #endif
1093 #ifndef DRWAV_MAX_CHANNELS
1094 #define DRWAV_MAX_CHANNELS          256
1095 #endif
1096 #ifndef DRWAV_MAX_BITS_PER_SAMPLE
1097 #define DRWAV_MAX_BITS_PER_SAMPLE   64
1098 #endif
1099
1100 static const drwav_uint8 drwavGUID_W64_RIFF[16] = {0x72,0x69,0x66,0x66, 0x2E,0x91, 0xCF,0x11, 0xA5,0xD6, 0x28,0xDB,0x04,0xC1,0x00,0x00};    /* 66666972-912E-11CF-A5D6-28DB04C10000 */
1101 static const drwav_uint8 drwavGUID_W64_WAVE[16] = {0x77,0x61,0x76,0x65, 0xF3,0xAC, 0xD3,0x11, 0x8C,0xD1, 0x00,0xC0,0x4F,0x8E,0xDB,0x8A};    /* 65766177-ACF3-11D3-8CD1-00C04F8EDB8A */
1102 /*static const drwav_uint8 drwavGUID_W64_JUNK[16] = {0x6A,0x75,0x6E,0x6B, 0xF3,0xAC, 0xD3,0x11, 0x8C,0xD1, 0x00,0xC0,0x4F,0x8E,0xDB,0x8A};*/    /* 6B6E756A-ACF3-11D3-8CD1-00C04F8EDB8A */
1103 static const drwav_uint8 drwavGUID_W64_FMT [16] = {0x66,0x6D,0x74,0x20, 0xF3,0xAC, 0xD3,0x11, 0x8C,0xD1, 0x00,0xC0,0x4F,0x8E,0xDB,0x8A};    /* 20746D66-ACF3-11D3-8CD1-00C04F8EDB8A */
1104 static const drwav_uint8 drwavGUID_W64_FACT[16] = {0x66,0x61,0x63,0x74, 0xF3,0xAC, 0xD3,0x11, 0x8C,0xD1, 0x00,0xC0,0x4F,0x8E,0xDB,0x8A};    /* 74636166-ACF3-11D3-8CD1-00C04F8EDB8A */
1105 static const drwav_uint8 drwavGUID_W64_DATA[16] = {0x64,0x61,0x74,0x61, 0xF3,0xAC, 0xD3,0x11, 0x8C,0xD1, 0x00,0xC0,0x4F,0x8E,0xDB,0x8A};    /* 61746164-ACF3-11D3-8CD1-00C04F8EDB8A */
1106 static const drwav_uint8 drwavGUID_W64_SMPL[16] = {0x73,0x6D,0x70,0x6C, 0xF3,0xAC, 0xD3,0x11, 0x8C,0xD1, 0x00,0xC0,0x4F,0x8E,0xDB,0x8A};    /* 6C706D73-ACF3-11D3-8CD1-00C04F8EDB8A */
1107
1108
1109 static DRWAV_INLINE int drwav__is_little_endian(void)
1110 {
1111 #if defined(DRWAV_X86) || defined(DRWAV_X64)
1112     return DRWAV_TRUE;
1113 #elif defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && __BYTE_ORDER == __LITTLE_ENDIAN
1114     return DRWAV_TRUE;
1115 #else
1116     int n = 1;
1117     return (*(char*)&n) == 1;
1118 #endif
1119 }
1120
1121
1122 static DRWAV_INLINE void drwav__bytes_to_guid(const drwav_uint8* data, drwav_uint8* guid)
1123 {
1124     int i;
1125     for (i = 0; i < 16; ++i) {
1126         guid[i] = data[i];
1127     }
1128 }
1129
1130
1131 static DRWAV_INLINE drwav_uint16 drwav__bswap16(drwav_uint16 n)
1132 {
1133 #ifdef DRWAV_HAS_BYTESWAP16_INTRINSIC
1134     #if defined(_MSC_VER)
1135         return _byteswap_ushort(n);
1136     #elif defined(__GNUC__) || defined(__clang__)
1137         return __builtin_bswap16(n);
1138     #else
1139         #error "This compiler does not support the byte swap intrinsic."
1140     #endif
1141 #else
1142     return ((n & 0xFF00) >> 8) |
1143            ((n & 0x00FF) << 8);
1144 #endif
1145 }
1146
1147 static DRWAV_INLINE drwav_uint32 drwav__bswap32(drwav_uint32 n)
1148 {
1149 #ifdef DRWAV_HAS_BYTESWAP32_INTRINSIC
1150     #if defined(_MSC_VER)
1151         return _byteswap_ulong(n);
1152     #elif defined(__GNUC__) || defined(__clang__)
1153         #if defined(DRWAV_ARM) && (defined(__ARM_ARCH) && __ARM_ARCH >= 6) && !defined(DRWAV_64BIT)   /* <-- 64-bit inline assembly has not been tested, so disabling for now. */
1154             /* Inline assembly optimized implementation for ARM. In my testing, GCC does not generate optimized code with __builtin_bswap32(). */
1155             drwav_uint32 r;
1156             __asm__ __volatile__ (
1157             #if defined(DRWAV_64BIT)
1158                 "rev %w[out], %w[in]" : [out]"=r"(r) : [in]"r"(n)   /* <-- This is untested. If someone in the community could test this, that would be appreciated! */
1159             #else
1160                 "rev %[out], %[in]" : [out]"=r"(r) : [in]"r"(n)
1161             #endif
1162             );
1163             return r;
1164         #else
1165             return __builtin_bswap32(n);
1166         #endif
1167     #else
1168         #error "This compiler does not support the byte swap intrinsic."
1169     #endif
1170 #else
1171     return ((n & 0xFF000000) >> 24) |
1172            ((n & 0x00FF0000) >>  8) |
1173            ((n & 0x0000FF00) <<  8) |
1174            ((n & 0x000000FF) << 24);
1175 #endif
1176 }
1177
1178 static DRWAV_INLINE drwav_uint64 drwav__bswap64(drwav_uint64 n)
1179 {
1180 #ifdef DRWAV_HAS_BYTESWAP64_INTRINSIC
1181     #if defined(_MSC_VER)
1182         return _byteswap_uint64(n);
1183     #elif defined(__GNUC__) || defined(__clang__)
1184         return __builtin_bswap64(n);
1185     #else
1186         #error "This compiler does not support the byte swap intrinsic."
1187     #endif
1188 #else
1189     /* Weird "<< 32" bitshift is required for C89 because it doesn't support 64-bit constants. Should be optimized out by a good compiler. */
1190     return ((n & ((drwav_uint64)0xFF000000 << 32)) >> 56) |
1191            ((n & ((drwav_uint64)0x00FF0000 << 32)) >> 40) |
1192            ((n & ((drwav_uint64)0x0000FF00 << 32)) >> 24) |
1193            ((n & ((drwav_uint64)0x000000FF << 32)) >>  8) |
1194            ((n & ((drwav_uint64)0xFF000000      )) <<  8) |
1195            ((n & ((drwav_uint64)0x00FF0000      )) << 24) |
1196            ((n & ((drwav_uint64)0x0000FF00      )) << 40) |
1197            ((n & ((drwav_uint64)0x000000FF      )) << 56);
1198 #endif
1199 }
1200
1201
1202 static DRWAV_INLINE drwav_int16 drwav__bswap_s16(drwav_int16 n)
1203 {
1204     return (drwav_int16)drwav__bswap16((drwav_uint16)n);
1205 }
1206
1207 static DRWAV_INLINE void drwav__bswap_samples_s16(drwav_int16* pSamples, drwav_uint64 sampleCount)
1208 {
1209     drwav_uint64 iSample;
1210     for (iSample = 0; iSample < sampleCount; iSample += 1) {
1211         pSamples[iSample] = drwav__bswap_s16(pSamples[iSample]);
1212     }
1213 }
1214
1215
1216 static DRWAV_INLINE void drwav__bswap_s24(drwav_uint8* p)
1217 {
1218     drwav_uint8 t;
1219     t = p[0];
1220     p[0] = p[2];
1221     p[2] = t;
1222 }
1223
1224 static DRWAV_INLINE void drwav__bswap_samples_s24(drwav_uint8* pSamples, drwav_uint64 sampleCount)
1225 {
1226     drwav_uint64 iSample;
1227     for (iSample = 0; iSample < sampleCount; iSample += 1) {
1228         drwav_uint8* pSample = pSamples + (iSample*3);
1229         drwav__bswap_s24(pSample);
1230     }
1231 }
1232
1233
1234 static DRWAV_INLINE drwav_int32 drwav__bswap_s32(drwav_int32 n)
1235 {
1236     return (drwav_int32)drwav__bswap32((drwav_uint32)n);
1237 }
1238
1239 static DRWAV_INLINE void drwav__bswap_samples_s32(drwav_int32* pSamples, drwav_uint64 sampleCount)
1240 {
1241     drwav_uint64 iSample;
1242     for (iSample = 0; iSample < sampleCount; iSample += 1) {
1243         pSamples[iSample] = drwav__bswap_s32(pSamples[iSample]);
1244     }
1245 }
1246
1247
1248 static DRWAV_INLINE float drwav__bswap_f32(float n)
1249 {
1250     union {
1251         drwav_uint32 i;
1252         float f;
1253     } x;
1254     x.f = n;
1255     x.i = drwav__bswap32(x.i);
1256
1257     return x.f;
1258 }
1259
1260 static DRWAV_INLINE void drwav__bswap_samples_f32(float* pSamples, drwav_uint64 sampleCount)
1261 {
1262     drwav_uint64 iSample;
1263     for (iSample = 0; iSample < sampleCount; iSample += 1) {
1264         pSamples[iSample] = drwav__bswap_f32(pSamples[iSample]);
1265     }
1266 }
1267
1268
1269 static DRWAV_INLINE double drwav__bswap_f64(double n)
1270 {
1271     union {
1272         drwav_uint64 i;
1273         double f;
1274     } x;
1275     x.f = n;
1276     x.i = drwav__bswap64(x.i);
1277
1278     return x.f;
1279 }
1280
1281 static DRWAV_INLINE void drwav__bswap_samples_f64(double* pSamples, drwav_uint64 sampleCount)
1282 {
1283     drwav_uint64 iSample;
1284     for (iSample = 0; iSample < sampleCount; iSample += 1) {
1285         pSamples[iSample] = drwav__bswap_f64(pSamples[iSample]);
1286     }
1287 }
1288
1289
1290 static DRWAV_INLINE void drwav__bswap_samples_pcm(void* pSamples, drwav_uint64 sampleCount, drwav_uint32 bytesPerSample)
1291 {
1292     /* Assumes integer PCM. Floating point PCM is done in drwav__bswap_samples_ieee(). */
1293     switch (bytesPerSample)
1294     {
1295         case 2: /* s16, s12 (loosely packed) */
1296         {
1297             drwav__bswap_samples_s16((drwav_int16*)pSamples, sampleCount);
1298         } break;
1299         case 3: /* s24 */
1300         {
1301             drwav__bswap_samples_s24((drwav_uint8*)pSamples, sampleCount);
1302         } break;
1303         case 4: /* s32 */
1304         {
1305             drwav__bswap_samples_s32((drwav_int32*)pSamples, sampleCount);
1306         } break;
1307         default:
1308         {
1309             /* Unsupported format. */
1310             DRWAV_ASSERT(DRWAV_FALSE);
1311         } break;
1312     }
1313 }
1314
1315 static DRWAV_INLINE void drwav__bswap_samples_ieee(void* pSamples, drwav_uint64 sampleCount, drwav_uint32 bytesPerSample)
1316 {
1317     switch (bytesPerSample)
1318     {
1319     #if 0   /* Contributions welcome for f16 support. */
1320         case 2: /* f16 */
1321         {
1322             drwav__bswap_samples_f16((drwav_float16*)pSamples, sampleCount);
1323         } break;
1324     #endif
1325         case 4: /* f32 */
1326         {
1327             drwav__bswap_samples_f32((float*)pSamples, sampleCount);
1328         } break;
1329         case 8: /* f64 */
1330         {
1331             drwav__bswap_samples_f64((double*)pSamples, sampleCount);
1332         } break;
1333         default:
1334         {
1335             /* Unsupported format. */
1336             DRWAV_ASSERT(DRWAV_FALSE);
1337         } break;
1338     }
1339 }
1340
1341 static DRWAV_INLINE void drwav__bswap_samples(void* pSamples, drwav_uint64 sampleCount, drwav_uint32 bytesPerSample, drwav_uint16 format)
1342 {
1343     switch (format)
1344     {
1345         case DR_WAVE_FORMAT_PCM:
1346         {
1347             drwav__bswap_samples_pcm(pSamples, sampleCount, bytesPerSample);
1348         } break;
1349
1350         case DR_WAVE_FORMAT_IEEE_FLOAT:
1351         {
1352             drwav__bswap_samples_ieee(pSamples, sampleCount, bytesPerSample);
1353         } break;
1354
1355         case DR_WAVE_FORMAT_ALAW:
1356         case DR_WAVE_FORMAT_MULAW:
1357         {
1358             drwav__bswap_samples_s16((drwav_int16*)pSamples, sampleCount);
1359         } break;
1360
1361         case DR_WAVE_FORMAT_ADPCM:
1362         case DR_WAVE_FORMAT_DVI_ADPCM:
1363         default:
1364         {
1365             /* Unsupported format. */
1366             DRWAV_ASSERT(DRWAV_FALSE);
1367         } break;
1368     }
1369 }
1370
1371
1372 DRWAV_PRIVATE void* drwav__malloc_default(size_t sz, void* pUserData)
1373 {
1374     (void)pUserData;
1375     return DRWAV_MALLOC(sz);
1376 }
1377
1378 DRWAV_PRIVATE void* drwav__realloc_default(void* p, size_t sz, void* pUserData)
1379 {
1380     (void)pUserData;
1381     return DRWAV_REALLOC(p, sz);
1382 }
1383
1384 DRWAV_PRIVATE void drwav__free_default(void* p, void* pUserData)
1385 {
1386     (void)pUserData;
1387     DRWAV_FREE(p);
1388 }
1389
1390
1391 DRWAV_PRIVATE void* drwav__malloc_from_callbacks(size_t sz, const drwav_allocation_callbacks* pAllocationCallbacks)
1392 {
1393     if (pAllocationCallbacks == NULL) {
1394         return NULL;
1395     }
1396
1397     if (pAllocationCallbacks->onMalloc != NULL) {
1398         return pAllocationCallbacks->onMalloc(sz, pAllocationCallbacks->pUserData);
1399     }
1400
1401     /* Try using realloc(). */
1402     if (pAllocationCallbacks->onRealloc != NULL) {
1403         return pAllocationCallbacks->onRealloc(NULL, sz, pAllocationCallbacks->pUserData);
1404     }
1405
1406     return NULL;
1407 }
1408
1409 DRWAV_PRIVATE void* drwav__realloc_from_callbacks(void* p, size_t szNew, size_t szOld, const drwav_allocation_callbacks* pAllocationCallbacks)
1410 {
1411     if (pAllocationCallbacks == NULL) {
1412         return NULL;
1413     }
1414
1415     if (pAllocationCallbacks->onRealloc != NULL) {
1416         return pAllocationCallbacks->onRealloc(p, szNew, pAllocationCallbacks->pUserData);
1417     }
1418
1419     /* Try emulating realloc() in terms of malloc()/free(). */
1420     if (pAllocationCallbacks->onMalloc != NULL && pAllocationCallbacks->onFree != NULL) {
1421         void* p2;
1422
1423         p2 = pAllocationCallbacks->onMalloc(szNew, pAllocationCallbacks->pUserData);
1424         if (p2 == NULL) {
1425             return NULL;
1426         }
1427
1428         if (p != NULL) {
1429             DRWAV_COPY_MEMORY(p2, p, szOld);
1430             pAllocationCallbacks->onFree(p, pAllocationCallbacks->pUserData);
1431         }
1432
1433         return p2;
1434     }
1435
1436     return NULL;
1437 }
1438
1439 DRWAV_PRIVATE void drwav__free_from_callbacks(void* p, const drwav_allocation_callbacks* pAllocationCallbacks)
1440 {
1441     if (p == NULL || pAllocationCallbacks == NULL) {
1442         return;
1443     }
1444
1445     if (pAllocationCallbacks->onFree != NULL) {
1446         pAllocationCallbacks->onFree(p, pAllocationCallbacks->pUserData);
1447     }
1448 }
1449
1450
1451 DRWAV_PRIVATE drwav_allocation_callbacks drwav_copy_allocation_callbacks_or_defaults(const drwav_allocation_callbacks* pAllocationCallbacks)
1452 {
1453     if (pAllocationCallbacks != NULL) {
1454         /* Copy. */
1455         return *pAllocationCallbacks;
1456     } else {
1457         /* Defaults. */
1458         drwav_allocation_callbacks allocationCallbacks;
1459         allocationCallbacks.pUserData = NULL;
1460         allocationCallbacks.onMalloc  = drwav__malloc_default;
1461         allocationCallbacks.onRealloc = drwav__realloc_default;
1462         allocationCallbacks.onFree    = drwav__free_default;
1463         return allocationCallbacks;
1464     }
1465 }
1466
1467
1468 static DRWAV_INLINE drwav_bool32 drwav__is_compressed_format_tag(drwav_uint16 formatTag)
1469 {
1470     return
1471         formatTag == DR_WAVE_FORMAT_ADPCM ||
1472         formatTag == DR_WAVE_FORMAT_DVI_ADPCM;
1473 }
1474
1475 DRWAV_PRIVATE unsigned int drwav__chunk_padding_size_riff(drwav_uint64 chunkSize)
1476 {
1477     return (unsigned int)(chunkSize % 2);
1478 }
1479
1480 DRWAV_PRIVATE unsigned int drwav__chunk_padding_size_w64(drwav_uint64 chunkSize)
1481 {
1482     return (unsigned int)(chunkSize % 8);
1483 }
1484
1485 DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__msadpcm(drwav* pWav, drwav_uint64 samplesToRead, drwav_int16* pBufferOut);
1486 DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__ima(drwav* pWav, drwav_uint64 samplesToRead, drwav_int16* pBufferOut);
1487 DRWAV_PRIVATE drwav_bool32 drwav_init_write__internal(drwav* pWav, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount);
1488
1489 DRWAV_PRIVATE drwav_result drwav__read_chunk_header(drwav_read_proc onRead, void* pUserData, drwav_container container, drwav_uint64* pRunningBytesReadOut, drwav_chunk_header* pHeaderOut)
1490 {
1491     if (container == drwav_container_riff || container == drwav_container_rf64) {
1492         drwav_uint8 sizeInBytes[4];
1493
1494         if (onRead(pUserData, pHeaderOut->id.fourcc, 4) != 4) {
1495             return DRWAV_AT_END;
1496         }
1497
1498         if (onRead(pUserData, sizeInBytes, 4) != 4) {
1499             return DRWAV_INVALID_FILE;
1500         }
1501
1502         pHeaderOut->sizeInBytes = drwav_bytes_to_u32(sizeInBytes);
1503         pHeaderOut->paddingSize = drwav__chunk_padding_size_riff(pHeaderOut->sizeInBytes);
1504         *pRunningBytesReadOut += 8;
1505     } else {
1506         drwav_uint8 sizeInBytes[8];
1507
1508         if (onRead(pUserData, pHeaderOut->id.guid, 16) != 16) {
1509             return DRWAV_AT_END;
1510         }
1511
1512         if (onRead(pUserData, sizeInBytes, 8) != 8) {
1513             return DRWAV_INVALID_FILE;
1514         }
1515
1516         pHeaderOut->sizeInBytes = drwav_bytes_to_u64(sizeInBytes) - 24;    /* <-- Subtract 24 because w64 includes the size of the header. */
1517         pHeaderOut->paddingSize = drwav__chunk_padding_size_w64(pHeaderOut->sizeInBytes);
1518         *pRunningBytesReadOut += 24;
1519     }
1520
1521     return DRWAV_SUCCESS;
1522 }
1523
1524 DRWAV_PRIVATE drwav_bool32 drwav__seek_forward(drwav_seek_proc onSeek, drwav_uint64 offset, void* pUserData)
1525 {
1526     drwav_uint64 bytesRemainingToSeek = offset;
1527     while (bytesRemainingToSeek > 0) {
1528         if (bytesRemainingToSeek > 0x7FFFFFFF) {
1529             if (!onSeek(pUserData, 0x7FFFFFFF, drwav_seek_origin_current)) {
1530                 return DRWAV_FALSE;
1531             }
1532             bytesRemainingToSeek -= 0x7FFFFFFF;
1533         } else {
1534             if (!onSeek(pUserData, (int)bytesRemainingToSeek, drwav_seek_origin_current)) {
1535                 return DRWAV_FALSE;
1536             }
1537             bytesRemainingToSeek = 0;
1538         }
1539     }
1540
1541     return DRWAV_TRUE;
1542 }
1543
1544 DRWAV_PRIVATE drwav_bool32 drwav__seek_from_start(drwav_seek_proc onSeek, drwav_uint64 offset, void* pUserData)
1545 {
1546     if (offset <= 0x7FFFFFFF) {
1547         return onSeek(pUserData, (int)offset, drwav_seek_origin_start);
1548     }
1549
1550     /* Larger than 32-bit seek. */
1551     if (!onSeek(pUserData, 0x7FFFFFFF, drwav_seek_origin_start)) {
1552         return DRWAV_FALSE;
1553     }
1554     offset -= 0x7FFFFFFF;
1555
1556     for (;;) {
1557         if (offset <= 0x7FFFFFFF) {
1558             return onSeek(pUserData, (int)offset, drwav_seek_origin_current);
1559         }
1560
1561         if (!onSeek(pUserData, 0x7FFFFFFF, drwav_seek_origin_current)) {
1562             return DRWAV_FALSE;
1563         }
1564         offset -= 0x7FFFFFFF;
1565     }
1566
1567     /* Should never get here. */
1568     /*return DRWAV_TRUE; */
1569 }
1570
1571
1572 DRWAV_PRIVATE drwav_bool32 drwav__read_fmt(drwav_read_proc onRead, drwav_seek_proc onSeek, void* pUserData, drwav_container container, drwav_uint64* pRunningBytesReadOut, drwav_fmt* fmtOut)
1573 {
1574     drwav_chunk_header header;
1575     drwav_uint8 fmt[16];
1576
1577     if (drwav__read_chunk_header(onRead, pUserData, container, pRunningBytesReadOut, &header) != DRWAV_SUCCESS) {
1578         return DRWAV_FALSE;
1579     }
1580
1581
1582     /* Skip non-fmt chunks. */
1583     while (((container == drwav_container_riff || container == drwav_container_rf64) && !drwav_fourcc_equal(header.id.fourcc, "fmt ")) || (container == drwav_container_w64 && !drwav_guid_equal(header.id.guid, drwavGUID_W64_FMT))) {
1584         if (!drwav__seek_forward(onSeek, header.sizeInBytes + header.paddingSize, pUserData)) {
1585             return DRWAV_FALSE;
1586         }
1587         *pRunningBytesReadOut += header.sizeInBytes + header.paddingSize;
1588
1589         /* Try the next header. */
1590         if (drwav__read_chunk_header(onRead, pUserData, container, pRunningBytesReadOut, &header) != DRWAV_SUCCESS) {
1591             return DRWAV_FALSE;
1592         }
1593     }
1594
1595
1596     /* Validation. */
1597     if (container == drwav_container_riff || container == drwav_container_rf64) {
1598         if (!drwav_fourcc_equal(header.id.fourcc, "fmt ")) {
1599             return DRWAV_FALSE;
1600         }
1601     } else {
1602         if (!drwav_guid_equal(header.id.guid, drwavGUID_W64_FMT)) {
1603             return DRWAV_FALSE;
1604         }
1605     }
1606
1607
1608     if (onRead(pUserData, fmt, sizeof(fmt)) != sizeof(fmt)) {
1609         return DRWAV_FALSE;
1610     }
1611     *pRunningBytesReadOut += sizeof(fmt);
1612
1613     fmtOut->formatTag      = drwav_bytes_to_u16(fmt + 0);
1614     fmtOut->channels       = drwav_bytes_to_u16(fmt + 2);
1615     fmtOut->sampleRate     = drwav_bytes_to_u32(fmt + 4);
1616     fmtOut->avgBytesPerSec = drwav_bytes_to_u32(fmt + 8);
1617     fmtOut->blockAlign     = drwav_bytes_to_u16(fmt + 12);
1618     fmtOut->bitsPerSample  = drwav_bytes_to_u16(fmt + 14);
1619
1620     fmtOut->extendedSize       = 0;
1621     fmtOut->validBitsPerSample = 0;
1622     fmtOut->channelMask        = 0;
1623     memset(fmtOut->subFormat, 0, sizeof(fmtOut->subFormat));
1624
1625     if (header.sizeInBytes > 16) {
1626         drwav_uint8 fmt_cbSize[2];
1627         int bytesReadSoFar = 0;
1628
1629         if (onRead(pUserData, fmt_cbSize, sizeof(fmt_cbSize)) != sizeof(fmt_cbSize)) {
1630             return DRWAV_FALSE;    /* Expecting more data. */
1631         }
1632         *pRunningBytesReadOut += sizeof(fmt_cbSize);
1633
1634         bytesReadSoFar = 18;
1635
1636         fmtOut->extendedSize = drwav_bytes_to_u16(fmt_cbSize);
1637         if (fmtOut->extendedSize > 0) {
1638             /* Simple validation. */
1639             if (fmtOut->formatTag == DR_WAVE_FORMAT_EXTENSIBLE) {
1640                 if (fmtOut->extendedSize != 22) {
1641                     return DRWAV_FALSE;
1642                 }
1643             }
1644
1645             if (fmtOut->formatTag == DR_WAVE_FORMAT_EXTENSIBLE) {
1646                 drwav_uint8 fmtext[22];
1647                 if (onRead(pUserData, fmtext, fmtOut->extendedSize) != fmtOut->extendedSize) {
1648                     return DRWAV_FALSE;    /* Expecting more data. */
1649                 }
1650
1651                 fmtOut->validBitsPerSample = drwav_bytes_to_u16(fmtext + 0);
1652                 fmtOut->channelMask        = drwav_bytes_to_u32(fmtext + 2);
1653                 drwav__bytes_to_guid(fmtext + 6, fmtOut->subFormat);
1654             } else {
1655                 if (!onSeek(pUserData, fmtOut->extendedSize, drwav_seek_origin_current)) {
1656                     return DRWAV_FALSE;
1657                 }
1658             }
1659             *pRunningBytesReadOut += fmtOut->extendedSize;
1660
1661             bytesReadSoFar += fmtOut->extendedSize;
1662         }
1663
1664         /* Seek past any leftover bytes. For w64 the leftover will be defined based on the chunk size. */
1665         if (!onSeek(pUserData, (int)(header.sizeInBytes - bytesReadSoFar), drwav_seek_origin_current)) {
1666             return DRWAV_FALSE;
1667         }
1668         *pRunningBytesReadOut += (header.sizeInBytes - bytesReadSoFar);
1669     }
1670
1671     if (header.paddingSize > 0) {
1672         if (!onSeek(pUserData, header.paddingSize, drwav_seek_origin_current)) {
1673             return DRWAV_FALSE;
1674         }
1675         *pRunningBytesReadOut += header.paddingSize;
1676     }
1677
1678     return DRWAV_TRUE;
1679 }
1680
1681
1682 DRWAV_PRIVATE size_t drwav__on_read(drwav_read_proc onRead, void* pUserData, void* pBufferOut, size_t bytesToRead, drwav_uint64* pCursor)
1683 {
1684     size_t bytesRead;
1685
1686     DRWAV_ASSERT(onRead != NULL);
1687     DRWAV_ASSERT(pCursor != NULL);
1688
1689     bytesRead = onRead(pUserData, pBufferOut, bytesToRead);
1690     *pCursor += bytesRead;
1691     return bytesRead;
1692 }
1693
1694 #if 0
1695 DRWAV_PRIVATE drwav_bool32 drwav__on_seek(drwav_seek_proc onSeek, void* pUserData, int offset, drwav_seek_origin origin, drwav_uint64* pCursor)
1696 {
1697     DRWAV_ASSERT(onSeek != NULL);
1698     DRWAV_ASSERT(pCursor != NULL);
1699
1700     if (!onSeek(pUserData, offset, origin)) {
1701         return DRWAV_FALSE;
1702     }
1703
1704     if (origin == drwav_seek_origin_start) {
1705         *pCursor = offset;
1706     } else {
1707         *pCursor += offset;
1708     }
1709
1710     return DRWAV_TRUE;
1711 }
1712 #endif
1713
1714
1715
1716 DRWAV_PRIVATE drwav_uint32 drwav_get_bytes_per_pcm_frame(drwav* pWav)
1717 {
1718     /*
1719     The bytes per frame is a bit ambiguous. It can be either be based on the bits per sample, or the block align. The way I'm doing it here
1720     is that if the bits per sample is a multiple of 8, use floor(bitsPerSample*channels/8), otherwise fall back to the block align.
1721     */
1722     if ((pWav->bitsPerSample & 0x7) == 0) {
1723         /* Bits per sample is a multiple of 8. */
1724         return (pWav->bitsPerSample * pWav->fmt.channels) >> 3;
1725     } else {
1726         return pWav->fmt.blockAlign;
1727     }
1728 }
1729
1730 DRWAV_API drwav_uint16 drwav_fmt_get_format(const drwav_fmt* pFMT)
1731 {
1732     if (pFMT == NULL) {
1733         return 0;
1734     }
1735
1736     if (pFMT->formatTag != DR_WAVE_FORMAT_EXTENSIBLE) {
1737         return pFMT->formatTag;
1738     } else {
1739         return drwav_bytes_to_u16(pFMT->subFormat);    /* Only the first two bytes are required. */
1740     }
1741 }
1742
1743 DRWAV_PRIVATE drwav_bool32 drwav_preinit(drwav* pWav, drwav_read_proc onRead, drwav_seek_proc onSeek, void* pReadSeekUserData, const drwav_allocation_callbacks* pAllocationCallbacks)
1744 {
1745     if (pWav == NULL || onRead == NULL || onSeek == NULL) {
1746         return DRWAV_FALSE;
1747     }
1748
1749     DRWAV_ZERO_MEMORY(pWav, sizeof(*pWav));
1750     pWav->onRead    = onRead;
1751     pWav->onSeek    = onSeek;
1752     pWav->pUserData = pReadSeekUserData;
1753     pWav->allocationCallbacks = drwav_copy_allocation_callbacks_or_defaults(pAllocationCallbacks);
1754
1755     if (pWav->allocationCallbacks.onFree == NULL || (pWav->allocationCallbacks.onMalloc == NULL && pWav->allocationCallbacks.onRealloc == NULL)) {
1756         return DRWAV_FALSE;    /* Invalid allocation callbacks. */
1757     }
1758
1759     return DRWAV_TRUE;
1760 }
1761
1762 DRWAV_PRIVATE drwav_bool32 drwav_init__internal(drwav* pWav, drwav_chunk_proc onChunk, void* pChunkUserData, drwav_uint32 flags)
1763 {
1764     /* This function assumes drwav_preinit() has been called beforehand. */
1765
1766     drwav_uint64 cursor;    /* <-- Keeps track of the byte position so we can seek to specific locations. */
1767     drwav_bool32 sequential;
1768     drwav_uint8 riff[4];
1769     drwav_fmt fmt;
1770     unsigned short translatedFormatTag;
1771     drwav_bool32 foundDataChunk;
1772     drwav_uint64 dataChunkSize = 0; /* <-- Important! Don't explicitly set this to 0 anywhere else. Calculation of the size of the data chunk is performed in different paths depending on the container. */
1773     drwav_uint64 sampleCountFromFactChunk = 0;  /* Same as dataChunkSize - make sure this is the only place this is initialized to 0. */
1774     drwav_uint64 chunkSize;
1775
1776     cursor = 0;
1777     sequential = (flags & DRWAV_SEQUENTIAL) != 0;
1778
1779     /* The first 4 bytes should be the RIFF identifier. */
1780     if (drwav__on_read(pWav->onRead, pWav->pUserData, riff, sizeof(riff), &cursor) != sizeof(riff)) {
1781         return DRWAV_FALSE;
1782     }
1783
1784     /*
1785     The first 4 bytes can be used to identify the container. For RIFF files it will start with "RIFF" and for
1786     w64 it will start with "riff".
1787     */
1788     if (drwav_fourcc_equal(riff, "RIFF")) {
1789         pWav->container = drwav_container_riff;
1790     } else if (drwav_fourcc_equal(riff, "riff")) {
1791         int i;
1792         drwav_uint8 riff2[12];
1793
1794         pWav->container = drwav_container_w64;
1795
1796         /* Check the rest of the GUID for validity. */
1797         if (drwav__on_read(pWav->onRead, pWav->pUserData, riff2, sizeof(riff2), &cursor) != sizeof(riff2)) {
1798             return DRWAV_FALSE;
1799         }
1800
1801         for (i = 0; i < 12; ++i) {
1802             if (riff2[i] != drwavGUID_W64_RIFF[i+4]) {
1803                 return DRWAV_FALSE;
1804             }
1805         }
1806     } else if (drwav_fourcc_equal(riff, "RF64")) {
1807         pWav->container = drwav_container_rf64;
1808     } else {
1809         return DRWAV_FALSE;   /* Unknown or unsupported container. */
1810     }
1811
1812
1813     if (pWav->container == drwav_container_riff || pWav->container == drwav_container_rf64) {
1814         drwav_uint8 chunkSizeBytes[4];
1815         drwav_uint8 wave[4];
1816
1817         /* RIFF/WAVE */
1818         if (drwav__on_read(pWav->onRead, pWav->pUserData, chunkSizeBytes, sizeof(chunkSizeBytes), &cursor) != sizeof(chunkSizeBytes)) {
1819             return DRWAV_FALSE;
1820         }
1821
1822         if (pWav->container == drwav_container_riff) {
1823             if (drwav_bytes_to_u32(chunkSizeBytes) < 36) {
1824                 return DRWAV_FALSE;    /* Chunk size should always be at least 36 bytes. */
1825             }
1826         } else {
1827             if (drwav_bytes_to_u32(chunkSizeBytes) != 0xFFFFFFFF) {
1828                 return DRWAV_FALSE;    /* Chunk size should always be set to -1/0xFFFFFFFF for RF64. The actual size is retrieved later. */
1829             }
1830         }
1831
1832         if (drwav__on_read(pWav->onRead, pWav->pUserData, wave, sizeof(wave), &cursor) != sizeof(wave)) {
1833             return DRWAV_FALSE;
1834         }
1835
1836         if (!drwav_fourcc_equal(wave, "WAVE")) {
1837             return DRWAV_FALSE;    /* Expecting "WAVE". */
1838         }
1839     } else {
1840         drwav_uint8 chunkSizeBytes[8];
1841         drwav_uint8 wave[16];
1842
1843         /* W64 */
1844         if (drwav__on_read(pWav->onRead, pWav->pUserData, chunkSizeBytes, sizeof(chunkSizeBytes), &cursor) != sizeof(chunkSizeBytes)) {
1845             return DRWAV_FALSE;
1846         }
1847
1848         if (drwav_bytes_to_u64(chunkSizeBytes) < 80) {
1849             return DRWAV_FALSE;
1850         }
1851
1852         if (drwav__on_read(pWav->onRead, pWav->pUserData, wave, sizeof(wave), &cursor) != sizeof(wave)) {
1853             return DRWAV_FALSE;
1854         }
1855
1856         if (!drwav_guid_equal(wave, drwavGUID_W64_WAVE)) {
1857             return DRWAV_FALSE;
1858         }
1859     }
1860
1861
1862     /* For RF64, the "ds64" chunk must come next, before the "fmt " chunk. */
1863     if (pWav->container == drwav_container_rf64) {
1864         drwav_uint8 sizeBytes[8];
1865         drwav_uint64 bytesRemainingInChunk;
1866         drwav_chunk_header header;
1867         drwav_result result = drwav__read_chunk_header(pWav->onRead, pWav->pUserData, pWav->container, &cursor, &header);
1868         if (result != DRWAV_SUCCESS) {
1869             return DRWAV_FALSE;
1870         }
1871
1872         if (!drwav_fourcc_equal(header.id.fourcc, "ds64")) {
1873             return DRWAV_FALSE; /* Expecting "ds64". */
1874         }
1875
1876         bytesRemainingInChunk = header.sizeInBytes + header.paddingSize;
1877
1878         /* We don't care about the size of the RIFF chunk - skip it. */
1879         if (!drwav__seek_forward(pWav->onSeek, 8, pWav->pUserData)) {
1880             return DRWAV_FALSE;
1881         }
1882         bytesRemainingInChunk -= 8;
1883         cursor += 8;
1884
1885
1886         /* Next 8 bytes is the size of the "data" chunk. */
1887         if (drwav__on_read(pWav->onRead, pWav->pUserData, sizeBytes, sizeof(sizeBytes), &cursor) != sizeof(sizeBytes)) {
1888             return DRWAV_FALSE;
1889         }
1890         bytesRemainingInChunk -= 8;
1891         dataChunkSize = drwav_bytes_to_u64(sizeBytes);
1892
1893
1894         /* Next 8 bytes is the same count which we would usually derived from the FACT chunk if it was available. */
1895         if (drwav__on_read(pWav->onRead, pWav->pUserData, sizeBytes, sizeof(sizeBytes), &cursor) != sizeof(sizeBytes)) {
1896             return DRWAV_FALSE;
1897         }
1898         bytesRemainingInChunk -= 8;
1899         sampleCountFromFactChunk = drwav_bytes_to_u64(sizeBytes);
1900
1901
1902         /* Skip over everything else. */
1903         if (!drwav__seek_forward(pWav->onSeek, bytesRemainingInChunk, pWav->pUserData)) {
1904             return DRWAV_FALSE;
1905         }
1906         cursor += bytesRemainingInChunk;
1907     }
1908
1909
1910     /* The next bytes should be the "fmt " chunk. */
1911     if (!drwav__read_fmt(pWav->onRead, pWav->onSeek, pWav->pUserData, pWav->container, &cursor, &fmt)) {
1912         return DRWAV_FALSE;    /* Failed to read the "fmt " chunk. */
1913     }
1914
1915     /* Basic validation. */
1916     if ((fmt.sampleRate    == 0 || fmt.sampleRate    > DRWAV_MAX_SAMPLE_RATE)     ||
1917         (fmt.channels      == 0 || fmt.channels      > DRWAV_MAX_CHANNELS)        ||
1918         (fmt.bitsPerSample == 0 || fmt.bitsPerSample > DRWAV_MAX_BITS_PER_SAMPLE) ||
1919         fmt.blockAlign == 0) {
1920         return DRWAV_FALSE; /* Probably an invalid WAV file. */
1921     }
1922
1923
1924     /* Translate the internal format. */
1925     translatedFormatTag = fmt.formatTag;
1926     if (translatedFormatTag == DR_WAVE_FORMAT_EXTENSIBLE) {
1927         translatedFormatTag = drwav_bytes_to_u16(fmt.subFormat + 0);
1928     }
1929
1930
1931     /*
1932     We need to enumerate over each chunk for two reasons:
1933       1) The "data" chunk may not be the next one
1934       2) We may want to report each chunk back to the client
1935     
1936     In order to correctly report each chunk back to the client we will need to keep looping until the end of the file.
1937     */
1938     foundDataChunk = DRWAV_FALSE;
1939
1940     /* The next chunk we care about is the "data" chunk. This is not necessarily the next chunk so we'll need to loop. */
1941     for (;;)
1942     {
1943         drwav_chunk_header header;
1944         drwav_result result = drwav__read_chunk_header(pWav->onRead, pWav->pUserData, pWav->container, &cursor, &header);
1945         if (result != DRWAV_SUCCESS) {
1946             if (!foundDataChunk) {
1947                 return DRWAV_FALSE;
1948             } else {
1949                 break;  /* Probably at the end of the file. Get out of the loop. */
1950             }
1951         }
1952
1953         /* Tell the client about this chunk. */
1954         if (!sequential && onChunk != NULL) {
1955             drwav_uint64 callbackBytesRead = onChunk(pChunkUserData, pWav->onRead, pWav->onSeek, pWav->pUserData, &header, pWav->container, &fmt);
1956
1957             /*
1958             dr_wav may need to read the contents of the chunk, so we now need to seek back to the position before
1959             we called the callback.
1960             */
1961             if (callbackBytesRead > 0) {
1962                 if (!drwav__seek_from_start(pWav->onSeek, cursor, pWav->pUserData)) {
1963                     return DRWAV_FALSE;
1964                 }
1965             }
1966         }
1967         
1968
1969         if (!foundDataChunk) {
1970             pWav->dataChunkDataPos = cursor;
1971         }
1972
1973         chunkSize = header.sizeInBytes;
1974         if (pWav->container == drwav_container_riff || pWav->container == drwav_container_rf64) {
1975             if (drwav_fourcc_equal(header.id.fourcc, "data")) {
1976                 foundDataChunk = DRWAV_TRUE;
1977                 if (pWav->container != drwav_container_rf64) {  /* The data chunk size for RF64 will always be set to 0xFFFFFFFF here. It was set to it's true value earlier. */
1978                     dataChunkSize = chunkSize;
1979                 }
1980             }
1981         } else {
1982             if (drwav_guid_equal(header.id.guid, drwavGUID_W64_DATA)) {
1983                 foundDataChunk = DRWAV_TRUE;
1984                 dataChunkSize = chunkSize;
1985             }
1986         }
1987
1988         /*
1989         If at this point we have found the data chunk and we're running in sequential mode, we need to break out of this loop. The reason for
1990         this is that we would otherwise require a backwards seek which sequential mode forbids.
1991         */
1992         if (foundDataChunk && sequential) {
1993             break;
1994         }
1995
1996         /* Optional. Get the total sample count from the FACT chunk. This is useful for compressed formats. */
1997         if (pWav->container == drwav_container_riff) {
1998             if (drwav_fourcc_equal(header.id.fourcc, "fact")) {
1999                 drwav_uint32 sampleCount;
2000                 if (drwav__on_read(pWav->onRead, pWav->pUserData, &sampleCount, 4, &cursor) != 4) {
2001                     return DRWAV_FALSE;
2002                 }
2003                 chunkSize -= 4;
2004
2005                 if (!foundDataChunk) {
2006                     pWav->dataChunkDataPos = cursor;
2007                 }
2008
2009                 /*
2010                 The sample count in the "fact" chunk is either unreliable, or I'm not understanding it properly. For now I am only enabling this
2011                 for Microsoft ADPCM formats.
2012                 */
2013                 if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ADPCM) {
2014                     sampleCountFromFactChunk = sampleCount;
2015                 } else {
2016                     sampleCountFromFactChunk = 0;
2017                 }
2018             }
2019         } else if (pWav->container == drwav_container_w64) {
2020             if (drwav_guid_equal(header.id.guid, drwavGUID_W64_FACT)) {
2021                 if (drwav__on_read(pWav->onRead, pWav->pUserData, &sampleCountFromFactChunk, 8, &cursor) != 8) {
2022                     return DRWAV_FALSE;
2023                 }
2024                 chunkSize -= 8;
2025
2026                 if (!foundDataChunk) {
2027                     pWav->dataChunkDataPos = cursor;
2028                 }
2029             }
2030         } else if (pWav->container == drwav_container_rf64) {
2031             /* We retrieved the sample count from the ds64 chunk earlier so no need to do that here. */
2032         }
2033
2034         /* "smpl" chunk. */
2035         if (pWav->container == drwav_container_riff || pWav->container == drwav_container_rf64) {
2036             if (drwav_fourcc_equal(header.id.fourcc, "smpl")) {
2037                 drwav_uint8 smplHeaderData[36];    /* 36 = size of the smpl header section, not including the loop data. */
2038                 if (chunkSize >= sizeof(smplHeaderData)) {
2039                     drwav_uint64 bytesJustRead = drwav__on_read(pWav->onRead, pWav->pUserData, smplHeaderData, sizeof(smplHeaderData), &cursor);
2040                     chunkSize -= bytesJustRead;
2041
2042                     if (bytesJustRead == sizeof(smplHeaderData)) {
2043                         drwav_uint32 iLoop;
2044
2045                         pWav->smpl.manufacturer      = drwav_bytes_to_u32(smplHeaderData+0);
2046                         pWav->smpl.product           = drwav_bytes_to_u32(smplHeaderData+4);
2047                         pWav->smpl.samplePeriod      = drwav_bytes_to_u32(smplHeaderData+8);
2048                         pWav->smpl.midiUnityNotes    = drwav_bytes_to_u32(smplHeaderData+12);
2049                         pWav->smpl.midiPitchFraction = drwav_bytes_to_u32(smplHeaderData+16);
2050                         pWav->smpl.smpteFormat       = drwav_bytes_to_u32(smplHeaderData+20);
2051                         pWav->smpl.smpteOffset       = drwav_bytes_to_u32(smplHeaderData+24);
2052                         pWav->smpl.numSampleLoops    = drwav_bytes_to_u32(smplHeaderData+28);
2053                         pWav->smpl.samplerData       = drwav_bytes_to_u32(smplHeaderData+32);
2054
2055                         for (iLoop = 0; iLoop < pWav->smpl.numSampleLoops && iLoop < drwav_countof(pWav->smpl.loops); ++iLoop) {
2056                             drwav_uint8 smplLoopData[24];  /* 24 = size of a loop section in the smpl chunk. */
2057                             bytesJustRead = drwav__on_read(pWav->onRead, pWav->pUserData, smplLoopData, sizeof(smplLoopData), &cursor);
2058                             chunkSize -= bytesJustRead;
2059
2060                             if (bytesJustRead == sizeof(smplLoopData)) {
2061                                 pWav->smpl.loops[iLoop].cuePointId = drwav_bytes_to_u32(smplLoopData+0);
2062                                 pWav->smpl.loops[iLoop].type       = drwav_bytes_to_u32(smplLoopData+4);
2063                                 pWav->smpl.loops[iLoop].start      = drwav_bytes_to_u32(smplLoopData+8);
2064                                 pWav->smpl.loops[iLoop].end        = drwav_bytes_to_u32(smplLoopData+12);
2065                                 pWav->smpl.loops[iLoop].fraction   = drwav_bytes_to_u32(smplLoopData+16);
2066                                 pWav->smpl.loops[iLoop].playCount  = drwav_bytes_to_u32(smplLoopData+20);
2067                             } else {
2068                                 break;  /* Break from the smpl loop for loop. */
2069                             }
2070                         }
2071                     }
2072                 } else {
2073                     /* Looks like invalid data. Ignore the chunk. */
2074                 }
2075             }
2076         } else {
2077             if (drwav_guid_equal(header.id.guid, drwavGUID_W64_SMPL)) {
2078                 /*
2079                 This path will be hit when a W64 WAV file contains a smpl chunk. I don't have a sample file to test this path, so a contribution
2080                 is welcome to add support for this.
2081                 */
2082             }
2083         }
2084
2085         /* Make sure we seek past the padding. */
2086         chunkSize += header.paddingSize;
2087         if (!drwav__seek_forward(pWav->onSeek, chunkSize, pWav->pUserData)) {
2088             break;
2089         }
2090         cursor += chunkSize;
2091
2092         if (!foundDataChunk) {
2093             pWav->dataChunkDataPos = cursor;
2094         }
2095     }
2096
2097     /* If we haven't found a data chunk, return an error. */
2098     if (!foundDataChunk) {
2099         return DRWAV_FALSE;
2100     }
2101
2102     /* We may have moved passed the data chunk. If so we need to move back. If running in sequential mode we can assume we are already sitting on the data chunk. */
2103     if (!sequential) {
2104         if (!drwav__seek_from_start(pWav->onSeek, pWav->dataChunkDataPos, pWav->pUserData)) {
2105             return DRWAV_FALSE;
2106         }
2107         cursor = pWav->dataChunkDataPos;
2108     }
2109     
2110
2111     /* At this point we should be sitting on the first byte of the raw audio data. */
2112
2113     pWav->fmt                 = fmt;
2114     pWav->sampleRate          = fmt.sampleRate;
2115     pWav->channels            = fmt.channels;
2116     pWav->bitsPerSample       = fmt.bitsPerSample;
2117     pWav->bytesRemaining      = dataChunkSize;
2118     pWav->translatedFormatTag = translatedFormatTag;
2119     pWav->dataChunkDataSize   = dataChunkSize;
2120
2121     if (sampleCountFromFactChunk != 0) {
2122         pWav->totalPCMFrameCount = sampleCountFromFactChunk;
2123     } else {
2124         pWav->totalPCMFrameCount = dataChunkSize / drwav_get_bytes_per_pcm_frame(pWav);
2125
2126         if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ADPCM) {
2127             drwav_uint64 totalBlockHeaderSizeInBytes;
2128             drwav_uint64 blockCount = dataChunkSize / fmt.blockAlign;
2129
2130             /* Make sure any trailing partial block is accounted for. */
2131             if ((blockCount * fmt.blockAlign) < dataChunkSize) {
2132                 blockCount += 1;
2133             }
2134
2135             /* We decode two samples per byte. There will be blockCount headers in the data chunk. This is enough to know how to calculate the total PCM frame count. */
2136             totalBlockHeaderSizeInBytes = blockCount * (6*fmt.channels);
2137             pWav->totalPCMFrameCount = ((dataChunkSize - totalBlockHeaderSizeInBytes) * 2) / fmt.channels;
2138         }
2139         if (pWav->translatedFormatTag == DR_WAVE_FORMAT_DVI_ADPCM) {
2140             drwav_uint64 totalBlockHeaderSizeInBytes;
2141             drwav_uint64 blockCount = dataChunkSize / fmt.blockAlign;
2142
2143             /* Make sure any trailing partial block is accounted for. */
2144             if ((blockCount * fmt.blockAlign) < dataChunkSize) {
2145                 blockCount += 1;
2146             }
2147
2148             /* We decode two samples per byte. There will be blockCount headers in the data chunk. This is enough to know how to calculate the total PCM frame count. */
2149             totalBlockHeaderSizeInBytes = blockCount * (4*fmt.channels);
2150             pWav->totalPCMFrameCount = ((dataChunkSize - totalBlockHeaderSizeInBytes) * 2) / fmt.channels;
2151
2152             /* The header includes a decoded sample for each channel which acts as the initial predictor sample. */
2153             pWav->totalPCMFrameCount += blockCount;
2154         }
2155     }
2156
2157     /* Some formats only support a certain number of channels. */
2158     if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ADPCM || pWav->translatedFormatTag == DR_WAVE_FORMAT_DVI_ADPCM) {
2159         if (pWav->channels > 2) {
2160             return DRWAV_FALSE;
2161         }
2162     }
2163
2164 #ifdef DR_WAV_LIBSNDFILE_COMPAT
2165     /*
2166     I use libsndfile as a benchmark for testing, however in the version I'm using (from the Windows installer on the libsndfile website),
2167     it appears the total sample count libsndfile uses for MS-ADPCM is incorrect. It would seem they are computing the total sample count
2168     from the number of blocks, however this results in the inclusion of extra silent samples at the end of the last block. The correct
2169     way to know the total sample count is to inspect the "fact" chunk, which should always be present for compressed formats, and should
2170     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
2171     correctness tests against libsndfile, and is disabled by default.
2172     */
2173     if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ADPCM) {
2174         drwav_uint64 blockCount = dataChunkSize / fmt.blockAlign;
2175         pWav->totalPCMFrameCount = (((blockCount * (fmt.blockAlign - (6*pWav->channels))) * 2)) / fmt.channels;  /* x2 because two samples per byte. */
2176     }
2177     if (pWav->translatedFormatTag == DR_WAVE_FORMAT_DVI_ADPCM) {
2178         drwav_uint64 blockCount = dataChunkSize / fmt.blockAlign;
2179         pWav->totalPCMFrameCount = (((blockCount * (fmt.blockAlign - (4*pWav->channels))) * 2) + (blockCount * pWav->channels)) / fmt.channels;
2180     }
2181 #endif
2182
2183     return DRWAV_TRUE;
2184 }
2185
2186 DRWAV_API drwav_bool32 drwav_init(drwav* pWav, drwav_read_proc onRead, drwav_seek_proc onSeek, void* pUserData, const drwav_allocation_callbacks* pAllocationCallbacks)
2187 {
2188     return drwav_init_ex(pWav, onRead, onSeek, NULL, pUserData, NULL, 0, pAllocationCallbacks);
2189 }
2190
2191 DRWAV_API drwav_bool32 drwav_init_ex(drwav* pWav, drwav_read_proc onRead, drwav_seek_proc onSeek, drwav_chunk_proc onChunk, void* pReadSeekUserData, void* pChunkUserData, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks)
2192 {
2193     if (!drwav_preinit(pWav, onRead, onSeek, pReadSeekUserData, pAllocationCallbacks)) {
2194         return DRWAV_FALSE;
2195     }
2196
2197     return drwav_init__internal(pWav, onChunk, pChunkUserData, flags);
2198 }
2199
2200
2201 DRWAV_PRIVATE drwav_uint32 drwav__riff_chunk_size_riff(drwav_uint64 dataChunkSize)
2202 {
2203     drwav_uint64 chunkSize = 4 + 24 + dataChunkSize + drwav__chunk_padding_size_riff(dataChunkSize); /* 4 = "WAVE". 24 = "fmt " chunk. */
2204     if (chunkSize > 0xFFFFFFFFUL) {
2205         chunkSize = 0xFFFFFFFFUL;
2206     }
2207
2208     return (drwav_uint32)chunkSize; /* Safe cast due to the clamp above. */
2209 }
2210
2211 DRWAV_PRIVATE drwav_uint32 drwav__data_chunk_size_riff(drwav_uint64 dataChunkSize)
2212 {
2213     if (dataChunkSize <= 0xFFFFFFFFUL) {
2214         return (drwav_uint32)dataChunkSize;
2215     } else {
2216         return 0xFFFFFFFFUL;
2217     }
2218 }
2219
2220 DRWAV_PRIVATE drwav_uint64 drwav__riff_chunk_size_w64(drwav_uint64 dataChunkSize)
2221 {
2222     drwav_uint64 dataSubchunkPaddingSize = drwav__chunk_padding_size_w64(dataChunkSize);
2223
2224     return 80 + 24 + dataChunkSize + dataSubchunkPaddingSize;   /* +24 because W64 includes the size of the GUID and size fields. */
2225 }
2226
2227 DRWAV_PRIVATE drwav_uint64 drwav__data_chunk_size_w64(drwav_uint64 dataChunkSize)
2228 {
2229     return 24 + dataChunkSize;        /* +24 because W64 includes the size of the GUID and size fields. */
2230 }
2231
2232 DRWAV_PRIVATE drwav_uint64 drwav__riff_chunk_size_rf64(drwav_uint64 dataChunkSize)
2233 {
2234     drwav_uint64 chunkSize = 4 + 36 + 24 + dataChunkSize + drwav__chunk_padding_size_riff(dataChunkSize); /* 4 = "WAVE". 36 = "ds64" chunk. 24 = "fmt " chunk. */
2235     if (chunkSize > 0xFFFFFFFFUL) {
2236         chunkSize = 0xFFFFFFFFUL;
2237     }
2238
2239     return chunkSize;
2240 }
2241
2242 DRWAV_PRIVATE drwav_uint64 drwav__data_chunk_size_rf64(drwav_uint64 dataChunkSize)
2243 {
2244     return dataChunkSize;
2245 }
2246
2247
2248 DRWAV_PRIVATE size_t drwav__write(drwav* pWav, const void* pData, size_t dataSize)
2249 {
2250     DRWAV_ASSERT(pWav          != NULL);
2251     DRWAV_ASSERT(pWav->onWrite != NULL);
2252
2253     /* Generic write. Assumes no byte reordering required. */
2254     return pWav->onWrite(pWav->pUserData, pData, dataSize);
2255 }
2256
2257 DRWAV_PRIVATE size_t drwav__write_u16ne_to_le(drwav* pWav, drwav_uint16 value)
2258 {
2259     DRWAV_ASSERT(pWav          != NULL);
2260     DRWAV_ASSERT(pWav->onWrite != NULL);
2261
2262     if (!drwav__is_little_endian()) {
2263         value = drwav__bswap16(value);
2264     }
2265
2266     return drwav__write(pWav, &value, 2);
2267 }
2268
2269 DRWAV_PRIVATE size_t drwav__write_u32ne_to_le(drwav* pWav, drwav_uint32 value)
2270 {
2271     DRWAV_ASSERT(pWav          != NULL);
2272     DRWAV_ASSERT(pWav->onWrite != NULL);
2273
2274     if (!drwav__is_little_endian()) {
2275         value = drwav__bswap32(value);
2276     }
2277
2278     return drwav__write(pWav, &value, 4);
2279 }
2280
2281 DRWAV_PRIVATE size_t drwav__write_u64ne_to_le(drwav* pWav, drwav_uint64 value)
2282 {
2283     DRWAV_ASSERT(pWav          != NULL);
2284     DRWAV_ASSERT(pWav->onWrite != NULL);
2285
2286     if (!drwav__is_little_endian()) {
2287         value = drwav__bswap64(value);
2288     }
2289
2290     return drwav__write(pWav, &value, 8);
2291 }
2292
2293
2294 DRWAV_PRIVATE drwav_bool32 drwav_preinit_write(drwav* pWav, const drwav_data_format* pFormat, drwav_bool32 isSequential, drwav_write_proc onWrite, drwav_seek_proc onSeek, void* pUserData, const drwav_allocation_callbacks* pAllocationCallbacks)
2295 {
2296     if (pWav == NULL || onWrite == NULL) {
2297         return DRWAV_FALSE;
2298     }
2299
2300     if (!isSequential && onSeek == NULL) {
2301         return DRWAV_FALSE; /* <-- onSeek is required when in non-sequential mode. */
2302     }
2303
2304     /* Not currently supporting compressed formats. Will need to add support for the "fact" chunk before we enable this. */
2305     if (pFormat->format == DR_WAVE_FORMAT_EXTENSIBLE) {
2306         return DRWAV_FALSE;
2307     }
2308     if (pFormat->format == DR_WAVE_FORMAT_ADPCM || pFormat->format == DR_WAVE_FORMAT_DVI_ADPCM) {
2309         return DRWAV_FALSE;
2310     }
2311
2312     DRWAV_ZERO_MEMORY(pWav, sizeof(*pWav));
2313     pWav->onWrite   = onWrite;
2314     pWav->onSeek    = onSeek;
2315     pWav->pUserData = pUserData;
2316     pWav->allocationCallbacks = drwav_copy_allocation_callbacks_or_defaults(pAllocationCallbacks);
2317
2318     if (pWav->allocationCallbacks.onFree == NULL || (pWav->allocationCallbacks.onMalloc == NULL && pWav->allocationCallbacks.onRealloc == NULL)) {
2319         return DRWAV_FALSE;    /* Invalid allocation callbacks. */
2320     }
2321
2322     pWav->fmt.formatTag = (drwav_uint16)pFormat->format;
2323     pWav->fmt.channels = (drwav_uint16)pFormat->channels;
2324     pWav->fmt.sampleRate = pFormat->sampleRate;
2325     pWav->fmt.avgBytesPerSec = (drwav_uint32)((pFormat->bitsPerSample * pFormat->sampleRate * pFormat->channels) / 8);
2326     pWav->fmt.blockAlign = (drwav_uint16)((pFormat->channels * pFormat->bitsPerSample) / 8);
2327     pWav->fmt.bitsPerSample = (drwav_uint16)pFormat->bitsPerSample;
2328     pWav->fmt.extendedSize = 0;
2329     pWav->isSequentialWrite = isSequential;
2330
2331     return DRWAV_TRUE;
2332 }
2333
2334 DRWAV_PRIVATE drwav_bool32 drwav_init_write__internal(drwav* pWav, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount)
2335 {
2336     /* The function assumes drwav_preinit_write() was called beforehand. */
2337
2338     size_t runningPos = 0;
2339     drwav_uint64 initialDataChunkSize = 0;
2340     drwav_uint64 chunkSizeFMT;
2341
2342     /*
2343     The initial values for the "RIFF" and "data" chunks depends on whether or not we are initializing in sequential mode or not. In
2344     sequential mode we set this to its final values straight away since they can be calculated from the total sample count. In non-
2345     sequential mode we initialize it all to zero and fill it out in drwav_uninit() using a backwards seek.
2346     */
2347     if (pWav->isSequentialWrite) {
2348         initialDataChunkSize = (totalSampleCount * pWav->fmt.bitsPerSample) / 8;
2349
2350         /*
2351         The RIFF container has a limit on the number of samples. drwav is not allowing this. There's no practical limits for Wave64
2352         so for the sake of simplicity I'm not doing any validation for that.
2353         */
2354         if (pFormat->container == drwav_container_riff) {
2355             if (initialDataChunkSize > (0xFFFFFFFFUL - 36)) {
2356                 return DRWAV_FALSE; /* Not enough room to store every sample. */
2357             }
2358         }
2359     }
2360
2361     pWav->dataChunkDataSizeTargetWrite = initialDataChunkSize;
2362
2363
2364     /* "RIFF" chunk. */
2365     if (pFormat->container == drwav_container_riff) {
2366         drwav_uint32 chunkSizeRIFF = 28 + (drwav_uint32)initialDataChunkSize;   /* +28 = "WAVE" + [sizeof "fmt " chunk] */
2367         runningPos += drwav__write(pWav, "RIFF", 4);
2368         runningPos += drwav__write_u32ne_to_le(pWav, chunkSizeRIFF);
2369         runningPos += drwav__write(pWav, "WAVE", 4);
2370     } else if (pFormat->container == drwav_container_w64) {
2371         drwav_uint64 chunkSizeRIFF = 80 + 24 + initialDataChunkSize;            /* +24 because W64 includes the size of the GUID and size fields. */
2372         runningPos += drwav__write(pWav, drwavGUID_W64_RIFF, 16);
2373         runningPos += drwav__write_u64ne_to_le(pWav, chunkSizeRIFF);
2374         runningPos += drwav__write(pWav, drwavGUID_W64_WAVE, 16);
2375     } else if (pFormat->container == drwav_container_rf64) {
2376         runningPos += drwav__write(pWav, "RF64", 4);
2377         runningPos += drwav__write_u32ne_to_le(pWav, 0xFFFFFFFF);               /* Always 0xFFFFFFFF for RF64. Set to a proper value in the "ds64" chunk. */
2378         runningPos += drwav__write(pWav, "WAVE", 4);
2379     }
2380
2381     
2382     /* "ds64" chunk (RF64 only). */
2383     if (pFormat->container == drwav_container_rf64) {
2384         drwav_uint32 initialds64ChunkSize = 28;                                 /* 28 = [Size of RIFF (8 bytes)] + [Size of DATA (8 bytes)] + [Sample Count (8 bytes)] + [Table Length (4 bytes)]. Table length always set to 0. */
2385         drwav_uint64 initialRiffChunkSize = 8 + initialds64ChunkSize + initialDataChunkSize;    /* +8 for the ds64 header. */
2386
2387         runningPos += drwav__write(pWav, "ds64", 4);
2388         runningPos += drwav__write_u32ne_to_le(pWav, initialds64ChunkSize);     /* Size of ds64. */
2389         runningPos += drwav__write_u64ne_to_le(pWav, initialRiffChunkSize);     /* Size of RIFF. Set to true value at the end. */
2390         runningPos += drwav__write_u64ne_to_le(pWav, initialDataChunkSize);     /* Size of DATA. Set to true value at the end. */
2391         runningPos += drwav__write_u64ne_to_le(pWav, totalSampleCount);         /* Sample count. */
2392         runningPos += drwav__write_u32ne_to_le(pWav, 0);                        /* Table length. Always set to zero in our case since we're not doing any other chunks than "DATA". */
2393     }
2394
2395
2396     /* "fmt " chunk. */
2397     if (pFormat->container == drwav_container_riff || pFormat->container == drwav_container_rf64) {
2398         chunkSizeFMT = 16;
2399         runningPos += drwav__write(pWav, "fmt ", 4);
2400         runningPos += drwav__write_u32ne_to_le(pWav, (drwav_uint32)chunkSizeFMT);
2401     } else if (pFormat->container == drwav_container_w64) {
2402         chunkSizeFMT = 40;
2403         runningPos += drwav__write(pWav, drwavGUID_W64_FMT, 16);
2404         runningPos += drwav__write_u64ne_to_le(pWav, chunkSizeFMT);
2405     }
2406
2407     runningPos += drwav__write_u16ne_to_le(pWav, pWav->fmt.formatTag);
2408     runningPos += drwav__write_u16ne_to_le(pWav, pWav->fmt.channels);
2409     runningPos += drwav__write_u32ne_to_le(pWav, pWav->fmt.sampleRate);
2410     runningPos += drwav__write_u32ne_to_le(pWav, pWav->fmt.avgBytesPerSec);
2411     runningPos += drwav__write_u16ne_to_le(pWav, pWav->fmt.blockAlign);
2412     runningPos += drwav__write_u16ne_to_le(pWav, pWav->fmt.bitsPerSample);
2413
2414     /* "data" chunk. */
2415     if (pFormat->container == drwav_container_riff) {
2416         drwav_uint32 chunkSizeDATA = (drwav_uint32)initialDataChunkSize;
2417         runningPos += drwav__write(pWav, "data", 4);
2418         runningPos += drwav__write_u32ne_to_le(pWav, chunkSizeDATA);
2419     } else if (pFormat->container == drwav_container_w64) {
2420         drwav_uint64 chunkSizeDATA = 24 + initialDataChunkSize;     /* +24 because W64 includes the size of the GUID and size fields. */
2421         runningPos += drwav__write(pWav, drwavGUID_W64_DATA, 16);
2422         runningPos += drwav__write_u64ne_to_le(pWav, chunkSizeDATA);
2423     } else if (pFormat->container == drwav_container_rf64) {
2424         runningPos += drwav__write(pWav, "data", 4);
2425         runningPos += drwav__write_u32ne_to_le(pWav, 0xFFFFFFFF);   /* Always set to 0xFFFFFFFF for RF64. The true size of the data chunk is specified in the ds64 chunk. */
2426     }
2427
2428     /* Set some properties for the client's convenience. */
2429     pWav->container = pFormat->container;
2430     pWav->channels = (drwav_uint16)pFormat->channels;
2431     pWav->sampleRate = pFormat->sampleRate;
2432     pWav->bitsPerSample = (drwav_uint16)pFormat->bitsPerSample;
2433     pWav->translatedFormatTag = (drwav_uint16)pFormat->format;
2434     pWav->dataChunkDataPos = runningPos;
2435
2436     return DRWAV_TRUE;
2437 }
2438
2439
2440 DRWAV_API drwav_bool32 drwav_init_write(drwav* pWav, const drwav_data_format* pFormat, drwav_write_proc onWrite, drwav_seek_proc onSeek, void* pUserData, const drwav_allocation_callbacks* pAllocationCallbacks)
2441 {
2442     if (!drwav_preinit_write(pWav, pFormat, DRWAV_FALSE, onWrite, onSeek, pUserData, pAllocationCallbacks)) {
2443         return DRWAV_FALSE;
2444     }
2445
2446     return drwav_init_write__internal(pWav, pFormat, 0);               /* DRWAV_FALSE = Not Sequential */
2447 }
2448
2449 DRWAV_API drwav_bool32 drwav_init_write_sequential(drwav* pWav, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount, drwav_write_proc onWrite, void* pUserData, const drwav_allocation_callbacks* pAllocationCallbacks)
2450 {
2451     if (!drwav_preinit_write(pWav, pFormat, DRWAV_TRUE, onWrite, NULL, pUserData, pAllocationCallbacks)) {
2452         return DRWAV_FALSE;
2453     }
2454
2455     return drwav_init_write__internal(pWav, pFormat, totalSampleCount); /* DRWAV_TRUE = Sequential */
2456 }
2457
2458 DRWAV_API drwav_bool32 drwav_init_write_sequential_pcm_frames(drwav* pWav, const drwav_data_format* pFormat, drwav_uint64 totalPCMFrameCount, drwav_write_proc onWrite, void* pUserData, const drwav_allocation_callbacks* pAllocationCallbacks)
2459 {
2460     if (pFormat == NULL) {
2461         return DRWAV_FALSE;
2462     }
2463
2464     return drwav_init_write_sequential(pWav, pFormat, totalPCMFrameCount*pFormat->channels, onWrite, pUserData, pAllocationCallbacks);
2465 }
2466
2467 DRWAV_API drwav_uint64 drwav_target_write_size_bytes(const drwav_data_format* pFormat, drwav_uint64 totalSampleCount)
2468 {
2469     /* Casting totalSampleCount to drwav_int64 for VC6 compatibility. No issues in practice because nobody is going to exhaust the whole 63 bits. */
2470     drwav_uint64 targetDataSizeBytes = (drwav_uint64)((drwav_int64)totalSampleCount * pFormat->channels * pFormat->bitsPerSample/8.0);
2471     drwav_uint64 riffChunkSizeBytes;
2472     drwav_uint64 fileSizeBytes = 0;
2473
2474     if (pFormat->container == drwav_container_riff) {
2475         riffChunkSizeBytes = drwav__riff_chunk_size_riff(targetDataSizeBytes);
2476         fileSizeBytes = (8 + riffChunkSizeBytes);   /* +8 because WAV doesn't include the size of the ChunkID and ChunkSize fields. */
2477     } else if (pFormat->container == drwav_container_w64) {
2478         riffChunkSizeBytes = drwav__riff_chunk_size_w64(targetDataSizeBytes);
2479         fileSizeBytes = riffChunkSizeBytes;
2480     } else if (pFormat->container == drwav_container_rf64) {
2481         riffChunkSizeBytes = drwav__riff_chunk_size_rf64(targetDataSizeBytes);
2482         fileSizeBytes = (8 + riffChunkSizeBytes);   /* +8 because WAV doesn't include the size of the ChunkID and ChunkSize fields. */
2483     }
2484
2485     return fileSizeBytes;
2486 }
2487
2488
2489 #ifndef DR_WAV_NO_STDIO
2490
2491 /* drwav_result_from_errno() is only used for fopen() and wfopen() so putting it inside DR_WAV_NO_STDIO for now. If something else needs this later we can move it out. */
2492 #include <errno.h>
2493 DRWAV_PRIVATE drwav_result drwav_result_from_errno(int e)
2494 {
2495     switch (e)
2496     {
2497         case 0: return DRWAV_SUCCESS;
2498     #ifdef EPERM
2499         case EPERM: return DRWAV_INVALID_OPERATION;
2500     #endif
2501     #ifdef ENOENT
2502         case ENOENT: return DRWAV_DOES_NOT_EXIST;
2503     #endif
2504     #ifdef ESRCH
2505         case ESRCH: return DRWAV_DOES_NOT_EXIST;
2506     #endif
2507     #ifdef EINTR
2508         case EINTR: return DRWAV_INTERRUPT;
2509     #endif
2510     #ifdef EIO
2511         case EIO: return DRWAV_IO_ERROR;
2512     #endif
2513     #ifdef ENXIO
2514         case ENXIO: return DRWAV_DOES_NOT_EXIST;
2515     #endif
2516     #ifdef E2BIG
2517         case E2BIG: return DRWAV_INVALID_ARGS;
2518     #endif
2519     #ifdef ENOEXEC
2520         case ENOEXEC: return DRWAV_INVALID_FILE;
2521     #endif
2522     #ifdef EBADF
2523         case EBADF: return DRWAV_INVALID_FILE;
2524     #endif
2525     #ifdef ECHILD
2526         case ECHILD: return DRWAV_ERROR;
2527     #endif
2528     #ifdef EAGAIN
2529         case EAGAIN: return DRWAV_UNAVAILABLE;
2530     #endif
2531     #ifdef ENOMEM
2532         case ENOMEM: return DRWAV_OUT_OF_MEMORY;
2533     #endif
2534     #ifdef EACCES
2535         case EACCES: return DRWAV_ACCESS_DENIED;
2536     #endif
2537     #ifdef EFAULT
2538         case EFAULT: return DRWAV_BAD_ADDRESS;
2539     #endif
2540     #ifdef ENOTBLK
2541         case ENOTBLK: return DRWAV_ERROR;
2542     #endif
2543     #ifdef EBUSY
2544         case EBUSY: return DRWAV_BUSY;
2545     #endif
2546     #ifdef EEXIST
2547         case EEXIST: return DRWAV_ALREADY_EXISTS;
2548     #endif
2549     #ifdef EXDEV
2550         case EXDEV: return DRWAV_ERROR;
2551     #endif
2552     #ifdef ENODEV
2553         case ENODEV: return DRWAV_DOES_NOT_EXIST;
2554     #endif
2555     #ifdef ENOTDIR
2556         case ENOTDIR: return DRWAV_NOT_DIRECTORY;
2557     #endif
2558     #ifdef EISDIR
2559         case EISDIR: return DRWAV_IS_DIRECTORY;
2560     #endif
2561     #ifdef EINVAL
2562         case EINVAL: return DRWAV_INVALID_ARGS;
2563     #endif
2564     #ifdef ENFILE
2565         case ENFILE: return DRWAV_TOO_MANY_OPEN_FILES;
2566     #endif
2567     #ifdef EMFILE
2568         case EMFILE: return DRWAV_TOO_MANY_OPEN_FILES;
2569     #endif
2570     #ifdef ENOTTY
2571         case ENOTTY: return DRWAV_INVALID_OPERATION;
2572     #endif
2573     #ifdef ETXTBSY
2574         case ETXTBSY: return DRWAV_BUSY;
2575     #endif
2576     #ifdef EFBIG
2577         case EFBIG: return DRWAV_TOO_BIG;
2578     #endif
2579     #ifdef ENOSPC
2580         case ENOSPC: return DRWAV_NO_SPACE;
2581     #endif
2582     #ifdef ESPIPE
2583         case ESPIPE: return DRWAV_BAD_SEEK;
2584     #endif
2585     #ifdef EROFS
2586         case EROFS: return DRWAV_ACCESS_DENIED;
2587     #endif
2588     #ifdef EMLINK
2589         case EMLINK: return DRWAV_TOO_MANY_LINKS;
2590     #endif
2591     #ifdef EPIPE
2592         case EPIPE: return DRWAV_BAD_PIPE;
2593     #endif
2594     #ifdef EDOM
2595         case EDOM: return DRWAV_OUT_OF_RANGE;
2596     #endif
2597     #ifdef ERANGE
2598         case ERANGE: return DRWAV_OUT_OF_RANGE;
2599     #endif
2600     #ifdef EDEADLK
2601         case EDEADLK: return DRWAV_DEADLOCK;
2602     #endif
2603     #ifdef ENAMETOOLONG
2604         case ENAMETOOLONG: return DRWAV_PATH_TOO_LONG;
2605     #endif
2606     #ifdef ENOLCK
2607         case ENOLCK: return DRWAV_ERROR;
2608     #endif
2609     #ifdef ENOSYS
2610         case ENOSYS: return DRWAV_NOT_IMPLEMENTED;
2611     #endif
2612     #ifdef ENOTEMPTY
2613         case ENOTEMPTY: return DRWAV_DIRECTORY_NOT_EMPTY;
2614     #endif
2615     #ifdef ELOOP
2616         case ELOOP: return DRWAV_TOO_MANY_LINKS;
2617     #endif
2618     #ifdef ENOMSG
2619         case ENOMSG: return DRWAV_NO_MESSAGE;
2620     #endif
2621     #ifdef EIDRM
2622         case EIDRM: return DRWAV_ERROR;
2623     #endif
2624     #ifdef ECHRNG
2625         case ECHRNG: return DRWAV_ERROR;
2626     #endif
2627     #ifdef EL2NSYNC
2628         case EL2NSYNC: return DRWAV_ERROR;
2629     #endif
2630     #ifdef EL3HLT
2631         case EL3HLT: return DRWAV_ERROR;
2632     #endif
2633     #ifdef EL3RST
2634         case EL3RST: return DRWAV_ERROR;
2635     #endif
2636     #ifdef ELNRNG
2637         case ELNRNG: return DRWAV_OUT_OF_RANGE;
2638     #endif
2639     #ifdef EUNATCH
2640         case EUNATCH: return DRWAV_ERROR;
2641     #endif
2642     #ifdef ENOCSI
2643         case ENOCSI: return DRWAV_ERROR;
2644     #endif
2645     #ifdef EL2HLT
2646         case EL2HLT: return DRWAV_ERROR;
2647     #endif
2648     #ifdef EBADE
2649         case EBADE: return DRWAV_ERROR;
2650     #endif
2651     #ifdef EBADR
2652         case EBADR: return DRWAV_ERROR;
2653     #endif
2654     #ifdef EXFULL
2655         case EXFULL: return DRWAV_ERROR;
2656     #endif
2657     #ifdef ENOANO
2658         case ENOANO: return DRWAV_ERROR;
2659     #endif
2660     #ifdef EBADRQC
2661         case EBADRQC: return DRWAV_ERROR;
2662     #endif
2663     #ifdef EBADSLT
2664         case EBADSLT: return DRWAV_ERROR;
2665     #endif
2666     #ifdef EBFONT
2667         case EBFONT: return DRWAV_INVALID_FILE;
2668     #endif
2669     #ifdef ENOSTR
2670         case ENOSTR: return DRWAV_ERROR;
2671     #endif
2672     #ifdef ENODATA
2673         case ENODATA: return DRWAV_NO_DATA_AVAILABLE;
2674     #endif
2675     #ifdef ETIME
2676         case ETIME: return DRWAV_TIMEOUT;
2677     #endif
2678     #ifdef ENOSR
2679         case ENOSR: return DRWAV_NO_DATA_AVAILABLE;
2680     #endif
2681     #ifdef ENONET
2682         case ENONET: return DRWAV_NO_NETWORK;
2683     #endif
2684     #ifdef ENOPKG
2685         case ENOPKG: return DRWAV_ERROR;
2686     #endif
2687     #ifdef EREMOTE
2688         case EREMOTE: return DRWAV_ERROR;
2689     #endif
2690     #ifdef ENOLINK
2691         case ENOLINK: return DRWAV_ERROR;
2692     #endif
2693     #ifdef EADV
2694         case EADV: return DRWAV_ERROR;
2695     #endif
2696     #ifdef ESRMNT
2697         case ESRMNT: return DRWAV_ERROR;
2698     #endif
2699     #ifdef ECOMM
2700         case ECOMM: return DRWAV_ERROR;
2701     #endif
2702     #ifdef EPROTO
2703         case EPROTO: return DRWAV_ERROR;
2704     #endif
2705     #ifdef EMULTIHOP
2706         case EMULTIHOP: return DRWAV_ERROR;
2707     #endif
2708     #ifdef EDOTDOT
2709         case EDOTDOT: return DRWAV_ERROR;
2710     #endif
2711     #ifdef EBADMSG
2712         case EBADMSG: return DRWAV_BAD_MESSAGE;
2713     #endif
2714     #ifdef EOVERFLOW
2715         case EOVERFLOW: return DRWAV_TOO_BIG;
2716     #endif
2717     #ifdef ENOTUNIQ
2718         case ENOTUNIQ: return DRWAV_NOT_UNIQUE;
2719     #endif
2720     #ifdef EBADFD
2721         case EBADFD: return DRWAV_ERROR;
2722     #endif
2723     #ifdef EREMCHG
2724         case EREMCHG: return DRWAV_ERROR;
2725     #endif
2726     #ifdef ELIBACC
2727         case ELIBACC: return DRWAV_ACCESS_DENIED;
2728     #endif
2729     #ifdef ELIBBAD
2730         case ELIBBAD: return DRWAV_INVALID_FILE;
2731     #endif
2732     #ifdef ELIBSCN
2733         case ELIBSCN: return DRWAV_INVALID_FILE;
2734     #endif
2735     #ifdef ELIBMAX
2736         case ELIBMAX: return DRWAV_ERROR;
2737     #endif
2738     #ifdef ELIBEXEC
2739         case ELIBEXEC: return DRWAV_ERROR;
2740     #endif
2741     #ifdef EILSEQ
2742         case EILSEQ: return DRWAV_INVALID_DATA;
2743     #endif
2744     #ifdef ERESTART
2745         case ERESTART: return DRWAV_ERROR;
2746     #endif
2747     #ifdef ESTRPIPE
2748         case ESTRPIPE: return DRWAV_ERROR;
2749     #endif
2750     #ifdef EUSERS
2751         case EUSERS: return DRWAV_ERROR;
2752     #endif
2753     #ifdef ENOTSOCK
2754         case ENOTSOCK: return DRWAV_NOT_SOCKET;
2755     #endif
2756     #ifdef EDESTADDRREQ
2757         case EDESTADDRREQ: return DRWAV_NO_ADDRESS;
2758     #endif
2759     #ifdef EMSGSIZE
2760         case EMSGSIZE: return DRWAV_TOO_BIG;
2761     #endif
2762     #ifdef EPROTOTYPE
2763         case EPROTOTYPE: return DRWAV_BAD_PROTOCOL;
2764     #endif
2765     #ifdef ENOPROTOOPT
2766         case ENOPROTOOPT: return DRWAV_PROTOCOL_UNAVAILABLE;
2767     #endif
2768     #ifdef EPROTONOSUPPORT
2769         case EPROTONOSUPPORT: return DRWAV_PROTOCOL_NOT_SUPPORTED;
2770     #endif
2771     #ifdef ESOCKTNOSUPPORT
2772         case ESOCKTNOSUPPORT: return DRWAV_SOCKET_NOT_SUPPORTED;
2773     #endif
2774     #ifdef EOPNOTSUPP
2775         case EOPNOTSUPP: return DRWAV_INVALID_OPERATION;
2776     #endif
2777     #ifdef EPFNOSUPPORT
2778         case EPFNOSUPPORT: return DRWAV_PROTOCOL_FAMILY_NOT_SUPPORTED;
2779     #endif
2780     #ifdef EAFNOSUPPORT
2781         case EAFNOSUPPORT: return DRWAV_ADDRESS_FAMILY_NOT_SUPPORTED;
2782     #endif
2783     #ifdef EADDRINUSE
2784         case EADDRINUSE: return DRWAV_ALREADY_IN_USE;
2785     #endif
2786     #ifdef EADDRNOTAVAIL
2787         case EADDRNOTAVAIL: return DRWAV_ERROR;
2788     #endif
2789     #ifdef ENETDOWN
2790         case ENETDOWN: return DRWAV_NO_NETWORK;
2791     #endif
2792     #ifdef ENETUNREACH
2793         case ENETUNREACH: return DRWAV_NO_NETWORK;
2794     #endif
2795     #ifdef ENETRESET
2796         case ENETRESET: return DRWAV_NO_NETWORK;
2797     #endif
2798     #ifdef ECONNABORTED
2799         case ECONNABORTED: return DRWAV_NO_NETWORK;
2800     #endif
2801     #ifdef ECONNRESET
2802         case ECONNRESET: return DRWAV_CONNECTION_RESET;
2803     #endif
2804     #ifdef ENOBUFS
2805         case ENOBUFS: return DRWAV_NO_SPACE;
2806     #endif
2807     #ifdef EISCONN
2808         case EISCONN: return DRWAV_ALREADY_CONNECTED;
2809     #endif
2810     #ifdef ENOTCONN
2811         case ENOTCONN: return DRWAV_NOT_CONNECTED;
2812     #endif
2813     #ifdef ESHUTDOWN
2814         case ESHUTDOWN: return DRWAV_ERROR;
2815     #endif
2816     #ifdef ETOOMANYREFS
2817         case ETOOMANYREFS: return DRWAV_ERROR;
2818     #endif
2819     #ifdef ETIMEDOUT
2820         case ETIMEDOUT: return DRWAV_TIMEOUT;
2821     #endif
2822     #ifdef ECONNREFUSED
2823         case ECONNREFUSED: return DRWAV_CONNECTION_REFUSED;
2824     #endif
2825     #ifdef EHOSTDOWN
2826         case EHOSTDOWN: return DRWAV_NO_HOST;
2827     #endif
2828     #ifdef EHOSTUNREACH
2829         case EHOSTUNREACH: return DRWAV_NO_HOST;
2830     #endif
2831     #ifdef EALREADY
2832         case EALREADY: return DRWAV_IN_PROGRESS;
2833     #endif
2834     #ifdef EINPROGRESS
2835         case EINPROGRESS: return DRWAV_IN_PROGRESS;
2836     #endif
2837     #ifdef ESTALE
2838         case ESTALE: return DRWAV_INVALID_FILE;
2839     #endif
2840     #ifdef EUCLEAN
2841         case EUCLEAN: return DRWAV_ERROR;
2842     #endif
2843     #ifdef ENOTNAM
2844         case ENOTNAM: return DRWAV_ERROR;
2845     #endif
2846     #ifdef ENAVAIL
2847         case ENAVAIL: return DRWAV_ERROR;
2848     #endif
2849     #ifdef EISNAM
2850         case EISNAM: return DRWAV_ERROR;
2851     #endif
2852     #ifdef EREMOTEIO
2853         case EREMOTEIO: return DRWAV_IO_ERROR;
2854     #endif
2855     #ifdef EDQUOT
2856         case EDQUOT: return DRWAV_NO_SPACE;
2857     #endif
2858     #ifdef ENOMEDIUM
2859         case ENOMEDIUM: return DRWAV_DOES_NOT_EXIST;
2860     #endif
2861     #ifdef EMEDIUMTYPE
2862         case EMEDIUMTYPE: return DRWAV_ERROR;
2863     #endif
2864     #ifdef ECANCELED
2865         case ECANCELED: return DRWAV_CANCELLED;
2866     #endif
2867     #ifdef ENOKEY
2868         case ENOKEY: return DRWAV_ERROR;
2869     #endif
2870     #ifdef EKEYEXPIRED
2871         case EKEYEXPIRED: return DRWAV_ERROR;
2872     #endif
2873     #ifdef EKEYREVOKED
2874         case EKEYREVOKED: return DRWAV_ERROR;
2875     #endif
2876     #ifdef EKEYREJECTED
2877         case EKEYREJECTED: return DRWAV_ERROR;
2878     #endif
2879     #ifdef EOWNERDEAD
2880         case EOWNERDEAD: return DRWAV_ERROR;
2881     #endif
2882     #ifdef ENOTRECOVERABLE
2883         case ENOTRECOVERABLE: return DRWAV_ERROR;
2884     #endif
2885     #ifdef ERFKILL
2886         case ERFKILL: return DRWAV_ERROR;
2887     #endif
2888     #ifdef EHWPOISON
2889         case EHWPOISON: return DRWAV_ERROR;
2890     #endif
2891         default: return DRWAV_ERROR;
2892     }
2893 }
2894
2895 DRWAV_PRIVATE drwav_result drwav_fopen(FILE** ppFile, const char* pFilePath, const char* pOpenMode)
2896 {
2897 #if defined(_MSC_VER) && _MSC_VER >= 1400
2898     errno_t err;
2899 #endif
2900
2901     if (ppFile != NULL) {
2902         *ppFile = NULL;  /* Safety. */
2903     }
2904
2905     if (pFilePath == NULL || pOpenMode == NULL || ppFile == NULL) {
2906         return DRWAV_INVALID_ARGS;
2907     }
2908
2909 #if defined(_MSC_VER) && _MSC_VER >= 1400
2910     err = fopen_s(ppFile, pFilePath, pOpenMode);
2911     if (err != 0) {
2912         return drwav_result_from_errno(err);
2913     }
2914 #else
2915 #if defined(_WIN32) || defined(__APPLE__)
2916     *ppFile = fopen(pFilePath, pOpenMode);
2917 #else
2918     #if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64 && defined(_LARGEFILE64_SOURCE)
2919         *ppFile = fopen64(pFilePath, pOpenMode);
2920     #else
2921         *ppFile = fopen(pFilePath, pOpenMode);
2922     #endif
2923 #endif
2924     if (*ppFile == NULL) {
2925         drwav_result result = drwav_result_from_errno(errno);
2926         if (result == DRWAV_SUCCESS) {
2927             result = DRWAV_ERROR;   /* Just a safety check to make sure we never ever return success when pFile == NULL. */
2928         }
2929
2930         return result;
2931     }
2932 #endif
2933
2934     return DRWAV_SUCCESS;
2935 }
2936
2937 /*
2938 _wfopen() isn't always available in all compilation environments.
2939
2940     * Windows only.
2941     * MSVC seems to support it universally as far back as VC6 from what I can tell (haven't checked further back).
2942     * MinGW-64 (both 32- and 64-bit) seems to support it.
2943     * MinGW wraps it in !defined(__STRICT_ANSI__).
2944     * OpenWatcom wraps it in !defined(_NO_EXT_KEYS).
2945
2946 This can be reviewed as compatibility issues arise. The preference is to use _wfopen_s() and _wfopen() as opposed to the wcsrtombs()
2947 fallback, so if you notice your compiler not detecting this properly I'm happy to look at adding support.
2948 */
2949 #if defined(_WIN32)
2950     #if defined(_MSC_VER) || defined(__MINGW64__) || (!defined(__STRICT_ANSI__) && !defined(_NO_EXT_KEYS))
2951         #define DRWAV_HAS_WFOPEN
2952     #endif
2953 #endif
2954
2955 DRWAV_PRIVATE drwav_result drwav_wfopen(FILE** ppFile, const wchar_t* pFilePath, const wchar_t* pOpenMode, const drwav_allocation_callbacks* pAllocationCallbacks)
2956 {
2957     if (ppFile != NULL) {
2958         *ppFile = NULL;  /* Safety. */
2959     }
2960
2961     if (pFilePath == NULL || pOpenMode == NULL || ppFile == NULL) {
2962         return DRWAV_INVALID_ARGS;
2963     }
2964
2965 #if defined(DRWAV_HAS_WFOPEN)
2966     {
2967         /* Use _wfopen() on Windows. */
2968     #if defined(_MSC_VER) && _MSC_VER >= 1400
2969         errno_t err = _wfopen_s(ppFile, pFilePath, pOpenMode);
2970         if (err != 0) {
2971             return drwav_result_from_errno(err);
2972         }
2973     #else
2974         *ppFile = _wfopen(pFilePath, pOpenMode);
2975         if (*ppFile == NULL) {
2976             return drwav_result_from_errno(errno);
2977         }
2978     #endif
2979         (void)pAllocationCallbacks;
2980     }
2981 #else
2982     /*
2983     Use fopen() on anything other than Windows. Requires a conversion. This is annoying because fopen() is locale specific. The only real way I can
2984     think of to do this is with wcsrtombs(). Note that wcstombs() is apparently not thread-safe because it uses a static global mbstate_t object for
2985     maintaining state. I've checked this with -std=c89 and it works, but if somebody get's a compiler error I'll look into improving compatibility.
2986     */
2987     {
2988         mbstate_t mbs;
2989         size_t lenMB;
2990         const wchar_t* pFilePathTemp = pFilePath;
2991         char* pFilePathMB = NULL;
2992         char pOpenModeMB[32] = {0};
2993
2994         /* Get the length first. */
2995         DRWAV_ZERO_OBJECT(&mbs);
2996         lenMB = wcsrtombs(NULL, &pFilePathTemp, 0, &mbs);
2997         if (lenMB == (size_t)-1) {
2998             return drwav_result_from_errno(errno);
2999         }
3000
3001         pFilePathMB = (char*)drwav__malloc_from_callbacks(lenMB + 1, pAllocationCallbacks);
3002         if (pFilePathMB == NULL) {
3003             return DRWAV_OUT_OF_MEMORY;
3004         }
3005
3006         pFilePathTemp = pFilePath;
3007         DRWAV_ZERO_OBJECT(&mbs);
3008         wcsrtombs(pFilePathMB, &pFilePathTemp, lenMB + 1, &mbs);
3009
3010         /* The open mode should always consist of ASCII characters so we should be able to do a trivial conversion. */
3011         {
3012             size_t i = 0;
3013             for (;;) {
3014                 if (pOpenMode[i] == 0) {
3015                     pOpenModeMB[i] = '\0';
3016                     break;
3017                 }
3018
3019                 pOpenModeMB[i] = (char)pOpenMode[i];
3020                 i += 1;
3021             }
3022         }
3023
3024         *ppFile = fopen(pFilePathMB, pOpenModeMB);
3025
3026         drwav__free_from_callbacks(pFilePathMB, pAllocationCallbacks);
3027     }
3028
3029     if (*ppFile == NULL) {
3030         return DRWAV_ERROR;
3031     }
3032 #endif
3033
3034     return DRWAV_SUCCESS;
3035 }
3036
3037
3038 DRWAV_PRIVATE size_t drwav__on_read_stdio(void* pUserData, void* pBufferOut, size_t bytesToRead)
3039 {
3040     return fread(pBufferOut, 1, bytesToRead, (FILE*)pUserData);
3041 }
3042
3043 DRWAV_PRIVATE size_t drwav__on_write_stdio(void* pUserData, const void* pData, size_t bytesToWrite)
3044 {
3045     return fwrite(pData, 1, bytesToWrite, (FILE*)pUserData);
3046 }
3047
3048 DRWAV_PRIVATE drwav_bool32 drwav__on_seek_stdio(void* pUserData, int offset, drwav_seek_origin origin)
3049 {
3050     return fseek((FILE*)pUserData, offset, (origin == drwav_seek_origin_current) ? SEEK_CUR : SEEK_SET) == 0;
3051 }
3052
3053 DRWAV_API drwav_bool32 drwav_init_file(drwav* pWav, const char* filename, const drwav_allocation_callbacks* pAllocationCallbacks)
3054 {
3055     return drwav_init_file_ex(pWav, filename, NULL, NULL, 0, pAllocationCallbacks);
3056 }
3057
3058
3059 DRWAV_PRIVATE drwav_bool32 drwav_init_file__internal_FILE(drwav* pWav, FILE* pFile, drwav_chunk_proc onChunk, void* pChunkUserData, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks)
3060 {
3061     drwav_bool32 result;
3062
3063     result = drwav_preinit(pWav, drwav__on_read_stdio, drwav__on_seek_stdio, (void*)pFile, pAllocationCallbacks);
3064     if (result != DRWAV_TRUE) {
3065         fclose(pFile);
3066         return result;
3067     }
3068
3069     result = drwav_init__internal(pWav, onChunk, pChunkUserData, flags);
3070     if (result != DRWAV_TRUE) {
3071         fclose(pFile);
3072         return result;
3073     }
3074
3075     return DRWAV_TRUE;
3076 }
3077
3078 DRWAV_API drwav_bool32 drwav_init_file_ex(drwav* pWav, const char* filename, drwav_chunk_proc onChunk, void* pChunkUserData, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks)
3079 {
3080     FILE* pFile;
3081     if (drwav_fopen(&pFile, filename, "rb") != DRWAV_SUCCESS) {
3082         return DRWAV_FALSE;
3083     }
3084
3085     /* This takes ownership of the FILE* object. */
3086     return drwav_init_file__internal_FILE(pWav, pFile, onChunk, pChunkUserData, flags, pAllocationCallbacks);
3087 }
3088
3089 DRWAV_API drwav_bool32 drwav_init_file_w(drwav* pWav, const wchar_t* filename, const drwav_allocation_callbacks* pAllocationCallbacks)
3090 {
3091     return drwav_init_file_ex_w(pWav, filename, NULL, NULL, 0, pAllocationCallbacks);
3092 }
3093
3094 DRWAV_API drwav_bool32 drwav_init_file_ex_w(drwav* pWav, const wchar_t* filename, drwav_chunk_proc onChunk, void* pChunkUserData, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks)
3095 {
3096     FILE* pFile;
3097     if (drwav_wfopen(&pFile, filename, L"rb", pAllocationCallbacks) != DRWAV_SUCCESS) {
3098         return DRWAV_FALSE;
3099     }
3100
3101     /* This takes ownership of the FILE* object. */
3102     return drwav_init_file__internal_FILE(pWav, pFile, onChunk, pChunkUserData, flags, pAllocationCallbacks);
3103 }
3104
3105
3106 DRWAV_PRIVATE drwav_bool32 drwav_init_file_write__internal_FILE(drwav* pWav, FILE* pFile, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount, drwav_bool32 isSequential, const drwav_allocation_callbacks* pAllocationCallbacks)
3107 {
3108     drwav_bool32 result;
3109
3110     result = drwav_preinit_write(pWav, pFormat, isSequential, drwav__on_write_stdio, drwav__on_seek_stdio, (void*)pFile, pAllocationCallbacks);
3111     if (result != DRWAV_TRUE) {
3112         fclose(pFile);
3113         return result;
3114     }
3115
3116     result = drwav_init_write__internal(pWav, pFormat, totalSampleCount);
3117     if (result != DRWAV_TRUE) {
3118         fclose(pFile);
3119         return result;
3120     }
3121
3122     return DRWAV_TRUE;
3123 }
3124
3125 DRWAV_PRIVATE drwav_bool32 drwav_init_file_write__internal(drwav* pWav, const char* filename, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount, drwav_bool32 isSequential, const drwav_allocation_callbacks* pAllocationCallbacks)
3126 {
3127     FILE* pFile;
3128     if (drwav_fopen(&pFile, filename, "wb") != DRWAV_SUCCESS) {
3129         return DRWAV_FALSE;
3130     }
3131
3132     /* This takes ownership of the FILE* object. */
3133     return drwav_init_file_write__internal_FILE(pWav, pFile, pFormat, totalSampleCount, isSequential, pAllocationCallbacks);
3134 }
3135
3136 DRWAV_PRIVATE drwav_bool32 drwav_init_file_write_w__internal(drwav* pWav, const wchar_t* filename, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount, drwav_bool32 isSequential, const drwav_allocation_callbacks* pAllocationCallbacks)
3137 {
3138     FILE* pFile;
3139     if (drwav_wfopen(&pFile, filename, L"wb", pAllocationCallbacks) != DRWAV_SUCCESS) {
3140         return DRWAV_FALSE;
3141     }
3142
3143     /* This takes ownership of the FILE* object. */
3144     return drwav_init_file_write__internal_FILE(pWav, pFile, pFormat, totalSampleCount, isSequential, pAllocationCallbacks);
3145 }
3146
3147 DRWAV_API drwav_bool32 drwav_init_file_write(drwav* pWav, const char* filename, const drwav_data_format* pFormat, const drwav_allocation_callbacks* pAllocationCallbacks)
3148 {
3149     return drwav_init_file_write__internal(pWav, filename, pFormat, 0, DRWAV_FALSE, pAllocationCallbacks);
3150 }
3151
3152 DRWAV_API drwav_bool32 drwav_init_file_write_sequential(drwav* pWav, const char* filename, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount, const drwav_allocation_callbacks* pAllocationCallbacks)
3153 {
3154     return drwav_init_file_write__internal(pWav, filename, pFormat, totalSampleCount, DRWAV_TRUE, pAllocationCallbacks);
3155 }
3156
3157 DRWAV_API drwav_bool32 drwav_init_file_write_sequential_pcm_frames(drwav* pWav, const char* filename, const drwav_data_format* pFormat, drwav_uint64 totalPCMFrameCount, const drwav_allocation_callbacks* pAllocationCallbacks)
3158 {
3159     if (pFormat == NULL) {
3160         return DRWAV_FALSE;
3161     }
3162
3163     return drwav_init_file_write_sequential(pWav, filename, pFormat, totalPCMFrameCount*pFormat->channels, pAllocationCallbacks);
3164 }
3165
3166 DRWAV_API drwav_bool32 drwav_init_file_write_w(drwav* pWav, const wchar_t* filename, const drwav_data_format* pFormat, const drwav_allocation_callbacks* pAllocationCallbacks)
3167 {
3168     return drwav_init_file_write_w__internal(pWav, filename, pFormat, 0, DRWAV_FALSE, pAllocationCallbacks);
3169 }
3170
3171 DRWAV_API drwav_bool32 drwav_init_file_write_sequential_w(drwav* pWav, const wchar_t* filename, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount, const drwav_allocation_callbacks* pAllocationCallbacks)
3172 {
3173     return drwav_init_file_write_w__internal(pWav, filename, pFormat, totalSampleCount, DRWAV_TRUE, pAllocationCallbacks);
3174 }
3175
3176 DRWAV_API drwav_bool32 drwav_init_file_write_sequential_pcm_frames_w(drwav* pWav, const wchar_t* filename, const drwav_data_format* pFormat, drwav_uint64 totalPCMFrameCount, const drwav_allocation_callbacks* pAllocationCallbacks)
3177 {
3178     if (pFormat == NULL) {
3179         return DRWAV_FALSE;
3180     }
3181
3182     return drwav_init_file_write_sequential_w(pWav, filename, pFormat, totalPCMFrameCount*pFormat->channels, pAllocationCallbacks);
3183 }
3184 #endif  /* DR_WAV_NO_STDIO */
3185
3186
3187 DRWAV_PRIVATE size_t drwav__on_read_memory(void* pUserData, void* pBufferOut, size_t bytesToRead)
3188 {
3189     drwav* pWav = (drwav*)pUserData;
3190     size_t bytesRemaining;
3191
3192     DRWAV_ASSERT(pWav != NULL);
3193     DRWAV_ASSERT(pWav->memoryStream.dataSize >= pWav->memoryStream.currentReadPos);
3194
3195     bytesRemaining = pWav->memoryStream.dataSize - pWav->memoryStream.currentReadPos;
3196     if (bytesToRead > bytesRemaining) {
3197         bytesToRead = bytesRemaining;
3198     }
3199
3200     if (bytesToRead > 0) {
3201         DRWAV_COPY_MEMORY(pBufferOut, pWav->memoryStream.data + pWav->memoryStream.currentReadPos, bytesToRead);
3202         pWav->memoryStream.currentReadPos += bytesToRead;
3203     }
3204
3205     return bytesToRead;
3206 }
3207
3208 DRWAV_PRIVATE drwav_bool32 drwav__on_seek_memory(void* pUserData, int offset, drwav_seek_origin origin)
3209 {
3210     drwav* pWav = (drwav*)pUserData;
3211     DRWAV_ASSERT(pWav != NULL);
3212
3213     if (origin == drwav_seek_origin_current) {
3214         if (offset > 0) {
3215             if (pWav->memoryStream.currentReadPos + offset > pWav->memoryStream.dataSize) {
3216                 return DRWAV_FALSE; /* Trying to seek too far forward. */
3217             }
3218         } else {
3219             if (pWav->memoryStream.currentReadPos < (size_t)-offset) {
3220                 return DRWAV_FALSE; /* Trying to seek too far backwards. */
3221             }
3222         }
3223
3224         /* This will never underflow thanks to the clamps above. */
3225         pWav->memoryStream.currentReadPos += offset;
3226     } else {
3227         if ((drwav_uint32)offset <= pWav->memoryStream.dataSize) {
3228             pWav->memoryStream.currentReadPos = offset;
3229         } else {
3230             return DRWAV_FALSE; /* Trying to seek too far forward. */
3231         }
3232     }
3233     
3234     return DRWAV_TRUE;
3235 }
3236
3237 DRWAV_PRIVATE size_t drwav__on_write_memory(void* pUserData, const void* pDataIn, size_t bytesToWrite)
3238 {
3239     drwav* pWav = (drwav*)pUserData;
3240     size_t bytesRemaining;
3241
3242     DRWAV_ASSERT(pWav != NULL);
3243     DRWAV_ASSERT(pWav->memoryStreamWrite.dataCapacity >= pWav->memoryStreamWrite.currentWritePos);
3244
3245     bytesRemaining = pWav->memoryStreamWrite.dataCapacity - pWav->memoryStreamWrite.currentWritePos;
3246     if (bytesRemaining < bytesToWrite) {
3247         /* Need to reallocate. */
3248         void* pNewData;
3249         size_t newDataCapacity = (pWav->memoryStreamWrite.dataCapacity == 0) ? 256 : pWav->memoryStreamWrite.dataCapacity * 2;
3250
3251         /* If doubling wasn't enough, just make it the minimum required size to write the data. */
3252         if ((newDataCapacity - pWav->memoryStreamWrite.currentWritePos) < bytesToWrite) {
3253             newDataCapacity = pWav->memoryStreamWrite.currentWritePos + bytesToWrite;
3254         }
3255
3256         pNewData = drwav__realloc_from_callbacks(*pWav->memoryStreamWrite.ppData, newDataCapacity, pWav->memoryStreamWrite.dataCapacity, &pWav->allocationCallbacks);
3257         if (pNewData == NULL) {
3258             return 0;
3259         }
3260
3261         *pWav->memoryStreamWrite.ppData = pNewData;
3262         pWav->memoryStreamWrite.dataCapacity = newDataCapacity;
3263     }
3264
3265     DRWAV_COPY_MEMORY(((drwav_uint8*)(*pWav->memoryStreamWrite.ppData)) + pWav->memoryStreamWrite.currentWritePos, pDataIn, bytesToWrite);
3266
3267     pWav->memoryStreamWrite.currentWritePos += bytesToWrite;
3268     if (pWav->memoryStreamWrite.dataSize < pWav->memoryStreamWrite.currentWritePos) {
3269         pWav->memoryStreamWrite.dataSize = pWav->memoryStreamWrite.currentWritePos;
3270     }
3271
3272     *pWav->memoryStreamWrite.pDataSize = pWav->memoryStreamWrite.dataSize;
3273
3274     return bytesToWrite;
3275 }
3276
3277 DRWAV_PRIVATE drwav_bool32 drwav__on_seek_memory_write(void* pUserData, int offset, drwav_seek_origin origin)
3278 {
3279     drwav* pWav = (drwav*)pUserData;
3280     DRWAV_ASSERT(pWav != NULL);
3281
3282     if (origin == drwav_seek_origin_current) {
3283         if (offset > 0) {
3284             if (pWav->memoryStreamWrite.currentWritePos + offset > pWav->memoryStreamWrite.dataSize) {
3285                 offset = (int)(pWav->memoryStreamWrite.dataSize - pWav->memoryStreamWrite.currentWritePos);  /* Trying to seek too far forward. */
3286             }
3287         } else {
3288             if (pWav->memoryStreamWrite.currentWritePos < (size_t)-offset) {
3289                 offset = -(int)pWav->memoryStreamWrite.currentWritePos;  /* Trying to seek too far backwards. */
3290             }
3291         }
3292
3293         /* This will never underflow thanks to the clamps above. */
3294         pWav->memoryStreamWrite.currentWritePos += offset;
3295     } else {
3296         if ((drwav_uint32)offset <= pWav->memoryStreamWrite.dataSize) {
3297             pWav->memoryStreamWrite.currentWritePos = offset;
3298         } else {
3299             pWav->memoryStreamWrite.currentWritePos = pWav->memoryStreamWrite.dataSize;  /* Trying to seek too far forward. */
3300         }
3301     }
3302     
3303     return DRWAV_TRUE;
3304 }
3305
3306 DRWAV_API drwav_bool32 drwav_init_memory(drwav* pWav, const void* data, size_t dataSize, const drwav_allocation_callbacks* pAllocationCallbacks)
3307 {
3308     return drwav_init_memory_ex(pWav, data, dataSize, NULL, NULL, 0, pAllocationCallbacks);
3309 }
3310
3311 DRWAV_API drwav_bool32 drwav_init_memory_ex(drwav* pWav, const void* data, size_t dataSize, drwav_chunk_proc onChunk, void* pChunkUserData, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks)
3312 {
3313     if (data == NULL || dataSize == 0) {
3314         return DRWAV_FALSE;
3315     }
3316
3317     if (!drwav_preinit(pWav, drwav__on_read_memory, drwav__on_seek_memory, pWav, pAllocationCallbacks)) {
3318         return DRWAV_FALSE;
3319     }
3320
3321     pWav->memoryStream.data = (const drwav_uint8*)data;
3322     pWav->memoryStream.dataSize = dataSize;
3323     pWav->memoryStream.currentReadPos = 0;
3324
3325     return drwav_init__internal(pWav, onChunk, pChunkUserData, flags);
3326 }
3327
3328
3329 DRWAV_PRIVATE 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, const drwav_allocation_callbacks* pAllocationCallbacks)
3330 {
3331     if (ppData == NULL || pDataSize == NULL) {
3332         return DRWAV_FALSE;
3333     }
3334
3335     *ppData = NULL; /* Important because we're using realloc()! */
3336     *pDataSize = 0;
3337
3338     if (!drwav_preinit_write(pWav, pFormat, isSequential, drwav__on_write_memory, drwav__on_seek_memory_write, pWav, pAllocationCallbacks)) {
3339         return DRWAV_FALSE;
3340     }
3341
3342     pWav->memoryStreamWrite.ppData = ppData;
3343     pWav->memoryStreamWrite.pDataSize = pDataSize;
3344     pWav->memoryStreamWrite.dataSize = 0;
3345     pWav->memoryStreamWrite.dataCapacity = 0;
3346     pWav->memoryStreamWrite.currentWritePos = 0;
3347
3348     return drwav_init_write__internal(pWav, pFormat, totalSampleCount);
3349 }
3350
3351 DRWAV_API drwav_bool32 drwav_init_memory_write(drwav* pWav, void** ppData, size_t* pDataSize, const drwav_data_format* pFormat, const drwav_allocation_callbacks* pAllocationCallbacks)
3352 {
3353     return drwav_init_memory_write__internal(pWav, ppData, pDataSize, pFormat, 0, DRWAV_FALSE, pAllocationCallbacks);
3354 }
3355
3356 DRWAV_API drwav_bool32 drwav_init_memory_write_sequential(drwav* pWav, void** ppData, size_t* pDataSize, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount, const drwav_allocation_callbacks* pAllocationCallbacks)
3357 {
3358     return drwav_init_memory_write__internal(pWav, ppData, pDataSize, pFormat, totalSampleCount, DRWAV_TRUE, pAllocationCallbacks);
3359 }
3360
3361 DRWAV_API drwav_bool32 drwav_init_memory_write_sequential_pcm_frames(drwav* pWav, void** ppData, size_t* pDataSize, const drwav_data_format* pFormat, drwav_uint64 totalPCMFrameCount, const drwav_allocation_callbacks* pAllocationCallbacks)
3362 {
3363     if (pFormat == NULL) {
3364         return DRWAV_FALSE;
3365     }
3366
3367     return drwav_init_memory_write_sequential(pWav, ppData, pDataSize, pFormat, totalPCMFrameCount*pFormat->channels, pAllocationCallbacks);
3368 }
3369
3370
3371
3372 DRWAV_API drwav_result drwav_uninit(drwav* pWav)
3373 {
3374     drwav_result result = DRWAV_SUCCESS;
3375
3376     if (pWav == NULL) {
3377         return DRWAV_INVALID_ARGS;
3378     }
3379
3380     /*
3381     If the drwav object was opened in write mode we'll need to finalize a few things:
3382       - Make sure the "data" chunk is aligned to 16-bits for RIFF containers, or 64 bits for W64 containers.
3383       - Set the size of the "data" chunk.
3384     */
3385     if (pWav->onWrite != NULL) {
3386         drwav_uint32 paddingSize = 0;
3387
3388         /* Padding. Do not adjust pWav->dataChunkDataSize - this should not include the padding. */
3389         if (pWav->container == drwav_container_riff || pWav->container == drwav_container_rf64) {
3390             paddingSize = drwav__chunk_padding_size_riff(pWav->dataChunkDataSize);
3391         } else {
3392             paddingSize = drwav__chunk_padding_size_w64(pWav->dataChunkDataSize);
3393         }
3394         
3395         if (paddingSize > 0) {
3396             drwav_uint64 paddingData = 0;
3397             drwav__write(pWav, &paddingData, paddingSize);  /* Byte order does not matter for this. */
3398         }
3399
3400         /*
3401         Chunk sizes. When using sequential mode, these will have been filled in at initialization time. We only need
3402         to do this when using non-sequential mode.
3403         */
3404         if (pWav->onSeek && !pWav->isSequentialWrite) {
3405             if (pWav->container == drwav_container_riff) {
3406                 /* The "RIFF" chunk size. */
3407                 if (pWav->onSeek(pWav->pUserData, 4, drwav_seek_origin_start)) {
3408                     drwav_uint32 riffChunkSize = drwav__riff_chunk_size_riff(pWav->dataChunkDataSize);
3409                     drwav__write_u32ne_to_le(pWav, riffChunkSize);
3410                 }
3411
3412                 /* The "data" chunk size. */
3413                 if (pWav->onSeek(pWav->pUserData, (int)pWav->dataChunkDataPos - 4, drwav_seek_origin_start)) {
3414                     drwav_uint32 dataChunkSize = drwav__data_chunk_size_riff(pWav->dataChunkDataSize);
3415                     drwav__write_u32ne_to_le(pWav, dataChunkSize);
3416                 }
3417             } else if (pWav->container == drwav_container_w64) {
3418                 /* The "RIFF" chunk size. */
3419                 if (pWav->onSeek(pWav->pUserData, 16, drwav_seek_origin_start)) {
3420                     drwav_uint64 riffChunkSize = drwav__riff_chunk_size_w64(pWav->dataChunkDataSize);
3421                     drwav__write_u64ne_to_le(pWav, riffChunkSize);
3422                 }
3423
3424                 /* The "data" chunk size. */
3425                 if (pWav->onSeek(pWav->pUserData, (int)pWav->dataChunkDataPos - 8, drwav_seek_origin_start)) {
3426                     drwav_uint64 dataChunkSize = drwav__data_chunk_size_w64(pWav->dataChunkDataSize);
3427                     drwav__write_u64ne_to_le(pWav, dataChunkSize);
3428                 }
3429             } else if (pWav->container == drwav_container_rf64) {
3430                 /* We only need to update the ds64 chunk. The "RIFF" and "data" chunks always have their sizes set to 0xFFFFFFFF for RF64. */
3431                 int ds64BodyPos = 12 + 8;
3432
3433                 /* The "RIFF" chunk size. */
3434                 if (pWav->onSeek(pWav->pUserData, ds64BodyPos + 0, drwav_seek_origin_start)) {
3435                     drwav_uint64 riffChunkSize = drwav__riff_chunk_size_rf64(pWav->dataChunkDataSize);
3436                     drwav__write_u64ne_to_le(pWav, riffChunkSize);
3437                 }
3438
3439                 /* The "data" chunk size. */
3440                 if (pWav->onSeek(pWav->pUserData, ds64BodyPos + 8, drwav_seek_origin_start)) {
3441                     drwav_uint64 dataChunkSize = drwav__data_chunk_size_rf64(pWav->dataChunkDataSize);
3442                     drwav__write_u64ne_to_le(pWav, dataChunkSize);
3443                 }
3444             }
3445         }
3446
3447         /* Validation for sequential mode. */
3448         if (pWav->isSequentialWrite) {
3449             if (pWav->dataChunkDataSize != pWav->dataChunkDataSizeTargetWrite) {
3450                 result = DRWAV_INVALID_FILE;
3451             }
3452         }
3453     }
3454
3455 #ifndef DR_WAV_NO_STDIO
3456     /*
3457     If we opened the file with drwav_open_file() we will want to close the file handle. We can know whether or not drwav_open_file()
3458     was used by looking at the onRead and onSeek callbacks.
3459     */
3460     if (pWav->onRead == drwav__on_read_stdio || pWav->onWrite == drwav__on_write_stdio) {
3461         fclose((FILE*)pWav->pUserData);
3462     }
3463 #endif
3464
3465     return result;
3466 }
3467
3468
3469
3470 DRWAV_API size_t drwav_read_raw(drwav* pWav, size_t bytesToRead, void* pBufferOut)
3471 {
3472     size_t bytesRead;
3473
3474     if (pWav == NULL || bytesToRead == 0) {
3475         return 0;
3476     }
3477
3478     if (bytesToRead > pWav->bytesRemaining) {
3479         bytesToRead = (size_t)pWav->bytesRemaining;
3480     }
3481
3482     if (pBufferOut != NULL) {
3483         bytesRead = pWav->onRead(pWav->pUserData, pBufferOut, bytesToRead);
3484     } else {
3485         /* We need to seek. If we fail, we need to read-and-discard to make sure we get a good byte count. */
3486         bytesRead = 0;
3487         while (bytesRead < bytesToRead) {
3488             size_t bytesToSeek = (bytesToRead - bytesRead);
3489             if (bytesToSeek > 0x7FFFFFFF) {
3490                 bytesToSeek = 0x7FFFFFFF;
3491             }
3492
3493             if (pWav->onSeek(pWav->pUserData, (int)bytesToSeek, drwav_seek_origin_current) == DRWAV_FALSE) {
3494                 break;
3495             }
3496
3497             bytesRead += bytesToSeek;
3498         }
3499
3500         /* When we get here we may need to read-and-discard some data. */
3501         while (bytesRead < bytesToRead) {
3502             drwav_uint8 buffer[4096];
3503             size_t bytesSeeked;
3504             size_t bytesToSeek = (bytesToRead - bytesRead);
3505             if (bytesToSeek > sizeof(buffer)) {
3506                 bytesToSeek = sizeof(buffer);
3507             }
3508
3509             bytesSeeked = pWav->onRead(pWav->pUserData, buffer, bytesToSeek);
3510             bytesRead += bytesSeeked;
3511
3512             if (bytesSeeked < bytesToSeek) {
3513                 break;  /* Reached the end. */
3514             }
3515         }
3516     }
3517
3518     pWav->bytesRemaining -= bytesRead;
3519     return bytesRead;
3520 }
3521
3522
3523
3524 DRWAV_API drwav_uint64 drwav_read_pcm_frames_le(drwav* pWav, drwav_uint64 framesToRead, void* pBufferOut)
3525 {
3526     drwav_uint32 bytesPerFrame;
3527     drwav_uint64 bytesToRead;   /* Intentionally uint64 instead of size_t so we can do a check that we're not reading too much on 32-bit builds. */
3528
3529     if (pWav == NULL || framesToRead == 0) {
3530         return 0;
3531     }
3532
3533     /* Cannot use this function for compressed formats. */
3534     if (drwav__is_compressed_format_tag(pWav->translatedFormatTag)) {
3535         return 0;
3536     }
3537
3538     bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
3539     if (bytesPerFrame == 0) {
3540         return 0;
3541     }
3542
3543     /* Don't try to read more samples than can potentially fit in the output buffer. */
3544     bytesToRead = framesToRead * bytesPerFrame;
3545     if (bytesToRead > DRWAV_SIZE_MAX) {
3546         bytesToRead = (DRWAV_SIZE_MAX / bytesPerFrame) * bytesPerFrame; /* Round the number of bytes to read to a clean frame boundary. */
3547     }
3548
3549     /*
3550     Doing an explicit check here just to make it clear that we don't want to be attempt to read anything if there's no bytes to read. There
3551     *could* be a time where it evaluates to 0 due to overflowing.
3552     */
3553     if (bytesToRead == 0) {
3554         return 0;
3555     }
3556
3557     return drwav_read_raw(pWav, (size_t)bytesToRead, pBufferOut) / bytesPerFrame;
3558 }
3559
3560 DRWAV_API drwav_uint64 drwav_read_pcm_frames_be(drwav* pWav, drwav_uint64 framesToRead, void* pBufferOut)
3561 {
3562     drwav_uint64 framesRead = drwav_read_pcm_frames_le(pWav, framesToRead, pBufferOut);
3563
3564     if (pBufferOut != NULL) {
3565         drwav__bswap_samples(pBufferOut, framesRead*pWav->channels, drwav_get_bytes_per_pcm_frame(pWav)/pWav->channels, pWav->translatedFormatTag);
3566     }
3567
3568     return framesRead;
3569 }
3570
3571 DRWAV_API drwav_uint64 drwav_read_pcm_frames(drwav* pWav, drwav_uint64 framesToRead, void* pBufferOut)
3572 {
3573     if (drwav__is_little_endian()) {
3574         return drwav_read_pcm_frames_le(pWav, framesToRead, pBufferOut);
3575     } else {
3576         return drwav_read_pcm_frames_be(pWav, framesToRead, pBufferOut);
3577     }
3578 }
3579
3580
3581
3582 DRWAV_PRIVATE drwav_bool32 drwav_seek_to_first_pcm_frame(drwav* pWav)
3583 {
3584     if (pWav->onWrite != NULL) {
3585         return DRWAV_FALSE; /* No seeking in write mode. */
3586     }
3587
3588     if (!pWav->onSeek(pWav->pUserData, (int)pWav->dataChunkDataPos, drwav_seek_origin_start)) {
3589         return DRWAV_FALSE;
3590     }
3591
3592     if (drwav__is_compressed_format_tag(pWav->translatedFormatTag)) {
3593         pWav->compressed.iCurrentPCMFrame = 0;
3594
3595         /* Cached data needs to be cleared for compressed formats. */
3596         if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ADPCM) {
3597             DRWAV_ZERO_OBJECT(&pWav->msadpcm);
3598         } else if (pWav->translatedFormatTag == DR_WAVE_FORMAT_DVI_ADPCM) {
3599             DRWAV_ZERO_OBJECT(&pWav->ima);
3600         } else {
3601             DRWAV_ASSERT(DRWAV_FALSE);  /* If this assertion is triggered it means I've implemented a new compressed format but forgot to add a branch for it here. */
3602         }
3603     }
3604     
3605     pWav->bytesRemaining = pWav->dataChunkDataSize;
3606     return DRWAV_TRUE;
3607 }
3608
3609 DRWAV_API drwav_bool32 drwav_seek_to_pcm_frame(drwav* pWav, drwav_uint64 targetFrameIndex)
3610 {
3611     /* Seeking should be compatible with wave files > 2GB. */
3612
3613     if (pWav == NULL || pWav->onSeek == NULL) {
3614         return DRWAV_FALSE;
3615     }
3616
3617     /* No seeking in write mode. */
3618     if (pWav->onWrite != NULL) {
3619         return DRWAV_FALSE;
3620     }
3621
3622     /* If there are no samples, just return DRWAV_TRUE without doing anything. */
3623     if (pWav->totalPCMFrameCount == 0) {
3624         return DRWAV_TRUE;
3625     }
3626
3627     /* Make sure the sample is clamped. */
3628     if (targetFrameIndex >= pWav->totalPCMFrameCount) {
3629         targetFrameIndex  = pWav->totalPCMFrameCount - 1;
3630     }
3631
3632     /*
3633     For compressed formats we just use a slow generic seek. If we are seeking forward we just seek forward. If we are going backwards we need
3634     to seek back to the start.
3635     */
3636     if (drwav__is_compressed_format_tag(pWav->translatedFormatTag)) {
3637         /* TODO: This can be optimized. */
3638         
3639         /*
3640         If we're seeking forward it's simple - just keep reading samples until we hit the sample we're requesting. If we're seeking backwards,
3641         we first need to seek back to the start and then just do the same thing as a forward seek.
3642         */
3643         if (targetFrameIndex < pWav->compressed.iCurrentPCMFrame) {
3644             if (!drwav_seek_to_first_pcm_frame(pWav)) {
3645                 return DRWAV_FALSE;
3646             }
3647         }
3648
3649         if (targetFrameIndex > pWav->compressed.iCurrentPCMFrame) {
3650             drwav_uint64 offsetInFrames = targetFrameIndex - pWav->compressed.iCurrentPCMFrame;
3651
3652             drwav_int16 devnull[2048];
3653             while (offsetInFrames > 0) {
3654                 drwav_uint64 framesRead = 0;
3655                 drwav_uint64 framesToRead = offsetInFrames;
3656                 if (framesToRead > drwav_countof(devnull)/pWav->channels) {
3657                     framesToRead = drwav_countof(devnull)/pWav->channels;
3658                 }
3659
3660                 if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ADPCM) {
3661                     framesRead = drwav_read_pcm_frames_s16__msadpcm(pWav, framesToRead, devnull);
3662                 } else if (pWav->translatedFormatTag == DR_WAVE_FORMAT_DVI_ADPCM) {
3663                     framesRead = drwav_read_pcm_frames_s16__ima(pWav, framesToRead, devnull);
3664                 } else {
3665                     DRWAV_ASSERT(DRWAV_FALSE);  /* If this assertion is triggered it means I've implemented a new compressed format but forgot to add a branch for it here. */
3666                 }
3667
3668                 if (framesRead != framesToRead) {
3669                     return DRWAV_FALSE;
3670                 }
3671
3672                 offsetInFrames -= framesRead;
3673             }
3674         }
3675     } else {
3676         drwav_uint64 totalSizeInBytes;
3677         drwav_uint64 currentBytePos;
3678         drwav_uint64 targetBytePos;
3679         drwav_uint64 offset;
3680
3681         totalSizeInBytes = pWav->totalPCMFrameCount * drwav_get_bytes_per_pcm_frame(pWav);
3682         DRWAV_ASSERT(totalSizeInBytes >= pWav->bytesRemaining);
3683
3684         currentBytePos = totalSizeInBytes - pWav->bytesRemaining;
3685         targetBytePos  = targetFrameIndex * drwav_get_bytes_per_pcm_frame(pWav);
3686
3687         if (currentBytePos < targetBytePos) {
3688             /* Offset forwards. */
3689             offset = (targetBytePos - currentBytePos);
3690         } else {
3691             /* Offset backwards. */
3692             if (!drwav_seek_to_first_pcm_frame(pWav)) {
3693                 return DRWAV_FALSE;
3694             }
3695             offset = targetBytePos;
3696         }
3697
3698         while (offset > 0) {
3699             int offset32 = ((offset > INT_MAX) ? INT_MAX : (int)offset);
3700             if (!pWav->onSeek(pWav->pUserData, offset32, drwav_seek_origin_current)) {
3701                 return DRWAV_FALSE;
3702             }
3703
3704             pWav->bytesRemaining -= offset32;
3705             offset -= offset32;
3706         }
3707     }
3708
3709     return DRWAV_TRUE;
3710 }
3711
3712
3713 DRWAV_API size_t drwav_write_raw(drwav* pWav, size_t bytesToWrite, const void* pData)
3714 {
3715     size_t bytesWritten;
3716
3717     if (pWav == NULL || bytesToWrite == 0 || pData == NULL) {
3718         return 0;
3719     }
3720
3721     bytesWritten = pWav->onWrite(pWav->pUserData, pData, bytesToWrite);
3722     pWav->dataChunkDataSize += bytesWritten;
3723
3724     return bytesWritten;
3725 }
3726
3727
3728 DRWAV_API drwav_uint64 drwav_write_pcm_frames_le(drwav* pWav, drwav_uint64 framesToWrite, const void* pData)
3729 {
3730     drwav_uint64 bytesToWrite;
3731     drwav_uint64 bytesWritten;
3732     const drwav_uint8* pRunningData;
3733
3734     if (pWav == NULL || framesToWrite == 0 || pData == NULL) {
3735         return 0;
3736     }
3737
3738     bytesToWrite = ((framesToWrite * pWav->channels * pWav->bitsPerSample) / 8);
3739     if (bytesToWrite > DRWAV_SIZE_MAX) {
3740         return 0;
3741     }
3742
3743     bytesWritten = 0;
3744     pRunningData = (const drwav_uint8*)pData;
3745
3746     while (bytesToWrite > 0) {
3747         size_t bytesJustWritten;
3748         drwav_uint64 bytesToWriteThisIteration;
3749
3750         bytesToWriteThisIteration = bytesToWrite;
3751         DRWAV_ASSERT(bytesToWriteThisIteration <= DRWAV_SIZE_MAX);  /* <-- This is checked above. */
3752
3753         bytesJustWritten = drwav_write_raw(pWav, (size_t)bytesToWriteThisIteration, pRunningData);
3754         if (bytesJustWritten == 0) {
3755             break;
3756         }
3757
3758         bytesToWrite -= bytesJustWritten;
3759         bytesWritten += bytesJustWritten;
3760         pRunningData += bytesJustWritten;
3761     }
3762
3763     return (bytesWritten * 8) / pWav->bitsPerSample / pWav->channels;
3764 }
3765
3766 DRWAV_API drwav_uint64 drwav_write_pcm_frames_be(drwav* pWav, drwav_uint64 framesToWrite, const void* pData)
3767 {
3768     drwav_uint64 bytesToWrite;
3769     drwav_uint64 bytesWritten;
3770     drwav_uint32 bytesPerSample;
3771     const drwav_uint8* pRunningData;
3772
3773     if (pWav == NULL || framesToWrite == 0 || pData == NULL) {
3774         return 0;
3775     }
3776
3777     bytesToWrite = ((framesToWrite * pWav->channels * pWav->bitsPerSample) / 8);
3778     if (bytesToWrite > DRWAV_SIZE_MAX) {
3779         return 0;
3780     }
3781
3782     bytesWritten = 0;
3783     pRunningData = (const drwav_uint8*)pData;
3784
3785     bytesPerSample = drwav_get_bytes_per_pcm_frame(pWav) / pWav->channels;
3786     
3787     while (bytesToWrite > 0) {
3788         drwav_uint8 temp[4096];
3789         drwav_uint32 sampleCount;
3790         size_t bytesJustWritten;
3791         drwav_uint64 bytesToWriteThisIteration;
3792
3793         bytesToWriteThisIteration = bytesToWrite;
3794         DRWAV_ASSERT(bytesToWriteThisIteration <= DRWAV_SIZE_MAX);  /* <-- This is checked above. */
3795
3796         /*
3797         WAV files are always little-endian. We need to byte swap on big-endian architectures. Since our input buffer is read-only we need
3798         to use an intermediary buffer for the conversion.
3799         */
3800         sampleCount = sizeof(temp)/bytesPerSample;
3801
3802         if (bytesToWriteThisIteration > ((drwav_uint64)sampleCount)*bytesPerSample) {
3803             bytesToWriteThisIteration = ((drwav_uint64)sampleCount)*bytesPerSample;
3804         }
3805
3806         DRWAV_COPY_MEMORY(temp, pRunningData, (size_t)bytesToWriteThisIteration);
3807         drwav__bswap_samples(temp, sampleCount, bytesPerSample, pWav->translatedFormatTag);
3808
3809         bytesJustWritten = drwav_write_raw(pWav, (size_t)bytesToWriteThisIteration, temp);
3810         if (bytesJustWritten == 0) {
3811             break;
3812         }
3813
3814         bytesToWrite -= bytesJustWritten;
3815         bytesWritten += bytesJustWritten;
3816         pRunningData += bytesJustWritten;
3817     }
3818
3819     return (bytesWritten * 8) / pWav->bitsPerSample / pWav->channels;
3820 }
3821
3822 DRWAV_API drwav_uint64 drwav_write_pcm_frames(drwav* pWav, drwav_uint64 framesToWrite, const void* pData)
3823 {
3824     if (drwav__is_little_endian()) {
3825         return drwav_write_pcm_frames_le(pWav, framesToWrite, pData);
3826     } else {
3827         return drwav_write_pcm_frames_be(pWav, framesToWrite, pData);
3828     }
3829 }
3830
3831
3832 DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__msadpcm(drwav* pWav, drwav_uint64 framesToRead, drwav_int16* pBufferOut)
3833 {
3834     drwav_uint64 totalFramesRead = 0;
3835
3836     DRWAV_ASSERT(pWav != NULL);
3837     DRWAV_ASSERT(framesToRead > 0);
3838
3839     /* TODO: Lots of room for optimization here. */
3840
3841     while (pWav->compressed.iCurrentPCMFrame < pWav->totalPCMFrameCount) {
3842         DRWAV_ASSERT(framesToRead > 0); /* This loop iteration will never get hit with framesToRead == 0 because it's asserted at the top, and we check for 0 inside the loop just below. */
3843
3844         /* If there are no cached frames we need to load a new block. */
3845         if (pWav->msadpcm.cachedFrameCount == 0 && pWav->msadpcm.bytesRemainingInBlock == 0) {
3846             if (pWav->channels == 1) {
3847                 /* Mono. */
3848                 drwav_uint8 header[7];
3849                 if (pWav->onRead(pWav->pUserData, header, sizeof(header)) != sizeof(header)) {
3850                     return totalFramesRead;
3851                 }
3852                 pWav->msadpcm.bytesRemainingInBlock = pWav->fmt.blockAlign - sizeof(header);
3853
3854                 pWav->msadpcm.predictor[0]     = header[0];
3855                 pWav->msadpcm.delta[0]         = drwav_bytes_to_s16(header + 1);
3856                 pWav->msadpcm.prevFrames[0][1] = (drwav_int32)drwav_bytes_to_s16(header + 3);
3857                 pWav->msadpcm.prevFrames[0][0] = (drwav_int32)drwav_bytes_to_s16(header + 5);
3858                 pWav->msadpcm.cachedFrames[2]  = pWav->msadpcm.prevFrames[0][0];
3859                 pWav->msadpcm.cachedFrames[3]  = pWav->msadpcm.prevFrames[0][1];
3860                 pWav->msadpcm.cachedFrameCount = 2;
3861             } else {
3862                 /* Stereo. */
3863                 drwav_uint8 header[14];
3864                 if (pWav->onRead(pWav->pUserData, header, sizeof(header)) != sizeof(header)) {
3865                     return totalFramesRead;
3866                 }
3867                 pWav->msadpcm.bytesRemainingInBlock = pWav->fmt.blockAlign - sizeof(header);
3868
3869                 pWav->msadpcm.predictor[0] = header[0];
3870                 pWav->msadpcm.predictor[1] = header[1];
3871                 pWav->msadpcm.delta[0] = drwav_bytes_to_s16(header + 2);
3872                 pWav->msadpcm.delta[1] = drwav_bytes_to_s16(header + 4);
3873                 pWav->msadpcm.prevFrames[0][1] = (drwav_int32)drwav_bytes_to_s16(header + 6);
3874                 pWav->msadpcm.prevFrames[1][1] = (drwav_int32)drwav_bytes_to_s16(header + 8);
3875                 pWav->msadpcm.prevFrames[0][0] = (drwav_int32)drwav_bytes_to_s16(header + 10);
3876                 pWav->msadpcm.prevFrames[1][0] = (drwav_int32)drwav_bytes_to_s16(header + 12);
3877
3878                 pWav->msadpcm.cachedFrames[0] = pWav->msadpcm.prevFrames[0][0];
3879                 pWav->msadpcm.cachedFrames[1] = pWav->msadpcm.prevFrames[1][0];
3880                 pWav->msadpcm.cachedFrames[2] = pWav->msadpcm.prevFrames[0][1];
3881                 pWav->msadpcm.cachedFrames[3] = pWav->msadpcm.prevFrames[1][1];
3882                 pWav->msadpcm.cachedFrameCount = 2;
3883             }
3884         }
3885
3886         /* Output anything that's cached. */
3887         while (framesToRead > 0 && pWav->msadpcm.cachedFrameCount > 0 && pWav->compressed.iCurrentPCMFrame < pWav->totalPCMFrameCount) {
3888             if (pBufferOut != NULL) {
3889                 drwav_uint32 iSample = 0;
3890                 for (iSample = 0; iSample < pWav->channels; iSample += 1) {
3891                     pBufferOut[iSample] = (drwav_int16)pWav->msadpcm.cachedFrames[(drwav_countof(pWav->msadpcm.cachedFrames) - (pWav->msadpcm.cachedFrameCount*pWav->channels)) + iSample];
3892                 }
3893
3894                 pBufferOut += pWav->channels;
3895             }
3896
3897             framesToRead    -= 1;
3898             totalFramesRead += 1;
3899             pWav->compressed.iCurrentPCMFrame += 1;
3900             pWav->msadpcm.cachedFrameCount -= 1;
3901         }
3902
3903         if (framesToRead == 0) {
3904             break;
3905         }
3906
3907
3908         /*
3909         If there's nothing left in the cache, just go ahead and load more. If there's nothing left to load in the current block we just continue to the next
3910         loop iteration which will trigger the loading of a new block.
3911         */
3912         if (pWav->msadpcm.cachedFrameCount == 0) {
3913             if (pWav->msadpcm.bytesRemainingInBlock == 0) {
3914                 continue;
3915             } else {
3916                 static drwav_int32 adaptationTable[] = { 
3917                     230, 230, 230, 230, 307, 409, 512, 614, 
3918                     768, 614, 512, 409, 307, 230, 230, 230 
3919                 };
3920                 static drwav_int32 coeff1Table[] = { 256, 512, 0, 192, 240, 460,  392 };
3921                 static drwav_int32 coeff2Table[] = { 0,  -256, 0, 64,  0,  -208, -232 };
3922
3923                 drwav_uint8 nibbles;
3924                 drwav_int32 nibble0;
3925                 drwav_int32 nibble1;
3926
3927                 if (pWav->onRead(pWav->pUserData, &nibbles, 1) != 1) {
3928                     return totalFramesRead;
3929                 }
3930                 pWav->msadpcm.bytesRemainingInBlock -= 1;
3931
3932                 /* TODO: Optimize away these if statements. */
3933                 nibble0 = ((nibbles & 0xF0) >> 4); if ((nibbles & 0x80)) { nibble0 |= 0xFFFFFFF0UL; }
3934                 nibble1 = ((nibbles & 0x0F) >> 0); if ((nibbles & 0x08)) { nibble1 |= 0xFFFFFFF0UL; }
3935
3936                 if (pWav->channels == 1) {
3937                     /* Mono. */
3938                     drwav_int32 newSample0;
3939                     drwav_int32 newSample1;
3940
3941                     newSample0  = ((pWav->msadpcm.prevFrames[0][1] * coeff1Table[pWav->msadpcm.predictor[0]]) + (pWav->msadpcm.prevFrames[0][0] * coeff2Table[pWav->msadpcm.predictor[0]])) >> 8;
3942                     newSample0 += nibble0 * pWav->msadpcm.delta[0];
3943                     newSample0  = drwav_clamp(newSample0, -32768, 32767);
3944
3945                     pWav->msadpcm.delta[0] = (adaptationTable[((nibbles & 0xF0) >> 4)] * pWav->msadpcm.delta[0]) >> 8;
3946                     if (pWav->msadpcm.delta[0] < 16) {
3947                         pWav->msadpcm.delta[0] = 16;
3948                     }
3949
3950                     pWav->msadpcm.prevFrames[0][0] = pWav->msadpcm.prevFrames[0][1];
3951                     pWav->msadpcm.prevFrames[0][1] = newSample0;
3952
3953
3954                     newSample1  = ((pWav->msadpcm.prevFrames[0][1] * coeff1Table[pWav->msadpcm.predictor[0]]) + (pWav->msadpcm.prevFrames[0][0] * coeff2Table[pWav->msadpcm.predictor[0]])) >> 8;
3955                     newSample1 += nibble1 * pWav->msadpcm.delta[0];
3956                     newSample1  = drwav_clamp(newSample1, -32768, 32767);
3957
3958                     pWav->msadpcm.delta[0] = (adaptationTable[((nibbles & 0x0F) >> 0)] * pWav->msadpcm.delta[0]) >> 8;
3959                     if (pWav->msadpcm.delta[0] < 16) {
3960                         pWav->msadpcm.delta[0] = 16;
3961                     }
3962
3963                     pWav->msadpcm.prevFrames[0][0] = pWav->msadpcm.prevFrames[0][1];
3964                     pWav->msadpcm.prevFrames[0][1] = newSample1;
3965
3966
3967                     pWav->msadpcm.cachedFrames[2] = newSample0;
3968                     pWav->msadpcm.cachedFrames[3] = newSample1;
3969                     pWav->msadpcm.cachedFrameCount = 2;
3970                 } else {
3971                     /* Stereo. */
3972                     drwav_int32 newSample0;
3973                     drwav_int32 newSample1;
3974
3975                     /* Left. */
3976                     newSample0  = ((pWav->msadpcm.prevFrames[0][1] * coeff1Table[pWav->msadpcm.predictor[0]]) + (pWav->msadpcm.prevFrames[0][0] * coeff2Table[pWav->msadpcm.predictor[0]])) >> 8;
3977                     newSample0 += nibble0 * pWav->msadpcm.delta[0];
3978                     newSample0  = drwav_clamp(newSample0, -32768, 32767);
3979
3980                     pWav->msadpcm.delta[0] = (adaptationTable[((nibbles & 0xF0) >> 4)] * pWav->msadpcm.delta[0]) >> 8;
3981                     if (pWav->msadpcm.delta[0] < 16) {
3982                         pWav->msadpcm.delta[0] = 16;
3983                     }
3984
3985                     pWav->msadpcm.prevFrames[0][0] = pWav->msadpcm.prevFrames[0][1];
3986                     pWav->msadpcm.prevFrames[0][1] = newSample0;
3987
3988
3989                     /* Right. */
3990                     newSample1  = ((pWav->msadpcm.prevFrames[1][1] * coeff1Table[pWav->msadpcm.predictor[1]]) + (pWav->msadpcm.prevFrames[1][0] * coeff2Table[pWav->msadpcm.predictor[1]])) >> 8;
3991                     newSample1 += nibble1 * pWav->msadpcm.delta[1];
3992                     newSample1  = drwav_clamp(newSample1, -32768, 32767);
3993
3994                     pWav->msadpcm.delta[1] = (adaptationTable[((nibbles & 0x0F) >> 0)] * pWav->msadpcm.delta[1]) >> 8;
3995                     if (pWav->msadpcm.delta[1] < 16) {
3996                         pWav->msadpcm.delta[1] = 16;
3997                     }
3998
3999                     pWav->msadpcm.prevFrames[1][0] = pWav->msadpcm.prevFrames[1][1];
4000                     pWav->msadpcm.prevFrames[1][1] = newSample1;
4001
4002                     pWav->msadpcm.cachedFrames[2] = newSample0;
4003                     pWav->msadpcm.cachedFrames[3] = newSample1;
4004                     pWav->msadpcm.cachedFrameCount = 1;
4005                 }
4006             }
4007         }
4008     }
4009
4010     return totalFramesRead;
4011 }
4012
4013
4014 DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__ima(drwav* pWav, drwav_uint64 framesToRead, drwav_int16* pBufferOut)
4015 {
4016     drwav_uint64 totalFramesRead = 0;
4017     drwav_uint32 iChannel;
4018
4019     static drwav_int32 indexTable[16] = {
4020         -1, -1, -1, -1, 2, 4, 6, 8,
4021         -1, -1, -1, -1, 2, 4, 6, 8
4022     };
4023
4024     static drwav_int32 stepTable[89] = {
4025         7,     8,     9,     10,    11,    12,    13,    14,    16,    17, 
4026         19,    21,    23,    25,    28,    31,    34,    37,    41,    45, 
4027         50,    55,    60,    66,    73,    80,    88,    97,    107,   118, 
4028         130,   143,   157,   173,   190,   209,   230,   253,   279,   307,
4029         337,   371,   408,   449,   494,   544,   598,   658,   724,   796,
4030         876,   963,   1060,  1166,  1282,  1411,  1552,  1707,  1878,  2066, 
4031         2272,  2499,  2749,  3024,  3327,  3660,  4026,  4428,  4871,  5358,
4032         5894,  6484,  7132,  7845,  8630,  9493,  10442, 11487, 12635, 13899, 
4033         15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767 
4034     };
4035
4036     DRWAV_ASSERT(pWav != NULL);
4037     DRWAV_ASSERT(framesToRead > 0);
4038
4039     /* TODO: Lots of room for optimization here. */
4040
4041     while (pWav->compressed.iCurrentPCMFrame < pWav->totalPCMFrameCount) {
4042         DRWAV_ASSERT(framesToRead > 0); /* This loop iteration will never get hit with framesToRead == 0 because it's asserted at the top, and we check for 0 inside the loop just below. */
4043
4044         /* If there are no cached samples we need to load a new block. */
4045         if (pWav->ima.cachedFrameCount == 0 && pWav->ima.bytesRemainingInBlock == 0) {
4046             if (pWav->channels == 1) {
4047                 /* Mono. */
4048                 drwav_uint8 header[4];
4049                 if (pWav->onRead(pWav->pUserData, header, sizeof(header)) != sizeof(header)) {
4050                     return totalFramesRead;
4051                 }
4052                 pWav->ima.bytesRemainingInBlock = pWav->fmt.blockAlign - sizeof(header);
4053
4054                 if (header[2] >= drwav_countof(stepTable)) {
4055                     pWav->onSeek(pWav->pUserData, pWav->ima.bytesRemainingInBlock, drwav_seek_origin_current);
4056                     pWav->ima.bytesRemainingInBlock = 0;
4057                     return totalFramesRead; /* Invalid data. */
4058                 }
4059
4060                 pWav->ima.predictor[0] = drwav_bytes_to_s16(header + 0);
4061                 pWav->ima.stepIndex[0] = header[2];
4062                 pWav->ima.cachedFrames[drwav_countof(pWav->ima.cachedFrames) - 1] = pWav->ima.predictor[0];
4063                 pWav->ima.cachedFrameCount = 1;
4064             } else {
4065                 /* Stereo. */
4066                 drwav_uint8 header[8];
4067                 if (pWav->onRead(pWav->pUserData, header, sizeof(header)) != sizeof(header)) {
4068                     return totalFramesRead;
4069                 }
4070                 pWav->ima.bytesRemainingInBlock = pWav->fmt.blockAlign - sizeof(header);
4071
4072                 if (header[2] >= drwav_countof(stepTable) || header[6] >= drwav_countof(stepTable)) {
4073                     pWav->onSeek(pWav->pUserData, pWav->ima.bytesRemainingInBlock, drwav_seek_origin_current);
4074                     pWav->ima.bytesRemainingInBlock = 0;
4075                     return totalFramesRead; /* Invalid data. */
4076                 }
4077
4078                 pWav->ima.predictor[0] = drwav_bytes_to_s16(header + 0);
4079                 pWav->ima.stepIndex[0] = header[2];
4080                 pWav->ima.predictor[1] = drwav_bytes_to_s16(header + 4);
4081                 pWav->ima.stepIndex[1] = header[6];
4082
4083                 pWav->ima.cachedFrames[drwav_countof(pWav->ima.cachedFrames) - 2] = pWav->ima.predictor[0];
4084                 pWav->ima.cachedFrames[drwav_countof(pWav->ima.cachedFrames) - 1] = pWav->ima.predictor[1];
4085                 pWav->ima.cachedFrameCount = 1;
4086             }
4087         }
4088
4089         /* Output anything that's cached. */
4090         while (framesToRead > 0 && pWav->ima.cachedFrameCount > 0 && pWav->compressed.iCurrentPCMFrame < pWav->totalPCMFrameCount) {
4091             if (pBufferOut != NULL) {
4092                 drwav_uint32 iSample;
4093                 for (iSample = 0; iSample < pWav->channels; iSample += 1) {
4094                     pBufferOut[iSample] = (drwav_int16)pWav->ima.cachedFrames[(drwav_countof(pWav->ima.cachedFrames) - (pWav->ima.cachedFrameCount*pWav->channels)) + iSample];
4095                 }
4096                 pBufferOut += pWav->channels;
4097             }
4098
4099             framesToRead    -= 1;
4100             totalFramesRead += 1;
4101             pWav->compressed.iCurrentPCMFrame += 1;
4102             pWav->ima.cachedFrameCount -= 1;
4103         }
4104
4105         if (framesToRead == 0) {
4106             break;
4107         }
4108
4109         /*
4110         If there's nothing left in the cache, just go ahead and load more. If there's nothing left to load in the current block we just continue to the next
4111         loop iteration which will trigger the loading of a new block.
4112         */
4113         if (pWav->ima.cachedFrameCount == 0) {
4114             if (pWav->ima.bytesRemainingInBlock == 0) {
4115                 continue;
4116             } else {
4117                 /*
4118                 From what I can tell with stereo streams, it looks like every 4 bytes (8 samples) is for one channel. So it goes 4 bytes for the
4119                 left channel, 4 bytes for the right channel.
4120                 */
4121                 pWav->ima.cachedFrameCount = 8;
4122                 for (iChannel = 0; iChannel < pWav->channels; ++iChannel) {
4123                     drwav_uint32 iByte;
4124                     drwav_uint8 nibbles[4];
4125                     if (pWav->onRead(pWav->pUserData, &nibbles, 4) != 4) {
4126                         pWav->ima.cachedFrameCount = 0;
4127                         return totalFramesRead;
4128                     }
4129                     pWav->ima.bytesRemainingInBlock -= 4;
4130
4131                     for (iByte = 0; iByte < 4; ++iByte) {
4132                         drwav_uint8 nibble0 = ((nibbles[iByte] & 0x0F) >> 0);
4133                         drwav_uint8 nibble1 = ((nibbles[iByte] & 0xF0) >> 4);
4134
4135                         drwav_int32 step      = stepTable[pWav->ima.stepIndex[iChannel]];
4136                         drwav_int32 predictor = pWav->ima.predictor[iChannel];
4137
4138                         drwav_int32      diff  = step >> 3;
4139                         if (nibble0 & 1) diff += step >> 2;
4140                         if (nibble0 & 2) diff += step >> 1;
4141                         if (nibble0 & 4) diff += step;
4142                         if (nibble0 & 8) diff  = -diff;
4143
4144                         predictor = drwav_clamp(predictor + diff, -32768, 32767);
4145                         pWav->ima.predictor[iChannel] = predictor;
4146                         pWav->ima.stepIndex[iChannel] = drwav_clamp(pWav->ima.stepIndex[iChannel] + indexTable[nibble0], 0, (drwav_int32)drwav_countof(stepTable)-1);
4147                         pWav->ima.cachedFrames[(drwav_countof(pWav->ima.cachedFrames) - (pWav->ima.cachedFrameCount*pWav->channels)) + (iByte*2+0)*pWav->channels + iChannel] = predictor;
4148
4149
4150                         step      = stepTable[pWav->ima.stepIndex[iChannel]];
4151                         predictor = pWav->ima.predictor[iChannel];
4152
4153                                          diff  = step >> 3;
4154                         if (nibble1 & 1) diff += step >> 2;
4155                         if (nibble1 & 2) diff += step >> 1;
4156                         if (nibble1 & 4) diff += step;
4157                         if (nibble1 & 8) diff  = -diff;
4158
4159                         predictor = drwav_clamp(predictor + diff, -32768, 32767);
4160                         pWav->ima.predictor[iChannel] = predictor;
4161                         pWav->ima.stepIndex[iChannel] = drwav_clamp(pWav->ima.stepIndex[iChannel] + indexTable[nibble1], 0, (drwav_int32)drwav_countof(stepTable)-1);
4162                         pWav->ima.cachedFrames[(drwav_countof(pWav->ima.cachedFrames) - (pWav->ima.cachedFrameCount*pWav->channels)) + (iByte*2+1)*pWav->channels + iChannel] = predictor;
4163                     }
4164                 }
4165             }
4166         }
4167     }
4168
4169     return totalFramesRead;
4170 }
4171
4172
4173 #ifndef DR_WAV_NO_CONVERSION_API
4174 static unsigned short g_drwavAlawTable[256] = {
4175     0xEA80, 0xEB80, 0xE880, 0xE980, 0xEE80, 0xEF80, 0xEC80, 0xED80, 0xE280, 0xE380, 0xE080, 0xE180, 0xE680, 0xE780, 0xE480, 0xE580, 
4176     0xF540, 0xF5C0, 0xF440, 0xF4C0, 0xF740, 0xF7C0, 0xF640, 0xF6C0, 0xF140, 0xF1C0, 0xF040, 0xF0C0, 0xF340, 0xF3C0, 0xF240, 0xF2C0, 
4177     0xAA00, 0xAE00, 0xA200, 0xA600, 0xBA00, 0xBE00, 0xB200, 0xB600, 0x8A00, 0x8E00, 0x8200, 0x8600, 0x9A00, 0x9E00, 0x9200, 0x9600, 
4178     0xD500, 0xD700, 0xD100, 0xD300, 0xDD00, 0xDF00, 0xD900, 0xDB00, 0xC500, 0xC700, 0xC100, 0xC300, 0xCD00, 0xCF00, 0xC900, 0xCB00, 
4179     0xFEA8, 0xFEB8, 0xFE88, 0xFE98, 0xFEE8, 0xFEF8, 0xFEC8, 0xFED8, 0xFE28, 0xFE38, 0xFE08, 0xFE18, 0xFE68, 0xFE78, 0xFE48, 0xFE58, 
4180     0xFFA8, 0xFFB8, 0xFF88, 0xFF98, 0xFFE8, 0xFFF8, 0xFFC8, 0xFFD8, 0xFF28, 0xFF38, 0xFF08, 0xFF18, 0xFF68, 0xFF78, 0xFF48, 0xFF58, 
4181     0xFAA0, 0xFAE0, 0xFA20, 0xFA60, 0xFBA0, 0xFBE0, 0xFB20, 0xFB60, 0xF8A0, 0xF8E0, 0xF820, 0xF860, 0xF9A0, 0xF9E0, 0xF920, 0xF960, 
4182     0xFD50, 0xFD70, 0xFD10, 0xFD30, 0xFDD0, 0xFDF0, 0xFD90, 0xFDB0, 0xFC50, 0xFC70, 0xFC10, 0xFC30, 0xFCD0, 0xFCF0, 0xFC90, 0xFCB0, 
4183     0x1580, 0x1480, 0x1780, 0x1680, 0x1180, 0x1080, 0x1380, 0x1280, 0x1D80, 0x1C80, 0x1F80, 0x1E80, 0x1980, 0x1880, 0x1B80, 0x1A80, 
4184     0x0AC0, 0x0A40, 0x0BC0, 0x0B40, 0x08C0, 0x0840, 0x09C0, 0x0940, 0x0EC0, 0x0E40, 0x0FC0, 0x0F40, 0x0CC0, 0x0C40, 0x0DC0, 0x0D40, 
4185     0x5600, 0x5200, 0x5E00, 0x5A00, 0x4600, 0x4200, 0x4E00, 0x4A00, 0x7600, 0x7200, 0x7E00, 0x7A00, 0x6600, 0x6200, 0x6E00, 0x6A00, 
4186     0x2B00, 0x2900, 0x2F00, 0x2D00, 0x2300, 0x2100, 0x2700, 0x2500, 0x3B00, 0x3900, 0x3F00, 0x3D00, 0x3300, 0x3100, 0x3700, 0x3500, 
4187     0x0158, 0x0148, 0x0178, 0x0168, 0x0118, 0x0108, 0x0138, 0x0128, 0x01D8, 0x01C8, 0x01F8, 0x01E8, 0x0198, 0x0188, 0x01B8, 0x01A8, 
4188     0x0058, 0x0048, 0x0078, 0x0068, 0x0018, 0x0008, 0x0038, 0x0028, 0x00D8, 0x00C8, 0x00F8, 0x00E8, 0x0098, 0x0088, 0x00B8, 0x00A8, 
4189     0x0560, 0x0520, 0x05E0, 0x05A0, 0x0460, 0x0420, 0x04E0, 0x04A0, 0x0760, 0x0720, 0x07E0, 0x07A0, 0x0660, 0x0620, 0x06E0, 0x06A0, 
4190     0x02B0, 0x0290, 0x02F0, 0x02D0, 0x0230, 0x0210, 0x0270, 0x0250, 0x03B0, 0x0390, 0x03F0, 0x03D0, 0x0330, 0x0310, 0x0370, 0x0350
4191 };
4192
4193 static unsigned short g_drwavMulawTable[256] = {
4194     0x8284, 0x8684, 0x8A84, 0x8E84, 0x9284, 0x9684, 0x9A84, 0x9E84, 0xA284, 0xA684, 0xAA84, 0xAE84, 0xB284, 0xB684, 0xBA84, 0xBE84, 
4195     0xC184, 0xC384, 0xC584, 0xC784, 0xC984, 0xCB84, 0xCD84, 0xCF84, 0xD184, 0xD384, 0xD584, 0xD784, 0xD984, 0xDB84, 0xDD84, 0xDF84, 
4196     0xE104, 0xE204, 0xE304, 0xE404, 0xE504, 0xE604, 0xE704, 0xE804, 0xE904, 0xEA04, 0xEB04, 0xEC04, 0xED04, 0xEE04, 0xEF04, 0xF004, 
4197     0xF0C4, 0xF144, 0xF1C4, 0xF244, 0xF2C4, 0xF344, 0xF3C4, 0xF444, 0xF4C4, 0xF544, 0xF5C4, 0xF644, 0xF6C4, 0xF744, 0xF7C4, 0xF844, 
4198     0xF8A4, 0xF8E4, 0xF924, 0xF964, 0xF9A4, 0xF9E4, 0xFA24, 0xFA64, 0xFAA4, 0xFAE4, 0xFB24, 0xFB64, 0xFBA4, 0xFBE4, 0xFC24, 0xFC64, 
4199     0xFC94, 0xFCB4, 0xFCD4, 0xFCF4, 0xFD14, 0xFD34, 0xFD54, 0xFD74, 0xFD94, 0xFDB4, 0xFDD4, 0xFDF4, 0xFE14, 0xFE34, 0xFE54, 0xFE74, 
4200     0xFE8C, 0xFE9C, 0xFEAC, 0xFEBC, 0xFECC, 0xFEDC, 0xFEEC, 0xFEFC, 0xFF0C, 0xFF1C, 0xFF2C, 0xFF3C, 0xFF4C, 0xFF5C, 0xFF6C, 0xFF7C, 
4201     0xFF88, 0xFF90, 0xFF98, 0xFFA0, 0xFFA8, 0xFFB0, 0xFFB8, 0xFFC0, 0xFFC8, 0xFFD0, 0xFFD8, 0xFFE0, 0xFFE8, 0xFFF0, 0xFFF8, 0x0000, 
4202     0x7D7C, 0x797C, 0x757C, 0x717C, 0x6D7C, 0x697C, 0x657C, 0x617C, 0x5D7C, 0x597C, 0x557C, 0x517C, 0x4D7C, 0x497C, 0x457C, 0x417C, 
4203     0x3E7C, 0x3C7C, 0x3A7C, 0x387C, 0x367C, 0x347C, 0x327C, 0x307C, 0x2E7C, 0x2C7C, 0x2A7C, 0x287C, 0x267C, 0x247C, 0x227C, 0x207C, 
4204     0x1EFC, 0x1DFC, 0x1CFC, 0x1BFC, 0x1AFC, 0x19FC, 0x18FC, 0x17FC, 0x16FC, 0x15FC, 0x14FC, 0x13FC, 0x12FC, 0x11FC, 0x10FC, 0x0FFC, 
4205     0x0F3C, 0x0EBC, 0x0E3C, 0x0DBC, 0x0D3C, 0x0CBC, 0x0C3C, 0x0BBC, 0x0B3C, 0x0ABC, 0x0A3C, 0x09BC, 0x093C, 0x08BC, 0x083C, 0x07BC, 
4206     0x075C, 0x071C, 0x06DC, 0x069C, 0x065C, 0x061C, 0x05DC, 0x059C, 0x055C, 0x051C, 0x04DC, 0x049C, 0x045C, 0x041C, 0x03DC, 0x039C, 
4207     0x036C, 0x034C, 0x032C, 0x030C, 0x02EC, 0x02CC, 0x02AC, 0x028C, 0x026C, 0x024C, 0x022C, 0x020C, 0x01EC, 0x01CC, 0x01AC, 0x018C, 
4208     0x0174, 0x0164, 0x0154, 0x0144, 0x0134, 0x0124, 0x0114, 0x0104, 0x00F4, 0x00E4, 0x00D4, 0x00C4, 0x00B4, 0x00A4, 0x0094, 0x0084, 
4209     0x0078, 0x0070, 0x0068, 0x0060, 0x0058, 0x0050, 0x0048, 0x0040, 0x0038, 0x0030, 0x0028, 0x0020, 0x0018, 0x0010, 0x0008, 0x0000
4210 };
4211
4212 static DRWAV_INLINE drwav_int16 drwav__alaw_to_s16(drwav_uint8 sampleIn)
4213 {
4214     return (short)g_drwavAlawTable[sampleIn];
4215 }
4216
4217 static DRWAV_INLINE drwav_int16 drwav__mulaw_to_s16(drwav_uint8 sampleIn)
4218 {
4219     return (short)g_drwavMulawTable[sampleIn];
4220 }
4221
4222
4223
4224 DRWAV_PRIVATE void drwav__pcm_to_s16(drwav_int16* pOut, const drwav_uint8* pIn, size_t totalSampleCount, unsigned int bytesPerSample)
4225 {
4226     unsigned int i;
4227
4228     /* Special case for 8-bit sample data because it's treated as unsigned. */
4229     if (bytesPerSample == 1) {
4230         drwav_u8_to_s16(pOut, pIn, totalSampleCount);
4231         return;
4232     }
4233
4234
4235     /* Slightly more optimal implementation for common formats. */
4236     if (bytesPerSample == 2) {
4237         for (i = 0; i < totalSampleCount; ++i) {
4238            *pOut++ = ((const drwav_int16*)pIn)[i];
4239         }
4240         return;
4241     }
4242     if (bytesPerSample == 3) {
4243         drwav_s24_to_s16(pOut, pIn, totalSampleCount);
4244         return;
4245     }
4246     if (bytesPerSample == 4) {
4247         drwav_s32_to_s16(pOut, (const drwav_int32*)pIn, totalSampleCount);
4248         return;
4249     }
4250
4251
4252     /* Anything more than 64 bits per sample is not supported. */
4253     if (bytesPerSample > 8) {
4254         DRWAV_ZERO_MEMORY(pOut, totalSampleCount * sizeof(*pOut));
4255         return;
4256     }
4257
4258
4259     /* Generic, slow converter. */
4260     for (i = 0; i < totalSampleCount; ++i) {
4261         drwav_uint64 sample = 0;
4262         unsigned int shift  = (8 - bytesPerSample) * 8;
4263
4264         unsigned int j;
4265         for (j = 0; j < bytesPerSample; j += 1) {
4266             DRWAV_ASSERT(j < 8);
4267             sample |= (drwav_uint64)(pIn[j]) << shift;
4268             shift  += 8;
4269         }
4270
4271         pIn += j;
4272         *pOut++ = (drwav_int16)((drwav_int64)sample >> 48);
4273     }
4274 }
4275
4276 DRWAV_PRIVATE void drwav__ieee_to_s16(drwav_int16* pOut, const drwav_uint8* pIn, size_t totalSampleCount, unsigned int bytesPerSample)
4277 {
4278     if (bytesPerSample == 4) {
4279         drwav_f32_to_s16(pOut, (const float*)pIn, totalSampleCount);
4280         return;
4281     } else if (bytesPerSample == 8) {
4282         drwav_f64_to_s16(pOut, (const double*)pIn, totalSampleCount);
4283         return;
4284     } else {
4285         /* Only supporting 32- and 64-bit float. Output silence in all other cases. Contributions welcome for 16-bit float. */
4286         DRWAV_ZERO_MEMORY(pOut, totalSampleCount * sizeof(*pOut));
4287         return;
4288     }
4289 }
4290
4291 DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__pcm(drwav* pWav, drwav_uint64 framesToRead, drwav_int16* pBufferOut)
4292 {
4293     drwav_uint64 totalFramesRead;
4294     drwav_uint8 sampleData[4096];
4295     drwav_uint32 bytesPerFrame;
4296
4297     /* Fast path. */
4298     if ((pWav->translatedFormatTag == DR_WAVE_FORMAT_PCM && pWav->bitsPerSample == 16) || pBufferOut == NULL) {
4299         return drwav_read_pcm_frames(pWav, framesToRead, pBufferOut);
4300     }
4301     
4302     bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
4303     if (bytesPerFrame == 0) {
4304         return 0;
4305     }
4306
4307     totalFramesRead = 0;
4308     
4309     while (framesToRead > 0) {
4310         drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame), sampleData);
4311         if (framesRead == 0) {
4312             break;
4313         }
4314
4315         drwav__pcm_to_s16(pBufferOut, sampleData, (size_t)(framesRead*pWav->channels), bytesPerFrame/pWav->channels);
4316
4317         pBufferOut      += framesRead*pWav->channels;
4318         framesToRead    -= framesRead;
4319         totalFramesRead += framesRead;
4320     }
4321
4322     return totalFramesRead;
4323 }
4324
4325 DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__ieee(drwav* pWav, drwav_uint64 framesToRead, drwav_int16* pBufferOut)
4326 {
4327     drwav_uint64 totalFramesRead;
4328     drwav_uint8 sampleData[4096];
4329     drwav_uint32 bytesPerFrame;
4330
4331     if (pBufferOut == NULL) {
4332         return drwav_read_pcm_frames(pWav, framesToRead, NULL);
4333     }
4334
4335     bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
4336     if (bytesPerFrame == 0) {
4337         return 0;
4338     }
4339
4340     totalFramesRead = 0;
4341     
4342     while (framesToRead > 0) {
4343         drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame), sampleData);
4344         if (framesRead == 0) {
4345             break;
4346         }
4347
4348         drwav__ieee_to_s16(pBufferOut, sampleData, (size_t)(framesRead*pWav->channels), bytesPerFrame/pWav->channels);
4349
4350         pBufferOut      += framesRead*pWav->channels;
4351         framesToRead    -= framesRead;
4352         totalFramesRead += framesRead;
4353     }
4354
4355     return totalFramesRead;
4356 }
4357
4358 DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__alaw(drwav* pWav, drwav_uint64 framesToRead, drwav_int16* pBufferOut)
4359 {
4360     drwav_uint64 totalFramesRead;
4361     drwav_uint8 sampleData[4096];
4362     drwav_uint32 bytesPerFrame;
4363
4364     if (pBufferOut == NULL) {
4365         return drwav_read_pcm_frames(pWav, framesToRead, NULL);
4366     }
4367
4368     bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
4369     if (bytesPerFrame == 0) {
4370         return 0;
4371     }
4372
4373     totalFramesRead = 0;
4374     
4375     while (framesToRead > 0) {
4376         drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame), sampleData);
4377         if (framesRead == 0) {
4378             break;
4379         }
4380
4381         drwav_alaw_to_s16(pBufferOut, sampleData, (size_t)(framesRead*pWav->channels));
4382
4383         pBufferOut      += framesRead*pWav->channels;
4384         framesToRead    -= framesRead;
4385         totalFramesRead += framesRead;
4386     }
4387
4388     return totalFramesRead;
4389 }
4390
4391 DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__mulaw(drwav* pWav, drwav_uint64 framesToRead, drwav_int16* pBufferOut)
4392 {
4393     drwav_uint64 totalFramesRead;
4394     drwav_uint8 sampleData[4096];
4395     drwav_uint32 bytesPerFrame;
4396
4397     if (pBufferOut == NULL) {
4398         return drwav_read_pcm_frames(pWav, framesToRead, NULL);
4399     }
4400
4401     bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
4402     if (bytesPerFrame == 0) {
4403         return 0;
4404     }
4405
4406     totalFramesRead = 0;
4407
4408     while (framesToRead > 0) {
4409         drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame), sampleData);
4410         if (framesRead == 0) {
4411             break;
4412         }
4413
4414         drwav_mulaw_to_s16(pBufferOut, sampleData, (size_t)(framesRead*pWav->channels));
4415
4416         pBufferOut      += framesRead*pWav->channels;
4417         framesToRead    -= framesRead;
4418         totalFramesRead += framesRead;
4419     }
4420
4421     return totalFramesRead;
4422 }
4423
4424 DRWAV_API drwav_uint64 drwav_read_pcm_frames_s16(drwav* pWav, drwav_uint64 framesToRead, drwav_int16* pBufferOut)
4425 {
4426     if (pWav == NULL || framesToRead == 0) {
4427         return 0;
4428     }
4429
4430     if (pBufferOut == NULL) {
4431         return drwav_read_pcm_frames(pWav, framesToRead, NULL);
4432     }
4433
4434     /* Don't try to read more samples than can potentially fit in the output buffer. */
4435     if (framesToRead * pWav->channels * sizeof(drwav_int16) > DRWAV_SIZE_MAX) {
4436         framesToRead = DRWAV_SIZE_MAX / sizeof(drwav_int16) / pWav->channels;
4437     }
4438
4439     if (pWav->translatedFormatTag == DR_WAVE_FORMAT_PCM) {
4440         return drwav_read_pcm_frames_s16__pcm(pWav, framesToRead, pBufferOut);
4441     }
4442
4443     if (pWav->translatedFormatTag == DR_WAVE_FORMAT_IEEE_FLOAT) {
4444         return drwav_read_pcm_frames_s16__ieee(pWav, framesToRead, pBufferOut);
4445     }
4446
4447     if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ALAW) {
4448         return drwav_read_pcm_frames_s16__alaw(pWav, framesToRead, pBufferOut);
4449     }
4450
4451     if (pWav->translatedFormatTag == DR_WAVE_FORMAT_MULAW) {
4452         return drwav_read_pcm_frames_s16__mulaw(pWav, framesToRead, pBufferOut);
4453     }
4454
4455     if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ADPCM) {
4456         return drwav_read_pcm_frames_s16__msadpcm(pWav, framesToRead, pBufferOut);
4457     }
4458
4459     if (pWav->translatedFormatTag == DR_WAVE_FORMAT_DVI_ADPCM) {
4460         return drwav_read_pcm_frames_s16__ima(pWav, framesToRead, pBufferOut);
4461     }
4462
4463     return 0;
4464 }
4465
4466 DRWAV_API drwav_uint64 drwav_read_pcm_frames_s16le(drwav* pWav, drwav_uint64 framesToRead, drwav_int16* pBufferOut)
4467 {
4468     drwav_uint64 framesRead = drwav_read_pcm_frames_s16(pWav, framesToRead, pBufferOut);
4469     if (pBufferOut != NULL && drwav__is_little_endian() == DRWAV_FALSE) {
4470         drwav__bswap_samples_s16(pBufferOut, framesRead*pWav->channels);
4471     }
4472
4473     return framesRead;
4474 }
4475
4476 DRWAV_API drwav_uint64 drwav_read_pcm_frames_s16be(drwav* pWav, drwav_uint64 framesToRead, drwav_int16* pBufferOut)
4477 {
4478     drwav_uint64 framesRead = drwav_read_pcm_frames_s16(pWav, framesToRead, pBufferOut);
4479     if (pBufferOut != NULL && drwav__is_little_endian() == DRWAV_TRUE) {
4480         drwav__bswap_samples_s16(pBufferOut, framesRead*pWav->channels);
4481     }
4482
4483     return framesRead;
4484 }
4485
4486
4487 DRWAV_API void drwav_u8_to_s16(drwav_int16* pOut, const drwav_uint8* pIn, size_t sampleCount)
4488 {
4489     int r;
4490     size_t i;
4491     for (i = 0; i < sampleCount; ++i) {
4492         int x = pIn[i];
4493         r = x << 8;
4494         r = r - 32768;
4495         pOut[i] = (short)r;
4496     }
4497 }
4498
4499 DRWAV_API void drwav_s24_to_s16(drwav_int16* pOut, const drwav_uint8* pIn, size_t sampleCount)
4500 {
4501     int r;
4502     size_t i;
4503     for (i = 0; i < sampleCount; ++i) {
4504         int x = ((int)(((unsigned int)(((const drwav_uint8*)pIn)[i*3+0]) << 8) | ((unsigned int)(((const drwav_uint8*)pIn)[i*3+1]) << 16) | ((unsigned int)(((const drwav_uint8*)pIn)[i*3+2])) << 24)) >> 8;
4505         r = x >> 8;
4506         pOut[i] = (short)r;
4507     }
4508 }
4509
4510 DRWAV_API void drwav_s32_to_s16(drwav_int16* pOut, const drwav_int32* pIn, size_t sampleCount)
4511 {
4512     int r;
4513     size_t i;
4514     for (i = 0; i < sampleCount; ++i) {
4515         int x = pIn[i];
4516         r = x >> 16;
4517         pOut[i] = (short)r;
4518     }
4519 }
4520
4521 DRWAV_API void drwav_f32_to_s16(drwav_int16* pOut, const float* pIn, size_t sampleCount)
4522 {
4523     int r;
4524     size_t i;
4525     for (i = 0; i < sampleCount; ++i) {
4526         float x = pIn[i];
4527         float c;
4528         c = ((x < -1) ? -1 : ((x > 1) ? 1 : x));
4529         c = c + 1;
4530         r = (int)(c * 32767.5f);
4531         r = r - 32768;
4532         pOut[i] = (short)r;
4533     }
4534 }
4535
4536 DRWAV_API void drwav_f64_to_s16(drwav_int16* pOut, const double* pIn, size_t sampleCount)
4537 {
4538     int r;
4539     size_t i;
4540     for (i = 0; i < sampleCount; ++i) {
4541         double x = pIn[i];
4542         double c;
4543         c = ((x < -1) ? -1 : ((x > 1) ? 1 : x));
4544         c = c + 1;
4545         r = (int)(c * 32767.5);
4546         r = r - 32768;
4547         pOut[i] = (short)r;
4548     }
4549 }
4550
4551 DRWAV_API void drwav_alaw_to_s16(drwav_int16* pOut, const drwav_uint8* pIn, size_t sampleCount)
4552 {
4553     size_t i;
4554     for (i = 0; i < sampleCount; ++i) {
4555         pOut[i] = drwav__alaw_to_s16(pIn[i]);
4556     }
4557 }
4558
4559 DRWAV_API void drwav_mulaw_to_s16(drwav_int16* pOut, const drwav_uint8* pIn, size_t sampleCount)
4560 {
4561     size_t i;
4562     for (i = 0; i < sampleCount; ++i) {
4563         pOut[i] = drwav__mulaw_to_s16(pIn[i]);
4564     }
4565 }
4566
4567
4568
4569 DRWAV_PRIVATE void drwav__pcm_to_f32(float* pOut, const drwav_uint8* pIn, size_t sampleCount, unsigned int bytesPerSample)
4570 {
4571     unsigned int i;
4572
4573     /* Special case for 8-bit sample data because it's treated as unsigned. */
4574     if (bytesPerSample == 1) {
4575         drwav_u8_to_f32(pOut, pIn, sampleCount);
4576         return;
4577     }
4578
4579     /* Slightly more optimal implementation for common formats. */
4580     if (bytesPerSample == 2) {
4581         drwav_s16_to_f32(pOut, (const drwav_int16*)pIn, sampleCount);
4582         return;
4583     }
4584     if (bytesPerSample == 3) {
4585         drwav_s24_to_f32(pOut, pIn, sampleCount);
4586         return;
4587     }
4588     if (bytesPerSample == 4) {
4589         drwav_s32_to_f32(pOut, (const drwav_int32*)pIn, sampleCount);
4590         return;
4591     }
4592
4593
4594     /* Anything more than 64 bits per sample is not supported. */
4595     if (bytesPerSample > 8) {
4596         DRWAV_ZERO_MEMORY(pOut, sampleCount * sizeof(*pOut));
4597         return;
4598     }
4599
4600
4601     /* Generic, slow converter. */
4602     for (i = 0; i < sampleCount; ++i) {
4603         drwav_uint64 sample = 0;
4604         unsigned int shift  = (8 - bytesPerSample) * 8;
4605
4606         unsigned int j;
4607         for (j = 0; j < bytesPerSample; j += 1) {
4608             DRWAV_ASSERT(j < 8);
4609             sample |= (drwav_uint64)(pIn[j]) << shift;
4610             shift  += 8;
4611         }
4612
4613         pIn += j;
4614         *pOut++ = (float)((drwav_int64)sample / 9223372036854775807.0);
4615     }
4616 }
4617
4618 DRWAV_PRIVATE void drwav__ieee_to_f32(float* pOut, const drwav_uint8* pIn, size_t sampleCount, unsigned int bytesPerSample)
4619 {
4620     if (bytesPerSample == 4) {
4621         unsigned int i;
4622         for (i = 0; i < sampleCount; ++i) {
4623             *pOut++ = ((const float*)pIn)[i];
4624         }
4625         return;
4626     } else if (bytesPerSample == 8) {
4627         drwav_f64_to_f32(pOut, (const double*)pIn, sampleCount);
4628         return;
4629     } else {
4630         /* Only supporting 32- and 64-bit float. Output silence in all other cases. Contributions welcome for 16-bit float. */
4631         DRWAV_ZERO_MEMORY(pOut, sampleCount * sizeof(*pOut));
4632         return;
4633     }
4634 }
4635
4636
4637 DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_f32__pcm(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut)
4638 {
4639     drwav_uint64 totalFramesRead;
4640     drwav_uint8 sampleData[4096];
4641     drwav_uint32 bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
4642
4643     if (bytesPerFrame == 0) {
4644         return 0;
4645     }
4646
4647     totalFramesRead = 0;
4648
4649     while (framesToRead > 0) {
4650         drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame), sampleData);
4651         if (framesRead == 0) {
4652             break;
4653         }
4654
4655         drwav__pcm_to_f32(pBufferOut, sampleData, (size_t)framesRead*pWav->channels, bytesPerFrame/pWav->channels);
4656
4657         pBufferOut      += framesRead*pWav->channels;
4658         framesToRead    -= framesRead;
4659         totalFramesRead += framesRead;
4660     }
4661
4662     return totalFramesRead;
4663 }
4664
4665 DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_f32__msadpcm(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut)
4666 {
4667     /*
4668     We're just going to borrow the implementation from the drwav_read_s16() since ADPCM is a little bit more complicated than other formats and I don't
4669     want to duplicate that code.
4670     */
4671     drwav_uint64 totalFramesRead = 0;
4672     drwav_int16 samples16[2048];
4673
4674     while (framesToRead > 0) {
4675         drwav_uint64 framesRead = drwav_read_pcm_frames_s16(pWav, drwav_min(framesToRead, drwav_countof(samples16)/pWav->channels), samples16);
4676         if (framesRead == 0) {
4677             break;
4678         }
4679
4680         drwav_s16_to_f32(pBufferOut, samples16, (size_t)(framesRead*pWav->channels));   /* <-- Safe cast because we're clamping to 2048. */
4681
4682         pBufferOut      += framesRead*pWav->channels;
4683         framesToRead    -= framesRead;
4684         totalFramesRead += framesRead;
4685     }
4686
4687     return totalFramesRead;
4688 }
4689
4690 DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_f32__ima(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut)
4691 {
4692     /*
4693     We're just going to borrow the implementation from the drwav_read_s16() since IMA-ADPCM is a little bit more complicated than other formats and I don't
4694     want to duplicate that code.
4695     */
4696     drwav_uint64 totalFramesRead = 0;
4697     drwav_int16 samples16[2048];
4698
4699     while (framesToRead > 0) {
4700         drwav_uint64 framesRead = drwav_read_pcm_frames_s16(pWav, drwav_min(framesToRead, drwav_countof(samples16)/pWav->channels), samples16);
4701         if (framesRead == 0) {
4702             break;
4703         }
4704
4705         drwav_s16_to_f32(pBufferOut, samples16, (size_t)(framesRead*pWav->channels));   /* <-- Safe cast because we're clamping to 2048. */
4706
4707         pBufferOut      += framesRead*pWav->channels;
4708         framesToRead    -= framesRead;
4709         totalFramesRead += framesRead;
4710     }
4711
4712     return totalFramesRead;
4713 }
4714
4715 DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_f32__ieee(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut)
4716 {
4717     drwav_uint64 totalFramesRead;
4718     drwav_uint8 sampleData[4096];
4719     drwav_uint32 bytesPerFrame;
4720
4721     /* Fast path. */
4722     if (pWav->translatedFormatTag == DR_WAVE_FORMAT_IEEE_FLOAT && pWav->bitsPerSample == 32) {
4723         return drwav_read_pcm_frames(pWav, framesToRead, pBufferOut);
4724     }
4725     
4726     bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
4727     if (bytesPerFrame == 0) {
4728         return 0;
4729     }
4730
4731     totalFramesRead = 0;
4732
4733     while (framesToRead > 0) {
4734         drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame), sampleData);
4735         if (framesRead == 0) {
4736             break;
4737         }
4738
4739         drwav__ieee_to_f32(pBufferOut, sampleData, (size_t)(framesRead*pWav->channels), bytesPerFrame/pWav->channels);
4740
4741         pBufferOut      += framesRead*pWav->channels;
4742         framesToRead    -= framesRead;
4743         totalFramesRead += framesRead;
4744     }
4745
4746     return totalFramesRead;
4747 }
4748
4749 DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_f32__alaw(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut)
4750 {
4751     drwav_uint64 totalFramesRead;
4752     drwav_uint8 sampleData[4096];
4753     drwav_uint32 bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
4754
4755     if (bytesPerFrame == 0) {
4756         return 0;
4757     }
4758
4759     totalFramesRead = 0;
4760
4761     while (framesToRead > 0) {
4762         drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame), sampleData);
4763         if (framesRead == 0) {
4764             break;
4765         }
4766
4767         drwav_alaw_to_f32(pBufferOut, sampleData, (size_t)(framesRead*pWav->channels));
4768
4769         pBufferOut      += framesRead*pWav->channels;
4770         framesToRead    -= framesRead;
4771         totalFramesRead += framesRead;
4772     }
4773
4774     return totalFramesRead;
4775 }
4776
4777 DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_f32__mulaw(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut)
4778 {
4779     drwav_uint64 totalFramesRead;
4780     drwav_uint8 sampleData[4096];
4781     drwav_uint32 bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
4782
4783     if (bytesPerFrame == 0) {
4784         return 0;
4785     }
4786
4787     totalFramesRead = 0;
4788
4789     while (framesToRead > 0) {
4790         drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame), sampleData);
4791         if (framesRead == 0) {
4792             break;
4793         }
4794
4795         drwav_mulaw_to_f32(pBufferOut, sampleData, (size_t)(framesRead*pWav->channels));
4796
4797         pBufferOut      += framesRead*pWav->channels;
4798         framesToRead    -= framesRead;
4799         totalFramesRead += framesRead;
4800     }
4801
4802     return totalFramesRead;
4803 }
4804
4805 DRWAV_API drwav_uint64 drwav_read_pcm_frames_f32(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut)
4806 {
4807     if (pWav == NULL || framesToRead == 0) {
4808         return 0;
4809     }
4810
4811     if (pBufferOut == NULL) {
4812         return drwav_read_pcm_frames(pWav, framesToRead, NULL);
4813     }
4814
4815     /* Don't try to read more samples than can potentially fit in the output buffer. */
4816     if (framesToRead * pWav->channels * sizeof(float) > DRWAV_SIZE_MAX) {
4817         framesToRead = DRWAV_SIZE_MAX / sizeof(float) / pWav->channels;
4818     }
4819
4820     if (pWav->translatedFormatTag == DR_WAVE_FORMAT_PCM) {
4821         return drwav_read_pcm_frames_f32__pcm(pWav, framesToRead, pBufferOut);
4822     }
4823
4824     if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ADPCM) {
4825         return drwav_read_pcm_frames_f32__msadpcm(pWav, framesToRead, pBufferOut);
4826     }
4827
4828     if (pWav->translatedFormatTag == DR_WAVE_FORMAT_IEEE_FLOAT) {
4829         return drwav_read_pcm_frames_f32__ieee(pWav, framesToRead, pBufferOut);
4830     }
4831
4832     if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ALAW) {
4833         return drwav_read_pcm_frames_f32__alaw(pWav, framesToRead, pBufferOut);
4834     }
4835
4836     if (pWav->translatedFormatTag == DR_WAVE_FORMAT_MULAW) {
4837         return drwav_read_pcm_frames_f32__mulaw(pWav, framesToRead, pBufferOut);
4838     }
4839
4840     if (pWav->translatedFormatTag == DR_WAVE_FORMAT_DVI_ADPCM) {
4841         return drwav_read_pcm_frames_f32__ima(pWav, framesToRead, pBufferOut);
4842     }
4843
4844     return 0;
4845 }
4846
4847 DRWAV_API drwav_uint64 drwav_read_pcm_frames_f32le(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut)
4848 {
4849     drwav_uint64 framesRead = drwav_read_pcm_frames_f32(pWav, framesToRead, pBufferOut);
4850     if (pBufferOut != NULL && drwav__is_little_endian() == DRWAV_FALSE) {
4851         drwav__bswap_samples_f32(pBufferOut, framesRead*pWav->channels);
4852     }
4853
4854     return framesRead;
4855 }
4856
4857 DRWAV_API drwav_uint64 drwav_read_pcm_frames_f32be(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut)
4858 {
4859     drwav_uint64 framesRead = drwav_read_pcm_frames_f32(pWav, framesToRead, pBufferOut);
4860     if (pBufferOut != NULL && drwav__is_little_endian() == DRWAV_TRUE) {
4861         drwav__bswap_samples_f32(pBufferOut, framesRead*pWav->channels);
4862     }
4863
4864     return framesRead;
4865 }
4866
4867
4868 DRWAV_API void drwav_u8_to_f32(float* pOut, const drwav_uint8* pIn, size_t sampleCount)
4869 {
4870     size_t i;
4871
4872     if (pOut == NULL || pIn == NULL) {
4873         return;
4874     }
4875
4876 #ifdef DR_WAV_LIBSNDFILE_COMPAT
4877     /*
4878     It appears libsndfile uses slightly different logic for the u8 -> f32 conversion to dr_wav, which in my opinion is incorrect. It appears
4879     libsndfile performs the conversion something like "f32 = (u8 / 256) * 2 - 1", however I think it should be "f32 = (u8 / 255) * 2 - 1" (note
4880     the divisor of 256 vs 255). I use libsndfile as a benchmark for testing, so I'm therefore leaving this block here just for my automated
4881     correctness testing. This is disabled by default.
4882     */
4883     for (i = 0; i < sampleCount; ++i) {
4884         *pOut++ = (pIn[i] / 256.0f) * 2 - 1;
4885     }
4886 #else
4887     for (i = 0; i < sampleCount; ++i) {
4888         float x = pIn[i];
4889         x = x * 0.00784313725490196078f;    /* 0..255 to 0..2 */
4890         x = x - 1;                          /* 0..2 to -1..1 */
4891
4892         *pOut++ = x;
4893     }
4894 #endif
4895 }
4896
4897 DRWAV_API void drwav_s16_to_f32(float* pOut, const drwav_int16* pIn, size_t sampleCount)
4898 {
4899     size_t i;
4900
4901     if (pOut == NULL || pIn == NULL) {
4902         return;
4903     }
4904
4905     for (i = 0; i < sampleCount; ++i) {
4906         *pOut++ = pIn[i] * 0.000030517578125f;
4907     }
4908 }
4909
4910 DRWAV_API void drwav_s24_to_f32(float* pOut, const drwav_uint8* pIn, size_t sampleCount)
4911 {
4912     size_t i;
4913
4914     if (pOut == NULL || pIn == NULL) {
4915         return;
4916     }
4917
4918     for (i = 0; i < sampleCount; ++i) {
4919         double x;
4920         drwav_uint32 a = ((drwav_uint32)(pIn[i*3+0]) <<  8);
4921         drwav_uint32 b = ((drwav_uint32)(pIn[i*3+1]) << 16);
4922         drwav_uint32 c = ((drwav_uint32)(pIn[i*3+2]) << 24);
4923
4924         x = (double)((drwav_int32)(a | b | c) >> 8);
4925         *pOut++ = (float)(x * 0.00000011920928955078125);
4926     }
4927 }
4928
4929 DRWAV_API void drwav_s32_to_f32(float* pOut, const drwav_int32* pIn, size_t sampleCount)
4930 {
4931     size_t i;
4932     if (pOut == NULL || pIn == NULL) {
4933         return;
4934     }
4935
4936     for (i = 0; i < sampleCount; ++i) {
4937         *pOut++ = (float)(pIn[i] / 2147483648.0);
4938     }
4939 }
4940
4941 DRWAV_API void drwav_f64_to_f32(float* pOut, const double* pIn, size_t sampleCount)
4942 {
4943     size_t i;
4944
4945     if (pOut == NULL || pIn == NULL) {
4946         return;
4947     }
4948
4949     for (i = 0; i < sampleCount; ++i) {
4950         *pOut++ = (float)pIn[i];
4951     }
4952 }
4953
4954 DRWAV_API void drwav_alaw_to_f32(float* pOut, const drwav_uint8* pIn, size_t sampleCount)
4955 {
4956     size_t i;
4957
4958     if (pOut == NULL || pIn == NULL) {
4959         return;
4960     }
4961
4962     for (i = 0; i < sampleCount; ++i) {
4963         *pOut++ = drwav__alaw_to_s16(pIn[i]) / 32768.0f;
4964     }
4965 }
4966
4967 DRWAV_API void drwav_mulaw_to_f32(float* pOut, const drwav_uint8* pIn, size_t sampleCount)
4968 {
4969     size_t i;
4970
4971     if (pOut == NULL || pIn == NULL) {
4972         return;
4973     }
4974
4975     for (i = 0; i < sampleCount; ++i) {
4976         *pOut++ = drwav__mulaw_to_s16(pIn[i]) / 32768.0f;
4977     }
4978 }
4979
4980
4981
4982 DRWAV_PRIVATE void drwav__pcm_to_s32(drwav_int32* pOut, const drwav_uint8* pIn, size_t totalSampleCount, unsigned int bytesPerSample)
4983 {
4984     unsigned int i;
4985
4986     /* Special case for 8-bit sample data because it's treated as unsigned. */
4987     if (bytesPerSample == 1) {
4988         drwav_u8_to_s32(pOut, pIn, totalSampleCount);
4989         return;
4990     }
4991
4992     /* Slightly more optimal implementation for common formats. */
4993     if (bytesPerSample == 2) {
4994         drwav_s16_to_s32(pOut, (const drwav_int16*)pIn, totalSampleCount);
4995         return;
4996     }
4997     if (bytesPerSample == 3) {
4998         drwav_s24_to_s32(pOut, pIn, totalSampleCount);
4999         return;
5000     }
5001     if (bytesPerSample == 4) {
5002         for (i = 0; i < totalSampleCount; ++i) {
5003            *pOut++ = ((const drwav_int32*)pIn)[i];
5004         }
5005         return;
5006     }
5007
5008
5009     /* Anything more than 64 bits per sample is not supported. */
5010     if (bytesPerSample > 8) {
5011         DRWAV_ZERO_MEMORY(pOut, totalSampleCount * sizeof(*pOut));
5012         return;
5013     }
5014
5015
5016     /* Generic, slow converter. */
5017     for (i = 0; i < totalSampleCount; ++i) {
5018         drwav_uint64 sample = 0;
5019         unsigned int shift  = (8 - bytesPerSample) * 8;
5020
5021         unsigned int j;
5022         for (j = 0; j < bytesPerSample; j += 1) {
5023             DRWAV_ASSERT(j < 8);
5024             sample |= (drwav_uint64)(pIn[j]) << shift;
5025             shift  += 8;
5026         }
5027
5028         pIn += j;
5029         *pOut++ = (drwav_int32)((drwav_int64)sample >> 32);
5030     }
5031 }
5032
5033 DRWAV_PRIVATE void drwav__ieee_to_s32(drwav_int32* pOut, const drwav_uint8* pIn, size_t totalSampleCount, unsigned int bytesPerSample)
5034 {
5035     if (bytesPerSample == 4) {
5036         drwav_f32_to_s32(pOut, (const float*)pIn, totalSampleCount);
5037         return;
5038     } else if (bytesPerSample == 8) {
5039         drwav_f64_to_s32(pOut, (const double*)pIn, totalSampleCount);
5040         return;
5041     } else {
5042         /* Only supporting 32- and 64-bit float. Output silence in all other cases. Contributions welcome for 16-bit float. */
5043         DRWAV_ZERO_MEMORY(pOut, totalSampleCount * sizeof(*pOut));
5044         return;
5045     }
5046 }
5047
5048
5049 DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s32__pcm(drwav* pWav, drwav_uint64 framesToRead, drwav_int32* pBufferOut)
5050 {
5051     drwav_uint64 totalFramesRead;
5052     drwav_uint8 sampleData[4096];
5053     drwav_uint32 bytesPerFrame;
5054
5055     /* Fast path. */
5056     if (pWav->translatedFormatTag == DR_WAVE_FORMAT_PCM && pWav->bitsPerSample == 32) {
5057         return drwav_read_pcm_frames(pWav, framesToRead, pBufferOut);
5058     }
5059     
5060     bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
5061     if (bytesPerFrame == 0) {
5062         return 0;
5063     }
5064
5065     totalFramesRead = 0;
5066
5067     while (framesToRead > 0) {
5068         drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame), sampleData);
5069         if (framesRead == 0) {
5070             break;
5071         }
5072
5073         drwav__pcm_to_s32(pBufferOut, sampleData, (size_t)(framesRead*pWav->channels), bytesPerFrame/pWav->channels);
5074
5075         pBufferOut      += framesRead*pWav->channels;
5076         framesToRead    -= framesRead;
5077         totalFramesRead += framesRead;
5078     }
5079
5080     return totalFramesRead;
5081 }
5082
5083 DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s32__msadpcm(drwav* pWav, drwav_uint64 framesToRead, drwav_int32* pBufferOut)
5084 {
5085     /*
5086     We're just going to borrow the implementation from the drwav_read_s16() since ADPCM is a little bit more complicated than other formats and I don't
5087     want to duplicate that code.
5088     */
5089     drwav_uint64 totalFramesRead = 0;
5090     drwav_int16 samples16[2048];
5091
5092     while (framesToRead > 0) {
5093         drwav_uint64 framesRead = drwav_read_pcm_frames_s16(pWav, drwav_min(framesToRead, drwav_countof(samples16)/pWav->channels), samples16);
5094         if (framesRead == 0) {
5095             break;
5096         }
5097
5098         drwav_s16_to_s32(pBufferOut, samples16, (size_t)(framesRead*pWav->channels));   /* <-- Safe cast because we're clamping to 2048. */
5099
5100         pBufferOut      += framesRead*pWav->channels;
5101         framesToRead    -= framesRead;
5102         totalFramesRead += framesRead;
5103     }
5104
5105     return totalFramesRead;
5106 }
5107
5108 DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s32__ima(drwav* pWav, drwav_uint64 framesToRead, drwav_int32* pBufferOut)
5109 {
5110     /*
5111     We're just going to borrow the implementation from the drwav_read_s16() since IMA-ADPCM is a little bit more complicated than other formats and I don't
5112     want to duplicate that code.
5113     */
5114     drwav_uint64 totalFramesRead = 0;
5115     drwav_int16 samples16[2048];
5116
5117     while (framesToRead > 0) {
5118         drwav_uint64 framesRead = drwav_read_pcm_frames_s16(pWav, drwav_min(framesToRead, drwav_countof(samples16)/pWav->channels), samples16);
5119         if (framesRead == 0) {
5120             break;
5121         }
5122
5123         drwav_s16_to_s32(pBufferOut, samples16, (size_t)(framesRead*pWav->channels));   /* <-- Safe cast because we're clamping to 2048. */
5124
5125         pBufferOut      += framesRead*pWav->channels;
5126         framesToRead    -= framesRead;
5127         totalFramesRead += framesRead;
5128     }
5129
5130     return totalFramesRead;
5131 }
5132
5133 DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s32__ieee(drwav* pWav, drwav_uint64 framesToRead, drwav_int32* pBufferOut)
5134 {
5135     drwav_uint64 totalFramesRead;
5136     drwav_uint8 sampleData[4096];
5137     drwav_uint32 bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
5138
5139     if (bytesPerFrame == 0) {
5140         return 0;
5141     }
5142
5143     totalFramesRead = 0;
5144
5145     while (framesToRead > 0) {
5146         drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame), sampleData);
5147         if (framesRead == 0) {
5148             break;
5149         }
5150
5151         drwav__ieee_to_s32(pBufferOut, sampleData, (size_t)(framesRead*pWav->channels), bytesPerFrame/pWav->channels);
5152
5153         pBufferOut      += framesRead*pWav->channels;
5154         framesToRead    -= framesRead;
5155         totalFramesRead += framesRead;
5156     }
5157
5158     return totalFramesRead;
5159 }
5160
5161 DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s32__alaw(drwav* pWav, drwav_uint64 framesToRead, drwav_int32* pBufferOut)
5162 {
5163     drwav_uint64 totalFramesRead;
5164     drwav_uint8 sampleData[4096];
5165     drwav_uint32 bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
5166
5167     if (bytesPerFrame == 0) {
5168         return 0;
5169     }
5170
5171     totalFramesRead = 0;
5172
5173     while (framesToRead > 0) {
5174         drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame), sampleData);
5175         if (framesRead == 0) {
5176             break;
5177         }
5178
5179         drwav_alaw_to_s32(pBufferOut, sampleData, (size_t)(framesRead*pWav->channels));
5180
5181         pBufferOut      += framesRead*pWav->channels;
5182         framesToRead    -= framesRead;
5183         totalFramesRead += framesRead;
5184     }
5185
5186     return totalFramesRead;
5187 }
5188
5189 DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s32__mulaw(drwav* pWav, drwav_uint64 framesToRead, drwav_int32* pBufferOut)
5190 {
5191     drwav_uint64 totalFramesRead;
5192     drwav_uint8 sampleData[4096];
5193     drwav_uint32 bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
5194
5195     if (bytesPerFrame == 0) {
5196         return 0;
5197     }
5198
5199     totalFramesRead = 0;
5200
5201     while (framesToRead > 0) {
5202         drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame), sampleData);
5203         if (framesRead == 0) {
5204             break;
5205         }
5206
5207         drwav_mulaw_to_s32(pBufferOut, sampleData, (size_t)(framesRead*pWav->channels));
5208
5209         pBufferOut      += framesRead*pWav->channels;
5210         framesToRead    -= framesRead;
5211         totalFramesRead += framesRead;
5212     }
5213
5214     return totalFramesRead;
5215 }
5216
5217 DRWAV_API drwav_uint64 drwav_read_pcm_frames_s32(drwav* pWav, drwav_uint64 framesToRead, drwav_int32* pBufferOut)
5218 {
5219     if (pWav == NULL || framesToRead == 0) {
5220         return 0;
5221     }
5222
5223     if (pBufferOut == NULL) {
5224         return drwav_read_pcm_frames(pWav, framesToRead, NULL);
5225     }
5226
5227     /* Don't try to read more samples than can potentially fit in the output buffer. */
5228     if (framesToRead * pWav->channels * sizeof(drwav_int32) > DRWAV_SIZE_MAX) {
5229         framesToRead = DRWAV_SIZE_MAX / sizeof(drwav_int32) / pWav->channels;
5230     }
5231
5232     if (pWav->translatedFormatTag == DR_WAVE_FORMAT_PCM) {
5233         return drwav_read_pcm_frames_s32__pcm(pWav, framesToRead, pBufferOut);
5234     }
5235
5236     if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ADPCM) {
5237         return drwav_read_pcm_frames_s32__msadpcm(pWav, framesToRead, pBufferOut);
5238     }
5239
5240     if (pWav->translatedFormatTag == DR_WAVE_FORMAT_IEEE_FLOAT) {
5241         return drwav_read_pcm_frames_s32__ieee(pWav, framesToRead, pBufferOut);
5242     }
5243
5244     if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ALAW) {
5245         return drwav_read_pcm_frames_s32__alaw(pWav, framesToRead, pBufferOut);
5246     }
5247
5248     if (pWav->translatedFormatTag == DR_WAVE_FORMAT_MULAW) {
5249         return drwav_read_pcm_frames_s32__mulaw(pWav, framesToRead, pBufferOut);
5250     }
5251
5252     if (pWav->translatedFormatTag == DR_WAVE_FORMAT_DVI_ADPCM) {
5253         return drwav_read_pcm_frames_s32__ima(pWav, framesToRead, pBufferOut);
5254     }
5255
5256     return 0;
5257 }
5258
5259 DRWAV_API drwav_uint64 drwav_read_pcm_frames_s32le(drwav* pWav, drwav_uint64 framesToRead, drwav_int32* pBufferOut)
5260 {
5261     drwav_uint64 framesRead = drwav_read_pcm_frames_s32(pWav, framesToRead, pBufferOut);
5262     if (pBufferOut != NULL && drwav__is_little_endian() == DRWAV_FALSE) {
5263         drwav__bswap_samples_s32(pBufferOut, framesRead*pWav->channels);
5264     }
5265
5266     return framesRead;
5267 }
5268
5269 DRWAV_API drwav_uint64 drwav_read_pcm_frames_s32be(drwav* pWav, drwav_uint64 framesToRead, drwav_int32* pBufferOut)
5270 {
5271     drwav_uint64 framesRead = drwav_read_pcm_frames_s32(pWav, framesToRead, pBufferOut);
5272     if (pBufferOut != NULL && drwav__is_little_endian() == DRWAV_TRUE) {
5273         drwav__bswap_samples_s32(pBufferOut, framesRead*pWav->channels);
5274     }
5275
5276     return framesRead;
5277 }
5278
5279
5280 DRWAV_API void drwav_u8_to_s32(drwav_int32* pOut, const drwav_uint8* pIn, size_t sampleCount)
5281 {
5282     size_t i;
5283
5284     if (pOut == NULL || pIn == NULL) {
5285         return;
5286     }
5287
5288     for (i = 0; i < sampleCount; ++i) {
5289         *pOut++ = ((int)pIn[i] - 128) << 24;
5290     }
5291 }
5292
5293 DRWAV_API void drwav_s16_to_s32(drwav_int32* pOut, const drwav_int16* pIn, size_t sampleCount)
5294 {
5295     size_t i;
5296
5297     if (pOut == NULL || pIn == NULL) {
5298         return;
5299     }
5300
5301     for (i = 0; i < sampleCount; ++i) {
5302         *pOut++ = pIn[i] << 16;
5303     }
5304 }
5305
5306 DRWAV_API void drwav_s24_to_s32(drwav_int32* pOut, const drwav_uint8* pIn, size_t sampleCount)
5307 {
5308     size_t i;
5309
5310     if (pOut == NULL || pIn == NULL) {
5311         return;
5312     }
5313
5314     for (i = 0; i < sampleCount; ++i) {
5315         unsigned int s0 = pIn[i*3 + 0];
5316         unsigned int s1 = pIn[i*3 + 1];
5317         unsigned int s2 = pIn[i*3 + 2];
5318
5319         drwav_int32 sample32 = (drwav_int32)((s0 << 8) | (s1 << 16) | (s2 << 24));
5320         *pOut++ = sample32;
5321     }
5322 }
5323
5324 DRWAV_API void drwav_f32_to_s32(drwav_int32* pOut, const float* pIn, size_t sampleCount)
5325 {
5326     size_t i;
5327
5328     if (pOut == NULL || pIn == NULL) {
5329         return;
5330     }
5331
5332     for (i = 0; i < sampleCount; ++i) {
5333         *pOut++ = (drwav_int32)(2147483648.0 * pIn[i]);
5334     }
5335 }
5336
5337 DRWAV_API void drwav_f64_to_s32(drwav_int32* pOut, const double* pIn, size_t sampleCount)
5338 {
5339     size_t i;
5340
5341     if (pOut == NULL || pIn == NULL) {
5342         return;
5343     }
5344
5345     for (i = 0; i < sampleCount; ++i) {
5346         *pOut++ = (drwav_int32)(2147483648.0 * pIn[i]);
5347     }
5348 }
5349
5350 DRWAV_API void drwav_alaw_to_s32(drwav_int32* pOut, const drwav_uint8* pIn, size_t sampleCount)
5351 {
5352     size_t i;
5353
5354     if (pOut == NULL || pIn == NULL) {
5355         return;
5356     }
5357
5358     for (i = 0; i < sampleCount; ++i) {
5359         *pOut++ = ((drwav_int32)drwav__alaw_to_s16(pIn[i])) << 16;
5360     }
5361 }
5362
5363 DRWAV_API void drwav_mulaw_to_s32(drwav_int32* pOut, const drwav_uint8* pIn, size_t sampleCount)
5364 {
5365     size_t i;
5366
5367     if (pOut == NULL || pIn == NULL) {
5368         return;
5369     }
5370
5371     for (i= 0; i < sampleCount; ++i) {
5372         *pOut++ = ((drwav_int32)drwav__mulaw_to_s16(pIn[i])) << 16;
5373     }
5374 }
5375
5376
5377
5378 DRWAV_PRIVATE drwav_int16* drwav__read_pcm_frames_and_close_s16(drwav* pWav, unsigned int* channels, unsigned int* sampleRate, drwav_uint64* totalFrameCount)
5379 {
5380     drwav_uint64 sampleDataSize;
5381     drwav_int16* pSampleData;
5382     drwav_uint64 framesRead;
5383
5384     DRWAV_ASSERT(pWav != NULL);
5385
5386     sampleDataSize = pWav->totalPCMFrameCount * pWav->channels * sizeof(drwav_int16);
5387     if (sampleDataSize > DRWAV_SIZE_MAX) {
5388         drwav_uninit(pWav);
5389         return NULL;    /* File's too big. */
5390     }
5391
5392     pSampleData = (drwav_int16*)drwav__malloc_from_callbacks((size_t)sampleDataSize, &pWav->allocationCallbacks); /* <-- Safe cast due to the check above. */
5393     if (pSampleData == NULL) {
5394         drwav_uninit(pWav);
5395         return NULL;    /* Failed to allocate memory. */
5396     }
5397
5398     framesRead = drwav_read_pcm_frames_s16(pWav, (size_t)pWav->totalPCMFrameCount, pSampleData);
5399     if (framesRead != pWav->totalPCMFrameCount) {
5400         drwav__free_from_callbacks(pSampleData, &pWav->allocationCallbacks);
5401         drwav_uninit(pWav);
5402         return NULL;    /* There was an error reading the samples. */
5403     }
5404
5405     drwav_uninit(pWav);
5406
5407     if (sampleRate) {
5408         *sampleRate = pWav->sampleRate;
5409     }
5410     if (channels) {
5411         *channels = pWav->channels;
5412     }
5413     if (totalFrameCount) {
5414         *totalFrameCount = pWav->totalPCMFrameCount;
5415     }
5416
5417     return pSampleData;
5418 }
5419
5420 DRWAV_PRIVATE float* drwav__read_pcm_frames_and_close_f32(drwav* pWav, unsigned int* channels, unsigned int* sampleRate, drwav_uint64* totalFrameCount)
5421 {
5422     drwav_uint64 sampleDataSize;
5423     float* pSampleData;
5424     drwav_uint64 framesRead;
5425
5426     DRWAV_ASSERT(pWav != NULL);
5427
5428     sampleDataSize = pWav->totalPCMFrameCount * pWav->channels * sizeof(float);
5429     if (sampleDataSize > DRWAV_SIZE_MAX) {
5430         drwav_uninit(pWav);
5431         return NULL;    /* File's too big. */
5432     }
5433
5434     pSampleData = (float*)drwav__malloc_from_callbacks((size_t)sampleDataSize, &pWav->allocationCallbacks); /* <-- Safe cast due to the check above. */
5435     if (pSampleData == NULL) {
5436         drwav_uninit(pWav);
5437         return NULL;    /* Failed to allocate memory. */
5438     }
5439
5440     framesRead = drwav_read_pcm_frames_f32(pWav, (size_t)pWav->totalPCMFrameCount, pSampleData);
5441     if (framesRead != pWav->totalPCMFrameCount) {
5442         drwav__free_from_callbacks(pSampleData, &pWav->allocationCallbacks);
5443         drwav_uninit(pWav);
5444         return NULL;    /* There was an error reading the samples. */
5445     }
5446
5447     drwav_uninit(pWav);
5448
5449     if (sampleRate) {
5450         *sampleRate = pWav->sampleRate;
5451     }
5452     if (channels) {
5453         *channels = pWav->channels;
5454     }
5455     if (totalFrameCount) {
5456         *totalFrameCount = pWav->totalPCMFrameCount;
5457     }
5458
5459     return pSampleData;
5460 }
5461
5462 DRWAV_PRIVATE drwav_int32* drwav__read_pcm_frames_and_close_s32(drwav* pWav, unsigned int* channels, unsigned int* sampleRate, drwav_uint64* totalFrameCount)
5463 {
5464     drwav_uint64 sampleDataSize;
5465     drwav_int32* pSampleData;
5466     drwav_uint64 framesRead;
5467
5468     DRWAV_ASSERT(pWav != NULL);
5469
5470     sampleDataSize = pWav->totalPCMFrameCount * pWav->channels * sizeof(drwav_int32);
5471     if (sampleDataSize > DRWAV_SIZE_MAX) {
5472         drwav_uninit(pWav);
5473         return NULL;    /* File's too big. */
5474     }
5475
5476     pSampleData = (drwav_int32*)drwav__malloc_from_callbacks((size_t)sampleDataSize, &pWav->allocationCallbacks); /* <-- Safe cast due to the check above. */
5477     if (pSampleData == NULL) {
5478         drwav_uninit(pWav);
5479         return NULL;    /* Failed to allocate memory. */
5480     }
5481
5482     framesRead = drwav_read_pcm_frames_s32(pWav, (size_t)pWav->totalPCMFrameCount, pSampleData);
5483     if (framesRead != pWav->totalPCMFrameCount) {
5484         drwav__free_from_callbacks(pSampleData, &pWav->allocationCallbacks);
5485         drwav_uninit(pWav);
5486         return NULL;    /* There was an error reading the samples. */
5487     }
5488
5489     drwav_uninit(pWav);
5490
5491     if (sampleRate) {
5492         *sampleRate = pWav->sampleRate;
5493     }
5494     if (channels) {
5495         *channels = pWav->channels;
5496     }
5497     if (totalFrameCount) {
5498         *totalFrameCount = pWav->totalPCMFrameCount;
5499     }
5500
5501     return pSampleData;
5502 }
5503
5504
5505
5506 DRWAV_API drwav_int16* drwav_open_and_read_pcm_frames_s16(drwav_read_proc onRead, drwav_seek_proc onSeek, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks)
5507 {
5508     drwav wav;
5509
5510     if (channelsOut) {
5511         *channelsOut = 0;
5512     }
5513     if (sampleRateOut) {
5514         *sampleRateOut = 0;
5515     }
5516     if (totalFrameCountOut) {
5517         *totalFrameCountOut = 0;
5518     }
5519
5520     if (!drwav_init(&wav, onRead, onSeek, pUserData, pAllocationCallbacks)) {
5521         return NULL;
5522     }
5523
5524     return drwav__read_pcm_frames_and_close_s16(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
5525 }
5526
5527 DRWAV_API float* drwav_open_and_read_pcm_frames_f32(drwav_read_proc onRead, drwav_seek_proc onSeek, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks)
5528 {
5529     drwav wav;
5530
5531     if (channelsOut) {
5532         *channelsOut = 0;
5533     }
5534     if (sampleRateOut) {
5535         *sampleRateOut = 0;
5536     }
5537     if (totalFrameCountOut) {
5538         *totalFrameCountOut = 0;
5539     }
5540
5541     if (!drwav_init(&wav, onRead, onSeek, pUserData, pAllocationCallbacks)) {
5542         return NULL;
5543     }
5544
5545     return drwav__read_pcm_frames_and_close_f32(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
5546 }
5547
5548 DRWAV_API drwav_int32* drwav_open_and_read_pcm_frames_s32(drwav_read_proc onRead, drwav_seek_proc onSeek, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks)
5549 {
5550     drwav wav;
5551
5552     if (channelsOut) {
5553         *channelsOut = 0;
5554     }
5555     if (sampleRateOut) {
5556         *sampleRateOut = 0;
5557     }
5558     if (totalFrameCountOut) {
5559         *totalFrameCountOut = 0;
5560     }
5561
5562     if (!drwav_init(&wav, onRead, onSeek, pUserData, pAllocationCallbacks)) {
5563         return NULL;
5564     }
5565
5566     return drwav__read_pcm_frames_and_close_s32(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
5567 }
5568
5569 #ifndef DR_WAV_NO_STDIO
5570 DRWAV_API drwav_int16* drwav_open_file_and_read_pcm_frames_s16(const char* filename, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks)
5571 {
5572     drwav wav;
5573
5574     if (channelsOut) {
5575         *channelsOut = 0;
5576     }
5577     if (sampleRateOut) {
5578         *sampleRateOut = 0;
5579     }
5580     if (totalFrameCountOut) {
5581         *totalFrameCountOut = 0;
5582     }
5583
5584     if (!drwav_init_file(&wav, filename, pAllocationCallbacks)) {
5585         return NULL;
5586     }
5587
5588     return drwav__read_pcm_frames_and_close_s16(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
5589 }
5590
5591 DRWAV_API float* drwav_open_file_and_read_pcm_frames_f32(const char* filename, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks)
5592 {
5593     drwav wav;
5594
5595     if (channelsOut) {
5596         *channelsOut = 0;
5597     }
5598     if (sampleRateOut) {
5599         *sampleRateOut = 0;
5600     }
5601     if (totalFrameCountOut) {
5602         *totalFrameCountOut = 0;
5603     }
5604
5605     if (!drwav_init_file(&wav, filename, pAllocationCallbacks)) {
5606         return NULL;
5607     }
5608
5609     return drwav__read_pcm_frames_and_close_f32(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
5610 }
5611
5612 DRWAV_API drwav_int32* drwav_open_file_and_read_pcm_frames_s32(const char* filename, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks)
5613 {
5614     drwav wav;
5615
5616     if (channelsOut) {
5617         *channelsOut = 0;
5618     }
5619     if (sampleRateOut) {
5620         *sampleRateOut = 0;
5621     }
5622     if (totalFrameCountOut) {
5623         *totalFrameCountOut = 0;
5624     }
5625
5626     if (!drwav_init_file(&wav, filename, pAllocationCallbacks)) {
5627         return NULL;
5628     }
5629
5630     return drwav__read_pcm_frames_and_close_s32(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
5631 }
5632
5633
5634 DRWAV_API drwav_int16* drwav_open_file_and_read_pcm_frames_s16_w(const wchar_t* filename, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks)
5635 {
5636     drwav wav;
5637
5638     if (sampleRateOut) {
5639         *sampleRateOut = 0;
5640     }
5641     if (channelsOut) {
5642         *channelsOut = 0;
5643     }
5644     if (totalFrameCountOut) {
5645         *totalFrameCountOut = 0;
5646     }
5647
5648     if (!drwav_init_file_w(&wav, filename, pAllocationCallbacks)) {
5649         return NULL;
5650     }
5651
5652     return drwav__read_pcm_frames_and_close_s16(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
5653 }
5654
5655 DRWAV_API float* drwav_open_file_and_read_pcm_frames_f32_w(const wchar_t* filename, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks)
5656 {
5657     drwav wav;
5658
5659     if (sampleRateOut) {
5660         *sampleRateOut = 0;
5661     }
5662     if (channelsOut) {
5663         *channelsOut = 0;
5664     }
5665     if (totalFrameCountOut) {
5666         *totalFrameCountOut = 0;
5667     }
5668
5669     if (!drwav_init_file_w(&wav, filename, pAllocationCallbacks)) {
5670         return NULL;
5671     }
5672
5673     return drwav__read_pcm_frames_and_close_f32(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
5674 }
5675
5676 DRWAV_API drwav_int32* drwav_open_file_and_read_pcm_frames_s32_w(const wchar_t* filename, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks)
5677 {
5678     drwav wav;
5679
5680     if (sampleRateOut) {
5681         *sampleRateOut = 0;
5682     }
5683     if (channelsOut) {
5684         *channelsOut = 0;
5685     }
5686     if (totalFrameCountOut) {
5687         *totalFrameCountOut = 0;
5688     }
5689
5690     if (!drwav_init_file_w(&wav, filename, pAllocationCallbacks)) {
5691         return NULL;
5692     }
5693
5694     return drwav__read_pcm_frames_and_close_s32(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
5695 }
5696 #endif
5697
5698 DRWAV_API drwav_int16* drwav_open_memory_and_read_pcm_frames_s16(const void* data, size_t dataSize, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks)
5699 {
5700     drwav wav;
5701
5702     if (channelsOut) {
5703         *channelsOut = 0;
5704     }
5705     if (sampleRateOut) {
5706         *sampleRateOut = 0;
5707     }
5708     if (totalFrameCountOut) {
5709         *totalFrameCountOut = 0;
5710     }
5711
5712     if (!drwav_init_memory(&wav, data, dataSize, pAllocationCallbacks)) {
5713         return NULL;
5714     }
5715
5716     return drwav__read_pcm_frames_and_close_s16(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
5717 }
5718
5719 DRWAV_API float* drwav_open_memory_and_read_pcm_frames_f32(const void* data, size_t dataSize, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks)
5720 {
5721     drwav wav;
5722
5723     if (channelsOut) {
5724         *channelsOut = 0;
5725     }
5726     if (sampleRateOut) {
5727         *sampleRateOut = 0;
5728     }
5729     if (totalFrameCountOut) {
5730         *totalFrameCountOut = 0;
5731     }
5732
5733     if (!drwav_init_memory(&wav, data, dataSize, pAllocationCallbacks)) {
5734         return NULL;
5735     }
5736
5737     return drwav__read_pcm_frames_and_close_f32(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
5738 }
5739
5740 DRWAV_API drwav_int32* drwav_open_memory_and_read_pcm_frames_s32(const void* data, size_t dataSize, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks)
5741 {
5742     drwav wav;
5743
5744     if (channelsOut) {
5745         *channelsOut = 0;
5746     }
5747     if (sampleRateOut) {
5748         *sampleRateOut = 0;
5749     }
5750     if (totalFrameCountOut) {
5751         *totalFrameCountOut = 0;
5752     }
5753
5754     if (!drwav_init_memory(&wav, data, dataSize, pAllocationCallbacks)) {
5755         return NULL;
5756     }
5757
5758     return drwav__read_pcm_frames_and_close_s32(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
5759 }
5760 #endif  /* DR_WAV_NO_CONVERSION_API */
5761
5762
5763 DRWAV_API void drwav_free(void* p, const drwav_allocation_callbacks* pAllocationCallbacks)
5764 {
5765     if (pAllocationCallbacks != NULL) {
5766         drwav__free_from_callbacks(p, pAllocationCallbacks);
5767     } else {
5768         drwav__free_default(p, NULL);
5769     }
5770 }
5771
5772 DRWAV_API drwav_uint16 drwav_bytes_to_u16(const drwav_uint8* data)
5773 {
5774     return (data[0] << 0) | (data[1] << 8);
5775 }
5776
5777 DRWAV_API drwav_int16 drwav_bytes_to_s16(const drwav_uint8* data)
5778 {
5779     return (short)drwav_bytes_to_u16(data);
5780 }
5781
5782 DRWAV_API drwav_uint32 drwav_bytes_to_u32(const drwav_uint8* data)
5783 {
5784     return (data[0] << 0) | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
5785 }
5786
5787 DRWAV_API drwav_int32 drwav_bytes_to_s32(const drwav_uint8* data)
5788 {
5789     return (drwav_int32)drwav_bytes_to_u32(data);
5790 }
5791
5792 DRWAV_API drwav_uint64 drwav_bytes_to_u64(const drwav_uint8* data)
5793 {
5794     return
5795         ((drwav_uint64)data[0] <<  0) | ((drwav_uint64)data[1] <<  8) | ((drwav_uint64)data[2] << 16) | ((drwav_uint64)data[3] << 24) |
5796         ((drwav_uint64)data[4] << 32) | ((drwav_uint64)data[5] << 40) | ((drwav_uint64)data[6] << 48) | ((drwav_uint64)data[7] << 56);
5797 }
5798
5799 DRWAV_API drwav_int64 drwav_bytes_to_s64(const drwav_uint8* data)
5800 {
5801     return (drwav_int64)drwav_bytes_to_u64(data);
5802 }
5803
5804
5805 DRWAV_API drwav_bool32 drwav_guid_equal(const drwav_uint8 a[16], const drwav_uint8 b[16])
5806 {
5807     int i;
5808     for (i = 0; i < 16; i += 1) {
5809         if (a[i] != b[i]) {
5810             return DRWAV_FALSE;
5811         }
5812     }
5813
5814     return DRWAV_TRUE;
5815 }
5816
5817 DRWAV_API drwav_bool32 drwav_fourcc_equal(const drwav_uint8* a, const char* b)
5818 {
5819     return
5820         a[0] == b[0] &&
5821         a[1] == b[1] &&
5822         a[2] == b[2] &&
5823         a[3] == b[3];
5824 }
5825
5826 #endif  /* dr_wav_c */
5827 #endif  /* DR_WAV_IMPLEMENTATION */
5828
5829 /*
5830 RELEASE NOTES - v0.11.0
5831 =======================
5832 Version 0.11.0 has breaking API changes.
5833
5834 Improved Client-Defined Memory Allocation
5835 -----------------------------------------
5836 The main change with this release is the addition of a more flexible way of implementing custom memory allocation routines. The
5837 existing system of DRWAV_MALLOC, DRWAV_REALLOC and DRWAV_FREE are still in place and will be used by default when no custom
5838 allocation callbacks are specified.
5839
5840 To use the new system, you pass in a pointer to a drwav_allocation_callbacks object to drwav_init() and family, like this:
5841
5842     void* my_malloc(size_t sz, void* pUserData)
5843     {
5844         return malloc(sz);
5845     }
5846     void* my_realloc(void* p, size_t sz, void* pUserData)
5847     {
5848         return realloc(p, sz);
5849     }
5850     void my_free(void* p, void* pUserData)
5851     {
5852         free(p);
5853     }
5854
5855     ...
5856
5857     drwav_allocation_callbacks allocationCallbacks;
5858     allocationCallbacks.pUserData = &myData;
5859     allocationCallbacks.onMalloc  = my_malloc;
5860     allocationCallbacks.onRealloc = my_realloc;
5861     allocationCallbacks.onFree    = my_free;
5862     drwav_init_file(&wav, "my_file.wav", &allocationCallbacks);
5863
5864 The advantage of this new system is that it allows you to specify user data which will be passed in to the allocation routines.
5865
5866 Passing in null for the allocation callbacks object will cause dr_wav to use defaults which is the same as DRWAV_MALLOC,
5867 DRWAV_REALLOC and DRWAV_FREE and the equivalent of how it worked in previous versions.
5868
5869 Every API that opens a drwav object now takes this extra parameter. These include the following:
5870
5871     drwav_init()
5872     drwav_init_ex()
5873     drwav_init_file()
5874     drwav_init_file_ex()
5875     drwav_init_file_w()
5876     drwav_init_file_w_ex()
5877     drwav_init_memory()
5878     drwav_init_memory_ex()
5879     drwav_init_write()
5880     drwav_init_write_sequential()
5881     drwav_init_write_sequential_pcm_frames()
5882     drwav_init_file_write()
5883     drwav_init_file_write_sequential()
5884     drwav_init_file_write_sequential_pcm_frames()
5885     drwav_init_file_write_w()
5886     drwav_init_file_write_sequential_w()
5887     drwav_init_file_write_sequential_pcm_frames_w()
5888     drwav_init_memory_write()
5889     drwav_init_memory_write_sequential()
5890     drwav_init_memory_write_sequential_pcm_frames()
5891     drwav_open_and_read_pcm_frames_s16()
5892     drwav_open_and_read_pcm_frames_f32()
5893     drwav_open_and_read_pcm_frames_s32()
5894     drwav_open_file_and_read_pcm_frames_s16()
5895     drwav_open_file_and_read_pcm_frames_f32()
5896     drwav_open_file_and_read_pcm_frames_s32()
5897     drwav_open_file_and_read_pcm_frames_s16_w()
5898     drwav_open_file_and_read_pcm_frames_f32_w()
5899     drwav_open_file_and_read_pcm_frames_s32_w()
5900     drwav_open_memory_and_read_pcm_frames_s16()
5901     drwav_open_memory_and_read_pcm_frames_f32()
5902     drwav_open_memory_and_read_pcm_frames_s32()
5903
5904 Endian Improvements
5905 -------------------
5906 Previously, the following APIs returned little-endian audio data. These now return native-endian data. This improves compatibility
5907 on big-endian architectures.
5908
5909     drwav_read_pcm_frames()
5910     drwav_read_pcm_frames_s16()
5911     drwav_read_pcm_frames_s32()
5912     drwav_read_pcm_frames_f32()
5913     drwav_open_and_read_pcm_frames_s16()
5914     drwav_open_and_read_pcm_frames_s32()
5915     drwav_open_and_read_pcm_frames_f32()
5916     drwav_open_file_and_read_pcm_frames_s16()
5917     drwav_open_file_and_read_pcm_frames_s32()
5918     drwav_open_file_and_read_pcm_frames_f32()
5919     drwav_open_file_and_read_pcm_frames_s16_w()
5920     drwav_open_file_and_read_pcm_frames_s32_w()
5921     drwav_open_file_and_read_pcm_frames_f32_w()
5922     drwav_open_memory_and_read_pcm_frames_s16()
5923     drwav_open_memory_and_read_pcm_frames_s32()
5924     drwav_open_memory_and_read_pcm_frames_f32()
5925
5926 APIs have been added to give you explicit control over whether or not audio data is read or written in big- or little-endian byte
5927 order:
5928
5929     drwav_read_pcm_frames_le()
5930     drwav_read_pcm_frames_be()
5931     drwav_read_pcm_frames_s16le()
5932     drwav_read_pcm_frames_s16be()
5933     drwav_read_pcm_frames_f32le()
5934     drwav_read_pcm_frames_f32be()
5935     drwav_read_pcm_frames_s32le()
5936     drwav_read_pcm_frames_s32be()
5937     drwav_write_pcm_frames_le()
5938     drwav_write_pcm_frames_be()
5939
5940 Removed APIs
5941 ------------
5942 The following APIs were deprecated in version 0.10.0 and have now been removed:
5943
5944     drwav_open()
5945     drwav_open_ex()
5946     drwav_open_write()
5947     drwav_open_write_sequential()
5948     drwav_open_file()
5949     drwav_open_file_ex()
5950     drwav_open_file_write()
5951     drwav_open_file_write_sequential()
5952     drwav_open_memory()
5953     drwav_open_memory_ex()
5954     drwav_open_memory_write()
5955     drwav_open_memory_write_sequential()
5956     drwav_close()
5957
5958
5959
5960 RELEASE NOTES - v0.10.0
5961 =======================
5962 Version 0.10.0 has breaking API changes. There are no significant bug fixes in this release, so if you are affected you do
5963 not need to upgrade.
5964
5965 Removed APIs
5966 ------------
5967 The following APIs were deprecated in version 0.9.0 and have been completely removed in version 0.10.0:
5968
5969     drwav_read()
5970     drwav_read_s16()
5971     drwav_read_f32()
5972     drwav_read_s32()
5973     drwav_seek_to_sample()
5974     drwav_write()
5975     drwav_open_and_read_s16()
5976     drwav_open_and_read_f32()
5977     drwav_open_and_read_s32()
5978     drwav_open_file_and_read_s16()
5979     drwav_open_file_and_read_f32()
5980     drwav_open_file_and_read_s32()
5981     drwav_open_memory_and_read_s16()
5982     drwav_open_memory_and_read_f32()
5983     drwav_open_memory_and_read_s32()
5984     drwav::totalSampleCount
5985
5986 See release notes for version 0.9.0 at the bottom of this file for replacement APIs.
5987
5988 Deprecated APIs
5989 ---------------
5990 The following APIs have been deprecated. There is a confusing and completely arbitrary difference between drwav_init*() and
5991 drwav_open*(), where drwav_init*() initializes a pre-allocated drwav object, whereas drwav_open*() will first allocated a
5992 drwav object on the heap and then initialize it. drwav_open*() has been deprecated which means you must now use a pre-
5993 allocated drwav object with drwav_init*(). If you need the previous functionality, you can just do a malloc() followed by
5994 a called to one of the drwav_init*() APIs.
5995
5996     drwav_open()
5997     drwav_open_ex()
5998     drwav_open_write()
5999     drwav_open_write_sequential()
6000     drwav_open_file()
6001     drwav_open_file_ex()
6002     drwav_open_file_write()
6003     drwav_open_file_write_sequential()
6004     drwav_open_memory()
6005     drwav_open_memory_ex()
6006     drwav_open_memory_write()
6007     drwav_open_memory_write_sequential()
6008     drwav_close()
6009
6010 These APIs will be removed completely in a future version. The rationale for this change is to remove confusion between the
6011 two different ways to initialize a drwav object.
6012 */
6013
6014 /*
6015 REVISION HISTORY
6016 ================
6017 v0.12.19 - 2021-02-21
6018   - Fix a warning due to referencing _MSC_VER when it is undefined.
6019   - Minor improvements to the management of some internal state concerning the data chunk cursor.
6020
6021 v0.12.18 - 2021-01-31
6022   - Clean up some static analysis warnings.
6023
6024 v0.12.17 - 2021-01-17
6025   - Minor fix to sample code in documentation.
6026   - Correctly qualify a private API as private rather than public.
6027   - Code cleanup.
6028
6029 v0.12.16 - 2020-12-02
6030   - Fix a bug when trying to read more bytes than can fit in a size_t.
6031
6032 v0.12.15 - 2020-11-21
6033   - Fix compilation with OpenWatcom.
6034
6035 v0.12.14 - 2020-11-13
6036   - Minor code clean up.
6037
6038 v0.12.13 - 2020-11-01
6039   - Improve compiler support for older versions of GCC.
6040
6041 v0.12.12 - 2020-09-28
6042   - Add support for RF64.
6043   - Fix a bug in writing mode where the size of the RIFF chunk incorrectly includes the header section.
6044
6045 v0.12.11 - 2020-09-08
6046   - Fix a compilation error on older compilers.
6047
6048 v0.12.10 - 2020-08-24
6049   - Fix a bug when seeking with ADPCM formats.
6050
6051 v0.12.9 - 2020-08-02
6052   - Simplify sized types.
6053
6054 v0.12.8 - 2020-07-25
6055   - Fix a compilation warning.
6056
6057 v0.12.7 - 2020-07-15
6058   - Fix some bugs on big-endian architectures.
6059   - Fix an error in s24 to f32 conversion.
6060
6061 v0.12.6 - 2020-06-23
6062   - Change drwav_read_*() to allow NULL to be passed in as the output buffer which is equivalent to a forward seek.
6063   - Fix a buffer overflow when trying to decode invalid IMA-ADPCM files.
6064   - Add include guard for the implementation section.
6065
6066 v0.12.5 - 2020-05-27
6067   - Minor documentation fix.
6068
6069 v0.12.4 - 2020-05-16
6070   - Replace assert() with DRWAV_ASSERT().
6071   - Add compile-time and run-time version querying.
6072     - DRWAV_VERSION_MINOR
6073     - DRWAV_VERSION_MAJOR
6074     - DRWAV_VERSION_REVISION
6075     - DRWAV_VERSION_STRING
6076     - drwav_version()
6077     - drwav_version_string()
6078
6079 v0.12.3 - 2020-04-30
6080   - Fix compilation errors with VC6.
6081
6082 v0.12.2 - 2020-04-21
6083   - Fix a bug where drwav_init_file() does not close the file handle after attempting to load an erroneous file.
6084
6085 v0.12.1 - 2020-04-13
6086   - Fix some pedantic warnings.
6087
6088 v0.12.0 - 2020-04-04
6089   - API CHANGE: Add container and format parameters to the chunk callback.
6090   - Minor documentation updates.
6091
6092 v0.11.5 - 2020-03-07
6093   - Fix compilation error with Visual Studio .NET 2003.
6094
6095 v0.11.4 - 2020-01-29
6096   - Fix some static analysis warnings.
6097   - Fix a bug when reading f32 samples from an A-law encoded stream.
6098
6099 v0.11.3 - 2020-01-12
6100   - Minor changes to some f32 format conversion routines.
6101   - Minor bug fix for ADPCM conversion when end of file is reached.
6102
6103 v0.11.2 - 2019-12-02
6104   - Fix a possible crash when using custom memory allocators without a custom realloc() implementation.
6105   - Fix an integer overflow bug.
6106   - Fix a null pointer dereference bug.
6107   - Add limits to sample rate, channels and bits per sample to tighten up some validation.
6108
6109 v0.11.1 - 2019-10-07
6110   - Internal code clean up.
6111
6112 v0.11.0 - 2019-10-06
6113   - API CHANGE: Add support for user defined memory allocation routines. This system allows the program to specify their own memory allocation
6114     routines with a user data pointer for client-specific contextual data. This adds an extra parameter to the end of the following APIs:
6115     - drwav_init()
6116     - drwav_init_ex()
6117     - drwav_init_file()
6118     - drwav_init_file_ex()
6119     - drwav_init_file_w()
6120     - drwav_init_file_w_ex()
6121     - drwav_init_memory()
6122     - drwav_init_memory_ex()
6123     - drwav_init_write()
6124     - drwav_init_write_sequential()
6125     - drwav_init_write_sequential_pcm_frames()
6126     - drwav_init_file_write()
6127     - drwav_init_file_write_sequential()
6128     - drwav_init_file_write_sequential_pcm_frames()
6129     - drwav_init_file_write_w()
6130     - drwav_init_file_write_sequential_w()
6131     - drwav_init_file_write_sequential_pcm_frames_w()
6132     - drwav_init_memory_write()
6133     - drwav_init_memory_write_sequential()
6134     - drwav_init_memory_write_sequential_pcm_frames()
6135     - drwav_open_and_read_pcm_frames_s16()
6136     - drwav_open_and_read_pcm_frames_f32()
6137     - drwav_open_and_read_pcm_frames_s32()
6138     - drwav_open_file_and_read_pcm_frames_s16()
6139     - drwav_open_file_and_read_pcm_frames_f32()
6140     - drwav_open_file_and_read_pcm_frames_s32()
6141     - drwav_open_file_and_read_pcm_frames_s16_w()
6142     - drwav_open_file_and_read_pcm_frames_f32_w()
6143     - drwav_open_file_and_read_pcm_frames_s32_w()
6144     - drwav_open_memory_and_read_pcm_frames_s16()
6145     - drwav_open_memory_and_read_pcm_frames_f32()
6146     - drwav_open_memory_and_read_pcm_frames_s32()
6147     Set this extra parameter to NULL to use defaults which is the same as the previous behaviour. Setting this NULL will use
6148     DRWAV_MALLOC, DRWAV_REALLOC and DRWAV_FREE.
6149   - Add support for reading and writing PCM frames in an explicit endianness. New APIs:
6150     - drwav_read_pcm_frames_le()
6151     - drwav_read_pcm_frames_be()
6152     - drwav_read_pcm_frames_s16le()
6153     - drwav_read_pcm_frames_s16be()
6154     - drwav_read_pcm_frames_f32le()
6155     - drwav_read_pcm_frames_f32be()
6156     - drwav_read_pcm_frames_s32le()
6157     - drwav_read_pcm_frames_s32be()
6158     - drwav_write_pcm_frames_le()
6159     - drwav_write_pcm_frames_be()
6160   - Remove deprecated APIs.
6161   - API CHANGE: The following APIs now return native-endian data. Previously they returned little-endian data.
6162     - drwav_read_pcm_frames()
6163     - drwav_read_pcm_frames_s16()
6164     - drwav_read_pcm_frames_s32()
6165     - drwav_read_pcm_frames_f32()
6166     - drwav_open_and_read_pcm_frames_s16()
6167     - drwav_open_and_read_pcm_frames_s32()
6168     - drwav_open_and_read_pcm_frames_f32()
6169     - drwav_open_file_and_read_pcm_frames_s16()
6170     - drwav_open_file_and_read_pcm_frames_s32()
6171     - drwav_open_file_and_read_pcm_frames_f32()
6172     - drwav_open_file_and_read_pcm_frames_s16_w()
6173     - drwav_open_file_and_read_pcm_frames_s32_w()
6174     - drwav_open_file_and_read_pcm_frames_f32_w()
6175     - drwav_open_memory_and_read_pcm_frames_s16()
6176     - drwav_open_memory_and_read_pcm_frames_s32()
6177     - drwav_open_memory_and_read_pcm_frames_f32()
6178
6179 v0.10.1 - 2019-08-31
6180   - Correctly handle partial trailing ADPCM blocks.
6181
6182 v0.10.0 - 2019-08-04
6183   - Remove deprecated APIs.
6184   - Add wchar_t variants for file loading APIs:
6185       drwav_init_file_w()
6186       drwav_init_file_ex_w()
6187       drwav_init_file_write_w()
6188       drwav_init_file_write_sequential_w()
6189   - Add drwav_target_write_size_bytes() which calculates the total size in bytes of a WAV file given a format and sample count.
6190   - Add APIs for specifying the PCM frame count instead of the sample count when opening in sequential write mode:
6191       drwav_init_write_sequential_pcm_frames()
6192       drwav_init_file_write_sequential_pcm_frames()
6193       drwav_init_file_write_sequential_pcm_frames_w()
6194       drwav_init_memory_write_sequential_pcm_frames()
6195   - Deprecate drwav_open*() and drwav_close():
6196       drwav_open()
6197       drwav_open_ex()
6198       drwav_open_write()
6199       drwav_open_write_sequential()
6200       drwav_open_file()
6201       drwav_open_file_ex()
6202       drwav_open_file_write()
6203       drwav_open_file_write_sequential()
6204       drwav_open_memory()
6205       drwav_open_memory_ex()
6206       drwav_open_memory_write()
6207       drwav_open_memory_write_sequential()
6208       drwav_close()
6209   - Minor documentation updates.
6210
6211 v0.9.2 - 2019-05-21
6212   - Fix warnings.
6213
6214 v0.9.1 - 2019-05-05
6215   - Add support for C89.
6216   - Change license to choice of public domain or MIT-0.
6217
6218 v0.9.0 - 2018-12-16
6219   - API CHANGE: Add new reading APIs for reading by PCM frames instead of samples. Old APIs have been deprecated and
6220     will be removed in v0.10.0. Deprecated APIs and their replacements:
6221       drwav_read()                     -> drwav_read_pcm_frames()
6222       drwav_read_s16()                 -> drwav_read_pcm_frames_s16()
6223       drwav_read_f32()                 -> drwav_read_pcm_frames_f32()
6224       drwav_read_s32()                 -> drwav_read_pcm_frames_s32()
6225       drwav_seek_to_sample()           -> drwav_seek_to_pcm_frame()
6226       drwav_write()                    -> drwav_write_pcm_frames()
6227       drwav_open_and_read_s16()        -> drwav_open_and_read_pcm_frames_s16()
6228       drwav_open_and_read_f32()        -> drwav_open_and_read_pcm_frames_f32()
6229       drwav_open_and_read_s32()        -> drwav_open_and_read_pcm_frames_s32()
6230       drwav_open_file_and_read_s16()   -> drwav_open_file_and_read_pcm_frames_s16()
6231       drwav_open_file_and_read_f32()   -> drwav_open_file_and_read_pcm_frames_f32()
6232       drwav_open_file_and_read_s32()   -> drwav_open_file_and_read_pcm_frames_s32()
6233       drwav_open_memory_and_read_s16() -> drwav_open_memory_and_read_pcm_frames_s16()
6234       drwav_open_memory_and_read_f32() -> drwav_open_memory_and_read_pcm_frames_f32()
6235       drwav_open_memory_and_read_s32() -> drwav_open_memory_and_read_pcm_frames_s32()
6236       drwav::totalSampleCount          -> drwav::totalPCMFrameCount
6237   - API CHANGE: Rename drwav_open_and_read_file_*() to drwav_open_file_and_read_*().
6238   - API CHANGE: Rename drwav_open_and_read_memory_*() to drwav_open_memory_and_read_*().
6239   - Add built-in support for smpl chunks.
6240   - Add support for firing a callback for each chunk in the file at initialization time.
6241     - This is enabled through the drwav_init_ex(), etc. family of APIs.
6242   - Handle invalid FMT chunks more robustly.
6243
6244 v0.8.5 - 2018-09-11
6245   - Const correctness.
6246   - Fix a potential stack overflow.
6247
6248 v0.8.4 - 2018-08-07
6249   - Improve 64-bit detection.
6250
6251 v0.8.3 - 2018-08-05
6252   - Fix C++ build on older versions of GCC.
6253
6254 v0.8.2 - 2018-08-02
6255   - Fix some big-endian bugs.
6256
6257 v0.8.1 - 2018-06-29
6258   - Add support for sequential writing APIs.
6259   - Disable seeking in write mode.
6260   - Fix bugs with Wave64.
6261   - Fix typos.
6262
6263 v0.8 - 2018-04-27
6264   - Bug fix.
6265   - Start using major.minor.revision versioning.
6266
6267 v0.7f - 2018-02-05
6268   - Restrict ADPCM formats to a maximum of 2 channels.
6269
6270 v0.7e - 2018-02-02
6271   - Fix a crash.
6272
6273 v0.7d - 2018-02-01
6274   - Fix a crash.
6275
6276 v0.7c - 2018-02-01
6277   - Set drwav.bytesPerSample to 0 for all compressed formats.
6278   - Fix a crash when reading 16-bit floating point WAV files. In this case dr_wav will output silence for
6279     all format conversion reading APIs (*_s16, *_s32, *_f32 APIs).
6280   - Fix some divide-by-zero errors.
6281
6282 v0.7b - 2018-01-22
6283   - Fix errors with seeking of compressed formats.
6284   - Fix compilation error when DR_WAV_NO_CONVERSION_API
6285
6286 v0.7a - 2017-11-17
6287   - Fix some GCC warnings.
6288
6289 v0.7 - 2017-11-04
6290   - Add writing APIs.
6291
6292 v0.6 - 2017-08-16
6293   - API CHANGE: Rename dr_* types to drwav_*.
6294   - Add support for custom implementations of malloc(), realloc(), etc.
6295   - Add support for Microsoft ADPCM.
6296   - Add support for IMA ADPCM (DVI, format code 0x11).
6297   - Optimizations to drwav_read_s16().
6298   - Bug fixes.
6299
6300 v0.5g - 2017-07-16
6301   - Change underlying type for booleans to unsigned.
6302
6303 v0.5f - 2017-04-04
6304   - Fix a minor bug with drwav_open_and_read_s16() and family.
6305
6306 v0.5e - 2016-12-29
6307   - Added support for reading samples as signed 16-bit integers. Use the _s16() family of APIs for this.
6308   - Minor fixes to documentation.
6309
6310 v0.5d - 2016-12-28
6311   - Use drwav_int* and drwav_uint* sized types to improve compiler support.
6312
6313 v0.5c - 2016-11-11
6314   - Properly handle JUNK chunks that come before the FMT chunk.
6315
6316 v0.5b - 2016-10-23
6317   - A minor change to drwav_bool8 and drwav_bool32 types.
6318
6319 v0.5a - 2016-10-11
6320   - Fixed a bug with drwav_open_and_read() and family due to incorrect argument ordering.
6321   - Improve A-law and mu-law efficiency.
6322
6323 v0.5 - 2016-09-29
6324   - API CHANGE. Swap the order of "channels" and "sampleRate" parameters in drwav_open_and_read*(). Rationale for this is to
6325     keep it consistent with dr_audio and dr_flac.
6326
6327 v0.4b - 2016-09-18
6328   - Fixed a typo in documentation.
6329
6330 v0.4a - 2016-09-18
6331   - Fixed a typo.
6332   - Change date format to ISO 8601 (YYYY-MM-DD)
6333
6334 v0.4 - 2016-07-13
6335   - API CHANGE. Make onSeek consistent with dr_flac.
6336   - API CHANGE. Rename drwav_seek() to drwav_seek_to_sample() for clarity and consistency with dr_flac.
6337   - Added support for Sony Wave64.
6338
6339 v0.3a - 2016-05-28
6340   - API CHANGE. Return drwav_bool32 instead of int in onSeek callback.
6341   - Fixed a memory leak.
6342
6343 v0.3 - 2016-05-22
6344   - Lots of API changes for consistency.
6345
6346 v0.2a - 2016-05-16
6347   - Fixed Linux/GCC build.
6348
6349 v0.2 - 2016-05-11
6350   - Added support for reading data as signed 32-bit PCM for consistency with dr_flac.
6351
6352 v0.1a - 2016-05-07
6353   - Fixed a bug in drwav_open_file() where the file handle would not be closed if the loader failed to initialize.
6354
6355 v0.1 - 2016-05-04
6356   - Initial versioned release.
6357 */
6358
6359 /*
6360 This software is available as a choice of the following licenses. Choose
6361 whichever you prefer.
6362
6363 ===============================================================================
6364 ALTERNATIVE 1 - Public Domain (www.unlicense.org)
6365 ===============================================================================
6366 This is free and unencumbered software released into the public domain.
6367
6368 Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
6369 software, either in source code form or as a compiled binary, for any purpose,
6370 commercial or non-commercial, and by any means.
6371
6372 In jurisdictions that recognize copyright laws, the author or authors of this
6373 software dedicate any and all copyright interest in the software to the public
6374 domain. We make this dedication for the benefit of the public at large and to
6375 the detriment of our heirs and successors. We intend this dedication to be an
6376 overt act of relinquishment in perpetuity of all present and future rights to
6377 this software under copyright law.
6378
6379 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
6380 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
6381 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
6382 AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
6383 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
6384 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
6385
6386 For more information, please refer to <http://unlicense.org/>
6387
6388 ===============================================================================
6389 ALTERNATIVE 2 - MIT No Attribution
6390 ===============================================================================
6391 Copyright 2020 David Reid
6392
6393 Permission is hereby granted, free of charge, to any person obtaining a copy of
6394 this software and associated documentation files (the "Software"), to deal in
6395 the Software without restriction, including without limitation the rights to
6396 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
6397 of the Software, and to permit persons to whom the Software is furnished to do
6398 so.
6399
6400 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
6401 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
6402 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
6403 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
6404 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
6405 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
6406 SOFTWARE.
6407 */