minesweeper

A minewseeper implementation to play around with Hare and Raylib
git clone https://git.tronto.net/minesweeper
Download | Log | Files | Refs | README | LICENSE

dr_wav.h (351978B)


      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.13.16 - 2024-02-27
      4 
      5 David Reid - mackron@gmail.com
      6 
      7 GitHub: https://github.com/mackron/dr_libs
      8 */
      9 
     10 /*
     11 Introduction
     12 ============
     13 This is a single file library. To use it, do something like the following in one .c file.
     14 
     15     ```c
     16     #define DR_WAV_IMPLEMENTATION
     17     #include "dr_wav.h"
     18     ```
     19 
     20 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:
     21 
     22     ```c
     23     drwav wav;
     24     if (!drwav_init_file(&wav, "my_song.wav", NULL)) {
     25         // Error opening WAV file.
     26     }
     27 
     28     drwav_int32* pDecodedInterleavedPCMFrames = malloc(wav.totalPCMFrameCount * wav.channels * sizeof(drwav_int32));
     29     size_t numberOfSamplesActuallyDecoded = drwav_read_pcm_frames_s32(&wav, wav.totalPCMFrameCount, pDecodedInterleavedPCMFrames);
     30 
     31     ...
     32 
     33     drwav_uninit(&wav);
     34     ```
     35 
     36 If you just want to quickly open and read the audio data in a single operation you can do something like this:
     37 
     38     ```c
     39     unsigned int channels;
     40     unsigned int sampleRate;
     41     drwav_uint64 totalPCMFrameCount;
     42     float* pSampleData = drwav_open_file_and_read_pcm_frames_f32("my_song.wav", &channels, &sampleRate, &totalPCMFrameCount, NULL);
     43     if (pSampleData == NULL) {
     44         // Error opening and reading WAV file.
     45     }
     46 
     47     ...
     48 
     49     drwav_free(pSampleData, NULL);
     50     ```
     51 
     52 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
     53 audio data in its internal format (see notes below for supported formats):
     54 
     55     ```c
     56     size_t framesRead = drwav_read_pcm_frames(&wav, wav.totalPCMFrameCount, pDecodedInterleavedPCMFrames);
     57     ```
     58 
     59 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:
     60 
     61     ```c
     62     size_t bytesRead = drwav_read_raw(&wav, bytesToRead, pRawDataBuffer);
     63     ```
     64 
     65 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()`,
     66 `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.
     67 
     68     ```c
     69     drwav_data_format format;
     70     format.container = drwav_container_riff;     // <-- drwav_container_riff = normal WAV files, drwav_container_w64 = Sony Wave64.
     71     format.format = DR_WAVE_FORMAT_PCM;          // <-- Any of the DR_WAVE_FORMAT_* codes.
     72     format.channels = 2;
     73     format.sampleRate = 44100;
     74     format.bitsPerSample = 16;
     75     drwav_init_file_write(&wav, "data/recording.wav", &format, NULL);
     76 
     77     ...
     78 
     79     drwav_uint64 framesWritten = drwav_write_pcm_frames(pWav, frameCount, pSamples);
     80     ```
     81 
     82 Note that writing to AIFF or RIFX is not supported.
     83 
     84 dr_wav has support for decoding from a number of different encapsulation formats. See below for details.
     85 
     86 
     87 Build Options
     88 =============
     89 #define these options before including this file.
     90 
     91 #define DR_WAV_NO_CONVERSION_API
     92   Disables conversion APIs such as `drwav_read_pcm_frames_f32()` and `drwav_s16_to_f32()`.
     93 
     94 #define DR_WAV_NO_STDIO
     95   Disables APIs that initialize a decoder from a file such as `drwav_init_file()`, `drwav_init_file_write()`, etc.
     96 
     97 #define DR_WAV_NO_WCHAR
     98   Disables all functions ending with `_w`. Use this if your compiler does not provide wchar.h. Not required if DR_WAV_NO_STDIO is also defined.
     99 
    100 
    101 Supported Encapsulations
    102 ========================
    103 - RIFF (Regular WAV)
    104 - RIFX (Big-Endian)
    105 - AIFF (Does not currently support ADPCM)
    106 - RF64
    107 - W64
    108 
    109 Note that AIFF and RIFX do not support write mode, nor do they support reading of metadata.
    110 
    111 
    112 Supported Encodings
    113 ===================
    114 - Unsigned 8-bit PCM
    115 - Signed 12-bit PCM
    116 - Signed 16-bit PCM
    117 - Signed 24-bit PCM
    118 - Signed 32-bit PCM
    119 - IEEE 32-bit floating point
    120 - IEEE 64-bit floating point
    121 - A-law and u-law
    122 - Microsoft ADPCM
    123 - IMA ADPCM (DVI, format code 0x11)
    124 
    125 8-bit PCM encodings are always assumed to be unsigned. Signed 8-bit encoding can only be read with `drwav_read_raw()`.
    126 
    127 Note that ADPCM is not currently supported with AIFF. Contributions welcome.
    128 
    129 
    130 Notes
    131 =====
    132 - Samples are always interleaved.
    133 - 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()`
    134   to read and convert audio data to 32-bit floating point, signed 32-bit integer and signed 16-bit integer samples respectively.
    135 - dr_wav will try to read the WAV file as best it can, even if it's not strictly conformant to the WAV format.
    136 */
    137 
    138 #ifndef dr_wav_h
    139 #define dr_wav_h
    140 
    141 #ifdef __cplusplus
    142 extern "C" {
    143 #endif
    144 
    145 #define DRWAV_STRINGIFY(x)      #x
    146 #define DRWAV_XSTRINGIFY(x)     DRWAV_STRINGIFY(x)
    147 
    148 #define DRWAV_VERSION_MAJOR     0
    149 #define DRWAV_VERSION_MINOR     13
    150 #define DRWAV_VERSION_REVISION  16
    151 #define DRWAV_VERSION_STRING    DRWAV_XSTRINGIFY(DRWAV_VERSION_MAJOR) "." DRWAV_XSTRINGIFY(DRWAV_VERSION_MINOR) "." DRWAV_XSTRINGIFY(DRWAV_VERSION_REVISION)
    152 
    153 #include <stddef.h> /* For size_t. */
    154 
    155 /* Sized Types */
    156 typedef   signed char           drwav_int8;
    157 typedef unsigned char           drwav_uint8;
    158 typedef   signed short          drwav_int16;
    159 typedef unsigned short          drwav_uint16;
    160 typedef   signed int            drwav_int32;
    161 typedef unsigned int            drwav_uint32;
    162 #if defined(_MSC_VER) && !defined(__clang__)
    163     typedef   signed __int64    drwav_int64;
    164     typedef unsigned __int64    drwav_uint64;
    165 #else
    166     #if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))
    167         #pragma GCC diagnostic push
    168         #pragma GCC diagnostic ignored "-Wlong-long"
    169         #if defined(__clang__)
    170             #pragma GCC diagnostic ignored "-Wc++11-long-long"
    171         #endif
    172     #endif
    173     typedef   signed long long  drwav_int64;
    174     typedef unsigned long long  drwav_uint64;
    175     #if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))
    176         #pragma GCC diagnostic pop
    177     #endif
    178 #endif
    179 #if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__)) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(_M_ARM64) || defined(__powerpc64__)
    180     typedef drwav_uint64        drwav_uintptr;
    181 #else
    182     typedef drwav_uint32        drwav_uintptr;
    183 #endif
    184 typedef drwav_uint8             drwav_bool8;
    185 typedef drwav_uint32            drwav_bool32;
    186 #define DRWAV_TRUE              1
    187 #define DRWAV_FALSE             0
    188 /* End Sized Types */
    189 
    190 /* Decorations */
    191 #if !defined(DRWAV_API)
    192     #if defined(DRWAV_DLL)
    193         #if defined(_WIN32)
    194             #define DRWAV_DLL_IMPORT  __declspec(dllimport)
    195             #define DRWAV_DLL_EXPORT  __declspec(dllexport)
    196             #define DRWAV_DLL_PRIVATE static
    197         #else
    198             #if defined(__GNUC__) && __GNUC__ >= 4
    199                 #define DRWAV_DLL_IMPORT  __attribute__((visibility("default")))
    200                 #define DRWAV_DLL_EXPORT  __attribute__((visibility("default")))
    201                 #define DRWAV_DLL_PRIVATE __attribute__((visibility("hidden")))
    202             #else
    203                 #define DRWAV_DLL_IMPORT
    204                 #define DRWAV_DLL_EXPORT
    205                 #define DRWAV_DLL_PRIVATE static
    206             #endif
    207         #endif
    208 
    209         #if defined(DR_WAV_IMPLEMENTATION) || defined(DRWAV_IMPLEMENTATION)
    210             #define DRWAV_API  DRWAV_DLL_EXPORT
    211         #else
    212             #define DRWAV_API  DRWAV_DLL_IMPORT
    213         #endif
    214         #define DRWAV_PRIVATE DRWAV_DLL_PRIVATE
    215     #else
    216         #define DRWAV_API extern
    217         #define DRWAV_PRIVATE static
    218     #endif
    219 #endif
    220 /* End Decorations */
    221 
    222 /* Result Codes */
    223 typedef drwav_int32 drwav_result;
    224 #define DRWAV_SUCCESS                        0
    225 #define DRWAV_ERROR                         -1   /* A generic error. */
    226 #define DRWAV_INVALID_ARGS                  -2
    227 #define DRWAV_INVALID_OPERATION             -3
    228 #define DRWAV_OUT_OF_MEMORY                 -4
    229 #define DRWAV_OUT_OF_RANGE                  -5
    230 #define DRWAV_ACCESS_DENIED                 -6
    231 #define DRWAV_DOES_NOT_EXIST                -7
    232 #define DRWAV_ALREADY_EXISTS                -8
    233 #define DRWAV_TOO_MANY_OPEN_FILES           -9
    234 #define DRWAV_INVALID_FILE                  -10
    235 #define DRWAV_TOO_BIG                       -11
    236 #define DRWAV_PATH_TOO_LONG                 -12
    237 #define DRWAV_NAME_TOO_LONG                 -13
    238 #define DRWAV_NOT_DIRECTORY                 -14
    239 #define DRWAV_IS_DIRECTORY                  -15
    240 #define DRWAV_DIRECTORY_NOT_EMPTY           -16
    241 #define DRWAV_END_OF_FILE                   -17
    242 #define DRWAV_NO_SPACE                      -18
    243 #define DRWAV_BUSY                          -19
    244 #define DRWAV_IO_ERROR                      -20
    245 #define DRWAV_INTERRUPT                     -21
    246 #define DRWAV_UNAVAILABLE                   -22
    247 #define DRWAV_ALREADY_IN_USE                -23
    248 #define DRWAV_BAD_ADDRESS                   -24
    249 #define DRWAV_BAD_SEEK                      -25
    250 #define DRWAV_BAD_PIPE                      -26
    251 #define DRWAV_DEADLOCK                      -27
    252 #define DRWAV_TOO_MANY_LINKS                -28
    253 #define DRWAV_NOT_IMPLEMENTED               -29
    254 #define DRWAV_NO_MESSAGE                    -30
    255 #define DRWAV_BAD_MESSAGE                   -31
    256 #define DRWAV_NO_DATA_AVAILABLE             -32
    257 #define DRWAV_INVALID_DATA                  -33
    258 #define DRWAV_TIMEOUT                       -34
    259 #define DRWAV_NO_NETWORK                    -35
    260 #define DRWAV_NOT_UNIQUE                    -36
    261 #define DRWAV_NOT_SOCKET                    -37
    262 #define DRWAV_NO_ADDRESS                    -38
    263 #define DRWAV_BAD_PROTOCOL                  -39
    264 #define DRWAV_PROTOCOL_UNAVAILABLE          -40
    265 #define DRWAV_PROTOCOL_NOT_SUPPORTED        -41
    266 #define DRWAV_PROTOCOL_FAMILY_NOT_SUPPORTED -42
    267 #define DRWAV_ADDRESS_FAMILY_NOT_SUPPORTED  -43
    268 #define DRWAV_SOCKET_NOT_SUPPORTED          -44
    269 #define DRWAV_CONNECTION_RESET              -45
    270 #define DRWAV_ALREADY_CONNECTED             -46
    271 #define DRWAV_NOT_CONNECTED                 -47
    272 #define DRWAV_CONNECTION_REFUSED            -48
    273 #define DRWAV_NO_HOST                       -49
    274 #define DRWAV_IN_PROGRESS                   -50
    275 #define DRWAV_CANCELLED                     -51
    276 #define DRWAV_MEMORY_ALREADY_MAPPED         -52
    277 #define DRWAV_AT_END                        -53
    278 /* End Result Codes */
    279 
    280 /* Common data formats. */
    281 #define DR_WAVE_FORMAT_PCM          0x1
    282 #define DR_WAVE_FORMAT_ADPCM        0x2
    283 #define DR_WAVE_FORMAT_IEEE_FLOAT   0x3
    284 #define DR_WAVE_FORMAT_ALAW         0x6
    285 #define DR_WAVE_FORMAT_MULAW        0x7
    286 #define DR_WAVE_FORMAT_DVI_ADPCM    0x11
    287 #define DR_WAVE_FORMAT_EXTENSIBLE   0xFFFE
    288 
    289 /* Flags to pass into drwav_init_ex(), etc. */
    290 #define DRWAV_SEQUENTIAL            0x00000001
    291 #define DRWAV_WITH_METADATA         0x00000002
    292 
    293 DRWAV_API void drwav_version(drwav_uint32* pMajor, drwav_uint32* pMinor, drwav_uint32* pRevision);
    294 DRWAV_API const char* drwav_version_string(void);
    295 
    296 /* Allocation Callbacks */
    297 typedef struct
    298 {
    299     void* pUserData;
    300     void* (* onMalloc)(size_t sz, void* pUserData);
    301     void* (* onRealloc)(void* p, size_t sz, void* pUserData);
    302     void  (* onFree)(void* p, void* pUserData);
    303 } drwav_allocation_callbacks;
    304 /* End Allocation Callbacks */
    305 
    306 typedef enum
    307 {
    308     drwav_seek_origin_start,
    309     drwav_seek_origin_current
    310 } drwav_seek_origin;
    311 
    312 typedef enum
    313 {
    314     drwav_container_riff,
    315     drwav_container_rifx,
    316     drwav_container_w64,
    317     drwav_container_rf64,
    318     drwav_container_aiff
    319 } drwav_container;
    320 
    321 typedef struct
    322 {
    323     union
    324     {
    325         drwav_uint8 fourcc[4];
    326         drwav_uint8 guid[16];
    327     } id;
    328 
    329     /* The size in bytes of the chunk. */
    330     drwav_uint64 sizeInBytes;
    331 
    332     /*
    333     RIFF = 2 byte alignment.
    334     W64  = 8 byte alignment.
    335     */
    336     unsigned int paddingSize;
    337 } drwav_chunk_header;
    338 
    339 typedef struct
    340 {
    341     /*
    342     The format tag exactly as specified in the wave file's "fmt" chunk. This can be used by applications
    343     that require support for data formats not natively supported by dr_wav.
    344     */
    345     drwav_uint16 formatTag;
    346 
    347     /* The number of channels making up the audio data. When this is set to 1 it is mono, 2 is stereo, etc. */
    348     drwav_uint16 channels;
    349 
    350     /* The sample rate. Usually set to something like 44100. */
    351     drwav_uint32 sampleRate;
    352 
    353     /* Average bytes per second. You probably don't need this, but it's left here for informational purposes. */
    354     drwav_uint32 avgBytesPerSec;
    355 
    356     /* Block align. This is equal to the number of channels * bytes per sample. */
    357     drwav_uint16 blockAlign;
    358 
    359     /* Bits per sample. */
    360     drwav_uint16 bitsPerSample;
    361 
    362     /* The size of the extended data. Only used internally for validation, but left here for informational purposes. */
    363     drwav_uint16 extendedSize;
    364 
    365     /*
    366     The number of valid bits per sample. When <formatTag> is equal to WAVE_FORMAT_EXTENSIBLE, <bitsPerSample>
    367     is always rounded up to the nearest multiple of 8. This variable contains information about exactly how
    368     many bits are valid per sample. Mainly used for informational purposes.
    369     */
    370     drwav_uint16 validBitsPerSample;
    371 
    372     /* The channel mask. Not used at the moment. */
    373     drwav_uint32 channelMask;
    374 
    375     /* The sub-format, exactly as specified by the wave file. */
    376     drwav_uint8 subFormat[16];
    377 } drwav_fmt;
    378 
    379 DRWAV_API drwav_uint16 drwav_fmt_get_format(const drwav_fmt* pFMT);
    380 
    381 
    382 /*
    383 Callback for when data is read. Return value is the number of bytes actually read.
    384 
    385 pUserData   [in]  The user data that was passed to drwav_init() and family.
    386 pBufferOut  [out] The output buffer.
    387 bytesToRead [in]  The number of bytes to read.
    388 
    389 Returns the number of bytes actually read.
    390 
    391 A return value of less than bytesToRead indicates the end of the stream. Do _not_ return from this callback until
    392 either the entire bytesToRead is filled or you have reached the end of the stream.
    393 */
    394 typedef size_t (* drwav_read_proc)(void* pUserData, void* pBufferOut, size_t bytesToRead);
    395 
    396 /*
    397 Callback for when data is written. Returns value is the number of bytes actually written.
    398 
    399 pUserData    [in]  The user data that was passed to drwav_init_write() and family.
    400 pData        [out] A pointer to the data to write.
    401 bytesToWrite [in]  The number of bytes to write.
    402 
    403 Returns the number of bytes actually written.
    404 
    405 If the return value differs from bytesToWrite, it indicates an error.
    406 */
    407 typedef size_t (* drwav_write_proc)(void* pUserData, const void* pData, size_t bytesToWrite);
    408 
    409 /*
    410 Callback for when data needs to be seeked.
    411 
    412 pUserData [in] The user data that was passed to drwav_init() and family.
    413 offset    [in] The number of bytes to move, relative to the origin. Will never be negative.
    414 origin    [in] The origin of the seek - the current position or the start of the stream.
    415 
    416 Returns whether or not the seek was successful.
    417 
    418 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
    419 drwav_seek_origin_current.
    420 */
    421 typedef drwav_bool32 (* drwav_seek_proc)(void* pUserData, int offset, drwav_seek_origin origin);
    422 
    423 /*
    424 Callback for when drwav_init_ex() finds a chunk.
    425 
    426 pChunkUserData    [in] The user data that was passed to the pChunkUserData parameter of drwav_init_ex() and family.
    427 onRead            [in] A pointer to the function to call when reading.
    428 onSeek            [in] A pointer to the function to call when seeking.
    429 pReadSeekUserData [in] The user data that was passed to the pReadSeekUserData parameter of drwav_init_ex() and family.
    430 pChunkHeader      [in] A pointer to an object containing basic header information about the chunk. Use this to identify the chunk.
    431 container         [in] Whether or not the WAV file is a RIFF or Wave64 container. If you're unsure of the difference, assume RIFF.
    432 pFMT              [in] A pointer to the object containing the contents of the "fmt" chunk.
    433 
    434 Returns the number of bytes read + seeked.
    435 
    436 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
    437 be the total number of bytes you have read _plus_ seeked.
    438 
    439 Use the `container` argument to discriminate the fields in `pChunkHeader->id`. If the container is `drwav_container_riff` or `drwav_container_rf64` you should
    440 use `id.fourcc`, otherwise you should use `id.guid`.
    441 
    442 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
    443 `DR_WAVE_FORMAT_*` identifiers.
    444 
    445 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.
    446 */
    447 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);
    448 
    449 
    450 /* Structure for internal use. Only used for loaders opened with drwav_init_memory(). */
    451 typedef struct
    452 {
    453     const drwav_uint8* data;
    454     size_t dataSize;
    455     size_t currentReadPos;
    456 } drwav__memory_stream;
    457 
    458 /* Structure for internal use. Only used for writers opened with drwav_init_memory_write(). */
    459 typedef struct
    460 {
    461     void** ppData;
    462     size_t* pDataSize;
    463     size_t dataSize;
    464     size_t dataCapacity;
    465     size_t currentWritePos;
    466 } drwav__memory_stream_write;
    467 
    468 typedef struct
    469 {
    470     drwav_container container;  /* RIFF, W64. */
    471     drwav_uint32 format;        /* DR_WAVE_FORMAT_* */
    472     drwav_uint32 channels;
    473     drwav_uint32 sampleRate;
    474     drwav_uint32 bitsPerSample;
    475 } drwav_data_format;
    476 
    477 typedef enum
    478 {
    479     drwav_metadata_type_none                        = 0,
    480 
    481     /*
    482     Unknown simply means a chunk that drwav does not handle specifically. You can still ask to
    483     receive these chunks as metadata objects. It is then up to you to interpret the chunk's data.
    484     You can also write unknown metadata to a wav file. Be careful writing unknown chunks if you
    485     have also edited the audio data. The unknown chunks could represent offsets/sizes that no
    486     longer correctly correspond to the audio data.
    487     */
    488     drwav_metadata_type_unknown                     = 1 << 0,
    489 
    490     /* Only 1 of each of these metadata items are allowed in a wav file. */
    491     drwav_metadata_type_smpl                        = 1 << 1,
    492     drwav_metadata_type_inst                        = 1 << 2,
    493     drwav_metadata_type_cue                         = 1 << 3,
    494     drwav_metadata_type_acid                        = 1 << 4,
    495     drwav_metadata_type_bext                        = 1 << 5,
    496 
    497     /*
    498     Wav files often have a LIST chunk. This is a chunk that contains a set of subchunks. For this
    499     higher-level metadata API, we don't make a distinction between a regular chunk and a LIST
    500     subchunk. Instead, they are all just 'metadata' items.
    501 
    502     There can be multiple of these metadata items in a wav file.
    503     */
    504     drwav_metadata_type_list_label                  = 1 << 6,
    505     drwav_metadata_type_list_note                   = 1 << 7,
    506     drwav_metadata_type_list_labelled_cue_region    = 1 << 8,
    507 
    508     drwav_metadata_type_list_info_software          = 1 << 9,
    509     drwav_metadata_type_list_info_copyright         = 1 << 10,
    510     drwav_metadata_type_list_info_title             = 1 << 11,
    511     drwav_metadata_type_list_info_artist            = 1 << 12,
    512     drwav_metadata_type_list_info_comment           = 1 << 13,
    513     drwav_metadata_type_list_info_date              = 1 << 14,
    514     drwav_metadata_type_list_info_genre             = 1 << 15,
    515     drwav_metadata_type_list_info_album             = 1 << 16,
    516     drwav_metadata_type_list_info_tracknumber       = 1 << 17,
    517 
    518     /* Other type constants for convenience. */
    519     drwav_metadata_type_list_all_info_strings       = drwav_metadata_type_list_info_software
    520                                                     | drwav_metadata_type_list_info_copyright
    521                                                     | drwav_metadata_type_list_info_title
    522                                                     | drwav_metadata_type_list_info_artist
    523                                                     | drwav_metadata_type_list_info_comment
    524                                                     | drwav_metadata_type_list_info_date
    525                                                     | drwav_metadata_type_list_info_genre
    526                                                     | drwav_metadata_type_list_info_album
    527                                                     | drwav_metadata_type_list_info_tracknumber,
    528 
    529     drwav_metadata_type_list_all_adtl               = drwav_metadata_type_list_label
    530                                                     | drwav_metadata_type_list_note
    531                                                     | drwav_metadata_type_list_labelled_cue_region,
    532 
    533     drwav_metadata_type_all                         = -2,   /*0xFFFFFFFF & ~drwav_metadata_type_unknown,*/
    534     drwav_metadata_type_all_including_unknown       = -1    /*0xFFFFFFFF,*/
    535 } drwav_metadata_type;
    536 
    537 /*
    538 Sampler Metadata
    539 
    540 The sampler chunk contains information about how a sound should be played in the context of a whole
    541 audio production, and when used in a sampler. See https://en.wikipedia.org/wiki/Sample-based_synthesis.
    542 */
    543 typedef enum
    544 {
    545     drwav_smpl_loop_type_forward  = 0,
    546     drwav_smpl_loop_type_pingpong = 1,
    547     drwav_smpl_loop_type_backward = 2
    548 } drwav_smpl_loop_type;
    549 
    550 typedef struct
    551 {
    552     /* The ID of the associated cue point, see drwav_cue and drwav_cue_point. As with all cue point IDs, this can correspond to a label chunk to give this loop a name, see drwav_list_label_or_note. */
    553     drwav_uint32 cuePointId;
    554 
    555     /* See drwav_smpl_loop_type. */
    556     drwav_uint32 type;
    557 
    558     /* The byte offset of the first sample to be played in the loop. */
    559     drwav_uint32 firstSampleByteOffset;
    560 
    561     /* The byte offset into the audio data of the last sample to be played in the loop. */
    562     drwav_uint32 lastSampleByteOffset;
    563 
    564     /* A value to represent that playback should occur at a point between samples. This value ranges from 0 to UINT32_MAX. Where a value of 0 means no fraction, and a value of (UINT32_MAX / 2) would mean half a sample. */
    565     drwav_uint32 sampleFraction;
    566 
    567     /* Number of times to play the loop. 0 means loop infinitely. */
    568     drwav_uint32 playCount;
    569 } drwav_smpl_loop;
    570 
    571 typedef struct
    572 {
    573     /* IDs for a particular MIDI manufacturer. 0 if not used. */
    574     drwav_uint32 manufacturerId;
    575     drwav_uint32 productId;
    576 
    577     /* The period of 1 sample in nanoseconds. */
    578     drwav_uint32 samplePeriodNanoseconds;
    579 
    580     /* The MIDI root note of this file. 0 to 127. */
    581     drwav_uint32 midiUnityNote;
    582 
    583     /* The fraction of a semitone up from the given MIDI note. This is a value from 0 to UINT32_MAX, where 0 means no change and (UINT32_MAX / 2) is half a semitone (AKA 50 cents). */
    584     drwav_uint32 midiPitchFraction;
    585 
    586     /* Data relating to SMPTE standards which are used for syncing audio and video. 0 if not used. */
    587     drwav_uint32 smpteFormat;
    588     drwav_uint32 smpteOffset;
    589 
    590     /* drwav_smpl_loop loops. */
    591     drwav_uint32 sampleLoopCount;
    592 
    593     /* Optional sampler-specific data. */
    594     drwav_uint32 samplerSpecificDataSizeInBytes;
    595 
    596     drwav_smpl_loop* pLoops;
    597     drwav_uint8* pSamplerSpecificData;
    598 } drwav_smpl;
    599 
    600 /*
    601 Instrument Metadata
    602 
    603 The inst metadata contains data about how a sound should be played as part of an instrument. This
    604 commonly read by samplers. See https://en.wikipedia.org/wiki/Sample-based_synthesis.
    605 */
    606 typedef struct
    607 {
    608     drwav_int8 midiUnityNote;   /* The root note of the audio as a MIDI note number. 0 to 127. */
    609     drwav_int8 fineTuneCents;   /* -50 to +50 */
    610     drwav_int8 gainDecibels;    /* -64 to +64 */
    611     drwav_int8 lowNote;         /* 0 to 127 */
    612     drwav_int8 highNote;        /* 0 to 127 */
    613     drwav_int8 lowVelocity;     /* 1 to 127 */
    614     drwav_int8 highVelocity;    /* 1 to 127 */
    615 } drwav_inst;
    616 
    617 /*
    618 Cue Metadata
    619 
    620 Cue points are markers at specific points in the audio. They often come with an associated piece of
    621 drwav_list_label_or_note metadata which contains the text for the marker.
    622 */
    623 typedef struct
    624 {
    625     /* Unique identification value. */
    626     drwav_uint32 id;
    627 
    628     /* Set to 0. This is only relevant if there is a 'playlist' chunk - which is not supported by dr_wav. */
    629     drwav_uint32 playOrderPosition;
    630 
    631     /* Should always be "data". This represents the fourcc value of the chunk that this cue point corresponds to. dr_wav only supports a single data chunk so this should always be "data". */
    632     drwav_uint8 dataChunkId[4];
    633 
    634     /* Set to 0. This is only relevant if there is a wave list chunk. dr_wav, like lots of readers/writers, do not support this. */
    635     drwav_uint32 chunkStart;
    636 
    637     /* Set to 0 for uncompressed formats. Else the last byte in compressed wave data where decompression can begin to find the value of the corresponding sample value. */
    638     drwav_uint32 blockStart;
    639 
    640     /* For uncompressed formats this is the byte offset of the cue point into the audio data. For compressed formats this is relative to the block specified with blockStart. */
    641     drwav_uint32 sampleByteOffset;
    642 } drwav_cue_point;
    643 
    644 typedef struct
    645 {
    646     drwav_uint32 cuePointCount;
    647     drwav_cue_point *pCuePoints;
    648 } drwav_cue;
    649 
    650 /*
    651 Acid Metadata
    652 
    653 This chunk contains some information about the time signature and the tempo of the audio.
    654 */
    655 typedef enum
    656 {
    657     drwav_acid_flag_one_shot      = 1,  /* If this is not set, then it is a loop instead of a one-shot. */
    658     drwav_acid_flag_root_note_set = 2,
    659     drwav_acid_flag_stretch       = 4,
    660     drwav_acid_flag_disk_based    = 8,
    661     drwav_acid_flag_acidizer      = 16  /* Not sure what this means. */
    662 } drwav_acid_flag;
    663 
    664 typedef struct
    665 {
    666     /* A bit-field, see drwav_acid_flag. */
    667     drwav_uint32 flags;
    668 
    669     /* Valid if flags contains drwav_acid_flag_root_note_set. It represents the MIDI root note the file - a value from 0 to 127. */
    670     drwav_uint16 midiUnityNote;
    671 
    672     /* Reserved values that should probably be ignored. reserved1 seems to often be 128 and reserved2 is 0. */
    673     drwav_uint16 reserved1;
    674     float reserved2;
    675 
    676     /* Number of beats. */
    677     drwav_uint32 numBeats;
    678 
    679     /* The time signature of the audio. */
    680     drwav_uint16 meterDenominator;
    681     drwav_uint16 meterNumerator;
    682 
    683     /* Beats per minute of the track. Setting a value of 0 suggests that there is no tempo. */
    684     float tempo;
    685 } drwav_acid;
    686 
    687 /*
    688 Cue Label or Note metadata
    689 
    690 These are 2 different types of metadata, but they have the exact same format. Labels tend to be the
    691 more common and represent a short name for a cue point. Notes might be used to represent a longer
    692 comment.
    693 */
    694 typedef struct
    695 {
    696     /* The ID of a cue point that this label or note corresponds to. */
    697     drwav_uint32 cuePointId;
    698 
    699     /* Size of the string not including any null terminator. */
    700     drwav_uint32 stringLength;
    701 
    702     /* The string. The *init_with_metadata functions null terminate this for convenience. */
    703     char* pString;
    704 } drwav_list_label_or_note;
    705 
    706 /*
    707 BEXT metadata, also known as Broadcast Wave Format (BWF)
    708 
    709 This metadata adds some extra description to an audio file. You must check the version field to
    710 determine if the UMID or the loudness fields are valid.
    711 */
    712 typedef struct
    713 {
    714     /*
    715     These top 3 fields, and the umid field are actually defined in the standard as a statically
    716     sized buffers. In order to reduce the size of this struct (and therefore the union in the
    717     metadata struct), we instead store these as pointers.
    718     */
    719     char* pDescription;                 /* Can be NULL or a null-terminated string, must be <= 256 characters. */
    720     char* pOriginatorName;              /* Can be NULL or a null-terminated string, must be <= 32 characters. */
    721     char* pOriginatorReference;         /* Can be NULL or a null-terminated string, must be <= 32 characters. */
    722     char  pOriginationDate[10];         /* ASCII "yyyy:mm:dd". */
    723     char  pOriginationTime[8];          /* ASCII "hh:mm:ss". */
    724     drwav_uint64 timeReference;         /* First sample count since midnight. */
    725     drwav_uint16 version;               /* Version of the BWF, check this to see if the fields below are valid. */
    726 
    727     /*
    728     Unrestricted ASCII characters containing a collection of strings terminated by CR/LF. Each
    729     string shall contain a description of a coding process applied to the audio data.
    730     */
    731     char* pCodingHistory;
    732     drwav_uint32 codingHistorySize;
    733 
    734     /* Fields below this point are only valid if the version is 1 or above. */
    735     drwav_uint8* pUMID;                  /* Exactly 64 bytes of SMPTE UMID */
    736 
    737     /* Fields below this point are only valid if the version is 2 or above. */
    738     drwav_uint16 loudnessValue;         /* Integrated Loudness Value of the file in LUFS (multiplied by 100). */
    739     drwav_uint16 loudnessRange;         /* Loudness Range of the file in LU (multiplied by 100). */
    740     drwav_uint16 maxTruePeakLevel;      /* Maximum True Peak Level of the file expressed as dBTP (multiplied by 100). */
    741     drwav_uint16 maxMomentaryLoudness;  /* Highest value of the Momentary Loudness Level of the file in LUFS (multiplied by 100). */
    742     drwav_uint16 maxShortTermLoudness;  /* Highest value of the Short-Term Loudness Level of the file in LUFS (multiplied by 100). */
    743 } drwav_bext;
    744 
    745 /*
    746 Info Text Metadata
    747 
    748 There a many different types of information text that can be saved in this format. This is where
    749 things like the album name, the artists, the year it was produced, etc are saved. See
    750 drwav_metadata_type for the full list of types that dr_wav supports.
    751 */
    752 typedef struct
    753 {
    754     /* Size of the string not including any null terminator. */
    755     drwav_uint32 stringLength;
    756 
    757     /* The string. The *init_with_metadata functions null terminate this for convenience. */
    758     char* pString;
    759 } drwav_list_info_text;
    760 
    761 /*
    762 Labelled Cue Region Metadata
    763 
    764 The labelled cue region metadata is used to associate some region of audio with text. The region
    765 starts at a cue point, and extends for the given number of samples.
    766 */
    767 typedef struct
    768 {
    769     /* The ID of a cue point that this object corresponds to. */
    770     drwav_uint32 cuePointId;
    771 
    772     /* The number of samples from the cue point forwards that should be considered this region */
    773     drwav_uint32 sampleLength;
    774 
    775     /* Four characters used to say what the purpose of this region is. */
    776     drwav_uint8 purposeId[4];
    777 
    778     /* Unsure of the exact meanings of these. It appears to be acceptable to set them all to 0. */
    779     drwav_uint16 country;
    780     drwav_uint16 language;
    781     drwav_uint16 dialect;
    782     drwav_uint16 codePage;
    783 
    784     /* Size of the string not including any null terminator. */
    785     drwav_uint32 stringLength;
    786 
    787     /* The string. The *init_with_metadata functions null terminate this for convenience. */
    788     char* pString;
    789 } drwav_list_labelled_cue_region;
    790 
    791 /*
    792 Unknown Metadata
    793 
    794 This chunk just represents a type of chunk that dr_wav does not understand.
    795 
    796 Unknown metadata has a location attached to it. This is because wav files can have a LIST chunk
    797 that contains subchunks. These LIST chunks can be one of two types. An adtl list, or an INFO
    798 list. This enum is used to specify the location of a chunk that dr_wav currently doesn't support.
    799 */
    800 typedef enum
    801 {
    802     drwav_metadata_location_invalid,
    803     drwav_metadata_location_top_level,
    804     drwav_metadata_location_inside_info_list,
    805     drwav_metadata_location_inside_adtl_list
    806 } drwav_metadata_location;
    807 
    808 typedef struct
    809 {
    810     drwav_uint8 id[4];
    811     drwav_metadata_location chunkLocation;
    812     drwav_uint32 dataSizeInBytes;
    813     drwav_uint8* pData;
    814 } drwav_unknown_metadata;
    815 
    816 /*
    817 Metadata is saved as a union of all the supported types.
    818 */
    819 typedef struct
    820 {
    821     /* Determines which item in the union is valid. */
    822     drwav_metadata_type type;
    823 
    824     union
    825     {
    826         drwav_cue cue;
    827         drwav_smpl smpl;
    828         drwav_acid acid;
    829         drwav_inst inst;
    830         drwav_bext bext;
    831         drwav_list_label_or_note labelOrNote;   /* List label or list note. */
    832         drwav_list_labelled_cue_region labelledCueRegion;
    833         drwav_list_info_text infoText;          /* Any of the list info types. */
    834         drwav_unknown_metadata unknown;
    835     } data;
    836 } drwav_metadata;
    837 
    838 typedef struct
    839 {
    840     /* A pointer to the function to call when more data is needed. */
    841     drwav_read_proc onRead;
    842 
    843     /* A pointer to the function to call when data needs to be written. Only used when the drwav object is opened in write mode. */
    844     drwav_write_proc onWrite;
    845 
    846     /* A pointer to the function to call when the wav file needs to be seeked. */
    847     drwav_seek_proc onSeek;
    848 
    849     /* The user data to pass to callbacks. */
    850     void* pUserData;
    851 
    852     /* Allocation callbacks. */
    853     drwav_allocation_callbacks allocationCallbacks;
    854 
    855 
    856     /* Whether or not the WAV file is formatted as a standard RIFF file or W64. */
    857     drwav_container container;
    858 
    859 
    860     /* Structure containing format information exactly as specified by the wav file. */
    861     drwav_fmt fmt;
    862 
    863     /* The sample rate. Will be set to something like 44100. */
    864     drwav_uint32 sampleRate;
    865 
    866     /* The number of channels. This will be set to 1 for monaural streams, 2 for stereo, etc. */
    867     drwav_uint16 channels;
    868 
    869     /* The bits per sample. Will be set to something like 16, 24, etc. */
    870     drwav_uint16 bitsPerSample;
    871 
    872     /* Equal to fmt.formatTag, or the value specified by fmt.subFormat if fmt.formatTag is equal to 65534 (WAVE_FORMAT_EXTENSIBLE). */
    873     drwav_uint16 translatedFormatTag;
    874 
    875     /* The total number of PCM frames making up the audio data. */
    876     drwav_uint64 totalPCMFrameCount;
    877 
    878 
    879     /* The size in bytes of the data chunk. */
    880     drwav_uint64 dataChunkDataSize;
    881 
    882     /* The position in the stream of the first data byte of the data chunk. This is used for seeking. */
    883     drwav_uint64 dataChunkDataPos;
    884 
    885     /* The number of bytes remaining in the data chunk. */
    886     drwav_uint64 bytesRemaining;
    887 
    888     /* The current read position in PCM frames. */
    889     drwav_uint64 readCursorInPCMFrames;
    890 
    891 
    892     /*
    893     Only used in sequential write mode. Keeps track of the desired size of the "data" chunk at the point of initialization time. Always
    894     set to 0 for non-sequential writes and when the drwav object is opened in read mode. Used for validation.
    895     */
    896     drwav_uint64 dataChunkDataSizeTargetWrite;
    897 
    898     /* Keeps track of whether or not the wav writer was initialized in sequential mode. */
    899     drwav_bool32 isSequentialWrite;
    900 
    901 
    902     /* A array of metadata. This is valid after the *init_with_metadata call returns. It will be valid until drwav_uninit() is called. You can take ownership of this data with drwav_take_ownership_of_metadata(). */
    903     drwav_metadata* pMetadata;
    904     drwav_uint32 metadataCount;
    905 
    906 
    907     /* A hack to avoid a DRWAV_MALLOC() when opening a decoder with drwav_init_memory(). */
    908     drwav__memory_stream memoryStream;
    909     drwav__memory_stream_write memoryStreamWrite;
    910 
    911 
    912     /* Microsoft ADPCM specific data. */
    913     struct
    914     {
    915         drwav_uint32 bytesRemainingInBlock;
    916         drwav_uint16 predictor[2];
    917         drwav_int32  delta[2];
    918         drwav_int32  cachedFrames[4];  /* Samples are stored in this cache during decoding. */
    919         drwav_uint32 cachedFrameCount;
    920         drwav_int32  prevFrames[2][2]; /* The previous 2 samples for each channel (2 channels at most). */
    921     } msadpcm;
    922 
    923     /* IMA ADPCM specific data. */
    924     struct
    925     {
    926         drwav_uint32 bytesRemainingInBlock;
    927         drwav_int32  predictor[2];
    928         drwav_int32  stepIndex[2];
    929         drwav_int32  cachedFrames[16]; /* Samples are stored in this cache during decoding. */
    930         drwav_uint32 cachedFrameCount;
    931     } ima;
    932 
    933     /* AIFF specific data. */
    934     struct
    935     {
    936         drwav_bool8 isLE;   /* Will be set to true if the audio data is little-endian encoded. */
    937         drwav_bool8 isUnsigned; /* Only used for 8-bit samples. When set to true, will be treated as unsigned. */
    938     } aiff;
    939 } drwav;
    940 
    941 
    942 /*
    943 Initializes a pre-allocated drwav object for reading.
    944 
    945 pWav                         [out]          A pointer to the drwav object being initialized.
    946 onRead                       [in]           The function to call when data needs to be read from the client.
    947 onSeek                       [in]           The function to call when the read position of the client data needs to move.
    948 onChunk                      [in, optional] The function to call when a chunk is enumerated at initialized time.
    949 pUserData, pReadSeekUserData [in, optional] A pointer to application defined data that will be passed to onRead and onSeek.
    950 pChunkUserData               [in, optional] A pointer to application defined data that will be passed to onChunk.
    951 flags                        [in, optional] A set of flags for controlling how things are loaded.
    952 
    953 Returns true if successful; false otherwise.
    954 
    955 Close the loader with drwav_uninit().
    956 
    957 This is the lowest level function for initializing a WAV file. You can also use drwav_init_file() and drwav_init_memory()
    958 to open the stream from a file or from a block of memory respectively.
    959 
    960 Possible values for flags:
    961   DRWAV_SEQUENTIAL: Never perform a backwards seek while loading. This disables the chunk callback and will cause this function
    962                     to return as soon as the data chunk is found. Any chunks after the data chunk will be ignored.
    963 
    964 drwav_init() is equivalent to "drwav_init_ex(pWav, onRead, onSeek, NULL, pUserData, NULL, 0);".
    965 
    966 The onChunk callback is not called for the WAVE or FMT chunks. The contents of the FMT chunk can be read from pWav->fmt
    967 after the function returns.
    968 
    969 See also: drwav_init_file(), drwav_init_memory(), drwav_uninit()
    970 */
    971 DRWAV_API drwav_bool32 drwav_init(drwav* pWav, drwav_read_proc onRead, drwav_seek_proc onSeek, void* pUserData, const drwav_allocation_callbacks* pAllocationCallbacks);
    972 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);
    973 DRWAV_API drwav_bool32 drwav_init_with_metadata(drwav* pWav, drwav_read_proc onRead, drwav_seek_proc onSeek, void* pUserData, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks);
    974 
    975 /*
    976 Initializes a pre-allocated drwav object for writing.
    977 
    978 onWrite               [in]           The function to call when data needs to be written.
    979 onSeek                [in]           The function to call when the write position needs to move.
    980 pUserData             [in, optional] A pointer to application defined data that will be passed to onWrite and onSeek.
    981 metadata, numMetadata [in, optional] An array of metadata objects that should be written to the file. The array is not edited. You are responsible for this metadata memory and it must maintain valid until drwav_uninit() is called.
    982 
    983 Returns true if successful; false otherwise.
    984 
    985 Close the writer with drwav_uninit().
    986 
    987 This is the lowest level function for initializing a WAV file. You can also use drwav_init_file_write() and drwav_init_memory_write()
    988 to open the stream from a file or from a block of memory respectively.
    989 
    990 If the total sample count is known, you can use drwav_init_write_sequential(). This avoids the need for dr_wav to perform
    991 a post-processing step for storing the total sample count and the size of the data chunk which requires a backwards seek.
    992 
    993 See also: drwav_init_file_write(), drwav_init_memory_write(), drwav_uninit()
    994 */
    995 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);
    996 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);
    997 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);
    998 DRWAV_API drwav_bool32 drwav_init_write_with_metadata(drwav* pWav, const drwav_data_format* pFormat, drwav_write_proc onWrite, drwav_seek_proc onSeek, void* pUserData, const drwav_allocation_callbacks* pAllocationCallbacks, drwav_metadata* pMetadata, drwav_uint32 metadataCount);
    999 
   1000 /*
   1001 Utility function to determine the target size of the entire data to be written (including all headers and chunks).
   1002 
   1003 Returns the target size in bytes.
   1004 
   1005 The metadata argument can be NULL meaning no metadata exists.
   1006 
   1007 Useful if the application needs to know the size to allocate.
   1008 
   1009 Only writing to the RIFF chunk and one data chunk is currently supported.
   1010 
   1011 See also: drwav_init_write(), drwav_init_file_write(), drwav_init_memory_write()
   1012 */
   1013 DRWAV_API drwav_uint64 drwav_target_write_size_bytes(const drwav_data_format* pFormat, drwav_uint64 totalFrameCount, drwav_metadata* pMetadata, drwav_uint32 metadataCount);
   1014 
   1015 /*
   1016 Take ownership of the metadata objects that were allocated via one of the init_with_metadata() function calls. The init_with_metdata functions perform a single heap allocation for this metadata.
   1017 
   1018 Useful if you want the data to persist beyond the lifetime of the drwav object.
   1019 
   1020 You must free the data returned from this function using drwav_free().
   1021 */
   1022 DRWAV_API drwav_metadata* drwav_take_ownership_of_metadata(drwav* pWav);
   1023 
   1024 /*
   1025 Uninitializes the given drwav object.
   1026 
   1027 Use this only for objects initialized with drwav_init*() functions (drwav_init(), drwav_init_ex(), drwav_init_write(), drwav_init_write_sequential()).
   1028 */
   1029 DRWAV_API drwav_result drwav_uninit(drwav* pWav);
   1030 
   1031 
   1032 /*
   1033 Reads raw audio data.
   1034 
   1035 This is the lowest level function for reading audio data. It simply reads the given number of
   1036 bytes of the raw internal sample data.
   1037 
   1038 Consider using drwav_read_pcm_frames_s16(), drwav_read_pcm_frames_s32() or drwav_read_pcm_frames_f32() for
   1039 reading sample data in a consistent format.
   1040 
   1041 pBufferOut can be NULL in which case a seek will be performed.
   1042 
   1043 Returns the number of bytes actually read.
   1044 */
   1045 DRWAV_API size_t drwav_read_raw(drwav* pWav, size_t bytesToRead, void* pBufferOut);
   1046 
   1047 /*
   1048 Reads up to the specified number of PCM frames from the WAV file.
   1049 
   1050 The output data will be in the file's internal format, converted to native-endian byte order. Use
   1051 drwav_read_pcm_frames_s16/f32/s32() to read data in a specific format.
   1052 
   1053 If the return value is less than <framesToRead> it means the end of the file has been reached or
   1054 you have requested more PCM frames than can possibly fit in the output buffer.
   1055 
   1056 This function will only work when sample data is of a fixed size and uncompressed. If you are
   1057 using a compressed format consider using drwav_read_raw() or drwav_read_pcm_frames_s16/s32/f32().
   1058 
   1059 pBufferOut can be NULL in which case a seek will be performed.
   1060 */
   1061 DRWAV_API drwav_uint64 drwav_read_pcm_frames(drwav* pWav, drwav_uint64 framesToRead, void* pBufferOut);
   1062 DRWAV_API drwav_uint64 drwav_read_pcm_frames_le(drwav* pWav, drwav_uint64 framesToRead, void* pBufferOut);
   1063 DRWAV_API drwav_uint64 drwav_read_pcm_frames_be(drwav* pWav, drwav_uint64 framesToRead, void* pBufferOut);
   1064 
   1065 /*
   1066 Seeks to the given PCM frame.
   1067 
   1068 Returns true if successful; false otherwise.
   1069 */
   1070 DRWAV_API drwav_bool32 drwav_seek_to_pcm_frame(drwav* pWav, drwav_uint64 targetFrameIndex);
   1071 
   1072 /*
   1073 Retrieves the current read position in pcm frames.
   1074 */
   1075 DRWAV_API drwav_result drwav_get_cursor_in_pcm_frames(drwav* pWav, drwav_uint64* pCursor);
   1076 
   1077 /*
   1078 Retrieves the length of the file.
   1079 */
   1080 DRWAV_API drwav_result drwav_get_length_in_pcm_frames(drwav* pWav, drwav_uint64* pLength);
   1081 
   1082 
   1083 /*
   1084 Writes raw audio data.
   1085 
   1086 Returns the number of bytes actually written. If this differs from bytesToWrite, it indicates an error.
   1087 */
   1088 DRWAV_API size_t drwav_write_raw(drwav* pWav, size_t bytesToWrite, const void* pData);
   1089 
   1090 /*
   1091 Writes PCM frames.
   1092 
   1093 Returns the number of PCM frames written.
   1094 
   1095 Input samples need to be in native-endian byte order. On big-endian architectures the input data will be converted to
   1096 little-endian. Use drwav_write_raw() to write raw audio data without performing any conversion.
   1097 */
   1098 DRWAV_API drwav_uint64 drwav_write_pcm_frames(drwav* pWav, drwav_uint64 framesToWrite, const void* pData);
   1099 DRWAV_API drwav_uint64 drwav_write_pcm_frames_le(drwav* pWav, drwav_uint64 framesToWrite, const void* pData);
   1100 DRWAV_API drwav_uint64 drwav_write_pcm_frames_be(drwav* pWav, drwav_uint64 framesToWrite, const void* pData);
   1101 
   1102 /* Conversion Utilities */
   1103 #ifndef DR_WAV_NO_CONVERSION_API
   1104 
   1105 /*
   1106 Reads a chunk of audio data and converts it to signed 16-bit PCM samples.
   1107 
   1108 pBufferOut can be NULL in which case a seek will be performed.
   1109 
   1110 Returns the number of PCM frames actually read.
   1111 
   1112 If the return value is less than <framesToRead> it means the end of the file has been reached.
   1113 */
   1114 DRWAV_API drwav_uint64 drwav_read_pcm_frames_s16(drwav* pWav, drwav_uint64 framesToRead, drwav_int16* pBufferOut);
   1115 DRWAV_API drwav_uint64 drwav_read_pcm_frames_s16le(drwav* pWav, drwav_uint64 framesToRead, drwav_int16* pBufferOut);
   1116 DRWAV_API drwav_uint64 drwav_read_pcm_frames_s16be(drwav* pWav, drwav_uint64 framesToRead, drwav_int16* pBufferOut);
   1117 
   1118 /* Low-level function for converting unsigned 8-bit PCM samples to signed 16-bit PCM samples. */
   1119 DRWAV_API void drwav_u8_to_s16(drwav_int16* pOut, const drwav_uint8* pIn, size_t sampleCount);
   1120 
   1121 /* Low-level function for converting signed 24-bit PCM samples to signed 16-bit PCM samples. */
   1122 DRWAV_API void drwav_s24_to_s16(drwav_int16* pOut, const drwav_uint8* pIn, size_t sampleCount);
   1123 
   1124 /* Low-level function for converting signed 32-bit PCM samples to signed 16-bit PCM samples. */
   1125 DRWAV_API void drwav_s32_to_s16(drwav_int16* pOut, const drwav_int32* pIn, size_t sampleCount);
   1126 
   1127 /* Low-level function for converting IEEE 32-bit floating point samples to signed 16-bit PCM samples. */
   1128 DRWAV_API void drwav_f32_to_s16(drwav_int16* pOut, const float* pIn, size_t sampleCount);
   1129 
   1130 /* Low-level function for converting IEEE 64-bit floating point samples to signed 16-bit PCM samples. */
   1131 DRWAV_API void drwav_f64_to_s16(drwav_int16* pOut, const double* pIn, size_t sampleCount);
   1132 
   1133 /* Low-level function for converting A-law samples to signed 16-bit PCM samples. */
   1134 DRWAV_API void drwav_alaw_to_s16(drwav_int16* pOut, const drwav_uint8* pIn, size_t sampleCount);
   1135 
   1136 /* Low-level function for converting u-law samples to signed 16-bit PCM samples. */
   1137 DRWAV_API void drwav_mulaw_to_s16(drwav_int16* pOut, const drwav_uint8* pIn, size_t sampleCount);
   1138 
   1139 
   1140 /*
   1141 Reads a chunk of audio data and converts it to IEEE 32-bit floating point samples.
   1142 
   1143 pBufferOut can be NULL in which case a seek will be performed.
   1144 
   1145 Returns the number of PCM frames actually read.
   1146 
   1147 If the return value is less than <framesToRead> it means the end of the file has been reached.
   1148 */
   1149 DRWAV_API drwav_uint64 drwav_read_pcm_frames_f32(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut);
   1150 DRWAV_API drwav_uint64 drwav_read_pcm_frames_f32le(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut);
   1151 DRWAV_API drwav_uint64 drwav_read_pcm_frames_f32be(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut);
   1152 
   1153 /* Low-level function for converting unsigned 8-bit PCM samples to IEEE 32-bit floating point samples. */
   1154 DRWAV_API void drwav_u8_to_f32(float* pOut, const drwav_uint8* pIn, size_t sampleCount);
   1155 
   1156 /* Low-level function for converting signed 16-bit PCM samples to IEEE 32-bit floating point samples. */
   1157 DRWAV_API void drwav_s16_to_f32(float* pOut, const drwav_int16* pIn, size_t sampleCount);
   1158 
   1159 /* Low-level function for converting signed 24-bit PCM samples to IEEE 32-bit floating point samples. */
   1160 DRWAV_API void drwav_s24_to_f32(float* pOut, const drwav_uint8* pIn, size_t sampleCount);
   1161 
   1162 /* Low-level function for converting signed 32-bit PCM samples to IEEE 32-bit floating point samples. */
   1163 DRWAV_API void drwav_s32_to_f32(float* pOut, const drwav_int32* pIn, size_t sampleCount);
   1164 
   1165 /* Low-level function for converting IEEE 64-bit floating point samples to IEEE 32-bit floating point samples. */
   1166 DRWAV_API void drwav_f64_to_f32(float* pOut, const double* pIn, size_t sampleCount);
   1167 
   1168 /* Low-level function for converting A-law samples to IEEE 32-bit floating point samples. */
   1169 DRWAV_API void drwav_alaw_to_f32(float* pOut, const drwav_uint8* pIn, size_t sampleCount);
   1170 
   1171 /* Low-level function for converting u-law samples to IEEE 32-bit floating point samples. */
   1172 DRWAV_API void drwav_mulaw_to_f32(float* pOut, const drwav_uint8* pIn, size_t sampleCount);
   1173 
   1174 
   1175 /*
   1176 Reads a chunk of audio data and converts it to signed 32-bit PCM samples.
   1177 
   1178 pBufferOut can be NULL in which case a seek will be performed.
   1179 
   1180 Returns the number of PCM frames actually read.
   1181 
   1182 If the return value is less than <framesToRead> it means the end of the file has been reached.
   1183 */
   1184 DRWAV_API drwav_uint64 drwav_read_pcm_frames_s32(drwav* pWav, drwav_uint64 framesToRead, drwav_int32* pBufferOut);
   1185 DRWAV_API drwav_uint64 drwav_read_pcm_frames_s32le(drwav* pWav, drwav_uint64 framesToRead, drwav_int32* pBufferOut);
   1186 DRWAV_API drwav_uint64 drwav_read_pcm_frames_s32be(drwav* pWav, drwav_uint64 framesToRead, drwav_int32* pBufferOut);
   1187 
   1188 /* Low-level function for converting unsigned 8-bit PCM samples to signed 32-bit PCM samples. */
   1189 DRWAV_API void drwav_u8_to_s32(drwav_int32* pOut, const drwav_uint8* pIn, size_t sampleCount);
   1190 
   1191 /* Low-level function for converting signed 16-bit PCM samples to signed 32-bit PCM samples. */
   1192 DRWAV_API void drwav_s16_to_s32(drwav_int32* pOut, const drwav_int16* pIn, size_t sampleCount);
   1193 
   1194 /* Low-level function for converting signed 24-bit PCM samples to signed 32-bit PCM samples. */
   1195 DRWAV_API void drwav_s24_to_s32(drwav_int32* pOut, const drwav_uint8* pIn, size_t sampleCount);
   1196 
   1197 /* Low-level function for converting IEEE 32-bit floating point samples to signed 32-bit PCM samples. */
   1198 DRWAV_API void drwav_f32_to_s32(drwav_int32* pOut, const float* pIn, size_t sampleCount);
   1199 
   1200 /* Low-level function for converting IEEE 64-bit floating point samples to signed 32-bit PCM samples. */
   1201 DRWAV_API void drwav_f64_to_s32(drwav_int32* pOut, const double* pIn, size_t sampleCount);
   1202 
   1203 /* Low-level function for converting A-law samples to signed 32-bit PCM samples. */
   1204 DRWAV_API void drwav_alaw_to_s32(drwav_int32* pOut, const drwav_uint8* pIn, size_t sampleCount);
   1205 
   1206 /* Low-level function for converting u-law samples to signed 32-bit PCM samples. */
   1207 DRWAV_API void drwav_mulaw_to_s32(drwav_int32* pOut, const drwav_uint8* pIn, size_t sampleCount);
   1208 
   1209 #endif  /* DR_WAV_NO_CONVERSION_API */
   1210 
   1211 
   1212 /* High-Level Convenience Helpers */
   1213 
   1214 #ifndef DR_WAV_NO_STDIO
   1215 /*
   1216 Helper for initializing a wave file for reading using stdio.
   1217 
   1218 This holds the internal FILE object until drwav_uninit() is called. Keep this in mind if you're caching drwav
   1219 objects because the operating system may restrict the number of file handles an application can have open at
   1220 any given time.
   1221 */
   1222 DRWAV_API drwav_bool32 drwav_init_file(drwav* pWav, const char* filename, const drwav_allocation_callbacks* pAllocationCallbacks);
   1223 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);
   1224 DRWAV_API drwav_bool32 drwav_init_file_w(drwav* pWav, const wchar_t* filename, const drwav_allocation_callbacks* pAllocationCallbacks);
   1225 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);
   1226 DRWAV_API drwav_bool32 drwav_init_file_with_metadata(drwav* pWav, const char* filename, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks);
   1227 DRWAV_API drwav_bool32 drwav_init_file_with_metadata_w(drwav* pWav, const wchar_t* filename, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks);
   1228 
   1229 
   1230 /*
   1231 Helper for initializing a wave file for writing using stdio.
   1232 
   1233 This holds the internal FILE object until drwav_uninit() is called. Keep this in mind if you're caching drwav
   1234 objects because the operating system may restrict the number of file handles an application can have open at
   1235 any given time.
   1236 */
   1237 DRWAV_API drwav_bool32 drwav_init_file_write(drwav* pWav, const char* filename, const drwav_data_format* pFormat, const drwav_allocation_callbacks* pAllocationCallbacks);
   1238 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);
   1239 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);
   1240 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);
   1241 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);
   1242 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);
   1243 #endif  /* DR_WAV_NO_STDIO */
   1244 
   1245 /*
   1246 Helper for initializing a loader from a pre-allocated memory buffer.
   1247 
   1248 This does not create a copy of the data. It is up to the application to ensure the buffer remains valid for
   1249 the lifetime of the drwav object.
   1250 
   1251 The buffer should contain the contents of the entire wave file, not just the sample data.
   1252 */
   1253 DRWAV_API drwav_bool32 drwav_init_memory(drwav* pWav, const void* data, size_t dataSize, const drwav_allocation_callbacks* pAllocationCallbacks);
   1254 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);
   1255 DRWAV_API drwav_bool32 drwav_init_memory_with_metadata(drwav* pWav, const void* data, size_t dataSize, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks);
   1256 
   1257 /*
   1258 Helper for initializing a writer which outputs data to a memory buffer.
   1259 
   1260 dr_wav will manage the memory allocations, however it is up to the caller to free the data with drwav_free().
   1261 
   1262 The buffer will remain allocated even after drwav_uninit() is called. The buffer should not be considered valid
   1263 until after drwav_uninit() has been called.
   1264 */
   1265 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);
   1266 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);
   1267 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);
   1268 
   1269 
   1270 #ifndef DR_WAV_NO_CONVERSION_API
   1271 /*
   1272 Opens and reads an entire wav file in a single operation.
   1273 
   1274 The return value is a heap-allocated buffer containing the audio data. Use drwav_free() to free the buffer.
   1275 */
   1276 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);
   1277 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);
   1278 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);
   1279 #ifndef DR_WAV_NO_STDIO
   1280 /*
   1281 Opens and decodes an entire wav file in a single operation.
   1282 
   1283 The return value is a heap-allocated buffer containing the audio data. Use drwav_free() to free the buffer.
   1284 */
   1285 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);
   1286 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);
   1287 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);
   1288 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);
   1289 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);
   1290 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);
   1291 #endif
   1292 /*
   1293 Opens and decodes an entire wav file from a block of memory in a single operation.
   1294 
   1295 The return value is a heap-allocated buffer containing the audio data. Use drwav_free() to free the buffer.
   1296 */
   1297 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);
   1298 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);
   1299 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);
   1300 #endif
   1301 
   1302 /* Frees data that was allocated internally by dr_wav. */
   1303 DRWAV_API void drwav_free(void* p, const drwav_allocation_callbacks* pAllocationCallbacks);
   1304 
   1305 /* Converts bytes from a wav stream to a sized type of native endian. */
   1306 DRWAV_API drwav_uint16 drwav_bytes_to_u16(const drwav_uint8* data);
   1307 DRWAV_API drwav_int16 drwav_bytes_to_s16(const drwav_uint8* data);
   1308 DRWAV_API drwav_uint32 drwav_bytes_to_u32(const drwav_uint8* data);
   1309 DRWAV_API drwav_int32 drwav_bytes_to_s32(const drwav_uint8* data);
   1310 DRWAV_API drwav_uint64 drwav_bytes_to_u64(const drwav_uint8* data);
   1311 DRWAV_API drwav_int64 drwav_bytes_to_s64(const drwav_uint8* data);
   1312 DRWAV_API float drwav_bytes_to_f32(const drwav_uint8* data);
   1313 
   1314 /* Compares a GUID for the purpose of checking the type of a Wave64 chunk. */
   1315 DRWAV_API drwav_bool32 drwav_guid_equal(const drwav_uint8 a[16], const drwav_uint8 b[16]);
   1316 
   1317 /* Compares a four-character-code for the purpose of checking the type of a RIFF chunk. */
   1318 DRWAV_API drwav_bool32 drwav_fourcc_equal(const drwav_uint8* a, const char* b);
   1319 
   1320 #ifdef __cplusplus
   1321 }
   1322 #endif
   1323 #endif  /* dr_wav_h */
   1324 
   1325 
   1326 /************************************************************************************************************************************************************
   1327  ************************************************************************************************************************************************************
   1328 
   1329  IMPLEMENTATION
   1330 
   1331  ************************************************************************************************************************************************************
   1332  ************************************************************************************************************************************************************/
   1333 #if defined(DR_WAV_IMPLEMENTATION) || defined(DRWAV_IMPLEMENTATION)
   1334 #ifndef dr_wav_c
   1335 #define dr_wav_c
   1336 
   1337 #ifdef __MRC__
   1338 /* MrC currently doesn't compile dr_wav correctly with any optimizations enabled. */
   1339 #pragma options opt off
   1340 #endif
   1341 
   1342 #include <stdlib.h>
   1343 #include <string.h>
   1344 #include <limits.h> /* For INT_MAX */
   1345 
   1346 #ifndef DR_WAV_NO_STDIO
   1347 #include <stdio.h>
   1348 #ifndef DR_WAV_NO_WCHAR
   1349 #include <wchar.h>
   1350 #endif
   1351 #endif
   1352 
   1353 /* Standard library stuff. */
   1354 #ifndef DRWAV_ASSERT
   1355 #include <assert.h>
   1356 #define DRWAV_ASSERT(expression)           assert(expression)
   1357 #endif
   1358 #ifndef DRWAV_MALLOC
   1359 #define DRWAV_MALLOC(sz)                   malloc((sz))
   1360 #endif
   1361 #ifndef DRWAV_REALLOC
   1362 #define DRWAV_REALLOC(p, sz)               realloc((p), (sz))
   1363 #endif
   1364 #ifndef DRWAV_FREE
   1365 #define DRWAV_FREE(p)                      free((p))
   1366 #endif
   1367 #ifndef DRWAV_COPY_MEMORY
   1368 #define DRWAV_COPY_MEMORY(dst, src, sz)    memcpy((dst), (src), (sz))
   1369 #endif
   1370 #ifndef DRWAV_ZERO_MEMORY
   1371 #define DRWAV_ZERO_MEMORY(p, sz)           memset((p), 0, (sz))
   1372 #endif
   1373 #ifndef DRWAV_ZERO_OBJECT
   1374 #define DRWAV_ZERO_OBJECT(p)               DRWAV_ZERO_MEMORY((p), sizeof(*p))
   1375 #endif
   1376 
   1377 #define drwav_countof(x)                   (sizeof(x) / sizeof(x[0]))
   1378 #define drwav_align(x, a)                  ((((x) + (a) - 1) / (a)) * (a))
   1379 #define drwav_min(a, b)                    (((a) < (b)) ? (a) : (b))
   1380 #define drwav_max(a, b)                    (((a) > (b)) ? (a) : (b))
   1381 #define drwav_clamp(x, lo, hi)             (drwav_max((lo), drwav_min((hi), (x))))
   1382 #define drwav_offset_ptr(p, offset)        (((drwav_uint8*)(p)) + (offset))
   1383 
   1384 #define DRWAV_MAX_SIMD_VECTOR_SIZE         32
   1385 
   1386 /* Architecture Detection */
   1387 #if defined(__x86_64__) || defined(_M_X64)
   1388     #define DRWAV_X64
   1389 #elif defined(__i386) || defined(_M_IX86)
   1390     #define DRWAV_X86
   1391 #elif defined(__arm__) || defined(_M_ARM)
   1392     #define DRWAV_ARM
   1393 #endif
   1394 /* End Architecture Detection */
   1395 
   1396 /* Inline */
   1397 #ifdef _MSC_VER
   1398     #define DRWAV_INLINE __forceinline
   1399 #elif defined(__GNUC__)
   1400     /*
   1401     I've had a bug report where GCC is emitting warnings about functions possibly not being inlineable. This warning happens when
   1402     the __attribute__((always_inline)) attribute is defined without an "inline" statement. I think therefore there must be some
   1403     case where "__inline__" is not always defined, thus the compiler emitting these warnings. When using -std=c89 or -ansi on the
   1404     command line, we cannot use the "inline" keyword and instead need to use "__inline__". In an attempt to work around this issue
   1405     I am using "__inline__" only when we're compiling in strict ANSI mode.
   1406     */
   1407     #if defined(__STRICT_ANSI__)
   1408         #define DRWAV_GNUC_INLINE_HINT __inline__
   1409     #else
   1410         #define DRWAV_GNUC_INLINE_HINT inline
   1411     #endif
   1412 
   1413     #if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 2)) || defined(__clang__)
   1414         #define DRWAV_INLINE DRWAV_GNUC_INLINE_HINT __attribute__((always_inline))
   1415     #else
   1416         #define DRWAV_INLINE DRWAV_GNUC_INLINE_HINT
   1417     #endif
   1418 #elif defined(__WATCOMC__)
   1419     #define DRWAV_INLINE __inline
   1420 #else
   1421     #define DRWAV_INLINE
   1422 #endif
   1423 /* End Inline */
   1424 
   1425 /* SIZE_MAX */
   1426 #if defined(SIZE_MAX)
   1427     #define DRWAV_SIZE_MAX  SIZE_MAX
   1428 #else
   1429     #if defined(_WIN64) || defined(_LP64) || defined(__LP64__)
   1430         #define DRWAV_SIZE_MAX  ((drwav_uint64)0xFFFFFFFFFFFFFFFF)
   1431     #else
   1432         #define DRWAV_SIZE_MAX  0xFFFFFFFF
   1433     #endif
   1434 #endif
   1435 /* End SIZE_MAX */
   1436 
   1437 /* Weird bit manipulation is for C89 compatibility (no direct support for 64-bit integers). */
   1438 #define DRWAV_INT64_MIN ((drwav_int64) ((drwav_uint64)0x80000000 << 32))
   1439 #define DRWAV_INT64_MAX ((drwav_int64)(((drwav_uint64)0x7FFFFFFF << 32) | 0xFFFFFFFF))
   1440 
   1441 #if defined(_MSC_VER) && _MSC_VER >= 1400
   1442     #define DRWAV_HAS_BYTESWAP16_INTRINSIC
   1443     #define DRWAV_HAS_BYTESWAP32_INTRINSIC
   1444     #define DRWAV_HAS_BYTESWAP64_INTRINSIC
   1445 #elif defined(__clang__)
   1446     #if defined(__has_builtin)
   1447         #if __has_builtin(__builtin_bswap16)
   1448             #define DRWAV_HAS_BYTESWAP16_INTRINSIC
   1449         #endif
   1450         #if __has_builtin(__builtin_bswap32)
   1451             #define DRWAV_HAS_BYTESWAP32_INTRINSIC
   1452         #endif
   1453         #if __has_builtin(__builtin_bswap64)
   1454             #define DRWAV_HAS_BYTESWAP64_INTRINSIC
   1455         #endif
   1456     #endif
   1457 #elif defined(__GNUC__)
   1458     #if ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
   1459         #define DRWAV_HAS_BYTESWAP32_INTRINSIC
   1460         #define DRWAV_HAS_BYTESWAP64_INTRINSIC
   1461     #endif
   1462     #if ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))
   1463         #define DRWAV_HAS_BYTESWAP16_INTRINSIC
   1464     #endif
   1465 #endif
   1466 
   1467 DRWAV_API void drwav_version(drwav_uint32* pMajor, drwav_uint32* pMinor, drwav_uint32* pRevision)
   1468 {
   1469     if (pMajor) {
   1470         *pMajor = DRWAV_VERSION_MAJOR;
   1471     }
   1472 
   1473     if (pMinor) {
   1474         *pMinor = DRWAV_VERSION_MINOR;
   1475     }
   1476 
   1477     if (pRevision) {
   1478         *pRevision = DRWAV_VERSION_REVISION;
   1479     }
   1480 }
   1481 
   1482 DRWAV_API const char* drwav_version_string(void)
   1483 {
   1484     return DRWAV_VERSION_STRING;
   1485 }
   1486 
   1487 /*
   1488 These limits are used for basic validation when initializing the decoder. If you exceed these limits, first of all: what on Earth are
   1489 you doing?! (Let me know, I'd be curious!) Second, you can adjust these by #define-ing them before the dr_wav implementation.
   1490 */
   1491 #ifndef DRWAV_MAX_SAMPLE_RATE
   1492 #define DRWAV_MAX_SAMPLE_RATE       384000
   1493 #endif
   1494 #ifndef DRWAV_MAX_CHANNELS
   1495 #define DRWAV_MAX_CHANNELS          256
   1496 #endif
   1497 #ifndef DRWAV_MAX_BITS_PER_SAMPLE
   1498 #define DRWAV_MAX_BITS_PER_SAMPLE   64
   1499 #endif
   1500 
   1501 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 */
   1502 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 */
   1503 /*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 */
   1504 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 */
   1505 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 */
   1506 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 */
   1507 /*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 */
   1508 
   1509 
   1510 static DRWAV_INLINE int drwav__is_little_endian(void)
   1511 {
   1512 #if defined(DRWAV_X86) || defined(DRWAV_X64)
   1513     return DRWAV_TRUE;
   1514 #elif defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && __BYTE_ORDER == __LITTLE_ENDIAN
   1515     return DRWAV_TRUE;
   1516 #else
   1517     int n = 1;
   1518     return (*(char*)&n) == 1;
   1519 #endif
   1520 }
   1521 
   1522 
   1523 static DRWAV_INLINE void drwav_bytes_to_guid(const drwav_uint8* data, drwav_uint8* guid)
   1524 {
   1525     int i;
   1526     for (i = 0; i < 16; ++i) {
   1527         guid[i] = data[i];
   1528     }
   1529 }
   1530 
   1531 
   1532 static DRWAV_INLINE drwav_uint16 drwav__bswap16(drwav_uint16 n)
   1533 {
   1534 #ifdef DRWAV_HAS_BYTESWAP16_INTRINSIC
   1535     #if defined(_MSC_VER)
   1536         return _byteswap_ushort(n);
   1537     #elif defined(__GNUC__) || defined(__clang__)
   1538         return __builtin_bswap16(n);
   1539     #else
   1540         #error "This compiler does not support the byte swap intrinsic."
   1541     #endif
   1542 #else
   1543     return ((n & 0xFF00) >> 8) |
   1544            ((n & 0x00FF) << 8);
   1545 #endif
   1546 }
   1547 
   1548 static DRWAV_INLINE drwav_uint32 drwav__bswap32(drwav_uint32 n)
   1549 {
   1550 #ifdef DRWAV_HAS_BYTESWAP32_INTRINSIC
   1551     #if defined(_MSC_VER)
   1552         return _byteswap_ulong(n);
   1553     #elif defined(__GNUC__) || defined(__clang__)
   1554         #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. */
   1555             /* Inline assembly optimized implementation for ARM. In my testing, GCC does not generate optimized code with __builtin_bswap32(). */
   1556             drwav_uint32 r;
   1557             __asm__ __volatile__ (
   1558             #if defined(DRWAV_64BIT)
   1559                 "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! */
   1560             #else
   1561                 "rev %[out], %[in]" : [out]"=r"(r) : [in]"r"(n)
   1562             #endif
   1563             );
   1564             return r;
   1565         #else
   1566             return __builtin_bswap32(n);
   1567         #endif
   1568     #else
   1569         #error "This compiler does not support the byte swap intrinsic."
   1570     #endif
   1571 #else
   1572     return ((n & 0xFF000000) >> 24) |
   1573            ((n & 0x00FF0000) >>  8) |
   1574            ((n & 0x0000FF00) <<  8) |
   1575            ((n & 0x000000FF) << 24);
   1576 #endif
   1577 }
   1578 
   1579 static DRWAV_INLINE drwav_uint64 drwav__bswap64(drwav_uint64 n)
   1580 {
   1581 #ifdef DRWAV_HAS_BYTESWAP64_INTRINSIC
   1582     #if defined(_MSC_VER)
   1583         return _byteswap_uint64(n);
   1584     #elif defined(__GNUC__) || defined(__clang__)
   1585         return __builtin_bswap64(n);
   1586     #else
   1587         #error "This compiler does not support the byte swap intrinsic."
   1588     #endif
   1589 #else
   1590     /* Weird "<< 32" bitshift is required for C89 because it doesn't support 64-bit constants. Should be optimized out by a good compiler. */
   1591     return ((n & ((drwav_uint64)0xFF000000 << 32)) >> 56) |
   1592            ((n & ((drwav_uint64)0x00FF0000 << 32)) >> 40) |
   1593            ((n & ((drwav_uint64)0x0000FF00 << 32)) >> 24) |
   1594            ((n & ((drwav_uint64)0x000000FF << 32)) >>  8) |
   1595            ((n & ((drwav_uint64)0xFF000000      )) <<  8) |
   1596            ((n & ((drwav_uint64)0x00FF0000      )) << 24) |
   1597            ((n & ((drwav_uint64)0x0000FF00      )) << 40) |
   1598            ((n & ((drwav_uint64)0x000000FF      )) << 56);
   1599 #endif
   1600 }
   1601 
   1602 
   1603 static DRWAV_INLINE drwav_int16 drwav__bswap_s16(drwav_int16 n)
   1604 {
   1605     return (drwav_int16)drwav__bswap16((drwav_uint16)n);
   1606 }
   1607 
   1608 static DRWAV_INLINE void drwav__bswap_samples_s16(drwav_int16* pSamples, drwav_uint64 sampleCount)
   1609 {
   1610     drwav_uint64 iSample;
   1611     for (iSample = 0; iSample < sampleCount; iSample += 1) {
   1612         pSamples[iSample] = drwav__bswap_s16(pSamples[iSample]);
   1613     }
   1614 }
   1615 
   1616 
   1617 static DRWAV_INLINE void drwav__bswap_s24(drwav_uint8* p)
   1618 {
   1619     drwav_uint8 t;
   1620     t = p[0];
   1621     p[0] = p[2];
   1622     p[2] = t;
   1623 }
   1624 
   1625 static DRWAV_INLINE void drwav__bswap_samples_s24(drwav_uint8* pSamples, drwav_uint64 sampleCount)
   1626 {
   1627     drwav_uint64 iSample;
   1628     for (iSample = 0; iSample < sampleCount; iSample += 1) {
   1629         drwav_uint8* pSample = pSamples + (iSample*3);
   1630         drwav__bswap_s24(pSample);
   1631     }
   1632 }
   1633 
   1634 
   1635 static DRWAV_INLINE drwav_int32 drwav__bswap_s32(drwav_int32 n)
   1636 {
   1637     return (drwav_int32)drwav__bswap32((drwav_uint32)n);
   1638 }
   1639 
   1640 static DRWAV_INLINE void drwav__bswap_samples_s32(drwav_int32* pSamples, drwav_uint64 sampleCount)
   1641 {
   1642     drwav_uint64 iSample;
   1643     for (iSample = 0; iSample < sampleCount; iSample += 1) {
   1644         pSamples[iSample] = drwav__bswap_s32(pSamples[iSample]);
   1645     }
   1646 }
   1647 
   1648 
   1649 static DRWAV_INLINE drwav_int64 drwav__bswap_s64(drwav_int64 n)
   1650 {
   1651     return (drwav_int64)drwav__bswap64((drwav_uint64)n);
   1652 }
   1653 
   1654 static DRWAV_INLINE void drwav__bswap_samples_s64(drwav_int64* pSamples, drwav_uint64 sampleCount)
   1655 {
   1656     drwav_uint64 iSample;
   1657     for (iSample = 0; iSample < sampleCount; iSample += 1) {
   1658         pSamples[iSample] = drwav__bswap_s64(pSamples[iSample]);
   1659     }
   1660 }
   1661 
   1662 
   1663 static DRWAV_INLINE float drwav__bswap_f32(float n)
   1664 {
   1665     union {
   1666         drwav_uint32 i;
   1667         float f;
   1668     } x;
   1669     x.f = n;
   1670     x.i = drwav__bswap32(x.i);
   1671 
   1672     return x.f;
   1673 }
   1674 
   1675 static DRWAV_INLINE void drwav__bswap_samples_f32(float* pSamples, drwav_uint64 sampleCount)
   1676 {
   1677     drwav_uint64 iSample;
   1678     for (iSample = 0; iSample < sampleCount; iSample += 1) {
   1679         pSamples[iSample] = drwav__bswap_f32(pSamples[iSample]);
   1680     }
   1681 }
   1682 
   1683 
   1684 static DRWAV_INLINE void drwav__bswap_samples(void* pSamples, drwav_uint64 sampleCount, drwav_uint32 bytesPerSample)
   1685 {
   1686     switch (bytesPerSample)
   1687     {
   1688         case 1:
   1689         {
   1690             /* No-op. */
   1691         } break;
   1692         case 2:
   1693         {
   1694             drwav__bswap_samples_s16((drwav_int16*)pSamples, sampleCount);
   1695         } break;
   1696         case 3:
   1697         {
   1698             drwav__bswap_samples_s24((drwav_uint8*)pSamples, sampleCount);
   1699         } break;
   1700         case 4:
   1701         {
   1702             drwav__bswap_samples_s32((drwav_int32*)pSamples, sampleCount);
   1703         } break;
   1704         case 8:
   1705         {
   1706             drwav__bswap_samples_s64((drwav_int64*)pSamples, sampleCount);
   1707         } break;
   1708         default:
   1709         {
   1710             /* Unsupported format. */
   1711             DRWAV_ASSERT(DRWAV_FALSE);
   1712         } break;
   1713     }
   1714 }
   1715 
   1716 
   1717 
   1718 DRWAV_PRIVATE DRWAV_INLINE drwav_bool32 drwav_is_container_be(drwav_container container)
   1719 {
   1720     if (container == drwav_container_rifx || container == drwav_container_aiff) {
   1721         return DRWAV_TRUE;
   1722     } else {
   1723         return DRWAV_FALSE;
   1724     }
   1725 }
   1726 
   1727 
   1728 DRWAV_PRIVATE DRWAV_INLINE drwav_uint16 drwav_bytes_to_u16_le(const drwav_uint8* data)
   1729 {
   1730     return ((drwav_uint16)data[0] << 0) | ((drwav_uint16)data[1] << 8);
   1731 }
   1732 
   1733 DRWAV_PRIVATE DRWAV_INLINE drwav_uint16 drwav_bytes_to_u16_be(const drwav_uint8* data)
   1734 {
   1735     return ((drwav_uint16)data[1] << 0) | ((drwav_uint16)data[0] << 8);
   1736 }
   1737 
   1738 DRWAV_PRIVATE DRWAV_INLINE drwav_uint16 drwav_bytes_to_u16_ex(const drwav_uint8* data, drwav_container container)
   1739 {
   1740     if (drwav_is_container_be(container)) {
   1741         return drwav_bytes_to_u16_be(data);
   1742     } else {
   1743         return drwav_bytes_to_u16_le(data);
   1744     }
   1745 }
   1746 
   1747 
   1748 DRWAV_PRIVATE DRWAV_INLINE drwav_uint32 drwav_bytes_to_u32_le(const drwav_uint8* data)
   1749 {
   1750     return ((drwav_uint32)data[0] << 0) | ((drwav_uint32)data[1] << 8) | ((drwav_uint32)data[2] << 16) | ((drwav_uint32)data[3] << 24);
   1751 }
   1752 
   1753 DRWAV_PRIVATE DRWAV_INLINE drwav_uint32 drwav_bytes_to_u32_be(const drwav_uint8* data)
   1754 {
   1755     return ((drwav_uint32)data[3] << 0) | ((drwav_uint32)data[2] << 8) | ((drwav_uint32)data[1] << 16) | ((drwav_uint32)data[0] << 24);
   1756 }
   1757 
   1758 DRWAV_PRIVATE DRWAV_INLINE drwav_uint32 drwav_bytes_to_u32_ex(const drwav_uint8* data, drwav_container container)
   1759 {
   1760     if (drwav_is_container_be(container)) {
   1761         return drwav_bytes_to_u32_be(data);
   1762     } else {
   1763         return drwav_bytes_to_u32_le(data);
   1764     }
   1765 }
   1766 
   1767 
   1768 
   1769 DRWAV_PRIVATE drwav_int64 drwav_aiff_extented_to_s64(const drwav_uint8* data)
   1770 {
   1771     drwav_uint32 exponent = ((drwav_uint32)data[0] << 8) | data[1];
   1772     drwav_uint64 hi = ((drwav_uint64)data[2] << 24) | ((drwav_uint64)data[3] << 16) | ((drwav_uint64)data[4] <<  8) | ((drwav_uint64)data[5] <<  0);
   1773     drwav_uint64 lo = ((drwav_uint64)data[6] << 24) | ((drwav_uint64)data[7] << 16) | ((drwav_uint64)data[8] <<  8) | ((drwav_uint64)data[9] <<  0);
   1774     drwav_uint64 significand = (hi << 32) | lo;
   1775     int sign = exponent >> 15;
   1776 
   1777     /* Remove sign bit. */
   1778     exponent &= 0x7FFF;
   1779 
   1780     /* Special cases. */
   1781     if (exponent == 0 && significand == 0) {
   1782         return 0;
   1783     } else if (exponent == 0x7FFF) {
   1784         return sign ? DRWAV_INT64_MIN : DRWAV_INT64_MAX;    /* Infinite. */
   1785     }
   1786 
   1787     exponent -= 16383;
   1788 
   1789     if (exponent > 63) {
   1790         return sign ? DRWAV_INT64_MIN : DRWAV_INT64_MAX;    /* Too big for a 64-bit integer. */
   1791     } else if (exponent < 1) {
   1792         return 0;  /* Number is less than 1, so rounds down to 0. */
   1793     }
   1794 
   1795     significand >>= (63 - exponent);
   1796 
   1797     if (sign) {
   1798         return -(drwav_int64)significand;
   1799     } else {
   1800         return  (drwav_int64)significand;
   1801     }
   1802 }
   1803 
   1804 
   1805 DRWAV_PRIVATE void* drwav__malloc_default(size_t sz, void* pUserData)
   1806 {
   1807     (void)pUserData;
   1808     return DRWAV_MALLOC(sz);
   1809 }
   1810 
   1811 DRWAV_PRIVATE void* drwav__realloc_default(void* p, size_t sz, void* pUserData)
   1812 {
   1813     (void)pUserData;
   1814     return DRWAV_REALLOC(p, sz);
   1815 }
   1816 
   1817 DRWAV_PRIVATE void drwav__free_default(void* p, void* pUserData)
   1818 {
   1819     (void)pUserData;
   1820     DRWAV_FREE(p);
   1821 }
   1822 
   1823 
   1824 DRWAV_PRIVATE void* drwav__malloc_from_callbacks(size_t sz, const drwav_allocation_callbacks* pAllocationCallbacks)
   1825 {
   1826     if (pAllocationCallbacks == NULL) {
   1827         return NULL;
   1828     }
   1829 
   1830     if (pAllocationCallbacks->onMalloc != NULL) {
   1831         return pAllocationCallbacks->onMalloc(sz, pAllocationCallbacks->pUserData);
   1832     }
   1833 
   1834     /* Try using realloc(). */
   1835     if (pAllocationCallbacks->onRealloc != NULL) {
   1836         return pAllocationCallbacks->onRealloc(NULL, sz, pAllocationCallbacks->pUserData);
   1837     }
   1838 
   1839     return NULL;
   1840 }
   1841 
   1842 DRWAV_PRIVATE void* drwav__realloc_from_callbacks(void* p, size_t szNew, size_t szOld, const drwav_allocation_callbacks* pAllocationCallbacks)
   1843 {
   1844     if (pAllocationCallbacks == NULL) {
   1845         return NULL;
   1846     }
   1847 
   1848     if (pAllocationCallbacks->onRealloc != NULL) {
   1849         return pAllocationCallbacks->onRealloc(p, szNew, pAllocationCallbacks->pUserData);
   1850     }
   1851 
   1852     /* Try emulating realloc() in terms of malloc()/free(). */
   1853     if (pAllocationCallbacks->onMalloc != NULL && pAllocationCallbacks->onFree != NULL) {
   1854         void* p2;
   1855 
   1856         p2 = pAllocationCallbacks->onMalloc(szNew, pAllocationCallbacks->pUserData);
   1857         if (p2 == NULL) {
   1858             return NULL;
   1859         }
   1860 
   1861         if (p != NULL) {
   1862             DRWAV_COPY_MEMORY(p2, p, szOld);
   1863             pAllocationCallbacks->onFree(p, pAllocationCallbacks->pUserData);
   1864         }
   1865 
   1866         return p2;
   1867     }
   1868 
   1869     return NULL;
   1870 }
   1871 
   1872 DRWAV_PRIVATE void drwav__free_from_callbacks(void* p, const drwav_allocation_callbacks* pAllocationCallbacks)
   1873 {
   1874     if (p == NULL || pAllocationCallbacks == NULL) {
   1875         return;
   1876     }
   1877 
   1878     if (pAllocationCallbacks->onFree != NULL) {
   1879         pAllocationCallbacks->onFree(p, pAllocationCallbacks->pUserData);
   1880     }
   1881 }
   1882 
   1883 
   1884 DRWAV_PRIVATE drwav_allocation_callbacks drwav_copy_allocation_callbacks_or_defaults(const drwav_allocation_callbacks* pAllocationCallbacks)
   1885 {
   1886     if (pAllocationCallbacks != NULL) {
   1887         /* Copy. */
   1888         return *pAllocationCallbacks;
   1889     } else {
   1890         /* Defaults. */
   1891         drwav_allocation_callbacks allocationCallbacks;
   1892         allocationCallbacks.pUserData = NULL;
   1893         allocationCallbacks.onMalloc  = drwav__malloc_default;
   1894         allocationCallbacks.onRealloc = drwav__realloc_default;
   1895         allocationCallbacks.onFree    = drwav__free_default;
   1896         return allocationCallbacks;
   1897     }
   1898 }
   1899 
   1900 
   1901 static DRWAV_INLINE drwav_bool32 drwav__is_compressed_format_tag(drwav_uint16 formatTag)
   1902 {
   1903     return
   1904         formatTag == DR_WAVE_FORMAT_ADPCM ||
   1905         formatTag == DR_WAVE_FORMAT_DVI_ADPCM;
   1906 }
   1907 
   1908 DRWAV_PRIVATE unsigned int drwav__chunk_padding_size_riff(drwav_uint64 chunkSize)
   1909 {
   1910     return (unsigned int)(chunkSize % 2);
   1911 }
   1912 
   1913 DRWAV_PRIVATE unsigned int drwav__chunk_padding_size_w64(drwav_uint64 chunkSize)
   1914 {
   1915     return (unsigned int)(chunkSize % 8);
   1916 }
   1917 
   1918 DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__msadpcm(drwav* pWav, drwav_uint64 samplesToRead, drwav_int16* pBufferOut);
   1919 DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__ima(drwav* pWav, drwav_uint64 samplesToRead, drwav_int16* pBufferOut);
   1920 DRWAV_PRIVATE drwav_bool32 drwav_init_write__internal(drwav* pWav, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount);
   1921 
   1922 DRWAV_PRIVATE drwav_result drwav__read_chunk_header(drwav_read_proc onRead, void* pUserData, drwav_container container, drwav_uint64* pRunningBytesReadOut, drwav_chunk_header* pHeaderOut)
   1923 {
   1924     if (container == drwav_container_riff || container == drwav_container_rifx || container == drwav_container_rf64 || container == drwav_container_aiff) {
   1925         drwav_uint8 sizeInBytes[4];
   1926 
   1927         if (onRead(pUserData, pHeaderOut->id.fourcc, 4) != 4) {
   1928             return DRWAV_AT_END;
   1929         }
   1930 
   1931         if (onRead(pUserData, sizeInBytes, 4) != 4) {
   1932             return DRWAV_INVALID_FILE;
   1933         }
   1934 
   1935         pHeaderOut->sizeInBytes = drwav_bytes_to_u32_ex(sizeInBytes, container);
   1936         pHeaderOut->paddingSize = drwav__chunk_padding_size_riff(pHeaderOut->sizeInBytes);
   1937 
   1938         *pRunningBytesReadOut += 8;
   1939     } else if (container == drwav_container_w64) {
   1940         drwav_uint8 sizeInBytes[8];
   1941 
   1942         if (onRead(pUserData, pHeaderOut->id.guid, 16) != 16) {
   1943             return DRWAV_AT_END;
   1944         }
   1945 
   1946         if (onRead(pUserData, sizeInBytes, 8) != 8) {
   1947             return DRWAV_INVALID_FILE;
   1948         }
   1949 
   1950         pHeaderOut->sizeInBytes = drwav_bytes_to_u64(sizeInBytes) - 24;    /* <-- Subtract 24 because w64 includes the size of the header. */
   1951         pHeaderOut->paddingSize = drwav__chunk_padding_size_w64(pHeaderOut->sizeInBytes);
   1952         *pRunningBytesReadOut += 24;
   1953     } else {
   1954         return DRWAV_INVALID_FILE;
   1955     }
   1956 
   1957     return DRWAV_SUCCESS;
   1958 }
   1959 
   1960 DRWAV_PRIVATE drwav_bool32 drwav__seek_forward(drwav_seek_proc onSeek, drwav_uint64 offset, void* pUserData)
   1961 {
   1962     drwav_uint64 bytesRemainingToSeek = offset;
   1963     while (bytesRemainingToSeek > 0) {
   1964         if (bytesRemainingToSeek > 0x7FFFFFFF) {
   1965             if (!onSeek(pUserData, 0x7FFFFFFF, drwav_seek_origin_current)) {
   1966                 return DRWAV_FALSE;
   1967             }
   1968             bytesRemainingToSeek -= 0x7FFFFFFF;
   1969         } else {
   1970             if (!onSeek(pUserData, (int)bytesRemainingToSeek, drwav_seek_origin_current)) {
   1971                 return DRWAV_FALSE;
   1972             }
   1973             bytesRemainingToSeek = 0;
   1974         }
   1975     }
   1976 
   1977     return DRWAV_TRUE;
   1978 }
   1979 
   1980 DRWAV_PRIVATE drwav_bool32 drwav__seek_from_start(drwav_seek_proc onSeek, drwav_uint64 offset, void* pUserData)
   1981 {
   1982     if (offset <= 0x7FFFFFFF) {
   1983         return onSeek(pUserData, (int)offset, drwav_seek_origin_start);
   1984     }
   1985 
   1986     /* Larger than 32-bit seek. */
   1987     if (!onSeek(pUserData, 0x7FFFFFFF, drwav_seek_origin_start)) {
   1988         return DRWAV_FALSE;
   1989     }
   1990     offset -= 0x7FFFFFFF;
   1991 
   1992     for (;;) {
   1993         if (offset <= 0x7FFFFFFF) {
   1994             return onSeek(pUserData, (int)offset, drwav_seek_origin_current);
   1995         }
   1996 
   1997         if (!onSeek(pUserData, 0x7FFFFFFF, drwav_seek_origin_current)) {
   1998             return DRWAV_FALSE;
   1999         }
   2000         offset -= 0x7FFFFFFF;
   2001     }
   2002 
   2003     /* Should never get here. */
   2004     /*return DRWAV_TRUE; */
   2005 }
   2006 
   2007 
   2008 
   2009 DRWAV_PRIVATE size_t drwav__on_read(drwav_read_proc onRead, void* pUserData, void* pBufferOut, size_t bytesToRead, drwav_uint64* pCursor)
   2010 {
   2011     size_t bytesRead;
   2012 
   2013     DRWAV_ASSERT(onRead != NULL);
   2014     DRWAV_ASSERT(pCursor != NULL);
   2015 
   2016     bytesRead = onRead(pUserData, pBufferOut, bytesToRead);
   2017     *pCursor += bytesRead;
   2018     return bytesRead;
   2019 }
   2020 
   2021 #if 0
   2022 DRWAV_PRIVATE drwav_bool32 drwav__on_seek(drwav_seek_proc onSeek, void* pUserData, int offset, drwav_seek_origin origin, drwav_uint64* pCursor)
   2023 {
   2024     DRWAV_ASSERT(onSeek != NULL);
   2025     DRWAV_ASSERT(pCursor != NULL);
   2026 
   2027     if (!onSeek(pUserData, offset, origin)) {
   2028         return DRWAV_FALSE;
   2029     }
   2030 
   2031     if (origin == drwav_seek_origin_start) {
   2032         *pCursor = offset;
   2033     } else {
   2034         *pCursor += offset;
   2035     }
   2036 
   2037     return DRWAV_TRUE;
   2038 }
   2039 #endif
   2040 
   2041 
   2042 #define DRWAV_SMPL_BYTES                    36
   2043 #define DRWAV_SMPL_LOOP_BYTES               24
   2044 #define DRWAV_INST_BYTES                    7
   2045 #define DRWAV_ACID_BYTES                    24
   2046 #define DRWAV_CUE_BYTES                     4
   2047 #define DRWAV_BEXT_BYTES                    602
   2048 #define DRWAV_BEXT_DESCRIPTION_BYTES        256
   2049 #define DRWAV_BEXT_ORIGINATOR_NAME_BYTES    32
   2050 #define DRWAV_BEXT_ORIGINATOR_REF_BYTES     32
   2051 #define DRWAV_BEXT_RESERVED_BYTES           180
   2052 #define DRWAV_BEXT_UMID_BYTES               64
   2053 #define DRWAV_CUE_POINT_BYTES               24
   2054 #define DRWAV_LIST_LABEL_OR_NOTE_BYTES      4
   2055 #define DRWAV_LIST_LABELLED_TEXT_BYTES      20
   2056 
   2057 #define DRWAV_METADATA_ALIGNMENT            8
   2058 
   2059 typedef enum
   2060 {
   2061     drwav__metadata_parser_stage_count,
   2062     drwav__metadata_parser_stage_read
   2063 } drwav__metadata_parser_stage;
   2064 
   2065 typedef struct
   2066 {
   2067     drwav_read_proc onRead;
   2068     drwav_seek_proc onSeek;
   2069     void *pReadSeekUserData;
   2070     drwav__metadata_parser_stage stage;
   2071     drwav_metadata *pMetadata;
   2072     drwav_uint32 metadataCount;
   2073     drwav_uint8 *pData;
   2074     drwav_uint8 *pDataCursor;
   2075     drwav_uint64 metadataCursor;
   2076     drwav_uint64 extraCapacity;
   2077 } drwav__metadata_parser;
   2078 
   2079 DRWAV_PRIVATE size_t drwav__metadata_memory_capacity(drwav__metadata_parser* pParser)
   2080 {
   2081     drwav_uint64 cap = sizeof(drwav_metadata) * (drwav_uint64)pParser->metadataCount + pParser->extraCapacity;
   2082     if (cap > DRWAV_SIZE_MAX) {
   2083         return 0;   /* Too big. */
   2084     }
   2085 
   2086     return (size_t)cap; /* Safe cast thanks to the check above. */
   2087 }
   2088 
   2089 DRWAV_PRIVATE drwav_uint8* drwav__metadata_get_memory(drwav__metadata_parser* pParser, size_t size, size_t align)
   2090 {
   2091     drwav_uint8* pResult;
   2092 
   2093     if (align) {
   2094         drwav_uintptr modulo = (drwav_uintptr)pParser->pDataCursor % align;
   2095         if (modulo != 0) {
   2096             pParser->pDataCursor += align - modulo;
   2097         }
   2098     }
   2099     
   2100     pResult = pParser->pDataCursor;
   2101 
   2102     /*
   2103     Getting to the point where this function is called means there should always be memory
   2104     available. Out of memory checks should have been done at an earlier stage.
   2105     */
   2106     DRWAV_ASSERT((pResult + size) <= (pParser->pData + drwav__metadata_memory_capacity(pParser)));
   2107 
   2108     pParser->pDataCursor += size;
   2109     return pResult;
   2110 }
   2111 
   2112 DRWAV_PRIVATE void drwav__metadata_request_extra_memory_for_stage_2(drwav__metadata_parser* pParser, size_t bytes, size_t align)
   2113 {
   2114     size_t extra = bytes + (align ? (align - 1) : 0);
   2115     pParser->extraCapacity += extra;
   2116 }
   2117 
   2118 DRWAV_PRIVATE drwav_result drwav__metadata_alloc(drwav__metadata_parser* pParser, drwav_allocation_callbacks* pAllocationCallbacks)
   2119 {
   2120     if (pParser->extraCapacity != 0 || pParser->metadataCount != 0) {
   2121         pAllocationCallbacks->onFree(pParser->pData, pAllocationCallbacks->pUserData);
   2122 
   2123         pParser->pData = (drwav_uint8*)pAllocationCallbacks->onMalloc(drwav__metadata_memory_capacity(pParser), pAllocationCallbacks->pUserData);
   2124         pParser->pDataCursor = pParser->pData;
   2125 
   2126         if (pParser->pData == NULL) {
   2127             return DRWAV_OUT_OF_MEMORY;
   2128         }
   2129 
   2130         /*
   2131         We don't need to worry about specifying an alignment here because malloc always returns something
   2132         of suitable alignment. This also means pParser->pMetadata is all that we need to store in order
   2133         for us to free when we are done.
   2134         */
   2135         pParser->pMetadata = (drwav_metadata*)drwav__metadata_get_memory(pParser, sizeof(drwav_metadata) * pParser->metadataCount, 1);
   2136         pParser->metadataCursor = 0;
   2137     }
   2138 
   2139     return DRWAV_SUCCESS;
   2140 }
   2141 
   2142 DRWAV_PRIVATE size_t drwav__metadata_parser_read(drwav__metadata_parser* pParser, void* pBufferOut, size_t bytesToRead, drwav_uint64* pCursor)
   2143 {
   2144     if (pCursor != NULL) {
   2145         return drwav__on_read(pParser->onRead, pParser->pReadSeekUserData, pBufferOut, bytesToRead, pCursor);
   2146     } else {
   2147         return pParser->onRead(pParser->pReadSeekUserData, pBufferOut, bytesToRead);
   2148     }
   2149 }
   2150 
   2151 DRWAV_PRIVATE drwav_uint64 drwav__read_smpl_to_metadata_obj(drwav__metadata_parser* pParser, const drwav_chunk_header* pChunkHeader, drwav_metadata* pMetadata)
   2152 {
   2153     drwav_uint8 smplHeaderData[DRWAV_SMPL_BYTES];
   2154     drwav_uint64 totalBytesRead = 0;
   2155     size_t bytesJustRead;
   2156 
   2157     if (pMetadata == NULL) {
   2158         return 0;
   2159     }
   2160 
   2161     bytesJustRead = drwav__metadata_parser_read(pParser, smplHeaderData, sizeof(smplHeaderData), &totalBytesRead);
   2162 
   2163     DRWAV_ASSERT(pParser->stage == drwav__metadata_parser_stage_read);
   2164     DRWAV_ASSERT(pChunkHeader != NULL);
   2165 
   2166     if (pMetadata != NULL && bytesJustRead == sizeof(smplHeaderData)) {
   2167         drwav_uint32 iSampleLoop;
   2168 
   2169         pMetadata->type                                     = drwav_metadata_type_smpl;
   2170         pMetadata->data.smpl.manufacturerId                 = drwav_bytes_to_u32(smplHeaderData + 0);
   2171         pMetadata->data.smpl.productId                      = drwav_bytes_to_u32(smplHeaderData + 4);
   2172         pMetadata->data.smpl.samplePeriodNanoseconds        = drwav_bytes_to_u32(smplHeaderData + 8);
   2173         pMetadata->data.smpl.midiUnityNote                  = drwav_bytes_to_u32(smplHeaderData + 12);
   2174         pMetadata->data.smpl.midiPitchFraction              = drwav_bytes_to_u32(smplHeaderData + 16);
   2175         pMetadata->data.smpl.smpteFormat                    = drwav_bytes_to_u32(smplHeaderData + 20);
   2176         pMetadata->data.smpl.smpteOffset                    = drwav_bytes_to_u32(smplHeaderData + 24);
   2177         pMetadata->data.smpl.sampleLoopCount                = drwav_bytes_to_u32(smplHeaderData + 28);
   2178         pMetadata->data.smpl.samplerSpecificDataSizeInBytes = drwav_bytes_to_u32(smplHeaderData + 32);
   2179 
   2180         /*
   2181         The loop count needs to be validated against the size of the chunk for safety so we don't
   2182         attempt to read over the boundary of the chunk.
   2183         */
   2184         if (pMetadata->data.smpl.sampleLoopCount == (pChunkHeader->sizeInBytes - DRWAV_SMPL_BYTES) / DRWAV_SMPL_LOOP_BYTES) {
   2185             pMetadata->data.smpl.pLoops = (drwav_smpl_loop*)drwav__metadata_get_memory(pParser, sizeof(drwav_smpl_loop) * pMetadata->data.smpl.sampleLoopCount, DRWAV_METADATA_ALIGNMENT);
   2186 
   2187             for (iSampleLoop = 0; iSampleLoop < pMetadata->data.smpl.sampleLoopCount; ++iSampleLoop) {
   2188                 drwav_uint8 smplLoopData[DRWAV_SMPL_LOOP_BYTES];
   2189                 bytesJustRead = drwav__metadata_parser_read(pParser, smplLoopData, sizeof(smplLoopData), &totalBytesRead);
   2190 
   2191                 if (bytesJustRead == sizeof(smplLoopData)) {
   2192                     pMetadata->data.smpl.pLoops[iSampleLoop].cuePointId            = drwav_bytes_to_u32(smplLoopData + 0);
   2193                     pMetadata->data.smpl.pLoops[iSampleLoop].type                  = drwav_bytes_to_u32(smplLoopData + 4);
   2194                     pMetadata->data.smpl.pLoops[iSampleLoop].firstSampleByteOffset = drwav_bytes_to_u32(smplLoopData + 8);
   2195                     pMetadata->data.smpl.pLoops[iSampleLoop].lastSampleByteOffset  = drwav_bytes_to_u32(smplLoopData + 12);
   2196                     pMetadata->data.smpl.pLoops[iSampleLoop].sampleFraction        = drwav_bytes_to_u32(smplLoopData + 16);
   2197                     pMetadata->data.smpl.pLoops[iSampleLoop].playCount             = drwav_bytes_to_u32(smplLoopData + 20);
   2198                 } else {
   2199                     break;
   2200                 }
   2201             }
   2202 
   2203             if (pMetadata->data.smpl.samplerSpecificDataSizeInBytes > 0) {
   2204                 pMetadata->data.smpl.pSamplerSpecificData = drwav__metadata_get_memory(pParser, pMetadata->data.smpl.samplerSpecificDataSizeInBytes, 1);
   2205                 DRWAV_ASSERT(pMetadata->data.smpl.pSamplerSpecificData != NULL);
   2206 
   2207                 drwav__metadata_parser_read(pParser, pMetadata->data.smpl.pSamplerSpecificData, pMetadata->data.smpl.samplerSpecificDataSizeInBytes, &totalBytesRead);
   2208             }
   2209         }
   2210     }
   2211 
   2212     return totalBytesRead;
   2213 }
   2214 
   2215 DRWAV_PRIVATE drwav_uint64 drwav__read_cue_to_metadata_obj(drwav__metadata_parser* pParser, const drwav_chunk_header* pChunkHeader, drwav_metadata* pMetadata)
   2216 {
   2217     drwav_uint8 cueHeaderSectionData[DRWAV_CUE_BYTES];
   2218     drwav_uint64 totalBytesRead = 0;
   2219     size_t bytesJustRead;
   2220 
   2221     if (pMetadata == NULL) {
   2222         return 0;
   2223     }
   2224 
   2225     bytesJustRead = drwav__metadata_parser_read(pParser, cueHeaderSectionData, sizeof(cueHeaderSectionData), &totalBytesRead);
   2226 
   2227     DRWAV_ASSERT(pParser->stage == drwav__metadata_parser_stage_read);
   2228 
   2229     if (bytesJustRead == sizeof(cueHeaderSectionData)) {
   2230         pMetadata->type                   = drwav_metadata_type_cue;
   2231         pMetadata->data.cue.cuePointCount = drwav_bytes_to_u32(cueHeaderSectionData);
   2232 
   2233         /*
   2234         We need to validate the cue point count against the size of the chunk so we don't read
   2235         beyond the chunk.
   2236         */
   2237         if (pMetadata->data.cue.cuePointCount == (pChunkHeader->sizeInBytes - DRWAV_CUE_BYTES) / DRWAV_CUE_POINT_BYTES) {
   2238             pMetadata->data.cue.pCuePoints    = (drwav_cue_point*)drwav__metadata_get_memory(pParser, sizeof(drwav_cue_point) * pMetadata->data.cue.cuePointCount, DRWAV_METADATA_ALIGNMENT);
   2239             DRWAV_ASSERT(pMetadata->data.cue.pCuePoints != NULL);
   2240 
   2241             if (pMetadata->data.cue.cuePointCount > 0) {
   2242                 drwav_uint32 iCuePoint;
   2243 
   2244                 for (iCuePoint = 0; iCuePoint < pMetadata->data.cue.cuePointCount; ++iCuePoint) {
   2245                     drwav_uint8 cuePointData[DRWAV_CUE_POINT_BYTES];
   2246                     bytesJustRead = drwav__metadata_parser_read(pParser, cuePointData, sizeof(cuePointData), &totalBytesRead);
   2247 
   2248                     if (bytesJustRead == sizeof(cuePointData)) {
   2249                         pMetadata->data.cue.pCuePoints[iCuePoint].id                = drwav_bytes_to_u32(cuePointData + 0);
   2250                         pMetadata->data.cue.pCuePoints[iCuePoint].playOrderPosition = drwav_bytes_to_u32(cuePointData + 4);
   2251                         pMetadata->data.cue.pCuePoints[iCuePoint].dataChunkId[0]    = cuePointData[8];
   2252                         pMetadata->data.cue.pCuePoints[iCuePoint].dataChunkId[1]    = cuePointData[9];
   2253                         pMetadata->data.cue.pCuePoints[iCuePoint].dataChunkId[2]    = cuePointData[10];
   2254                         pMetadata->data.cue.pCuePoints[iCuePoint].dataChunkId[3]    = cuePointData[11];
   2255                         pMetadata->data.cue.pCuePoints[iCuePoint].chunkStart        = drwav_bytes_to_u32(cuePointData + 12);
   2256                         pMetadata->data.cue.pCuePoints[iCuePoint].blockStart        = drwav_bytes_to_u32(cuePointData + 16);
   2257                         pMetadata->data.cue.pCuePoints[iCuePoint].sampleByteOffset  = drwav_bytes_to_u32(cuePointData + 20);
   2258                     } else {
   2259                         break;
   2260                     }
   2261                 }
   2262             }
   2263         }
   2264     }
   2265 
   2266     return totalBytesRead;
   2267 }
   2268 
   2269 DRWAV_PRIVATE drwav_uint64 drwav__read_inst_to_metadata_obj(drwav__metadata_parser* pParser, drwav_metadata* pMetadata)
   2270 {
   2271     drwav_uint8 instData[DRWAV_INST_BYTES];
   2272     drwav_uint64 bytesRead;
   2273 
   2274     if (pMetadata == NULL) {
   2275         return 0;
   2276     }
   2277 
   2278     bytesRead = drwav__metadata_parser_read(pParser, instData, sizeof(instData), NULL);
   2279 
   2280     DRWAV_ASSERT(pParser->stage == drwav__metadata_parser_stage_read);
   2281 
   2282     if (bytesRead == sizeof(instData)) {
   2283         pMetadata->type                    = drwav_metadata_type_inst;
   2284         pMetadata->data.inst.midiUnityNote = (drwav_int8)instData[0];
   2285         pMetadata->data.inst.fineTuneCents = (drwav_int8)instData[1];
   2286         pMetadata->data.inst.gainDecibels  = (drwav_int8)instData[2];
   2287         pMetadata->data.inst.lowNote       = (drwav_int8)instData[3];
   2288         pMetadata->data.inst.highNote      = (drwav_int8)instData[4];
   2289         pMetadata->data.inst.lowVelocity   = (drwav_int8)instData[5];
   2290         pMetadata->data.inst.highVelocity  = (drwav_int8)instData[6];
   2291     }
   2292 
   2293     return bytesRead;
   2294 }
   2295 
   2296 DRWAV_PRIVATE drwav_uint64 drwav__read_acid_to_metadata_obj(drwav__metadata_parser* pParser, drwav_metadata* pMetadata)
   2297 {
   2298     drwav_uint8 acidData[DRWAV_ACID_BYTES];
   2299     drwav_uint64 bytesRead;
   2300 
   2301     if (pMetadata == NULL) {
   2302         return 0;
   2303     }
   2304 
   2305     bytesRead = drwav__metadata_parser_read(pParser, acidData, sizeof(acidData), NULL);
   2306 
   2307     DRWAV_ASSERT(pParser->stage == drwav__metadata_parser_stage_read);
   2308 
   2309     if (bytesRead == sizeof(acidData)) {
   2310         pMetadata->type                       = drwav_metadata_type_acid;
   2311         pMetadata->data.acid.flags            = drwav_bytes_to_u32(acidData + 0);
   2312         pMetadata->data.acid.midiUnityNote    = drwav_bytes_to_u16(acidData + 4);
   2313         pMetadata->data.acid.reserved1        = drwav_bytes_to_u16(acidData + 6);
   2314         pMetadata->data.acid.reserved2        = drwav_bytes_to_f32(acidData + 8);
   2315         pMetadata->data.acid.numBeats         = drwav_bytes_to_u32(acidData + 12);
   2316         pMetadata->data.acid.meterDenominator = drwav_bytes_to_u16(acidData + 16);
   2317         pMetadata->data.acid.meterNumerator   = drwav_bytes_to_u16(acidData + 18);
   2318         pMetadata->data.acid.tempo            = drwav_bytes_to_f32(acidData + 20);
   2319     }
   2320 
   2321     return bytesRead;
   2322 }
   2323 
   2324 DRWAV_PRIVATE size_t drwav__strlen(const char* str)
   2325 {
   2326     size_t result = 0;
   2327 
   2328     while (*str++) {
   2329         result += 1;
   2330     }
   2331 
   2332     return result;
   2333 }
   2334 
   2335 DRWAV_PRIVATE size_t drwav__strlen_clamped(const char* str, size_t maxToRead)
   2336 {
   2337     size_t result = 0;
   2338 
   2339     while (*str++ && result < maxToRead) {
   2340         result += 1;
   2341     }
   2342 
   2343     return result;
   2344 }
   2345 
   2346 DRWAV_PRIVATE char* drwav__metadata_copy_string(drwav__metadata_parser* pParser, const char* str, size_t maxToRead)
   2347 {
   2348     size_t len = drwav__strlen_clamped(str, maxToRead);
   2349 
   2350     if (len) {
   2351         char* result = (char*)drwav__metadata_get_memory(pParser, len + 1, 1);
   2352         DRWAV_ASSERT(result != NULL);
   2353 
   2354         DRWAV_COPY_MEMORY(result, str, len);
   2355         result[len] = '\0';
   2356 
   2357         return result;
   2358     } else {
   2359         return NULL;
   2360     }
   2361 }
   2362 
   2363 typedef struct
   2364 {
   2365     const void* pBuffer;
   2366     size_t sizeInBytes;
   2367     size_t cursor;
   2368 } drwav_buffer_reader;
   2369 
   2370 DRWAV_PRIVATE drwav_result drwav_buffer_reader_init(const void* pBuffer, size_t sizeInBytes, drwav_buffer_reader* pReader)
   2371 {
   2372     DRWAV_ASSERT(pBuffer != NULL);
   2373     DRWAV_ASSERT(pReader != NULL);
   2374 
   2375     DRWAV_ZERO_OBJECT(pReader);
   2376 
   2377     pReader->pBuffer     = pBuffer;
   2378     pReader->sizeInBytes = sizeInBytes;
   2379     pReader->cursor      = 0;
   2380 
   2381     return DRWAV_SUCCESS;
   2382 }
   2383 
   2384 DRWAV_PRIVATE const void* drwav_buffer_reader_ptr(const drwav_buffer_reader* pReader)
   2385 {
   2386     DRWAV_ASSERT(pReader != NULL);
   2387 
   2388     return drwav_offset_ptr(pReader->pBuffer, pReader->cursor);
   2389 }
   2390 
   2391 DRWAV_PRIVATE drwav_result drwav_buffer_reader_seek(drwav_buffer_reader* pReader, size_t bytesToSeek)
   2392 {
   2393     DRWAV_ASSERT(pReader != NULL);
   2394 
   2395     if (pReader->cursor + bytesToSeek > pReader->sizeInBytes) {
   2396         return DRWAV_BAD_SEEK;  /* Seeking too far forward. */
   2397     }
   2398 
   2399     pReader->cursor += bytesToSeek;
   2400 
   2401     return DRWAV_SUCCESS;
   2402 }
   2403 
   2404 DRWAV_PRIVATE drwav_result drwav_buffer_reader_read(drwav_buffer_reader* pReader, void* pDst, size_t bytesToRead, size_t* pBytesRead)
   2405 {
   2406     drwav_result result = DRWAV_SUCCESS;
   2407     size_t bytesRemaining;
   2408 
   2409     DRWAV_ASSERT(pReader != NULL);
   2410     
   2411     if (pBytesRead != NULL) {
   2412         *pBytesRead = 0;
   2413     }
   2414 
   2415     bytesRemaining = (pReader->sizeInBytes - pReader->cursor);
   2416     if (bytesToRead > bytesRemaining) {
   2417         bytesToRead = bytesRemaining;
   2418     }
   2419 
   2420     if (pDst == NULL) {
   2421         /* Seek. */
   2422         result = drwav_buffer_reader_seek(pReader, bytesToRead);
   2423     } else {
   2424         /* Read. */
   2425         DRWAV_COPY_MEMORY(pDst, drwav_buffer_reader_ptr(pReader), bytesToRead);
   2426         pReader->cursor += bytesToRead;
   2427     }
   2428 
   2429     DRWAV_ASSERT(pReader->cursor <= pReader->sizeInBytes);
   2430 
   2431     if (result == DRWAV_SUCCESS) {
   2432         if (pBytesRead != NULL) {
   2433             *pBytesRead = bytesToRead;
   2434         }
   2435     }
   2436 
   2437     return DRWAV_SUCCESS;
   2438 }
   2439 
   2440 DRWAV_PRIVATE drwav_result drwav_buffer_reader_read_u16(drwav_buffer_reader* pReader, drwav_uint16* pDst)
   2441 {
   2442     drwav_result result;
   2443     size_t bytesRead;
   2444     drwav_uint8 data[2];
   2445 
   2446     DRWAV_ASSERT(pReader != NULL);
   2447     DRWAV_ASSERT(pDst != NULL);
   2448 
   2449     *pDst = 0;  /* Safety. */
   2450 
   2451     result = drwav_buffer_reader_read(pReader, data, sizeof(*pDst), &bytesRead);
   2452     if (result != DRWAV_SUCCESS || bytesRead != sizeof(*pDst)) {
   2453         return result;
   2454     }
   2455 
   2456     *pDst = drwav_bytes_to_u16(data);
   2457 
   2458     return DRWAV_SUCCESS;
   2459 }
   2460 
   2461 DRWAV_PRIVATE drwav_result drwav_buffer_reader_read_u32(drwav_buffer_reader* pReader, drwav_uint32* pDst)
   2462 {
   2463     drwav_result result;
   2464     size_t bytesRead;
   2465     drwav_uint8 data[4];
   2466 
   2467     DRWAV_ASSERT(pReader != NULL);
   2468     DRWAV_ASSERT(pDst != NULL);
   2469 
   2470     *pDst = 0;  /* Safety. */
   2471 
   2472     result = drwav_buffer_reader_read(pReader, data, sizeof(*pDst), &bytesRead);
   2473     if (result != DRWAV_SUCCESS || bytesRead != sizeof(*pDst)) {
   2474         return result;
   2475     }
   2476 
   2477     *pDst = drwav_bytes_to_u32(data);
   2478 
   2479     return DRWAV_SUCCESS;
   2480 }
   2481 
   2482 
   2483 
   2484 DRWAV_PRIVATE drwav_uint64 drwav__read_bext_to_metadata_obj(drwav__metadata_parser* pParser, drwav_metadata* pMetadata, drwav_uint64 chunkSize)
   2485 {
   2486     drwav_uint8 bextData[DRWAV_BEXT_BYTES];
   2487     size_t bytesRead = drwav__metadata_parser_read(pParser, bextData, sizeof(bextData), NULL);
   2488 
   2489     DRWAV_ASSERT(pParser->stage == drwav__metadata_parser_stage_read);
   2490     
   2491     if (bytesRead == sizeof(bextData)) {
   2492         drwav_buffer_reader reader;
   2493         drwav_uint32 timeReferenceLow;
   2494         drwav_uint32 timeReferenceHigh;
   2495         size_t extraBytes;
   2496 
   2497         pMetadata->type = drwav_metadata_type_bext;
   2498 
   2499         if (drwav_buffer_reader_init(bextData, bytesRead, &reader) == DRWAV_SUCCESS) {
   2500             pMetadata->data.bext.pDescription = drwav__metadata_copy_string(pParser, (const char*)drwav_buffer_reader_ptr(&reader), DRWAV_BEXT_DESCRIPTION_BYTES);
   2501             drwav_buffer_reader_seek(&reader, DRWAV_BEXT_DESCRIPTION_BYTES);
   2502 
   2503             pMetadata->data.bext.pOriginatorName = drwav__metadata_copy_string(pParser, (const char*)drwav_buffer_reader_ptr(&reader), DRWAV_BEXT_ORIGINATOR_NAME_BYTES);
   2504             drwav_buffer_reader_seek(&reader, DRWAV_BEXT_ORIGINATOR_NAME_BYTES);
   2505 
   2506             pMetadata->data.bext.pOriginatorReference = drwav__metadata_copy_string(pParser, (const char*)drwav_buffer_reader_ptr(&reader), DRWAV_BEXT_ORIGINATOR_REF_BYTES);
   2507             drwav_buffer_reader_seek(&reader, DRWAV_BEXT_ORIGINATOR_REF_BYTES);
   2508 
   2509             drwav_buffer_reader_read(&reader, pMetadata->data.bext.pOriginationDate, sizeof(pMetadata->data.bext.pOriginationDate), NULL);
   2510             drwav_buffer_reader_read(&reader, pMetadata->data.bext.pOriginationTime, sizeof(pMetadata->data.bext.pOriginationTime), NULL);
   2511 
   2512             drwav_buffer_reader_read_u32(&reader, &timeReferenceLow);
   2513             drwav_buffer_reader_read_u32(&reader, &timeReferenceHigh);
   2514             pMetadata->data.bext.timeReference = ((drwav_uint64)timeReferenceHigh << 32) + timeReferenceLow;
   2515 
   2516             drwav_buffer_reader_read_u16(&reader, &pMetadata->data.bext.version);
   2517 
   2518             pMetadata->data.bext.pUMID = drwav__metadata_get_memory(pParser, DRWAV_BEXT_UMID_BYTES, 1);
   2519             drwav_buffer_reader_read(&reader, pMetadata->data.bext.pUMID, DRWAV_BEXT_UMID_BYTES, NULL);
   2520 
   2521             drwav_buffer_reader_read_u16(&reader, &pMetadata->data.bext.loudnessValue);
   2522             drwav_buffer_reader_read_u16(&reader, &pMetadata->data.bext.loudnessRange);
   2523             drwav_buffer_reader_read_u16(&reader, &pMetadata->data.bext.maxTruePeakLevel);
   2524             drwav_buffer_reader_read_u16(&reader, &pMetadata->data.bext.maxMomentaryLoudness);
   2525             drwav_buffer_reader_read_u16(&reader, &pMetadata->data.bext.maxShortTermLoudness);
   2526 
   2527             DRWAV_ASSERT((drwav_offset_ptr(drwav_buffer_reader_ptr(&reader), DRWAV_BEXT_RESERVED_BYTES)) == (bextData + DRWAV_BEXT_BYTES));
   2528 
   2529             extraBytes = (size_t)(chunkSize - DRWAV_BEXT_BYTES);
   2530             if (extraBytes > 0) {
   2531                 pMetadata->data.bext.pCodingHistory = (char*)drwav__metadata_get_memory(pParser, extraBytes + 1, 1);
   2532                 DRWAV_ASSERT(pMetadata->data.bext.pCodingHistory != NULL);
   2533 
   2534                 bytesRead += drwav__metadata_parser_read(pParser, pMetadata->data.bext.pCodingHistory, extraBytes, NULL);
   2535                 pMetadata->data.bext.codingHistorySize = (drwav_uint32)drwav__strlen(pMetadata->data.bext.pCodingHistory);
   2536             } else {
   2537                 pMetadata->data.bext.pCodingHistory    = NULL;
   2538                 pMetadata->data.bext.codingHistorySize = 0;
   2539             }
   2540         }
   2541     }
   2542 
   2543     return bytesRead;
   2544 }
   2545 
   2546 DRWAV_PRIVATE drwav_uint64 drwav__read_list_label_or_note_to_metadata_obj(drwav__metadata_parser* pParser, drwav_metadata* pMetadata, drwav_uint64 chunkSize, drwav_metadata_type type)
   2547 {
   2548     drwav_uint8 cueIDBuffer[DRWAV_LIST_LABEL_OR_NOTE_BYTES];
   2549     drwav_uint64 totalBytesRead = 0;
   2550     size_t bytesJustRead = drwav__metadata_parser_read(pParser, cueIDBuffer, sizeof(cueIDBuffer), &totalBytesRead);
   2551 
   2552     DRWAV_ASSERT(pParser->stage == drwav__metadata_parser_stage_read);    
   2553 
   2554     if (bytesJustRead == sizeof(cueIDBuffer)) {
   2555         drwav_uint32 sizeIncludingNullTerminator;
   2556 
   2557         pMetadata->type = type;
   2558         pMetadata->data.labelOrNote.cuePointId = drwav_bytes_to_u32(cueIDBuffer);
   2559 
   2560         sizeIncludingNullTerminator = (drwav_uint32)chunkSize - DRWAV_LIST_LABEL_OR_NOTE_BYTES;
   2561         if (sizeIncludingNullTerminator > 0) {
   2562             pMetadata->data.labelOrNote.stringLength = sizeIncludingNullTerminator - 1;
   2563             pMetadata->data.labelOrNote.pString      = (char*)drwav__metadata_get_memory(pParser, sizeIncludingNullTerminator, 1);
   2564             DRWAV_ASSERT(pMetadata->data.labelOrNote.pString != NULL);
   2565 
   2566             drwav__metadata_parser_read(pParser, pMetadata->data.labelOrNote.pString, sizeIncludingNullTerminator, &totalBytesRead);
   2567         } else {
   2568             pMetadata->data.labelOrNote.stringLength = 0;
   2569             pMetadata->data.labelOrNote.pString      = NULL;
   2570         }
   2571     }
   2572 
   2573     return totalBytesRead;
   2574 }
   2575 
   2576 DRWAV_PRIVATE drwav_uint64 drwav__read_list_labelled_cue_region_to_metadata_obj(drwav__metadata_parser* pParser, drwav_metadata* pMetadata, drwav_uint64 chunkSize)
   2577 {
   2578     drwav_uint8 buffer[DRWAV_LIST_LABELLED_TEXT_BYTES];
   2579     drwav_uint64 totalBytesRead = 0;
   2580     size_t bytesJustRead = drwav__metadata_parser_read(pParser, buffer, sizeof(buffer), &totalBytesRead);
   2581 
   2582     DRWAV_ASSERT(pParser->stage == drwav__metadata_parser_stage_read);
   2583 
   2584     if (bytesJustRead == sizeof(buffer)) {
   2585         drwav_uint32 sizeIncludingNullTerminator;
   2586 
   2587         pMetadata->type                                = drwav_metadata_type_list_labelled_cue_region;
   2588         pMetadata->data.labelledCueRegion.cuePointId   = drwav_bytes_to_u32(buffer + 0);
   2589         pMetadata->data.labelledCueRegion.sampleLength = drwav_bytes_to_u32(buffer + 4);
   2590         pMetadata->data.labelledCueRegion.purposeId[0] = buffer[8];
   2591         pMetadata->data.labelledCueRegion.purposeId[1] = buffer[9];
   2592         pMetadata->data.labelledCueRegion.purposeId[2] = buffer[10];
   2593         pMetadata->data.labelledCueRegion.purposeId[3] = buffer[11];
   2594         pMetadata->data.labelledCueRegion.country      = drwav_bytes_to_u16(buffer + 12);
   2595         pMetadata->data.labelledCueRegion.language     = drwav_bytes_to_u16(buffer + 14);
   2596         pMetadata->data.labelledCueRegion.dialect      = drwav_bytes_to_u16(buffer + 16);
   2597         pMetadata->data.labelledCueRegion.codePage     = drwav_bytes_to_u16(buffer + 18);
   2598 
   2599         sizeIncludingNullTerminator = (drwav_uint32)chunkSize - DRWAV_LIST_LABELLED_TEXT_BYTES;
   2600         if (sizeIncludingNullTerminator > 0) {
   2601             pMetadata->data.labelledCueRegion.stringLength = sizeIncludingNullTerminator - 1;
   2602             pMetadata->data.labelledCueRegion.pString      = (char*)drwav__metadata_get_memory(pParser, sizeIncludingNullTerminator, 1);
   2603             DRWAV_ASSERT(pMetadata->data.labelledCueRegion.pString != NULL);
   2604 
   2605             drwav__metadata_parser_read(pParser, pMetadata->data.labelledCueRegion.pString, sizeIncludingNullTerminator, &totalBytesRead);
   2606         } else {
   2607             pMetadata->data.labelledCueRegion.stringLength = 0;
   2608             pMetadata->data.labelledCueRegion.pString      = NULL;
   2609         }
   2610     }
   2611 
   2612     return totalBytesRead;
   2613 }
   2614 
   2615 DRWAV_PRIVATE drwav_uint64 drwav__metadata_process_info_text_chunk(drwav__metadata_parser* pParser, drwav_uint64 chunkSize, drwav_metadata_type type)
   2616 {
   2617     drwav_uint64 bytesRead = 0;
   2618     drwav_uint32 stringSizeWithNullTerminator = (drwav_uint32)chunkSize;
   2619 
   2620     if (pParser->stage == drwav__metadata_parser_stage_count) {
   2621         pParser->metadataCount += 1;
   2622         drwav__metadata_request_extra_memory_for_stage_2(pParser, stringSizeWithNullTerminator, 1);
   2623     } else {
   2624         drwav_metadata* pMetadata = &pParser->pMetadata[pParser->metadataCursor];
   2625         pMetadata->type = type;
   2626         if (stringSizeWithNullTerminator > 0) {
   2627             pMetadata->data.infoText.stringLength = stringSizeWithNullTerminator - 1;
   2628             pMetadata->data.infoText.pString = (char*)drwav__metadata_get_memory(pParser, stringSizeWithNullTerminator, 1);
   2629             DRWAV_ASSERT(pMetadata->data.infoText.pString != NULL);
   2630 
   2631             bytesRead = drwav__metadata_parser_read(pParser, pMetadata->data.infoText.pString, (size_t)stringSizeWithNullTerminator, NULL);
   2632             if (bytesRead == chunkSize) {
   2633                 pParser->metadataCursor += 1;
   2634             } else {
   2635                 /* Failed to parse. */
   2636             }
   2637         } else {
   2638             pMetadata->data.infoText.stringLength = 0;
   2639             pMetadata->data.infoText.pString      = NULL;
   2640             pParser->metadataCursor += 1;
   2641         }
   2642     }
   2643 
   2644     return bytesRead;
   2645 }
   2646 
   2647 DRWAV_PRIVATE drwav_uint64 drwav__metadata_process_unknown_chunk(drwav__metadata_parser* pParser, const drwav_uint8* pChunkId, drwav_uint64 chunkSize, drwav_metadata_location location)
   2648 {
   2649     drwav_uint64 bytesRead = 0;
   2650 
   2651     if (location == drwav_metadata_location_invalid) {
   2652         return 0;
   2653     }
   2654 
   2655     if (drwav_fourcc_equal(pChunkId, "data") || drwav_fourcc_equal(pChunkId, "fmt ") || drwav_fourcc_equal(pChunkId, "fact")) {
   2656         return 0;
   2657     }
   2658 
   2659     if (pParser->stage == drwav__metadata_parser_stage_count) {
   2660         pParser->metadataCount += 1;
   2661         drwav__metadata_request_extra_memory_for_stage_2(pParser, (size_t)chunkSize, 1);
   2662     } else {
   2663         drwav_metadata* pMetadata = &pParser->pMetadata[pParser->metadataCursor];
   2664         pMetadata->type                         = drwav_metadata_type_unknown;
   2665         pMetadata->data.unknown.chunkLocation   = location;
   2666         pMetadata->data.unknown.id[0]           = pChunkId[0];
   2667         pMetadata->data.unknown.id[1]           = pChunkId[1];
   2668         pMetadata->data.unknown.id[2]           = pChunkId[2];
   2669         pMetadata->data.unknown.id[3]           = pChunkId[3];
   2670         pMetadata->data.unknown.dataSizeInBytes = (drwav_uint32)chunkSize;
   2671         pMetadata->data.unknown.pData           = (drwav_uint8 *)drwav__metadata_get_memory(pParser, (size_t)chunkSize, 1);
   2672         DRWAV_ASSERT(pMetadata->data.unknown.pData != NULL);
   2673 
   2674         bytesRead = drwav__metadata_parser_read(pParser, pMetadata->data.unknown.pData, pMetadata->data.unknown.dataSizeInBytes, NULL);
   2675         if (bytesRead == pMetadata->data.unknown.dataSizeInBytes) {
   2676             pParser->metadataCursor += 1;
   2677         } else {
   2678             /* Failed to read. */
   2679         }
   2680     }
   2681 
   2682     return bytesRead;
   2683 }
   2684 
   2685 DRWAV_PRIVATE drwav_bool32 drwav__chunk_matches(drwav_metadata_type allowedMetadataTypes, const drwav_uint8* pChunkID, drwav_metadata_type type, const char* pID)
   2686 {
   2687     return (allowedMetadataTypes & type) && drwav_fourcc_equal(pChunkID, pID);
   2688 }
   2689 
   2690 DRWAV_PRIVATE drwav_uint64 drwav__metadata_process_chunk(drwav__metadata_parser* pParser, const drwav_chunk_header* pChunkHeader, drwav_metadata_type allowedMetadataTypes)
   2691 {
   2692     const drwav_uint8 *pChunkID = pChunkHeader->id.fourcc;
   2693     drwav_uint64 bytesRead = 0;
   2694 
   2695     if (drwav__chunk_matches(allowedMetadataTypes, pChunkID, drwav_metadata_type_smpl, "smpl")) {
   2696         if (pChunkHeader->sizeInBytes >= DRWAV_SMPL_BYTES) {
   2697             if (pParser->stage == drwav__metadata_parser_stage_count) {
   2698                 drwav_uint8 buffer[4];
   2699                 size_t bytesJustRead;
   2700 
   2701                 if (!pParser->onSeek(pParser->pReadSeekUserData, 28, drwav_seek_origin_current)) {
   2702                     return bytesRead;
   2703                 }
   2704                 bytesRead += 28;
   2705 
   2706                 bytesJustRead = drwav__metadata_parser_read(pParser, buffer, sizeof(buffer), &bytesRead);
   2707                 if (bytesJustRead == sizeof(buffer)) {
   2708                     drwav_uint32 loopCount = drwav_bytes_to_u32(buffer);
   2709                     drwav_uint64 calculatedLoopCount;
   2710 
   2711                     /* The loop count must be validated against the size of the chunk. */
   2712                     calculatedLoopCount = (pChunkHeader->sizeInBytes - DRWAV_SMPL_BYTES) / DRWAV_SMPL_LOOP_BYTES;
   2713                     if (calculatedLoopCount == loopCount) {
   2714                         bytesJustRead = drwav__metadata_parser_read(pParser, buffer, sizeof(buffer), &bytesRead);
   2715                         if (bytesJustRead == sizeof(buffer)) {
   2716                             drwav_uint32 samplerSpecificDataSizeInBytes = drwav_bytes_to_u32(buffer);
   2717 
   2718                             pParser->metadataCount += 1;
   2719                             drwav__metadata_request_extra_memory_for_stage_2(pParser, sizeof(drwav_smpl_loop) * loopCount, DRWAV_METADATA_ALIGNMENT);
   2720                             drwav__metadata_request_extra_memory_for_stage_2(pParser, samplerSpecificDataSizeInBytes, 1);
   2721                         }
   2722                     } else {
   2723                         /* Loop count in header does not match the size of the chunk. */
   2724                     }                    
   2725                 }
   2726             } else {
   2727                 bytesRead = drwav__read_smpl_to_metadata_obj(pParser, pChunkHeader, &pParser->pMetadata[pParser->metadataCursor]);
   2728                 if (bytesRead == pChunkHeader->sizeInBytes) {
   2729                     pParser->metadataCursor += 1;
   2730                 } else {
   2731                     /* Failed to parse. */
   2732                 }
   2733             }
   2734         } else {
   2735             /* Incorrectly formed chunk. */
   2736         }
   2737     } else if (drwav__chunk_matches(allowedMetadataTypes, pChunkID, drwav_metadata_type_inst, "inst")) {
   2738         if (pChunkHeader->sizeInBytes == DRWAV_INST_BYTES) {
   2739             if (pParser->stage == drwav__metadata_parser_stage_count) {
   2740                 pParser->metadataCount += 1;
   2741             } else {
   2742                 bytesRead = drwav__read_inst_to_metadata_obj(pParser, &pParser->pMetadata[pParser->metadataCursor]);
   2743                 if (bytesRead == pChunkHeader->sizeInBytes) {
   2744                     pParser->metadataCursor += 1;
   2745                 } else {
   2746                     /* Failed to parse. */
   2747                 }
   2748             }
   2749         } else {
   2750             /* Incorrectly formed chunk. */
   2751         }
   2752     } else if (drwav__chunk_matches(allowedMetadataTypes, pChunkID, drwav_metadata_type_acid, "acid")) {
   2753         if (pChunkHeader->sizeInBytes == DRWAV_ACID_BYTES) {
   2754             if (pParser->stage == drwav__metadata_parser_stage_count) {
   2755                 pParser->metadataCount += 1;
   2756             } else {
   2757                 bytesRead = drwav__read_acid_to_metadata_obj(pParser, &pParser->pMetadata[pParser->metadataCursor]);
   2758                 if (bytesRead == pChunkHeader->sizeInBytes) {
   2759                     pParser->metadataCursor += 1;
   2760                 } else {
   2761                     /* Failed to parse. */
   2762                 }
   2763             }
   2764         } else {
   2765             /* Incorrectly formed chunk. */
   2766         }
   2767     } else if (drwav__chunk_matches(allowedMetadataTypes, pChunkID, drwav_metadata_type_cue, "cue ")) {
   2768         if (pChunkHeader->sizeInBytes >= DRWAV_CUE_BYTES) {
   2769             if (pParser->stage == drwav__metadata_parser_stage_count) {
   2770                 size_t cueCount;
   2771 
   2772                 pParser->metadataCount += 1;
   2773                 cueCount = (size_t)(pChunkHeader->sizeInBytes - DRWAV_CUE_BYTES) / DRWAV_CUE_POINT_BYTES;
   2774                 drwav__metadata_request_extra_memory_for_stage_2(pParser, sizeof(drwav_cue_point) * cueCount, DRWAV_METADATA_ALIGNMENT);
   2775             } else {
   2776                 bytesRead = drwav__read_cue_to_metadata_obj(pParser, pChunkHeader, &pParser->pMetadata[pParser->metadataCursor]);
   2777                 if (bytesRead == pChunkHeader->sizeInBytes) {
   2778                     pParser->metadataCursor += 1;
   2779                 } else {
   2780                     /* Failed to parse. */
   2781                 }
   2782             }
   2783         } else {
   2784             /* Incorrectly formed chunk. */
   2785         }
   2786     } else if (drwav__chunk_matches(allowedMetadataTypes, pChunkID, drwav_metadata_type_bext, "bext")) {
   2787         if (pChunkHeader->sizeInBytes >= DRWAV_BEXT_BYTES) {
   2788             if (pParser->stage == drwav__metadata_parser_stage_count) {
   2789                 /* The description field is the largest one in a bext chunk, so that is the max size of this temporary buffer. */
   2790                 char buffer[DRWAV_BEXT_DESCRIPTION_BYTES + 1];
   2791                 size_t allocSizeNeeded = DRWAV_BEXT_UMID_BYTES; /* We know we will need SMPTE umid size. */
   2792                 size_t bytesJustRead;
   2793 
   2794                 buffer[DRWAV_BEXT_DESCRIPTION_BYTES] = '\0';
   2795                 bytesJustRead = drwav__metadata_parser_read(pParser, buffer, DRWAV_BEXT_DESCRIPTION_BYTES, &bytesRead);
   2796                 if (bytesJustRead != DRWAV_BEXT_DESCRIPTION_BYTES) {
   2797                     return bytesRead;
   2798                 }
   2799                 allocSizeNeeded += drwav__strlen(buffer) + 1;
   2800 
   2801                 buffer[DRWAV_BEXT_ORIGINATOR_NAME_BYTES] = '\0';
   2802                 bytesJustRead = drwav__metadata_parser_read(pParser, buffer, DRWAV_BEXT_ORIGINATOR_NAME_BYTES, &bytesRead);
   2803                 if (bytesJustRead != DRWAV_BEXT_ORIGINATOR_NAME_BYTES) {
   2804                     return bytesRead;
   2805                 }
   2806                 allocSizeNeeded += drwav__strlen(buffer) + 1;
   2807 
   2808                 buffer[DRWAV_BEXT_ORIGINATOR_REF_BYTES] = '\0';
   2809                 bytesJustRead = drwav__metadata_parser_read(pParser, buffer, DRWAV_BEXT_ORIGINATOR_REF_BYTES, &bytesRead);
   2810                 if (bytesJustRead != DRWAV_BEXT_ORIGINATOR_REF_BYTES) {
   2811                     return bytesRead;
   2812                 }
   2813                 allocSizeNeeded += drwav__strlen(buffer) + 1;
   2814                 allocSizeNeeded += (size_t)pChunkHeader->sizeInBytes - DRWAV_BEXT_BYTES; /* Coding history. */
   2815 
   2816                 drwav__metadata_request_extra_memory_for_stage_2(pParser, allocSizeNeeded, 1);
   2817 
   2818                 pParser->metadataCount += 1;
   2819             } else {
   2820                 bytesRead = drwav__read_bext_to_metadata_obj(pParser, &pParser->pMetadata[pParser->metadataCursor], pChunkHeader->sizeInBytes);
   2821                 if (bytesRead == pChunkHeader->sizeInBytes) {
   2822                     pParser->metadataCursor += 1;
   2823                 } else {
   2824                     /* Failed to parse. */
   2825                 }
   2826             }
   2827         } else {
   2828             /* Incorrectly formed chunk. */
   2829         }
   2830     } else if (drwav_fourcc_equal(pChunkID, "LIST") || drwav_fourcc_equal(pChunkID, "list")) {
   2831         drwav_metadata_location listType = drwav_metadata_location_invalid;
   2832         while (bytesRead < pChunkHeader->sizeInBytes) {
   2833             drwav_uint8 subchunkId[4];
   2834             drwav_uint8 subchunkSizeBuffer[4];
   2835             drwav_uint64 subchunkDataSize;
   2836             drwav_uint64 subchunkBytesRead = 0;
   2837             drwav_uint64 bytesJustRead = drwav__metadata_parser_read(pParser, subchunkId, sizeof(subchunkId), &bytesRead);
   2838             if (bytesJustRead != sizeof(subchunkId)) {
   2839                 break;
   2840             }
   2841 
   2842             /*
   2843             The first thing in a list chunk should be "adtl" or "INFO".
   2844 
   2845               - adtl means this list is a Associated Data List Chunk and will contain labels, notes
   2846                 or labelled cue regions.
   2847               - INFO means this list is an Info List Chunk containing info text chunks such as IPRD
   2848                 which would specifies the album of this wav file.
   2849 
   2850             No data follows the adtl or INFO id so we just make note of what type this list is and
   2851             continue.
   2852             */
   2853             if (drwav_fourcc_equal(subchunkId, "adtl")) {
   2854                 listType = drwav_metadata_location_inside_adtl_list;
   2855                 continue;
   2856             } else if (drwav_fourcc_equal(subchunkId, "INFO")) {
   2857                 listType = drwav_metadata_location_inside_info_list;
   2858                 continue;
   2859             }
   2860 
   2861             bytesJustRead = drwav__metadata_parser_read(pParser, subchunkSizeBuffer, sizeof(subchunkSizeBuffer), &bytesRead);
   2862             if (bytesJustRead != sizeof(subchunkSizeBuffer)) {
   2863                 break;
   2864             }
   2865             subchunkDataSize = drwav_bytes_to_u32(subchunkSizeBuffer);
   2866 
   2867             if (drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_label, "labl") || drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_note, "note")) {
   2868                 if (subchunkDataSize >= DRWAV_LIST_LABEL_OR_NOTE_BYTES) {
   2869                     drwav_uint64 stringSizeWithNullTerm = subchunkDataSize - DRWAV_LIST_LABEL_OR_NOTE_BYTES;
   2870                     if (pParser->stage == drwav__metadata_parser_stage_count) {
   2871                         pParser->metadataCount += 1;
   2872                         drwav__metadata_request_extra_memory_for_stage_2(pParser, (size_t)stringSizeWithNullTerm, 1);
   2873                     } else {
   2874                         subchunkBytesRead = drwav__read_list_label_or_note_to_metadata_obj(pParser, &pParser->pMetadata[pParser->metadataCursor], subchunkDataSize, drwav_fourcc_equal(subchunkId, "labl") ? drwav_metadata_type_list_label : drwav_metadata_type_list_note);
   2875                         if (subchunkBytesRead == subchunkDataSize) {
   2876                             pParser->metadataCursor += 1;
   2877                         } else {
   2878                             /* Failed to parse. */
   2879                         }
   2880                     }
   2881                 } else {
   2882                     /* Incorrectly formed chunk. */
   2883                 }
   2884             } else if (drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_labelled_cue_region, "ltxt")) {
   2885                 if (subchunkDataSize >= DRWAV_LIST_LABELLED_TEXT_BYTES) {
   2886                     drwav_uint64 stringSizeWithNullTerminator = subchunkDataSize - DRWAV_LIST_LABELLED_TEXT_BYTES;
   2887                     if (pParser->stage == drwav__metadata_parser_stage_count) {
   2888                         pParser->metadataCount += 1;
   2889                         drwav__metadata_request_extra_memory_for_stage_2(pParser, (size_t)stringSizeWithNullTerminator, 1);
   2890                     } else {
   2891                         subchunkBytesRead = drwav__read_list_labelled_cue_region_to_metadata_obj(pParser, &pParser->pMetadata[pParser->metadataCursor], subchunkDataSize);
   2892                         if (subchunkBytesRead == subchunkDataSize) {
   2893                             pParser->metadataCursor += 1;
   2894                         } else {
   2895                             /* Failed to parse. */
   2896                         }
   2897                     }
   2898                 } else {
   2899                     /* Incorrectly formed chunk. */
   2900                 }
   2901             } else if (drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_info_software, "ISFT")) {
   2902                 subchunkBytesRead = drwav__metadata_process_info_text_chunk(pParser, subchunkDataSize,  drwav_metadata_type_list_info_software);
   2903             } else if (drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_info_copyright, "ICOP")) {
   2904                 subchunkBytesRead = drwav__metadata_process_info_text_chunk(pParser, subchunkDataSize,  drwav_metadata_type_list_info_copyright);
   2905             } else if (drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_info_title, "INAM")) {
   2906                 subchunkBytesRead = drwav__metadata_process_info_text_chunk(pParser, subchunkDataSize,  drwav_metadata_type_list_info_title);
   2907             } else if (drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_info_artist, "IART")) {
   2908                 subchunkBytesRead = drwav__metadata_process_info_text_chunk(pParser, subchunkDataSize,  drwav_metadata_type_list_info_artist);
   2909             } else if (drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_info_comment, "ICMT")) {
   2910                 subchunkBytesRead = drwav__metadata_process_info_text_chunk(pParser, subchunkDataSize,  drwav_metadata_type_list_info_comment);
   2911             } else if (drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_info_date, "ICRD")) {
   2912                 subchunkBytesRead = drwav__metadata_process_info_text_chunk(pParser, subchunkDataSize,  drwav_metadata_type_list_info_date);
   2913             } else if (drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_info_genre, "IGNR")) {
   2914                 subchunkBytesRead = drwav__metadata_process_info_text_chunk(pParser, subchunkDataSize,  drwav_metadata_type_list_info_genre);
   2915             } else if (drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_info_album, "IPRD")) {
   2916                 subchunkBytesRead = drwav__metadata_process_info_text_chunk(pParser, subchunkDataSize,  drwav_metadata_type_list_info_album);
   2917             } else if (drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_info_tracknumber, "ITRK")) {
   2918                 subchunkBytesRead = drwav__metadata_process_info_text_chunk(pParser, subchunkDataSize,  drwav_metadata_type_list_info_tracknumber);
   2919             } else if ((allowedMetadataTypes & drwav_metadata_type_unknown) != 0) {
   2920                 subchunkBytesRead = drwav__metadata_process_unknown_chunk(pParser, subchunkId, subchunkDataSize, listType);
   2921             }
   2922 
   2923             bytesRead += subchunkBytesRead;
   2924             DRWAV_ASSERT(subchunkBytesRead <= subchunkDataSize);
   2925 
   2926             if (subchunkBytesRead < subchunkDataSize) {
   2927                 drwav_uint64 bytesToSeek = subchunkDataSize - subchunkBytesRead;
   2928 
   2929                 if (!pParser->onSeek(pParser->pReadSeekUserData, (int)bytesToSeek, drwav_seek_origin_current)) {
   2930                     break;
   2931                 }
   2932                 bytesRead += bytesToSeek;
   2933             }
   2934 
   2935             if ((subchunkDataSize % 2) == 1) {
   2936                 if (!pParser->onSeek(pParser->pReadSeekUserData, 1, drwav_seek_origin_current)) {
   2937                     break;
   2938                 }
   2939                 bytesRead += 1;
   2940             }
   2941         }
   2942     } else if ((allowedMetadataTypes & drwav_metadata_type_unknown) != 0) {
   2943         bytesRead = drwav__metadata_process_unknown_chunk(pParser, pChunkID, pChunkHeader->sizeInBytes, drwav_metadata_location_top_level);
   2944     }
   2945 
   2946     return bytesRead;
   2947 }
   2948 
   2949 
   2950 DRWAV_PRIVATE drwav_uint32 drwav_get_bytes_per_pcm_frame(drwav* pWav)
   2951 {
   2952     drwav_uint32 bytesPerFrame;
   2953 
   2954     /*
   2955     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
   2956     is that if the bits per sample is a multiple of 8, use floor(bitsPerSample*channels/8), otherwise fall back to the block align.
   2957     */
   2958     if ((pWav->bitsPerSample & 0x7) == 0) {
   2959         /* Bits per sample is a multiple of 8. */
   2960         bytesPerFrame = (pWav->bitsPerSample * pWav->fmt.channels) >> 3;
   2961     } else {
   2962         bytesPerFrame = pWav->fmt.blockAlign;
   2963     }
   2964 
   2965     /* Validation for known formats. a-law and mu-law should be 1 byte per channel. If it's not, it's not decodable. */
   2966     if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ALAW || pWav->translatedFormatTag == DR_WAVE_FORMAT_MULAW) {
   2967         if (bytesPerFrame != pWav->fmt.channels) {
   2968             return 0;   /* Invalid file. */
   2969         }
   2970     }
   2971 
   2972     return bytesPerFrame;
   2973 }
   2974 
   2975 DRWAV_API drwav_uint16 drwav_fmt_get_format(const drwav_fmt* pFMT)
   2976 {
   2977     if (pFMT == NULL) {
   2978         return 0;
   2979     }
   2980 
   2981     if (pFMT->formatTag != DR_WAVE_FORMAT_EXTENSIBLE) {
   2982         return pFMT->formatTag;
   2983     } else {
   2984         return drwav_bytes_to_u16(pFMT->subFormat);    /* Only the first two bytes are required. */
   2985     }
   2986 }
   2987 
   2988 DRWAV_PRIVATE drwav_bool32 drwav_preinit(drwav* pWav, drwav_read_proc onRead, drwav_seek_proc onSeek, void* pReadSeekUserData, const drwav_allocation_callbacks* pAllocationCallbacks)
   2989 {
   2990     if (pWav == NULL || onRead == NULL || onSeek == NULL) {
   2991         return DRWAV_FALSE;
   2992     }
   2993 
   2994     DRWAV_ZERO_MEMORY(pWav, sizeof(*pWav));
   2995     pWav->onRead    = onRead;
   2996     pWav->onSeek    = onSeek;
   2997     pWav->pUserData = pReadSeekUserData;
   2998     pWav->allocationCallbacks = drwav_copy_allocation_callbacks_or_defaults(pAllocationCallbacks);
   2999 
   3000     if (pWav->allocationCallbacks.onFree == NULL || (pWav->allocationCallbacks.onMalloc == NULL && pWav->allocationCallbacks.onRealloc == NULL)) {
   3001         return DRWAV_FALSE;    /* Invalid allocation callbacks. */
   3002     }
   3003 
   3004     return DRWAV_TRUE;
   3005 }
   3006 
   3007 DRWAV_PRIVATE drwav_bool32 drwav_init__internal(drwav* pWav, drwav_chunk_proc onChunk, void* pChunkUserData, drwav_uint32 flags)
   3008 {
   3009     /* This function assumes drwav_preinit() has been called beforehand. */
   3010     drwav_result result;
   3011     drwav_uint64 cursor;    /* <-- Keeps track of the byte position so we can seek to specific locations. */
   3012     drwav_bool32 sequential;
   3013     drwav_uint8 riff[4];
   3014     drwav_fmt fmt;
   3015     unsigned short translatedFormatTag;
   3016     drwav_uint64 dataChunkSize = 0;             /* <-- Important! Don't explicitly set this to 0 anywhere else. Calculation of the size of the data chunk is performed in different paths depending on the container. */
   3017     drwav_uint64 sampleCountFromFactChunk = 0;  /* Same as dataChunkSize - make sure this is the only place this is initialized to 0. */
   3018     drwav_uint64 metadataStartPos;
   3019     drwav__metadata_parser metadataParser;
   3020     drwav_bool8 isProcessingMetadata = DRWAV_FALSE;
   3021     drwav_bool8 foundChunk_fmt  = DRWAV_FALSE;
   3022     drwav_bool8 foundChunk_data = DRWAV_FALSE;
   3023     drwav_bool8 isAIFCFormType = DRWAV_FALSE;   /* Only used with AIFF. */
   3024     drwav_uint64 aiffFrameCount = 0;
   3025 
   3026     cursor = 0;
   3027     sequential = (flags & DRWAV_SEQUENTIAL) != 0;
   3028     DRWAV_ZERO_OBJECT(&fmt);
   3029 
   3030     /* The first 4 bytes should be the RIFF identifier. */
   3031     if (drwav__on_read(pWav->onRead, pWav->pUserData, riff, sizeof(riff), &cursor) != sizeof(riff)) {
   3032         return DRWAV_FALSE;
   3033     }
   3034 
   3035     /*
   3036     The first 4 bytes can be used to identify the container. For RIFF files it will start with "RIFF" and for
   3037     w64 it will start with "riff".
   3038     */
   3039     if (drwav_fourcc_equal(riff, "RIFF")) {
   3040         pWav->container = drwav_container_riff;
   3041     } else if (drwav_fourcc_equal(riff, "RIFX")) {
   3042         pWav->container = drwav_container_rifx;
   3043     } else if (drwav_fourcc_equal(riff, "riff")) {
   3044         int i;
   3045         drwav_uint8 riff2[12];
   3046 
   3047         pWav->container = drwav_container_w64;
   3048 
   3049         /* Check the rest of the GUID for validity. */
   3050         if (drwav__on_read(pWav->onRead, pWav->pUserData, riff2, sizeof(riff2), &cursor) != sizeof(riff2)) {
   3051             return DRWAV_FALSE;
   3052         }
   3053 
   3054         for (i = 0; i < 12; ++i) {
   3055             if (riff2[i] != drwavGUID_W64_RIFF[i+4]) {
   3056                 return DRWAV_FALSE;
   3057             }
   3058         }
   3059     } else if (drwav_fourcc_equal(riff, "RF64")) {
   3060         pWav->container = drwav_container_rf64;
   3061     } else if (drwav_fourcc_equal(riff, "FORM")) {
   3062         pWav->container = drwav_container_aiff;
   3063     } else {
   3064         return DRWAV_FALSE;   /* Unknown or unsupported container. */
   3065     }
   3066 
   3067 
   3068     if (pWav->container == drwav_container_riff || pWav->container == drwav_container_rifx || pWav->container == drwav_container_rf64) {
   3069         drwav_uint8 chunkSizeBytes[4];
   3070         drwav_uint8 wave[4];
   3071 
   3072         if (drwav__on_read(pWav->onRead, pWav->pUserData, chunkSizeBytes, sizeof(chunkSizeBytes), &cursor) != sizeof(chunkSizeBytes)) {
   3073             return DRWAV_FALSE;
   3074         }
   3075 
   3076         if (pWav->container == drwav_container_riff || pWav->container == drwav_container_rifx) {
   3077             if (drwav_bytes_to_u32_ex(chunkSizeBytes, pWav->container) < 36) {
   3078                 /*
   3079                 I've had a report of a WAV file failing to load when the size of the WAVE chunk is not encoded
   3080                 and is instead just set to 0. I'm going to relax the validation here to allow these files to
   3081                 load. Considering the chunk size isn't actually used this should be safe. With this change my
   3082                 test suite still passes.
   3083                 */
   3084                 /*return DRWAV_FALSE;*/    /* Chunk size should always be at least 36 bytes. */
   3085             }
   3086         } else if (pWav->container == drwav_container_rf64) {
   3087             if (drwav_bytes_to_u32_le(chunkSizeBytes) != 0xFFFFFFFF) {
   3088                 return DRWAV_FALSE;    /* Chunk size should always be set to -1/0xFFFFFFFF for RF64. The actual size is retrieved later. */
   3089             }
   3090         } else {
   3091             return DRWAV_FALSE; /* Should never hit this. */
   3092         }
   3093 
   3094         if (drwav__on_read(pWav->onRead, pWav->pUserData, wave, sizeof(wave), &cursor) != sizeof(wave)) {
   3095             return DRWAV_FALSE;
   3096         }
   3097 
   3098         if (!drwav_fourcc_equal(wave, "WAVE")) {
   3099             return DRWAV_FALSE;    /* Expecting "WAVE". */
   3100         }
   3101     } else if (pWav->container == drwav_container_w64) {
   3102         drwav_uint8 chunkSizeBytes[8];
   3103         drwav_uint8 wave[16];
   3104 
   3105         if (drwav__on_read(pWav->onRead, pWav->pUserData, chunkSizeBytes, sizeof(chunkSizeBytes), &cursor) != sizeof(chunkSizeBytes)) {
   3106             return DRWAV_FALSE;
   3107         }
   3108 
   3109         if (drwav_bytes_to_u64(chunkSizeBytes) < 80) {
   3110             return DRWAV_FALSE;
   3111         }
   3112 
   3113         if (drwav__on_read(pWav->onRead, pWav->pUserData, wave, sizeof(wave), &cursor) != sizeof(wave)) {
   3114             return DRWAV_FALSE;
   3115         }
   3116 
   3117         if (!drwav_guid_equal(wave, drwavGUID_W64_WAVE)) {
   3118             return DRWAV_FALSE;
   3119         }
   3120     } else if (pWav->container == drwav_container_aiff) {
   3121         drwav_uint8 chunkSizeBytes[4];
   3122         drwav_uint8 aiff[4];
   3123 
   3124         if (drwav__on_read(pWav->onRead, pWav->pUserData, chunkSizeBytes, sizeof(chunkSizeBytes), &cursor) != sizeof(chunkSizeBytes)) {
   3125             return DRWAV_FALSE;
   3126         }
   3127 
   3128         if (drwav_bytes_to_u32_be(chunkSizeBytes) < 18) {
   3129             return DRWAV_FALSE;
   3130         }
   3131 
   3132         if (drwav__on_read(pWav->onRead, pWav->pUserData, aiff, sizeof(aiff), &cursor) != sizeof(aiff)) {
   3133             return DRWAV_FALSE;
   3134         }
   3135 
   3136         if (drwav_fourcc_equal(aiff, "AIFF")) {
   3137             isAIFCFormType = DRWAV_FALSE;
   3138         } else if (drwav_fourcc_equal(aiff, "AIFC")) {
   3139             isAIFCFormType = DRWAV_TRUE;
   3140         } else {
   3141             return DRWAV_FALSE; /* Expecting "AIFF" or "AIFC". */
   3142         }
   3143     } else {
   3144         return DRWAV_FALSE;
   3145     }
   3146 
   3147 
   3148     /* For RF64, the "ds64" chunk must come next, before the "fmt " chunk. */
   3149     if (pWav->container == drwav_container_rf64) {
   3150         drwav_uint8 sizeBytes[8];
   3151         drwav_uint64 bytesRemainingInChunk;
   3152         drwav_chunk_header header;
   3153         result = drwav__read_chunk_header(pWav->onRead, pWav->pUserData, pWav->container, &cursor, &header);
   3154         if (result != DRWAV_SUCCESS) {
   3155             return DRWAV_FALSE;
   3156         }
   3157 
   3158         if (!drwav_fourcc_equal(header.id.fourcc, "ds64")) {
   3159             return DRWAV_FALSE; /* Expecting "ds64". */
   3160         }
   3161 
   3162         bytesRemainingInChunk = header.sizeInBytes + header.paddingSize;
   3163 
   3164         /* We don't care about the size of the RIFF chunk - skip it. */
   3165         if (!drwav__seek_forward(pWav->onSeek, 8, pWav->pUserData)) {
   3166             return DRWAV_FALSE;
   3167         }
   3168         bytesRemainingInChunk -= 8;
   3169         cursor += 8;
   3170 
   3171 
   3172         /* Next 8 bytes is the size of the "data" chunk. */
   3173         if (drwav__on_read(pWav->onRead, pWav->pUserData, sizeBytes, sizeof(sizeBytes), &cursor) != sizeof(sizeBytes)) {
   3174             return DRWAV_FALSE;
   3175         }
   3176         bytesRemainingInChunk -= 8;
   3177         dataChunkSize = drwav_bytes_to_u64(sizeBytes);
   3178 
   3179 
   3180         /* Next 8 bytes is the same count which we would usually derived from the FACT chunk if it was available. */
   3181         if (drwav__on_read(pWav->onRead, pWav->pUserData, sizeBytes, sizeof(sizeBytes), &cursor) != sizeof(sizeBytes)) {
   3182             return DRWAV_FALSE;
   3183         }
   3184         bytesRemainingInChunk -= 8;
   3185         sampleCountFromFactChunk = drwav_bytes_to_u64(sizeBytes);
   3186 
   3187 
   3188         /* Skip over everything else. */
   3189         if (!drwav__seek_forward(pWav->onSeek, bytesRemainingInChunk, pWav->pUserData)) {
   3190             return DRWAV_FALSE;
   3191         }
   3192         cursor += bytesRemainingInChunk;
   3193     }
   3194 
   3195 
   3196     metadataStartPos = cursor;
   3197 
   3198     /*
   3199     Whether or not we are processing metadata controls how we load. We can load more efficiently when
   3200     metadata is not being processed, but we also cannot process metadata for Wave64 because I have not
   3201     been able to test it. If someone is able to test this and provide a patch I'm happy to enable it.
   3202 
   3203     Seqential mode cannot support metadata because it involves seeking backwards.
   3204     */
   3205     isProcessingMetadata = !sequential && ((flags & DRWAV_WITH_METADATA) != 0);
   3206 
   3207     /* Don't allow processing of metadata with untested containers. */
   3208     if (pWav->container != drwav_container_riff && pWav->container != drwav_container_rf64) {
   3209         isProcessingMetadata = DRWAV_FALSE;
   3210     }
   3211 
   3212     DRWAV_ZERO_MEMORY(&metadataParser, sizeof(metadataParser));
   3213     if (isProcessingMetadata) {
   3214         metadataParser.onRead = pWav->onRead;
   3215         metadataParser.onSeek = pWav->onSeek;
   3216         metadataParser.pReadSeekUserData = pWav->pUserData;
   3217         metadataParser.stage  = drwav__metadata_parser_stage_count;
   3218     }
   3219 
   3220 
   3221     /*
   3222     From here on out, chunks might be in any order. In order to robustly handle metadata we'll need
   3223     to loop through every chunk and handle them as we find them. In sequential mode we need to get
   3224     out of the loop as soon as we find the data chunk because we won't be able to seek back.
   3225     */
   3226     for (;;) {  /* For each chunk... */
   3227         drwav_chunk_header header;
   3228         drwav_uint64 chunkSize;
   3229 
   3230         result = drwav__read_chunk_header(pWav->onRead, pWav->pUserData, pWav->container, &cursor, &header);
   3231         if (result != DRWAV_SUCCESS) {
   3232             break;
   3233         }
   3234 
   3235         chunkSize = header.sizeInBytes;
   3236 
   3237 
   3238         /*
   3239         Always tell the caller about this chunk. We cannot do this in sequential mode because the
   3240         callback is allowed to read from the file, in which case we'll need to rewind.
   3241         */
   3242         if (!sequential && onChunk != NULL) {
   3243             drwav_uint64 callbackBytesRead = onChunk(pChunkUserData, pWav->onRead, pWav->onSeek, pWav->pUserData, &header, pWav->container, &fmt);
   3244 
   3245             /*
   3246             dr_wav may need to read the contents of the chunk, so we now need to seek back to the position before
   3247             we called the callback.
   3248             */
   3249             if (callbackBytesRead > 0) {
   3250                 if (drwav__seek_from_start(pWav->onSeek, cursor, pWav->pUserData) == DRWAV_FALSE) {
   3251                     return DRWAV_FALSE;
   3252                 }
   3253             }
   3254         }
   3255 
   3256 
   3257         /* Explicitly handle known chunks first. */
   3258 
   3259         /* "fmt " */
   3260         if (((pWav->container == drwav_container_riff || pWav->container == drwav_container_rifx || pWav->container == drwav_container_rf64) && drwav_fourcc_equal(header.id.fourcc, "fmt ")) ||
   3261             ((pWav->container == drwav_container_w64) && drwav_guid_equal(header.id.guid, drwavGUID_W64_FMT))) {
   3262             drwav_uint8 fmtData[16];
   3263 
   3264             foundChunk_fmt = DRWAV_TRUE;
   3265 
   3266             if (pWav->onRead(pWav->pUserData, fmtData, sizeof(fmtData)) != sizeof(fmtData)) {
   3267                 return DRWAV_FALSE;
   3268             }
   3269             cursor += sizeof(fmtData);
   3270 
   3271             fmt.formatTag      = drwav_bytes_to_u16_ex(fmtData + 0,  pWav->container);
   3272             fmt.channels       = drwav_bytes_to_u16_ex(fmtData + 2,  pWav->container);
   3273             fmt.sampleRate     = drwav_bytes_to_u32_ex(fmtData + 4,  pWav->container);
   3274             fmt.avgBytesPerSec = drwav_bytes_to_u32_ex(fmtData + 8,  pWav->container);
   3275             fmt.blockAlign     = drwav_bytes_to_u16_ex(fmtData + 12, pWav->container);
   3276             fmt.bitsPerSample  = drwav_bytes_to_u16_ex(fmtData + 14, pWav->container);
   3277 
   3278             fmt.extendedSize       = 0;
   3279             fmt.validBitsPerSample = 0;
   3280             fmt.channelMask        = 0;
   3281             DRWAV_ZERO_MEMORY(fmt.subFormat, sizeof(fmt.subFormat));
   3282 
   3283             if (header.sizeInBytes > 16) {
   3284                 drwav_uint8 fmt_cbSize[2];
   3285                 int bytesReadSoFar = 0;
   3286 
   3287                 if (pWav->onRead(pWav->pUserData, fmt_cbSize, sizeof(fmt_cbSize)) != sizeof(fmt_cbSize)) {
   3288                     return DRWAV_FALSE;    /* Expecting more data. */
   3289                 }
   3290                 cursor += sizeof(fmt_cbSize);
   3291 
   3292                 bytesReadSoFar = 18;
   3293 
   3294                 fmt.extendedSize = drwav_bytes_to_u16_ex(fmt_cbSize, pWav->container);
   3295                 if (fmt.extendedSize > 0) {
   3296                     /* Simple validation. */
   3297                     if (fmt.formatTag == DR_WAVE_FORMAT_EXTENSIBLE) {
   3298                         if (fmt.extendedSize != 22) {
   3299                             return DRWAV_FALSE;
   3300                         }
   3301                     }
   3302 
   3303                     if (fmt.formatTag == DR_WAVE_FORMAT_EXTENSIBLE) {
   3304                         drwav_uint8 fmtext[22];
   3305 
   3306                         if (pWav->onRead(pWav->pUserData, fmtext, fmt.extendedSize) != fmt.extendedSize) {
   3307                             return DRWAV_FALSE;    /* Expecting more data. */
   3308                         }
   3309 
   3310                         fmt.validBitsPerSample = drwav_bytes_to_u16_ex(fmtext + 0, pWav->container);
   3311                         fmt.channelMask        = drwav_bytes_to_u32_ex(fmtext + 2, pWav->container);
   3312                         drwav_bytes_to_guid(fmtext + 6, fmt.subFormat);
   3313                     } else {
   3314                         if (pWav->onSeek(pWav->pUserData, fmt.extendedSize, drwav_seek_origin_current) == DRWAV_FALSE) {
   3315                             return DRWAV_FALSE;
   3316                         }
   3317                     }
   3318                     cursor += fmt.extendedSize;
   3319 
   3320                     bytesReadSoFar += fmt.extendedSize;
   3321                 }
   3322 
   3323                 /* Seek past any leftover bytes. For w64 the leftover will be defined based on the chunk size. */
   3324                 if (pWav->onSeek(pWav->pUserData, (int)(header.sizeInBytes - bytesReadSoFar), drwav_seek_origin_current) == DRWAV_FALSE) {
   3325                     return DRWAV_FALSE;
   3326                 }
   3327                 cursor += (header.sizeInBytes - bytesReadSoFar);
   3328             }
   3329 
   3330             if (header.paddingSize > 0) {
   3331                 if (drwav__seek_forward(pWav->onSeek, header.paddingSize, pWav->pUserData) == DRWAV_FALSE) {
   3332                     break;
   3333                 }
   3334                 cursor += header.paddingSize;
   3335             }
   3336 
   3337             /* Go to the next chunk. Don't include this chunk in metadata. */
   3338             continue;
   3339         }
   3340 
   3341         /* "data" */
   3342         if (((pWav->container == drwav_container_riff || pWav->container == drwav_container_rifx || pWav->container == drwav_container_rf64) && drwav_fourcc_equal(header.id.fourcc, "data")) ||
   3343             ((pWav->container == drwav_container_w64) && drwav_guid_equal(header.id.guid, drwavGUID_W64_DATA))) {
   3344             foundChunk_data = DRWAV_TRUE;
   3345             
   3346             pWav->dataChunkDataPos  = cursor;
   3347 
   3348             if (pWav->container != drwav_container_rf64) {  /* The data chunk size for RF64 will always be set to 0xFFFFFFFF here. It was set to it's true value earlier. */
   3349                 dataChunkSize = chunkSize;
   3350             }
   3351 
   3352             /* If we're running in sequential mode, or we're not reading metadata, we have enough now that we can get out of the loop. */
   3353             if (sequential || !isProcessingMetadata) {
   3354                 break;      /* No need to keep reading beyond the data chunk. */
   3355             } else {
   3356                 chunkSize += header.paddingSize;    /* <-- Make sure we seek past the padding. */
   3357                 if (drwav__seek_forward(pWav->onSeek, chunkSize, pWav->pUserData) == DRWAV_FALSE) {
   3358                     break;
   3359                 }
   3360                 cursor += chunkSize;
   3361 
   3362                 continue;   /* There may be some more metadata to read. */
   3363             }
   3364         }
   3365 
   3366         /* "fact". This is optional. Can use this to get the sample count which is useful for compressed formats. For RF64 we retrieved the sample count from the ds64 chunk earlier. */
   3367         if (((pWav->container == drwav_container_riff || pWav->container == drwav_container_rifx || pWav->container == drwav_container_rf64) && drwav_fourcc_equal(header.id.fourcc, "fact")) ||
   3368             ((pWav->container == drwav_container_w64) && drwav_guid_equal(header.id.guid, drwavGUID_W64_FACT))) {
   3369             if (pWav->container == drwav_container_riff || pWav->container == drwav_container_rifx) {
   3370                 drwav_uint8 sampleCount[4];
   3371                 if (drwav__on_read(pWav->onRead, pWav->pUserData, &sampleCount, 4, &cursor) != 4) {
   3372                     return DRWAV_FALSE;
   3373                 }
   3374 
   3375                 chunkSize -= 4;
   3376 
   3377                 /*
   3378                 The sample count in the "fact" chunk is either unreliable, or I'm not understanding it properly. For now I am only enabling this
   3379                 for Microsoft ADPCM formats.
   3380                 */
   3381                 if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ADPCM) {
   3382                     sampleCountFromFactChunk = drwav_bytes_to_u32_ex(sampleCount, pWav->container);
   3383                 } else {
   3384                     sampleCountFromFactChunk = 0;
   3385                 }
   3386             } else if (pWav->container == drwav_container_w64) {
   3387                 if (drwav__on_read(pWav->onRead, pWav->pUserData, &sampleCountFromFactChunk, 8, &cursor) != 8) {
   3388                     return DRWAV_FALSE;
   3389                 }
   3390 
   3391                 chunkSize -= 8;
   3392             } else if (pWav->container == drwav_container_rf64) {
   3393                 /* We retrieved the sample count from the ds64 chunk earlier so no need to do that here. */
   3394             }
   3395 
   3396             /* Seek to the next chunk in preparation for the next iteration. */
   3397             chunkSize += header.paddingSize;    /* <-- Make sure we seek past the padding. */
   3398             if (drwav__seek_forward(pWav->onSeek, chunkSize, pWav->pUserData) == DRWAV_FALSE) {
   3399                 break;
   3400             }
   3401             cursor += chunkSize;
   3402 
   3403             continue;
   3404         }
   3405 
   3406 
   3407         /* "COMM". AIFF/AIFC only. */
   3408         if (pWav->container == drwav_container_aiff && drwav_fourcc_equal(header.id.fourcc, "COMM")) {
   3409             drwav_uint8 commData[24];
   3410             drwav_uint32 commDataBytesToRead;
   3411             drwav_uint16 channels;
   3412             drwav_uint32 frameCount;
   3413             drwav_uint16 sampleSizeInBits;
   3414             drwav_int64  sampleRate;
   3415             drwav_uint16 compressionFormat;
   3416 
   3417             foundChunk_fmt = DRWAV_TRUE;
   3418 
   3419             if (isAIFCFormType) {
   3420                 commDataBytesToRead = 24;
   3421                 if (header.sizeInBytes < commDataBytesToRead) {
   3422                     return DRWAV_FALSE; /* Invalid COMM chunk. */
   3423                 }
   3424             } else {
   3425                 commDataBytesToRead = 18;
   3426                 if (header.sizeInBytes != commDataBytesToRead) {
   3427                     return DRWAV_FALSE; /* INVALID COMM chunk. */
   3428                 }
   3429             }
   3430 
   3431             if (drwav__on_read(pWav->onRead, pWav->pUserData, commData, commDataBytesToRead, &cursor) != commDataBytesToRead) {
   3432                 return DRWAV_FALSE;
   3433             }
   3434 
   3435             
   3436             channels         = drwav_bytes_to_u16_ex     (commData + 0, pWav->container);
   3437             frameCount       = drwav_bytes_to_u32_ex     (commData + 2, pWav->container);
   3438             sampleSizeInBits = drwav_bytes_to_u16_ex     (commData + 6, pWav->container);
   3439             sampleRate       = drwav_aiff_extented_to_s64(commData + 8);
   3440 
   3441             if (sampleRate < 0 || sampleRate > 0xFFFFFFFF) {
   3442                 return DRWAV_FALSE; /* Invalid sample rate. */
   3443             }
   3444 
   3445             if (isAIFCFormType) {
   3446                 const drwav_uint8* type = commData + 18;
   3447 
   3448                 if (drwav_fourcc_equal(type, "NONE")) {
   3449                     compressionFormat = DR_WAVE_FORMAT_PCM; /* PCM, big-endian. */
   3450                 } else if (drwav_fourcc_equal(type, "raw ")) {
   3451                     compressionFormat = DR_WAVE_FORMAT_PCM;
   3452 
   3453                     /* In my testing, it looks like when the "raw " compression type is used, 8-bit samples should be considered unsigned. */
   3454                     if (sampleSizeInBits == 8) {
   3455                         pWav->aiff.isUnsigned = DRWAV_TRUE;
   3456                     }
   3457                 } else if (drwav_fourcc_equal(type, "sowt")) {
   3458                     compressionFormat = DR_WAVE_FORMAT_PCM; /* PCM, little-endian. */
   3459                     pWav->aiff.isLE = DRWAV_TRUE;
   3460                 } else if (drwav_fourcc_equal(type, "fl32") || drwav_fourcc_equal(type, "fl64") || drwav_fourcc_equal(type, "FL32") || drwav_fourcc_equal(type, "FL64")) {
   3461                     compressionFormat = DR_WAVE_FORMAT_IEEE_FLOAT;
   3462                 } else if (drwav_fourcc_equal(type, "alaw") || drwav_fourcc_equal(type, "ALAW")) {
   3463                     compressionFormat = DR_WAVE_FORMAT_ALAW;
   3464                 } else if (drwav_fourcc_equal(type, "ulaw") || drwav_fourcc_equal(type, "ULAW")) {
   3465                     compressionFormat = DR_WAVE_FORMAT_MULAW;
   3466                 } else if (drwav_fourcc_equal(type, "ima4")) {
   3467                     compressionFormat = DR_WAVE_FORMAT_DVI_ADPCM;
   3468                     sampleSizeInBits = 4;
   3469 
   3470                     /*
   3471                     I haven't been able to figure out how to get correct decoding for IMA ADPCM. Until this is figured out
   3472                     we'll need to abort when we encounter such an encoding. Advice welcome!
   3473                     */
   3474                     return DRWAV_FALSE;
   3475                 } else {
   3476                     return DRWAV_FALSE; /* Unknown or unsupported compression format. Need to abort. */
   3477                 }
   3478             } else {
   3479                 compressionFormat = DR_WAVE_FORMAT_PCM; /* It's a standard AIFF form which is always compressed. */
   3480             }
   3481 
   3482             /* With AIFF we want to use the explicitly defined frame count rather than deriving it from the size of the chunk. */
   3483             aiffFrameCount = frameCount;
   3484 
   3485             /* We should now have enough information to fill out our fmt structure. */
   3486             fmt.formatTag      = compressionFormat;
   3487             fmt.channels       = channels;
   3488             fmt.sampleRate     = (drwav_uint32)sampleRate;
   3489             fmt.bitsPerSample  = sampleSizeInBits;
   3490             fmt.blockAlign     = (drwav_uint16)(fmt.channels * fmt.bitsPerSample / 8);
   3491             fmt.avgBytesPerSec = fmt.blockAlign * fmt.sampleRate;
   3492 
   3493             if (fmt.blockAlign == 0 && compressionFormat == DR_WAVE_FORMAT_DVI_ADPCM) {
   3494                 fmt.blockAlign = 34 * fmt.channels;
   3495             }
   3496 
   3497             /*
   3498             Weird one. I've seen some alaw and ulaw encoded files that for some reason set the bits per sample to 16 when
   3499             it should be 8. To get this working I need to explicitly check for this and change it.
   3500             */
   3501             if (compressionFormat == DR_WAVE_FORMAT_ALAW || compressionFormat == DR_WAVE_FORMAT_MULAW) {
   3502                 if (fmt.bitsPerSample > 8) {
   3503                     fmt.bitsPerSample = 8;
   3504                     fmt.blockAlign = fmt.channels;
   3505                 }
   3506             }
   3507 
   3508             /* In AIFF, samples are padded to 8 byte boundaries. We need to round up our bits per sample here. */
   3509             fmt.bitsPerSample += (fmt.bitsPerSample & 7);
   3510             
   3511 
   3512             /* If the form type is AIFC there will be some additional data in the chunk. We need to seek past it. */
   3513             if (isAIFCFormType) {
   3514                 if (drwav__seek_forward(pWav->onSeek, (chunkSize - commDataBytesToRead), pWav->pUserData) == DRWAV_FALSE) {
   3515                     return DRWAV_FALSE;
   3516                 }
   3517                 cursor += (chunkSize - commDataBytesToRead);
   3518             }
   3519 
   3520             /* Don't fall through or else we'll end up treating this chunk as metadata which is incorrect. */
   3521             continue;
   3522         }
   3523 
   3524 
   3525         /* "SSND". AIFF/AIFC only. This is the AIFF equivalent of the "data" chunk. */
   3526         if (pWav->container == drwav_container_aiff && drwav_fourcc_equal(header.id.fourcc, "SSND")) {
   3527             drwav_uint8 offsetAndBlockSizeData[8];
   3528             drwav_uint32 offset;
   3529 
   3530             foundChunk_data = DRWAV_TRUE;
   3531 
   3532             if (drwav__on_read(pWav->onRead, pWav->pUserData, offsetAndBlockSizeData, sizeof(offsetAndBlockSizeData), &cursor) != sizeof(offsetAndBlockSizeData)) {
   3533                 return DRWAV_FALSE;
   3534             }
   3535 
   3536             /* We need to seek forward by the offset. */
   3537             offset = drwav_bytes_to_u32_ex(offsetAndBlockSizeData + 0, pWav->container);
   3538             if (drwav__seek_forward(pWav->onSeek, offset, pWav->pUserData) == DRWAV_FALSE) {
   3539                 return DRWAV_FALSE;
   3540             }
   3541             cursor += offset;
   3542 
   3543             pWav->dataChunkDataPos = cursor;
   3544             dataChunkSize = chunkSize;
   3545 
   3546             /* If we're running in sequential mode, or we're not reading metadata, we have enough now that we can get out of the loop. */
   3547             if (sequential || !isProcessingMetadata) {
   3548                 break;      /* No need to keep reading beyond the data chunk. */
   3549             } else {
   3550                 if (drwav__seek_forward(pWav->onSeek, chunkSize, pWav->pUserData) == DRWAV_FALSE) {
   3551                     break;
   3552                 }
   3553                 cursor += chunkSize;
   3554 
   3555                 continue;   /* There may be some more metadata to read. */
   3556             }
   3557         }
   3558 
   3559 
   3560 
   3561         /* Getting here means it's not a chunk that we care about internally, but might need to be handled as metadata by the caller. */
   3562         if (isProcessingMetadata) {
   3563             drwav__metadata_process_chunk(&metadataParser, &header, drwav_metadata_type_all_including_unknown);
   3564 
   3565             /* Go back to the start of the chunk so we can normalize the position of the cursor. */
   3566             if (drwav__seek_from_start(pWav->onSeek, cursor, pWav->pUserData) == DRWAV_FALSE) {
   3567                 break;  /* Failed to seek. Can't reliable read the remaining chunks. Get out. */
   3568             }
   3569         }
   3570 
   3571 
   3572         /* Make sure we skip past the content of this chunk before we go to the next one. */
   3573         chunkSize += header.paddingSize;    /* <-- Make sure we seek past the padding. */
   3574         if (drwav__seek_forward(pWav->onSeek, chunkSize, pWav->pUserData) == DRWAV_FALSE) {
   3575             break;
   3576         }
   3577         cursor += chunkSize;
   3578     }
   3579 
   3580     /* There's some mandatory chunks that must exist. If they were not found in the iteration above we must abort. */
   3581     if (!foundChunk_fmt || !foundChunk_data) {
   3582         return DRWAV_FALSE;
   3583     }
   3584 
   3585     /* Basic validation. */
   3586     if ((fmt.sampleRate    == 0 || fmt.sampleRate    > DRWAV_MAX_SAMPLE_RATE    ) ||
   3587         (fmt.channels      == 0 || fmt.channels      > DRWAV_MAX_CHANNELS       ) ||
   3588         (fmt.bitsPerSample == 0 || fmt.bitsPerSample > DRWAV_MAX_BITS_PER_SAMPLE) ||
   3589         fmt.blockAlign == 0) {
   3590         return DRWAV_FALSE; /* Probably an invalid WAV file. */
   3591     }
   3592 
   3593     /* Translate the internal format. */
   3594     translatedFormatTag = fmt.formatTag;
   3595     if (translatedFormatTag == DR_WAVE_FORMAT_EXTENSIBLE) {
   3596         translatedFormatTag = drwav_bytes_to_u16_ex(fmt.subFormat + 0, pWav->container);
   3597     }
   3598 
   3599     /* 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. */
   3600     if (!sequential) {
   3601         if (!drwav__seek_from_start(pWav->onSeek, pWav->dataChunkDataPos, pWav->pUserData)) {
   3602             return DRWAV_FALSE;
   3603         }
   3604         cursor = pWav->dataChunkDataPos;
   3605     }
   3606 
   3607 
   3608     /*
   3609     At this point we should have done the initial parsing of each of our chunks, but we now need to
   3610     do a second pass to extract the actual contents of the metadata (the first pass just calculated
   3611     the length of the memory allocation).
   3612 
   3613     We only do this if we've actually got metadata to parse.
   3614     */
   3615     if (isProcessingMetadata && metadataParser.metadataCount > 0) {
   3616         if (drwav__seek_from_start(pWav->onSeek, metadataStartPos, pWav->pUserData) == DRWAV_FALSE) {
   3617             return DRWAV_FALSE;
   3618         }
   3619 
   3620         result = drwav__metadata_alloc(&metadataParser, &pWav->allocationCallbacks);
   3621         if (result != DRWAV_SUCCESS) {
   3622             return DRWAV_FALSE;
   3623         }
   3624 
   3625         metadataParser.stage = drwav__metadata_parser_stage_read;
   3626 
   3627         for (;;) {
   3628             drwav_chunk_header header;
   3629             drwav_uint64 metadataBytesRead;
   3630 
   3631             result = drwav__read_chunk_header(pWav->onRead, pWav->pUserData, pWav->container, &cursor, &header);
   3632             if (result != DRWAV_SUCCESS) {
   3633                 break;
   3634             }
   3635 
   3636             metadataBytesRead = drwav__metadata_process_chunk(&metadataParser, &header, drwav_metadata_type_all_including_unknown);
   3637 
   3638             /* Move to the end of the chunk so we can keep iterating. */
   3639             if (drwav__seek_forward(pWav->onSeek, (header.sizeInBytes + header.paddingSize) - metadataBytesRead, pWav->pUserData) == DRWAV_FALSE) {
   3640                 drwav_free(metadataParser.pMetadata, &pWav->allocationCallbacks);
   3641                 return DRWAV_FALSE;
   3642             }
   3643         }
   3644 
   3645         /* Getting here means we're finished parsing the metadata. */
   3646         pWav->pMetadata     = metadataParser.pMetadata;
   3647         pWav->metadataCount = metadataParser.metadataCount;
   3648     }
   3649 
   3650 
   3651     /* At this point we should be sitting on the first byte of the raw audio data. */
   3652 
   3653     /*
   3654     I've seen a WAV file in the wild where a RIFF-ecapsulated file has the size of it's "RIFF" and
   3655     "data" chunks set to 0xFFFFFFFF when the file is definitely not that big. In this case we're
   3656     going to have to calculate the size by reading and discarding bytes, and then seeking back. We
   3657     cannot do this in sequential mode. We just assume that the rest of the file is audio data.
   3658     */
   3659     if (dataChunkSize == 0xFFFFFFFF && (pWav->container == drwav_container_riff || pWav->container == drwav_container_rifx) && pWav->isSequentialWrite == DRWAV_FALSE) {
   3660         dataChunkSize = 0;
   3661 
   3662         for (;;) {
   3663             drwav_uint8 temp[4096];
   3664             size_t bytesRead = pWav->onRead(pWav->pUserData, temp, sizeof(temp));
   3665             dataChunkSize += bytesRead;
   3666 
   3667             if (bytesRead < sizeof(temp)) {
   3668                 break;
   3669             }
   3670         }
   3671     }
   3672 
   3673     if (drwav__seek_from_start(pWav->onSeek, pWav->dataChunkDataPos, pWav->pUserData) == DRWAV_FALSE) {
   3674         drwav_free(pWav->pMetadata, &pWav->allocationCallbacks);
   3675         return DRWAV_FALSE;
   3676     }
   3677 
   3678 
   3679     pWav->fmt                 = fmt;
   3680     pWav->sampleRate          = fmt.sampleRate;
   3681     pWav->channels            = fmt.channels;
   3682     pWav->bitsPerSample       = fmt.bitsPerSample;
   3683     pWav->bytesRemaining      = dataChunkSize;
   3684     pWav->translatedFormatTag = translatedFormatTag;
   3685     pWav->dataChunkDataSize   = dataChunkSize;
   3686 
   3687     if (sampleCountFromFactChunk != 0) {
   3688         pWav->totalPCMFrameCount = sampleCountFromFactChunk;
   3689     } else if (aiffFrameCount != 0) {
   3690         pWav->totalPCMFrameCount = aiffFrameCount;
   3691     } else {
   3692         drwav_uint32 bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
   3693         if (bytesPerFrame == 0) {
   3694             drwav_free(pWav->pMetadata, &pWav->allocationCallbacks);
   3695             return DRWAV_FALSE; /* Invalid file. */
   3696         }
   3697 
   3698         pWav->totalPCMFrameCount = dataChunkSize / bytesPerFrame;
   3699 
   3700         if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ADPCM) {
   3701             drwav_uint64 totalBlockHeaderSizeInBytes;
   3702             drwav_uint64 blockCount = dataChunkSize / fmt.blockAlign;
   3703 
   3704             /* Make sure any trailing partial block is accounted for. */
   3705             if ((blockCount * fmt.blockAlign) < dataChunkSize) {
   3706                 blockCount += 1;
   3707             }
   3708 
   3709             /* 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. */
   3710             totalBlockHeaderSizeInBytes = blockCount * (6*fmt.channels);
   3711             pWav->totalPCMFrameCount = ((dataChunkSize - totalBlockHeaderSizeInBytes) * 2) / fmt.channels;
   3712         }
   3713         if (pWav->translatedFormatTag == DR_WAVE_FORMAT_DVI_ADPCM) {
   3714             drwav_uint64 totalBlockHeaderSizeInBytes;
   3715             drwav_uint64 blockCount = dataChunkSize / fmt.blockAlign;
   3716 
   3717             /* Make sure any trailing partial block is accounted for. */
   3718             if ((blockCount * fmt.blockAlign) < dataChunkSize) {
   3719                 blockCount += 1;
   3720             }
   3721 
   3722             /* 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. */
   3723             totalBlockHeaderSizeInBytes = blockCount * (4*fmt.channels);
   3724             pWav->totalPCMFrameCount = ((dataChunkSize - totalBlockHeaderSizeInBytes) * 2) / fmt.channels;
   3725 
   3726             /* The header includes a decoded sample for each channel which acts as the initial predictor sample. */
   3727             pWav->totalPCMFrameCount += blockCount;
   3728         }
   3729     }
   3730 
   3731     /* Some formats only support a certain number of channels. */
   3732     if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ADPCM || pWav->translatedFormatTag == DR_WAVE_FORMAT_DVI_ADPCM) {
   3733         if (pWav->channels > 2) {
   3734             drwav_free(pWav->pMetadata, &pWav->allocationCallbacks);
   3735             return DRWAV_FALSE;
   3736         }
   3737     }
   3738 
   3739     /* The number of bytes per frame must be known. If not, it's an invalid file and not decodable. */
   3740     if (drwav_get_bytes_per_pcm_frame(pWav) == 0) {
   3741         drwav_free(pWav->pMetadata, &pWav->allocationCallbacks);
   3742         return DRWAV_FALSE;
   3743     }
   3744 
   3745 #ifdef DR_WAV_LIBSNDFILE_COMPAT
   3746     /*
   3747     I use libsndfile as a benchmark for testing, however in the version I'm using (from the Windows installer on the libsndfile website),
   3748     it appears the total sample count libsndfile uses for MS-ADPCM is incorrect. It would seem they are computing the total sample count
   3749     from the number of blocks, however this results in the inclusion of extra silent samples at the end of the last block. The correct
   3750     way to know the total sample count is to inspect the "fact" chunk, which should always be present for compressed formats, and should
   3751     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
   3752     correctness tests against libsndfile, and is disabled by default.
   3753     */
   3754     if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ADPCM) {
   3755         drwav_uint64 blockCount = dataChunkSize / fmt.blockAlign;
   3756         pWav->totalPCMFrameCount = (((blockCount * (fmt.blockAlign - (6*pWav->channels))) * 2)) / fmt.channels;  /* x2 because two samples per byte. */
   3757     }
   3758     if (pWav->translatedFormatTag == DR_WAVE_FORMAT_DVI_ADPCM) {
   3759         drwav_uint64 blockCount = dataChunkSize / fmt.blockAlign;
   3760         pWav->totalPCMFrameCount = (((blockCount * (fmt.blockAlign - (4*pWav->channels))) * 2) + (blockCount * pWav->channels)) / fmt.channels;
   3761     }
   3762 #endif
   3763 
   3764     return DRWAV_TRUE;
   3765 }
   3766 
   3767 DRWAV_API drwav_bool32 drwav_init(drwav* pWav, drwav_read_proc onRead, drwav_seek_proc onSeek, void* pUserData, const drwav_allocation_callbacks* pAllocationCallbacks)
   3768 {
   3769     return drwav_init_ex(pWav, onRead, onSeek, NULL, pUserData, NULL, 0, pAllocationCallbacks);
   3770 }
   3771 
   3772 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)
   3773 {
   3774     if (!drwav_preinit(pWav, onRead, onSeek, pReadSeekUserData, pAllocationCallbacks)) {
   3775         return DRWAV_FALSE;
   3776     }
   3777 
   3778     return drwav_init__internal(pWav, onChunk, pChunkUserData, flags);
   3779 }
   3780 
   3781 DRWAV_API drwav_bool32 drwav_init_with_metadata(drwav* pWav, drwav_read_proc onRead, drwav_seek_proc onSeek, void* pUserData, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks)
   3782 {
   3783     if (!drwav_preinit(pWav, onRead, onSeek, pUserData, pAllocationCallbacks)) {
   3784         return DRWAV_FALSE;
   3785     }
   3786 
   3787     return drwav_init__internal(pWav, NULL, NULL, flags | DRWAV_WITH_METADATA);
   3788 }
   3789 
   3790 DRWAV_API drwav_metadata* drwav_take_ownership_of_metadata(drwav* pWav)
   3791 {
   3792     drwav_metadata *result = pWav->pMetadata;
   3793 
   3794     pWav->pMetadata     = NULL;
   3795     pWav->metadataCount = 0;
   3796 
   3797     return result;
   3798 }
   3799 
   3800 
   3801 DRWAV_PRIVATE size_t drwav__write(drwav* pWav, const void* pData, size_t dataSize)
   3802 {
   3803     DRWAV_ASSERT(pWav          != NULL);
   3804     DRWAV_ASSERT(pWav->onWrite != NULL);
   3805 
   3806     /* Generic write. Assumes no byte reordering required. */
   3807     return pWav->onWrite(pWav->pUserData, pData, dataSize);
   3808 }
   3809 
   3810 DRWAV_PRIVATE size_t drwav__write_byte(drwav* pWav, drwav_uint8 byte)
   3811 {
   3812     DRWAV_ASSERT(pWav          != NULL);
   3813     DRWAV_ASSERT(pWav->onWrite != NULL);
   3814 
   3815     return pWav->onWrite(pWav->pUserData, &byte, 1);
   3816 }
   3817 
   3818 DRWAV_PRIVATE size_t drwav__write_u16ne_to_le(drwav* pWav, drwav_uint16 value)
   3819 {
   3820     DRWAV_ASSERT(pWav          != NULL);
   3821     DRWAV_ASSERT(pWav->onWrite != NULL);
   3822 
   3823     if (!drwav__is_little_endian()) {
   3824         value = drwav__bswap16(value);
   3825     }
   3826 
   3827     return drwav__write(pWav, &value, 2);
   3828 }
   3829 
   3830 DRWAV_PRIVATE size_t drwav__write_u32ne_to_le(drwav* pWav, drwav_uint32 value)
   3831 {
   3832     DRWAV_ASSERT(pWav          != NULL);
   3833     DRWAV_ASSERT(pWav->onWrite != NULL);
   3834 
   3835     if (!drwav__is_little_endian()) {
   3836         value = drwav__bswap32(value);
   3837     }
   3838 
   3839     return drwav__write(pWav, &value, 4);
   3840 }
   3841 
   3842 DRWAV_PRIVATE size_t drwav__write_u64ne_to_le(drwav* pWav, drwav_uint64 value)
   3843 {
   3844     DRWAV_ASSERT(pWav          != NULL);
   3845     DRWAV_ASSERT(pWav->onWrite != NULL);
   3846 
   3847     if (!drwav__is_little_endian()) {
   3848         value = drwav__bswap64(value);
   3849     }
   3850 
   3851     return drwav__write(pWav, &value, 8);
   3852 }
   3853 
   3854 DRWAV_PRIVATE size_t drwav__write_f32ne_to_le(drwav* pWav, float value)
   3855 {
   3856     union {
   3857        drwav_uint32 u32;
   3858        float f32;
   3859     } u;
   3860 
   3861     DRWAV_ASSERT(pWav          != NULL);
   3862     DRWAV_ASSERT(pWav->onWrite != NULL);
   3863 
   3864     u.f32 = value;
   3865 
   3866     if (!drwav__is_little_endian()) {
   3867         u.u32 = drwav__bswap32(u.u32);
   3868     }
   3869 
   3870     return drwav__write(pWav, &u.u32, 4);
   3871 }
   3872 
   3873 DRWAV_PRIVATE size_t drwav__write_or_count(drwav* pWav, const void* pData, size_t dataSize)
   3874 {
   3875     if (pWav == NULL) {
   3876         return dataSize;
   3877     }
   3878 
   3879     return drwav__write(pWav, pData, dataSize);
   3880 }
   3881 
   3882 DRWAV_PRIVATE size_t drwav__write_or_count_byte(drwav* pWav, drwav_uint8 byte)
   3883 {
   3884     if (pWav == NULL) {
   3885         return 1;
   3886     }
   3887 
   3888     return drwav__write_byte(pWav, byte);
   3889 }
   3890 
   3891 DRWAV_PRIVATE size_t drwav__write_or_count_u16ne_to_le(drwav* pWav, drwav_uint16 value)
   3892 {
   3893     if (pWav == NULL) {
   3894         return 2;
   3895     }
   3896 
   3897     return drwav__write_u16ne_to_le(pWav, value);
   3898 }
   3899 
   3900 DRWAV_PRIVATE size_t drwav__write_or_count_u32ne_to_le(drwav* pWav, drwav_uint32 value)
   3901 {
   3902     if (pWav == NULL) {
   3903         return 4;
   3904     }
   3905 
   3906     return drwav__write_u32ne_to_le(pWav, value);
   3907 }
   3908 
   3909 #if 0   /* Unused for now. */
   3910 DRWAV_PRIVATE size_t drwav__write_or_count_u64ne_to_le(drwav* pWav, drwav_uint64 value)
   3911 {
   3912     if (pWav == NULL) {
   3913         return 8;
   3914     }
   3915 
   3916     return drwav__write_u64ne_to_le(pWav, value);
   3917 }
   3918 #endif
   3919 
   3920 DRWAV_PRIVATE size_t drwav__write_or_count_f32ne_to_le(drwav* pWav, float value)
   3921 {
   3922     if (pWav == NULL) {
   3923         return 4;
   3924     }
   3925 
   3926     return drwav__write_f32ne_to_le(pWav, value);
   3927 }
   3928 
   3929 DRWAV_PRIVATE size_t drwav__write_or_count_string_to_fixed_size_buf(drwav* pWav, char* str, size_t bufFixedSize)
   3930 {
   3931     size_t len;
   3932 
   3933     if (pWav == NULL) {
   3934         return bufFixedSize;
   3935     }
   3936 
   3937     len = drwav__strlen_clamped(str, bufFixedSize);
   3938     drwav__write_or_count(pWav, str, len);
   3939 
   3940     if (len < bufFixedSize) {
   3941         size_t i;
   3942         for (i = 0; i < bufFixedSize - len; ++i) {
   3943             drwav__write_byte(pWav, 0);
   3944         }
   3945     }
   3946 
   3947     return bufFixedSize;
   3948 }
   3949 
   3950 
   3951 /* pWav can be NULL meaning just count the bytes that would be written. */
   3952 DRWAV_PRIVATE size_t drwav__write_or_count_metadata(drwav* pWav, drwav_metadata* pMetadatas, drwav_uint32 metadataCount)
   3953 {
   3954     size_t bytesWritten = 0;
   3955     drwav_bool32 hasListAdtl = DRWAV_FALSE;
   3956     drwav_bool32 hasListInfo = DRWAV_FALSE;
   3957     drwav_uint32 iMetadata;
   3958 
   3959     if (pMetadatas == NULL || metadataCount == 0) {
   3960         return 0;
   3961     }
   3962 
   3963     for (iMetadata = 0; iMetadata < metadataCount; ++iMetadata) {
   3964         drwav_metadata* pMetadata = &pMetadatas[iMetadata];
   3965         drwav_uint32 chunkSize = 0;
   3966 
   3967         if ((pMetadata->type & drwav_metadata_type_list_all_info_strings) || (pMetadata->type == drwav_metadata_type_unknown && pMetadata->data.unknown.chunkLocation == drwav_metadata_location_inside_info_list)) {
   3968             hasListInfo = DRWAV_TRUE;
   3969         }
   3970 
   3971         if ((pMetadata->type & drwav_metadata_type_list_all_adtl) || (pMetadata->type == drwav_metadata_type_unknown && pMetadata->data.unknown.chunkLocation == drwav_metadata_location_inside_adtl_list)) {
   3972             hasListAdtl = DRWAV_TRUE;
   3973         }
   3974 
   3975         switch (pMetadata->type) {
   3976             case drwav_metadata_type_smpl:
   3977             {
   3978                 drwav_uint32 iLoop;
   3979 
   3980                 chunkSize = DRWAV_SMPL_BYTES + DRWAV_SMPL_LOOP_BYTES * pMetadata->data.smpl.sampleLoopCount + pMetadata->data.smpl.samplerSpecificDataSizeInBytes;
   3981 
   3982                 bytesWritten += drwav__write_or_count(pWav, "smpl", 4);
   3983                 bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, chunkSize);
   3984 
   3985                 bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.manufacturerId);
   3986                 bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.productId);
   3987                 bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.samplePeriodNanoseconds);
   3988                 bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.midiUnityNote);
   3989                 bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.midiPitchFraction);
   3990                 bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.smpteFormat);
   3991                 bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.smpteOffset);
   3992                 bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.sampleLoopCount);
   3993                 bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.samplerSpecificDataSizeInBytes);
   3994 
   3995                 for (iLoop = 0; iLoop < pMetadata->data.smpl.sampleLoopCount; ++iLoop) {
   3996                     bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.pLoops[iLoop].cuePointId);
   3997                     bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.pLoops[iLoop].type);
   3998                     bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.pLoops[iLoop].firstSampleByteOffset);
   3999                     bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.pLoops[iLoop].lastSampleByteOffset);
   4000                     bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.pLoops[iLoop].sampleFraction);
   4001                     bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.pLoops[iLoop].playCount);
   4002                 }
   4003 
   4004                 if (pMetadata->data.smpl.samplerSpecificDataSizeInBytes > 0) {
   4005                     bytesWritten += drwav__write_or_count(pWav, pMetadata->data.smpl.pSamplerSpecificData, pMetadata->data.smpl.samplerSpecificDataSizeInBytes);
   4006                 }
   4007             } break;
   4008 
   4009             case drwav_metadata_type_inst:
   4010             {
   4011                 chunkSize = DRWAV_INST_BYTES;
   4012 
   4013                 bytesWritten += drwav__write_or_count(pWav, "inst", 4);
   4014                 bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, chunkSize);
   4015                 bytesWritten += drwav__write_or_count(pWav, &pMetadata->data.inst.midiUnityNote, 1);
   4016                 bytesWritten += drwav__write_or_count(pWav, &pMetadata->data.inst.fineTuneCents, 1);
   4017                 bytesWritten += drwav__write_or_count(pWav, &pMetadata->data.inst.gainDecibels, 1);
   4018                 bytesWritten += drwav__write_or_count(pWav, &pMetadata->data.inst.lowNote, 1);
   4019                 bytesWritten += drwav__write_or_count(pWav, &pMetadata->data.inst.highNote, 1);
   4020                 bytesWritten += drwav__write_or_count(pWav, &pMetadata->data.inst.lowVelocity, 1);
   4021                 bytesWritten += drwav__write_or_count(pWav, &pMetadata->data.inst.highVelocity, 1);
   4022             } break;
   4023 
   4024             case drwav_metadata_type_cue:
   4025             {
   4026                 drwav_uint32 iCuePoint;
   4027 
   4028                 chunkSize = DRWAV_CUE_BYTES + DRWAV_CUE_POINT_BYTES * pMetadata->data.cue.cuePointCount;
   4029 
   4030                 bytesWritten += drwav__write_or_count(pWav, "cue ", 4);
   4031                 bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, chunkSize);
   4032                 bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.cue.cuePointCount);
   4033                 for (iCuePoint = 0; iCuePoint < pMetadata->data.cue.cuePointCount; ++iCuePoint) {
   4034                     bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.cue.pCuePoints[iCuePoint].id);
   4035                     bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.cue.pCuePoints[iCuePoint].playOrderPosition);
   4036                     bytesWritten += drwav__write_or_count(pWav, pMetadata->data.cue.pCuePoints[iCuePoint].dataChunkId, 4);
   4037                     bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.cue.pCuePoints[iCuePoint].chunkStart);
   4038                     bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.cue.pCuePoints[iCuePoint].blockStart);
   4039                     bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.cue.pCuePoints[iCuePoint].sampleByteOffset);
   4040                 }
   4041             } break;
   4042 
   4043             case drwav_metadata_type_acid:
   4044             {
   4045                 chunkSize = DRWAV_ACID_BYTES;
   4046 
   4047                 bytesWritten += drwav__write_or_count(pWav, "acid", 4);
   4048                 bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, chunkSize);
   4049                 bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.acid.flags);
   4050                 bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.acid.midiUnityNote);
   4051                 bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.acid.reserved1);
   4052                 bytesWritten += drwav__write_or_count_f32ne_to_le(pWav, pMetadata->data.acid.reserved2);
   4053                 bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.acid.numBeats);
   4054                 bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.acid.meterDenominator);
   4055                 bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.acid.meterNumerator);
   4056                 bytesWritten += drwav__write_or_count_f32ne_to_le(pWav, pMetadata->data.acid.tempo);
   4057             } break;
   4058 
   4059             case drwav_metadata_type_bext:
   4060             {
   4061                 char reservedBuf[DRWAV_BEXT_RESERVED_BYTES];
   4062                 drwav_uint32 timeReferenceLow;
   4063                 drwav_uint32 timeReferenceHigh;
   4064 
   4065                 chunkSize = DRWAV_BEXT_BYTES + pMetadata->data.bext.codingHistorySize;
   4066 
   4067                 bytesWritten += drwav__write_or_count(pWav, "bext", 4);
   4068                 bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, chunkSize);
   4069 
   4070                 bytesWritten += drwav__write_or_count_string_to_fixed_size_buf(pWav, pMetadata->data.bext.pDescription, DRWAV_BEXT_DESCRIPTION_BYTES);
   4071                 bytesWritten += drwav__write_or_count_string_to_fixed_size_buf(pWav, pMetadata->data.bext.pOriginatorName, DRWAV_BEXT_ORIGINATOR_NAME_BYTES);
   4072                 bytesWritten += drwav__write_or_count_string_to_fixed_size_buf(pWav, pMetadata->data.bext.pOriginatorReference, DRWAV_BEXT_ORIGINATOR_REF_BYTES);
   4073                 bytesWritten += drwav__write_or_count(pWav, pMetadata->data.bext.pOriginationDate, sizeof(pMetadata->data.bext.pOriginationDate));
   4074                 bytesWritten += drwav__write_or_count(pWav, pMetadata->data.bext.pOriginationTime, sizeof(pMetadata->data.bext.pOriginationTime));
   4075 
   4076                 timeReferenceLow  = (drwav_uint32)(pMetadata->data.bext.timeReference & 0xFFFFFFFF);
   4077                 timeReferenceHigh = (drwav_uint32)(pMetadata->data.bext.timeReference >> 32);
   4078                 bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, timeReferenceLow);
   4079                 bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, timeReferenceHigh);
   4080 
   4081                 bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.bext.version);
   4082                 bytesWritten += drwav__write_or_count(pWav, pMetadata->data.bext.pUMID, DRWAV_BEXT_UMID_BYTES);
   4083                 bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.bext.loudnessValue);
   4084                 bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.bext.loudnessRange);
   4085                 bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.bext.maxTruePeakLevel);
   4086                 bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.bext.maxMomentaryLoudness);
   4087                 bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.bext.maxShortTermLoudness);
   4088 
   4089                 DRWAV_ZERO_MEMORY(reservedBuf, sizeof(reservedBuf));
   4090                 bytesWritten += drwav__write_or_count(pWav, reservedBuf, sizeof(reservedBuf));
   4091 
   4092                 if (pMetadata->data.bext.codingHistorySize > 0) {
   4093                     bytesWritten += drwav__write_or_count(pWav, pMetadata->data.bext.pCodingHistory, pMetadata->data.bext.codingHistorySize);
   4094                 }
   4095             } break;
   4096 
   4097             case drwav_metadata_type_unknown:
   4098             {
   4099                 if (pMetadata->data.unknown.chunkLocation == drwav_metadata_location_top_level) {
   4100                     chunkSize = pMetadata->data.unknown.dataSizeInBytes;
   4101 
   4102                     bytesWritten += drwav__write_or_count(pWav, pMetadata->data.unknown.id, 4);
   4103                     bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, chunkSize);
   4104                     bytesWritten += drwav__write_or_count(pWav, pMetadata->data.unknown.pData, pMetadata->data.unknown.dataSizeInBytes);
   4105                 }
   4106             } break;
   4107 
   4108             default: break;
   4109         }
   4110         if ((chunkSize % 2) != 0) {
   4111             bytesWritten += drwav__write_or_count_byte(pWav, 0);
   4112         }
   4113     }
   4114 
   4115     if (hasListInfo) {
   4116         drwav_uint32 chunkSize = 4; /* Start with 4 bytes for "INFO". */
   4117         for (iMetadata = 0; iMetadata < metadataCount; ++iMetadata) {
   4118             drwav_metadata* pMetadata = &pMetadatas[iMetadata];
   4119 
   4120             if ((pMetadata->type & drwav_metadata_type_list_all_info_strings)) {
   4121                 chunkSize += 8; /* For id and string size. */
   4122                 chunkSize += pMetadata->data.infoText.stringLength + 1; /* Include null terminator. */
   4123             } else if (pMetadata->type == drwav_metadata_type_unknown && pMetadata->data.unknown.chunkLocation == drwav_metadata_location_inside_info_list) {
   4124                 chunkSize += 8; /* For id string size. */
   4125                 chunkSize += pMetadata->data.unknown.dataSizeInBytes;
   4126             }
   4127 
   4128             if ((chunkSize % 2) != 0) {
   4129                 chunkSize += 1;
   4130             }
   4131         }
   4132 
   4133         bytesWritten += drwav__write_or_count(pWav, "LIST", 4);
   4134         bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, chunkSize);
   4135         bytesWritten += drwav__write_or_count(pWav, "INFO", 4);
   4136 
   4137         for (iMetadata = 0; iMetadata < metadataCount; ++iMetadata) {
   4138             drwav_metadata* pMetadata = &pMetadatas[iMetadata];
   4139             drwav_uint32 subchunkSize = 0;
   4140 
   4141             if (pMetadata->type & drwav_metadata_type_list_all_info_strings) {
   4142                 const char* pID = NULL;
   4143 
   4144                 switch (pMetadata->type) {
   4145                     case drwav_metadata_type_list_info_software:    pID = "ISFT"; break;
   4146                     case drwav_metadata_type_list_info_copyright:   pID = "ICOP"; break;
   4147                     case drwav_metadata_type_list_info_title:       pID = "INAM"; break;
   4148                     case drwav_metadata_type_list_info_artist:      pID = "IART"; break;
   4149                     case drwav_metadata_type_list_info_comment:     pID = "ICMT"; break;
   4150                     case drwav_metadata_type_list_info_date:        pID = "ICRD"; break;
   4151                     case drwav_metadata_type_list_info_genre:       pID = "IGNR"; break;
   4152                     case drwav_metadata_type_list_info_album:       pID = "IPRD"; break;
   4153                     case drwav_metadata_type_list_info_tracknumber: pID = "ITRK"; break;
   4154                     default: break;
   4155                 }
   4156 
   4157                 DRWAV_ASSERT(pID != NULL);
   4158 
   4159                 if (pMetadata->data.infoText.stringLength) {
   4160                     subchunkSize = pMetadata->data.infoText.stringLength + 1;
   4161                     bytesWritten += drwav__write_or_count(pWav, pID, 4);
   4162                     bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, subchunkSize);
   4163                     bytesWritten += drwav__write_or_count(pWav, pMetadata->data.infoText.pString, pMetadata->data.infoText.stringLength);
   4164                     bytesWritten += drwav__write_or_count_byte(pWav, '\0');
   4165                 }
   4166             } else if (pMetadata->type == drwav_metadata_type_unknown && pMetadata->data.unknown.chunkLocation == drwav_metadata_location_inside_info_list) {
   4167                 if (pMetadata->data.unknown.dataSizeInBytes) {
   4168                     subchunkSize = pMetadata->data.unknown.dataSizeInBytes;
   4169 
   4170                     bytesWritten += drwav__write_or_count(pWav, pMetadata->data.unknown.id, 4);
   4171                     bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.unknown.dataSizeInBytes);
   4172                     bytesWritten += drwav__write_or_count(pWav, pMetadata->data.unknown.pData, subchunkSize);
   4173                 }
   4174             }
   4175 
   4176             if ((subchunkSize % 2) != 0) {
   4177                 bytesWritten += drwav__write_or_count_byte(pWav, 0);
   4178             }
   4179         }
   4180     }
   4181 
   4182     if (hasListAdtl) {
   4183         drwav_uint32 chunkSize = 4; /* start with 4 bytes for "adtl" */
   4184 
   4185         for (iMetadata = 0; iMetadata < metadataCount; ++iMetadata) {
   4186             drwav_metadata* pMetadata = &pMetadatas[iMetadata];
   4187 
   4188             switch (pMetadata->type)
   4189             {
   4190                 case drwav_metadata_type_list_label:
   4191                 case drwav_metadata_type_list_note:
   4192                 {
   4193                     chunkSize += 8; /* for id and chunk size */
   4194                     chunkSize += DRWAV_LIST_LABEL_OR_NOTE_BYTES;
   4195 
   4196                     if (pMetadata->data.labelOrNote.stringLength > 0) {
   4197                         chunkSize += pMetadata->data.labelOrNote.stringLength + 1;
   4198                     }    
   4199                 } break;
   4200 
   4201                 case drwav_metadata_type_list_labelled_cue_region:
   4202                 {
   4203                     chunkSize += 8; /* for id and chunk size */
   4204                     chunkSize += DRWAV_LIST_LABELLED_TEXT_BYTES;
   4205 
   4206                     if (pMetadata->data.labelledCueRegion.stringLength > 0) {
   4207                         chunkSize += pMetadata->data.labelledCueRegion.stringLength + 1;
   4208                     }
   4209                 } break;
   4210 
   4211                 case drwav_metadata_type_unknown:
   4212                 {
   4213                     if (pMetadata->data.unknown.chunkLocation == drwav_metadata_location_inside_adtl_list) {
   4214                         chunkSize += 8; /* for id and chunk size */
   4215                         chunkSize += pMetadata->data.unknown.dataSizeInBytes;
   4216                     }
   4217                 } break;
   4218 
   4219                 default: break;
   4220             }
   4221 
   4222             if ((chunkSize % 2) != 0) {
   4223                 chunkSize += 1;
   4224             }
   4225         }
   4226 
   4227         bytesWritten += drwav__write_or_count(pWav, "LIST", 4);
   4228         bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, chunkSize);
   4229         bytesWritten += drwav__write_or_count(pWav, "adtl", 4);
   4230 
   4231         for (iMetadata = 0; iMetadata < metadataCount; ++iMetadata) {
   4232             drwav_metadata* pMetadata = &pMetadatas[iMetadata];
   4233             drwav_uint32 subchunkSize = 0;
   4234 
   4235             switch (pMetadata->type)
   4236             {
   4237                 case drwav_metadata_type_list_label:
   4238                 case drwav_metadata_type_list_note:
   4239                 {
   4240                     if (pMetadata->data.labelOrNote.stringLength > 0) {
   4241                         const char *pID = NULL;
   4242 
   4243                         if (pMetadata->type == drwav_metadata_type_list_label) {
   4244                             pID = "labl";
   4245                         }
   4246                         else if (pMetadata->type == drwav_metadata_type_list_note) {
   4247                             pID = "note";
   4248                         }
   4249 
   4250                         DRWAV_ASSERT(pID != NULL);
   4251                         DRWAV_ASSERT(pMetadata->data.labelOrNote.pString != NULL);
   4252 
   4253                         subchunkSize = DRWAV_LIST_LABEL_OR_NOTE_BYTES;
   4254 
   4255                         bytesWritten += drwav__write_or_count(pWav, pID, 4);
   4256                         subchunkSize += pMetadata->data.labelOrNote.stringLength + 1;
   4257                         bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, subchunkSize);
   4258 
   4259                         bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.labelOrNote.cuePointId);
   4260                         bytesWritten += drwav__write_or_count(pWav, pMetadata->data.labelOrNote.pString, pMetadata->data.labelOrNote.stringLength);
   4261                         bytesWritten += drwav__write_or_count_byte(pWav, '\0');
   4262                     }
   4263                 } break;
   4264 
   4265                 case drwav_metadata_type_list_labelled_cue_region:
   4266                 {
   4267                     subchunkSize = DRWAV_LIST_LABELLED_TEXT_BYTES;
   4268 
   4269                     bytesWritten += drwav__write_or_count(pWav, "ltxt", 4);
   4270                     if (pMetadata->data.labelledCueRegion.stringLength > 0) {
   4271                         subchunkSize += pMetadata->data.labelledCueRegion.stringLength + 1;
   4272                     }
   4273                     bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, subchunkSize);
   4274                     bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.labelledCueRegion.cuePointId);
   4275                     bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.labelledCueRegion.sampleLength);
   4276                     bytesWritten += drwav__write_or_count(pWav, pMetadata->data.labelledCueRegion.purposeId, 4);
   4277                     bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.labelledCueRegion.country);
   4278                     bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.labelledCueRegion.language);
   4279                     bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.labelledCueRegion.dialect);
   4280                     bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.labelledCueRegion.codePage);
   4281 
   4282                     if (pMetadata->data.labelledCueRegion.stringLength > 0) {
   4283                         DRWAV_ASSERT(pMetadata->data.labelledCueRegion.pString != NULL);
   4284 
   4285                         bytesWritten += drwav__write_or_count(pWav, pMetadata->data.labelledCueRegion.pString, pMetadata->data.labelledCueRegion.stringLength);
   4286                         bytesWritten += drwav__write_or_count_byte(pWav, '\0');
   4287                     }
   4288                 } break;
   4289 
   4290                 case drwav_metadata_type_unknown:
   4291                 {
   4292                     if (pMetadata->data.unknown.chunkLocation == drwav_metadata_location_inside_adtl_list) {
   4293                         subchunkSize = pMetadata->data.unknown.dataSizeInBytes;
   4294 
   4295                         DRWAV_ASSERT(pMetadata->data.unknown.pData != NULL);
   4296                         bytesWritten += drwav__write_or_count(pWav, pMetadata->data.unknown.id, 4);
   4297                         bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, subchunkSize);
   4298                         bytesWritten += drwav__write_or_count(pWav, pMetadata->data.unknown.pData, subchunkSize);
   4299                     }
   4300                 } break;
   4301 
   4302                 default: break;
   4303             }
   4304 
   4305             if ((subchunkSize % 2) != 0) {
   4306                 bytesWritten += drwav__write_or_count_byte(pWav, 0);
   4307             }
   4308         }
   4309     }
   4310 
   4311     DRWAV_ASSERT((bytesWritten % 2) == 0);
   4312 
   4313     return bytesWritten;
   4314 }
   4315 
   4316 DRWAV_PRIVATE drwav_uint32 drwav__riff_chunk_size_riff(drwav_uint64 dataChunkSize, drwav_metadata* pMetadata, drwav_uint32 metadataCount)
   4317 {
   4318     drwav_uint64 chunkSize = 4 + 24 + (drwav_uint64)drwav__write_or_count_metadata(NULL, pMetadata, metadataCount) + 8 + dataChunkSize + drwav__chunk_padding_size_riff(dataChunkSize); /* 4 = "WAVE". 24 = "fmt " chunk. 8 = "data" + u32 data size. */
   4319     if (chunkSize > 0xFFFFFFFFUL) {
   4320         chunkSize = 0xFFFFFFFFUL;
   4321     }
   4322 
   4323     return (drwav_uint32)chunkSize; /* Safe cast due to the clamp above. */
   4324 }
   4325 
   4326 DRWAV_PRIVATE drwav_uint32 drwav__data_chunk_size_riff(drwav_uint64 dataChunkSize)
   4327 {
   4328     if (dataChunkSize <= 0xFFFFFFFFUL) {
   4329         return (drwav_uint32)dataChunkSize;
   4330     } else {
   4331         return 0xFFFFFFFFUL;
   4332     }
   4333 }
   4334 
   4335 DRWAV_PRIVATE drwav_uint64 drwav__riff_chunk_size_w64(drwav_uint64 dataChunkSize)
   4336 {
   4337     drwav_uint64 dataSubchunkPaddingSize = drwav__chunk_padding_size_w64(dataChunkSize);
   4338 
   4339     return 80 + 24 + dataChunkSize + dataSubchunkPaddingSize;   /* +24 because W64 includes the size of the GUID and size fields. */
   4340 }
   4341 
   4342 DRWAV_PRIVATE drwav_uint64 drwav__data_chunk_size_w64(drwav_uint64 dataChunkSize)
   4343 {
   4344     return 24 + dataChunkSize;        /* +24 because W64 includes the size of the GUID and size fields. */
   4345 }
   4346 
   4347 DRWAV_PRIVATE drwav_uint64 drwav__riff_chunk_size_rf64(drwav_uint64 dataChunkSize, drwav_metadata *metadata, drwav_uint32 numMetadata)
   4348 {
   4349     drwav_uint64 chunkSize = 4 + 36 + 24 + (drwav_uint64)drwav__write_or_count_metadata(NULL, metadata, numMetadata) + 8 + dataChunkSize + drwav__chunk_padding_size_riff(dataChunkSize); /* 4 = "WAVE". 36 = "ds64" chunk. 24 = "fmt " chunk. 8 = "data" + u32 data size. */
   4350     if (chunkSize > 0xFFFFFFFFUL) {
   4351         chunkSize = 0xFFFFFFFFUL;
   4352     }
   4353 
   4354     return chunkSize;
   4355 }
   4356 
   4357 DRWAV_PRIVATE drwav_uint64 drwav__data_chunk_size_rf64(drwav_uint64 dataChunkSize)
   4358 {
   4359     return dataChunkSize;
   4360 }
   4361 
   4362 
   4363 
   4364 DRWAV_PRIVATE drwav_bool32 drwav_preinit_write(drwav* pWav, const drwav_data_format* pFormat, drwav_bool32 isSequential, drwav_write_proc onWrite, drwav_seek_proc onSeek, void* pUserData, const drwav_allocation_callbacks* pAllocationCallbacks)
   4365 {
   4366     if (pWav == NULL || onWrite == NULL) {
   4367         return DRWAV_FALSE;
   4368     }
   4369 
   4370     if (!isSequential && onSeek == NULL) {
   4371         return DRWAV_FALSE; /* <-- onSeek is required when in non-sequential mode. */
   4372     }
   4373 
   4374     /* Not currently supporting compressed formats. Will need to add support for the "fact" chunk before we enable this. */
   4375     if (pFormat->format == DR_WAVE_FORMAT_EXTENSIBLE) {
   4376         return DRWAV_FALSE;
   4377     }
   4378     if (pFormat->format == DR_WAVE_FORMAT_ADPCM || pFormat->format == DR_WAVE_FORMAT_DVI_ADPCM) {
   4379         return DRWAV_FALSE;
   4380     }
   4381 
   4382     DRWAV_ZERO_MEMORY(pWav, sizeof(*pWav));
   4383     pWav->onWrite   = onWrite;
   4384     pWav->onSeek    = onSeek;
   4385     pWav->pUserData = pUserData;
   4386     pWav->allocationCallbacks = drwav_copy_allocation_callbacks_or_defaults(pAllocationCallbacks);
   4387 
   4388     if (pWav->allocationCallbacks.onFree == NULL || (pWav->allocationCallbacks.onMalloc == NULL && pWav->allocationCallbacks.onRealloc == NULL)) {
   4389         return DRWAV_FALSE;    /* Invalid allocation callbacks. */
   4390     }
   4391 
   4392     pWav->fmt.formatTag = (drwav_uint16)pFormat->format;
   4393     pWav->fmt.channels = (drwav_uint16)pFormat->channels;
   4394     pWav->fmt.sampleRate = pFormat->sampleRate;
   4395     pWav->fmt.avgBytesPerSec = (drwav_uint32)((pFormat->bitsPerSample * pFormat->sampleRate * pFormat->channels) / 8);
   4396     pWav->fmt.blockAlign = (drwav_uint16)((pFormat->channels * pFormat->bitsPerSample) / 8);
   4397     pWav->fmt.bitsPerSample = (drwav_uint16)pFormat->bitsPerSample;
   4398     pWav->fmt.extendedSize = 0;
   4399     pWav->isSequentialWrite = isSequential;
   4400 
   4401     return DRWAV_TRUE;
   4402 }
   4403 
   4404 
   4405 DRWAV_PRIVATE drwav_bool32 drwav_init_write__internal(drwav* pWav, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount)
   4406 {
   4407     /* The function assumes drwav_preinit_write() was called beforehand. */
   4408 
   4409     size_t runningPos = 0;
   4410     drwav_uint64 initialDataChunkSize = 0;
   4411     drwav_uint64 chunkSizeFMT;
   4412 
   4413     /*
   4414     The initial values for the "RIFF" and "data" chunks depends on whether or not we are initializing in sequential mode or not. In
   4415     sequential mode we set this to its final values straight away since they can be calculated from the total sample count. In non-
   4416     sequential mode we initialize it all to zero and fill it out in drwav_uninit() using a backwards seek.
   4417     */
   4418     if (pWav->isSequentialWrite) {
   4419         initialDataChunkSize = (totalSampleCount * pWav->fmt.bitsPerSample) / 8;
   4420 
   4421         /*
   4422         The RIFF container has a limit on the number of samples. drwav is not allowing this. There's no practical limits for Wave64
   4423         so for the sake of simplicity I'm not doing any validation for that.
   4424         */
   4425         if (pFormat->container == drwav_container_riff) {
   4426             if (initialDataChunkSize > (0xFFFFFFFFUL - 36)) {
   4427                 return DRWAV_FALSE; /* Not enough room to store every sample. */
   4428             }
   4429         }
   4430     }
   4431 
   4432     pWav->dataChunkDataSizeTargetWrite = initialDataChunkSize;
   4433 
   4434 
   4435     /* "RIFF" chunk. */
   4436     if (pFormat->container == drwav_container_riff) {
   4437         drwav_uint32 chunkSizeRIFF = 28 + (drwav_uint32)initialDataChunkSize;   /* +28 = "WAVE" + [sizeof "fmt " chunk] */
   4438         runningPos += drwav__write(pWav, "RIFF", 4);
   4439         runningPos += drwav__write_u32ne_to_le(pWav, chunkSizeRIFF);
   4440         runningPos += drwav__write(pWav, "WAVE", 4);
   4441     } else if (pFormat->container == drwav_container_w64) {
   4442         drwav_uint64 chunkSizeRIFF = 80 + 24 + initialDataChunkSize;            /* +24 because W64 includes the size of the GUID and size fields. */
   4443         runningPos += drwav__write(pWav, drwavGUID_W64_RIFF, 16);
   4444         runningPos += drwav__write_u64ne_to_le(pWav, chunkSizeRIFF);
   4445         runningPos += drwav__write(pWav, drwavGUID_W64_WAVE, 16);
   4446     } else if (pFormat->container == drwav_container_rf64) {
   4447         runningPos += drwav__write(pWav, "RF64", 4);
   4448         runningPos += drwav__write_u32ne_to_le(pWav, 0xFFFFFFFF);               /* Always 0xFFFFFFFF for RF64. Set to a proper value in the "ds64" chunk. */
   4449         runningPos += drwav__write(pWav, "WAVE", 4);
   4450     } else {
   4451         return DRWAV_FALSE; /* Container not supported for writing. */
   4452     }
   4453 
   4454 
   4455     /* "ds64" chunk (RF64 only). */
   4456     if (pFormat->container == drwav_container_rf64) {
   4457         drwav_uint32 initialds64ChunkSize = 28;                                 /* 28 = [Size of RIFF (8 bytes)] + [Size of DATA (8 bytes)] + [Sample Count (8 bytes)] + [Table Length (4 bytes)]. Table length always set to 0. */
   4458         drwav_uint64 initialRiffChunkSize = 8 + initialds64ChunkSize + initialDataChunkSize;    /* +8 for the ds64 header. */
   4459 
   4460         runningPos += drwav__write(pWav, "ds64", 4);
   4461         runningPos += drwav__write_u32ne_to_le(pWav, initialds64ChunkSize);     /* Size of ds64. */
   4462         runningPos += drwav__write_u64ne_to_le(pWav, initialRiffChunkSize);     /* Size of RIFF. Set to true value at the end. */
   4463         runningPos += drwav__write_u64ne_to_le(pWav, initialDataChunkSize);     /* Size of DATA. Set to true value at the end. */
   4464         runningPos += drwav__write_u64ne_to_le(pWav, totalSampleCount);         /* Sample count. */
   4465         runningPos += drwav__write_u32ne_to_le(pWav, 0);                        /* Table length. Always set to zero in our case since we're not doing any other chunks than "DATA". */
   4466     }
   4467 
   4468 
   4469     /* "fmt " chunk. */
   4470     if (pFormat->container == drwav_container_riff || pFormat->container == drwav_container_rf64) {
   4471         chunkSizeFMT = 16;
   4472         runningPos += drwav__write(pWav, "fmt ", 4);
   4473         runningPos += drwav__write_u32ne_to_le(pWav, (drwav_uint32)chunkSizeFMT);
   4474     } else if (pFormat->container == drwav_container_w64) {
   4475         chunkSizeFMT = 40;
   4476         runningPos += drwav__write(pWav, drwavGUID_W64_FMT, 16);
   4477         runningPos += drwav__write_u64ne_to_le(pWav, chunkSizeFMT);
   4478     }
   4479 
   4480     runningPos += drwav__write_u16ne_to_le(pWav, pWav->fmt.formatTag);
   4481     runningPos += drwav__write_u16ne_to_le(pWav, pWav->fmt.channels);
   4482     runningPos += drwav__write_u32ne_to_le(pWav, pWav->fmt.sampleRate);
   4483     runningPos += drwav__write_u32ne_to_le(pWav, pWav->fmt.avgBytesPerSec);
   4484     runningPos += drwav__write_u16ne_to_le(pWav, pWav->fmt.blockAlign);
   4485     runningPos += drwav__write_u16ne_to_le(pWav, pWav->fmt.bitsPerSample);
   4486 
   4487     /* TODO: is a 'fact' chunk required for DR_WAVE_FORMAT_IEEE_FLOAT? */
   4488 
   4489     if (!pWav->isSequentialWrite && pWav->pMetadata != NULL && pWav->metadataCount > 0 && (pFormat->container == drwav_container_riff || pFormat->container == drwav_container_rf64)) {
   4490         runningPos += drwav__write_or_count_metadata(pWav, pWav->pMetadata, pWav->metadataCount);
   4491     }
   4492 
   4493     pWav->dataChunkDataPos = runningPos;
   4494 
   4495     /* "data" chunk. */
   4496     if (pFormat->container == drwav_container_riff) {
   4497         drwav_uint32 chunkSizeDATA = (drwav_uint32)initialDataChunkSize;
   4498         runningPos += drwav__write(pWav, "data", 4);
   4499         runningPos += drwav__write_u32ne_to_le(pWav, chunkSizeDATA);
   4500     } else if (pFormat->container == drwav_container_w64) {
   4501         drwav_uint64 chunkSizeDATA = 24 + initialDataChunkSize;     /* +24 because W64 includes the size of the GUID and size fields. */
   4502         runningPos += drwav__write(pWav, drwavGUID_W64_DATA, 16);
   4503         runningPos += drwav__write_u64ne_to_le(pWav, chunkSizeDATA);
   4504     } else if (pFormat->container == drwav_container_rf64) {
   4505         runningPos += drwav__write(pWav, "data", 4);
   4506         runningPos += drwav__write_u32ne_to_le(pWav, 0xFFFFFFFF);   /* Always set to 0xFFFFFFFF for RF64. The true size of the data chunk is specified in the ds64 chunk. */
   4507     }
   4508 
   4509     /* Set some properties for the client's convenience. */
   4510     pWav->container = pFormat->container;
   4511     pWav->channels = (drwav_uint16)pFormat->channels;
   4512     pWav->sampleRate = pFormat->sampleRate;
   4513     pWav->bitsPerSample = (drwav_uint16)pFormat->bitsPerSample;
   4514     pWav->translatedFormatTag = (drwav_uint16)pFormat->format;
   4515     pWav->dataChunkDataPos = runningPos;
   4516 
   4517     return DRWAV_TRUE;
   4518 }
   4519 
   4520 
   4521 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)
   4522 {
   4523     if (!drwav_preinit_write(pWav, pFormat, DRWAV_FALSE, onWrite, onSeek, pUserData, pAllocationCallbacks)) {
   4524         return DRWAV_FALSE;
   4525     }
   4526 
   4527     return drwav_init_write__internal(pWav, pFormat, 0);               /* DRWAV_FALSE = Not Sequential */
   4528 }
   4529 
   4530 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)
   4531 {
   4532     if (!drwav_preinit_write(pWav, pFormat, DRWAV_TRUE, onWrite, NULL, pUserData, pAllocationCallbacks)) {
   4533         return DRWAV_FALSE;
   4534     }
   4535 
   4536     return drwav_init_write__internal(pWav, pFormat, totalSampleCount); /* DRWAV_TRUE = Sequential */
   4537 }
   4538 
   4539 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)
   4540 {
   4541     if (pFormat == NULL) {
   4542         return DRWAV_FALSE;
   4543     }
   4544 
   4545     return drwav_init_write_sequential(pWav, pFormat, totalPCMFrameCount*pFormat->channels, onWrite, pUserData, pAllocationCallbacks);
   4546 }
   4547 
   4548 DRWAV_API drwav_bool32 drwav_init_write_with_metadata(drwav* pWav, const drwav_data_format* pFormat, drwav_write_proc onWrite, drwav_seek_proc onSeek, void* pUserData, const drwav_allocation_callbacks* pAllocationCallbacks, drwav_metadata* pMetadata, drwav_uint32 metadataCount)
   4549 {
   4550     if (!drwav_preinit_write(pWav, pFormat, DRWAV_FALSE, onWrite, onSeek, pUserData, pAllocationCallbacks)) {
   4551         return DRWAV_FALSE;
   4552     }
   4553 
   4554     pWav->pMetadata     = pMetadata;
   4555     pWav->metadataCount = metadataCount;
   4556 
   4557     return drwav_init_write__internal(pWav, pFormat, 0);
   4558 }
   4559 
   4560 
   4561 DRWAV_API drwav_uint64 drwav_target_write_size_bytes(const drwav_data_format* pFormat, drwav_uint64 totalFrameCount, drwav_metadata* pMetadata, drwav_uint32 metadataCount)
   4562 {
   4563     /* Casting totalFrameCount to drwav_int64 for VC6 compatibility. No issues in practice because nobody is going to exhaust the whole 63 bits. */
   4564     drwav_uint64 targetDataSizeBytes = (drwav_uint64)((drwav_int64)totalFrameCount * pFormat->channels * pFormat->bitsPerSample/8.0);
   4565     drwav_uint64 riffChunkSizeBytes;
   4566     drwav_uint64 fileSizeBytes = 0;
   4567 
   4568     if (pFormat->container == drwav_container_riff) {
   4569         riffChunkSizeBytes = drwav__riff_chunk_size_riff(targetDataSizeBytes, pMetadata, metadataCount);
   4570         fileSizeBytes = (8 + riffChunkSizeBytes);   /* +8 because WAV doesn't include the size of the ChunkID and ChunkSize fields. */
   4571     } else if (pFormat->container == drwav_container_w64) {
   4572         riffChunkSizeBytes = drwav__riff_chunk_size_w64(targetDataSizeBytes);
   4573         fileSizeBytes = riffChunkSizeBytes;
   4574     } else if (pFormat->container == drwav_container_rf64) {
   4575         riffChunkSizeBytes = drwav__riff_chunk_size_rf64(targetDataSizeBytes, pMetadata, metadataCount);
   4576         fileSizeBytes = (8 + riffChunkSizeBytes);   /* +8 because WAV doesn't include the size of the ChunkID and ChunkSize fields. */
   4577     }
   4578 
   4579     return fileSizeBytes;
   4580 }
   4581 
   4582 
   4583 #ifndef DR_WAV_NO_STDIO
   4584 
   4585 /* Errno */
   4586 /* 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. */
   4587 #include <errno.h>
   4588 DRWAV_PRIVATE drwav_result drwav_result_from_errno(int e)
   4589 {
   4590     switch (e)
   4591     {
   4592         case 0: return DRWAV_SUCCESS;
   4593     #ifdef EPERM
   4594         case EPERM: return DRWAV_INVALID_OPERATION;
   4595     #endif
   4596     #ifdef ENOENT
   4597         case ENOENT: return DRWAV_DOES_NOT_EXIST;
   4598     #endif
   4599     #ifdef ESRCH
   4600         case ESRCH: return DRWAV_DOES_NOT_EXIST;
   4601     #endif
   4602     #ifdef EINTR
   4603         case EINTR: return DRWAV_INTERRUPT;
   4604     #endif
   4605     #ifdef EIO
   4606         case EIO: return DRWAV_IO_ERROR;
   4607     #endif
   4608     #ifdef ENXIO
   4609         case ENXIO: return DRWAV_DOES_NOT_EXIST;
   4610     #endif
   4611     #ifdef E2BIG
   4612         case E2BIG: return DRWAV_INVALID_ARGS;
   4613     #endif
   4614     #ifdef ENOEXEC
   4615         case ENOEXEC: return DRWAV_INVALID_FILE;
   4616     #endif
   4617     #ifdef EBADF
   4618         case EBADF: return DRWAV_INVALID_FILE;
   4619     #endif
   4620     #ifdef ECHILD
   4621         case ECHILD: return DRWAV_ERROR;
   4622     #endif
   4623     #ifdef EAGAIN
   4624         case EAGAIN: return DRWAV_UNAVAILABLE;
   4625     #endif
   4626     #ifdef ENOMEM
   4627         case ENOMEM: return DRWAV_OUT_OF_MEMORY;
   4628     #endif
   4629     #ifdef EACCES
   4630         case EACCES: return DRWAV_ACCESS_DENIED;
   4631     #endif
   4632     #ifdef EFAULT
   4633         case EFAULT: return DRWAV_BAD_ADDRESS;
   4634     #endif
   4635     #ifdef ENOTBLK
   4636         case ENOTBLK: return DRWAV_ERROR;
   4637     #endif
   4638     #ifdef EBUSY
   4639         case EBUSY: return DRWAV_BUSY;
   4640     #endif
   4641     #ifdef EEXIST
   4642         case EEXIST: return DRWAV_ALREADY_EXISTS;
   4643     #endif
   4644     #ifdef EXDEV
   4645         case EXDEV: return DRWAV_ERROR;
   4646     #endif
   4647     #ifdef ENODEV
   4648         case ENODEV: return DRWAV_DOES_NOT_EXIST;
   4649     #endif
   4650     #ifdef ENOTDIR
   4651         case ENOTDIR: return DRWAV_NOT_DIRECTORY;
   4652     #endif
   4653     #ifdef EISDIR
   4654         case EISDIR: return DRWAV_IS_DIRECTORY;
   4655     #endif
   4656     #ifdef EINVAL
   4657         case EINVAL: return DRWAV_INVALID_ARGS;
   4658     #endif
   4659     #ifdef ENFILE
   4660         case ENFILE: return DRWAV_TOO_MANY_OPEN_FILES;
   4661     #endif
   4662     #ifdef EMFILE
   4663         case EMFILE: return DRWAV_TOO_MANY_OPEN_FILES;
   4664     #endif
   4665     #ifdef ENOTTY
   4666         case ENOTTY: return DRWAV_INVALID_OPERATION;
   4667     #endif
   4668     #ifdef ETXTBSY
   4669         case ETXTBSY: return DRWAV_BUSY;
   4670     #endif
   4671     #ifdef EFBIG
   4672         case EFBIG: return DRWAV_TOO_BIG;
   4673     #endif
   4674     #ifdef ENOSPC
   4675         case ENOSPC: return DRWAV_NO_SPACE;
   4676     #endif
   4677     #ifdef ESPIPE
   4678         case ESPIPE: return DRWAV_BAD_SEEK;
   4679     #endif
   4680     #ifdef EROFS
   4681         case EROFS: return DRWAV_ACCESS_DENIED;
   4682     #endif
   4683     #ifdef EMLINK
   4684         case EMLINK: return DRWAV_TOO_MANY_LINKS;
   4685     #endif
   4686     #ifdef EPIPE
   4687         case EPIPE: return DRWAV_BAD_PIPE;
   4688     #endif
   4689     #ifdef EDOM
   4690         case EDOM: return DRWAV_OUT_OF_RANGE;
   4691     #endif
   4692     #ifdef ERANGE
   4693         case ERANGE: return DRWAV_OUT_OF_RANGE;
   4694     #endif
   4695     #ifdef EDEADLK
   4696         case EDEADLK: return DRWAV_DEADLOCK;
   4697     #endif
   4698     #ifdef ENAMETOOLONG
   4699         case ENAMETOOLONG: return DRWAV_PATH_TOO_LONG;
   4700     #endif
   4701     #ifdef ENOLCK
   4702         case ENOLCK: return DRWAV_ERROR;
   4703     #endif
   4704     #ifdef ENOSYS
   4705         case ENOSYS: return DRWAV_NOT_IMPLEMENTED;
   4706     #endif
   4707     #ifdef ENOTEMPTY
   4708         case ENOTEMPTY: return DRWAV_DIRECTORY_NOT_EMPTY;
   4709     #endif
   4710     #ifdef ELOOP
   4711         case ELOOP: return DRWAV_TOO_MANY_LINKS;
   4712     #endif
   4713     #ifdef ENOMSG
   4714         case ENOMSG: return DRWAV_NO_MESSAGE;
   4715     #endif
   4716     #ifdef EIDRM
   4717         case EIDRM: return DRWAV_ERROR;
   4718     #endif
   4719     #ifdef ECHRNG
   4720         case ECHRNG: return DRWAV_ERROR;
   4721     #endif
   4722     #ifdef EL2NSYNC
   4723         case EL2NSYNC: return DRWAV_ERROR;
   4724     #endif
   4725     #ifdef EL3HLT
   4726         case EL3HLT: return DRWAV_ERROR;
   4727     #endif
   4728     #ifdef EL3RST
   4729         case EL3RST: return DRWAV_ERROR;
   4730     #endif
   4731     #ifdef ELNRNG
   4732         case ELNRNG: return DRWAV_OUT_OF_RANGE;
   4733     #endif
   4734     #ifdef EUNATCH
   4735         case EUNATCH: return DRWAV_ERROR;
   4736     #endif
   4737     #ifdef ENOCSI
   4738         case ENOCSI: return DRWAV_ERROR;
   4739     #endif
   4740     #ifdef EL2HLT
   4741         case EL2HLT: return DRWAV_ERROR;
   4742     #endif
   4743     #ifdef EBADE
   4744         case EBADE: return DRWAV_ERROR;
   4745     #endif
   4746     #ifdef EBADR
   4747         case EBADR: return DRWAV_ERROR;
   4748     #endif
   4749     #ifdef EXFULL
   4750         case EXFULL: return DRWAV_ERROR;
   4751     #endif
   4752     #ifdef ENOANO
   4753         case ENOANO: return DRWAV_ERROR;
   4754     #endif
   4755     #ifdef EBADRQC
   4756         case EBADRQC: return DRWAV_ERROR;
   4757     #endif
   4758     #ifdef EBADSLT
   4759         case EBADSLT: return DRWAV_ERROR;
   4760     #endif
   4761     #ifdef EBFONT
   4762         case EBFONT: return DRWAV_INVALID_FILE;
   4763     #endif
   4764     #ifdef ENOSTR
   4765         case ENOSTR: return DRWAV_ERROR;
   4766     #endif
   4767     #ifdef ENODATA
   4768         case ENODATA: return DRWAV_NO_DATA_AVAILABLE;
   4769     #endif
   4770     #ifdef ETIME
   4771         case ETIME: return DRWAV_TIMEOUT;
   4772     #endif
   4773     #ifdef ENOSR
   4774         case ENOSR: return DRWAV_NO_DATA_AVAILABLE;
   4775     #endif
   4776     #ifdef ENONET
   4777         case ENONET: return DRWAV_NO_NETWORK;
   4778     #endif
   4779     #ifdef ENOPKG
   4780         case ENOPKG: return DRWAV_ERROR;
   4781     #endif
   4782     #ifdef EREMOTE
   4783         case EREMOTE: return DRWAV_ERROR;
   4784     #endif
   4785     #ifdef ENOLINK
   4786         case ENOLINK: return DRWAV_ERROR;
   4787     #endif
   4788     #ifdef EADV
   4789         case EADV: return DRWAV_ERROR;
   4790     #endif
   4791     #ifdef ESRMNT
   4792         case ESRMNT: return DRWAV_ERROR;
   4793     #endif
   4794     #ifdef ECOMM
   4795         case ECOMM: return DRWAV_ERROR;
   4796     #endif
   4797     #ifdef EPROTO
   4798         case EPROTO: return DRWAV_ERROR;
   4799     #endif
   4800     #ifdef EMULTIHOP
   4801         case EMULTIHOP: return DRWAV_ERROR;
   4802     #endif
   4803     #ifdef EDOTDOT
   4804         case EDOTDOT: return DRWAV_ERROR;
   4805     #endif
   4806     #ifdef EBADMSG
   4807         case EBADMSG: return DRWAV_BAD_MESSAGE;
   4808     #endif
   4809     #ifdef EOVERFLOW
   4810         case EOVERFLOW: return DRWAV_TOO_BIG;
   4811     #endif
   4812     #ifdef ENOTUNIQ
   4813         case ENOTUNIQ: return DRWAV_NOT_UNIQUE;
   4814     #endif
   4815     #ifdef EBADFD
   4816         case EBADFD: return DRWAV_ERROR;
   4817     #endif
   4818     #ifdef EREMCHG
   4819         case EREMCHG: return DRWAV_ERROR;
   4820     #endif
   4821     #ifdef ELIBACC
   4822         case ELIBACC: return DRWAV_ACCESS_DENIED;
   4823     #endif
   4824     #ifdef ELIBBAD
   4825         case ELIBBAD: return DRWAV_INVALID_FILE;
   4826     #endif
   4827     #ifdef ELIBSCN
   4828         case ELIBSCN: return DRWAV_INVALID_FILE;
   4829     #endif
   4830     #ifdef ELIBMAX
   4831         case ELIBMAX: return DRWAV_ERROR;
   4832     #endif
   4833     #ifdef ELIBEXEC
   4834         case ELIBEXEC: return DRWAV_ERROR;
   4835     #endif
   4836     #ifdef EILSEQ
   4837         case EILSEQ: return DRWAV_INVALID_DATA;
   4838     #endif
   4839     #ifdef ERESTART
   4840         case ERESTART: return DRWAV_ERROR;
   4841     #endif
   4842     #ifdef ESTRPIPE
   4843         case ESTRPIPE: return DRWAV_ERROR;
   4844     #endif
   4845     #ifdef EUSERS
   4846         case EUSERS: return DRWAV_ERROR;
   4847     #endif
   4848     #ifdef ENOTSOCK
   4849         case ENOTSOCK: return DRWAV_NOT_SOCKET;
   4850     #endif
   4851     #ifdef EDESTADDRREQ
   4852         case EDESTADDRREQ: return DRWAV_NO_ADDRESS;
   4853     #endif
   4854     #ifdef EMSGSIZE
   4855         case EMSGSIZE: return DRWAV_TOO_BIG;
   4856     #endif
   4857     #ifdef EPROTOTYPE
   4858         case EPROTOTYPE: return DRWAV_BAD_PROTOCOL;
   4859     #endif
   4860     #ifdef ENOPROTOOPT
   4861         case ENOPROTOOPT: return DRWAV_PROTOCOL_UNAVAILABLE;
   4862     #endif
   4863     #ifdef EPROTONOSUPPORT
   4864         case EPROTONOSUPPORT: return DRWAV_PROTOCOL_NOT_SUPPORTED;
   4865     #endif
   4866     #ifdef ESOCKTNOSUPPORT
   4867         case ESOCKTNOSUPPORT: return DRWAV_SOCKET_NOT_SUPPORTED;
   4868     #endif
   4869     #ifdef EOPNOTSUPP
   4870         case EOPNOTSUPP: return DRWAV_INVALID_OPERATION;
   4871     #endif
   4872     #ifdef EPFNOSUPPORT
   4873         case EPFNOSUPPORT: return DRWAV_PROTOCOL_FAMILY_NOT_SUPPORTED;
   4874     #endif
   4875     #ifdef EAFNOSUPPORT
   4876         case EAFNOSUPPORT: return DRWAV_ADDRESS_FAMILY_NOT_SUPPORTED;
   4877     #endif
   4878     #ifdef EADDRINUSE
   4879         case EADDRINUSE: return DRWAV_ALREADY_IN_USE;
   4880     #endif
   4881     #ifdef EADDRNOTAVAIL
   4882         case EADDRNOTAVAIL: return DRWAV_ERROR;
   4883     #endif
   4884     #ifdef ENETDOWN
   4885         case ENETDOWN: return DRWAV_NO_NETWORK;
   4886     #endif
   4887     #ifdef ENETUNREACH
   4888         case ENETUNREACH: return DRWAV_NO_NETWORK;
   4889     #endif
   4890     #ifdef ENETRESET
   4891         case ENETRESET: return DRWAV_NO_NETWORK;
   4892     #endif
   4893     #ifdef ECONNABORTED
   4894         case ECONNABORTED: return DRWAV_NO_NETWORK;
   4895     #endif
   4896     #ifdef ECONNRESET
   4897         case ECONNRESET: return DRWAV_CONNECTION_RESET;
   4898     #endif
   4899     #ifdef ENOBUFS
   4900         case ENOBUFS: return DRWAV_NO_SPACE;
   4901     #endif
   4902     #ifdef EISCONN
   4903         case EISCONN: return DRWAV_ALREADY_CONNECTED;
   4904     #endif
   4905     #ifdef ENOTCONN
   4906         case ENOTCONN: return DRWAV_NOT_CONNECTED;
   4907     #endif
   4908     #ifdef ESHUTDOWN
   4909         case ESHUTDOWN: return DRWAV_ERROR;
   4910     #endif
   4911     #ifdef ETOOMANYREFS
   4912         case ETOOMANYREFS: return DRWAV_ERROR;
   4913     #endif
   4914     #ifdef ETIMEDOUT
   4915         case ETIMEDOUT: return DRWAV_TIMEOUT;
   4916     #endif
   4917     #ifdef ECONNREFUSED
   4918         case ECONNREFUSED: return DRWAV_CONNECTION_REFUSED;
   4919     #endif
   4920     #ifdef EHOSTDOWN
   4921         case EHOSTDOWN: return DRWAV_NO_HOST;
   4922     #endif
   4923     #ifdef EHOSTUNREACH
   4924         case EHOSTUNREACH: return DRWAV_NO_HOST;
   4925     #endif
   4926     #ifdef EALREADY
   4927         case EALREADY: return DRWAV_IN_PROGRESS;
   4928     #endif
   4929     #ifdef EINPROGRESS
   4930         case EINPROGRESS: return DRWAV_IN_PROGRESS;
   4931     #endif
   4932     #ifdef ESTALE
   4933         case ESTALE: return DRWAV_INVALID_FILE;
   4934     #endif
   4935     #ifdef EUCLEAN
   4936         case EUCLEAN: return DRWAV_ERROR;
   4937     #endif
   4938     #ifdef ENOTNAM
   4939         case ENOTNAM: return DRWAV_ERROR;
   4940     #endif
   4941     #ifdef ENAVAIL
   4942         case ENAVAIL: return DRWAV_ERROR;
   4943     #endif
   4944     #ifdef EISNAM
   4945         case EISNAM: return DRWAV_ERROR;
   4946     #endif
   4947     #ifdef EREMOTEIO
   4948         case EREMOTEIO: return DRWAV_IO_ERROR;
   4949     #endif
   4950     #ifdef EDQUOT
   4951         case EDQUOT: return DRWAV_NO_SPACE;
   4952     #endif
   4953     #ifdef ENOMEDIUM
   4954         case ENOMEDIUM: return DRWAV_DOES_NOT_EXIST;
   4955     #endif
   4956     #ifdef EMEDIUMTYPE
   4957         case EMEDIUMTYPE: return DRWAV_ERROR;
   4958     #endif
   4959     #ifdef ECANCELED
   4960         case ECANCELED: return DRWAV_CANCELLED;
   4961     #endif
   4962     #ifdef ENOKEY
   4963         case ENOKEY: return DRWAV_ERROR;
   4964     #endif
   4965     #ifdef EKEYEXPIRED
   4966         case EKEYEXPIRED: return DRWAV_ERROR;
   4967     #endif
   4968     #ifdef EKEYREVOKED
   4969         case EKEYREVOKED: return DRWAV_ERROR;
   4970     #endif
   4971     #ifdef EKEYREJECTED
   4972         case EKEYREJECTED: return DRWAV_ERROR;
   4973     #endif
   4974     #ifdef EOWNERDEAD
   4975         case EOWNERDEAD: return DRWAV_ERROR;
   4976     #endif
   4977     #ifdef ENOTRECOVERABLE
   4978         case ENOTRECOVERABLE: return DRWAV_ERROR;
   4979     #endif
   4980     #ifdef ERFKILL
   4981         case ERFKILL: return DRWAV_ERROR;
   4982     #endif
   4983     #ifdef EHWPOISON
   4984         case EHWPOISON: return DRWAV_ERROR;
   4985     #endif
   4986         default: return DRWAV_ERROR;
   4987     }
   4988 }
   4989 /* End Errno */
   4990 
   4991 /* fopen */
   4992 DRWAV_PRIVATE drwav_result drwav_fopen(FILE** ppFile, const char* pFilePath, const char* pOpenMode)
   4993 {
   4994 #if defined(_MSC_VER) && _MSC_VER >= 1400
   4995     errno_t err;
   4996 #endif
   4997 
   4998     if (ppFile != NULL) {
   4999         *ppFile = NULL;  /* Safety. */
   5000     }
   5001 
   5002     if (pFilePath == NULL || pOpenMode == NULL || ppFile == NULL) {
   5003         return DRWAV_INVALID_ARGS;
   5004     }
   5005 
   5006 #if defined(_MSC_VER) && _MSC_VER >= 1400
   5007     err = fopen_s(ppFile, pFilePath, pOpenMode);
   5008     if (err != 0) {
   5009         return drwav_result_from_errno(err);
   5010     }
   5011 #else
   5012 #if defined(_WIN32) || defined(__APPLE__)
   5013     *ppFile = fopen(pFilePath, pOpenMode);
   5014 #else
   5015     #if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64 && defined(_LARGEFILE64_SOURCE)
   5016         *ppFile = fopen64(pFilePath, pOpenMode);
   5017     #else
   5018         *ppFile = fopen(pFilePath, pOpenMode);
   5019     #endif
   5020 #endif
   5021     if (*ppFile == NULL) {
   5022         drwav_result result = drwav_result_from_errno(errno);
   5023         if (result == DRWAV_SUCCESS) {
   5024             result = DRWAV_ERROR;   /* Just a safety check to make sure we never ever return success when pFile == NULL. */
   5025         }
   5026 
   5027         return result;
   5028     }
   5029 #endif
   5030 
   5031     return DRWAV_SUCCESS;
   5032 }
   5033 
   5034 /*
   5035 _wfopen() isn't always available in all compilation environments.
   5036 
   5037     * Windows only.
   5038     * MSVC seems to support it universally as far back as VC6 from what I can tell (haven't checked further back).
   5039     * MinGW-64 (both 32- and 64-bit) seems to support it.
   5040     * MinGW wraps it in !defined(__STRICT_ANSI__).
   5041     * OpenWatcom wraps it in !defined(_NO_EXT_KEYS).
   5042 
   5043 This can be reviewed as compatibility issues arise. The preference is to use _wfopen_s() and _wfopen() as opposed to the wcsrtombs()
   5044 fallback, so if you notice your compiler not detecting this properly I'm happy to look at adding support.
   5045 */
   5046 #if defined(_WIN32)
   5047     #if defined(_MSC_VER) || defined(__MINGW64__) || (!defined(__STRICT_ANSI__) && !defined(_NO_EXT_KEYS))
   5048         #define DRWAV_HAS_WFOPEN
   5049     #endif
   5050 #endif
   5051 
   5052 #ifndef DR_WAV_NO_WCHAR
   5053 DRWAV_PRIVATE drwav_result drwav_wfopen(FILE** ppFile, const wchar_t* pFilePath, const wchar_t* pOpenMode, const drwav_allocation_callbacks* pAllocationCallbacks)
   5054 {
   5055     if (ppFile != NULL) {
   5056         *ppFile = NULL;  /* Safety. */
   5057     }
   5058 
   5059     if (pFilePath == NULL || pOpenMode == NULL || ppFile == NULL) {
   5060         return DRWAV_INVALID_ARGS;
   5061     }
   5062 
   5063 #if defined(DRWAV_HAS_WFOPEN)
   5064     {
   5065         /* Use _wfopen() on Windows. */
   5066     #if defined(_MSC_VER) && _MSC_VER >= 1400
   5067         errno_t err = _wfopen_s(ppFile, pFilePath, pOpenMode);
   5068         if (err != 0) {
   5069             return drwav_result_from_errno(err);
   5070         }
   5071     #else
   5072         *ppFile = _wfopen(pFilePath, pOpenMode);
   5073         if (*ppFile == NULL) {
   5074             return drwav_result_from_errno(errno);
   5075         }
   5076     #endif
   5077         (void)pAllocationCallbacks;
   5078     }
   5079 #else
   5080 	/*
   5081     Use fopen() on anything other than Windows. Requires a conversion. This is annoying because
   5082 	fopen() is locale specific. The only real way I can think of to do this is with wcsrtombs(). Note
   5083 	that wcstombs() is apparently not thread-safe because it uses a static global mbstate_t object for
   5084     maintaining state. I've checked this with -std=c89 and it works, but if somebody get's a compiler
   5085 	error I'll look into improving compatibility.
   5086     */
   5087 
   5088 	/*
   5089 	Some compilers don't support wchar_t or wcsrtombs() which we're using below. In this case we just
   5090 	need to abort with an error. If you encounter a compiler lacking such support, add it to this list
   5091 	and submit a bug report and it'll be added to the library upstream.
   5092 	*/
   5093 	#if defined(__DJGPP__)
   5094 	{
   5095 		/* Nothing to do here. This will fall through to the error check below. */
   5096 	}
   5097 	#else
   5098     {
   5099         mbstate_t mbs;
   5100         size_t lenMB;
   5101         const wchar_t* pFilePathTemp = pFilePath;
   5102         char* pFilePathMB = NULL;
   5103         char pOpenModeMB[32] = {0};
   5104 
   5105         /* Get the length first. */
   5106         DRWAV_ZERO_OBJECT(&mbs);
   5107         lenMB = wcsrtombs(NULL, &pFilePathTemp, 0, &mbs);
   5108         if (lenMB == (size_t)-1) {
   5109             return drwav_result_from_errno(errno);
   5110         }
   5111 
   5112         pFilePathMB = (char*)drwav__malloc_from_callbacks(lenMB + 1, pAllocationCallbacks);
   5113         if (pFilePathMB == NULL) {
   5114             return DRWAV_OUT_OF_MEMORY;
   5115         }
   5116 
   5117         pFilePathTemp = pFilePath;
   5118         DRWAV_ZERO_OBJECT(&mbs);
   5119         wcsrtombs(pFilePathMB, &pFilePathTemp, lenMB + 1, &mbs);
   5120 
   5121         /* The open mode should always consist of ASCII characters so we should be able to do a trivial conversion. */
   5122         {
   5123             size_t i = 0;
   5124             for (;;) {
   5125                 if (pOpenMode[i] == 0) {
   5126                     pOpenModeMB[i] = '\0';
   5127                     break;
   5128                 }
   5129 
   5130                 pOpenModeMB[i] = (char)pOpenMode[i];
   5131                 i += 1;
   5132             }
   5133         }
   5134 
   5135         *ppFile = fopen(pFilePathMB, pOpenModeMB);
   5136 
   5137         drwav__free_from_callbacks(pFilePathMB, pAllocationCallbacks);
   5138     }
   5139 	#endif
   5140 
   5141     if (*ppFile == NULL) {
   5142         return DRWAV_ERROR;
   5143     }
   5144 #endif
   5145 
   5146     return DRWAV_SUCCESS;
   5147 }
   5148 #endif
   5149 /* End fopen */
   5150 
   5151 
   5152 DRWAV_PRIVATE size_t drwav__on_read_stdio(void* pUserData, void* pBufferOut, size_t bytesToRead)
   5153 {
   5154     return fread(pBufferOut, 1, bytesToRead, (FILE*)pUserData);
   5155 }
   5156 
   5157 DRWAV_PRIVATE size_t drwav__on_write_stdio(void* pUserData, const void* pData, size_t bytesToWrite)
   5158 {
   5159     return fwrite(pData, 1, bytesToWrite, (FILE*)pUserData);
   5160 }
   5161 
   5162 DRWAV_PRIVATE drwav_bool32 drwav__on_seek_stdio(void* pUserData, int offset, drwav_seek_origin origin)
   5163 {
   5164     return fseek((FILE*)pUserData, offset, (origin == drwav_seek_origin_current) ? SEEK_CUR : SEEK_SET) == 0;
   5165 }
   5166 
   5167 DRWAV_API drwav_bool32 drwav_init_file(drwav* pWav, const char* filename, const drwav_allocation_callbacks* pAllocationCallbacks)
   5168 {
   5169     return drwav_init_file_ex(pWav, filename, NULL, NULL, 0, pAllocationCallbacks);
   5170 }
   5171 
   5172 
   5173 DRWAV_PRIVATE drwav_bool32 drwav_init_file__internal_FILE(drwav* pWav, FILE* pFile, drwav_chunk_proc onChunk, void* pChunkUserData, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks)
   5174 {
   5175     drwav_bool32 result;
   5176 
   5177     result = drwav_preinit(pWav, drwav__on_read_stdio, drwav__on_seek_stdio, (void*)pFile, pAllocationCallbacks);
   5178     if (result != DRWAV_TRUE) {
   5179         fclose(pFile);
   5180         return result;
   5181     }
   5182     
   5183     result = drwav_init__internal(pWav, onChunk, pChunkUserData, flags);
   5184     if (result != DRWAV_TRUE) {
   5185         fclose(pFile);
   5186         return result;
   5187     }
   5188 
   5189     return DRWAV_TRUE;
   5190 }
   5191 
   5192 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)
   5193 {
   5194     FILE* pFile;
   5195     if (drwav_fopen(&pFile, filename, "rb") != DRWAV_SUCCESS) {
   5196         return DRWAV_FALSE;
   5197     }
   5198 
   5199     /* This takes ownership of the FILE* object. */
   5200     return drwav_init_file__internal_FILE(pWav, pFile, onChunk, pChunkUserData, flags, pAllocationCallbacks);
   5201 }
   5202 
   5203 #ifndef DR_WAV_NO_WCHAR
   5204 DRWAV_API drwav_bool32 drwav_init_file_w(drwav* pWav, const wchar_t* filename, const drwav_allocation_callbacks* pAllocationCallbacks)
   5205 {
   5206     return drwav_init_file_ex_w(pWav, filename, NULL, NULL, 0, pAllocationCallbacks);
   5207 }
   5208 
   5209 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)
   5210 {
   5211     FILE* pFile;
   5212     if (drwav_wfopen(&pFile, filename, L"rb", pAllocationCallbacks) != DRWAV_SUCCESS) {
   5213         return DRWAV_FALSE;
   5214     }
   5215 
   5216     /* This takes ownership of the FILE* object. */
   5217     return drwav_init_file__internal_FILE(pWav, pFile, onChunk, pChunkUserData, flags, pAllocationCallbacks);
   5218 }
   5219 #endif
   5220 
   5221 DRWAV_API drwav_bool32 drwav_init_file_with_metadata(drwav* pWav, const char* filename, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks)
   5222 {
   5223     FILE* pFile;
   5224     if (drwav_fopen(&pFile, filename, "rb") != DRWAV_SUCCESS) {
   5225         return DRWAV_FALSE;
   5226     }
   5227 
   5228     /* This takes ownership of the FILE* object. */
   5229     return drwav_init_file__internal_FILE(pWav, pFile, NULL, NULL, flags | DRWAV_WITH_METADATA, pAllocationCallbacks);
   5230 }
   5231 
   5232 #ifndef DR_WAV_NO_WCHAR
   5233 DRWAV_API drwav_bool32 drwav_init_file_with_metadata_w(drwav* pWav, const wchar_t* filename, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks)
   5234 {
   5235     FILE* pFile;
   5236     if (drwav_wfopen(&pFile, filename, L"rb", pAllocationCallbacks) != DRWAV_SUCCESS) {
   5237         return DRWAV_FALSE;
   5238     }
   5239 
   5240     /* This takes ownership of the FILE* object. */
   5241     return drwav_init_file__internal_FILE(pWav, pFile, NULL, NULL, flags | DRWAV_WITH_METADATA, pAllocationCallbacks);
   5242 }
   5243 #endif
   5244 
   5245 
   5246 DRWAV_PRIVATE drwav_bool32 drwav_init_file_write__internal_FILE(drwav* pWav, FILE* pFile, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount, drwav_bool32 isSequential, const drwav_allocation_callbacks* pAllocationCallbacks)
   5247 {
   5248     drwav_bool32 result;
   5249 
   5250     result = drwav_preinit_write(pWav, pFormat, isSequential, drwav__on_write_stdio, drwav__on_seek_stdio, (void*)pFile, pAllocationCallbacks);
   5251     if (result != DRWAV_TRUE) {
   5252         fclose(pFile);
   5253         return result;
   5254     }
   5255 
   5256     result = drwav_init_write__internal(pWav, pFormat, totalSampleCount);
   5257     if (result != DRWAV_TRUE) {
   5258         fclose(pFile);
   5259         return result;
   5260     }
   5261 
   5262     return DRWAV_TRUE;
   5263 }
   5264 
   5265 DRWAV_PRIVATE drwav_bool32 drwav_init_file_write__internal(drwav* pWav, const char* filename, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount, drwav_bool32 isSequential, const drwav_allocation_callbacks* pAllocationCallbacks)
   5266 {
   5267     FILE* pFile;
   5268     if (drwav_fopen(&pFile, filename, "wb") != DRWAV_SUCCESS) {
   5269         return DRWAV_FALSE;
   5270     }
   5271 
   5272     /* This takes ownership of the FILE* object. */
   5273     return drwav_init_file_write__internal_FILE(pWav, pFile, pFormat, totalSampleCount, isSequential, pAllocationCallbacks);
   5274 }
   5275 
   5276 #ifndef DR_WAV_NO_WCHAR
   5277 DRWAV_PRIVATE drwav_bool32 drwav_init_file_write_w__internal(drwav* pWav, const wchar_t* filename, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount, drwav_bool32 isSequential, const drwav_allocation_callbacks* pAllocationCallbacks)
   5278 {
   5279     FILE* pFile;
   5280     if (drwav_wfopen(&pFile, filename, L"wb", pAllocationCallbacks) != DRWAV_SUCCESS) {
   5281         return DRWAV_FALSE;
   5282     }
   5283 
   5284     /* This takes ownership of the FILE* object. */
   5285     return drwav_init_file_write__internal_FILE(pWav, pFile, pFormat, totalSampleCount, isSequential, pAllocationCallbacks);
   5286 }
   5287 #endif
   5288 
   5289 DRWAV_API drwav_bool32 drwav_init_file_write(drwav* pWav, const char* filename, const drwav_data_format* pFormat, const drwav_allocation_callbacks* pAllocationCallbacks)
   5290 {
   5291     return drwav_init_file_write__internal(pWav, filename, pFormat, 0, DRWAV_FALSE, pAllocationCallbacks);
   5292 }
   5293 
   5294 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)
   5295 {
   5296     return drwav_init_file_write__internal(pWav, filename, pFormat, totalSampleCount, DRWAV_TRUE, pAllocationCallbacks);
   5297 }
   5298 
   5299 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)
   5300 {
   5301     if (pFormat == NULL) {
   5302         return DRWAV_FALSE;
   5303     }
   5304 
   5305     return drwav_init_file_write_sequential(pWav, filename, pFormat, totalPCMFrameCount*pFormat->channels, pAllocationCallbacks);
   5306 }
   5307 
   5308 #ifndef DR_WAV_NO_WCHAR
   5309 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)
   5310 {
   5311     return drwav_init_file_write_w__internal(pWav, filename, pFormat, 0, DRWAV_FALSE, pAllocationCallbacks);
   5312 }
   5313 
   5314 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)
   5315 {
   5316     return drwav_init_file_write_w__internal(pWav, filename, pFormat, totalSampleCount, DRWAV_TRUE, pAllocationCallbacks);
   5317 }
   5318 
   5319 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)
   5320 {
   5321     if (pFormat == NULL) {
   5322         return DRWAV_FALSE;
   5323     }
   5324 
   5325     return drwav_init_file_write_sequential_w(pWav, filename, pFormat, totalPCMFrameCount*pFormat->channels, pAllocationCallbacks);
   5326 }
   5327 #endif
   5328 #endif  /* DR_WAV_NO_STDIO */
   5329 
   5330 
   5331 DRWAV_PRIVATE size_t drwav__on_read_memory(void* pUserData, void* pBufferOut, size_t bytesToRead)
   5332 {
   5333     drwav* pWav = (drwav*)pUserData;
   5334     size_t bytesRemaining;
   5335 
   5336     DRWAV_ASSERT(pWav != NULL);
   5337     DRWAV_ASSERT(pWav->memoryStream.dataSize >= pWav->memoryStream.currentReadPos);
   5338 
   5339     bytesRemaining = pWav->memoryStream.dataSize - pWav->memoryStream.currentReadPos;
   5340     if (bytesToRead > bytesRemaining) {
   5341         bytesToRead = bytesRemaining;
   5342     }
   5343 
   5344     if (bytesToRead > 0) {
   5345         DRWAV_COPY_MEMORY(pBufferOut, pWav->memoryStream.data + pWav->memoryStream.currentReadPos, bytesToRead);
   5346         pWav->memoryStream.currentReadPos += bytesToRead;
   5347     }
   5348 
   5349     return bytesToRead;
   5350 }
   5351 
   5352 DRWAV_PRIVATE drwav_bool32 drwav__on_seek_memory(void* pUserData, int offset, drwav_seek_origin origin)
   5353 {
   5354     drwav* pWav = (drwav*)pUserData;
   5355     DRWAV_ASSERT(pWav != NULL);
   5356 
   5357     if (origin == drwav_seek_origin_current) {
   5358         if (offset > 0) {
   5359             if (pWav->memoryStream.currentReadPos + offset > pWav->memoryStream.dataSize) {
   5360                 return DRWAV_FALSE; /* Trying to seek too far forward. */
   5361             }
   5362         } else {
   5363             if (pWav->memoryStream.currentReadPos < (size_t)-offset) {
   5364                 return DRWAV_FALSE; /* Trying to seek too far backwards. */
   5365             }
   5366         }
   5367 
   5368         /* This will never underflow thanks to the clamps above. */
   5369         pWav->memoryStream.currentReadPos += offset;
   5370     } else {
   5371         if ((drwav_uint32)offset <= pWav->memoryStream.dataSize) {
   5372             pWav->memoryStream.currentReadPos = offset;
   5373         } else {
   5374             return DRWAV_FALSE; /* Trying to seek too far forward. */
   5375         }
   5376     }
   5377 
   5378     return DRWAV_TRUE;
   5379 }
   5380 
   5381 DRWAV_PRIVATE size_t drwav__on_write_memory(void* pUserData, const void* pDataIn, size_t bytesToWrite)
   5382 {
   5383     drwav* pWav = (drwav*)pUserData;
   5384     size_t bytesRemaining;
   5385 
   5386     DRWAV_ASSERT(pWav != NULL);
   5387     DRWAV_ASSERT(pWav->memoryStreamWrite.dataCapacity >= pWav->memoryStreamWrite.currentWritePos);
   5388 
   5389     bytesRemaining = pWav->memoryStreamWrite.dataCapacity - pWav->memoryStreamWrite.currentWritePos;
   5390     if (bytesRemaining < bytesToWrite) {
   5391         /* Need to reallocate. */
   5392         void* pNewData;
   5393         size_t newDataCapacity = (pWav->memoryStreamWrite.dataCapacity == 0) ? 256 : pWav->memoryStreamWrite.dataCapacity * 2;
   5394 
   5395         /* If doubling wasn't enough, just make it the minimum required size to write the data. */
   5396         if ((newDataCapacity - pWav->memoryStreamWrite.currentWritePos) < bytesToWrite) {
   5397             newDataCapacity = pWav->memoryStreamWrite.currentWritePos + bytesToWrite;
   5398         }
   5399 
   5400         pNewData = drwav__realloc_from_callbacks(*pWav->memoryStreamWrite.ppData, newDataCapacity, pWav->memoryStreamWrite.dataCapacity, &pWav->allocationCallbacks);
   5401         if (pNewData == NULL) {
   5402             return 0;
   5403         }
   5404 
   5405         *pWav->memoryStreamWrite.ppData = pNewData;
   5406         pWav->memoryStreamWrite.dataCapacity = newDataCapacity;
   5407     }
   5408 
   5409     DRWAV_COPY_MEMORY(((drwav_uint8*)(*pWav->memoryStreamWrite.ppData)) + pWav->memoryStreamWrite.currentWritePos, pDataIn, bytesToWrite);
   5410 
   5411     pWav->memoryStreamWrite.currentWritePos += bytesToWrite;
   5412     if (pWav->memoryStreamWrite.dataSize < pWav->memoryStreamWrite.currentWritePos) {
   5413         pWav->memoryStreamWrite.dataSize = pWav->memoryStreamWrite.currentWritePos;
   5414     }
   5415 
   5416     *pWav->memoryStreamWrite.pDataSize = pWav->memoryStreamWrite.dataSize;
   5417 
   5418     return bytesToWrite;
   5419 }
   5420 
   5421 DRWAV_PRIVATE drwav_bool32 drwav__on_seek_memory_write(void* pUserData, int offset, drwav_seek_origin origin)
   5422 {
   5423     drwav* pWav = (drwav*)pUserData;
   5424     DRWAV_ASSERT(pWav != NULL);
   5425 
   5426     if (origin == drwav_seek_origin_current) {
   5427         if (offset > 0) {
   5428             if (pWav->memoryStreamWrite.currentWritePos + offset > pWav->memoryStreamWrite.dataSize) {
   5429                 offset = (int)(pWav->memoryStreamWrite.dataSize - pWav->memoryStreamWrite.currentWritePos);  /* Trying to seek too far forward. */
   5430             }
   5431         } else {
   5432             if (pWav->memoryStreamWrite.currentWritePos < (size_t)-offset) {
   5433                 offset = -(int)pWav->memoryStreamWrite.currentWritePos;  /* Trying to seek too far backwards. */
   5434             }
   5435         }
   5436 
   5437         /* This will never underflow thanks to the clamps above. */
   5438         pWav->memoryStreamWrite.currentWritePos += offset;
   5439     } else {
   5440         if ((drwav_uint32)offset <= pWav->memoryStreamWrite.dataSize) {
   5441             pWav->memoryStreamWrite.currentWritePos = offset;
   5442         } else {
   5443             pWav->memoryStreamWrite.currentWritePos = pWav->memoryStreamWrite.dataSize;  /* Trying to seek too far forward. */
   5444         }
   5445     }
   5446 
   5447     return DRWAV_TRUE;
   5448 }
   5449 
   5450 DRWAV_API drwav_bool32 drwav_init_memory(drwav* pWav, const void* data, size_t dataSize, const drwav_allocation_callbacks* pAllocationCallbacks)
   5451 {
   5452     return drwav_init_memory_ex(pWav, data, dataSize, NULL, NULL, 0, pAllocationCallbacks);
   5453 }
   5454 
   5455 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)
   5456 {
   5457     if (data == NULL || dataSize == 0) {
   5458         return DRWAV_FALSE;
   5459     }
   5460 
   5461     if (!drwav_preinit(pWav, drwav__on_read_memory, drwav__on_seek_memory, pWav, pAllocationCallbacks)) {
   5462         return DRWAV_FALSE;
   5463     }
   5464 
   5465     pWav->memoryStream.data = (const drwav_uint8*)data;
   5466     pWav->memoryStream.dataSize = dataSize;
   5467     pWav->memoryStream.currentReadPos = 0;
   5468 
   5469     return drwav_init__internal(pWav, onChunk, pChunkUserData, flags);
   5470 }
   5471 
   5472 DRWAV_API drwav_bool32 drwav_init_memory_with_metadata(drwav* pWav, const void* data, size_t dataSize, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks)
   5473 {
   5474     if (data == NULL || dataSize == 0) {
   5475         return DRWAV_FALSE;
   5476     }
   5477 
   5478     if (!drwav_preinit(pWav, drwav__on_read_memory, drwav__on_seek_memory, pWav, pAllocationCallbacks)) {
   5479         return DRWAV_FALSE;
   5480     }
   5481 
   5482     pWav->memoryStream.data = (const drwav_uint8*)data;
   5483     pWav->memoryStream.dataSize = dataSize;
   5484     pWav->memoryStream.currentReadPos = 0;
   5485 
   5486     return drwav_init__internal(pWav, NULL, NULL, flags | DRWAV_WITH_METADATA);
   5487 }
   5488 
   5489 
   5490 DRWAV_PRIVATE drwav_bool32 drwav_init_memory_write__internal(drwav* pWav, void** ppData, size_t* pDataSize, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount, drwav_bool32 isSequential, const drwav_allocation_callbacks* pAllocationCallbacks)
   5491 {
   5492     if (ppData == NULL || pDataSize == NULL) {
   5493         return DRWAV_FALSE;
   5494     }
   5495 
   5496     *ppData = NULL; /* Important because we're using realloc()! */
   5497     *pDataSize = 0;
   5498 
   5499     if (!drwav_preinit_write(pWav, pFormat, isSequential, drwav__on_write_memory, drwav__on_seek_memory_write, pWav, pAllocationCallbacks)) {
   5500         return DRWAV_FALSE;
   5501     }
   5502 
   5503     pWav->memoryStreamWrite.ppData = ppData;
   5504     pWav->memoryStreamWrite.pDataSize = pDataSize;
   5505     pWav->memoryStreamWrite.dataSize = 0;
   5506     pWav->memoryStreamWrite.dataCapacity = 0;
   5507     pWav->memoryStreamWrite.currentWritePos = 0;
   5508 
   5509     return drwav_init_write__internal(pWav, pFormat, totalSampleCount);
   5510 }
   5511 
   5512 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)
   5513 {
   5514     return drwav_init_memory_write__internal(pWav, ppData, pDataSize, pFormat, 0, DRWAV_FALSE, pAllocationCallbacks);
   5515 }
   5516 
   5517 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)
   5518 {
   5519     return drwav_init_memory_write__internal(pWav, ppData, pDataSize, pFormat, totalSampleCount, DRWAV_TRUE, pAllocationCallbacks);
   5520 }
   5521 
   5522 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)
   5523 {
   5524     if (pFormat == NULL) {
   5525         return DRWAV_FALSE;
   5526     }
   5527 
   5528     return drwav_init_memory_write_sequential(pWav, ppData, pDataSize, pFormat, totalPCMFrameCount*pFormat->channels, pAllocationCallbacks);
   5529 }
   5530 
   5531 
   5532 
   5533 DRWAV_API drwav_result drwav_uninit(drwav* pWav)
   5534 {
   5535     drwav_result result = DRWAV_SUCCESS;
   5536 
   5537     if (pWav == NULL) {
   5538         return DRWAV_INVALID_ARGS;
   5539     }
   5540 
   5541     /*
   5542     If the drwav object was opened in write mode we'll need to finalize a few things:
   5543       - Make sure the "data" chunk is aligned to 16-bits for RIFF containers, or 64 bits for W64 containers.
   5544       - Set the size of the "data" chunk.
   5545     */
   5546     if (pWav->onWrite != NULL) {
   5547         drwav_uint32 paddingSize = 0;
   5548 
   5549         /* Padding. Do not adjust pWav->dataChunkDataSize - this should not include the padding. */
   5550         if (pWav->container == drwav_container_riff || pWav->container == drwav_container_rf64) {
   5551             paddingSize = drwav__chunk_padding_size_riff(pWav->dataChunkDataSize);
   5552         } else {
   5553             paddingSize = drwav__chunk_padding_size_w64(pWav->dataChunkDataSize);
   5554         }
   5555 
   5556         if (paddingSize > 0) {
   5557             drwav_uint64 paddingData = 0;
   5558             drwav__write(pWav, &paddingData, paddingSize);  /* Byte order does not matter for this. */
   5559         }
   5560 
   5561         /*
   5562         Chunk sizes. When using sequential mode, these will have been filled in at initialization time. We only need
   5563         to do this when using non-sequential mode.
   5564         */
   5565         if (pWav->onSeek && !pWav->isSequentialWrite) {
   5566             if (pWav->container == drwav_container_riff) {
   5567                 /* The "RIFF" chunk size. */
   5568                 if (pWav->onSeek(pWav->pUserData, 4, drwav_seek_origin_start)) {
   5569                     drwav_uint32 riffChunkSize = drwav__riff_chunk_size_riff(pWav->dataChunkDataSize, pWav->pMetadata, pWav->metadataCount);
   5570                     drwav__write_u32ne_to_le(pWav, riffChunkSize);
   5571                 }
   5572 
   5573                 /* The "data" chunk size. */
   5574                 if (pWav->onSeek(pWav->pUserData, (int)pWav->dataChunkDataPos - 4, drwav_seek_origin_start)) {
   5575                     drwav_uint32 dataChunkSize = drwav__data_chunk_size_riff(pWav->dataChunkDataSize);
   5576                     drwav__write_u32ne_to_le(pWav, dataChunkSize);
   5577                 }
   5578             } else if (pWav->container == drwav_container_w64) {
   5579                 /* The "RIFF" chunk size. */
   5580                 if (pWav->onSeek(pWav->pUserData, 16, drwav_seek_origin_start)) {
   5581                     drwav_uint64 riffChunkSize = drwav__riff_chunk_size_w64(pWav->dataChunkDataSize);
   5582                     drwav__write_u64ne_to_le(pWav, riffChunkSize);
   5583                 }
   5584 
   5585                 /* The "data" chunk size. */
   5586                 if (pWav->onSeek(pWav->pUserData, (int)pWav->dataChunkDataPos - 8, drwav_seek_origin_start)) {
   5587                     drwav_uint64 dataChunkSize = drwav__data_chunk_size_w64(pWav->dataChunkDataSize);
   5588                     drwav__write_u64ne_to_le(pWav, dataChunkSize);
   5589                 }
   5590             } else if (pWav->container == drwav_container_rf64) {
   5591                 /* We only need to update the ds64 chunk. The "RIFF" and "data" chunks always have their sizes set to 0xFFFFFFFF for RF64. */
   5592                 int ds64BodyPos = 12 + 8;
   5593 
   5594                 /* The "RIFF" chunk size. */
   5595                 if (pWav->onSeek(pWav->pUserData, ds64BodyPos + 0, drwav_seek_origin_start)) {
   5596                     drwav_uint64 riffChunkSize = drwav__riff_chunk_size_rf64(pWav->dataChunkDataSize, pWav->pMetadata, pWav->metadataCount);
   5597                     drwav__write_u64ne_to_le(pWav, riffChunkSize);
   5598                 }
   5599 
   5600                 /* The "data" chunk size. */
   5601                 if (pWav->onSeek(pWav->pUserData, ds64BodyPos + 8, drwav_seek_origin_start)) {
   5602                     drwav_uint64 dataChunkSize = drwav__data_chunk_size_rf64(pWav->dataChunkDataSize);
   5603                     drwav__write_u64ne_to_le(pWav, dataChunkSize);
   5604                 }
   5605             }
   5606         }
   5607 
   5608         /* Validation for sequential mode. */
   5609         if (pWav->isSequentialWrite) {
   5610             if (pWav->dataChunkDataSize != pWav->dataChunkDataSizeTargetWrite) {
   5611                 result = DRWAV_INVALID_FILE;
   5612             }
   5613         }
   5614     } else {
   5615         drwav_free(pWav->pMetadata, &pWav->allocationCallbacks);
   5616     }
   5617 
   5618 #ifndef DR_WAV_NO_STDIO
   5619     /*
   5620     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()
   5621     was used by looking at the onRead and onSeek callbacks.
   5622     */
   5623     if (pWav->onRead == drwav__on_read_stdio || pWav->onWrite == drwav__on_write_stdio) {
   5624         fclose((FILE*)pWav->pUserData);
   5625     }
   5626 #endif
   5627 
   5628     return result;
   5629 }
   5630 
   5631 
   5632 
   5633 DRWAV_API size_t drwav_read_raw(drwav* pWav, size_t bytesToRead, void* pBufferOut)
   5634 {
   5635     size_t bytesRead;
   5636     drwav_uint32 bytesPerFrame;
   5637 
   5638     if (pWav == NULL || bytesToRead == 0) {
   5639         return 0;   /* Invalid args. */
   5640     }
   5641 
   5642     if (bytesToRead > pWav->bytesRemaining) {
   5643         bytesToRead = (size_t)pWav->bytesRemaining;
   5644     }
   5645 
   5646     if (bytesToRead == 0) {
   5647         return 0;   /* At end. */
   5648     }
   5649 
   5650     bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
   5651     if (bytesPerFrame == 0) {
   5652         return 0;   /* Could not determine the bytes per frame. */
   5653     }
   5654 
   5655     if (pBufferOut != NULL) {
   5656         bytesRead = pWav->onRead(pWav->pUserData, pBufferOut, bytesToRead);
   5657     } else {
   5658         /* We need to seek. If we fail, we need to read-and-discard to make sure we get a good byte count. */
   5659         bytesRead = 0;
   5660         while (bytesRead < bytesToRead) {
   5661             size_t bytesToSeek = (bytesToRead - bytesRead);
   5662             if (bytesToSeek > 0x7FFFFFFF) {
   5663                 bytesToSeek = 0x7FFFFFFF;
   5664             }
   5665 
   5666             if (pWav->onSeek(pWav->pUserData, (int)bytesToSeek, drwav_seek_origin_current) == DRWAV_FALSE) {
   5667                 break;
   5668             }
   5669 
   5670             bytesRead += bytesToSeek;
   5671         }
   5672 
   5673         /* When we get here we may need to read-and-discard some data. */
   5674         while (bytesRead < bytesToRead) {
   5675             drwav_uint8 buffer[4096];
   5676             size_t bytesSeeked;
   5677             size_t bytesToSeek = (bytesToRead - bytesRead);
   5678             if (bytesToSeek > sizeof(buffer)) {
   5679                 bytesToSeek = sizeof(buffer);
   5680             }
   5681 
   5682             bytesSeeked = pWav->onRead(pWav->pUserData, buffer, bytesToSeek);
   5683             bytesRead += bytesSeeked;
   5684 
   5685             if (bytesSeeked < bytesToSeek) {
   5686                 break;  /* Reached the end. */
   5687             }
   5688         }
   5689     }
   5690 
   5691     pWav->readCursorInPCMFrames += bytesRead / bytesPerFrame;
   5692 
   5693     pWav->bytesRemaining -= bytesRead;
   5694     return bytesRead;
   5695 }
   5696 
   5697 
   5698 
   5699 DRWAV_API drwav_uint64 drwav_read_pcm_frames_le(drwav* pWav, drwav_uint64 framesToRead, void* pBufferOut)
   5700 {
   5701     drwav_uint32 bytesPerFrame;
   5702     drwav_uint64 bytesToRead;   /* Intentionally uint64 instead of size_t so we can do a check that we're not reading too much on 32-bit builds. */
   5703     drwav_uint64 framesRemainingInFile;
   5704 
   5705     if (pWav == NULL || framesToRead == 0) {
   5706         return 0;
   5707     }
   5708 
   5709     /* Cannot use this function for compressed formats. */
   5710     if (drwav__is_compressed_format_tag(pWav->translatedFormatTag)) {
   5711         return 0;
   5712     }
   5713 
   5714     framesRemainingInFile = pWav->totalPCMFrameCount - pWav->readCursorInPCMFrames;
   5715     if (framesToRead > framesRemainingInFile) {
   5716         framesToRead = framesRemainingInFile;
   5717     }
   5718 
   5719     bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
   5720     if (bytesPerFrame == 0) {
   5721         return 0;
   5722     }
   5723 
   5724     /* Don't try to read more samples than can potentially fit in the output buffer. */
   5725     bytesToRead = framesToRead * bytesPerFrame;
   5726     if (bytesToRead > DRWAV_SIZE_MAX) {
   5727         bytesToRead = (DRWAV_SIZE_MAX / bytesPerFrame) * bytesPerFrame; /* Round the number of bytes to read to a clean frame boundary. */
   5728     }
   5729 
   5730     /*
   5731     Doing an explicit check here just to make it clear that we don't want to be attempt to read anything if there's no bytes to read. There
   5732     *could* be a time where it evaluates to 0 due to overflowing.
   5733     */
   5734     if (bytesToRead == 0) {
   5735         return 0;
   5736     }
   5737 
   5738     return drwav_read_raw(pWav, (size_t)bytesToRead, pBufferOut) / bytesPerFrame;
   5739 }
   5740 
   5741 DRWAV_API drwav_uint64 drwav_read_pcm_frames_be(drwav* pWav, drwav_uint64 framesToRead, void* pBufferOut)
   5742 {
   5743     drwav_uint64 framesRead = drwav_read_pcm_frames_le(pWav, framesToRead, pBufferOut);
   5744 
   5745     if (pBufferOut != NULL) {
   5746         drwav_uint32 bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
   5747         if (bytesPerFrame == 0) {
   5748             return 0;   /* Could not get the bytes per frame which means bytes per sample cannot be determined and we don't know how to byte swap. */
   5749         }
   5750 
   5751         drwav__bswap_samples(pBufferOut, framesRead*pWav->channels, bytesPerFrame/pWav->channels);
   5752     }
   5753 
   5754     return framesRead;
   5755 }
   5756 
   5757 DRWAV_API drwav_uint64 drwav_read_pcm_frames(drwav* pWav, drwav_uint64 framesToRead, void* pBufferOut)
   5758 {
   5759     drwav_uint64 framesRead = 0;
   5760 
   5761     if (drwav_is_container_be(pWav->container)) {
   5762         /*
   5763         Special case for AIFF. AIFF is a big-endian encoded format, but it supports a format that is
   5764         PCM in little-endian encoding. In this case, we fall through this branch and treate it as
   5765         little-endian.
   5766         */
   5767         if (pWav->container != drwav_container_aiff || pWav->aiff.isLE == DRWAV_FALSE) {
   5768             if (drwav__is_little_endian()) {
   5769                 framesRead = drwav_read_pcm_frames_be(pWav, framesToRead, pBufferOut);
   5770             } else {
   5771                 framesRead = drwav_read_pcm_frames_le(pWav, framesToRead, pBufferOut);
   5772             }
   5773 
   5774             goto post_process;
   5775         }
   5776     }
   5777 
   5778     /* Getting here means the data should be considered little-endian. */
   5779     if (drwav__is_little_endian()) {
   5780         framesRead = drwav_read_pcm_frames_le(pWav, framesToRead, pBufferOut);
   5781     } else {
   5782         framesRead = drwav_read_pcm_frames_be(pWav, framesToRead, pBufferOut);
   5783     }
   5784 
   5785     /*
   5786     Here is where we check if we need to do a signed/unsigned conversion for AIFF. The reason we need to do this
   5787     is because dr_wav always assumes an 8-bit sample is unsigned, whereas AIFF can have signed 8-bit formats.
   5788     */
   5789     post_process:
   5790     {
   5791         if (pWav->container == drwav_container_aiff && pWav->bitsPerSample == 8 && pWav->aiff.isUnsigned == DRWAV_FALSE) {
   5792             if (pBufferOut != NULL) {
   5793                 drwav_uint64 iSample;
   5794 
   5795                 for (iSample = 0; iSample < framesRead * pWav->channels; iSample += 1) {
   5796                     ((drwav_uint8*)pBufferOut)[iSample] += 128;
   5797                 }
   5798             }
   5799         }
   5800     }
   5801 
   5802     return framesRead;
   5803 }
   5804 
   5805 
   5806 
   5807 DRWAV_PRIVATE drwav_bool32 drwav_seek_to_first_pcm_frame(drwav* pWav)
   5808 {
   5809     if (pWav->onWrite != NULL) {
   5810         return DRWAV_FALSE; /* No seeking in write mode. */
   5811     }
   5812 
   5813     if (!pWav->onSeek(pWav->pUserData, (int)pWav->dataChunkDataPos, drwav_seek_origin_start)) {
   5814         return DRWAV_FALSE;
   5815     }
   5816 
   5817     if (drwav__is_compressed_format_tag(pWav->translatedFormatTag)) {
   5818         /* Cached data needs to be cleared for compressed formats. */
   5819         if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ADPCM) {
   5820             DRWAV_ZERO_OBJECT(&pWav->msadpcm);
   5821         } else if (pWav->translatedFormatTag == DR_WAVE_FORMAT_DVI_ADPCM) {
   5822             DRWAV_ZERO_OBJECT(&pWav->ima);
   5823         } else {
   5824             DRWAV_ASSERT(DRWAV_FALSE);  /* If this assertion is triggered it means I've implemented a new compressed format but forgot to add a branch for it here. */
   5825         }
   5826     }
   5827 
   5828     pWav->readCursorInPCMFrames = 0;
   5829     pWav->bytesRemaining = pWav->dataChunkDataSize;
   5830 
   5831     return DRWAV_TRUE;
   5832 }
   5833 
   5834 DRWAV_API drwav_bool32 drwav_seek_to_pcm_frame(drwav* pWav, drwav_uint64 targetFrameIndex)
   5835 {
   5836     /* Seeking should be compatible with wave files > 2GB. */
   5837 
   5838     if (pWav == NULL || pWav->onSeek == NULL) {
   5839         return DRWAV_FALSE;
   5840     }
   5841 
   5842     /* No seeking in write mode. */
   5843     if (pWav->onWrite != NULL) {
   5844         return DRWAV_FALSE;
   5845     }
   5846 
   5847     /* If there are no samples, just return DRWAV_TRUE without doing anything. */
   5848     if (pWav->totalPCMFrameCount == 0) {
   5849         return DRWAV_TRUE;
   5850     }
   5851 
   5852     /* Make sure the sample is clamped. */
   5853     if (targetFrameIndex > pWav->totalPCMFrameCount) {
   5854         targetFrameIndex = pWav->totalPCMFrameCount;
   5855     }
   5856 
   5857     /*
   5858     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
   5859     to seek back to the start.
   5860     */
   5861     if (drwav__is_compressed_format_tag(pWav->translatedFormatTag)) {
   5862         /* TODO: This can be optimized. */
   5863 
   5864         /*
   5865         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,
   5866         we first need to seek back to the start and then just do the same thing as a forward seek.
   5867         */
   5868         if (targetFrameIndex < pWav->readCursorInPCMFrames) {
   5869             if (!drwav_seek_to_first_pcm_frame(pWav)) {
   5870                 return DRWAV_FALSE;
   5871             }
   5872         }
   5873 
   5874         if (targetFrameIndex > pWav->readCursorInPCMFrames) {
   5875             drwav_uint64 offsetInFrames = targetFrameIndex - pWav->readCursorInPCMFrames;
   5876 
   5877             drwav_int16 devnull[2048];
   5878             while (offsetInFrames > 0) {
   5879                 drwav_uint64 framesRead = 0;
   5880                 drwav_uint64 framesToRead = offsetInFrames;
   5881                 if (framesToRead > drwav_countof(devnull)/pWav->channels) {
   5882                     framesToRead = drwav_countof(devnull)/pWav->channels;
   5883                 }
   5884 
   5885                 if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ADPCM) {
   5886                     framesRead = drwav_read_pcm_frames_s16__msadpcm(pWav, framesToRead, devnull);
   5887                 } else if (pWav->translatedFormatTag == DR_WAVE_FORMAT_DVI_ADPCM) {
   5888                     framesRead = drwav_read_pcm_frames_s16__ima(pWav, framesToRead, devnull);
   5889                 } else {
   5890                     DRWAV_ASSERT(DRWAV_FALSE);  /* If this assertion is triggered it means I've implemented a new compressed format but forgot to add a branch for it here. */
   5891                 }
   5892 
   5893                 if (framesRead != framesToRead) {
   5894                     return DRWAV_FALSE;
   5895                 }
   5896 
   5897                 offsetInFrames -= framesRead;
   5898             }
   5899         }
   5900     } else {
   5901         drwav_uint64 totalSizeInBytes;
   5902         drwav_uint64 currentBytePos;
   5903         drwav_uint64 targetBytePos;
   5904         drwav_uint64 offset;
   5905         drwav_uint32 bytesPerFrame;
   5906 
   5907         bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
   5908         if (bytesPerFrame == 0) {
   5909             return DRWAV_FALSE; /* Not able to calculate offset. */
   5910         }
   5911 
   5912         totalSizeInBytes = pWav->totalPCMFrameCount * bytesPerFrame;
   5913         /*DRWAV_ASSERT(totalSizeInBytes >= pWav->bytesRemaining);*/
   5914 
   5915         currentBytePos = totalSizeInBytes - pWav->bytesRemaining;
   5916         targetBytePos  = targetFrameIndex * bytesPerFrame;
   5917 
   5918         if (currentBytePos < targetBytePos) {
   5919             /* Offset forwards. */
   5920             offset = (targetBytePos - currentBytePos);
   5921         } else {
   5922             /* Offset backwards. */
   5923             if (!drwav_seek_to_first_pcm_frame(pWav)) {
   5924                 return DRWAV_FALSE;
   5925             }
   5926             offset = targetBytePos;
   5927         }
   5928 
   5929         while (offset > 0) {
   5930             int offset32 = ((offset > INT_MAX) ? INT_MAX : (int)offset);
   5931             if (!pWav->onSeek(pWav->pUserData, offset32, drwav_seek_origin_current)) {
   5932                 return DRWAV_FALSE;
   5933             }
   5934 
   5935             pWav->readCursorInPCMFrames += offset32 / bytesPerFrame;
   5936             pWav->bytesRemaining        -= offset32;
   5937             offset                      -= offset32;
   5938         }
   5939     }
   5940 
   5941     return DRWAV_TRUE;
   5942 }
   5943 
   5944 DRWAV_API drwav_result drwav_get_cursor_in_pcm_frames(drwav* pWav, drwav_uint64* pCursor)
   5945 {
   5946     if (pCursor == NULL) {
   5947         return DRWAV_INVALID_ARGS;
   5948     }
   5949 
   5950     *pCursor = 0;   /* Safety. */
   5951 
   5952     if (pWav == NULL) {
   5953         return DRWAV_INVALID_ARGS;
   5954     }
   5955 
   5956     *pCursor = pWav->readCursorInPCMFrames;
   5957 
   5958     return DRWAV_SUCCESS;
   5959 }
   5960 
   5961 DRWAV_API drwav_result drwav_get_length_in_pcm_frames(drwav* pWav, drwav_uint64* pLength)
   5962 {
   5963     if (pLength == NULL) {
   5964         return DRWAV_INVALID_ARGS;
   5965     }
   5966 
   5967     *pLength = 0;   /* Safety. */
   5968 
   5969     if (pWav == NULL) {
   5970         return DRWAV_INVALID_ARGS;
   5971     }
   5972 
   5973     *pLength = pWav->totalPCMFrameCount;
   5974 
   5975     return DRWAV_SUCCESS;
   5976 }
   5977 
   5978 
   5979 DRWAV_API size_t drwav_write_raw(drwav* pWav, size_t bytesToWrite, const void* pData)
   5980 {
   5981     size_t bytesWritten;
   5982 
   5983     if (pWav == NULL || bytesToWrite == 0 || pData == NULL) {
   5984         return 0;
   5985     }
   5986 
   5987     bytesWritten = pWav->onWrite(pWav->pUserData, pData, bytesToWrite);
   5988     pWav->dataChunkDataSize += bytesWritten;
   5989 
   5990     return bytesWritten;
   5991 }
   5992 
   5993 DRWAV_API drwav_uint64 drwav_write_pcm_frames_le(drwav* pWav, drwav_uint64 framesToWrite, const void* pData)
   5994 {
   5995     drwav_uint64 bytesToWrite;
   5996     drwav_uint64 bytesWritten;
   5997     const drwav_uint8* pRunningData;
   5998 
   5999     if (pWav == NULL || framesToWrite == 0 || pData == NULL) {
   6000         return 0;
   6001     }
   6002 
   6003     bytesToWrite = ((framesToWrite * pWav->channels * pWav->bitsPerSample) / 8);
   6004     if (bytesToWrite > DRWAV_SIZE_MAX) {
   6005         return 0;
   6006     }
   6007 
   6008     bytesWritten = 0;
   6009     pRunningData = (const drwav_uint8*)pData;
   6010 
   6011     while (bytesToWrite > 0) {
   6012         size_t bytesJustWritten;
   6013         drwav_uint64 bytesToWriteThisIteration;
   6014 
   6015         bytesToWriteThisIteration = bytesToWrite;
   6016         DRWAV_ASSERT(bytesToWriteThisIteration <= DRWAV_SIZE_MAX);  /* <-- This is checked above. */
   6017 
   6018         bytesJustWritten = drwav_write_raw(pWav, (size_t)bytesToWriteThisIteration, pRunningData);
   6019         if (bytesJustWritten == 0) {
   6020             break;
   6021         }
   6022 
   6023         bytesToWrite -= bytesJustWritten;
   6024         bytesWritten += bytesJustWritten;
   6025         pRunningData += bytesJustWritten;
   6026     }
   6027 
   6028     return (bytesWritten * 8) / pWav->bitsPerSample / pWav->channels;
   6029 }
   6030 
   6031 DRWAV_API drwav_uint64 drwav_write_pcm_frames_be(drwav* pWav, drwav_uint64 framesToWrite, const void* pData)
   6032 {
   6033     drwav_uint64 bytesToWrite;
   6034     drwav_uint64 bytesWritten;
   6035     drwav_uint32 bytesPerSample;
   6036     const drwav_uint8* pRunningData;
   6037 
   6038     if (pWav == NULL || framesToWrite == 0 || pData == NULL) {
   6039         return 0;
   6040     }
   6041 
   6042     bytesToWrite = ((framesToWrite * pWav->channels * pWav->bitsPerSample) / 8);
   6043     if (bytesToWrite > DRWAV_SIZE_MAX) {
   6044         return 0;
   6045     }
   6046 
   6047     bytesWritten = 0;
   6048     pRunningData = (const drwav_uint8*)pData;
   6049 
   6050     bytesPerSample = drwav_get_bytes_per_pcm_frame(pWav) / pWav->channels;
   6051     if (bytesPerSample == 0) {
   6052         return 0;   /* Cannot determine bytes per sample, or bytes per sample is less than one byte. */
   6053     }
   6054 
   6055     while (bytesToWrite > 0) {
   6056         drwav_uint8 temp[4096];
   6057         drwav_uint32 sampleCount;
   6058         size_t bytesJustWritten;
   6059         drwav_uint64 bytesToWriteThisIteration;
   6060 
   6061         bytesToWriteThisIteration = bytesToWrite;
   6062         DRWAV_ASSERT(bytesToWriteThisIteration <= DRWAV_SIZE_MAX);  /* <-- This is checked above. */
   6063 
   6064         /*
   6065         WAV files are always little-endian. We need to byte swap on big-endian architectures. Since our input buffer is read-only we need
   6066         to use an intermediary buffer for the conversion.
   6067         */
   6068         sampleCount = sizeof(temp)/bytesPerSample;
   6069 
   6070         if (bytesToWriteThisIteration > ((drwav_uint64)sampleCount)*bytesPerSample) {
   6071             bytesToWriteThisIteration = ((drwav_uint64)sampleCount)*bytesPerSample;
   6072         }
   6073 
   6074         DRWAV_COPY_MEMORY(temp, pRunningData, (size_t)bytesToWriteThisIteration);
   6075         drwav__bswap_samples(temp, sampleCount, bytesPerSample);
   6076 
   6077         bytesJustWritten = drwav_write_raw(pWav, (size_t)bytesToWriteThisIteration, temp);
   6078         if (bytesJustWritten == 0) {
   6079             break;
   6080         }
   6081 
   6082         bytesToWrite -= bytesJustWritten;
   6083         bytesWritten += bytesJustWritten;
   6084         pRunningData += bytesJustWritten;
   6085     }
   6086 
   6087     return (bytesWritten * 8) / pWav->bitsPerSample / pWav->channels;
   6088 }
   6089 
   6090 DRWAV_API drwav_uint64 drwav_write_pcm_frames(drwav* pWav, drwav_uint64 framesToWrite, const void* pData)
   6091 {
   6092     if (drwav__is_little_endian()) {
   6093         return drwav_write_pcm_frames_le(pWav, framesToWrite, pData);
   6094     } else {
   6095         return drwav_write_pcm_frames_be(pWav, framesToWrite, pData);
   6096     }
   6097 }
   6098 
   6099 
   6100 DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__msadpcm(drwav* pWav, drwav_uint64 framesToRead, drwav_int16* pBufferOut)
   6101 {
   6102     drwav_uint64 totalFramesRead = 0;
   6103 
   6104     DRWAV_ASSERT(pWav != NULL);
   6105     DRWAV_ASSERT(framesToRead > 0);
   6106 
   6107     /* TODO: Lots of room for optimization here. */
   6108 
   6109     while (pWav->readCursorInPCMFrames < pWav->totalPCMFrameCount) {
   6110         DRWAV_ASSERT(framesToRead > 0); /* This loop iteration will never get hit with framesToRead == 0 because it's asserted at the top, and we check for 0 inside the loop just below. */
   6111 
   6112         /* If there are no cached frames we need to load a new block. */
   6113         if (pWav->msadpcm.cachedFrameCount == 0 && pWav->msadpcm.bytesRemainingInBlock == 0) {
   6114             if (pWav->channels == 1) {
   6115                 /* Mono. */
   6116                 drwav_uint8 header[7];
   6117                 if (pWav->onRead(pWav->pUserData, header, sizeof(header)) != sizeof(header)) {
   6118                     return totalFramesRead;
   6119                 }
   6120                 pWav->msadpcm.bytesRemainingInBlock = pWav->fmt.blockAlign - sizeof(header);
   6121 
   6122                 pWav->msadpcm.predictor[0]     = header[0];
   6123                 pWav->msadpcm.delta[0]         = drwav_bytes_to_s16(header + 1);
   6124                 pWav->msadpcm.prevFrames[0][1] = (drwav_int32)drwav_bytes_to_s16(header + 3);
   6125                 pWav->msadpcm.prevFrames[0][0] = (drwav_int32)drwav_bytes_to_s16(header + 5);
   6126                 pWav->msadpcm.cachedFrames[2]  = pWav->msadpcm.prevFrames[0][0];
   6127                 pWav->msadpcm.cachedFrames[3]  = pWav->msadpcm.prevFrames[0][1];
   6128                 pWav->msadpcm.cachedFrameCount = 2;
   6129             } else {
   6130                 /* Stereo. */
   6131                 drwav_uint8 header[14];
   6132                 if (pWav->onRead(pWav->pUserData, header, sizeof(header)) != sizeof(header)) {
   6133                     return totalFramesRead;
   6134                 }
   6135                 pWav->msadpcm.bytesRemainingInBlock = pWav->fmt.blockAlign - sizeof(header);
   6136 
   6137                 pWav->msadpcm.predictor[0] = header[0];
   6138                 pWav->msadpcm.predictor[1] = header[1];
   6139                 pWav->msadpcm.delta[0] = drwav_bytes_to_s16(header + 2);
   6140                 pWav->msadpcm.delta[1] = drwav_bytes_to_s16(header + 4);
   6141                 pWav->msadpcm.prevFrames[0][1] = (drwav_int32)drwav_bytes_to_s16(header + 6);
   6142                 pWav->msadpcm.prevFrames[1][1] = (drwav_int32)drwav_bytes_to_s16(header + 8);
   6143                 pWav->msadpcm.prevFrames[0][0] = (drwav_int32)drwav_bytes_to_s16(header + 10);
   6144                 pWav->msadpcm.prevFrames[1][0] = (drwav_int32)drwav_bytes_to_s16(header + 12);
   6145 
   6146                 pWav->msadpcm.cachedFrames[0] = pWav->msadpcm.prevFrames[0][0];
   6147                 pWav->msadpcm.cachedFrames[1] = pWav->msadpcm.prevFrames[1][0];
   6148                 pWav->msadpcm.cachedFrames[2] = pWav->msadpcm.prevFrames[0][1];
   6149                 pWav->msadpcm.cachedFrames[3] = pWav->msadpcm.prevFrames[1][1];
   6150                 pWav->msadpcm.cachedFrameCount = 2;
   6151             }
   6152         }
   6153 
   6154         /* Output anything that's cached. */
   6155         while (framesToRead > 0 && pWav->msadpcm.cachedFrameCount > 0 && pWav->readCursorInPCMFrames < pWav->totalPCMFrameCount) {
   6156             if (pBufferOut != NULL) {
   6157                 drwav_uint32 iSample = 0;
   6158                 for (iSample = 0; iSample < pWav->channels; iSample += 1) {
   6159                     pBufferOut[iSample] = (drwav_int16)pWav->msadpcm.cachedFrames[(drwav_countof(pWav->msadpcm.cachedFrames) - (pWav->msadpcm.cachedFrameCount*pWav->channels)) + iSample];
   6160                 }
   6161 
   6162                 pBufferOut += pWav->channels;
   6163             }
   6164 
   6165             framesToRead    -= 1;
   6166             totalFramesRead += 1;
   6167             pWav->readCursorInPCMFrames += 1;
   6168             pWav->msadpcm.cachedFrameCount -= 1;
   6169         }
   6170 
   6171         if (framesToRead == 0) {
   6172             break;
   6173         }
   6174 
   6175 
   6176         /*
   6177         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
   6178         loop iteration which will trigger the loading of a new block.
   6179         */
   6180         if (pWav->msadpcm.cachedFrameCount == 0) {
   6181             if (pWav->msadpcm.bytesRemainingInBlock == 0) {
   6182                 continue;
   6183             } else {
   6184                 static drwav_int32 adaptationTable[] = {
   6185                     230, 230, 230, 230, 307, 409, 512, 614,
   6186                     768, 614, 512, 409, 307, 230, 230, 230
   6187                 };
   6188                 static drwav_int32 coeff1Table[] = { 256, 512, 0, 192, 240, 460,  392 };
   6189                 static drwav_int32 coeff2Table[] = { 0,  -256, 0, 64,  0,  -208, -232 };
   6190 
   6191                 drwav_uint8 nibbles;
   6192                 drwav_int32 nibble0;
   6193                 drwav_int32 nibble1;
   6194 
   6195                 if (pWav->onRead(pWav->pUserData, &nibbles, 1) != 1) {
   6196                     return totalFramesRead;
   6197                 }
   6198                 pWav->msadpcm.bytesRemainingInBlock -= 1;
   6199 
   6200                 /* TODO: Optimize away these if statements. */
   6201                 nibble0 = ((nibbles & 0xF0) >> 4); if ((nibbles & 0x80)) { nibble0 |= 0xFFFFFFF0UL; }
   6202                 nibble1 = ((nibbles & 0x0F) >> 0); if ((nibbles & 0x08)) { nibble1 |= 0xFFFFFFF0UL; }
   6203 
   6204                 if (pWav->channels == 1) {
   6205                     /* Mono. */
   6206                     drwav_int32 newSample0;
   6207                     drwav_int32 newSample1;
   6208 
   6209                     newSample0  = ((pWav->msadpcm.prevFrames[0][1] * coeff1Table[pWav->msadpcm.predictor[0]]) + (pWav->msadpcm.prevFrames[0][0] * coeff2Table[pWav->msadpcm.predictor[0]])) >> 8;
   6210                     newSample0 += nibble0 * pWav->msadpcm.delta[0];
   6211                     newSample0  = drwav_clamp(newSample0, -32768, 32767);
   6212 
   6213                     pWav->msadpcm.delta[0] = (adaptationTable[((nibbles & 0xF0) >> 4)] * pWav->msadpcm.delta[0]) >> 8;
   6214                     if (pWav->msadpcm.delta[0] < 16) {
   6215                         pWav->msadpcm.delta[0] = 16;
   6216                     }
   6217 
   6218                     pWav->msadpcm.prevFrames[0][0] = pWav->msadpcm.prevFrames[0][1];
   6219                     pWav->msadpcm.prevFrames[0][1] = newSample0;
   6220 
   6221 
   6222                     newSample1  = ((pWav->msadpcm.prevFrames[0][1] * coeff1Table[pWav->msadpcm.predictor[0]]) + (pWav->msadpcm.prevFrames[0][0] * coeff2Table[pWav->msadpcm.predictor[0]])) >> 8;
   6223                     newSample1 += nibble1 * pWav->msadpcm.delta[0];
   6224                     newSample1  = drwav_clamp(newSample1, -32768, 32767);
   6225 
   6226                     pWav->msadpcm.delta[0] = (adaptationTable[((nibbles & 0x0F) >> 0)] * pWav->msadpcm.delta[0]) >> 8;
   6227                     if (pWav->msadpcm.delta[0] < 16) {
   6228                         pWav->msadpcm.delta[0] = 16;
   6229                     }
   6230 
   6231                     pWav->msadpcm.prevFrames[0][0] = pWav->msadpcm.prevFrames[0][1];
   6232                     pWav->msadpcm.prevFrames[0][1] = newSample1;
   6233 
   6234 
   6235                     pWav->msadpcm.cachedFrames[2] = newSample0;
   6236                     pWav->msadpcm.cachedFrames[3] = newSample1;
   6237                     pWav->msadpcm.cachedFrameCount = 2;
   6238                 } else {
   6239                     /* Stereo. */
   6240                     drwav_int32 newSample0;
   6241                     drwav_int32 newSample1;
   6242 
   6243                     /* Left. */
   6244                     newSample0  = ((pWav->msadpcm.prevFrames[0][1] * coeff1Table[pWav->msadpcm.predictor[0]]) + (pWav->msadpcm.prevFrames[0][0] * coeff2Table[pWav->msadpcm.predictor[0]])) >> 8;
   6245                     newSample0 += nibble0 * pWav->msadpcm.delta[0];
   6246                     newSample0  = drwav_clamp(newSample0, -32768, 32767);
   6247 
   6248                     pWav->msadpcm.delta[0] = (adaptationTable[((nibbles & 0xF0) >> 4)] * pWav->msadpcm.delta[0]) >> 8;
   6249                     if (pWav->msadpcm.delta[0] < 16) {
   6250                         pWav->msadpcm.delta[0] = 16;
   6251                     }
   6252 
   6253                     pWav->msadpcm.prevFrames[0][0] = pWav->msadpcm.prevFrames[0][1];
   6254                     pWav->msadpcm.prevFrames[0][1] = newSample0;
   6255 
   6256 
   6257                     /* Right. */
   6258                     newSample1  = ((pWav->msadpcm.prevFrames[1][1] * coeff1Table[pWav->msadpcm.predictor[1]]) + (pWav->msadpcm.prevFrames[1][0] * coeff2Table[pWav->msadpcm.predictor[1]])) >> 8;
   6259                     newSample1 += nibble1 * pWav->msadpcm.delta[1];
   6260                     newSample1  = drwav_clamp(newSample1, -32768, 32767);
   6261 
   6262                     pWav->msadpcm.delta[1] = (adaptationTable[((nibbles & 0x0F) >> 0)] * pWav->msadpcm.delta[1]) >> 8;
   6263                     if (pWav->msadpcm.delta[1] < 16) {
   6264                         pWav->msadpcm.delta[1] = 16;
   6265                     }
   6266 
   6267                     pWav->msadpcm.prevFrames[1][0] = pWav->msadpcm.prevFrames[1][1];
   6268                     pWav->msadpcm.prevFrames[1][1] = newSample1;
   6269 
   6270                     pWav->msadpcm.cachedFrames[2] = newSample0;
   6271                     pWav->msadpcm.cachedFrames[3] = newSample1;
   6272                     pWav->msadpcm.cachedFrameCount = 1;
   6273                 }
   6274             }
   6275         }
   6276     }
   6277 
   6278     return totalFramesRead;
   6279 }
   6280 
   6281 
   6282 DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__ima(drwav* pWav, drwav_uint64 framesToRead, drwav_int16* pBufferOut)
   6283 {
   6284     drwav_uint64 totalFramesRead = 0;
   6285     drwav_uint32 iChannel;
   6286 
   6287     static drwav_int32 indexTable[16] = {
   6288         -1, -1, -1, -1, 2, 4, 6, 8,
   6289         -1, -1, -1, -1, 2, 4, 6, 8
   6290     };
   6291 
   6292     static drwav_int32 stepTable[89] = {
   6293         7,     8,     9,     10,    11,    12,    13,    14,    16,    17,
   6294         19,    21,    23,    25,    28,    31,    34,    37,    41,    45,
   6295         50,    55,    60,    66,    73,    80,    88,    97,    107,   118,
   6296         130,   143,   157,   173,   190,   209,   230,   253,   279,   307,
   6297         337,   371,   408,   449,   494,   544,   598,   658,   724,   796,
   6298         876,   963,   1060,  1166,  1282,  1411,  1552,  1707,  1878,  2066,
   6299         2272,  2499,  2749,  3024,  3327,  3660,  4026,  4428,  4871,  5358,
   6300         5894,  6484,  7132,  7845,  8630,  9493,  10442, 11487, 12635, 13899,
   6301         15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
   6302     };
   6303 
   6304     DRWAV_ASSERT(pWav != NULL);
   6305     DRWAV_ASSERT(framesToRead > 0);
   6306 
   6307     /* TODO: Lots of room for optimization here. */
   6308 
   6309     while (pWav->readCursorInPCMFrames < pWav->totalPCMFrameCount) {
   6310         DRWAV_ASSERT(framesToRead > 0); /* This loop iteration will never get hit with framesToRead == 0 because it's asserted at the top, and we check for 0 inside the loop just below. */
   6311 
   6312         /* If there are no cached samples we need to load a new block. */
   6313         if (pWav->ima.cachedFrameCount == 0 && pWav->ima.bytesRemainingInBlock == 0) {
   6314             if (pWav->channels == 1) {
   6315                 /* Mono. */
   6316                 drwav_uint8 header[4];
   6317                 if (pWav->onRead(pWav->pUserData, header, sizeof(header)) != sizeof(header)) {
   6318                     return totalFramesRead;
   6319                 }
   6320                 pWav->ima.bytesRemainingInBlock = pWav->fmt.blockAlign - sizeof(header);
   6321 
   6322                 if (header[2] >= drwav_countof(stepTable)) {
   6323                     pWav->onSeek(pWav->pUserData, pWav->ima.bytesRemainingInBlock, drwav_seek_origin_current);
   6324                     pWav->ima.bytesRemainingInBlock = 0;
   6325                     return totalFramesRead; /* Invalid data. */
   6326                 }
   6327 
   6328                 pWav->ima.predictor[0] = (drwav_int16)drwav_bytes_to_u16(header + 0);
   6329                 pWav->ima.stepIndex[0] = drwav_clamp(header[2], 0, (drwav_int32)drwav_countof(stepTable)-1);    /* Clamp not necessary because we checked above, but adding here to silence a static analysis warning. */
   6330                 pWav->ima.cachedFrames[drwav_countof(pWav->ima.cachedFrames) - 1] = pWav->ima.predictor[0];
   6331                 pWav->ima.cachedFrameCount = 1;
   6332             } else {
   6333                 /* Stereo. */
   6334                 drwav_uint8 header[8];
   6335                 if (pWav->onRead(pWav->pUserData, header, sizeof(header)) != sizeof(header)) {
   6336                     return totalFramesRead;
   6337                 }
   6338                 pWav->ima.bytesRemainingInBlock = pWav->fmt.blockAlign - sizeof(header);
   6339 
   6340                 if (header[2] >= drwav_countof(stepTable) || header[6] >= drwav_countof(stepTable)) {
   6341                     pWav->onSeek(pWav->pUserData, pWav->ima.bytesRemainingInBlock, drwav_seek_origin_current);
   6342                     pWav->ima.bytesRemainingInBlock = 0;
   6343                     return totalFramesRead; /* Invalid data. */
   6344                 }
   6345 
   6346                 pWav->ima.predictor[0] = drwav_bytes_to_s16(header + 0);
   6347                 pWav->ima.stepIndex[0] = drwav_clamp(header[2], 0, (drwav_int32)drwav_countof(stepTable)-1);    /* Clamp not necessary because we checked above, but adding here to silence a static analysis warning. */
   6348                 pWav->ima.predictor[1] = drwav_bytes_to_s16(header + 4);
   6349                 pWav->ima.stepIndex[1] = drwav_clamp(header[6], 0, (drwav_int32)drwav_countof(stepTable)-1);    /* Clamp not necessary because we checked above, but adding here to silence a static analysis warning. */
   6350 
   6351                 pWav->ima.cachedFrames[drwav_countof(pWav->ima.cachedFrames) - 2] = pWav->ima.predictor[0];
   6352                 pWav->ima.cachedFrames[drwav_countof(pWav->ima.cachedFrames) - 1] = pWav->ima.predictor[1];
   6353                 pWav->ima.cachedFrameCount = 1;
   6354             }
   6355         }
   6356 
   6357         /* Output anything that's cached. */
   6358         while (framesToRead > 0 && pWav->ima.cachedFrameCount > 0 && pWav->readCursorInPCMFrames < pWav->totalPCMFrameCount) {
   6359             if (pBufferOut != NULL) {
   6360                 drwav_uint32 iSample;
   6361                 for (iSample = 0; iSample < pWav->channels; iSample += 1) {
   6362                     pBufferOut[iSample] = (drwav_int16)pWav->ima.cachedFrames[(drwav_countof(pWav->ima.cachedFrames) - (pWav->ima.cachedFrameCount*pWav->channels)) + iSample];
   6363                 }
   6364                 pBufferOut += pWav->channels;
   6365             }
   6366 
   6367             framesToRead    -= 1;
   6368             totalFramesRead += 1;
   6369             pWav->readCursorInPCMFrames += 1;
   6370             pWav->ima.cachedFrameCount -= 1;
   6371         }
   6372 
   6373         if (framesToRead == 0) {
   6374             break;
   6375         }
   6376 
   6377         /*
   6378         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
   6379         loop iteration which will trigger the loading of a new block.
   6380         */
   6381         if (pWav->ima.cachedFrameCount == 0) {
   6382             if (pWav->ima.bytesRemainingInBlock == 0) {
   6383                 continue;
   6384             } else {
   6385                 /*
   6386                 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
   6387                 left channel, 4 bytes for the right channel.
   6388                 */
   6389                 pWav->ima.cachedFrameCount = 8;
   6390                 for (iChannel = 0; iChannel < pWav->channels; ++iChannel) {
   6391                     drwav_uint32 iByte;
   6392                     drwav_uint8 nibbles[4];
   6393                     if (pWav->onRead(pWav->pUserData, &nibbles, 4) != 4) {
   6394                         pWav->ima.cachedFrameCount = 0;
   6395                         return totalFramesRead;
   6396                     }
   6397                     pWav->ima.bytesRemainingInBlock -= 4;
   6398 
   6399                     for (iByte = 0; iByte < 4; ++iByte) {
   6400                         drwav_uint8 nibble0 = ((nibbles[iByte] & 0x0F) >> 0);
   6401                         drwav_uint8 nibble1 = ((nibbles[iByte] & 0xF0) >> 4);
   6402 
   6403                         drwav_int32 step      = stepTable[pWav->ima.stepIndex[iChannel]];
   6404                         drwav_int32 predictor = pWav->ima.predictor[iChannel];
   6405 
   6406                         drwav_int32      diff  = step >> 3;
   6407                         if (nibble0 & 1) diff += step >> 2;
   6408                         if (nibble0 & 2) diff += step >> 1;
   6409                         if (nibble0 & 4) diff += step;
   6410                         if (nibble0 & 8) diff  = -diff;
   6411 
   6412                         predictor = drwav_clamp(predictor + diff, -32768, 32767);
   6413                         pWav->ima.predictor[iChannel] = predictor;
   6414                         pWav->ima.stepIndex[iChannel] = drwav_clamp(pWav->ima.stepIndex[iChannel] + indexTable[nibble0], 0, (drwav_int32)drwav_countof(stepTable)-1);
   6415                         pWav->ima.cachedFrames[(drwav_countof(pWav->ima.cachedFrames) - (pWav->ima.cachedFrameCount*pWav->channels)) + (iByte*2+0)*pWav->channels + iChannel] = predictor;
   6416 
   6417 
   6418                         step      = stepTable[pWav->ima.stepIndex[iChannel]];
   6419                         predictor = pWav->ima.predictor[iChannel];
   6420 
   6421                                          diff  = step >> 3;
   6422                         if (nibble1 & 1) diff += step >> 2;
   6423                         if (nibble1 & 2) diff += step >> 1;
   6424                         if (nibble1 & 4) diff += step;
   6425                         if (nibble1 & 8) diff  = -diff;
   6426 
   6427                         predictor = drwav_clamp(predictor + diff, -32768, 32767);
   6428                         pWav->ima.predictor[iChannel] = predictor;
   6429                         pWav->ima.stepIndex[iChannel] = drwav_clamp(pWav->ima.stepIndex[iChannel] + indexTable[nibble1], 0, (drwav_int32)drwav_countof(stepTable)-1);
   6430                         pWav->ima.cachedFrames[(drwav_countof(pWav->ima.cachedFrames) - (pWav->ima.cachedFrameCount*pWav->channels)) + (iByte*2+1)*pWav->channels + iChannel] = predictor;
   6431                     }
   6432                 }
   6433             }
   6434         }
   6435     }
   6436 
   6437     return totalFramesRead;
   6438 }
   6439 
   6440 
   6441 #ifndef DR_WAV_NO_CONVERSION_API
   6442 static unsigned short g_drwavAlawTable[256] = {
   6443     0xEA80, 0xEB80, 0xE880, 0xE980, 0xEE80, 0xEF80, 0xEC80, 0xED80, 0xE280, 0xE380, 0xE080, 0xE180, 0xE680, 0xE780, 0xE480, 0xE580,
   6444     0xF540, 0xF5C0, 0xF440, 0xF4C0, 0xF740, 0xF7C0, 0xF640, 0xF6C0, 0xF140, 0xF1C0, 0xF040, 0xF0C0, 0xF340, 0xF3C0, 0xF240, 0xF2C0,
   6445     0xAA00, 0xAE00, 0xA200, 0xA600, 0xBA00, 0xBE00, 0xB200, 0xB600, 0x8A00, 0x8E00, 0x8200, 0x8600, 0x9A00, 0x9E00, 0x9200, 0x9600,
   6446     0xD500, 0xD700, 0xD100, 0xD300, 0xDD00, 0xDF00, 0xD900, 0xDB00, 0xC500, 0xC700, 0xC100, 0xC300, 0xCD00, 0xCF00, 0xC900, 0xCB00,
   6447     0xFEA8, 0xFEB8, 0xFE88, 0xFE98, 0xFEE8, 0xFEF8, 0xFEC8, 0xFED8, 0xFE28, 0xFE38, 0xFE08, 0xFE18, 0xFE68, 0xFE78, 0xFE48, 0xFE58,
   6448     0xFFA8, 0xFFB8, 0xFF88, 0xFF98, 0xFFE8, 0xFFF8, 0xFFC8, 0xFFD8, 0xFF28, 0xFF38, 0xFF08, 0xFF18, 0xFF68, 0xFF78, 0xFF48, 0xFF58,
   6449     0xFAA0, 0xFAE0, 0xFA20, 0xFA60, 0xFBA0, 0xFBE0, 0xFB20, 0xFB60, 0xF8A0, 0xF8E0, 0xF820, 0xF860, 0xF9A0, 0xF9E0, 0xF920, 0xF960,
   6450     0xFD50, 0xFD70, 0xFD10, 0xFD30, 0xFDD0, 0xFDF0, 0xFD90, 0xFDB0, 0xFC50, 0xFC70, 0xFC10, 0xFC30, 0xFCD0, 0xFCF0, 0xFC90, 0xFCB0,
   6451     0x1580, 0x1480, 0x1780, 0x1680, 0x1180, 0x1080, 0x1380, 0x1280, 0x1D80, 0x1C80, 0x1F80, 0x1E80, 0x1980, 0x1880, 0x1B80, 0x1A80,
   6452     0x0AC0, 0x0A40, 0x0BC0, 0x0B40, 0x08C0, 0x0840, 0x09C0, 0x0940, 0x0EC0, 0x0E40, 0x0FC0, 0x0F40, 0x0CC0, 0x0C40, 0x0DC0, 0x0D40,
   6453     0x5600, 0x5200, 0x5E00, 0x5A00, 0x4600, 0x4200, 0x4E00, 0x4A00, 0x7600, 0x7200, 0x7E00, 0x7A00, 0x6600, 0x6200, 0x6E00, 0x6A00,
   6454     0x2B00, 0x2900, 0x2F00, 0x2D00, 0x2300, 0x2100, 0x2700, 0x2500, 0x3B00, 0x3900, 0x3F00, 0x3D00, 0x3300, 0x3100, 0x3700, 0x3500,
   6455     0x0158, 0x0148, 0x0178, 0x0168, 0x0118, 0x0108, 0x0138, 0x0128, 0x01D8, 0x01C8, 0x01F8, 0x01E8, 0x0198, 0x0188, 0x01B8, 0x01A8,
   6456     0x0058, 0x0048, 0x0078, 0x0068, 0x0018, 0x0008, 0x0038, 0x0028, 0x00D8, 0x00C8, 0x00F8, 0x00E8, 0x0098, 0x0088, 0x00B8, 0x00A8,
   6457     0x0560, 0x0520, 0x05E0, 0x05A0, 0x0460, 0x0420, 0x04E0, 0x04A0, 0x0760, 0x0720, 0x07E0, 0x07A0, 0x0660, 0x0620, 0x06E0, 0x06A0,
   6458     0x02B0, 0x0290, 0x02F0, 0x02D0, 0x0230, 0x0210, 0x0270, 0x0250, 0x03B0, 0x0390, 0x03F0, 0x03D0, 0x0330, 0x0310, 0x0370, 0x0350
   6459 };
   6460 
   6461 static unsigned short g_drwavMulawTable[256] = {
   6462     0x8284, 0x8684, 0x8A84, 0x8E84, 0x9284, 0x9684, 0x9A84, 0x9E84, 0xA284, 0xA684, 0xAA84, 0xAE84, 0xB284, 0xB684, 0xBA84, 0xBE84,
   6463     0xC184, 0xC384, 0xC584, 0xC784, 0xC984, 0xCB84, 0xCD84, 0xCF84, 0xD184, 0xD384, 0xD584, 0xD784, 0xD984, 0xDB84, 0xDD84, 0xDF84,
   6464     0xE104, 0xE204, 0xE304, 0xE404, 0xE504, 0xE604, 0xE704, 0xE804, 0xE904, 0xEA04, 0xEB04, 0xEC04, 0xED04, 0xEE04, 0xEF04, 0xF004,
   6465     0xF0C4, 0xF144, 0xF1C4, 0xF244, 0xF2C4, 0xF344, 0xF3C4, 0xF444, 0xF4C4, 0xF544, 0xF5C4, 0xF644, 0xF6C4, 0xF744, 0xF7C4, 0xF844,
   6466     0xF8A4, 0xF8E4, 0xF924, 0xF964, 0xF9A4, 0xF9E4, 0xFA24, 0xFA64, 0xFAA4, 0xFAE4, 0xFB24, 0xFB64, 0xFBA4, 0xFBE4, 0xFC24, 0xFC64,
   6467     0xFC94, 0xFCB4, 0xFCD4, 0xFCF4, 0xFD14, 0xFD34, 0xFD54, 0xFD74, 0xFD94, 0xFDB4, 0xFDD4, 0xFDF4, 0xFE14, 0xFE34, 0xFE54, 0xFE74,
   6468     0xFE8C, 0xFE9C, 0xFEAC, 0xFEBC, 0xFECC, 0xFEDC, 0xFEEC, 0xFEFC, 0xFF0C, 0xFF1C, 0xFF2C, 0xFF3C, 0xFF4C, 0xFF5C, 0xFF6C, 0xFF7C,
   6469     0xFF88, 0xFF90, 0xFF98, 0xFFA0, 0xFFA8, 0xFFB0, 0xFFB8, 0xFFC0, 0xFFC8, 0xFFD0, 0xFFD8, 0xFFE0, 0xFFE8, 0xFFF0, 0xFFF8, 0x0000,
   6470     0x7D7C, 0x797C, 0x757C, 0x717C, 0x6D7C, 0x697C, 0x657C, 0x617C, 0x5D7C, 0x597C, 0x557C, 0x517C, 0x4D7C, 0x497C, 0x457C, 0x417C,
   6471     0x3E7C, 0x3C7C, 0x3A7C, 0x387C, 0x367C, 0x347C, 0x327C, 0x307C, 0x2E7C, 0x2C7C, 0x2A7C, 0x287C, 0x267C, 0x247C, 0x227C, 0x207C,
   6472     0x1EFC, 0x1DFC, 0x1CFC, 0x1BFC, 0x1AFC, 0x19FC, 0x18FC, 0x17FC, 0x16FC, 0x15FC, 0x14FC, 0x13FC, 0x12FC, 0x11FC, 0x10FC, 0x0FFC,
   6473     0x0F3C, 0x0EBC, 0x0E3C, 0x0DBC, 0x0D3C, 0x0CBC, 0x0C3C, 0x0BBC, 0x0B3C, 0x0ABC, 0x0A3C, 0x09BC, 0x093C, 0x08BC, 0x083C, 0x07BC,
   6474     0x075C, 0x071C, 0x06DC, 0x069C, 0x065C, 0x061C, 0x05DC, 0x059C, 0x055C, 0x051C, 0x04DC, 0x049C, 0x045C, 0x041C, 0x03DC, 0x039C,
   6475     0x036C, 0x034C, 0x032C, 0x030C, 0x02EC, 0x02CC, 0x02AC, 0x028C, 0x026C, 0x024C, 0x022C, 0x020C, 0x01EC, 0x01CC, 0x01AC, 0x018C,
   6476     0x0174, 0x0164, 0x0154, 0x0144, 0x0134, 0x0124, 0x0114, 0x0104, 0x00F4, 0x00E4, 0x00D4, 0x00C4, 0x00B4, 0x00A4, 0x0094, 0x0084,
   6477     0x0078, 0x0070, 0x0068, 0x0060, 0x0058, 0x0050, 0x0048, 0x0040, 0x0038, 0x0030, 0x0028, 0x0020, 0x0018, 0x0010, 0x0008, 0x0000
   6478 };
   6479 
   6480 static DRWAV_INLINE drwav_int16 drwav__alaw_to_s16(drwav_uint8 sampleIn)
   6481 {
   6482     return (short)g_drwavAlawTable[sampleIn];
   6483 }
   6484 
   6485 static DRWAV_INLINE drwav_int16 drwav__mulaw_to_s16(drwav_uint8 sampleIn)
   6486 {
   6487     return (short)g_drwavMulawTable[sampleIn];
   6488 }
   6489 
   6490 
   6491 
   6492 DRWAV_PRIVATE void drwav__pcm_to_s16(drwav_int16* pOut, const drwav_uint8* pIn, size_t totalSampleCount, unsigned int bytesPerSample)
   6493 {
   6494     size_t i;
   6495 
   6496     /* Special case for 8-bit sample data because it's treated as unsigned. */
   6497     if (bytesPerSample == 1) {
   6498         drwav_u8_to_s16(pOut, pIn, totalSampleCount);
   6499         return;
   6500     }
   6501 
   6502 
   6503     /* Slightly more optimal implementation for common formats. */
   6504     if (bytesPerSample == 2) {
   6505         for (i = 0; i < totalSampleCount; ++i) {
   6506            *pOut++ = ((const drwav_int16*)pIn)[i];
   6507         }
   6508         return;
   6509     }
   6510     if (bytesPerSample == 3) {
   6511         drwav_s24_to_s16(pOut, pIn, totalSampleCount);
   6512         return;
   6513     }
   6514     if (bytesPerSample == 4) {
   6515         drwav_s32_to_s16(pOut, (const drwav_int32*)pIn, totalSampleCount);
   6516         return;
   6517     }
   6518 
   6519 
   6520     /* Anything more than 64 bits per sample is not supported. */
   6521     if (bytesPerSample > 8) {
   6522         DRWAV_ZERO_MEMORY(pOut, totalSampleCount * sizeof(*pOut));
   6523         return;
   6524     }
   6525 
   6526 
   6527     /* Generic, slow converter. */
   6528     for (i = 0; i < totalSampleCount; ++i) {
   6529         drwav_uint64 sample = 0;
   6530         unsigned int shift  = (8 - bytesPerSample) * 8;
   6531 
   6532         unsigned int j;
   6533         for (j = 0; j < bytesPerSample; j += 1) {
   6534             DRWAV_ASSERT(j < 8);
   6535             sample |= (drwav_uint64)(pIn[j]) << shift;
   6536             shift  += 8;
   6537         }
   6538 
   6539         pIn += j;
   6540         *pOut++ = (drwav_int16)((drwav_int64)sample >> 48);
   6541     }
   6542 }
   6543 
   6544 DRWAV_PRIVATE void drwav__ieee_to_s16(drwav_int16* pOut, const drwav_uint8* pIn, size_t totalSampleCount, unsigned int bytesPerSample)
   6545 {
   6546     if (bytesPerSample == 4) {
   6547         drwav_f32_to_s16(pOut, (const float*)pIn, totalSampleCount);
   6548         return;
   6549     } else if (bytesPerSample == 8) {
   6550         drwav_f64_to_s16(pOut, (const double*)pIn, totalSampleCount);
   6551         return;
   6552     } else {
   6553         /* Only supporting 32- and 64-bit float. Output silence in all other cases. Contributions welcome for 16-bit float. */
   6554         DRWAV_ZERO_MEMORY(pOut, totalSampleCount * sizeof(*pOut));
   6555         return;
   6556     }
   6557 }
   6558 
   6559 DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__pcm(drwav* pWav, drwav_uint64 framesToRead, drwav_int16* pBufferOut)
   6560 {
   6561     drwav_uint64 totalFramesRead;
   6562     drwav_uint8 sampleData[4096] = {0};
   6563     drwav_uint32 bytesPerFrame;
   6564     drwav_uint32 bytesPerSample;
   6565     drwav_uint64 samplesRead;
   6566 
   6567     /* Fast path. */
   6568     if ((pWav->translatedFormatTag == DR_WAVE_FORMAT_PCM && pWav->bitsPerSample == 16) || pBufferOut == NULL) {
   6569         return drwav_read_pcm_frames(pWav, framesToRead, pBufferOut);
   6570     }
   6571 
   6572     bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
   6573     if (bytesPerFrame == 0) {
   6574         return 0;
   6575     }
   6576 
   6577     bytesPerSample = bytesPerFrame / pWav->channels;
   6578     if (bytesPerSample == 0 || (bytesPerFrame % pWav->channels) != 0) {
   6579         return 0;   /* Only byte-aligned formats are supported. */
   6580     }
   6581 
   6582     totalFramesRead = 0;
   6583 
   6584     while (framesToRead > 0) {
   6585         drwav_uint64 framesToReadThisIteration = drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame);
   6586         drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, framesToReadThisIteration, sampleData);
   6587         if (framesRead == 0) {
   6588             break;
   6589         }
   6590 
   6591         DRWAV_ASSERT(framesRead <= framesToReadThisIteration);   /* If this fails it means there's a bug in drwav_read_pcm_frames(). */
   6592 
   6593         /* Validation to ensure we don't read too much from out intermediary buffer. This is to protect from invalid files. */
   6594         samplesRead = framesRead * pWav->channels;
   6595         if ((samplesRead * bytesPerSample) > sizeof(sampleData)) {
   6596             DRWAV_ASSERT(DRWAV_FALSE);  /* This should never happen with a valid file. */
   6597             break;
   6598         }
   6599 
   6600         drwav__pcm_to_s16(pBufferOut, sampleData, (size_t)samplesRead, bytesPerSample);
   6601 
   6602         pBufferOut      += samplesRead;
   6603         framesToRead    -= framesRead;
   6604         totalFramesRead += framesRead;
   6605     }
   6606 
   6607     return totalFramesRead;
   6608 }
   6609 
   6610 DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__ieee(drwav* pWav, drwav_uint64 framesToRead, drwav_int16* pBufferOut)
   6611 {
   6612     drwav_uint64 totalFramesRead;
   6613     drwav_uint8 sampleData[4096] = {0};
   6614     drwav_uint32 bytesPerFrame;
   6615     drwav_uint32 bytesPerSample;
   6616     drwav_uint64 samplesRead;
   6617 
   6618     if (pBufferOut == NULL) {
   6619         return drwav_read_pcm_frames(pWav, framesToRead, NULL);
   6620     }
   6621 
   6622     bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
   6623     if (bytesPerFrame == 0) {
   6624         return 0;
   6625     }
   6626 
   6627     bytesPerSample = bytesPerFrame / pWav->channels;
   6628     if (bytesPerSample == 0 || (bytesPerFrame % pWav->channels) != 0) {
   6629         return 0;   /* Only byte-aligned formats are supported. */
   6630     }
   6631 
   6632     totalFramesRead = 0;
   6633 
   6634     while (framesToRead > 0) {
   6635         drwav_uint64 framesToReadThisIteration = drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame);
   6636         drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, framesToReadThisIteration, sampleData);
   6637         if (framesRead == 0) {
   6638             break;
   6639         }
   6640 
   6641         DRWAV_ASSERT(framesRead <= framesToReadThisIteration);   /* If this fails it means there's a bug in drwav_read_pcm_frames(). */
   6642 
   6643         /* Validation to ensure we don't read too much from out intermediary buffer. This is to protect from invalid files. */
   6644         samplesRead = framesRead * pWav->channels;
   6645         if ((samplesRead * bytesPerSample) > sizeof(sampleData)) {
   6646             DRWAV_ASSERT(DRWAV_FALSE);  /* This should never happen with a valid file. */
   6647             break;
   6648         }
   6649 
   6650         drwav__ieee_to_s16(pBufferOut, sampleData, (size_t)samplesRead, bytesPerSample);    /* Safe cast. */
   6651 
   6652         pBufferOut      += samplesRead;
   6653         framesToRead    -= framesRead;
   6654         totalFramesRead += framesRead;
   6655     }
   6656 
   6657     return totalFramesRead;
   6658 }
   6659 
   6660 DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__alaw(drwav* pWav, drwav_uint64 framesToRead, drwav_int16* pBufferOut)
   6661 {
   6662     drwav_uint64 totalFramesRead;
   6663     drwav_uint8 sampleData[4096] = {0};
   6664     drwav_uint32 bytesPerFrame;
   6665     drwav_uint32 bytesPerSample;
   6666     drwav_uint64 samplesRead;
   6667 
   6668     if (pBufferOut == NULL) {
   6669         return drwav_read_pcm_frames(pWav, framesToRead, NULL);
   6670     }
   6671 
   6672     bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
   6673     if (bytesPerFrame == 0) {
   6674         return 0;
   6675     }
   6676 
   6677     bytesPerSample = bytesPerFrame / pWav->channels;
   6678     if (bytesPerSample == 0 || (bytesPerFrame % pWav->channels) != 0) {
   6679         return 0;   /* Only byte-aligned formats are supported. */
   6680     }
   6681 
   6682     totalFramesRead = 0;
   6683 
   6684     while (framesToRead > 0) {
   6685         drwav_uint64 framesToReadThisIteration = drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame);
   6686         drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, framesToReadThisIteration, sampleData);
   6687         if (framesRead == 0) {
   6688             break;
   6689         }
   6690 
   6691         DRWAV_ASSERT(framesRead <= framesToReadThisIteration);   /* If this fails it means there's a bug in drwav_read_pcm_frames(). */
   6692 
   6693         /* Validation to ensure we don't read too much from out intermediary buffer. This is to protect from invalid files. */
   6694         samplesRead = framesRead * pWav->channels;
   6695         if ((samplesRead * bytesPerSample) > sizeof(sampleData)) {
   6696             DRWAV_ASSERT(DRWAV_FALSE);  /* This should never happen with a valid file. */
   6697             break;
   6698         }
   6699 
   6700         drwav_alaw_to_s16(pBufferOut, sampleData, (size_t)samplesRead);
   6701 
   6702         /*
   6703         For some reason libsndfile seems to be returning samples of the opposite sign for a-law, but only
   6704         with AIFF files. For WAV files it seems to be the same as dr_wav. This is resulting in dr_wav's
   6705         automated tests failing. I'm not sure which is correct, but will assume dr_wav. If we're enforcing
   6706         libsndfile compatibility we'll swap the signs here.
   6707         */
   6708         #ifdef DR_WAV_LIBSNDFILE_COMPAT
   6709         {
   6710             if (pWav->container == drwav_container_aiff) {
   6711                 drwav_uint64 iSample;
   6712                 for (iSample = 0; iSample < samplesRead; iSample += 1) {
   6713                     pBufferOut[iSample] = -pBufferOut[iSample];
   6714                 }
   6715             }
   6716         }
   6717         #endif
   6718 
   6719         pBufferOut      += samplesRead;
   6720         framesToRead    -= framesRead;
   6721         totalFramesRead += framesRead;
   6722     }
   6723 
   6724     return totalFramesRead;
   6725 }
   6726 
   6727 DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__mulaw(drwav* pWav, drwav_uint64 framesToRead, drwav_int16* pBufferOut)
   6728 {
   6729     drwav_uint64 totalFramesRead;
   6730     drwav_uint8 sampleData[4096] = {0};
   6731     drwav_uint32 bytesPerFrame;
   6732     drwav_uint32 bytesPerSample;
   6733     drwav_uint64 samplesRead;
   6734 
   6735     if (pBufferOut == NULL) {
   6736         return drwav_read_pcm_frames(pWav, framesToRead, NULL);
   6737     }
   6738 
   6739     bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
   6740     if (bytesPerFrame == 0) {
   6741         return 0;
   6742     }
   6743 
   6744     bytesPerSample = bytesPerFrame / pWav->channels;
   6745     if (bytesPerSample == 0 || (bytesPerFrame % pWav->channels) != 0) {
   6746         return 0;   /* Only byte-aligned formats are supported. */
   6747     }
   6748 
   6749     totalFramesRead = 0;
   6750 
   6751     while (framesToRead > 0) {
   6752         drwav_uint64 framesToReadThisIteration = drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame);
   6753         drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, framesToReadThisIteration, sampleData);
   6754         if (framesRead == 0) {
   6755             break;
   6756         }
   6757 
   6758         DRWAV_ASSERT(framesRead <= framesToReadThisIteration);   /* If this fails it means there's a bug in drwav_read_pcm_frames(). */
   6759 
   6760         /* Validation to ensure we don't read too much from out intermediary buffer. This is to protect from invalid files. */
   6761         samplesRead = framesRead * pWav->channels;
   6762         if ((samplesRead * bytesPerSample) > sizeof(sampleData)) {
   6763             DRWAV_ASSERT(DRWAV_FALSE);  /* This should never happen with a valid file. */
   6764             break;
   6765         }
   6766 
   6767         drwav_mulaw_to_s16(pBufferOut, sampleData, (size_t)samplesRead);
   6768 
   6769         /*
   6770         Just like with alaw, for some reason the signs between libsndfile and dr_wav are opposite. We just need to
   6771         swap the sign if we're compiling with libsndfile compatiblity so our automated tests don't fail.
   6772         */
   6773         #ifdef DR_WAV_LIBSNDFILE_COMPAT
   6774         {
   6775             if (pWav->container == drwav_container_aiff) {
   6776                 drwav_uint64 iSample;
   6777                 for (iSample = 0; iSample < samplesRead; iSample += 1) {
   6778                     pBufferOut[iSample] = -pBufferOut[iSample];
   6779                 }
   6780             }
   6781         }
   6782         #endif
   6783 
   6784         pBufferOut      += samplesRead;
   6785         framesToRead    -= framesRead;
   6786         totalFramesRead += framesRead;
   6787     }
   6788 
   6789     return totalFramesRead;
   6790 }
   6791 
   6792 DRWAV_API drwav_uint64 drwav_read_pcm_frames_s16(drwav* pWav, drwav_uint64 framesToRead, drwav_int16* pBufferOut)
   6793 {
   6794     if (pWav == NULL || framesToRead == 0) {
   6795         return 0;
   6796     }
   6797 
   6798     if (pBufferOut == NULL) {
   6799         return drwav_read_pcm_frames(pWav, framesToRead, NULL);
   6800     }
   6801 
   6802     /* Don't try to read more samples than can potentially fit in the output buffer. */
   6803     if (framesToRead * pWav->channels * sizeof(drwav_int16) > DRWAV_SIZE_MAX) {
   6804         framesToRead = DRWAV_SIZE_MAX / sizeof(drwav_int16) / pWav->channels;
   6805     }
   6806 
   6807     if (pWav->translatedFormatTag == DR_WAVE_FORMAT_PCM) {
   6808         return drwav_read_pcm_frames_s16__pcm(pWav, framesToRead, pBufferOut);
   6809     }
   6810 
   6811     if (pWav->translatedFormatTag == DR_WAVE_FORMAT_IEEE_FLOAT) {
   6812         return drwav_read_pcm_frames_s16__ieee(pWav, framesToRead, pBufferOut);
   6813     }
   6814 
   6815     if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ALAW) {
   6816         return drwav_read_pcm_frames_s16__alaw(pWav, framesToRead, pBufferOut);
   6817     }
   6818 
   6819     if (pWav->translatedFormatTag == DR_WAVE_FORMAT_MULAW) {
   6820         return drwav_read_pcm_frames_s16__mulaw(pWav, framesToRead, pBufferOut);
   6821     }
   6822 
   6823     if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ADPCM) {
   6824         return drwav_read_pcm_frames_s16__msadpcm(pWav, framesToRead, pBufferOut);
   6825     }
   6826 
   6827     if (pWav->translatedFormatTag == DR_WAVE_FORMAT_DVI_ADPCM) {
   6828         return drwav_read_pcm_frames_s16__ima(pWav, framesToRead, pBufferOut);
   6829     }
   6830 
   6831     return 0;
   6832 }
   6833 
   6834 DRWAV_API drwav_uint64 drwav_read_pcm_frames_s16le(drwav* pWav, drwav_uint64 framesToRead, drwav_int16* pBufferOut)
   6835 {
   6836     drwav_uint64 framesRead = drwav_read_pcm_frames_s16(pWav, framesToRead, pBufferOut);
   6837     if (pBufferOut != NULL && drwav__is_little_endian() == DRWAV_FALSE) {
   6838         drwav__bswap_samples_s16(pBufferOut, framesRead*pWav->channels);
   6839     }
   6840 
   6841     return framesRead;
   6842 }
   6843 
   6844 DRWAV_API drwav_uint64 drwav_read_pcm_frames_s16be(drwav* pWav, drwav_uint64 framesToRead, drwav_int16* pBufferOut)
   6845 {
   6846     drwav_uint64 framesRead = drwav_read_pcm_frames_s16(pWav, framesToRead, pBufferOut);
   6847     if (pBufferOut != NULL && drwav__is_little_endian() == DRWAV_TRUE) {
   6848         drwav__bswap_samples_s16(pBufferOut, framesRead*pWav->channels);
   6849     }
   6850 
   6851     return framesRead;
   6852 }
   6853 
   6854 
   6855 DRWAV_API void drwav_u8_to_s16(drwav_int16* pOut, const drwav_uint8* pIn, size_t sampleCount)
   6856 {
   6857     int r;
   6858     size_t i;
   6859     for (i = 0; i < sampleCount; ++i) {
   6860         int x = pIn[i];
   6861         r = x << 8;
   6862         r = r - 32768;
   6863         pOut[i] = (short)r;
   6864     }
   6865 }
   6866 
   6867 DRWAV_API void drwav_s24_to_s16(drwav_int16* pOut, const drwav_uint8* pIn, size_t sampleCount)
   6868 {
   6869     int r;
   6870     size_t i;
   6871     for (i = 0; i < sampleCount; ++i) {
   6872         int x = ((int)(((unsigned int)(((const drwav_uint8*)pIn)[i*3+0]) << 8) | ((unsigned int)(((const drwav_uint8*)pIn)[i*3+1]) << 16) | ((unsigned int)(((const drwav_uint8*)pIn)[i*3+2])) << 24)) >> 8;
   6873         r = x >> 8;
   6874         pOut[i] = (short)r;
   6875     }
   6876 }
   6877 
   6878 DRWAV_API void drwav_s32_to_s16(drwav_int16* pOut, const drwav_int32* pIn, size_t sampleCount)
   6879 {
   6880     int r;
   6881     size_t i;
   6882     for (i = 0; i < sampleCount; ++i) {
   6883         int x = pIn[i];
   6884         r = x >> 16;
   6885         pOut[i] = (short)r;
   6886     }
   6887 }
   6888 
   6889 DRWAV_API void drwav_f32_to_s16(drwav_int16* pOut, const float* pIn, size_t sampleCount)
   6890 {
   6891     int r;
   6892     size_t i;
   6893     for (i = 0; i < sampleCount; ++i) {
   6894         float x = pIn[i];
   6895         float c;
   6896         c = ((x < -1) ? -1 : ((x > 1) ? 1 : x));
   6897         c = c + 1;
   6898         r = (int)(c * 32767.5f);
   6899         r = r - 32768;
   6900         pOut[i] = (short)r;
   6901     }
   6902 }
   6903 
   6904 DRWAV_API void drwav_f64_to_s16(drwav_int16* pOut, const double* pIn, size_t sampleCount)
   6905 {
   6906     int r;
   6907     size_t i;
   6908     for (i = 0; i < sampleCount; ++i) {
   6909         double x = pIn[i];
   6910         double c;
   6911         c = ((x < -1) ? -1 : ((x > 1) ? 1 : x));
   6912         c = c + 1;
   6913         r = (int)(c * 32767.5);
   6914         r = r - 32768;
   6915         pOut[i] = (short)r;
   6916     }
   6917 }
   6918 
   6919 DRWAV_API void drwav_alaw_to_s16(drwav_int16* pOut, const drwav_uint8* pIn, size_t sampleCount)
   6920 {
   6921     size_t i;
   6922     for (i = 0; i < sampleCount; ++i) {
   6923         pOut[i] = drwav__alaw_to_s16(pIn[i]);
   6924     }
   6925 }
   6926 
   6927 DRWAV_API void drwav_mulaw_to_s16(drwav_int16* pOut, const drwav_uint8* pIn, size_t sampleCount)
   6928 {
   6929     size_t i;
   6930     for (i = 0; i < sampleCount; ++i) {
   6931         pOut[i] = drwav__mulaw_to_s16(pIn[i]);
   6932     }
   6933 }
   6934 
   6935 
   6936 DRWAV_PRIVATE void drwav__pcm_to_f32(float* pOut, const drwav_uint8* pIn, size_t sampleCount, unsigned int bytesPerSample)
   6937 {
   6938     unsigned int i;
   6939 
   6940     /* Special case for 8-bit sample data because it's treated as unsigned. */
   6941     if (bytesPerSample == 1) {
   6942         drwav_u8_to_f32(pOut, pIn, sampleCount);
   6943         return;
   6944     }
   6945 
   6946     /* Slightly more optimal implementation for common formats. */
   6947     if (bytesPerSample == 2) {
   6948         drwav_s16_to_f32(pOut, (const drwav_int16*)pIn, sampleCount);
   6949         return;
   6950     }
   6951     if (bytesPerSample == 3) {
   6952         drwav_s24_to_f32(pOut, pIn, sampleCount);
   6953         return;
   6954     }
   6955     if (bytesPerSample == 4) {
   6956         drwav_s32_to_f32(pOut, (const drwav_int32*)pIn, sampleCount);
   6957         return;
   6958     }
   6959 
   6960 
   6961     /* Anything more than 64 bits per sample is not supported. */
   6962     if (bytesPerSample > 8) {
   6963         DRWAV_ZERO_MEMORY(pOut, sampleCount * sizeof(*pOut));
   6964         return;
   6965     }
   6966 
   6967 
   6968     /* Generic, slow converter. */
   6969     for (i = 0; i < sampleCount; ++i) {
   6970         drwav_uint64 sample = 0;
   6971         unsigned int shift  = (8 - bytesPerSample) * 8;
   6972 
   6973         unsigned int j;
   6974         for (j = 0; j < bytesPerSample; j += 1) {
   6975             DRWAV_ASSERT(j < 8);
   6976             sample |= (drwav_uint64)(pIn[j]) << shift;
   6977             shift  += 8;
   6978         }
   6979 
   6980         pIn += j;
   6981         *pOut++ = (float)((drwav_int64)sample / 9223372036854775807.0);
   6982     }
   6983 }
   6984 
   6985 DRWAV_PRIVATE void drwav__ieee_to_f32(float* pOut, const drwav_uint8* pIn, size_t sampleCount, unsigned int bytesPerSample)
   6986 {
   6987     if (bytesPerSample == 4) {
   6988         unsigned int i;
   6989         for (i = 0; i < sampleCount; ++i) {
   6990             *pOut++ = ((const float*)pIn)[i];
   6991         }
   6992         return;
   6993     } else if (bytesPerSample == 8) {
   6994         drwav_f64_to_f32(pOut, (const double*)pIn, sampleCount);
   6995         return;
   6996     } else {
   6997         /* Only supporting 32- and 64-bit float. Output silence in all other cases. Contributions welcome for 16-bit float. */
   6998         DRWAV_ZERO_MEMORY(pOut, sampleCount * sizeof(*pOut));
   6999         return;
   7000     }
   7001 }
   7002 
   7003 
   7004 DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_f32__pcm(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut)
   7005 {
   7006     drwav_uint64 totalFramesRead;
   7007     drwav_uint8 sampleData[4096] = {0};
   7008     drwav_uint32 bytesPerFrame;
   7009     drwav_uint32 bytesPerSample;
   7010     drwav_uint64 samplesRead;
   7011 
   7012     bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
   7013     if (bytesPerFrame == 0) {
   7014         return 0;
   7015     }
   7016 
   7017     bytesPerSample = bytesPerFrame / pWav->channels;
   7018     if (bytesPerSample == 0 || (bytesPerFrame % pWav->channels) != 0) {
   7019         return 0;   /* Only byte-aligned formats are supported. */
   7020     }
   7021 
   7022     totalFramesRead = 0;
   7023 
   7024     while (framesToRead > 0) {
   7025         drwav_uint64 framesToReadThisIteration = drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame);
   7026         drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, framesToReadThisIteration, sampleData);
   7027         if (framesRead == 0) {
   7028             break;
   7029         }
   7030 
   7031         DRWAV_ASSERT(framesRead <= framesToReadThisIteration);   /* If this fails it means there's a bug in drwav_read_pcm_frames(). */
   7032 
   7033         /* Validation to ensure we don't read too much from out intermediary buffer. This is to protect from invalid files. */
   7034         samplesRead = framesRead * pWav->channels;
   7035         if ((samplesRead * bytesPerSample) > sizeof(sampleData)) {
   7036             DRWAV_ASSERT(DRWAV_FALSE);  /* This should never happen with a valid file. */
   7037             break;
   7038         }
   7039 
   7040         drwav__pcm_to_f32(pBufferOut, sampleData, (size_t)samplesRead, bytesPerSample);
   7041 
   7042         pBufferOut      += samplesRead;
   7043         framesToRead    -= framesRead;
   7044         totalFramesRead += framesRead;
   7045     }
   7046 
   7047     return totalFramesRead;
   7048 }
   7049 
   7050 DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_f32__msadpcm_ima(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut)
   7051 {
   7052     /*
   7053     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
   7054     want to duplicate that code.
   7055     */
   7056     drwav_uint64 totalFramesRead;
   7057     drwav_int16 samples16[2048];
   7058 
   7059     totalFramesRead = 0;
   7060 
   7061     while (framesToRead > 0) {
   7062         drwav_uint64 framesToReadThisIteration = drwav_min(framesToRead, drwav_countof(samples16)/pWav->channels);
   7063         drwav_uint64 framesRead = drwav_read_pcm_frames_s16(pWav, framesToReadThisIteration, samples16);
   7064         if (framesRead == 0) {
   7065             break;
   7066         }
   7067 
   7068         DRWAV_ASSERT(framesRead <= framesToReadThisIteration);   /* If this fails it means there's a bug in drwav_read_pcm_frames(). */
   7069 
   7070         drwav_s16_to_f32(pBufferOut, samples16, (size_t)(framesRead*pWav->channels));   /* <-- Safe cast because we're clamping to 2048. */
   7071 
   7072         pBufferOut      += framesRead*pWav->channels;
   7073         framesToRead    -= framesRead;
   7074         totalFramesRead += framesRead;
   7075     }
   7076 
   7077     return totalFramesRead;
   7078 }
   7079 
   7080 DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_f32__ieee(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut)
   7081 {
   7082     drwav_uint64 totalFramesRead;
   7083     drwav_uint8 sampleData[4096] = {0};
   7084     drwav_uint32 bytesPerFrame;
   7085     drwav_uint32 bytesPerSample;
   7086     drwav_uint64 samplesRead;
   7087 
   7088     /* Fast path. */
   7089     if (pWav->translatedFormatTag == DR_WAVE_FORMAT_IEEE_FLOAT && pWav->bitsPerSample == 32) {
   7090         return drwav_read_pcm_frames(pWav, framesToRead, pBufferOut);
   7091     }
   7092 
   7093     bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
   7094     if (bytesPerFrame == 0) {
   7095         return 0;
   7096     }
   7097 
   7098     bytesPerSample = bytesPerFrame / pWav->channels;
   7099     if (bytesPerSample == 0 || (bytesPerFrame % pWav->channels) != 0) {
   7100         return 0;   /* Only byte-aligned formats are supported. */
   7101     }
   7102 
   7103     totalFramesRead = 0;
   7104 
   7105     while (framesToRead > 0) {
   7106         drwav_uint64 framesToReadThisIteration = drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame);
   7107         drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, framesToReadThisIteration, sampleData);
   7108         if (framesRead == 0) {
   7109             break;
   7110         }
   7111 
   7112         DRWAV_ASSERT(framesRead <= framesToReadThisIteration);   /* If this fails it means there's a bug in drwav_read_pcm_frames(). */
   7113 
   7114         /* Validation to ensure we don't read too much from out intermediary buffer. This is to protect from invalid files. */
   7115         samplesRead = framesRead * pWav->channels;
   7116         if ((samplesRead * bytesPerSample) > sizeof(sampleData)) {
   7117             DRWAV_ASSERT(DRWAV_FALSE);  /* This should never happen with a valid file. */
   7118             break;
   7119         }
   7120 
   7121         drwav__ieee_to_f32(pBufferOut, sampleData, (size_t)samplesRead, bytesPerSample);
   7122 
   7123         pBufferOut      += samplesRead;
   7124         framesToRead    -= framesRead;
   7125         totalFramesRead += framesRead;
   7126     }
   7127 
   7128     return totalFramesRead;
   7129 }
   7130 
   7131 DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_f32__alaw(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut)
   7132 {
   7133     drwav_uint64 totalFramesRead;
   7134     drwav_uint8 sampleData[4096] = {0};
   7135     drwav_uint32 bytesPerFrame;
   7136     drwav_uint32 bytesPerSample;
   7137     drwav_uint64 samplesRead;
   7138 
   7139     bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
   7140     if (bytesPerFrame == 0) {
   7141         return 0;
   7142     }
   7143 
   7144     bytesPerSample = bytesPerFrame / pWav->channels;
   7145     if (bytesPerSample == 0 || (bytesPerFrame % pWav->channels) != 0) {
   7146         return 0;   /* Only byte-aligned formats are supported. */
   7147     }
   7148 
   7149     totalFramesRead = 0;
   7150 
   7151     while (framesToRead > 0) {
   7152         drwav_uint64 framesToReadThisIteration = drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame);
   7153         drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, framesToReadThisIteration, sampleData);
   7154         if (framesRead == 0) {
   7155             break;
   7156         }
   7157 
   7158         DRWAV_ASSERT(framesRead <= framesToReadThisIteration);   /* If this fails it means there's a bug in drwav_read_pcm_frames(). */
   7159 
   7160         /* Validation to ensure we don't read too much from out intermediary buffer. This is to protect from invalid files. */
   7161         samplesRead = framesRead * pWav->channels;
   7162         if ((samplesRead * bytesPerSample) > sizeof(sampleData)) {
   7163             DRWAV_ASSERT(DRWAV_FALSE);  /* This should never happen with a valid file. */
   7164             break;
   7165         }
   7166 
   7167         drwav_alaw_to_f32(pBufferOut, sampleData, (size_t)samplesRead);
   7168 
   7169         #ifdef DR_WAV_LIBSNDFILE_COMPAT
   7170         {
   7171             if (pWav->container == drwav_container_aiff) {
   7172                 drwav_uint64 iSample;
   7173                 for (iSample = 0; iSample < samplesRead; iSample += 1) {
   7174                     pBufferOut[iSample] = -pBufferOut[iSample];
   7175                 }
   7176             }
   7177         }
   7178         #endif
   7179 
   7180         pBufferOut      += samplesRead;
   7181         framesToRead    -= framesRead;
   7182         totalFramesRead += framesRead;
   7183     }
   7184 
   7185     return totalFramesRead;
   7186 }
   7187 
   7188 DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_f32__mulaw(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut)
   7189 {
   7190     drwav_uint64 totalFramesRead;
   7191     drwav_uint8 sampleData[4096] = {0};
   7192     drwav_uint32 bytesPerFrame;
   7193     drwav_uint32 bytesPerSample;
   7194     drwav_uint64 samplesRead;
   7195 
   7196     bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
   7197     if (bytesPerFrame == 0) {
   7198         return 0;
   7199     }
   7200 
   7201     bytesPerSample = bytesPerFrame / pWav->channels;
   7202     if (bytesPerSample == 0 || (bytesPerFrame % pWav->channels) != 0) {
   7203         return 0;   /* Only byte-aligned formats are supported. */
   7204     }
   7205 
   7206     totalFramesRead = 0;
   7207 
   7208     while (framesToRead > 0) {
   7209         drwav_uint64 framesToReadThisIteration = drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame);
   7210         drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, framesToReadThisIteration, sampleData);
   7211         if (framesRead == 0) {
   7212             break;
   7213         }
   7214 
   7215         DRWAV_ASSERT(framesRead <= framesToReadThisIteration);   /* If this fails it means there's a bug in drwav_read_pcm_frames(). */
   7216 
   7217         /* Validation to ensure we don't read too much from out intermediary buffer. This is to protect from invalid files. */
   7218         samplesRead = framesRead * pWav->channels;
   7219         if ((samplesRead * bytesPerSample) > sizeof(sampleData)) {
   7220             DRWAV_ASSERT(DRWAV_FALSE);  /* This should never happen with a valid file. */
   7221             break;
   7222         }
   7223 
   7224         drwav_mulaw_to_f32(pBufferOut, sampleData, (size_t)samplesRead);
   7225 
   7226         #ifdef DR_WAV_LIBSNDFILE_COMPAT
   7227         {
   7228             if (pWav->container == drwav_container_aiff) {
   7229                 drwav_uint64 iSample;
   7230                 for (iSample = 0; iSample < samplesRead; iSample += 1) {
   7231                     pBufferOut[iSample] = -pBufferOut[iSample];
   7232                 }
   7233             }
   7234         }
   7235         #endif
   7236 
   7237         pBufferOut      += samplesRead;
   7238         framesToRead    -= framesRead;
   7239         totalFramesRead += framesRead;
   7240     }
   7241 
   7242     return totalFramesRead;
   7243 }
   7244 
   7245 DRWAV_API drwav_uint64 drwav_read_pcm_frames_f32(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut)
   7246 {
   7247     if (pWav == NULL || framesToRead == 0) {
   7248         return 0;
   7249     }
   7250 
   7251     if (pBufferOut == NULL) {
   7252         return drwav_read_pcm_frames(pWav, framesToRead, NULL);
   7253     }
   7254 
   7255     /* Don't try to read more samples than can potentially fit in the output buffer. */
   7256     if (framesToRead * pWav->channels * sizeof(float) > DRWAV_SIZE_MAX) {
   7257         framesToRead = DRWAV_SIZE_MAX / sizeof(float) / pWav->channels;
   7258     }
   7259 
   7260     if (pWav->translatedFormatTag == DR_WAVE_FORMAT_PCM) {
   7261         return drwav_read_pcm_frames_f32__pcm(pWav, framesToRead, pBufferOut);
   7262     }
   7263 
   7264     if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ADPCM || pWav->translatedFormatTag == DR_WAVE_FORMAT_DVI_ADPCM) {
   7265         return drwav_read_pcm_frames_f32__msadpcm_ima(pWav, framesToRead, pBufferOut);
   7266     }
   7267 
   7268     if (pWav->translatedFormatTag == DR_WAVE_FORMAT_IEEE_FLOAT) {
   7269         return drwav_read_pcm_frames_f32__ieee(pWav, framesToRead, pBufferOut);
   7270     }
   7271 
   7272     if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ALAW) {
   7273         return drwav_read_pcm_frames_f32__alaw(pWav, framesToRead, pBufferOut);
   7274     }
   7275 
   7276     if (pWav->translatedFormatTag == DR_WAVE_FORMAT_MULAW) {
   7277         return drwav_read_pcm_frames_f32__mulaw(pWav, framesToRead, pBufferOut);
   7278     }
   7279 
   7280     return 0;
   7281 }
   7282 
   7283 DRWAV_API drwav_uint64 drwav_read_pcm_frames_f32le(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut)
   7284 {
   7285     drwav_uint64 framesRead = drwav_read_pcm_frames_f32(pWav, framesToRead, pBufferOut);
   7286     if (pBufferOut != NULL && drwav__is_little_endian() == DRWAV_FALSE) {
   7287         drwav__bswap_samples_f32(pBufferOut, framesRead*pWav->channels);
   7288     }
   7289 
   7290     return framesRead;
   7291 }
   7292 
   7293 DRWAV_API drwav_uint64 drwav_read_pcm_frames_f32be(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut)
   7294 {
   7295     drwav_uint64 framesRead = drwav_read_pcm_frames_f32(pWav, framesToRead, pBufferOut);
   7296     if (pBufferOut != NULL && drwav__is_little_endian() == DRWAV_TRUE) {
   7297         drwav__bswap_samples_f32(pBufferOut, framesRead*pWav->channels);
   7298     }
   7299 
   7300     return framesRead;
   7301 }
   7302 
   7303 
   7304 DRWAV_API void drwav_u8_to_f32(float* pOut, const drwav_uint8* pIn, size_t sampleCount)
   7305 {
   7306     size_t i;
   7307 
   7308     if (pOut == NULL || pIn == NULL) {
   7309         return;
   7310     }
   7311 
   7312 #ifdef DR_WAV_LIBSNDFILE_COMPAT
   7313     /*
   7314     It appears libsndfile uses slightly different logic for the u8 -> f32 conversion to dr_wav, which in my opinion is incorrect. It appears
   7315     libsndfile performs the conversion something like "f32 = (u8 / 256) * 2 - 1", however I think it should be "f32 = (u8 / 255) * 2 - 1" (note
   7316     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
   7317     correctness testing. This is disabled by default.
   7318     */
   7319     for (i = 0; i < sampleCount; ++i) {
   7320         *pOut++ = (pIn[i] / 256.0f) * 2 - 1;
   7321     }
   7322 #else
   7323     for (i = 0; i < sampleCount; ++i) {
   7324         float x = pIn[i];
   7325         x = x * 0.00784313725490196078f;    /* 0..255 to 0..2 */
   7326         x = x - 1;                          /* 0..2 to -1..1 */
   7327 
   7328         *pOut++ = x;
   7329     }
   7330 #endif
   7331 }
   7332 
   7333 DRWAV_API void drwav_s16_to_f32(float* pOut, const drwav_int16* pIn, size_t sampleCount)
   7334 {
   7335     size_t i;
   7336 
   7337     if (pOut == NULL || pIn == NULL) {
   7338         return;
   7339     }
   7340 
   7341     for (i = 0; i < sampleCount; ++i) {
   7342         *pOut++ = pIn[i] * 0.000030517578125f;
   7343     }
   7344 }
   7345 
   7346 DRWAV_API void drwav_s24_to_f32(float* pOut, const drwav_uint8* pIn, size_t sampleCount)
   7347 {
   7348     size_t i;
   7349 
   7350     if (pOut == NULL || pIn == NULL) {
   7351         return;
   7352     }
   7353 
   7354     for (i = 0; i < sampleCount; ++i) {
   7355         double x;
   7356         drwav_uint32 a = ((drwav_uint32)(pIn[i*3+0]) <<  8);
   7357         drwav_uint32 b = ((drwav_uint32)(pIn[i*3+1]) << 16);
   7358         drwav_uint32 c = ((drwav_uint32)(pIn[i*3+2]) << 24);
   7359 
   7360         x = (double)((drwav_int32)(a | b | c) >> 8);
   7361         *pOut++ = (float)(x * 0.00000011920928955078125);
   7362     }
   7363 }
   7364 
   7365 DRWAV_API void drwav_s32_to_f32(float* pOut, const drwav_int32* pIn, size_t sampleCount)
   7366 {
   7367     size_t i;
   7368     if (pOut == NULL || pIn == NULL) {
   7369         return;
   7370     }
   7371 
   7372     for (i = 0; i < sampleCount; ++i) {
   7373         *pOut++ = (float)(pIn[i] / 2147483648.0);
   7374     }
   7375 }
   7376 
   7377 DRWAV_API void drwav_f64_to_f32(float* pOut, const double* pIn, size_t sampleCount)
   7378 {
   7379     size_t i;
   7380 
   7381     if (pOut == NULL || pIn == NULL) {
   7382         return;
   7383     }
   7384 
   7385     for (i = 0; i < sampleCount; ++i) {
   7386         *pOut++ = (float)pIn[i];
   7387     }
   7388 }
   7389 
   7390 DRWAV_API void drwav_alaw_to_f32(float* pOut, const drwav_uint8* pIn, size_t sampleCount)
   7391 {
   7392     size_t i;
   7393 
   7394     if (pOut == NULL || pIn == NULL) {
   7395         return;
   7396     }
   7397 
   7398     for (i = 0; i < sampleCount; ++i) {
   7399         *pOut++ = drwav__alaw_to_s16(pIn[i]) / 32768.0f;
   7400     }
   7401 }
   7402 
   7403 DRWAV_API void drwav_mulaw_to_f32(float* pOut, const drwav_uint8* pIn, size_t sampleCount)
   7404 {
   7405     size_t i;
   7406 
   7407     if (pOut == NULL || pIn == NULL) {
   7408         return;
   7409     }
   7410 
   7411     for (i = 0; i < sampleCount; ++i) {
   7412         *pOut++ = drwav__mulaw_to_s16(pIn[i]) / 32768.0f;
   7413     }
   7414 }
   7415 
   7416 
   7417 
   7418 DRWAV_PRIVATE void drwav__pcm_to_s32(drwav_int32* pOut, const drwav_uint8* pIn, size_t totalSampleCount, unsigned int bytesPerSample)
   7419 {
   7420     unsigned int i;
   7421 
   7422     /* Special case for 8-bit sample data because it's treated as unsigned. */
   7423     if (bytesPerSample == 1) {
   7424         drwav_u8_to_s32(pOut, pIn, totalSampleCount);
   7425         return;
   7426     }
   7427 
   7428     /* Slightly more optimal implementation for common formats. */
   7429     if (bytesPerSample == 2) {
   7430         drwav_s16_to_s32(pOut, (const drwav_int16*)pIn, totalSampleCount);
   7431         return;
   7432     }
   7433     if (bytesPerSample == 3) {
   7434         drwav_s24_to_s32(pOut, pIn, totalSampleCount);
   7435         return;
   7436     }
   7437     if (bytesPerSample == 4) {
   7438         for (i = 0; i < totalSampleCount; ++i) {
   7439            *pOut++ = ((const drwav_int32*)pIn)[i];
   7440         }
   7441         return;
   7442     }
   7443 
   7444 
   7445     /* Anything more than 64 bits per sample is not supported. */
   7446     if (bytesPerSample > 8) {
   7447         DRWAV_ZERO_MEMORY(pOut, totalSampleCount * sizeof(*pOut));
   7448         return;
   7449     }
   7450 
   7451 
   7452     /* Generic, slow converter. */
   7453     for (i = 0; i < totalSampleCount; ++i) {
   7454         drwav_uint64 sample = 0;
   7455         unsigned int shift  = (8 - bytesPerSample) * 8;
   7456 
   7457         unsigned int j;
   7458         for (j = 0; j < bytesPerSample; j += 1) {
   7459             DRWAV_ASSERT(j < 8);
   7460             sample |= (drwav_uint64)(pIn[j]) << shift;
   7461             shift  += 8;
   7462         }
   7463 
   7464         pIn += j;
   7465         *pOut++ = (drwav_int32)((drwav_int64)sample >> 32);
   7466     }
   7467 }
   7468 
   7469 DRWAV_PRIVATE void drwav__ieee_to_s32(drwav_int32* pOut, const drwav_uint8* pIn, size_t totalSampleCount, unsigned int bytesPerSample)
   7470 {
   7471     if (bytesPerSample == 4) {
   7472         drwav_f32_to_s32(pOut, (const float*)pIn, totalSampleCount);
   7473         return;
   7474     } else if (bytesPerSample == 8) {
   7475         drwav_f64_to_s32(pOut, (const double*)pIn, totalSampleCount);
   7476         return;
   7477     } else {
   7478         /* Only supporting 32- and 64-bit float. Output silence in all other cases. Contributions welcome for 16-bit float. */
   7479         DRWAV_ZERO_MEMORY(pOut, totalSampleCount * sizeof(*pOut));
   7480         return;
   7481     }
   7482 }
   7483 
   7484 
   7485 DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s32__pcm(drwav* pWav, drwav_uint64 framesToRead, drwav_int32* pBufferOut)
   7486 {
   7487     drwav_uint64 totalFramesRead;
   7488     drwav_uint8 sampleData[4096] = {0};
   7489     drwav_uint32 bytesPerFrame;
   7490     drwav_uint32 bytesPerSample;
   7491     drwav_uint64 samplesRead;
   7492 
   7493     /* Fast path. */
   7494     if (pWav->translatedFormatTag == DR_WAVE_FORMAT_PCM && pWav->bitsPerSample == 32) {
   7495         return drwav_read_pcm_frames(pWav, framesToRead, pBufferOut);
   7496     }
   7497 
   7498     bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
   7499     if (bytesPerFrame == 0) {
   7500         return 0;
   7501     }
   7502 
   7503     bytesPerSample = bytesPerFrame / pWav->channels;
   7504     if (bytesPerSample == 0 || (bytesPerFrame % pWav->channels) != 0) {
   7505         return 0;   /* Only byte-aligned formats are supported. */
   7506     }
   7507 
   7508     totalFramesRead = 0;
   7509 
   7510     while (framesToRead > 0) {
   7511         drwav_uint64 framesToReadThisIteration = drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame);
   7512         drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, framesToReadThisIteration, sampleData);
   7513         if (framesRead == 0) {
   7514             break;
   7515         }
   7516 
   7517         DRWAV_ASSERT(framesRead <= framesToReadThisIteration);   /* If this fails it means there's a bug in drwav_read_pcm_frames(). */
   7518 
   7519         /* Validation to ensure we don't read too much from out intermediary buffer. This is to protect from invalid files. */
   7520         samplesRead = framesRead * pWav->channels;
   7521         if ((samplesRead * bytesPerSample) > sizeof(sampleData)) {
   7522             DRWAV_ASSERT(DRWAV_FALSE);  /* This should never happen with a valid file. */
   7523             break;
   7524         }
   7525 
   7526         drwav__pcm_to_s32(pBufferOut, sampleData, (size_t)samplesRead, bytesPerSample);
   7527 
   7528         pBufferOut      += samplesRead;
   7529         framesToRead    -= framesRead;
   7530         totalFramesRead += framesRead;
   7531     }
   7532 
   7533     return totalFramesRead;
   7534 }
   7535 
   7536 DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s32__msadpcm_ima(drwav* pWav, drwav_uint64 framesToRead, drwav_int32* pBufferOut)
   7537 {
   7538     /*
   7539     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
   7540     want to duplicate that code.
   7541     */
   7542     drwav_uint64 totalFramesRead = 0;
   7543     drwav_int16 samples16[2048];
   7544 
   7545     while (framesToRead > 0) {
   7546         drwav_uint64 framesToReadThisIteration = drwav_min(framesToRead, drwav_countof(samples16)/pWav->channels);
   7547         drwav_uint64 framesRead = drwav_read_pcm_frames_s16(pWav, framesToReadThisIteration, samples16);
   7548         if (framesRead == 0) {
   7549             break;
   7550         }
   7551 
   7552         DRWAV_ASSERT(framesRead <= framesToReadThisIteration);   /* If this fails it means there's a bug in drwav_read_pcm_frames(). */
   7553 
   7554         drwav_s16_to_s32(pBufferOut, samples16, (size_t)(framesRead*pWav->channels));   /* <-- Safe cast because we're clamping to 2048. */
   7555 
   7556         pBufferOut      += framesRead*pWav->channels;
   7557         framesToRead    -= framesRead;
   7558         totalFramesRead += framesRead;
   7559     }
   7560 
   7561     return totalFramesRead;
   7562 }
   7563 
   7564 DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s32__ieee(drwav* pWav, drwav_uint64 framesToRead, drwav_int32* pBufferOut)
   7565 {
   7566     drwav_uint64 totalFramesRead;
   7567     drwav_uint8 sampleData[4096] = {0};
   7568     drwav_uint32 bytesPerFrame;
   7569     drwav_uint32 bytesPerSample;
   7570     drwav_uint64 samplesRead;
   7571 
   7572     bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
   7573     if (bytesPerFrame == 0) {
   7574         return 0;
   7575     }
   7576 
   7577     bytesPerSample = bytesPerFrame / pWav->channels;
   7578     if (bytesPerSample == 0 || (bytesPerFrame % pWav->channels) != 0) {
   7579         return 0;   /* Only byte-aligned formats are supported. */
   7580     }
   7581 
   7582     totalFramesRead = 0;
   7583 
   7584     while (framesToRead > 0) {
   7585         drwav_uint64 framesToReadThisIteration = drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame);
   7586         drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, framesToReadThisIteration, sampleData);
   7587         if (framesRead == 0) {
   7588             break;
   7589         }
   7590 
   7591         DRWAV_ASSERT(framesRead <= framesToReadThisIteration);   /* If this fails it means there's a bug in drwav_read_pcm_frames(). */
   7592 
   7593         /* Validation to ensure we don't read too much from out intermediary buffer. This is to protect from invalid files. */
   7594         samplesRead = framesRead * pWav->channels;
   7595         if ((samplesRead * bytesPerSample) > sizeof(sampleData)) {
   7596             DRWAV_ASSERT(DRWAV_FALSE);  /* This should never happen with a valid file. */
   7597             break;
   7598         }
   7599 
   7600         drwav__ieee_to_s32(pBufferOut, sampleData, (size_t)samplesRead, bytesPerSample);
   7601 
   7602         pBufferOut      += samplesRead;
   7603         framesToRead    -= framesRead;
   7604         totalFramesRead += framesRead;
   7605     }
   7606 
   7607     return totalFramesRead;
   7608 }
   7609 
   7610 DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s32__alaw(drwav* pWav, drwav_uint64 framesToRead, drwav_int32* pBufferOut)
   7611 {
   7612     drwav_uint64 totalFramesRead;
   7613     drwav_uint8 sampleData[4096] = {0};
   7614     drwav_uint32 bytesPerFrame;
   7615     drwav_uint32 bytesPerSample;
   7616     drwav_uint64 samplesRead;
   7617 
   7618     bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
   7619     if (bytesPerFrame == 0) {
   7620         return 0;
   7621     }
   7622 
   7623     bytesPerSample = bytesPerFrame / pWav->channels;
   7624     if (bytesPerSample == 0 || (bytesPerFrame % pWav->channels) != 0) {
   7625         return 0;   /* Only byte-aligned formats are supported. */
   7626     }
   7627 
   7628     totalFramesRead = 0;
   7629 
   7630     while (framesToRead > 0) {
   7631         drwav_uint64 framesToReadThisIteration = drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame);
   7632         drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, framesToReadThisIteration, sampleData);
   7633         if (framesRead == 0) {
   7634             break;
   7635         }
   7636 
   7637         DRWAV_ASSERT(framesRead <= framesToReadThisIteration);   /* If this fails it means there's a bug in drwav_read_pcm_frames(). */
   7638 
   7639         /* Validation to ensure we don't read too much from out intermediary buffer. This is to protect from invalid files. */
   7640         samplesRead = framesRead * pWav->channels;
   7641         if ((samplesRead * bytesPerSample) > sizeof(sampleData)) {
   7642             DRWAV_ASSERT(DRWAV_FALSE);  /* This should never happen with a valid file. */
   7643             break;
   7644         }
   7645 
   7646         drwav_alaw_to_s32(pBufferOut, sampleData, (size_t)samplesRead);
   7647 
   7648         #ifdef DR_WAV_LIBSNDFILE_COMPAT
   7649         {
   7650             if (pWav->container == drwav_container_aiff) {
   7651                 drwav_uint64 iSample;
   7652                 for (iSample = 0; iSample < samplesRead; iSample += 1) {
   7653                     pBufferOut[iSample] = -pBufferOut[iSample];
   7654                 }
   7655             }
   7656         }
   7657         #endif
   7658 
   7659         pBufferOut      += samplesRead;
   7660         framesToRead    -= framesRead;
   7661         totalFramesRead += framesRead;
   7662     }
   7663 
   7664     return totalFramesRead;
   7665 }
   7666 
   7667 DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s32__mulaw(drwav* pWav, drwav_uint64 framesToRead, drwav_int32* pBufferOut)
   7668 {
   7669     drwav_uint64 totalFramesRead;
   7670     drwav_uint8 sampleData[4096] = {0};
   7671     drwav_uint32 bytesPerFrame;
   7672     drwav_uint32 bytesPerSample;
   7673     drwav_uint64 samplesRead;
   7674 
   7675     bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
   7676     if (bytesPerFrame == 0) {
   7677         return 0;
   7678     }
   7679 
   7680     bytesPerSample = bytesPerFrame / pWav->channels;
   7681     if (bytesPerSample == 0 || (bytesPerFrame % pWav->channels) != 0) {
   7682         return 0;   /* Only byte-aligned formats are supported. */
   7683     }
   7684 
   7685     totalFramesRead = 0;
   7686 
   7687     while (framesToRead > 0) {
   7688         drwav_uint64 framesToReadThisIteration = drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame);
   7689         drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, framesToReadThisIteration, sampleData);
   7690         if (framesRead == 0) {
   7691             break;
   7692         }
   7693 
   7694         DRWAV_ASSERT(framesRead <= framesToReadThisIteration);   /* If this fails it means there's a bug in drwav_read_pcm_frames(). */
   7695 
   7696         /* Validation to ensure we don't read too much from out intermediary buffer. This is to protect from invalid files. */
   7697         samplesRead = framesRead * pWav->channels;
   7698         if ((samplesRead * bytesPerSample) > sizeof(sampleData)) {
   7699             DRWAV_ASSERT(DRWAV_FALSE);  /* This should never happen with a valid file. */
   7700             break;
   7701         }
   7702 
   7703         drwav_mulaw_to_s32(pBufferOut, sampleData, (size_t)samplesRead);
   7704 
   7705         #ifdef DR_WAV_LIBSNDFILE_COMPAT
   7706         {
   7707             if (pWav->container == drwav_container_aiff) {
   7708                 drwav_uint64 iSample;
   7709                 for (iSample = 0; iSample < samplesRead; iSample += 1) {
   7710                     pBufferOut[iSample] = -pBufferOut[iSample];
   7711                 }
   7712             }
   7713         }
   7714         #endif
   7715 
   7716         pBufferOut      += samplesRead;
   7717         framesToRead    -= framesRead;
   7718         totalFramesRead += framesRead;
   7719     }
   7720 
   7721     return totalFramesRead;
   7722 }
   7723 
   7724 DRWAV_API drwav_uint64 drwav_read_pcm_frames_s32(drwav* pWav, drwav_uint64 framesToRead, drwav_int32* pBufferOut)
   7725 {
   7726     if (pWav == NULL || framesToRead == 0) {
   7727         return 0;
   7728     }
   7729 
   7730     if (pBufferOut == NULL) {
   7731         return drwav_read_pcm_frames(pWav, framesToRead, NULL);
   7732     }
   7733 
   7734     /* Don't try to read more samples than can potentially fit in the output buffer. */
   7735     if (framesToRead * pWav->channels * sizeof(drwav_int32) > DRWAV_SIZE_MAX) {
   7736         framesToRead = DRWAV_SIZE_MAX / sizeof(drwav_int32) / pWav->channels;
   7737     }
   7738 
   7739     if (pWav->translatedFormatTag == DR_WAVE_FORMAT_PCM) {
   7740         return drwav_read_pcm_frames_s32__pcm(pWav, framesToRead, pBufferOut);
   7741     }
   7742 
   7743     if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ADPCM || pWav->translatedFormatTag == DR_WAVE_FORMAT_DVI_ADPCM) {
   7744         return drwav_read_pcm_frames_s32__msadpcm_ima(pWav, framesToRead, pBufferOut);
   7745     }
   7746 
   7747     if (pWav->translatedFormatTag == DR_WAVE_FORMAT_IEEE_FLOAT) {
   7748         return drwav_read_pcm_frames_s32__ieee(pWav, framesToRead, pBufferOut);
   7749     }
   7750 
   7751     if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ALAW) {
   7752         return drwav_read_pcm_frames_s32__alaw(pWav, framesToRead, pBufferOut);
   7753     }
   7754 
   7755     if (pWav->translatedFormatTag == DR_WAVE_FORMAT_MULAW) {
   7756         return drwav_read_pcm_frames_s32__mulaw(pWav, framesToRead, pBufferOut);
   7757     }
   7758 
   7759     return 0;
   7760 }
   7761 
   7762 DRWAV_API drwav_uint64 drwav_read_pcm_frames_s32le(drwav* pWav, drwav_uint64 framesToRead, drwav_int32* pBufferOut)
   7763 {
   7764     drwav_uint64 framesRead = drwav_read_pcm_frames_s32(pWav, framesToRead, pBufferOut);
   7765     if (pBufferOut != NULL && drwav__is_little_endian() == DRWAV_FALSE) {
   7766         drwav__bswap_samples_s32(pBufferOut, framesRead*pWav->channels);
   7767     }
   7768 
   7769     return framesRead;
   7770 }
   7771 
   7772 DRWAV_API drwav_uint64 drwav_read_pcm_frames_s32be(drwav* pWav, drwav_uint64 framesToRead, drwav_int32* pBufferOut)
   7773 {
   7774     drwav_uint64 framesRead = drwav_read_pcm_frames_s32(pWav, framesToRead, pBufferOut);
   7775     if (pBufferOut != NULL && drwav__is_little_endian() == DRWAV_TRUE) {
   7776         drwav__bswap_samples_s32(pBufferOut, framesRead*pWav->channels);
   7777     }
   7778 
   7779     return framesRead;
   7780 }
   7781 
   7782 
   7783 DRWAV_API void drwav_u8_to_s32(drwav_int32* pOut, const drwav_uint8* pIn, size_t sampleCount)
   7784 {
   7785     size_t i;
   7786 
   7787     if (pOut == NULL || pIn == NULL) {
   7788         return;
   7789     }
   7790 
   7791     for (i = 0; i < sampleCount; ++i) {
   7792         *pOut++ = ((int)pIn[i] - 128) << 24;
   7793     }
   7794 }
   7795 
   7796 DRWAV_API void drwav_s16_to_s32(drwav_int32* pOut, const drwav_int16* pIn, size_t sampleCount)
   7797 {
   7798     size_t i;
   7799 
   7800     if (pOut == NULL || pIn == NULL) {
   7801         return;
   7802     }
   7803 
   7804     for (i = 0; i < sampleCount; ++i) {
   7805         *pOut++ = pIn[i] << 16;
   7806     }
   7807 }
   7808 
   7809 DRWAV_API void drwav_s24_to_s32(drwav_int32* pOut, const drwav_uint8* pIn, size_t sampleCount)
   7810 {
   7811     size_t i;
   7812 
   7813     if (pOut == NULL || pIn == NULL) {
   7814         return;
   7815     }
   7816 
   7817     for (i = 0; i < sampleCount; ++i) {
   7818         unsigned int s0 = pIn[i*3 + 0];
   7819         unsigned int s1 = pIn[i*3 + 1];
   7820         unsigned int s2 = pIn[i*3 + 2];
   7821 
   7822         drwav_int32 sample32 = (drwav_int32)((s0 << 8) | (s1 << 16) | (s2 << 24));
   7823         *pOut++ = sample32;
   7824     }
   7825 }
   7826 
   7827 DRWAV_API void drwav_f32_to_s32(drwav_int32* pOut, const float* pIn, size_t sampleCount)
   7828 {
   7829     size_t i;
   7830 
   7831     if (pOut == NULL || pIn == NULL) {
   7832         return;
   7833     }
   7834 
   7835     for (i = 0; i < sampleCount; ++i) {
   7836         *pOut++ = (drwav_int32)(2147483648.0f * pIn[i]);
   7837     }
   7838 }
   7839 
   7840 DRWAV_API void drwav_f64_to_s32(drwav_int32* pOut, const double* pIn, size_t sampleCount)
   7841 {
   7842     size_t i;
   7843 
   7844     if (pOut == NULL || pIn == NULL) {
   7845         return;
   7846     }
   7847 
   7848     for (i = 0; i < sampleCount; ++i) {
   7849         *pOut++ = (drwav_int32)(2147483648.0 * pIn[i]);
   7850     }
   7851 }
   7852 
   7853 DRWAV_API void drwav_alaw_to_s32(drwav_int32* pOut, const drwav_uint8* pIn, size_t sampleCount)
   7854 {
   7855     size_t i;
   7856 
   7857     if (pOut == NULL || pIn == NULL) {
   7858         return;
   7859     }
   7860 
   7861     for (i = 0; i < sampleCount; ++i) {
   7862         *pOut++ = ((drwav_int32)drwav__alaw_to_s16(pIn[i])) << 16;
   7863     }
   7864 }
   7865 
   7866 DRWAV_API void drwav_mulaw_to_s32(drwav_int32* pOut, const drwav_uint8* pIn, size_t sampleCount)
   7867 {
   7868     size_t i;
   7869 
   7870     if (pOut == NULL || pIn == NULL) {
   7871         return;
   7872     }
   7873 
   7874     for (i= 0; i < sampleCount; ++i) {
   7875         *pOut++ = ((drwav_int32)drwav__mulaw_to_s16(pIn[i])) << 16;
   7876     }
   7877 }
   7878 
   7879 
   7880 
   7881 DRWAV_PRIVATE drwav_int16* drwav__read_pcm_frames_and_close_s16(drwav* pWav, unsigned int* channels, unsigned int* sampleRate, drwav_uint64* totalFrameCount)
   7882 {
   7883     drwav_uint64 sampleDataSize;
   7884     drwav_int16* pSampleData;
   7885     drwav_uint64 framesRead;
   7886 
   7887     DRWAV_ASSERT(pWav != NULL);
   7888 
   7889     sampleDataSize = pWav->totalPCMFrameCount * pWav->channels * sizeof(drwav_int16);
   7890     if (sampleDataSize > DRWAV_SIZE_MAX) {
   7891         drwav_uninit(pWav);
   7892         return NULL;    /* File's too big. */
   7893     }
   7894 
   7895     pSampleData = (drwav_int16*)drwav__malloc_from_callbacks((size_t)sampleDataSize, &pWav->allocationCallbacks); /* <-- Safe cast due to the check above. */
   7896     if (pSampleData == NULL) {
   7897         drwav_uninit(pWav);
   7898         return NULL;    /* Failed to allocate memory. */
   7899     }
   7900 
   7901     framesRead = drwav_read_pcm_frames_s16(pWav, (size_t)pWav->totalPCMFrameCount, pSampleData);
   7902     if (framesRead != pWav->totalPCMFrameCount) {
   7903         drwav__free_from_callbacks(pSampleData, &pWav->allocationCallbacks);
   7904         drwav_uninit(pWav);
   7905         return NULL;    /* There was an error reading the samples. */
   7906     }
   7907 
   7908     drwav_uninit(pWav);
   7909 
   7910     if (sampleRate) {
   7911         *sampleRate = pWav->sampleRate;
   7912     }
   7913     if (channels) {
   7914         *channels = pWav->channels;
   7915     }
   7916     if (totalFrameCount) {
   7917         *totalFrameCount = pWav->totalPCMFrameCount;
   7918     }
   7919 
   7920     return pSampleData;
   7921 }
   7922 
   7923 DRWAV_PRIVATE float* drwav__read_pcm_frames_and_close_f32(drwav* pWav, unsigned int* channels, unsigned int* sampleRate, drwav_uint64* totalFrameCount)
   7924 {
   7925     drwav_uint64 sampleDataSize;
   7926     float* pSampleData;
   7927     drwav_uint64 framesRead;
   7928 
   7929     DRWAV_ASSERT(pWav != NULL);
   7930 
   7931     sampleDataSize = pWav->totalPCMFrameCount * pWav->channels * sizeof(float);
   7932     if (sampleDataSize > DRWAV_SIZE_MAX) {
   7933         drwav_uninit(pWav);
   7934         return NULL;    /* File's too big. */
   7935     }
   7936 
   7937     pSampleData = (float*)drwav__malloc_from_callbacks((size_t)sampleDataSize, &pWav->allocationCallbacks); /* <-- Safe cast due to the check above. */
   7938     if (pSampleData == NULL) {
   7939         drwav_uninit(pWav);
   7940         return NULL;    /* Failed to allocate memory. */
   7941     }
   7942 
   7943     framesRead = drwav_read_pcm_frames_f32(pWav, (size_t)pWav->totalPCMFrameCount, pSampleData);
   7944     if (framesRead != pWav->totalPCMFrameCount) {
   7945         drwav__free_from_callbacks(pSampleData, &pWav->allocationCallbacks);
   7946         drwav_uninit(pWav);
   7947         return NULL;    /* There was an error reading the samples. */
   7948     }
   7949 
   7950     drwav_uninit(pWav);
   7951 
   7952     if (sampleRate) {
   7953         *sampleRate = pWav->sampleRate;
   7954     }
   7955     if (channels) {
   7956         *channels = pWav->channels;
   7957     }
   7958     if (totalFrameCount) {
   7959         *totalFrameCount = pWav->totalPCMFrameCount;
   7960     }
   7961 
   7962     return pSampleData;
   7963 }
   7964 
   7965 DRWAV_PRIVATE drwav_int32* drwav__read_pcm_frames_and_close_s32(drwav* pWav, unsigned int* channels, unsigned int* sampleRate, drwav_uint64* totalFrameCount)
   7966 {
   7967     drwav_uint64 sampleDataSize;
   7968     drwav_int32* pSampleData;
   7969     drwav_uint64 framesRead;
   7970 
   7971     DRWAV_ASSERT(pWav != NULL);
   7972 
   7973     sampleDataSize = pWav->totalPCMFrameCount * pWav->channels * sizeof(drwav_int32);
   7974     if (sampleDataSize > DRWAV_SIZE_MAX) {
   7975         drwav_uninit(pWav);
   7976         return NULL;    /* File's too big. */
   7977     }
   7978 
   7979     pSampleData = (drwav_int32*)drwav__malloc_from_callbacks((size_t)sampleDataSize, &pWav->allocationCallbacks); /* <-- Safe cast due to the check above. */
   7980     if (pSampleData == NULL) {
   7981         drwav_uninit(pWav);
   7982         return NULL;    /* Failed to allocate memory. */
   7983     }
   7984 
   7985     framesRead = drwav_read_pcm_frames_s32(pWav, (size_t)pWav->totalPCMFrameCount, pSampleData);
   7986     if (framesRead != pWav->totalPCMFrameCount) {
   7987         drwav__free_from_callbacks(pSampleData, &pWav->allocationCallbacks);
   7988         drwav_uninit(pWav);
   7989         return NULL;    /* There was an error reading the samples. */
   7990     }
   7991 
   7992     drwav_uninit(pWav);
   7993 
   7994     if (sampleRate) {
   7995         *sampleRate = pWav->sampleRate;
   7996     }
   7997     if (channels) {
   7998         *channels = pWav->channels;
   7999     }
   8000     if (totalFrameCount) {
   8001         *totalFrameCount = pWav->totalPCMFrameCount;
   8002     }
   8003 
   8004     return pSampleData;
   8005 }
   8006 
   8007 
   8008 
   8009 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)
   8010 {
   8011     drwav wav;
   8012 
   8013     if (channelsOut) {
   8014         *channelsOut = 0;
   8015     }
   8016     if (sampleRateOut) {
   8017         *sampleRateOut = 0;
   8018     }
   8019     if (totalFrameCountOut) {
   8020         *totalFrameCountOut = 0;
   8021     }
   8022 
   8023     if (!drwav_init(&wav, onRead, onSeek, pUserData, pAllocationCallbacks)) {
   8024         return NULL;
   8025     }
   8026 
   8027     return drwav__read_pcm_frames_and_close_s16(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
   8028 }
   8029 
   8030 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)
   8031 {
   8032     drwav wav;
   8033 
   8034     if (channelsOut) {
   8035         *channelsOut = 0;
   8036     }
   8037     if (sampleRateOut) {
   8038         *sampleRateOut = 0;
   8039     }
   8040     if (totalFrameCountOut) {
   8041         *totalFrameCountOut = 0;
   8042     }
   8043 
   8044     if (!drwav_init(&wav, onRead, onSeek, pUserData, pAllocationCallbacks)) {
   8045         return NULL;
   8046     }
   8047 
   8048     return drwav__read_pcm_frames_and_close_f32(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
   8049 }
   8050 
   8051 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)
   8052 {
   8053     drwav wav;
   8054 
   8055     if (channelsOut) {
   8056         *channelsOut = 0;
   8057     }
   8058     if (sampleRateOut) {
   8059         *sampleRateOut = 0;
   8060     }
   8061     if (totalFrameCountOut) {
   8062         *totalFrameCountOut = 0;
   8063     }
   8064 
   8065     if (!drwav_init(&wav, onRead, onSeek, pUserData, pAllocationCallbacks)) {
   8066         return NULL;
   8067     }
   8068 
   8069     return drwav__read_pcm_frames_and_close_s32(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
   8070 }
   8071 
   8072 #ifndef DR_WAV_NO_STDIO
   8073 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)
   8074 {
   8075     drwav wav;
   8076 
   8077     if (channelsOut) {
   8078         *channelsOut = 0;
   8079     }
   8080     if (sampleRateOut) {
   8081         *sampleRateOut = 0;
   8082     }
   8083     if (totalFrameCountOut) {
   8084         *totalFrameCountOut = 0;
   8085     }
   8086 
   8087     if (!drwav_init_file(&wav, filename, pAllocationCallbacks)) {
   8088         return NULL;
   8089     }
   8090 
   8091     return drwav__read_pcm_frames_and_close_s16(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
   8092 }
   8093 
   8094 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)
   8095 {
   8096     drwav wav;
   8097 
   8098     if (channelsOut) {
   8099         *channelsOut = 0;
   8100     }
   8101     if (sampleRateOut) {
   8102         *sampleRateOut = 0;
   8103     }
   8104     if (totalFrameCountOut) {
   8105         *totalFrameCountOut = 0;
   8106     }
   8107 
   8108     if (!drwav_init_file(&wav, filename, pAllocationCallbacks)) {
   8109         return NULL;
   8110     }
   8111 
   8112     return drwav__read_pcm_frames_and_close_f32(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
   8113 }
   8114 
   8115 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)
   8116 {
   8117     drwav wav;
   8118 
   8119     if (channelsOut) {
   8120         *channelsOut = 0;
   8121     }
   8122     if (sampleRateOut) {
   8123         *sampleRateOut = 0;
   8124     }
   8125     if (totalFrameCountOut) {
   8126         *totalFrameCountOut = 0;
   8127     }
   8128 
   8129     if (!drwav_init_file(&wav, filename, pAllocationCallbacks)) {
   8130         return NULL;
   8131     }
   8132 
   8133     return drwav__read_pcm_frames_and_close_s32(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
   8134 }
   8135 
   8136 
   8137 #ifndef DR_WAV_NO_WCHAR
   8138 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)
   8139 {
   8140     drwav wav;
   8141 
   8142     if (sampleRateOut) {
   8143         *sampleRateOut = 0;
   8144     }
   8145     if (channelsOut) {
   8146         *channelsOut = 0;
   8147     }
   8148     if (totalFrameCountOut) {
   8149         *totalFrameCountOut = 0;
   8150     }
   8151 
   8152     if (!drwav_init_file_w(&wav, filename, pAllocationCallbacks)) {
   8153         return NULL;
   8154     }
   8155 
   8156     return drwav__read_pcm_frames_and_close_s16(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
   8157 }
   8158 
   8159 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)
   8160 {
   8161     drwav wav;
   8162 
   8163     if (sampleRateOut) {
   8164         *sampleRateOut = 0;
   8165     }
   8166     if (channelsOut) {
   8167         *channelsOut = 0;
   8168     }
   8169     if (totalFrameCountOut) {
   8170         *totalFrameCountOut = 0;
   8171     }
   8172 
   8173     if (!drwav_init_file_w(&wav, filename, pAllocationCallbacks)) {
   8174         return NULL;
   8175     }
   8176 
   8177     return drwav__read_pcm_frames_and_close_f32(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
   8178 }
   8179 
   8180 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)
   8181 {
   8182     drwav wav;
   8183 
   8184     if (sampleRateOut) {
   8185         *sampleRateOut = 0;
   8186     }
   8187     if (channelsOut) {
   8188         *channelsOut = 0;
   8189     }
   8190     if (totalFrameCountOut) {
   8191         *totalFrameCountOut = 0;
   8192     }
   8193 
   8194     if (!drwav_init_file_w(&wav, filename, pAllocationCallbacks)) {
   8195         return NULL;
   8196     }
   8197 
   8198     return drwav__read_pcm_frames_and_close_s32(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
   8199 }
   8200 #endif /* DR_WAV_NO_WCHAR */
   8201 #endif /* DR_WAV_NO_STDIO */
   8202 
   8203 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)
   8204 {
   8205     drwav wav;
   8206 
   8207     if (channelsOut) {
   8208         *channelsOut = 0;
   8209     }
   8210     if (sampleRateOut) {
   8211         *sampleRateOut = 0;
   8212     }
   8213     if (totalFrameCountOut) {
   8214         *totalFrameCountOut = 0;
   8215     }
   8216 
   8217     if (!drwav_init_memory(&wav, data, dataSize, pAllocationCallbacks)) {
   8218         return NULL;
   8219     }
   8220 
   8221     return drwav__read_pcm_frames_and_close_s16(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
   8222 }
   8223 
   8224 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)
   8225 {
   8226     drwav wav;
   8227 
   8228     if (channelsOut) {
   8229         *channelsOut = 0;
   8230     }
   8231     if (sampleRateOut) {
   8232         *sampleRateOut = 0;
   8233     }
   8234     if (totalFrameCountOut) {
   8235         *totalFrameCountOut = 0;
   8236     }
   8237 
   8238     if (!drwav_init_memory(&wav, data, dataSize, pAllocationCallbacks)) {
   8239         return NULL;
   8240     }
   8241 
   8242     return drwav__read_pcm_frames_and_close_f32(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
   8243 }
   8244 
   8245 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)
   8246 {
   8247     drwav wav;
   8248 
   8249     if (channelsOut) {
   8250         *channelsOut = 0;
   8251     }
   8252     if (sampleRateOut) {
   8253         *sampleRateOut = 0;
   8254     }
   8255     if (totalFrameCountOut) {
   8256         *totalFrameCountOut = 0;
   8257     }
   8258 
   8259     if (!drwav_init_memory(&wav, data, dataSize, pAllocationCallbacks)) {
   8260         return NULL;
   8261     }
   8262 
   8263     return drwav__read_pcm_frames_and_close_s32(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
   8264 }
   8265 #endif  /* DR_WAV_NO_CONVERSION_API */
   8266 
   8267 
   8268 DRWAV_API void drwav_free(void* p, const drwav_allocation_callbacks* pAllocationCallbacks)
   8269 {
   8270     if (pAllocationCallbacks != NULL) {
   8271         drwav__free_from_callbacks(p, pAllocationCallbacks);
   8272     } else {
   8273         drwav__free_default(p, NULL);
   8274     }
   8275 }
   8276 
   8277 DRWAV_API drwav_uint16 drwav_bytes_to_u16(const drwav_uint8* data)
   8278 {
   8279     return ((drwav_uint16)data[0] << 0) | ((drwav_uint16)data[1] << 8);
   8280 }
   8281 
   8282 DRWAV_API drwav_int16 drwav_bytes_to_s16(const drwav_uint8* data)
   8283 {
   8284     return (drwav_int16)drwav_bytes_to_u16(data);
   8285 }
   8286 
   8287 DRWAV_API drwav_uint32 drwav_bytes_to_u32(const drwav_uint8* data)
   8288 {
   8289     return drwav_bytes_to_u32_le(data);
   8290 }
   8291 
   8292 DRWAV_API float drwav_bytes_to_f32(const drwav_uint8* data)
   8293 {
   8294     union {
   8295         drwav_uint32 u32;
   8296         float f32;
   8297     } value;
   8298 
   8299     value.u32 = drwav_bytes_to_u32(data);
   8300     return value.f32;
   8301 }
   8302 
   8303 DRWAV_API drwav_int32 drwav_bytes_to_s32(const drwav_uint8* data)
   8304 {
   8305     return (drwav_int32)drwav_bytes_to_u32(data);
   8306 }
   8307 
   8308 DRWAV_API drwav_uint64 drwav_bytes_to_u64(const drwav_uint8* data)
   8309 {
   8310     return
   8311         ((drwav_uint64)data[0] <<  0) | ((drwav_uint64)data[1] <<  8) | ((drwav_uint64)data[2] << 16) | ((drwav_uint64)data[3] << 24) |
   8312         ((drwav_uint64)data[4] << 32) | ((drwav_uint64)data[5] << 40) | ((drwav_uint64)data[6] << 48) | ((drwav_uint64)data[7] << 56);
   8313 }
   8314 
   8315 DRWAV_API drwav_int64 drwav_bytes_to_s64(const drwav_uint8* data)
   8316 {
   8317     return (drwav_int64)drwav_bytes_to_u64(data);
   8318 }
   8319 
   8320 
   8321 DRWAV_API drwav_bool32 drwav_guid_equal(const drwav_uint8 a[16], const drwav_uint8 b[16])
   8322 {
   8323     int i;
   8324     for (i = 0; i < 16; i += 1) {
   8325         if (a[i] != b[i]) {
   8326             return DRWAV_FALSE;
   8327         }
   8328     }
   8329 
   8330     return DRWAV_TRUE;
   8331 }
   8332 
   8333 DRWAV_API drwav_bool32 drwav_fourcc_equal(const drwav_uint8* a, const char* b)
   8334 {
   8335     return
   8336         a[0] == b[0] &&
   8337         a[1] == b[1] &&
   8338         a[2] == b[2] &&
   8339         a[3] == b[3];
   8340 }
   8341 
   8342 #ifdef __MRC__
   8343 /* Undo the pragma at the beginning of this file. */
   8344 #pragma options opt reset
   8345 #endif
   8346 
   8347 #endif  /* dr_wav_c */
   8348 #endif  /* DR_WAV_IMPLEMENTATION */
   8349 
   8350 /*
   8351 REVISION HISTORY
   8352 ================
   8353 v0.13.16 - 2024-02-27
   8354   - Fix a Wdouble-promotion warning.
   8355 
   8356 v0.13.15 - 2024-01-23
   8357   - Relax some unnecessary validation that prevented some files from loading.
   8358 
   8359 v0.13.14 - 2023-12-02
   8360   - Fix a warning about an unused variable.
   8361 
   8362 v0.13.13 - 2023-11-02
   8363   - Fix a warning when compiling with Clang.
   8364 
   8365 v0.13.12 - 2023-08-07
   8366   - Fix a possible crash in drwav_read_pcm_frames().
   8367 
   8368 v0.13.11 - 2023-07-07
   8369   - AIFF compatibility improvements.
   8370 
   8371 v0.13.10 - 2023-05-29
   8372   - Fix a bug where drwav_init_with_metadata() does not decode any frames after initializtion.
   8373 
   8374 v0.13.9 - 2023-05-22
   8375   - Add support for AIFF decoding (writing and metadata not supported).
   8376   - Add support for RIFX decoding (writing and metadata not supported).
   8377   - Fix a bug where metadata is not processed if it's located before the "fmt " chunk.
   8378   - Add a workaround for a type of malformed WAV file where the size of the "RIFF" and "data" chunks
   8379     are incorrectly set to 0xFFFFFFFF.
   8380 
   8381 v0.13.8 - 2023-03-25
   8382   - Fix a possible null pointer dereference.
   8383   - Fix a crash when loading files with badly formed metadata.
   8384 
   8385 v0.13.7 - 2022-09-17
   8386   - Fix compilation with DJGPP.
   8387   - Add support for disabling wchar_t with DR_WAV_NO_WCHAR.
   8388 
   8389 v0.13.6 - 2022-04-10
   8390   - Fix compilation error on older versions of GCC.
   8391   - Remove some dependencies on the standard library.
   8392 
   8393 v0.13.5 - 2022-01-26
   8394   - Fix an error when seeking to the end of the file.
   8395 
   8396 v0.13.4 - 2021-12-08
   8397   - Fix some static analysis warnings.
   8398 
   8399 v0.13.3 - 2021-11-24
   8400   - Fix an incorrect assertion when trying to endian swap 1-byte sample formats. This is now a no-op
   8401     rather than a failed assertion.
   8402   - Fix a bug with parsing of the bext chunk.
   8403   - Fix some static analysis warnings.
   8404 
   8405 v0.13.2 - 2021-10-02
   8406   - Fix a possible buffer overflow when reading from compressed formats.
   8407 
   8408 v0.13.1 - 2021-07-31
   8409   - Fix platform detection for ARM64.
   8410 
   8411 v0.13.0 - 2021-07-01
   8412   - Improve support for reading and writing metadata. Use the `_with_metadata()` APIs to initialize
   8413     a WAV decoder and store the metadata within the `drwav` object. Use the `pMetadata` and
   8414     `metadataCount` members of the `drwav` object to read the data. The old way of handling metadata
   8415     via a callback is still usable and valid.
   8416   - API CHANGE: drwav_target_write_size_bytes() now takes extra parameters for calculating the
   8417     required write size when writing metadata.
   8418   - Add drwav_get_cursor_in_pcm_frames()
   8419   - Add drwav_get_length_in_pcm_frames()
   8420   - Fix a bug where drwav_read_raw() can call the read callback with a byte count of zero.
   8421 
   8422 v0.12.20 - 2021-06-11
   8423   - Fix some undefined behavior.
   8424 
   8425 v0.12.19 - 2021-02-21
   8426   - Fix a warning due to referencing _MSC_VER when it is undefined.
   8427   - Minor improvements to the management of some internal state concerning the data chunk cursor.
   8428 
   8429 v0.12.18 - 2021-01-31
   8430   - Clean up some static analysis warnings.
   8431 
   8432 v0.12.17 - 2021-01-17
   8433   - Minor fix to sample code in documentation.
   8434   - Correctly qualify a private API as private rather than public.
   8435   - Code cleanup.
   8436 
   8437 v0.12.16 - 2020-12-02
   8438   - Fix a bug when trying to read more bytes than can fit in a size_t.
   8439 
   8440 v0.12.15 - 2020-11-21
   8441   - Fix compilation with OpenWatcom.
   8442 
   8443 v0.12.14 - 2020-11-13
   8444   - Minor code clean up.
   8445 
   8446 v0.12.13 - 2020-11-01
   8447   - Improve compiler support for older versions of GCC.
   8448 
   8449 v0.12.12 - 2020-09-28
   8450   - Add support for RF64.
   8451   - Fix a bug in writing mode where the size of the RIFF chunk incorrectly includes the header section.
   8452 
   8453 v0.12.11 - 2020-09-08
   8454   - Fix a compilation error on older compilers.
   8455 
   8456 v0.12.10 - 2020-08-24
   8457   - Fix a bug when seeking with ADPCM formats.
   8458 
   8459 v0.12.9 - 2020-08-02
   8460   - Simplify sized types.
   8461 
   8462 v0.12.8 - 2020-07-25
   8463   - Fix a compilation warning.
   8464 
   8465 v0.12.7 - 2020-07-15
   8466   - Fix some bugs on big-endian architectures.
   8467   - Fix an error in s24 to f32 conversion.
   8468 
   8469 v0.12.6 - 2020-06-23
   8470   - Change drwav_read_*() to allow NULL to be passed in as the output buffer which is equivalent to a forward seek.
   8471   - Fix a buffer overflow when trying to decode invalid IMA-ADPCM files.
   8472   - Add include guard for the implementation section.
   8473 
   8474 v0.12.5 - 2020-05-27
   8475   - Minor documentation fix.
   8476 
   8477 v0.12.4 - 2020-05-16
   8478   - Replace assert() with DRWAV_ASSERT().
   8479   - Add compile-time and run-time version querying.
   8480     - DRWAV_VERSION_MINOR
   8481     - DRWAV_VERSION_MAJOR
   8482     - DRWAV_VERSION_REVISION
   8483     - DRWAV_VERSION_STRING
   8484     - drwav_version()
   8485     - drwav_version_string()
   8486 
   8487 v0.12.3 - 2020-04-30
   8488   - Fix compilation errors with VC6.
   8489 
   8490 v0.12.2 - 2020-04-21
   8491   - Fix a bug where drwav_init_file() does not close the file handle after attempting to load an erroneous file.
   8492 
   8493 v0.12.1 - 2020-04-13
   8494   - Fix some pedantic warnings.
   8495 
   8496 v0.12.0 - 2020-04-04
   8497   - API CHANGE: Add container and format parameters to the chunk callback.
   8498   - Minor documentation updates.
   8499 
   8500 v0.11.5 - 2020-03-07
   8501   - Fix compilation error with Visual Studio .NET 2003.
   8502 
   8503 v0.11.4 - 2020-01-29
   8504   - Fix some static analysis warnings.
   8505   - Fix a bug when reading f32 samples from an A-law encoded stream.
   8506 
   8507 v0.11.3 - 2020-01-12
   8508   - Minor changes to some f32 format conversion routines.
   8509   - Minor bug fix for ADPCM conversion when end of file is reached.
   8510 
   8511 v0.11.2 - 2019-12-02
   8512   - Fix a possible crash when using custom memory allocators without a custom realloc() implementation.
   8513   - Fix an integer overflow bug.
   8514   - Fix a null pointer dereference bug.
   8515   - Add limits to sample rate, channels and bits per sample to tighten up some validation.
   8516 
   8517 v0.11.1 - 2019-10-07
   8518   - Internal code clean up.
   8519 
   8520 v0.11.0 - 2019-10-06
   8521   - API CHANGE: Add support for user defined memory allocation routines. This system allows the program to specify their own memory allocation
   8522     routines with a user data pointer for client-specific contextual data. This adds an extra parameter to the end of the following APIs:
   8523     - drwav_init()
   8524     - drwav_init_ex()
   8525     - drwav_init_file()
   8526     - drwav_init_file_ex()
   8527     - drwav_init_file_w()
   8528     - drwav_init_file_w_ex()
   8529     - drwav_init_memory()
   8530     - drwav_init_memory_ex()
   8531     - drwav_init_write()
   8532     - drwav_init_write_sequential()
   8533     - drwav_init_write_sequential_pcm_frames()
   8534     - drwav_init_file_write()
   8535     - drwav_init_file_write_sequential()
   8536     - drwav_init_file_write_sequential_pcm_frames()
   8537     - drwav_init_file_write_w()
   8538     - drwav_init_file_write_sequential_w()
   8539     - drwav_init_file_write_sequential_pcm_frames_w()
   8540     - drwav_init_memory_write()
   8541     - drwav_init_memory_write_sequential()
   8542     - drwav_init_memory_write_sequential_pcm_frames()
   8543     - drwav_open_and_read_pcm_frames_s16()
   8544     - drwav_open_and_read_pcm_frames_f32()
   8545     - drwav_open_and_read_pcm_frames_s32()
   8546     - drwav_open_file_and_read_pcm_frames_s16()
   8547     - drwav_open_file_and_read_pcm_frames_f32()
   8548     - drwav_open_file_and_read_pcm_frames_s32()
   8549     - drwav_open_file_and_read_pcm_frames_s16_w()
   8550     - drwav_open_file_and_read_pcm_frames_f32_w()
   8551     - drwav_open_file_and_read_pcm_frames_s32_w()
   8552     - drwav_open_memory_and_read_pcm_frames_s16()
   8553     - drwav_open_memory_and_read_pcm_frames_f32()
   8554     - drwav_open_memory_and_read_pcm_frames_s32()
   8555     Set this extra parameter to NULL to use defaults which is the same as the previous behaviour. Setting this NULL will use
   8556     DRWAV_MALLOC, DRWAV_REALLOC and DRWAV_FREE.
   8557   - Add support for reading and writing PCM frames in an explicit endianness. New APIs:
   8558     - drwav_read_pcm_frames_le()
   8559     - drwav_read_pcm_frames_be()
   8560     - drwav_read_pcm_frames_s16le()
   8561     - drwav_read_pcm_frames_s16be()
   8562     - drwav_read_pcm_frames_f32le()
   8563     - drwav_read_pcm_frames_f32be()
   8564     - drwav_read_pcm_frames_s32le()
   8565     - drwav_read_pcm_frames_s32be()
   8566     - drwav_write_pcm_frames_le()
   8567     - drwav_write_pcm_frames_be()
   8568   - Remove deprecated APIs.
   8569   - API CHANGE: The following APIs now return native-endian data. Previously they returned little-endian data.
   8570     - drwav_read_pcm_frames()
   8571     - drwav_read_pcm_frames_s16()
   8572     - drwav_read_pcm_frames_s32()
   8573     - drwav_read_pcm_frames_f32()
   8574     - drwav_open_and_read_pcm_frames_s16()
   8575     - drwav_open_and_read_pcm_frames_s32()
   8576     - drwav_open_and_read_pcm_frames_f32()
   8577     - drwav_open_file_and_read_pcm_frames_s16()
   8578     - drwav_open_file_and_read_pcm_frames_s32()
   8579     - drwav_open_file_and_read_pcm_frames_f32()
   8580     - drwav_open_file_and_read_pcm_frames_s16_w()
   8581     - drwav_open_file_and_read_pcm_frames_s32_w()
   8582     - drwav_open_file_and_read_pcm_frames_f32_w()
   8583     - drwav_open_memory_and_read_pcm_frames_s16()
   8584     - drwav_open_memory_and_read_pcm_frames_s32()
   8585     - drwav_open_memory_and_read_pcm_frames_f32()
   8586 
   8587 v0.10.1 - 2019-08-31
   8588   - Correctly handle partial trailing ADPCM blocks.
   8589 
   8590 v0.10.0 - 2019-08-04
   8591   - Remove deprecated APIs.
   8592   - Add wchar_t variants for file loading APIs:
   8593       drwav_init_file_w()
   8594       drwav_init_file_ex_w()
   8595       drwav_init_file_write_w()
   8596       drwav_init_file_write_sequential_w()
   8597   - Add drwav_target_write_size_bytes() which calculates the total size in bytes of a WAV file given a format and sample count.
   8598   - Add APIs for specifying the PCM frame count instead of the sample count when opening in sequential write mode:
   8599       drwav_init_write_sequential_pcm_frames()
   8600       drwav_init_file_write_sequential_pcm_frames()
   8601       drwav_init_file_write_sequential_pcm_frames_w()
   8602       drwav_init_memory_write_sequential_pcm_frames()
   8603   - Deprecate drwav_open*() and drwav_close():
   8604       drwav_open()
   8605       drwav_open_ex()
   8606       drwav_open_write()
   8607       drwav_open_write_sequential()
   8608       drwav_open_file()
   8609       drwav_open_file_ex()
   8610       drwav_open_file_write()
   8611       drwav_open_file_write_sequential()
   8612       drwav_open_memory()
   8613       drwav_open_memory_ex()
   8614       drwav_open_memory_write()
   8615       drwav_open_memory_write_sequential()
   8616       drwav_close()
   8617   - Minor documentation updates.
   8618 
   8619 v0.9.2 - 2019-05-21
   8620   - Fix warnings.
   8621 
   8622 v0.9.1 - 2019-05-05
   8623   - Add support for C89.
   8624   - Change license to choice of public domain or MIT-0.
   8625 
   8626 v0.9.0 - 2018-12-16
   8627   - API CHANGE: Add new reading APIs for reading by PCM frames instead of samples. Old APIs have been deprecated and
   8628     will be removed in v0.10.0. Deprecated APIs and their replacements:
   8629       drwav_read()                     -> drwav_read_pcm_frames()
   8630       drwav_read_s16()                 -> drwav_read_pcm_frames_s16()
   8631       drwav_read_f32()                 -> drwav_read_pcm_frames_f32()
   8632       drwav_read_s32()                 -> drwav_read_pcm_frames_s32()
   8633       drwav_seek_to_sample()           -> drwav_seek_to_pcm_frame()
   8634       drwav_write()                    -> drwav_write_pcm_frames()
   8635       drwav_open_and_read_s16()        -> drwav_open_and_read_pcm_frames_s16()
   8636       drwav_open_and_read_f32()        -> drwav_open_and_read_pcm_frames_f32()
   8637       drwav_open_and_read_s32()        -> drwav_open_and_read_pcm_frames_s32()
   8638       drwav_open_file_and_read_s16()   -> drwav_open_file_and_read_pcm_frames_s16()
   8639       drwav_open_file_and_read_f32()   -> drwav_open_file_and_read_pcm_frames_f32()
   8640       drwav_open_file_and_read_s32()   -> drwav_open_file_and_read_pcm_frames_s32()
   8641       drwav_open_memory_and_read_s16() -> drwav_open_memory_and_read_pcm_frames_s16()
   8642       drwav_open_memory_and_read_f32() -> drwav_open_memory_and_read_pcm_frames_f32()
   8643       drwav_open_memory_and_read_s32() -> drwav_open_memory_and_read_pcm_frames_s32()
   8644       drwav::totalSampleCount          -> drwav::totalPCMFrameCount
   8645   - API CHANGE: Rename drwav_open_and_read_file_*() to drwav_open_file_and_read_*().
   8646   - API CHANGE: Rename drwav_open_and_read_memory_*() to drwav_open_memory_and_read_*().
   8647   - Add built-in support for smpl chunks.
   8648   - Add support for firing a callback for each chunk in the file at initialization time.
   8649     - This is enabled through the drwav_init_ex(), etc. family of APIs.
   8650   - Handle invalid FMT chunks more robustly.
   8651 
   8652 v0.8.5 - 2018-09-11
   8653   - Const correctness.
   8654   - Fix a potential stack overflow.
   8655 
   8656 v0.8.4 - 2018-08-07
   8657   - Improve 64-bit detection.
   8658 
   8659 v0.8.3 - 2018-08-05
   8660   - Fix C++ build on older versions of GCC.
   8661 
   8662 v0.8.2 - 2018-08-02
   8663   - Fix some big-endian bugs.
   8664 
   8665 v0.8.1 - 2018-06-29
   8666   - Add support for sequential writing APIs.
   8667   - Disable seeking in write mode.
   8668   - Fix bugs with Wave64.
   8669   - Fix typos.
   8670 
   8671 v0.8 - 2018-04-27
   8672   - Bug fix.
   8673   - Start using major.minor.revision versioning.
   8674 
   8675 v0.7f - 2018-02-05
   8676   - Restrict ADPCM formats to a maximum of 2 channels.
   8677 
   8678 v0.7e - 2018-02-02
   8679   - Fix a crash.
   8680 
   8681 v0.7d - 2018-02-01
   8682   - Fix a crash.
   8683 
   8684 v0.7c - 2018-02-01
   8685   - Set drwav.bytesPerSample to 0 for all compressed formats.
   8686   - Fix a crash when reading 16-bit floating point WAV files. In this case dr_wav will output silence for
   8687     all format conversion reading APIs (*_s16, *_s32, *_f32 APIs).
   8688   - Fix some divide-by-zero errors.
   8689 
   8690 v0.7b - 2018-01-22
   8691   - Fix errors with seeking of compressed formats.
   8692   - Fix compilation error when DR_WAV_NO_CONVERSION_API
   8693 
   8694 v0.7a - 2017-11-17
   8695   - Fix some GCC warnings.
   8696 
   8697 v0.7 - 2017-11-04
   8698   - Add writing APIs.
   8699 
   8700 v0.6 - 2017-08-16
   8701   - API CHANGE: Rename dr_* types to drwav_*.
   8702   - Add support for custom implementations of malloc(), realloc(), etc.
   8703   - Add support for Microsoft ADPCM.
   8704   - Add support for IMA ADPCM (DVI, format code 0x11).
   8705   - Optimizations to drwav_read_s16().
   8706   - Bug fixes.
   8707 
   8708 v0.5g - 2017-07-16
   8709   - Change underlying type for booleans to unsigned.
   8710 
   8711 v0.5f - 2017-04-04
   8712   - Fix a minor bug with drwav_open_and_read_s16() and family.
   8713 
   8714 v0.5e - 2016-12-29
   8715   - Added support for reading samples as signed 16-bit integers. Use the _s16() family of APIs for this.
   8716   - Minor fixes to documentation.
   8717 
   8718 v0.5d - 2016-12-28
   8719   - Use drwav_int* and drwav_uint* sized types to improve compiler support.
   8720 
   8721 v0.5c - 2016-11-11
   8722   - Properly handle JUNK chunks that come before the FMT chunk.
   8723 
   8724 v0.5b - 2016-10-23
   8725   - A minor change to drwav_bool8 and drwav_bool32 types.
   8726 
   8727 v0.5a - 2016-10-11
   8728   - Fixed a bug with drwav_open_and_read() and family due to incorrect argument ordering.
   8729   - Improve A-law and mu-law efficiency.
   8730 
   8731 v0.5 - 2016-09-29
   8732   - API CHANGE. Swap the order of "channels" and "sampleRate" parameters in drwav_open_and_read*(). Rationale for this is to
   8733     keep it consistent with dr_audio and dr_flac.
   8734 
   8735 v0.4b - 2016-09-18
   8736   - Fixed a typo in documentation.
   8737 
   8738 v0.4a - 2016-09-18
   8739   - Fixed a typo.
   8740   - Change date format to ISO 8601 (YYYY-MM-DD)
   8741 
   8742 v0.4 - 2016-07-13
   8743   - API CHANGE. Make onSeek consistent with dr_flac.
   8744   - API CHANGE. Rename drwav_seek() to drwav_seek_to_sample() for clarity and consistency with dr_flac.
   8745   - Added support for Sony Wave64.
   8746 
   8747 v0.3a - 2016-05-28
   8748   - API CHANGE. Return drwav_bool32 instead of int in onSeek callback.
   8749   - Fixed a memory leak.
   8750 
   8751 v0.3 - 2016-05-22
   8752   - Lots of API changes for consistency.
   8753 
   8754 v0.2a - 2016-05-16
   8755   - Fixed Linux/GCC build.
   8756 
   8757 v0.2 - 2016-05-11
   8758   - Added support for reading data as signed 32-bit PCM for consistency with dr_flac.
   8759 
   8760 v0.1a - 2016-05-07
   8761   - Fixed a bug in drwav_open_file() where the file handle would not be closed if the loader failed to initialize.
   8762 
   8763 v0.1 - 2016-05-04
   8764   - Initial versioned release.
   8765 */
   8766 
   8767 /*
   8768 This software is available as a choice of the following licenses. Choose
   8769 whichever you prefer.
   8770 
   8771 ===============================================================================
   8772 ALTERNATIVE 1 - Public Domain (www.unlicense.org)
   8773 ===============================================================================
   8774 This is free and unencumbered software released into the public domain.
   8775 
   8776 Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
   8777 software, either in source code form or as a compiled binary, for any purpose,
   8778 commercial or non-commercial, and by any means.
   8779 
   8780 In jurisdictions that recognize copyright laws, the author or authors of this
   8781 software dedicate any and all copyright interest in the software to the public
   8782 domain. We make this dedication for the benefit of the public at large and to
   8783 the detriment of our heirs and successors. We intend this dedication to be an
   8784 overt act of relinquishment in perpetuity of all present and future rights to
   8785 this software under copyright law.
   8786 
   8787 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   8788 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   8789 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   8790 AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
   8791 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
   8792 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
   8793 
   8794 For more information, please refer to <http://unlicense.org/>
   8795 
   8796 ===============================================================================
   8797 ALTERNATIVE 2 - MIT No Attribution
   8798 ===============================================================================
   8799 Copyright 2023 David Reid
   8800 
   8801 Permission is hereby granted, free of charge, to any person obtaining a copy of
   8802 this software and associated documentation files (the "Software"), to deal in
   8803 the Software without restriction, including without limitation the rights to
   8804 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
   8805 of the Software, and to permit persons to whom the Software is furnished to do
   8806 so.
   8807 
   8808 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   8809 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   8810 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   8811 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   8812 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   8813 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
   8814 SOFTWARE.
   8815 */