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