DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
src/libs/decoders/dr_wav.h
00001 /*
00002 WAV audio loader and writer. Choice of public domain or MIT-0. See license statements at the end of this file.
00003 dr_wav - v0.12.4 - 2020-05-16
00004 
00005 David Reid - mackron@gmail.com
00006 
00007 GitHub: https://github.com/mackron/dr_libs
00008 */
00009 
00010 /*
00011 RELEASE NOTES - VERSION 0.12
00012 ============================
00013 Version 0.12 includes breaking changes to custom chunk handling.
00014 
00015 
00016 Changes to Chunk Callback
00017 -------------------------
00018 dr_wav supports the ability to fire a callback when a chunk is encounted (except for WAVE and FMT chunks). The callback has been update to include both the
00019 container (RIFF or Wave64) and the FMT chunk which contains information about the format of the data in the wave file.
00020 
00021 Previously, there was no direct way to determine the container, and therefore no way discriminate against the different IDs in the chunk header (RIFF and
00022 Wave64 containers encode chunk ID's differently). The `container` parameter can be used to know which ID to use.
00023 
00024 Sometimes it can be useful to know the data format at the time the chunk callback is fired. A pointer to a `drwav_fmt` object is now passed into the chunk
00025 callback which will give you information about the data format. To determine the sample format, use `drwav_fmt_get_format()`. This will return one of the
00026 `DR_WAVE_FORMAT_*` tokens.
00027 */
00028 
00029 /*
00030 Introduction
00031 ============
00032 This is a single file library. To use it, do something like the following in one .c file.
00033     
00034     ```c
00035     #define DR_WAV_IMPLEMENTATION
00036     #include "dr_wav.h"
00037     ```
00038 
00039 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:
00040 
00041     ```c
00042     drwav wav;
00043     if (!drwav_init_file(&wav, "my_song.wav", NULL)) {
00044         // Error opening WAV file.
00045     }
00046 
00047     drwav_int32* pDecodedInterleavedPCMFrames = malloc(wav.totalPCMFrameCount * wav.channels * sizeof(drwav_int32));
00048     size_t numberOfSamplesActuallyDecoded = drwav_read_pcm_frames_s32(&wav, wav.totalPCMFrameCount, pDecodedInterleavedPCMFrames);
00049 
00050     ...
00051 
00052     drwav_uninit(&wav);
00053     ```
00054 
00055 If you just want to quickly open and read the audio data in a single operation you can do something like this:
00056 
00057     ```c
00058     unsigned int channels;
00059     unsigned int sampleRate;
00060     drwav_uint64 totalPCMFrameCount;
00061     float* pSampleData = drwav_open_file_and_read_pcm_frames_f32("my_song.wav", &channels, &sampleRate, &totalPCMFrameCount, NULL);
00062     if (pSampleData == NULL) {
00063         // Error opening and reading WAV file.
00064     }
00065 
00066     ...
00067 
00068     drwav_free(pSampleData);
00069     ```
00070 
00071 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
00072 audio data in its internal format (see notes below for supported formats):
00073 
00074     ```c
00075     size_t framesRead = drwav_read_pcm_frames(&wav, wav.totalPCMFrameCount, pDecodedInterleavedPCMFrames);
00076     ```
00077 
00078 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:
00079 
00080     ```c
00081     size_t bytesRead = drwav_read_raw(&wav, bytesToRead, pRawDataBuffer);
00082     ```
00083 
00084 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()`,
00085 `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.
00086 
00087     ```c
00088     drwav_data_format format;
00089     format.container = drwav_container_riff;     // <-- drwav_container_riff = normal WAV files, drwav_container_w64 = Sony Wave64.
00090     format.format = DR_WAVE_FORMAT_PCM;          // <-- Any of the DR_WAVE_FORMAT_* codes.
00091     format.channels = 2;
00092     format.sampleRate = 44100;
00093     format.bitsPerSample = 16;
00094     drwav_init_file_write(&wav, "data/recording.wav", &format, NULL);
00095 
00096     ...
00097 
00098     drwav_uint64 framesWritten = drwav_write_pcm_frames(pWav, frameCount, pSamples);
00099     ```
00100 
00101 dr_wav has seamless support the Sony Wave64 format. The decoder will automatically detect it and it should Just Work without any manual intervention.
00102 
00103 
00104 Build Options
00105 =============
00106 #define these options before including this file.
00107 
00108 #define DR_WAV_NO_CONVERSION_API
00109   Disables conversion APIs such as `drwav_read_pcm_frames_f32()` and `drwav_s16_to_f32()`.
00110 
00111 #define DR_WAV_NO_STDIO
00112   Disables APIs that initialize a decoder from a file such as `drwav_init_file()`, `drwav_init_file_write()`, etc.
00113 
00114 
00115 
00116 Notes
00117 =====
00118 - Samples are always interleaved.
00119 - 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()`
00120   to read and convert audio data to 32-bit floating point, signed 32-bit integer and signed 16-bit integer samples respectively. Tested and supported internal
00121   formats include the following:
00122   - Unsigned 8-bit PCM
00123   - Signed 12-bit PCM
00124   - Signed 16-bit PCM
00125   - Signed 24-bit PCM
00126   - Signed 32-bit PCM
00127   - IEEE 32-bit floating point
00128   - IEEE 64-bit floating point
00129   - A-law and u-law
00130   - Microsoft ADPCM
00131   - IMA ADPCM (DVI, format code 0x11)
00132 - dr_wav will try to read the WAV file as best it can, even if it's not strictly conformant to the WAV format.
00133 */
00134 
00135 #ifndef dr_wav_h
00136 #define dr_wav_h
00137 
00138 #ifdef __cplusplus
00139 extern "C" {
00140 #endif
00141 
00142 #define DRWAV_STRINGIFY(x)      #x
00143 #define DRWAV_XSTRINGIFY(x)     DRWAV_STRINGIFY(x)
00144 
00145 #define DRWAV_VERSION_MAJOR     0
00146 #define DRWAV_VERSION_MINOR     12
00147 #define DRWAV_VERSION_REVISION  4
00148 #define DRWAV_VERSION_STRING    DRWAV_XSTRINGIFY(DRWAV_VERSION_MAJOR) "." DRWAV_XSTRINGIFY(DRWAV_VERSION_MINOR) "." DRWAV_XSTRINGIFY(DRWAV_VERSION_REVISION)
00149 
00150 #include <stddef.h> /* For size_t. */
00151 
00152 /* Sized types. Prefer built-in types. Fall back to stdint. */
00153 #ifdef _MSC_VER
00154     #if defined(__clang__)
00155         #pragma GCC diagnostic push
00156         #pragma GCC diagnostic ignored "-Wlanguage-extension-token"
00157         #pragma GCC diagnostic ignored "-Wlong-long"        
00158         #pragma GCC diagnostic ignored "-Wc++11-long-long"
00159     #endif
00160     typedef   signed __int8  drwav_int8;
00161     typedef unsigned __int8  drwav_uint8;
00162     typedef   signed __int16 drwav_int16;
00163     typedef unsigned __int16 drwav_uint16;
00164     typedef   signed __int32 drwav_int32;
00165     typedef unsigned __int32 drwav_uint32;
00166     typedef   signed __int64 drwav_int64;
00167     typedef unsigned __int64 drwav_uint64;
00168     #if defined(__clang__)
00169         #pragma GCC diagnostic pop
00170     #endif
00171 #else
00172     #include <stdint.h>
00173     typedef int8_t           drwav_int8;
00174     typedef uint8_t          drwav_uint8;
00175     typedef int16_t          drwav_int16;
00176     typedef uint16_t         drwav_uint16;
00177     typedef int32_t          drwav_int32;
00178     typedef uint32_t         drwav_uint32;
00179     typedef int64_t          drwav_int64;
00180     typedef uint64_t         drwav_uint64;
00181 #endif
00182 typedef drwav_uint8          drwav_bool8;
00183 typedef drwav_uint32         drwav_bool32;
00184 #define DRWAV_TRUE           1
00185 #define DRWAV_FALSE          0
00186 
00187 #if !defined(DRWAV_API)
00188     #if defined(DRWAV_DLL)
00189         #if defined(_WIN32)
00190             #define DRWAV_DLL_IMPORT  __declspec(dllimport)
00191             #define DRWAV_DLL_EXPORT  __declspec(dllexport)
00192             #define DRWAV_DLL_PRIVATE static
00193         #else
00194             #if defined(__GNUC__) && __GNUC__ >= 4
00195                 #define DRWAV_DLL_IMPORT  __attribute__((visibility("default")))
00196                 #define DRWAV_DLL_EXPORT  __attribute__((visibility("default")))
00197                 #define DRWAV_DLL_PRIVATE __attribute__((visibility("hidden")))
00198             #else
00199                 #define DRWAV_DLL_IMPORT
00200                 #define DRWAV_DLL_EXPORT
00201                 #define DRWAV_DLL_PRIVATE static
00202             #endif
00203         #endif
00204 
00205         #if defined(DR_WAV_IMPLEMENTATION) || defined(DRWAV_IMPLEMENTATION)
00206             #define DRWAV_API  DRWAV_DLL_EXPORT
00207         #else
00208             #define DRWAV_API  DRWAV_DLL_IMPORT
00209         #endif
00210         #define DRWAV_PRIVATE DRWAV_DLL_PRIVATE
00211     #else
00212         #define DRWAV_API extern
00213         #define DRWAV_PRIVATE static
00214     #endif
00215 #endif
00216 
00217 typedef drwav_int32 drwav_result;
00218 #define DRWAV_SUCCESS                        0
00219 #define DRWAV_ERROR                         -1   /* A generic error. */
00220 #define DRWAV_INVALID_ARGS                  -2
00221 #define DRWAV_INVALID_OPERATION             -3
00222 #define DRWAV_OUT_OF_MEMORY                 -4
00223 #define DRWAV_OUT_OF_RANGE                  -5
00224 #define DRWAV_ACCESS_DENIED                 -6
00225 #define DRWAV_DOES_NOT_EXIST                -7
00226 #define DRWAV_ALREADY_EXISTS                -8
00227 #define DRWAV_TOO_MANY_OPEN_FILES           -9
00228 #define DRWAV_INVALID_FILE                  -10
00229 #define DRWAV_TOO_BIG                       -11
00230 #define DRWAV_PATH_TOO_LONG                 -12
00231 #define DRWAV_NAME_TOO_LONG                 -13
00232 #define DRWAV_NOT_DIRECTORY                 -14
00233 #define DRWAV_IS_DIRECTORY                  -15
00234 #define DRWAV_DIRECTORY_NOT_EMPTY           -16
00235 #define DRWAV_END_OF_FILE                   -17
00236 #define DRWAV_NO_SPACE                      -18
00237 #define DRWAV_BUSY                          -19
00238 #define DRWAV_IO_ERROR                      -20
00239 #define DRWAV_INTERRUPT                     -21
00240 #define DRWAV_UNAVAILABLE                   -22
00241 #define DRWAV_ALREADY_IN_USE                -23
00242 #define DRWAV_BAD_ADDRESS                   -24
00243 #define DRWAV_BAD_SEEK                      -25
00244 #define DRWAV_BAD_PIPE                      -26
00245 #define DRWAV_DEADLOCK                      -27
00246 #define DRWAV_TOO_MANY_LINKS                -28
00247 #define DRWAV_NOT_IMPLEMENTED               -29
00248 #define DRWAV_NO_MESSAGE                    -30
00249 #define DRWAV_BAD_MESSAGE                   -31
00250 #define DRWAV_NO_DATA_AVAILABLE             -32
00251 #define DRWAV_INVALID_DATA                  -33
00252 #define DRWAV_TIMEOUT                       -34
00253 #define DRWAV_NO_NETWORK                    -35
00254 #define DRWAV_NOT_UNIQUE                    -36
00255 #define DRWAV_NOT_SOCKET                    -37
00256 #define DRWAV_NO_ADDRESS                    -38
00257 #define DRWAV_BAD_PROTOCOL                  -39
00258 #define DRWAV_PROTOCOL_UNAVAILABLE          -40
00259 #define DRWAV_PROTOCOL_NOT_SUPPORTED        -41
00260 #define DRWAV_PROTOCOL_FAMILY_NOT_SUPPORTED -42
00261 #define DRWAV_ADDRESS_FAMILY_NOT_SUPPORTED  -43
00262 #define DRWAV_SOCKET_NOT_SUPPORTED          -44
00263 #define DRWAV_CONNECTION_RESET              -45
00264 #define DRWAV_ALREADY_CONNECTED             -46
00265 #define DRWAV_NOT_CONNECTED                 -47
00266 #define DRWAV_CONNECTION_REFUSED            -48
00267 #define DRWAV_NO_HOST                       -49
00268 #define DRWAV_IN_PROGRESS                   -50
00269 #define DRWAV_CANCELLED                     -51
00270 #define DRWAV_MEMORY_ALREADY_MAPPED         -52
00271 #define DRWAV_AT_END                        -53
00272 
00273 /* Common data formats. */
00274 #define DR_WAVE_FORMAT_PCM          0x1
00275 #define DR_WAVE_FORMAT_ADPCM        0x2
00276 #define DR_WAVE_FORMAT_IEEE_FLOAT   0x3
00277 #define DR_WAVE_FORMAT_ALAW         0x6
00278 #define DR_WAVE_FORMAT_MULAW        0x7
00279 #define DR_WAVE_FORMAT_DVI_ADPCM    0x11
00280 #define DR_WAVE_FORMAT_EXTENSIBLE   0xFFFE
00281 
00282 /* Constants. */
00283 #ifndef DRWAV_MAX_SMPL_LOOPS
00284 #define DRWAV_MAX_SMPL_LOOPS        1
00285 #endif
00286 
00287 /* Flags to pass into drwav_init_ex(), etc. */
00288 #define DRWAV_SEQUENTIAL            0x00000001
00289 
00290 DRWAV_API void drwav_version(drwav_uint32* pMajor, drwav_uint32* pMinor, drwav_uint32* pRevision);
00291 DRWAV_API const char* drwav_version_string();
00292 
00293 typedef enum
00294 {
00295     drwav_seek_origin_start,
00296     drwav_seek_origin_current
00297 } drwav_seek_origin;
00298 
00299 typedef enum
00300 {
00301     drwav_container_riff,
00302     drwav_container_w64
00303 } drwav_container;
00304 
00305 typedef struct
00306 {
00307     union
00308     {
00309         drwav_uint8 fourcc[4];
00310         drwav_uint8 guid[16];
00311     } id;
00312 
00313     /* The size in bytes of the chunk. */
00314     drwav_uint64 sizeInBytes;
00315 
00316     /*
00317     RIFF = 2 byte alignment.
00318     W64  = 8 byte alignment.
00319     */
00320     unsigned int paddingSize;
00321 } drwav_chunk_header;
00322 
00323 typedef struct
00324 {
00325     /*
00326     The format tag exactly as specified in the wave file's "fmt" chunk. This can be used by applications
00327     that require support for data formats not natively supported by dr_wav.
00328     */
00329     drwav_uint16 formatTag;
00330 
00331     /* The number of channels making up the audio data. When this is set to 1 it is mono, 2 is stereo, etc. */
00332     drwav_uint16 channels;
00333 
00334     /* The sample rate. Usually set to something like 44100. */
00335     drwav_uint32 sampleRate;
00336 
00337     /* Average bytes per second. You probably don't need this, but it's left here for informational purposes. */
00338     drwav_uint32 avgBytesPerSec;
00339 
00340     /* Block align. This is equal to the number of channels * bytes per sample. */
00341     drwav_uint16 blockAlign;
00342 
00343     /* Bits per sample. */
00344     drwav_uint16 bitsPerSample;
00345 
00346     /* The size of the extended data. Only used internally for validation, but left here for informational purposes. */
00347     drwav_uint16 extendedSize;
00348 
00349     /*
00350     The number of valid bits per sample. When <formatTag> is equal to WAVE_FORMAT_EXTENSIBLE, <bitsPerSample>
00351     is always rounded up to the nearest multiple of 8. This variable contains information about exactly how
00352     many bits are valid per sample. Mainly used for informational purposes.
00353     */
00354     drwav_uint16 validBitsPerSample;
00355 
00356     /* The channel mask. Not used at the moment. */
00357     drwav_uint32 channelMask;
00358 
00359     /* The sub-format, exactly as specified by the wave file. */
00360     drwav_uint8 subFormat[16];
00361 } drwav_fmt;
00362 
00363 DRWAV_API drwav_uint16 drwav_fmt_get_format(const drwav_fmt* pFMT);
00364 
00365 
00366 /*
00367 Callback for when data is read. Return value is the number of bytes actually read.
00368 
00369 pUserData   [in]  The user data that was passed to drwav_init() and family.
00370 pBufferOut  [out] The output buffer.
00371 bytesToRead [in]  The number of bytes to read.
00372 
00373 Returns the number of bytes actually read.
00374 
00375 A return value of less than bytesToRead indicates the end of the stream. Do _not_ return from this callback until
00376 either the entire bytesToRead is filled or you have reached the end of the stream.
00377 */
00378 typedef size_t (* drwav_read_proc)(void* pUserData, void* pBufferOut, size_t bytesToRead);
00379 
00380 /*
00381 Callback for when data is written. Returns value is the number of bytes actually written.
00382 
00383 pUserData    [in]  The user data that was passed to drwav_init_write() and family.
00384 pData        [out] A pointer to the data to write.
00385 bytesToWrite [in]  The number of bytes to write.
00386 
00387 Returns the number of bytes actually written.
00388 
00389 If the return value differs from bytesToWrite, it indicates an error.
00390 */
00391 typedef size_t (* drwav_write_proc)(void* pUserData, const void* pData, size_t bytesToWrite);
00392 
00393 /*
00394 Callback for when data needs to be seeked.
00395 
00396 pUserData [in] The user data that was passed to drwav_init() and family.
00397 offset    [in] The number of bytes to move, relative to the origin. Will never be negative.
00398 origin    [in] The origin of the seek - the current position or the start of the stream.
00399 
00400 Returns whether or not the seek was successful.
00401 
00402 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
00403 drwav_seek_origin_current.
00404 */
00405 typedef drwav_bool32 (* drwav_seek_proc)(void* pUserData, int offset, drwav_seek_origin origin);
00406 
00407 /*
00408 Callback for when drwav_init_ex() finds a chunk.
00409 
00410 pChunkUserData    [in] The user data that was passed to the pChunkUserData parameter of drwav_init_ex() and family.
00411 onRead            [in] A pointer to the function to call when reading.
00412 onSeek            [in] A pointer to the function to call when seeking.
00413 pReadSeekUserData [in] The user data that was passed to the pReadSeekUserData parameter of drwav_init_ex() and family.
00414 pChunkHeader      [in] A pointer to an object containing basic header information about the chunk. Use this to identify the chunk.
00415 container         [in] Whether or not the WAV file is a RIFF or Wave64 container. If you're unsure of the difference, assume RIFF.
00416 pFMT              [in] A pointer to the object containing the contents of the "fmt" chunk.
00417 
00418 Returns the number of bytes read + seeked.
00419 
00420 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
00421 be the total number of bytes you have read _plus_ seeked.
00422 
00423 Use the `container` argument to discriminate the fields in `pChunkHeader->id`. If the container is `drwav_container_riff` you should use `id.fourcc`,
00424 otherwise you should use `id.guid`.
00425 
00426 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
00427 `DR_WAVE_FORMAT_*` identifiers. 
00428 
00429 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.
00430 */
00431 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);
00432 
00433 typedef struct
00434 {
00435     void* pUserData;
00436     void* (* onMalloc)(size_t sz, void* pUserData);
00437     void* (* onRealloc)(void* p, size_t sz, void* pUserData);
00438     void  (* onFree)(void* p, void* pUserData);
00439 } drwav_allocation_callbacks;
00440 
00441 /* Structure for internal use. Only used for loaders opened with drwav_init_memory(). */
00442 typedef struct
00443 {
00444     const drwav_uint8* data;
00445     size_t dataSize;
00446     size_t currentReadPos;
00447 } drwav__memory_stream;
00448 
00449 /* Structure for internal use. Only used for writers opened with drwav_init_memory_write(). */
00450 typedef struct
00451 {
00452     void** ppData;
00453     size_t* pDataSize;
00454     size_t dataSize;
00455     size_t dataCapacity;
00456     size_t currentWritePos;
00457 } drwav__memory_stream_write;
00458 
00459 typedef struct
00460 {
00461     drwav_container container;  /* RIFF, W64. */
00462     drwav_uint32 format;        /* DR_WAVE_FORMAT_* */
00463     drwav_uint32 channels;
00464     drwav_uint32 sampleRate;
00465     drwav_uint32 bitsPerSample;
00466 } drwav_data_format;
00467 
00468 
00469 /* See the following for details on the 'smpl' chunk: https://sites.google.com/site/musicgapi/technical-documents/wav-file-format#smpl */
00470 typedef struct
00471 {
00472     drwav_uint32 cuePointId;
00473     drwav_uint32 type;
00474     drwav_uint32 start;
00475     drwav_uint32 end;
00476     drwav_uint32 fraction;
00477     drwav_uint32 playCount;
00478 } drwav_smpl_loop;
00479 
00480  typedef struct
00481 {
00482     drwav_uint32 manufacturer;
00483     drwav_uint32 product;
00484     drwav_uint32 samplePeriod;
00485     drwav_uint32 midiUnityNotes;
00486     drwav_uint32 midiPitchFraction;
00487     drwav_uint32 smpteFormat;
00488     drwav_uint32 smpteOffset;
00489     drwav_uint32 numSampleLoops;
00490     drwav_uint32 samplerData;
00491     drwav_smpl_loop loops[DRWAV_MAX_SMPL_LOOPS];
00492 } drwav_smpl;
00493 
00494 typedef struct
00495 {
00496     /* A pointer to the function to call when more data is needed. */
00497     drwav_read_proc onRead;
00498 
00499     /* A pointer to the function to call when data needs to be written. Only used when the drwav object is opened in write mode. */
00500     drwav_write_proc onWrite;
00501 
00502     /* A pointer to the function to call when the wav file needs to be seeked. */
00503     drwav_seek_proc onSeek;
00504 
00505     /* The user data to pass to callbacks. */
00506     void* pUserData;
00507 
00508     /* Allocation callbacks. */
00509     drwav_allocation_callbacks allocationCallbacks;
00510 
00511 
00512     /* Whether or not the WAV file is formatted as a standard RIFF file or W64. */
00513     drwav_container container;
00514 
00515 
00516     /* Structure containing format information exactly as specified by the wav file. */
00517     drwav_fmt fmt;
00518 
00519     /* The sample rate. Will be set to something like 44100. */
00520     drwav_uint32 sampleRate;
00521 
00522     /* The number of channels. This will be set to 1 for monaural streams, 2 for stereo, etc. */
00523     drwav_uint16 channels;
00524 
00525     /* The bits per sample. Will be set to something like 16, 24, etc. */
00526     drwav_uint16 bitsPerSample;
00527 
00528     /* Equal to fmt.formatTag, or the value specified by fmt.subFormat if fmt.formatTag is equal to 65534 (WAVE_FORMAT_EXTENSIBLE). */
00529     drwav_uint16 translatedFormatTag;
00530 
00531     /* The total number of PCM frames making up the audio data. */
00532     drwav_uint64 totalPCMFrameCount;
00533 
00534 
00535     /* The size in bytes of the data chunk. */
00536     drwav_uint64 dataChunkDataSize;
00537     
00538     /* The position in the stream of the first byte of the data chunk. This is used for seeking. */
00539     drwav_uint64 dataChunkDataPos;
00540 
00541     /* The number of bytes remaining in the data chunk. */
00542     drwav_uint64 bytesRemaining;
00543 
00544 
00545     /*
00546     Only used in sequential write mode. Keeps track of the desired size of the "data" chunk at the point of initialization time. Always
00547     set to 0 for non-sequential writes and when the drwav object is opened in read mode. Used for validation.
00548     */
00549     drwav_uint64 dataChunkDataSizeTargetWrite;
00550 
00551     /* Keeps track of whether or not the wav writer was initialized in sequential mode. */
00552     drwav_bool32 isSequentialWrite;
00553 
00554 
00555     /* smpl chunk. */
00556     drwav_smpl smpl;
00557 
00558 
00559     /* A hack to avoid a DRWAV_MALLOC() when opening a decoder with drwav_init_memory(). */
00560     drwav__memory_stream memoryStream;
00561     drwav__memory_stream_write memoryStreamWrite;
00562 
00563     /* Generic data for compressed formats. This data is shared across all block-compressed formats. */
00564     struct
00565     {
00566         drwav_uint64 iCurrentPCMFrame;  /* The index of the next PCM frame that will be read by drwav_read_*(). This is used with "totalPCMFrameCount" to ensure we don't read excess samples at the end of the last block. */
00567     } compressed;
00568     
00569     /* Microsoft ADPCM specific data. */
00570     struct
00571     {
00572         drwav_uint32 bytesRemainingInBlock;
00573         drwav_uint16 predictor[2];
00574         drwav_int32  delta[2];
00575         drwav_int32  cachedFrames[4];  /* Samples are stored in this cache during decoding. */
00576         drwav_uint32 cachedFrameCount;
00577         drwav_int32  prevFrames[2][2]; /* The previous 2 samples for each channel (2 channels at most). */
00578     } msadpcm;
00579 
00580     /* IMA ADPCM specific data. */
00581     struct
00582     {
00583         drwav_uint32 bytesRemainingInBlock;
00584         drwav_int32  predictor[2];
00585         drwav_int32  stepIndex[2];
00586         drwav_int32  cachedFrames[16]; /* Samples are stored in this cache during decoding. */
00587         drwav_uint32 cachedFrameCount;
00588     } ima;
00589 } drwav;
00590 
00591 
00592 /*
00593 Initializes a pre-allocated drwav object for reading.
00594 
00595 pWav                         [out]          A pointer to the drwav object being initialized.
00596 onRead                       [in]           The function to call when data needs to be read from the client.
00597 onSeek                       [in]           The function to call when the read position of the client data needs to move.
00598 onChunk                      [in, optional] The function to call when a chunk is enumerated at initialized time.
00599 pUserData, pReadSeekUserData [in, optional] A pointer to application defined data that will be passed to onRead and onSeek.
00600 pChunkUserData               [in, optional] A pointer to application defined data that will be passed to onChunk.
00601 flags                        [in, optional] A set of flags for controlling how things are loaded.
00602 
00603 Returns true if successful; false otherwise.
00604 
00605 Close the loader with drwav_uninit().
00606 
00607 This is the lowest level function for initializing a WAV file. You can also use drwav_init_file() and drwav_init_memory()
00608 to open the stream from a file or from a block of memory respectively.
00609 
00610 Possible values for flags:
00611   DRWAV_SEQUENTIAL: Never perform a backwards seek while loading. This disables the chunk callback and will cause this function
00612                     to return as soon as the data chunk is found. Any chunks after the data chunk will be ignored.
00613 
00614 drwav_init() is equivalent to "drwav_init_ex(pWav, onRead, onSeek, NULL, pUserData, NULL, 0);".
00615 
00616 The onChunk callback is not called for the WAVE or FMT chunks. The contents of the FMT chunk can be read from pWav->fmt
00617 after the function returns.
00618 
00619 See also: drwav_init_file(), drwav_init_memory(), drwav_uninit()
00620 */
00621 DRWAV_API drwav_bool32 drwav_init(drwav* pWav, drwav_read_proc onRead, drwav_seek_proc onSeek, void* pUserData, const drwav_allocation_callbacks* pAllocationCallbacks);
00622 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);
00623 
00624 /*
00625 Initializes a pre-allocated drwav object for writing.
00626 
00627 onWrite   [in]           The function to call when data needs to be written.
00628 onSeek    [in]           The function to call when the write position needs to move.
00629 pUserData [in, optional] A pointer to application defined data that will be passed to onWrite and onSeek.
00630 
00631 Returns true if successful; false otherwise.
00632 
00633 Close the writer with drwav_uninit().
00634 
00635 This is the lowest level function for initializing a WAV file. You can also use drwav_init_file_write() and drwav_init_memory_write()
00636 to open the stream from a file or from a block of memory respectively.
00637 
00638 If the total sample count is known, you can use drwav_init_write_sequential(). This avoids the need for dr_wav to perform
00639 a post-processing step for storing the total sample count and the size of the data chunk which requires a backwards seek.
00640 
00641 See also: drwav_init_file_write(), drwav_init_memory_write(), drwav_uninit()
00642 */
00643 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);
00644 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);
00645 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);
00646 
00647 /*
00648 Utility function to determine the target size of the entire data to be written (including all headers and chunks).
00649 
00650 Returns the target size in bytes.
00651 
00652 Useful if the application needs to know the size to allocate.
00653 
00654 Only writing to the RIFF chunk and one data chunk is currently supported.
00655 
00656 See also: drwav_init_write(), drwav_init_file_write(), drwav_init_memory_write()
00657 */
00658 DRWAV_API drwav_uint64 drwav_target_write_size_bytes(const drwav_data_format* pFormat, drwav_uint64 totalSampleCount);
00659 
00660 /*
00661 Uninitializes the given drwav object.
00662 
00663 Use this only for objects initialized with drwav_init*() functions (drwav_init(), drwav_init_ex(), drwav_init_write(), drwav_init_write_sequential()).
00664 */
00665 DRWAV_API drwav_result drwav_uninit(drwav* pWav);
00666 
00667 
00668 /*
00669 Reads raw audio data.
00670 
00671 This is the lowest level function for reading audio data. It simply reads the given number of
00672 bytes of the raw internal sample data.
00673 
00674 Consider using drwav_read_pcm_frames_s16(), drwav_read_pcm_frames_s32() or drwav_read_pcm_frames_f32() for
00675 reading sample data in a consistent format.
00676 
00677 Returns the number of bytes actually read.
00678 */
00679 DRWAV_API size_t drwav_read_raw(drwav* pWav, size_t bytesToRead, void* pBufferOut);
00680 
00681 /*
00682 Reads up to the specified number of PCM frames from the WAV file.
00683 
00684 The output data will be in the file's internal format, converted to native-endian byte order. Use
00685 drwav_read_pcm_frames_s16/f32/s32() to read data in a specific format.
00686 
00687 If the return value is less than <framesToRead> it means the end of the file has been reached or
00688 you have requested more PCM frames than can possibly fit in the output buffer.
00689 
00690 This function will only work when sample data is of a fixed size and uncompressed. If you are
00691 using a compressed format consider using drwav_read_raw() or drwav_read_pcm_frames_s16/s32/f32().
00692 */
00693 DRWAV_API drwav_uint64 drwav_read_pcm_frames(drwav* pWav, drwav_uint64 framesToRead, void* pBufferOut);
00694 DRWAV_API drwav_uint64 drwav_read_pcm_frames_le(drwav* pWav, drwav_uint64 framesToRead, void* pBufferOut);
00695 DRWAV_API drwav_uint64 drwav_read_pcm_frames_be(drwav* pWav, drwav_uint64 framesToRead, void* pBufferOut);
00696 
00697 /*
00698 Seeks to the given PCM frame.
00699 
00700 Returns true if successful; false otherwise.
00701 */
00702 DRWAV_API drwav_bool32 drwav_seek_to_pcm_frame(drwav* pWav, drwav_uint64 targetFrameIndex);
00703 
00704 
00705 /*
00706 Writes raw audio data.
00707 
00708 Returns the number of bytes actually written. If this differs from bytesToWrite, it indicates an error.
00709 */
00710 DRWAV_API size_t drwav_write_raw(drwav* pWav, size_t bytesToWrite, const void* pData);
00711 
00712 /*
00713 Writes PCM frames.
00714 
00715 Returns the number of PCM frames written.
00716 
00717 Input samples need to be in native-endian byte order. On big-endian architectures the input data will be converted to
00718 little-endian. Use drwav_write_raw() to write raw audio data without performing any conversion.
00719 */
00720 DRWAV_API drwav_uint64 drwav_write_pcm_frames(drwav* pWav, drwav_uint64 framesToWrite, const void* pData);
00721 DRWAV_API drwav_uint64 drwav_write_pcm_frames_le(drwav* pWav, drwav_uint64 framesToWrite, const void* pData);
00722 DRWAV_API drwav_uint64 drwav_write_pcm_frames_be(drwav* pWav, drwav_uint64 framesToWrite, const void* pData);
00723 
00724 
00725 /* Conversion Utilities */
00726 #ifndef DR_WAV_NO_CONVERSION_API
00727 
00728 /*
00729 Reads a chunk of audio data and converts it to signed 16-bit PCM samples.
00730 
00731 Returns the number of PCM frames actually read.
00732 
00733 If the return value is less than <framesToRead> it means the end of the file has been reached.
00734 */
00735 DRWAV_API drwav_uint64 drwav_read_pcm_frames_s16(drwav* pWav, drwav_uint64 framesToRead, drwav_int16* pBufferOut);
00736 DRWAV_API drwav_uint64 drwav_read_pcm_frames_s16le(drwav* pWav, drwav_uint64 framesToRead, drwav_int16* pBufferOut);
00737 DRWAV_API drwav_uint64 drwav_read_pcm_frames_s16be(drwav* pWav, drwav_uint64 framesToRead, drwav_int16* pBufferOut);
00738 
00739 /* Low-level function for converting unsigned 8-bit PCM samples to signed 16-bit PCM samples. */
00740 DRWAV_API void drwav_u8_to_s16(drwav_int16* pOut, const drwav_uint8* pIn, size_t sampleCount);
00741 
00742 /* Low-level function for converting signed 24-bit PCM samples to signed 16-bit PCM samples. */
00743 DRWAV_API void drwav_s24_to_s16(drwav_int16* pOut, const drwav_uint8* pIn, size_t sampleCount);
00744 
00745 /* Low-level function for converting signed 32-bit PCM samples to signed 16-bit PCM samples. */
00746 DRWAV_API void drwav_s32_to_s16(drwav_int16* pOut, const drwav_int32* pIn, size_t sampleCount);
00747 
00748 /* Low-level function for converting IEEE 32-bit floating point samples to signed 16-bit PCM samples. */
00749 DRWAV_API void drwav_f32_to_s16(drwav_int16* pOut, const float* pIn, size_t sampleCount);
00750 
00751 /* Low-level function for converting IEEE 64-bit floating point samples to signed 16-bit PCM samples. */
00752 DRWAV_API void drwav_f64_to_s16(drwav_int16* pOut, const double* pIn, size_t sampleCount);
00753 
00754 /* Low-level function for converting A-law samples to signed 16-bit PCM samples. */
00755 DRWAV_API void drwav_alaw_to_s16(drwav_int16* pOut, const drwav_uint8* pIn, size_t sampleCount);
00756 
00757 /* Low-level function for converting u-law samples to signed 16-bit PCM samples. */
00758 DRWAV_API void drwav_mulaw_to_s16(drwav_int16* pOut, const drwav_uint8* pIn, size_t sampleCount);
00759 
00760 
00761 /*
00762 Reads a chunk of audio data and converts it to IEEE 32-bit floating point samples.
00763 
00764 Returns the number of PCM frames actually read.
00765 
00766 If the return value is less than <framesToRead> it means the end of the file has been reached.
00767 */
00768 DRWAV_API drwav_uint64 drwav_read_pcm_frames_f32(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut);
00769 DRWAV_API drwav_uint64 drwav_read_pcm_frames_f32le(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut);
00770 DRWAV_API drwav_uint64 drwav_read_pcm_frames_f32be(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut);
00771 
00772 /* Low-level function for converting unsigned 8-bit PCM samples to IEEE 32-bit floating point samples. */
00773 DRWAV_API void drwav_u8_to_f32(float* pOut, const drwav_uint8* pIn, size_t sampleCount);
00774 
00775 /* Low-level function for converting signed 16-bit PCM samples to IEEE 32-bit floating point samples. */
00776 DRWAV_API void drwav_s16_to_f32(float* pOut, const drwav_int16* pIn, size_t sampleCount);
00777 
00778 /* Low-level function for converting signed 24-bit PCM samples to IEEE 32-bit floating point samples. */
00779 DRWAV_API void drwav_s24_to_f32(float* pOut, const drwav_uint8* pIn, size_t sampleCount);
00780 
00781 /* Low-level function for converting signed 32-bit PCM samples to IEEE 32-bit floating point samples. */
00782 DRWAV_API void drwav_s32_to_f32(float* pOut, const drwav_int32* pIn, size_t sampleCount);
00783 
00784 /* Low-level function for converting IEEE 64-bit floating point samples to IEEE 32-bit floating point samples. */
00785 DRWAV_API void drwav_f64_to_f32(float* pOut, const double* pIn, size_t sampleCount);
00786 
00787 /* Low-level function for converting A-law samples to IEEE 32-bit floating point samples. */
00788 DRWAV_API void drwav_alaw_to_f32(float* pOut, const drwav_uint8* pIn, size_t sampleCount);
00789 
00790 /* Low-level function for converting u-law samples to IEEE 32-bit floating point samples. */
00791 DRWAV_API void drwav_mulaw_to_f32(float* pOut, const drwav_uint8* pIn, size_t sampleCount);
00792 
00793 
00794 /*
00795 Reads a chunk of audio data and converts it to signed 32-bit PCM samples.
00796 
00797 Returns the number of PCM frames actually read.
00798 
00799 If the return value is less than <framesToRead> it means the end of the file has been reached.
00800 */
00801 DRWAV_API drwav_uint64 drwav_read_pcm_frames_s32(drwav* pWav, drwav_uint64 framesToRead, drwav_int32* pBufferOut);
00802 DRWAV_API drwav_uint64 drwav_read_pcm_frames_s32le(drwav* pWav, drwav_uint64 framesToRead, drwav_int32* pBufferOut);
00803 DRWAV_API drwav_uint64 drwav_read_pcm_frames_s32be(drwav* pWav, drwav_uint64 framesToRead, drwav_int32* pBufferOut);
00804 
00805 /* Low-level function for converting unsigned 8-bit PCM samples to signed 32-bit PCM samples. */
00806 DRWAV_API void drwav_u8_to_s32(drwav_int32* pOut, const drwav_uint8* pIn, size_t sampleCount);
00807 
00808 /* Low-level function for converting signed 16-bit PCM samples to signed 32-bit PCM samples. */
00809 DRWAV_API void drwav_s16_to_s32(drwav_int32* pOut, const drwav_int16* pIn, size_t sampleCount);
00810 
00811 /* Low-level function for converting signed 24-bit PCM samples to signed 32-bit PCM samples. */
00812 DRWAV_API void drwav_s24_to_s32(drwav_int32* pOut, const drwav_uint8* pIn, size_t sampleCount);
00813 
00814 /* Low-level function for converting IEEE 32-bit floating point samples to signed 32-bit PCM samples. */
00815 DRWAV_API void drwav_f32_to_s32(drwav_int32* pOut, const float* pIn, size_t sampleCount);
00816 
00817 /* Low-level function for converting IEEE 64-bit floating point samples to signed 32-bit PCM samples. */
00818 DRWAV_API void drwav_f64_to_s32(drwav_int32* pOut, const double* pIn, size_t sampleCount);
00819 
00820 /* Low-level function for converting A-law samples to signed 32-bit PCM samples. */
00821 DRWAV_API void drwav_alaw_to_s32(drwav_int32* pOut, const drwav_uint8* pIn, size_t sampleCount);
00822 
00823 /* Low-level function for converting u-law samples to signed 32-bit PCM samples. */
00824 DRWAV_API void drwav_mulaw_to_s32(drwav_int32* pOut, const drwav_uint8* pIn, size_t sampleCount);
00825 
00826 #endif  /* DR_WAV_NO_CONVERSION_API */
00827 
00828 
00829 /* High-Level Convenience Helpers */
00830 
00831 #ifndef DR_WAV_NO_STDIO
00832 /*
00833 Helper for initializing a wave file for reading using stdio.
00834 
00835 This holds the internal FILE object until drwav_uninit() is called. Keep this in mind if you're caching drwav
00836 objects because the operating system may restrict the number of file handles an application can have open at
00837 any given time.
00838 */
00839 DRWAV_API drwav_bool32 drwav_init_file(drwav* pWav, const char* filename, const drwav_allocation_callbacks* pAllocationCallbacks);
00840 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);
00841 DRWAV_API drwav_bool32 drwav_init_file_w(drwav* pWav, const wchar_t* filename, const drwav_allocation_callbacks* pAllocationCallbacks);
00842 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);
00843 
00844 /*
00845 Helper for initializing a wave file for writing using stdio.
00846 
00847 This holds the internal FILE object until drwav_uninit() is called. Keep this in mind if you're caching drwav
00848 objects because the operating system may restrict the number of file handles an application can have open at
00849 any given time.
00850 */
00851 DRWAV_API drwav_bool32 drwav_init_file_write(drwav* pWav, const char* filename, const drwav_data_format* pFormat, const drwav_allocation_callbacks* pAllocationCallbacks);
00852 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);
00853 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);
00854 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);
00855 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);
00856 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);
00857 #endif  /* DR_WAV_NO_STDIO */
00858 
00859 /*
00860 Helper for initializing a loader from a pre-allocated memory buffer.
00861 
00862 This does not create a copy of the data. It is up to the application to ensure the buffer remains valid for
00863 the lifetime of the drwav object.
00864 
00865 The buffer should contain the contents of the entire wave file, not just the sample data.
00866 */
00867 DRWAV_API drwav_bool32 drwav_init_memory(drwav* pWav, const void* data, size_t dataSize, const drwav_allocation_callbacks* pAllocationCallbacks);
00868 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);
00869 
00870 /*
00871 Helper for initializing a writer which outputs data to a memory buffer.
00872 
00873 dr_wav will manage the memory allocations, however it is up to the caller to free the data with drwav_free().
00874 
00875 The buffer will remain allocated even after drwav_uninit() is called. Indeed, the buffer should not be
00876 considered valid until after drwav_uninit() has been called anyway.
00877 */
00878 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);
00879 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);
00880 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);
00881 
00882 
00883 #ifndef DR_WAV_NO_CONVERSION_API
00884 /*
00885 Opens and reads an entire wav file in a single operation.
00886 
00887 The return value is a heap-allocated buffer containing the audio data. Use drwav_free() to free the buffer.
00888 */
00889 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);
00890 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);
00891 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);
00892 #ifndef DR_WAV_NO_STDIO
00893 /*
00894 Opens and decodes an entire wav file in a single operation.
00895 
00896 The return value is a heap-allocated buffer containing the audio data. Use drwav_free() to free the buffer.
00897 */
00898 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);
00899 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);
00900 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);
00901 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);
00902 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);
00903 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);
00904 #endif
00905 /*
00906 Opens and decodes an entire wav file from a block of memory in a single operation.
00907 
00908 The return value is a heap-allocated buffer containing the audio data. Use drwav_free() to free the buffer.
00909 */
00910 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);
00911 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);
00912 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);
00913 #endif
00914 
00915 /* Frees data that was allocated internally by dr_wav. */
00916 DRWAV_API void drwav_free(void* p, const drwav_allocation_callbacks* pAllocationCallbacks);
00917 
00918 /* Converts bytes from a wav stream to a sized type of native endian. */
00919 DRWAV_API drwav_uint16 drwav_bytes_to_u16(const drwav_uint8* data);
00920 DRWAV_API drwav_int16 drwav_bytes_to_s16(const drwav_uint8* data);
00921 DRWAV_API drwav_uint32 drwav_bytes_to_u32(const drwav_uint8* data);
00922 DRWAV_API drwav_int32 drwav_bytes_to_s32(const drwav_uint8* data);
00923 DRWAV_API drwav_uint64 drwav_bytes_to_u64(const drwav_uint8* data);
00924 DRWAV_API drwav_int64 drwav_bytes_to_s64(const drwav_uint8* data);
00925 
00926 /* Compares a GUID for the purpose of checking the type of a Wave64 chunk. */
00927 DRWAV_API drwav_bool32 drwav_guid_equal(const drwav_uint8 a[16], const drwav_uint8 b[16]);
00928 
00929 /* Compares a four-character-code for the purpose of checking the type of a RIFF chunk. */
00930 DRWAV_API drwav_bool32 drwav_fourcc_equal(const drwav_uint8* a, const char* b);
00931 
00932 #ifdef __cplusplus
00933 }
00934 #endif
00935 #endif  /* dr_wav_h */
00936 
00937 
00938 /************************************************************************************************************************************************************
00939  ************************************************************************************************************************************************************
00940 
00941  IMPLEMENTATION
00942 
00943  ************************************************************************************************************************************************************
00944  ************************************************************************************************************************************************************/
00945 #if defined(DR_WAV_IMPLEMENTATION) || defined(DRWAV_IMPLEMENTATION)
00946 #include <stdlib.h>
00947 #include <string.h> /* For memcpy(), memset() */
00948 #include <limits.h> /* For INT_MAX */
00949 
00950 #ifndef DR_WAV_NO_STDIO
00951 #include <stdio.h>
00952 #include <wchar.h>
00953 #endif
00954 
00955 /* Standard library stuff. */
00956 #ifndef DRWAV_ASSERT
00957 #include <assert.h>
00958 #define DRWAV_ASSERT(expression)           assert(expression)
00959 #endif
00960 #ifndef DRWAV_MALLOC
00961 #define DRWAV_MALLOC(sz)                   malloc((sz))
00962 #endif
00963 #ifndef DRWAV_REALLOC
00964 #define DRWAV_REALLOC(p, sz)               realloc((p), (sz))
00965 #endif
00966 #ifndef DRWAV_FREE
00967 #define DRWAV_FREE(p)                      free((p))
00968 #endif
00969 #ifndef DRWAV_COPY_MEMORY
00970 #define DRWAV_COPY_MEMORY(dst, src, sz)    memcpy((dst), (src), (sz))
00971 #endif
00972 #ifndef DRWAV_ZERO_MEMORY
00973 #define DRWAV_ZERO_MEMORY(p, sz)           memset((p), 0, (sz))
00974 #endif
00975 #ifndef DRWAV_ZERO_OBJECT
00976 #define DRWAV_ZERO_OBJECT(p)               DRWAV_ZERO_MEMORY((p), sizeof(*p))
00977 #endif
00978 
00979 #define drwav_countof(x)                   (sizeof(x) / sizeof(x[0]))
00980 #define drwav_align(x, a)                  ((((x) + (a) - 1) / (a)) * (a))
00981 #define drwav_min(a, b)                    (((a) < (b)) ? (a) : (b))
00982 #define drwav_max(a, b)                    (((a) > (b)) ? (a) : (b))
00983 #define drwav_clamp(x, lo, hi)             (drwav_max((lo), drwav_min((hi), (x))))
00984 
00985 #define DRWAV_MAX_SIMD_VECTOR_SIZE         64  /* 64 for AVX-512 in the future. */
00986 
00987 /* CPU architecture. */
00988 #if defined(__x86_64__) || defined(_M_X64)
00989     #define DRWAV_X64
00990 #elif defined(__i386) || defined(_M_IX86)
00991     #define DRWAV_X86
00992 #elif defined(__arm__) || defined(_M_ARM)
00993     #define DRWAV_ARM
00994 #endif
00995 
00996 #ifdef _MSC_VER
00997     #define DRWAV_INLINE __forceinline
00998 #elif defined(__GNUC__)
00999     /*
01000     I've had a bug report where GCC is emitting warnings about functions possibly not being inlineable. This warning happens when
01001     the __attribute__((always_inline)) attribute is defined without an "inline" statement. I think therefore there must be some
01002     case where "__inline__" is not always defined, thus the compiler emitting these warnings. When using -std=c89 or -ansi on the
01003     command line, we cannot use the "inline" keyword and instead need to use "__inline__". In an attempt to work around this issue
01004     I am using "__inline__" only when we're compiling in strict ANSI mode.
01005     */
01006     #if defined(__STRICT_ANSI__)
01007         #define DRWAV_INLINE __inline__ __attribute__((always_inline))
01008     #else
01009         #define DRWAV_INLINE inline __attribute__((always_inline))
01010     #endif
01011 #else
01012     #define DRWAV_INLINE
01013 #endif
01014 
01015 #if defined(SIZE_MAX)
01016     #define DRWAV_SIZE_MAX  SIZE_MAX
01017 #else
01018     #if defined(_WIN64) || defined(_LP64) || defined(__LP64__)
01019         #define DRWAV_SIZE_MAX  ((drwav_uint64)0xFFFFFFFFFFFFFFFF)
01020     #else
01021         #define DRWAV_SIZE_MAX  0xFFFFFFFF
01022     #endif
01023 #endif
01024 
01025 #if defined(_MSC_VER) && _MSC_VER >= 1400
01026     #define DRWAV_HAS_BYTESWAP16_INTRINSIC
01027     #define DRWAV_HAS_BYTESWAP32_INTRINSIC
01028     #define DRWAV_HAS_BYTESWAP64_INTRINSIC
01029 #elif defined(__clang__)
01030     #if defined(__has_builtin)
01031         #if __has_builtin(__builtin_bswap16)
01032             #define DRWAV_HAS_BYTESWAP16_INTRINSIC
01033         #endif
01034         #if __has_builtin(__builtin_bswap32)
01035             #define DRWAV_HAS_BYTESWAP32_INTRINSIC
01036         #endif
01037         #if __has_builtin(__builtin_bswap64)
01038             #define DRWAV_HAS_BYTESWAP64_INTRINSIC
01039         #endif
01040     #endif
01041 #elif defined(__GNUC__)
01042     #if ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
01043         #define DRWAV_HAS_BYTESWAP32_INTRINSIC
01044         #define DRWAV_HAS_BYTESWAP64_INTRINSIC
01045     #endif
01046     #if ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))
01047         #define DRWAV_HAS_BYTESWAP16_INTRINSIC
01048     #endif
01049 #endif
01050 
01051 DRWAV_API void drwav_version(drwav_uint32* pMajor, drwav_uint32* pMinor, drwav_uint32* pRevision)
01052 {
01053     if (pMajor) {
01054         *pMajor = DRWAV_VERSION_MAJOR;
01055     }
01056 
01057     if (pMinor) {
01058         *pMinor = DRWAV_VERSION_MINOR;
01059     }
01060 
01061     if (pRevision) {
01062         *pRevision = DRWAV_VERSION_REVISION;
01063     }
01064 }
01065 
01066 DRWAV_API const char* drwav_version_string()
01067 {
01068     return DRWAV_VERSION_STRING;
01069 }
01070 
01071 /*
01072 These limits are used for basic validation when initializing the decoder. If you exceed these limits, first of all: what on Earth are
01073 you doing?! (Let me know, I'd be curious!) Second, you can adjust these by #define-ing them before the dr_wav implementation.
01074 */
01075 #ifndef DRWAV_MAX_SAMPLE_RATE
01076 #define DRWAV_MAX_SAMPLE_RATE       384000
01077 #endif
01078 #ifndef DRWAV_MAX_CHANNELS
01079 #define DRWAV_MAX_CHANNELS          256
01080 #endif
01081 #ifndef DRWAV_MAX_BITS_PER_SAMPLE
01082 #define DRWAV_MAX_BITS_PER_SAMPLE   64
01083 #endif
01084 
01085 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 */
01086 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 */
01087 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 */
01088 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 */
01089 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 */
01090 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 */
01091 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 */
01092 
01093 static DRWAV_INLINE drwav_bool32 drwav__guid_equal(const drwav_uint8 a[16], const drwav_uint8 b[16])
01094 {
01095     int i;
01096     for (i = 0; i < 16; i += 1) {
01097         if (a[i] != b[i]) {
01098             return DRWAV_FALSE;
01099         }
01100     }
01101 
01102     return DRWAV_TRUE;
01103 }
01104 
01105 static DRWAV_INLINE drwav_bool32 drwav__fourcc_equal(const drwav_uint8* a, const char* b)
01106 {
01107     return
01108         a[0] == b[0] &&
01109         a[1] == b[1] &&
01110         a[2] == b[2] &&
01111         a[3] == b[3];
01112 }
01113 
01114 
01115 
01116 static DRWAV_INLINE int drwav__is_little_endian(void)
01117 {
01118 #if defined(DRWAV_X86) || defined(DRWAV_X64)
01119     return DRWAV_TRUE;
01120 #elif defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && __BYTE_ORDER == __LITTLE_ENDIAN
01121     return DRWAV_TRUE;
01122 #else
01123     int n = 1;
01124     return (*(char*)&n) == 1;
01125 #endif
01126 }
01127 
01128 static DRWAV_INLINE drwav_uint16 drwav__bytes_to_u16(const drwav_uint8* data)
01129 {
01130     return (data[0] << 0) | (data[1] << 8);
01131 }
01132 
01133 static DRWAV_INLINE drwav_int16 drwav__bytes_to_s16(const drwav_uint8* data)
01134 {
01135     return (short)drwav__bytes_to_u16(data);
01136 }
01137 
01138 static DRWAV_INLINE drwav_uint32 drwav__bytes_to_u32(const drwav_uint8* data)
01139 {
01140     return (data[0] << 0) | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
01141 }
01142 
01143 static DRWAV_INLINE drwav_int32 drwav__bytes_to_s32(const drwav_uint8* data)
01144 {
01145     return (drwav_int32)drwav__bytes_to_u32(data);
01146 }
01147 
01148 static DRWAV_INLINE drwav_uint64 drwav__bytes_to_u64(const drwav_uint8* data)
01149 {
01150     return
01151         ((drwav_uint64)data[0] <<  0) | ((drwav_uint64)data[1] <<  8) | ((drwav_uint64)data[2] << 16) | ((drwav_uint64)data[3] << 24) |
01152         ((drwav_uint64)data[4] << 32) | ((drwav_uint64)data[5] << 40) | ((drwav_uint64)data[6] << 48) | ((drwav_uint64)data[7] << 56);
01153 }
01154 
01155 static DRWAV_INLINE drwav_int64 drwav__bytes_to_s64(const drwav_uint8* data)
01156 {
01157     return (drwav_int64)drwav__bytes_to_u64(data);
01158 }
01159 
01160 static DRWAV_INLINE void drwav__bytes_to_guid(const drwav_uint8* data, drwav_uint8* guid)
01161 {
01162     int i;
01163     for (i = 0; i < 16; ++i) {
01164         guid[i] = data[i];
01165     }
01166 }
01167 
01168 
01169 static DRWAV_INLINE drwav_uint16 drwav__bswap16(drwav_uint16 n)
01170 {
01171 #ifdef DRWAV_HAS_BYTESWAP16_INTRINSIC
01172     #if defined(_MSC_VER)
01173         return _byteswap_ushort(n);
01174     #elif defined(__GNUC__) || defined(__clang__)
01175         return __builtin_bswap16(n);
01176     #else
01177         #error "This compiler does not support the byte swap intrinsic."
01178     #endif
01179 #else
01180     return ((n & 0xFF00) >> 8) |
01181            ((n & 0x00FF) << 8);
01182 #endif
01183 }
01184 
01185 static DRWAV_INLINE drwav_uint32 drwav__bswap32(drwav_uint32 n)
01186 {
01187 #ifdef DRWAV_HAS_BYTESWAP32_INTRINSIC
01188     #if defined(_MSC_VER)
01189         return _byteswap_ulong(n);
01190     #elif defined(__GNUC__) || defined(__clang__)
01191         #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. */
01192             /* Inline assembly optimized implementation for ARM. In my testing, GCC does not generate optimized code with __builtin_bswap32(). */
01193             drwav_uint32 r;
01194             __asm__ __volatile__ (
01195             #if defined(DRWAV_64BIT)
01196                 "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! */
01197             #else
01198                 "rev %[out], %[in]" : [out]"=r"(r) : [in]"r"(n)
01199             #endif
01200             );
01201             return r;
01202         #else
01203             return __builtin_bswap32(n);
01204         #endif
01205     #else
01206         #error "This compiler does not support the byte swap intrinsic."
01207     #endif
01208 #else
01209     return ((n & 0xFF000000) >> 24) |
01210            ((n & 0x00FF0000) >>  8) |
01211            ((n & 0x0000FF00) <<  8) |
01212            ((n & 0x000000FF) << 24);
01213 #endif
01214 }
01215 
01216 static DRWAV_INLINE drwav_uint64 drwav__bswap64(drwav_uint64 n)
01217 {
01218 #ifdef DRWAV_HAS_BYTESWAP64_INTRINSIC
01219     #if defined(_MSC_VER)
01220         return _byteswap_uint64(n);
01221     #elif defined(__GNUC__) || defined(__clang__)
01222         return __builtin_bswap64(n);
01223     #else
01224         #error "This compiler does not support the byte swap intrinsic."
01225     #endif
01226 #else
01227     return ((n & (drwav_uint64)0xFF00000000000000) >> 56) |
01228            ((n & (drwav_uint64)0x00FF000000000000) >> 40) |
01229            ((n & (drwav_uint64)0x0000FF0000000000) >> 24) |
01230            ((n & (drwav_uint64)0x000000FF00000000) >>  8) |
01231            ((n & (drwav_uint64)0x00000000FF000000) <<  8) |
01232            ((n & (drwav_uint64)0x0000000000FF0000) << 24) |
01233            ((n & (drwav_uint64)0x000000000000FF00) << 40) |
01234            ((n & (drwav_uint64)0x00000000000000FF) << 56);
01235 #endif
01236 }
01237 
01238 
01239 static DRWAV_INLINE drwav_int16 drwav__bswap_s16(drwav_int16 n)
01240 {
01241     return (drwav_int16)drwav__bswap16((drwav_uint16)n);
01242 }
01243 
01244 static DRWAV_INLINE void drwav__bswap_samples_s16(drwav_int16* pSamples, drwav_uint64 sampleCount)
01245 {
01246     drwav_uint64 iSample;
01247     for (iSample = 0; iSample < sampleCount; iSample += 1) {
01248         pSamples[iSample] = drwav__bswap_s16(pSamples[iSample]);
01249     }
01250 }
01251 
01252 
01253 static DRWAV_INLINE void drwav__bswap_s24(drwav_uint8* p)
01254 {
01255     drwav_uint8 t;
01256     t = p[0];
01257     p[0] = p[2];
01258     p[2] = t;
01259 }
01260 
01261 static DRWAV_INLINE void drwav__bswap_samples_s24(drwav_uint8* pSamples, drwav_uint64 sampleCount)
01262 {
01263     drwav_uint64 iSample;
01264     for (iSample = 0; iSample < sampleCount; iSample += 1) {
01265         drwav_uint8* pSample = pSamples + (iSample*3);
01266         drwav__bswap_s24(pSample);
01267     }
01268 }
01269 
01270 
01271 static DRWAV_INLINE drwav_int32 drwav__bswap_s32(drwav_int32 n)
01272 {
01273     return (drwav_int32)drwav__bswap32((drwav_uint32)n);
01274 }
01275 
01276 static DRWAV_INLINE void drwav__bswap_samples_s32(drwav_int32* pSamples, drwav_uint64 sampleCount)
01277 {
01278     drwav_uint64 iSample;
01279     for (iSample = 0; iSample < sampleCount; iSample += 1) {
01280         pSamples[iSample] = drwav__bswap_s32(pSamples[iSample]);
01281     }
01282 }
01283 
01284 
01285 static DRWAV_INLINE float drwav__bswap_f32(float n)
01286 {
01287     union {
01288         drwav_uint32 i;
01289         float f;
01290     } x;
01291     x.f = n;
01292     x.i = drwav__bswap32(x.i);
01293 
01294     return x.f;
01295 }
01296 
01297 static DRWAV_INLINE void drwav__bswap_samples_f32(float* pSamples, drwav_uint64 sampleCount)
01298 {
01299     drwav_uint64 iSample;
01300     for (iSample = 0; iSample < sampleCount; iSample += 1) {
01301         pSamples[iSample] = drwav__bswap_f32(pSamples[iSample]);
01302     }
01303 }
01304 
01305 
01306 static DRWAV_INLINE double drwav__bswap_f64(double n)
01307 {
01308     union {
01309         drwav_uint64 i;
01310         double f;
01311     } x;
01312     x.f = n;
01313     x.i = drwav__bswap64(x.i);
01314 
01315     return x.f;
01316 }
01317 
01318 static DRWAV_INLINE void drwav__bswap_samples_f64(double* pSamples, drwav_uint64 sampleCount)
01319 {
01320     drwav_uint64 iSample;
01321     for (iSample = 0; iSample < sampleCount; iSample += 1) {
01322         pSamples[iSample] = drwav__bswap_f64(pSamples[iSample]);
01323     }
01324 }
01325 
01326 
01327 static DRWAV_INLINE void drwav__bswap_samples_pcm(void* pSamples, drwav_uint64 sampleCount, drwav_uint32 bytesPerSample)
01328 {
01329     /* Assumes integer PCM. Floating point PCM is done in drwav__bswap_samples_ieee(). */
01330     switch (bytesPerSample)
01331     {
01332         case 2: /* s16, s12 (loosely packed) */
01333         {
01334             drwav__bswap_samples_s16((drwav_int16*)pSamples, sampleCount);
01335         } break;
01336         case 3: /* s24 */
01337         {
01338             drwav__bswap_samples_s24((drwav_uint8*)pSamples, sampleCount);
01339         } break;
01340         case 4: /* s32 */
01341         {
01342             drwav__bswap_samples_s32((drwav_int32*)pSamples, sampleCount);
01343         } break;
01344         default:
01345         {
01346             /* Unsupported format. */
01347             DRWAV_ASSERT(DRWAV_FALSE);
01348         } break;
01349     }
01350 }
01351 
01352 static DRWAV_INLINE void drwav__bswap_samples_ieee(void* pSamples, drwav_uint64 sampleCount, drwav_uint32 bytesPerSample)
01353 {
01354     switch (bytesPerSample)
01355     {
01356     #if 0   /* Contributions welcome for f16 support. */
01357         case 2: /* f16 */
01358         {
01359             drwav__bswap_samples_f16((drwav_float16*)pSamples, sampleCount);
01360         } break;
01361     #endif
01362         case 4: /* f32 */
01363         {
01364             drwav__bswap_samples_f32((float*)pSamples, sampleCount);
01365         } break;
01366         case 8: /* f64 */
01367         {
01368             drwav__bswap_samples_f64((double*)pSamples, sampleCount);
01369         } break;
01370         default:
01371         {
01372             /* Unsupported format. */
01373             DRWAV_ASSERT(DRWAV_FALSE);
01374         } break;
01375     }
01376 }
01377 
01378 static DRWAV_INLINE void drwav__bswap_samples(void* pSamples, drwav_uint64 sampleCount, drwav_uint32 bytesPerSample, drwav_uint16 format)
01379 {
01380     switch (format)
01381     {
01382         case DR_WAVE_FORMAT_PCM:
01383         {
01384             drwav__bswap_samples_pcm(pSamples, sampleCount, bytesPerSample);
01385         } break;
01386 
01387         case DR_WAVE_FORMAT_IEEE_FLOAT:
01388         {
01389             drwav__bswap_samples_ieee(pSamples, sampleCount, bytesPerSample);
01390         } break;
01391 
01392         case DR_WAVE_FORMAT_ALAW:
01393         case DR_WAVE_FORMAT_MULAW:
01394         {
01395             drwav__bswap_samples_s16((drwav_int16*)pSamples, sampleCount);
01396         } break;
01397 
01398         case DR_WAVE_FORMAT_ADPCM:
01399         case DR_WAVE_FORMAT_DVI_ADPCM:
01400         default:
01401         {
01402             /* Unsupported format. */
01403             DRWAV_ASSERT(DRWAV_FALSE);
01404         } break;
01405     }
01406 }
01407 
01408 
01409 static void* drwav__malloc_default(size_t sz, void* pUserData)
01410 {
01411     (void)pUserData;
01412     return DRWAV_MALLOC(sz);
01413 }
01414 
01415 static void* drwav__realloc_default(void* p, size_t sz, void* pUserData)
01416 {
01417     (void)pUserData;
01418     return DRWAV_REALLOC(p, sz);
01419 }
01420 
01421 static void drwav__free_default(void* p, void* pUserData)
01422 {
01423     (void)pUserData;
01424     DRWAV_FREE(p);
01425 }
01426 
01427 
01428 static void* drwav__malloc_from_callbacks(size_t sz, const drwav_allocation_callbacks* pAllocationCallbacks)
01429 {
01430     if (pAllocationCallbacks == NULL) {
01431         return NULL;
01432     }
01433 
01434     if (pAllocationCallbacks->onMalloc != NULL) {
01435         return pAllocationCallbacks->onMalloc(sz, pAllocationCallbacks->pUserData);
01436     }
01437 
01438     /* Try using realloc(). */
01439     if (pAllocationCallbacks->onRealloc != NULL) {
01440         return pAllocationCallbacks->onRealloc(NULL, sz, pAllocationCallbacks->pUserData);
01441     }
01442 
01443     return NULL;
01444 }
01445 
01446 static void* drwav__realloc_from_callbacks(void* p, size_t szNew, size_t szOld, const drwav_allocation_callbacks* pAllocationCallbacks)
01447 {
01448     if (pAllocationCallbacks == NULL) {
01449         return NULL;
01450     }
01451 
01452     if (pAllocationCallbacks->onRealloc != NULL) {
01453         return pAllocationCallbacks->onRealloc(p, szNew, pAllocationCallbacks->pUserData);
01454     }
01455 
01456     /* Try emulating realloc() in terms of malloc()/free(). */
01457     if (pAllocationCallbacks->onMalloc != NULL && pAllocationCallbacks->onFree != NULL) {
01458         void* p2;
01459 
01460         p2 = pAllocationCallbacks->onMalloc(szNew, pAllocationCallbacks->pUserData);
01461         if (p2 == NULL) {
01462             return NULL;
01463         }
01464 
01465         if (p != NULL) {
01466             DRWAV_COPY_MEMORY(p2, p, szOld);
01467             pAllocationCallbacks->onFree(p, pAllocationCallbacks->pUserData);
01468         }
01469 
01470         return p2;
01471     }
01472 
01473     return NULL;
01474 }
01475 
01476 static void drwav__free_from_callbacks(void* p, const drwav_allocation_callbacks* pAllocationCallbacks)
01477 {
01478     if (p == NULL || pAllocationCallbacks == NULL) {
01479         return;
01480     }
01481 
01482     if (pAllocationCallbacks->onFree != NULL) {
01483         pAllocationCallbacks->onFree(p, pAllocationCallbacks->pUserData);
01484     }
01485 }
01486 
01487 
01488 static drwav_allocation_callbacks drwav_copy_allocation_callbacks_or_defaults(const drwav_allocation_callbacks* pAllocationCallbacks)
01489 {
01490     if (pAllocationCallbacks != NULL) {
01491         /* Copy. */
01492         return *pAllocationCallbacks;
01493     } else {
01494         /* Defaults. */
01495         drwav_allocation_callbacks allocationCallbacks;
01496         allocationCallbacks.pUserData = NULL;
01497         allocationCallbacks.onMalloc  = drwav__malloc_default;
01498         allocationCallbacks.onRealloc = drwav__realloc_default;
01499         allocationCallbacks.onFree    = drwav__free_default;
01500         return allocationCallbacks;
01501     }
01502 }
01503 
01504 
01505 static DRWAV_INLINE drwav_bool32 drwav__is_compressed_format_tag(drwav_uint16 formatTag)
01506 {
01507     return
01508         formatTag == DR_WAVE_FORMAT_ADPCM ||
01509         formatTag == DR_WAVE_FORMAT_DVI_ADPCM;
01510 }
01511 
01512 static unsigned int drwav__chunk_padding_size_riff(drwav_uint64 chunkSize)
01513 {
01514     return (unsigned int)(chunkSize % 2);
01515 }
01516 
01517 static unsigned int drwav__chunk_padding_size_w64(drwav_uint64 chunkSize)
01518 {
01519     return (unsigned int)(chunkSize % 8);
01520 }
01521 
01522 static drwav_uint64 drwav_read_pcm_frames_s16__msadpcm(drwav* pWav, drwav_uint64 samplesToRead, drwav_int16* pBufferOut);
01523 static drwav_uint64 drwav_read_pcm_frames_s16__ima(drwav* pWav, drwav_uint64 samplesToRead, drwav_int16* pBufferOut);
01524 static drwav_bool32 drwav_init_write__internal(drwav* pWav, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount);
01525 
01526 static drwav_result drwav__read_chunk_header(drwav_read_proc onRead, void* pUserData, drwav_container container, drwav_uint64* pRunningBytesReadOut, drwav_chunk_header* pHeaderOut)
01527 {
01528     if (container == drwav_container_riff) {
01529         drwav_uint8 sizeInBytes[4];
01530 
01531         if (onRead(pUserData, pHeaderOut->id.fourcc, 4) != 4) {
01532             return DRWAV_AT_END;
01533         }
01534 
01535         if (onRead(pUserData, sizeInBytes, 4) != 4) {
01536             return DRWAV_INVALID_FILE;
01537         }
01538 
01539         pHeaderOut->sizeInBytes = drwav__bytes_to_u32(sizeInBytes);
01540         pHeaderOut->paddingSize = drwav__chunk_padding_size_riff(pHeaderOut->sizeInBytes);
01541         *pRunningBytesReadOut += 8;
01542     } else {
01543         drwav_uint8 sizeInBytes[8];
01544 
01545         if (onRead(pUserData, pHeaderOut->id.guid, 16) != 16) {
01546             return DRWAV_AT_END;
01547         }
01548 
01549         if (onRead(pUserData, sizeInBytes, 8) != 8) {
01550             return DRWAV_INVALID_FILE;
01551         }
01552 
01553         pHeaderOut->sizeInBytes = drwav__bytes_to_u64(sizeInBytes) - 24;    /* <-- Subtract 24 because w64 includes the size of the header. */
01554         pHeaderOut->paddingSize = drwav__chunk_padding_size_w64(pHeaderOut->sizeInBytes);
01555         *pRunningBytesReadOut += 24;
01556     }
01557 
01558     return DRWAV_SUCCESS;
01559 }
01560 
01561 static drwav_bool32 drwav__seek_forward(drwav_seek_proc onSeek, drwav_uint64 offset, void* pUserData)
01562 {
01563     drwav_uint64 bytesRemainingToSeek = offset;
01564     while (bytesRemainingToSeek > 0) {
01565         if (bytesRemainingToSeek > 0x7FFFFFFF) {
01566             if (!onSeek(pUserData, 0x7FFFFFFF, drwav_seek_origin_current)) {
01567                 return DRWAV_FALSE;
01568             }
01569             bytesRemainingToSeek -= 0x7FFFFFFF;
01570         } else {
01571             if (!onSeek(pUserData, (int)bytesRemainingToSeek, drwav_seek_origin_current)) {
01572                 return DRWAV_FALSE;
01573             }
01574             bytesRemainingToSeek = 0;
01575         }
01576     }
01577 
01578     return DRWAV_TRUE;
01579 }
01580 
01581 static drwav_bool32 drwav__seek_from_start(drwav_seek_proc onSeek, drwav_uint64 offset, void* pUserData)
01582 {
01583     if (offset <= 0x7FFFFFFF) {
01584         return onSeek(pUserData, (int)offset, drwav_seek_origin_start);
01585     }
01586 
01587     /* Larger than 32-bit seek. */
01588     if (!onSeek(pUserData, 0x7FFFFFFF, drwav_seek_origin_start)) {
01589         return DRWAV_FALSE;
01590     }
01591     offset -= 0x7FFFFFFF;
01592 
01593     for (;;) {
01594         if (offset <= 0x7FFFFFFF) {
01595             return onSeek(pUserData, (int)offset, drwav_seek_origin_current);
01596         }
01597 
01598         if (!onSeek(pUserData, 0x7FFFFFFF, drwav_seek_origin_current)) {
01599             return DRWAV_FALSE;
01600         }
01601         offset -= 0x7FFFFFFF;
01602     }
01603 
01604     /* Should never get here. */
01605     /*return DRWAV_TRUE; */
01606 }
01607 
01608 
01609 static drwav_bool32 drwav__read_fmt(drwav_read_proc onRead, drwav_seek_proc onSeek, void* pUserData, drwav_container container, drwav_uint64* pRunningBytesReadOut, drwav_fmt* fmtOut)
01610 {
01611     drwav_chunk_header header;
01612     drwav_uint8 fmt[16];
01613 
01614     if (drwav__read_chunk_header(onRead, pUserData, container, pRunningBytesReadOut, &header) != DRWAV_SUCCESS) {
01615         return DRWAV_FALSE;
01616     }
01617 
01618 
01619     /* Skip non-fmt chunks. */
01620     while ((container == drwav_container_riff && !drwav__fourcc_equal(header.id.fourcc, "fmt ")) || (container == drwav_container_w64 && !drwav__guid_equal(header.id.guid, drwavGUID_W64_FMT))) {
01621         if (!drwav__seek_forward(onSeek, header.sizeInBytes + header.paddingSize, pUserData)) {
01622             return DRWAV_FALSE;
01623         }
01624         *pRunningBytesReadOut += header.sizeInBytes + header.paddingSize;
01625 
01626         /* Try the next header. */
01627         if (drwav__read_chunk_header(onRead, pUserData, container, pRunningBytesReadOut, &header) != DRWAV_SUCCESS) {
01628             return DRWAV_FALSE;
01629         }
01630     }
01631 
01632 
01633     /* Validation. */
01634     if (container == drwav_container_riff) {
01635         if (!drwav__fourcc_equal(header.id.fourcc, "fmt ")) {
01636             return DRWAV_FALSE;
01637         }
01638     } else {
01639         if (!drwav__guid_equal(header.id.guid, drwavGUID_W64_FMT)) {
01640             return DRWAV_FALSE;
01641         }
01642     }
01643 
01644 
01645     if (onRead(pUserData, fmt, sizeof(fmt)) != sizeof(fmt)) {
01646         return DRWAV_FALSE;
01647     }
01648     *pRunningBytesReadOut += sizeof(fmt);
01649 
01650     fmtOut->formatTag      = drwav__bytes_to_u16(fmt + 0);
01651     fmtOut->channels       = drwav__bytes_to_u16(fmt + 2);
01652     fmtOut->sampleRate     = drwav__bytes_to_u32(fmt + 4);
01653     fmtOut->avgBytesPerSec = drwav__bytes_to_u32(fmt + 8);
01654     fmtOut->blockAlign     = drwav__bytes_to_u16(fmt + 12);
01655     fmtOut->bitsPerSample  = drwav__bytes_to_u16(fmt + 14);
01656 
01657     fmtOut->extendedSize       = 0;
01658     fmtOut->validBitsPerSample = 0;
01659     fmtOut->channelMask        = 0;
01660     memset(fmtOut->subFormat, 0, sizeof(fmtOut->subFormat));
01661 
01662     if (header.sizeInBytes > 16) {
01663         drwav_uint8 fmt_cbSize[2];
01664         int bytesReadSoFar = 0;
01665 
01666         if (onRead(pUserData, fmt_cbSize, sizeof(fmt_cbSize)) != sizeof(fmt_cbSize)) {
01667             return DRWAV_FALSE;    /* Expecting more data. */
01668         }
01669         *pRunningBytesReadOut += sizeof(fmt_cbSize);
01670 
01671         bytesReadSoFar = 18;
01672 
01673         fmtOut->extendedSize = drwav__bytes_to_u16(fmt_cbSize);
01674         if (fmtOut->extendedSize > 0) {
01675             /* Simple validation. */
01676             if (fmtOut->formatTag == DR_WAVE_FORMAT_EXTENSIBLE) {
01677                 if (fmtOut->extendedSize != 22) {
01678                     return DRWAV_FALSE;
01679                 }
01680             }
01681 
01682             if (fmtOut->formatTag == DR_WAVE_FORMAT_EXTENSIBLE) {
01683                 drwav_uint8 fmtext[22];
01684                 if (onRead(pUserData, fmtext, fmtOut->extendedSize) != fmtOut->extendedSize) {
01685                     return DRWAV_FALSE;    /* Expecting more data. */
01686                 }
01687 
01688                 fmtOut->validBitsPerSample = drwav__bytes_to_u16(fmtext + 0);
01689                 fmtOut->channelMask        = drwav__bytes_to_u32(fmtext + 2);
01690                 drwav__bytes_to_guid(fmtext + 6, fmtOut->subFormat);
01691             } else {
01692                 if (!onSeek(pUserData, fmtOut->extendedSize, drwav_seek_origin_current)) {
01693                     return DRWAV_FALSE;
01694                 }
01695             }
01696             *pRunningBytesReadOut += fmtOut->extendedSize;
01697 
01698             bytesReadSoFar += fmtOut->extendedSize;
01699         }
01700 
01701         /* Seek past any leftover bytes. For w64 the leftover will be defined based on the chunk size. */
01702         if (!onSeek(pUserData, (int)(header.sizeInBytes - bytesReadSoFar), drwav_seek_origin_current)) {
01703             return DRWAV_FALSE;
01704         }
01705         *pRunningBytesReadOut += (header.sizeInBytes - bytesReadSoFar);
01706     }
01707 
01708     if (header.paddingSize > 0) {
01709         if (!onSeek(pUserData, header.paddingSize, drwav_seek_origin_current)) {
01710             return DRWAV_FALSE;
01711         }
01712         *pRunningBytesReadOut += header.paddingSize;
01713     }
01714 
01715     return DRWAV_TRUE;
01716 }
01717 
01718 
01719 static size_t drwav__on_read(drwav_read_proc onRead, void* pUserData, void* pBufferOut, size_t bytesToRead, drwav_uint64* pCursor)
01720 {
01721     size_t bytesRead;
01722 
01723     DRWAV_ASSERT(onRead != NULL);
01724     DRWAV_ASSERT(pCursor != NULL);
01725 
01726     bytesRead = onRead(pUserData, pBufferOut, bytesToRead);
01727     *pCursor += bytesRead;
01728     return bytesRead;
01729 }
01730 
01731 #if 0
01732 static drwav_bool32 drwav__on_seek(drwav_seek_proc onSeek, void* pUserData, int offset, drwav_seek_origin origin, drwav_uint64* pCursor)
01733 {
01734     DRWAV_ASSERT(onSeek != NULL);
01735     DRWAV_ASSERT(pCursor != NULL);
01736 
01737     if (!onSeek(pUserData, offset, origin)) {
01738         return DRWAV_FALSE;
01739     }
01740 
01741     if (origin == drwav_seek_origin_start) {
01742         *pCursor = offset;
01743     } else {
01744         *pCursor += offset;
01745     }
01746 
01747     return DRWAV_TRUE;
01748 }
01749 #endif
01750 
01751 
01752 
01753 static drwav_uint32 drwav_get_bytes_per_pcm_frame(drwav* pWav)
01754 {
01755     /*
01756     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
01757     is that if the bits per sample is a multiple of 8, use floor(bitsPerSample*channels/8), otherwise fall back to the block align.
01758     */
01759     if ((pWav->bitsPerSample & 0x7) == 0) {
01760         /* Bits per sample is a multiple of 8. */
01761         return (pWav->bitsPerSample * pWav->fmt.channels) >> 3;
01762     } else {
01763         return pWav->fmt.blockAlign;
01764     }
01765 }
01766 
01767 DRWAV_API drwav_uint16 drwav_fmt_get_format(const drwav_fmt* pFMT)
01768 {
01769     if (pFMT == NULL) {
01770         return 0;
01771     }
01772 
01773     if (pFMT->formatTag != DR_WAVE_FORMAT_EXTENSIBLE) {
01774         return pFMT->formatTag;
01775     } else {
01776         return drwav__bytes_to_u16(pFMT->subFormat);    /* Only the first two bytes are required. */
01777     }
01778 }
01779 
01780 static drwav_bool32 drwav_preinit(drwav* pWav, drwav_read_proc onRead, drwav_seek_proc onSeek, void* pReadSeekUserData, const drwav_allocation_callbacks* pAllocationCallbacks)
01781 {
01782     if (pWav == NULL || onRead == NULL || onSeek == NULL) {
01783         return DRWAV_FALSE;
01784     }
01785 
01786     DRWAV_ZERO_MEMORY(pWav, sizeof(*pWav));
01787     pWav->onRead    = onRead;
01788     pWav->onSeek    = onSeek;
01789     pWav->pUserData = pReadSeekUserData;
01790     pWav->allocationCallbacks = drwav_copy_allocation_callbacks_or_defaults(pAllocationCallbacks);
01791 
01792     if (pWav->allocationCallbacks.onFree == NULL || (pWav->allocationCallbacks.onMalloc == NULL && pWav->allocationCallbacks.onRealloc == NULL)) {
01793         return DRWAV_FALSE;    /* Invalid allocation callbacks. */
01794     }
01795 
01796     return DRWAV_TRUE;
01797 }
01798 
01799 static drwav_bool32 drwav_init__internal(drwav* pWav, drwav_chunk_proc onChunk, void* pChunkUserData, drwav_uint32 flags)
01800 {
01801     /* This function assumes drwav_preinit() has been called beforehand. */
01802 
01803     drwav_uint64 cursor;    /* <-- Keeps track of the byte position so we can seek to specific locations. */
01804     drwav_bool32 sequential;
01805     drwav_uint8 riff[4];
01806     drwav_fmt fmt;
01807     unsigned short translatedFormatTag;
01808     drwav_uint64 sampleCountFromFactChunk;
01809     drwav_bool32 foundDataChunk;
01810     drwav_uint64 dataChunkSize;
01811     drwav_uint64 chunkSize;
01812 
01813     cursor = 0;
01814     sequential = (flags & DRWAV_SEQUENTIAL) != 0;
01815 
01816     /* The first 4 bytes should be the RIFF identifier. */
01817     if (drwav__on_read(pWav->onRead, pWav->pUserData, riff, sizeof(riff), &cursor) != sizeof(riff)) {
01818         return DRWAV_FALSE;
01819     }
01820 
01821     /*
01822     The first 4 bytes can be used to identify the container. For RIFF files it will start with "RIFF" and for
01823     w64 it will start with "riff".
01824     */
01825     if (drwav__fourcc_equal(riff, "RIFF")) {
01826         pWav->container = drwav_container_riff;
01827     } else if (drwav__fourcc_equal(riff, "riff")) {
01828         int i;
01829         drwav_uint8 riff2[12];
01830 
01831         pWav->container = drwav_container_w64;
01832 
01833         /* Check the rest of the GUID for validity. */
01834         if (drwav__on_read(pWav->onRead, pWav->pUserData, riff2, sizeof(riff2), &cursor) != sizeof(riff2)) {
01835             return DRWAV_FALSE;
01836         }
01837 
01838         for (i = 0; i < 12; ++i) {
01839             if (riff2[i] != drwavGUID_W64_RIFF[i+4]) {
01840                 return DRWAV_FALSE;
01841             }
01842         }
01843     } else {
01844         return DRWAV_FALSE;   /* Unknown or unsupported container. */
01845     }
01846 
01847 
01848     if (pWav->container == drwav_container_riff) {
01849         drwav_uint8 chunkSizeBytes[4];
01850         drwav_uint8 wave[4];
01851 
01852         /* RIFF/WAVE */
01853         if (drwav__on_read(pWav->onRead, pWav->pUserData, chunkSizeBytes, sizeof(chunkSizeBytes), &cursor) != sizeof(chunkSizeBytes)) {
01854             return DRWAV_FALSE;
01855         }
01856 
01857         if (drwav__bytes_to_u32(chunkSizeBytes) < 36) {
01858             return DRWAV_FALSE;    /* Chunk size should always be at least 36 bytes. */
01859         }
01860 
01861         if (drwav__on_read(pWav->onRead, pWav->pUserData, wave, sizeof(wave), &cursor) != sizeof(wave)) {
01862             return DRWAV_FALSE;
01863         }
01864 
01865         if (!drwav__fourcc_equal(wave, "WAVE")) {
01866             return DRWAV_FALSE;    /* Expecting "WAVE". */
01867         }
01868     } else {
01869         drwav_uint8 chunkSizeBytes[8];
01870         drwav_uint8 wave[16];
01871 
01872         /* W64 */
01873         if (drwav__on_read(pWav->onRead, pWav->pUserData, chunkSizeBytes, sizeof(chunkSizeBytes), &cursor) != sizeof(chunkSizeBytes)) {
01874             return DRWAV_FALSE;
01875         }
01876 
01877         if (drwav__bytes_to_u64(chunkSizeBytes) < 80) {
01878             return DRWAV_FALSE;
01879         }
01880 
01881         if (drwav__on_read(pWav->onRead, pWav->pUserData, wave, sizeof(wave), &cursor) != sizeof(wave)) {
01882             return DRWAV_FALSE;
01883         }
01884 
01885         if (!drwav__guid_equal(wave, drwavGUID_W64_WAVE)) {
01886             return DRWAV_FALSE;
01887         }
01888     }
01889 
01890 
01891     /* The next bytes should be the "fmt " chunk. */
01892     if (!drwav__read_fmt(pWav->onRead, pWav->onSeek, pWav->pUserData, pWav->container, &cursor, &fmt)) {
01893         return DRWAV_FALSE;    /* Failed to read the "fmt " chunk. */
01894     }
01895 
01896     /* Basic validation. */
01897     if ((fmt.sampleRate    == 0 || fmt.sampleRate    > DRWAV_MAX_SAMPLE_RATE)     ||
01898         (fmt.channels      == 0 || fmt.channels      > DRWAV_MAX_CHANNELS)        ||
01899         (fmt.bitsPerSample == 0 || fmt.bitsPerSample > DRWAV_MAX_BITS_PER_SAMPLE) ||
01900         fmt.blockAlign == 0) {
01901         return DRWAV_FALSE; /* Probably an invalid WAV file. */
01902     }
01903 
01904 
01905     /* Translate the internal format. */
01906     translatedFormatTag = fmt.formatTag;
01907     if (translatedFormatTag == DR_WAVE_FORMAT_EXTENSIBLE) {
01908         translatedFormatTag = drwav__bytes_to_u16(fmt.subFormat + 0);
01909     }
01910 
01911 
01912 
01913     sampleCountFromFactChunk = 0;
01914 
01915     /*
01916     We need to enumerate over each chunk for two reasons:
01917       1) The "data" chunk may not be the next one
01918       2) We may want to report each chunk back to the client
01919     
01920     In order to correctly report each chunk back to the client we will need to keep looping until the end of the file.
01921     */
01922     foundDataChunk = DRWAV_FALSE;
01923     dataChunkSize = 0;
01924 
01925     /* The next chunk we care about is the "data" chunk. This is not necessarily the next chunk so we'll need to loop. */
01926     for (;;)
01927     {
01928         drwav_chunk_header header;
01929         drwav_result result = drwav__read_chunk_header(pWav->onRead, pWav->pUserData, pWav->container, &cursor, &header);
01930         if (result != DRWAV_SUCCESS) {
01931             if (!foundDataChunk) {
01932                 return DRWAV_FALSE;
01933             } else {
01934                 break;  /* Probably at the end of the file. Get out of the loop. */
01935             }
01936         }
01937 
01938         /* Tell the client about this chunk. */
01939         if (!sequential && onChunk != NULL) {
01940             drwav_uint64 callbackBytesRead = onChunk(pChunkUserData, pWav->onRead, pWav->onSeek, pWav->pUserData, &header, pWav->container, &fmt);
01941 
01942             /*
01943             dr_wav may need to read the contents of the chunk, so we now need to seek back to the position before
01944             we called the callback.
01945             */
01946             if (callbackBytesRead > 0) {
01947                 if (!drwav__seek_from_start(pWav->onSeek, cursor, pWav->pUserData)) {
01948                     return DRWAV_FALSE;
01949                 }
01950             }
01951         }
01952         
01953 
01954         if (!foundDataChunk) {
01955             pWav->dataChunkDataPos = cursor;
01956         }
01957 
01958         chunkSize = header.sizeInBytes;
01959         if (pWav->container == drwav_container_riff) {
01960             if (drwav__fourcc_equal(header.id.fourcc, "data")) {
01961                 foundDataChunk = DRWAV_TRUE;
01962                 dataChunkSize = chunkSize;
01963             }
01964         } else {
01965             if (drwav__guid_equal(header.id.guid, drwavGUID_W64_DATA)) {
01966                 foundDataChunk = DRWAV_TRUE;
01967                 dataChunkSize = chunkSize;
01968             }
01969         }
01970 
01971         /*
01972         If at this point we have found the data chunk and we're running in sequential mode, we need to break out of this loop. The reason for
01973         this is that we would otherwise require a backwards seek which sequential mode forbids.
01974         */
01975         if (foundDataChunk && sequential) {
01976             break;
01977         }
01978 
01979         /* Optional. Get the total sample count from the FACT chunk. This is useful for compressed formats. */
01980         if (pWav->container == drwav_container_riff) {
01981             if (drwav__fourcc_equal(header.id.fourcc, "fact")) {
01982                 drwav_uint32 sampleCount;
01983                 if (drwav__on_read(pWav->onRead, pWav->pUserData, &sampleCount, 4, &cursor) != 4) {
01984                     return DRWAV_FALSE;
01985                 }
01986                 chunkSize -= 4;
01987 
01988                 if (!foundDataChunk) {
01989                     pWav->dataChunkDataPos = cursor;
01990                 }
01991 
01992                 /*
01993                 The sample count in the "fact" chunk is either unreliable, or I'm not understanding it properly. For now I am only enabling this
01994                 for Microsoft ADPCM formats.
01995                 */
01996                 if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ADPCM) {
01997                     sampleCountFromFactChunk = sampleCount;
01998                 } else {
01999                     sampleCountFromFactChunk = 0;
02000                 }
02001             }
02002         } else {
02003             if (drwav__guid_equal(header.id.guid, drwavGUID_W64_FACT)) {
02004                 if (drwav__on_read(pWav->onRead, pWav->pUserData, &sampleCountFromFactChunk, 8, &cursor) != 8) {
02005                     return DRWAV_FALSE;
02006                 }
02007                 chunkSize -= 8;
02008 
02009                 if (!foundDataChunk) {
02010                     pWav->dataChunkDataPos = cursor;
02011                 }
02012             }
02013         }
02014 
02015         /* "smpl" chunk. */
02016         if (pWav->container == drwav_container_riff) {
02017             if (drwav__fourcc_equal(header.id.fourcc, "smpl")) {
02018                 drwav_uint8 smplHeaderData[36];    /* 36 = size of the smpl header section, not including the loop data. */
02019                 if (chunkSize >= sizeof(smplHeaderData)) {
02020                     drwav_uint64 bytesJustRead = drwav__on_read(pWav->onRead, pWav->pUserData, smplHeaderData, sizeof(smplHeaderData), &cursor);
02021                     chunkSize -= bytesJustRead;
02022 
02023                     if (bytesJustRead == sizeof(smplHeaderData)) {
02024                         drwav_uint32 iLoop;
02025 
02026                         pWav->smpl.manufacturer      = drwav__bytes_to_u32(smplHeaderData+0);
02027                         pWav->smpl.product           = drwav__bytes_to_u32(smplHeaderData+4);
02028                         pWav->smpl.samplePeriod      = drwav__bytes_to_u32(smplHeaderData+8);
02029                         pWav->smpl.midiUnityNotes    = drwav__bytes_to_u32(smplHeaderData+12);
02030                         pWav->smpl.midiPitchFraction = drwav__bytes_to_u32(smplHeaderData+16);
02031                         pWav->smpl.smpteFormat       = drwav__bytes_to_u32(smplHeaderData+20);
02032                         pWav->smpl.smpteOffset       = drwav__bytes_to_u32(smplHeaderData+24);
02033                         pWav->smpl.numSampleLoops    = drwav__bytes_to_u32(smplHeaderData+28);
02034                         pWav->smpl.samplerData       = drwav__bytes_to_u32(smplHeaderData+32);
02035 
02036                         for (iLoop = 0; iLoop < pWav->smpl.numSampleLoops && iLoop < drwav_countof(pWav->smpl.loops); ++iLoop) {
02037                             drwav_uint8 smplLoopData[24];  /* 24 = size of a loop section in the smpl chunk. */
02038                             bytesJustRead = drwav__on_read(pWav->onRead, pWav->pUserData, smplLoopData, sizeof(smplLoopData), &cursor);
02039                             chunkSize -= bytesJustRead;
02040 
02041                             if (bytesJustRead == sizeof(smplLoopData)) {
02042                                 pWav->smpl.loops[iLoop].cuePointId = drwav__bytes_to_u32(smplLoopData+0);
02043                                 pWav->smpl.loops[iLoop].type       = drwav__bytes_to_u32(smplLoopData+4);
02044                                 pWav->smpl.loops[iLoop].start      = drwav__bytes_to_u32(smplLoopData+8);
02045                                 pWav->smpl.loops[iLoop].end        = drwav__bytes_to_u32(smplLoopData+12);
02046                                 pWav->smpl.loops[iLoop].fraction   = drwav__bytes_to_u32(smplLoopData+16);
02047                                 pWav->smpl.loops[iLoop].playCount  = drwav__bytes_to_u32(smplLoopData+20);
02048                             } else {
02049                                 break;  /* Break from the smpl loop for loop. */
02050                             }
02051                         }
02052                     }
02053                 } else {
02054                     /* Looks like invalid data. Ignore the chunk. */
02055                 }
02056             }
02057         } else {
02058             if (drwav__guid_equal(header.id.guid, drwavGUID_W64_SMPL)) {
02059                 /*
02060                 This path will be hit when a W64 WAV file contains a smpl chunk. I don't have a sample file to test this path, so a contribution
02061                 is welcome to add support for this.
02062                 */
02063             }
02064         }
02065 
02066         /* Make sure we seek past the padding. */
02067         chunkSize += header.paddingSize;
02068         if (!drwav__seek_forward(pWav->onSeek, chunkSize, pWav->pUserData)) {
02069             break;
02070         }
02071         cursor += chunkSize;
02072 
02073         if (!foundDataChunk) {
02074             pWav->dataChunkDataPos = cursor;
02075         }
02076     }
02077 
02078     /* If we haven't found a data chunk, return an error. */
02079     if (!foundDataChunk) {
02080         return DRWAV_FALSE;
02081     }
02082 
02083     /* 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. */
02084     if (!sequential) {
02085         if (!drwav__seek_from_start(pWav->onSeek, pWav->dataChunkDataPos, pWav->pUserData)) {
02086             return DRWAV_FALSE;
02087         }
02088         cursor = pWav->dataChunkDataPos;
02089     }
02090     
02091 
02092     /* At this point we should be sitting on the first byte of the raw audio data. */
02093 
02094     pWav->fmt                 = fmt;
02095     pWav->sampleRate          = fmt.sampleRate;
02096     pWav->channels            = fmt.channels;
02097     pWav->bitsPerSample       = fmt.bitsPerSample;
02098     pWav->bytesRemaining      = dataChunkSize;
02099     pWav->translatedFormatTag = translatedFormatTag;
02100     pWav->dataChunkDataSize   = dataChunkSize;
02101 
02102     if (sampleCountFromFactChunk != 0) {
02103         pWav->totalPCMFrameCount = sampleCountFromFactChunk;
02104     } else {
02105         pWav->totalPCMFrameCount = dataChunkSize / drwav_get_bytes_per_pcm_frame(pWav);
02106 
02107         if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ADPCM) {
02108             drwav_uint64 totalBlockHeaderSizeInBytes;
02109             drwav_uint64 blockCount = dataChunkSize / fmt.blockAlign;
02110 
02111             /* Make sure any trailing partial block is accounted for. */
02112             if ((blockCount * fmt.blockAlign) < dataChunkSize) {
02113                 blockCount += 1;
02114             }
02115 
02116             /* 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. */
02117             totalBlockHeaderSizeInBytes = blockCount * (6*fmt.channels);
02118             pWav->totalPCMFrameCount = ((dataChunkSize - totalBlockHeaderSizeInBytes) * 2) / fmt.channels;
02119         }
02120         if (pWav->translatedFormatTag == DR_WAVE_FORMAT_DVI_ADPCM) {
02121             drwav_uint64 totalBlockHeaderSizeInBytes;
02122             drwav_uint64 blockCount = dataChunkSize / fmt.blockAlign;
02123 
02124             /* Make sure any trailing partial block is accounted for. */
02125             if ((blockCount * fmt.blockAlign) < dataChunkSize) {
02126                 blockCount += 1;
02127             }
02128 
02129             /* 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. */
02130             totalBlockHeaderSizeInBytes = blockCount * (4*fmt.channels);
02131             pWav->totalPCMFrameCount = ((dataChunkSize - totalBlockHeaderSizeInBytes) * 2) / fmt.channels;
02132 
02133             /* The header includes a decoded sample for each channel which acts as the initial predictor sample. */
02134             pWav->totalPCMFrameCount += blockCount;
02135         }
02136     }
02137 
02138     /* Some formats only support a certain number of channels. */
02139     if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ADPCM || pWav->translatedFormatTag == DR_WAVE_FORMAT_DVI_ADPCM) {
02140         if (pWav->channels > 2) {
02141             return DRWAV_FALSE;
02142         }
02143     }
02144 
02145 #ifdef DR_WAV_LIBSNDFILE_COMPAT
02146     /*
02147     I use libsndfile as a benchmark for testing, however in the version I'm using (from the Windows installer on the libsndfile website),
02148     it appears the total sample count libsndfile uses for MS-ADPCM is incorrect. It would seem they are computing the total sample count
02149     from the number of blocks, however this results in the inclusion of extra silent samples at the end of the last block. The correct
02150     way to know the total sample count is to inspect the "fact" chunk, which should always be present for compressed formats, and should
02151     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
02152     correctness tests against libsndfile, and is disabled by default.
02153     */
02154     if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ADPCM) {
02155         drwav_uint64 blockCount = dataChunkSize / fmt.blockAlign;
02156         pWav->totalPCMFrameCount = (((blockCount * (fmt.blockAlign - (6*pWav->channels))) * 2)) / fmt.channels;  /* x2 because two samples per byte. */
02157     }
02158     if (pWav->translatedFormatTag == DR_WAVE_FORMAT_DVI_ADPCM) {
02159         drwav_uint64 blockCount = dataChunkSize / fmt.blockAlign;
02160         pWav->totalPCMFrameCount = (((blockCount * (fmt.blockAlign - (4*pWav->channels))) * 2) + (blockCount * pWav->channels)) / fmt.channels;
02161     }
02162 #endif
02163 
02164     return DRWAV_TRUE;
02165 }
02166 
02167 DRWAV_API drwav_bool32 drwav_init(drwav* pWav, drwav_read_proc onRead, drwav_seek_proc onSeek, void* pUserData, const drwav_allocation_callbacks* pAllocationCallbacks)
02168 {
02169     return drwav_init_ex(pWav, onRead, onSeek, NULL, pUserData, NULL, 0, pAllocationCallbacks);
02170 }
02171 
02172 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)
02173 {
02174     if (!drwav_preinit(pWav, onRead, onSeek, pReadSeekUserData, pAllocationCallbacks)) {
02175         return DRWAV_FALSE;
02176     }
02177 
02178     return drwav_init__internal(pWav, onChunk, pChunkUserData, flags);
02179 }
02180 
02181 
02182 static drwav_uint32 drwav__riff_chunk_size_riff(drwav_uint64 dataChunkSize)
02183 {
02184     drwav_uint32 dataSubchunkPaddingSize = drwav__chunk_padding_size_riff(dataChunkSize);
02185 
02186     if (dataChunkSize <= (0xFFFFFFFFUL - 36 - dataSubchunkPaddingSize)) {
02187         return 36 + (drwav_uint32)(dataChunkSize + dataSubchunkPaddingSize);
02188     } else {
02189         return 0xFFFFFFFF;
02190     }
02191 }
02192 
02193 static drwav_uint32 drwav__data_chunk_size_riff(drwav_uint64 dataChunkSize)
02194 {
02195     if (dataChunkSize <= 0xFFFFFFFFUL) {
02196         return (drwav_uint32)dataChunkSize;
02197     } else {
02198         return 0xFFFFFFFFUL;
02199     }
02200 }
02201 
02202 static drwav_uint64 drwav__riff_chunk_size_w64(drwav_uint64 dataChunkSize)
02203 {
02204     drwav_uint64 dataSubchunkPaddingSize = drwav__chunk_padding_size_w64(dataChunkSize);
02205 
02206     return 80 + 24 + dataChunkSize + dataSubchunkPaddingSize;   /* +24 because W64 includes the size of the GUID and size fields. */
02207 }
02208 
02209 static drwav_uint64 drwav__data_chunk_size_w64(drwav_uint64 dataChunkSize)
02210 {
02211     return 24 + dataChunkSize;        /* +24 because W64 includes the size of the GUID and size fields. */
02212 }
02213 
02214 
02215 static drwav_bool32 drwav_preinit_write(drwav* pWav, const drwav_data_format* pFormat, drwav_bool32 isSequential, drwav_write_proc onWrite, drwav_seek_proc onSeek, void* pUserData, const drwav_allocation_callbacks* pAllocationCallbacks)
02216 {
02217     if (pWav == NULL || onWrite == NULL) {
02218         return DRWAV_FALSE;
02219     }
02220 
02221     if (!isSequential && onSeek == NULL) {
02222         return DRWAV_FALSE; /* <-- onSeek is required when in non-sequential mode. */
02223     }
02224 
02225     /* Not currently supporting compressed formats. Will need to add support for the "fact" chunk before we enable this. */
02226     if (pFormat->format == DR_WAVE_FORMAT_EXTENSIBLE) {
02227         return DRWAV_FALSE;
02228     }
02229     if (pFormat->format == DR_WAVE_FORMAT_ADPCM || pFormat->format == DR_WAVE_FORMAT_DVI_ADPCM) {
02230         return DRWAV_FALSE;
02231     }
02232 
02233     DRWAV_ZERO_MEMORY(pWav, sizeof(*pWav));
02234     pWav->onWrite   = onWrite;
02235     pWav->onSeek    = onSeek;
02236     pWav->pUserData = pUserData;
02237     pWav->allocationCallbacks = drwav_copy_allocation_callbacks_or_defaults(pAllocationCallbacks);
02238 
02239     if (pWav->allocationCallbacks.onFree == NULL || (pWav->allocationCallbacks.onMalloc == NULL && pWav->allocationCallbacks.onRealloc == NULL)) {
02240         return DRWAV_FALSE;    /* Invalid allocation callbacks. */
02241     }
02242 
02243     pWav->fmt.formatTag = (drwav_uint16)pFormat->format;
02244     pWav->fmt.channels = (drwav_uint16)pFormat->channels;
02245     pWav->fmt.sampleRate = pFormat->sampleRate;
02246     pWav->fmt.avgBytesPerSec = (drwav_uint32)((pFormat->bitsPerSample * pFormat->sampleRate * pFormat->channels) / 8);
02247     pWav->fmt.blockAlign = (drwav_uint16)((pFormat->channels * pFormat->bitsPerSample) / 8);
02248     pWav->fmt.bitsPerSample = (drwav_uint16)pFormat->bitsPerSample;
02249     pWav->fmt.extendedSize = 0;
02250     pWav->isSequentialWrite = isSequential;
02251 
02252     return DRWAV_TRUE;
02253 }
02254 
02255 static drwav_bool32 drwav_init_write__internal(drwav* pWav, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount)
02256 {
02257     /* The function assumes drwav_preinit_write() was called beforehand. */
02258 
02259     size_t runningPos = 0;
02260     drwav_uint64 initialDataChunkSize = 0;
02261     drwav_uint64 chunkSizeFMT;
02262 
02263     /*
02264     The initial values for the "RIFF" and "data" chunks depends on whether or not we are initializing in sequential mode or not. In
02265     sequential mode we set this to its final values straight away since they can be calculated from the total sample count. In non-
02266     sequential mode we initialize it all to zero and fill it out in drwav_uninit() using a backwards seek.
02267     */
02268     if (pWav->isSequentialWrite) {
02269         initialDataChunkSize = (totalSampleCount * pWav->fmt.bitsPerSample) / 8;
02270 
02271         /*
02272         The RIFF container has a limit on the number of samples. drwav is not allowing this. There's no practical limits for Wave64
02273         so for the sake of simplicity I'm not doing any validation for that.
02274         */
02275         if (pFormat->container == drwav_container_riff) {
02276             if (initialDataChunkSize > (0xFFFFFFFFUL - 36)) {
02277                 return DRWAV_FALSE; /* Not enough room to store every sample. */
02278             }
02279         }
02280     }
02281 
02282     pWav->dataChunkDataSizeTargetWrite = initialDataChunkSize;
02283 
02284 
02285     /* "RIFF" chunk. */
02286     if (pFormat->container == drwav_container_riff) {
02287         drwav_uint32 chunkSizeRIFF = 36 + (drwav_uint32)initialDataChunkSize;   /* +36 = "RIFF"+[RIFF Chunk Size]+"WAVE" + [sizeof "fmt " chunk] */
02288         runningPos += pWav->onWrite(pWav->pUserData, "RIFF", 4);
02289         runningPos += pWav->onWrite(pWav->pUserData, &chunkSizeRIFF, 4);
02290         runningPos += pWav->onWrite(pWav->pUserData, "WAVE", 4);
02291     } else {
02292         drwav_uint64 chunkSizeRIFF = 80 + 24 + initialDataChunkSize;   /* +24 because W64 includes the size of the GUID and size fields. */
02293         runningPos += pWav->onWrite(pWav->pUserData, drwavGUID_W64_RIFF, 16);
02294         runningPos += pWav->onWrite(pWav->pUserData, &chunkSizeRIFF, 8);
02295         runningPos += pWav->onWrite(pWav->pUserData, drwavGUID_W64_WAVE, 16);
02296     }
02297 
02298     /* "fmt " chunk. */
02299     if (pFormat->container == drwav_container_riff) {
02300         chunkSizeFMT = 16;
02301         runningPos += pWav->onWrite(pWav->pUserData, "fmt ", 4);
02302         runningPos += pWav->onWrite(pWav->pUserData, &chunkSizeFMT, 4);
02303     } else {
02304         chunkSizeFMT = 40;
02305         runningPos += pWav->onWrite(pWav->pUserData, drwavGUID_W64_FMT, 16);
02306         runningPos += pWav->onWrite(pWav->pUserData, &chunkSizeFMT, 8);
02307     }
02308 
02309     runningPos += pWav->onWrite(pWav->pUserData, &pWav->fmt.formatTag,      2);
02310     runningPos += pWav->onWrite(pWav->pUserData, &pWav->fmt.channels,       2);
02311     runningPos += pWav->onWrite(pWav->pUserData, &pWav->fmt.sampleRate,     4);
02312     runningPos += pWav->onWrite(pWav->pUserData, &pWav->fmt.avgBytesPerSec, 4);
02313     runningPos += pWav->onWrite(pWav->pUserData, &pWav->fmt.blockAlign,     2);
02314     runningPos += pWav->onWrite(pWav->pUserData, &pWav->fmt.bitsPerSample,  2);
02315 
02316     pWav->dataChunkDataPos = runningPos;
02317 
02318     /* "data" chunk. */
02319     if (pFormat->container == drwav_container_riff) {
02320         drwav_uint32 chunkSizeDATA = (drwav_uint32)initialDataChunkSize;
02321         runningPos += pWav->onWrite(pWav->pUserData, "data", 4);
02322         runningPos += pWav->onWrite(pWav->pUserData, &chunkSizeDATA, 4);
02323     } else {
02324         drwav_uint64 chunkSizeDATA = 24 + initialDataChunkSize; /* +24 because W64 includes the size of the GUID and size fields. */
02325         runningPos += pWav->onWrite(pWav->pUserData, drwavGUID_W64_DATA, 16);
02326         runningPos += pWav->onWrite(pWav->pUserData, &chunkSizeDATA, 8);
02327     }
02328 
02329 
02330     /* Simple validation. */
02331     if (pFormat->container == drwav_container_riff) {
02332         if (runningPos != 20 + chunkSizeFMT + 8) {
02333             return DRWAV_FALSE;
02334         }
02335     } else {
02336         if (runningPos != 40 + chunkSizeFMT + 24) {
02337             return DRWAV_FALSE;
02338         }
02339     }
02340     
02341 
02342     /* Set some properties for the client's convenience. */
02343     pWav->container = pFormat->container;
02344     pWav->channels = (drwav_uint16)pFormat->channels;
02345     pWav->sampleRate = pFormat->sampleRate;
02346     pWav->bitsPerSample = (drwav_uint16)pFormat->bitsPerSample;
02347     pWav->translatedFormatTag = (drwav_uint16)pFormat->format;
02348 
02349     return DRWAV_TRUE;
02350 }
02351 
02352 
02353 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)
02354 {
02355     if (!drwav_preinit_write(pWav, pFormat, DRWAV_FALSE, onWrite, onSeek, pUserData, pAllocationCallbacks)) {
02356         return DRWAV_FALSE;
02357     }
02358 
02359     return drwav_init_write__internal(pWav, pFormat, 0);               /* DRWAV_FALSE = Not Sequential */
02360 }
02361 
02362 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)
02363 {
02364     if (!drwav_preinit_write(pWav, pFormat, DRWAV_TRUE, onWrite, NULL, pUserData, pAllocationCallbacks)) {
02365         return DRWAV_FALSE;
02366     }
02367 
02368     return drwav_init_write__internal(pWav, pFormat, totalSampleCount); /* DRWAV_TRUE = Sequential */
02369 }
02370 
02371 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)
02372 {
02373     if (pFormat == NULL) {
02374         return DRWAV_FALSE;
02375     }
02376 
02377     return drwav_init_write_sequential(pWav, pFormat, totalPCMFrameCount*pFormat->channels, onWrite, pUserData, pAllocationCallbacks);
02378 }
02379 
02380 DRWAV_API drwav_uint64 drwav_target_write_size_bytes(const drwav_data_format* pFormat, drwav_uint64 totalSampleCount)
02381 {
02382     /* Casting totalSampleCount to drwav_int64 for VC6 compatibility. No issues in practice because nobody is going to exhaust the whole 63 bits. */
02383     drwav_uint64 targetDataSizeBytes = (drwav_uint64)((drwav_int64)totalSampleCount * pFormat->channels * pFormat->bitsPerSample/8.0);
02384     drwav_uint64 riffChunkSizeBytes;
02385     drwav_uint64 fileSizeBytes;
02386 
02387     if (pFormat->container == drwav_container_riff) {
02388         riffChunkSizeBytes = drwav__riff_chunk_size_riff(targetDataSizeBytes);
02389         fileSizeBytes = (8 + riffChunkSizeBytes); /* +8 because WAV doesn't include the size of the ChunkID and ChunkSize fields. */
02390     } else {
02391         riffChunkSizeBytes = drwav__riff_chunk_size_w64(targetDataSizeBytes);
02392         fileSizeBytes = riffChunkSizeBytes;
02393     }
02394 
02395     return fileSizeBytes;
02396 }
02397 
02398 
02399 #ifndef DR_WAV_NO_STDIO
02400 
02401 /* 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. */
02402 #include <errno.h>
02403 static drwav_result drwav_result_from_errno(int e)
02404 {
02405     switch (e)
02406     {
02407         case 0: return DRWAV_SUCCESS;
02408     #ifdef EPERM
02409         case EPERM: return DRWAV_INVALID_OPERATION;
02410     #endif
02411     #ifdef ENOENT
02412         case ENOENT: return DRWAV_DOES_NOT_EXIST;
02413     #endif
02414     #ifdef ESRCH
02415         case ESRCH: return DRWAV_DOES_NOT_EXIST;
02416     #endif
02417     #ifdef EINTR
02418         case EINTR: return DRWAV_INTERRUPT;
02419     #endif
02420     #ifdef EIO
02421         case EIO: return DRWAV_IO_ERROR;
02422     #endif
02423     #ifdef ENXIO
02424         case ENXIO: return DRWAV_DOES_NOT_EXIST;
02425     #endif
02426     #ifdef E2BIG
02427         case E2BIG: return DRWAV_INVALID_ARGS;
02428     #endif
02429     #ifdef ENOEXEC
02430         case ENOEXEC: return DRWAV_INVALID_FILE;
02431     #endif
02432     #ifdef EBADF
02433         case EBADF: return DRWAV_INVALID_FILE;
02434     #endif
02435     #ifdef ECHILD
02436         case ECHILD: return DRWAV_ERROR;
02437     #endif
02438     #ifdef EAGAIN
02439         case EAGAIN: return DRWAV_UNAVAILABLE;
02440     #endif
02441     #ifdef ENOMEM
02442         case ENOMEM: return DRWAV_OUT_OF_MEMORY;
02443     #endif
02444     #ifdef EACCES
02445         case EACCES: return DRWAV_ACCESS_DENIED;
02446     #endif
02447     #ifdef EFAULT
02448         case EFAULT: return DRWAV_BAD_ADDRESS;
02449     #endif
02450     #ifdef ENOTBLK
02451         case ENOTBLK: return DRWAV_ERROR;
02452     #endif
02453     #ifdef EBUSY
02454         case EBUSY: return DRWAV_BUSY;
02455     #endif
02456     #ifdef EEXIST
02457         case EEXIST: return DRWAV_ALREADY_EXISTS;
02458     #endif
02459     #ifdef EXDEV
02460         case EXDEV: return DRWAV_ERROR;
02461     #endif
02462     #ifdef ENODEV
02463         case ENODEV: return DRWAV_DOES_NOT_EXIST;
02464     #endif
02465     #ifdef ENOTDIR
02466         case ENOTDIR: return DRWAV_NOT_DIRECTORY;
02467     #endif
02468     #ifdef EISDIR
02469         case EISDIR: return DRWAV_IS_DIRECTORY;
02470     #endif
02471     #ifdef EINVAL
02472         case EINVAL: return DRWAV_INVALID_ARGS;
02473     #endif
02474     #ifdef ENFILE
02475         case ENFILE: return DRWAV_TOO_MANY_OPEN_FILES;
02476     #endif
02477     #ifdef EMFILE
02478         case EMFILE: return DRWAV_TOO_MANY_OPEN_FILES;
02479     #endif
02480     #ifdef ENOTTY
02481         case ENOTTY: return DRWAV_INVALID_OPERATION;
02482     #endif
02483     #ifdef ETXTBSY
02484         case ETXTBSY: return DRWAV_BUSY;
02485     #endif
02486     #ifdef EFBIG
02487         case EFBIG: return DRWAV_TOO_BIG;
02488     #endif
02489     #ifdef ENOSPC
02490         case ENOSPC: return DRWAV_NO_SPACE;
02491     #endif
02492     #ifdef ESPIPE
02493         case ESPIPE: return DRWAV_BAD_SEEK;
02494     #endif
02495     #ifdef EROFS
02496         case EROFS: return DRWAV_ACCESS_DENIED;
02497     #endif
02498     #ifdef EMLINK
02499         case EMLINK: return DRWAV_TOO_MANY_LINKS;
02500     #endif
02501     #ifdef EPIPE
02502         case EPIPE: return DRWAV_BAD_PIPE;
02503     #endif
02504     #ifdef EDOM
02505         case EDOM: return DRWAV_OUT_OF_RANGE;
02506     #endif
02507     #ifdef ERANGE
02508         case ERANGE: return DRWAV_OUT_OF_RANGE;
02509     #endif
02510     #ifdef EDEADLK
02511         case EDEADLK: return DRWAV_DEADLOCK;
02512     #endif
02513     #ifdef ENAMETOOLONG
02514         case ENAMETOOLONG: return DRWAV_PATH_TOO_LONG;
02515     #endif
02516     #ifdef ENOLCK
02517         case ENOLCK: return DRWAV_ERROR;
02518     #endif
02519     #ifdef ENOSYS
02520         case ENOSYS: return DRWAV_NOT_IMPLEMENTED;
02521     #endif
02522     #ifdef ENOTEMPTY
02523         case ENOTEMPTY: return DRWAV_DIRECTORY_NOT_EMPTY;
02524     #endif
02525     #ifdef ELOOP
02526         case ELOOP: return DRWAV_TOO_MANY_LINKS;
02527     #endif
02528     #ifdef ENOMSG
02529         case ENOMSG: return DRWAV_NO_MESSAGE;
02530     #endif
02531     #ifdef EIDRM
02532         case EIDRM: return DRWAV_ERROR;
02533     #endif
02534     #ifdef ECHRNG
02535         case ECHRNG: return DRWAV_ERROR;
02536     #endif
02537     #ifdef EL2NSYNC
02538         case EL2NSYNC: return DRWAV_ERROR;
02539     #endif
02540     #ifdef EL3HLT
02541         case EL3HLT: return DRWAV_ERROR;
02542     #endif
02543     #ifdef EL3RST
02544         case EL3RST: return DRWAV_ERROR;
02545     #endif
02546     #ifdef ELNRNG
02547         case ELNRNG: return DRWAV_OUT_OF_RANGE;
02548     #endif
02549     #ifdef EUNATCH
02550         case EUNATCH: return DRWAV_ERROR;
02551     #endif
02552     #ifdef ENOCSI
02553         case ENOCSI: return DRWAV_ERROR;
02554     #endif
02555     #ifdef EL2HLT
02556         case EL2HLT: return DRWAV_ERROR;
02557     #endif
02558     #ifdef EBADE
02559         case EBADE: return DRWAV_ERROR;
02560     #endif
02561     #ifdef EBADR
02562         case EBADR: return DRWAV_ERROR;
02563     #endif
02564     #ifdef EXFULL
02565         case EXFULL: return DRWAV_ERROR;
02566     #endif
02567     #ifdef ENOANO
02568         case ENOANO: return DRWAV_ERROR;
02569     #endif
02570     #ifdef EBADRQC
02571         case EBADRQC: return DRWAV_ERROR;
02572     #endif
02573     #ifdef EBADSLT
02574         case EBADSLT: return DRWAV_ERROR;
02575     #endif
02576     #ifdef EBFONT
02577         case EBFONT: return DRWAV_INVALID_FILE;
02578     #endif
02579     #ifdef ENOSTR
02580         case ENOSTR: return DRWAV_ERROR;
02581     #endif
02582     #ifdef ENODATA
02583         case ENODATA: return DRWAV_NO_DATA_AVAILABLE;
02584     #endif
02585     #ifdef ETIME
02586         case ETIME: return DRWAV_TIMEOUT;
02587     #endif
02588     #ifdef ENOSR
02589         case ENOSR: return DRWAV_NO_DATA_AVAILABLE;
02590     #endif
02591     #ifdef ENONET
02592         case ENONET: return DRWAV_NO_NETWORK;
02593     #endif
02594     #ifdef ENOPKG
02595         case ENOPKG: return DRWAV_ERROR;
02596     #endif
02597     #ifdef EREMOTE
02598         case EREMOTE: return DRWAV_ERROR;
02599     #endif
02600     #ifdef ENOLINK
02601         case ENOLINK: return DRWAV_ERROR;
02602     #endif
02603     #ifdef EADV
02604         case EADV: return DRWAV_ERROR;
02605     #endif
02606     #ifdef ESRMNT
02607         case ESRMNT: return DRWAV_ERROR;
02608     #endif
02609     #ifdef ECOMM
02610         case ECOMM: return DRWAV_ERROR;
02611     #endif
02612     #ifdef EPROTO
02613         case EPROTO: return DRWAV_ERROR;
02614     #endif
02615     #ifdef EMULTIHOP
02616         case EMULTIHOP: return DRWAV_ERROR;
02617     #endif
02618     #ifdef EDOTDOT
02619         case EDOTDOT: return DRWAV_ERROR;
02620     #endif
02621     #ifdef EBADMSG
02622         case EBADMSG: return DRWAV_BAD_MESSAGE;
02623     #endif
02624     #ifdef EOVERFLOW
02625         case EOVERFLOW: return DRWAV_TOO_BIG;
02626     #endif
02627     #ifdef ENOTUNIQ
02628         case ENOTUNIQ: return DRWAV_NOT_UNIQUE;
02629     #endif
02630     #ifdef EBADFD
02631         case EBADFD: return DRWAV_ERROR;
02632     #endif
02633     #ifdef EREMCHG
02634         case EREMCHG: return DRWAV_ERROR;
02635     #endif
02636     #ifdef ELIBACC
02637         case ELIBACC: return DRWAV_ACCESS_DENIED;
02638     #endif
02639     #ifdef ELIBBAD
02640         case ELIBBAD: return DRWAV_INVALID_FILE;
02641     #endif
02642     #ifdef ELIBSCN
02643         case ELIBSCN: return DRWAV_INVALID_FILE;
02644     #endif
02645     #ifdef ELIBMAX
02646         case ELIBMAX: return DRWAV_ERROR;
02647     #endif
02648     #ifdef ELIBEXEC
02649         case ELIBEXEC: return DRWAV_ERROR;
02650     #endif
02651     #ifdef EILSEQ
02652         case EILSEQ: return DRWAV_INVALID_DATA;
02653     #endif
02654     #ifdef ERESTART
02655         case ERESTART: return DRWAV_ERROR;
02656     #endif
02657     #ifdef ESTRPIPE
02658         case ESTRPIPE: return DRWAV_ERROR;
02659     #endif
02660     #ifdef EUSERS
02661         case EUSERS: return DRWAV_ERROR;
02662     #endif
02663     #ifdef ENOTSOCK
02664         case ENOTSOCK: return DRWAV_NOT_SOCKET;
02665     #endif
02666     #ifdef EDESTADDRREQ
02667         case EDESTADDRREQ: return DRWAV_NO_ADDRESS;
02668     #endif
02669     #ifdef EMSGSIZE
02670         case EMSGSIZE: return DRWAV_TOO_BIG;
02671     #endif
02672     #ifdef EPROTOTYPE
02673         case EPROTOTYPE: return DRWAV_BAD_PROTOCOL;
02674     #endif
02675     #ifdef ENOPROTOOPT
02676         case ENOPROTOOPT: return DRWAV_PROTOCOL_UNAVAILABLE;
02677     #endif
02678     #ifdef EPROTONOSUPPORT
02679         case EPROTONOSUPPORT: return DRWAV_PROTOCOL_NOT_SUPPORTED;
02680     #endif
02681     #ifdef ESOCKTNOSUPPORT
02682         case ESOCKTNOSUPPORT: return DRWAV_SOCKET_NOT_SUPPORTED;
02683     #endif
02684     #ifdef EOPNOTSUPP
02685         case EOPNOTSUPP: return DRWAV_INVALID_OPERATION;
02686     #endif
02687     #ifdef EPFNOSUPPORT
02688         case EPFNOSUPPORT: return DRWAV_PROTOCOL_FAMILY_NOT_SUPPORTED;
02689     #endif
02690     #ifdef EAFNOSUPPORT
02691         case EAFNOSUPPORT: return DRWAV_ADDRESS_FAMILY_NOT_SUPPORTED;
02692     #endif
02693     #ifdef EADDRINUSE
02694         case EADDRINUSE: return DRWAV_ALREADY_IN_USE;
02695     #endif
02696     #ifdef EADDRNOTAVAIL
02697         case EADDRNOTAVAIL: return DRWAV_ERROR;
02698     #endif
02699     #ifdef ENETDOWN
02700         case ENETDOWN: return DRWAV_NO_NETWORK;
02701     #endif
02702     #ifdef ENETUNREACH
02703         case ENETUNREACH: return DRWAV_NO_NETWORK;
02704     #endif
02705     #ifdef ENETRESET
02706         case ENETRESET: return DRWAV_NO_NETWORK;
02707     #endif
02708     #ifdef ECONNABORTED
02709         case ECONNABORTED: return DRWAV_NO_NETWORK;
02710     #endif
02711     #ifdef ECONNRESET
02712         case ECONNRESET: return DRWAV_CONNECTION_RESET;
02713     #endif
02714     #ifdef ENOBUFS
02715         case ENOBUFS: return DRWAV_NO_SPACE;
02716     #endif
02717     #ifdef EISCONN
02718         case EISCONN: return DRWAV_ALREADY_CONNECTED;
02719     #endif
02720     #ifdef ENOTCONN
02721         case ENOTCONN: return DRWAV_NOT_CONNECTED;
02722     #endif
02723     #ifdef ESHUTDOWN
02724         case ESHUTDOWN: return DRWAV_ERROR;
02725     #endif
02726     #ifdef ETOOMANYREFS
02727         case ETOOMANYREFS: return DRWAV_ERROR;
02728     #endif
02729     #ifdef ETIMEDOUT
02730         case ETIMEDOUT: return DRWAV_TIMEOUT;
02731     #endif
02732     #ifdef ECONNREFUSED
02733         case ECONNREFUSED: return DRWAV_CONNECTION_REFUSED;
02734     #endif
02735     #ifdef EHOSTDOWN
02736         case EHOSTDOWN: return DRWAV_NO_HOST;
02737     #endif
02738     #ifdef EHOSTUNREACH
02739         case EHOSTUNREACH: return DRWAV_NO_HOST;
02740     #endif
02741     #ifdef EALREADY
02742         case EALREADY: return DRWAV_IN_PROGRESS;
02743     #endif
02744     #ifdef EINPROGRESS
02745         case EINPROGRESS: return DRWAV_IN_PROGRESS;
02746     #endif
02747     #ifdef ESTALE
02748         case ESTALE: return DRWAV_INVALID_FILE;
02749     #endif
02750     #ifdef EUCLEAN
02751         case EUCLEAN: return DRWAV_ERROR;
02752     #endif
02753     #ifdef ENOTNAM
02754         case ENOTNAM: return DRWAV_ERROR;
02755     #endif
02756     #ifdef ENAVAIL
02757         case ENAVAIL: return DRWAV_ERROR;
02758     #endif
02759     #ifdef EISNAM
02760         case EISNAM: return DRWAV_ERROR;
02761     #endif
02762     #ifdef EREMOTEIO
02763         case EREMOTEIO: return DRWAV_IO_ERROR;
02764     #endif
02765     #ifdef EDQUOT
02766         case EDQUOT: return DRWAV_NO_SPACE;
02767     #endif
02768     #ifdef ENOMEDIUM
02769         case ENOMEDIUM: return DRWAV_DOES_NOT_EXIST;
02770     #endif
02771     #ifdef EMEDIUMTYPE
02772         case EMEDIUMTYPE: return DRWAV_ERROR;
02773     #endif
02774     #ifdef ECANCELED
02775         case ECANCELED: return DRWAV_CANCELLED;
02776     #endif
02777     #ifdef ENOKEY
02778         case ENOKEY: return DRWAV_ERROR;
02779     #endif
02780     #ifdef EKEYEXPIRED
02781         case EKEYEXPIRED: return DRWAV_ERROR;
02782     #endif
02783     #ifdef EKEYREVOKED
02784         case EKEYREVOKED: return DRWAV_ERROR;
02785     #endif
02786     #ifdef EKEYREJECTED
02787         case EKEYREJECTED: return DRWAV_ERROR;
02788     #endif
02789     #ifdef EOWNERDEAD
02790         case EOWNERDEAD: return DRWAV_ERROR;
02791     #endif
02792     #ifdef ENOTRECOVERABLE
02793         case ENOTRECOVERABLE: return DRWAV_ERROR;
02794     #endif
02795     #ifdef ERFKILL
02796         case ERFKILL: return DRWAV_ERROR;
02797     #endif
02798     #ifdef EHWPOISON
02799         case EHWPOISON: return DRWAV_ERROR;
02800     #endif
02801         default: return DRWAV_ERROR;
02802     }
02803 }
02804 
02805 static drwav_result drwav_fopen(FILE** ppFile, const char* pFilePath, const char* pOpenMode)
02806 {
02807 #if _MSC_VER && _MSC_VER >= 1400
02808     errno_t err;
02809 #endif
02810 
02811     if (ppFile != NULL) {
02812         *ppFile = NULL;  /* Safety. */
02813     }
02814 
02815     if (pFilePath == NULL || pOpenMode == NULL || ppFile == NULL) {
02816         return DRWAV_INVALID_ARGS;
02817     }
02818 
02819 #if _MSC_VER && _MSC_VER >= 1400
02820     err = fopen_s(ppFile, pFilePath, pOpenMode);
02821     if (err != 0) {
02822         return drwav_result_from_errno(err);
02823     }
02824 #else
02825 #if defined(_WIN32) || defined(__APPLE__)
02826     *ppFile = fopen(pFilePath, pOpenMode);
02827 #else
02828     #if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64 && defined(_LARGEFILE64_SOURCE)
02829         *ppFile = fopen64(pFilePath, pOpenMode);
02830     #else
02831         *ppFile = fopen(pFilePath, pOpenMode);
02832     #endif
02833 #endif
02834     if (*ppFile == NULL) {
02835         drwav_result result = drwav_result_from_errno(errno);
02836         if (result == DRWAV_SUCCESS) {
02837             result = DRWAV_ERROR;   /* Just a safety check to make sure we never ever return success when pFile == NULL. */
02838         }
02839 
02840         return result;
02841     }
02842 #endif
02843 
02844     return DRWAV_SUCCESS;
02845 }
02846 
02847 /*
02848 _wfopen() isn't always available in all compilation environments.
02849 
02850     * Windows only.
02851     * MSVC seems to support it universally as far back as VC6 from what I can tell (haven't checked further back).
02852     * MinGW-64 (both 32- and 64-bit) seems to support it.
02853     * MinGW wraps it in !defined(__STRICT_ANSI__).
02854 
02855 This can be reviewed as compatibility issues arise. The preference is to use _wfopen_s() and _wfopen() as opposed to the wcsrtombs()
02856 fallback, so if you notice your compiler not detecting this properly I'm happy to look at adding support.
02857 */
02858 #if defined(_WIN32)
02859     #if defined(_MSC_VER) || defined(__MINGW64__) || !defined(__STRICT_ANSI__)
02860         #define DRWAV_HAS_WFOPEN
02861     #endif
02862 #endif
02863 
02864 static drwav_result drwav_wfopen(FILE** ppFile, const wchar_t* pFilePath, const wchar_t* pOpenMode, const drwav_allocation_callbacks* pAllocationCallbacks)
02865 {
02866     if (ppFile != NULL) {
02867         *ppFile = NULL;  /* Safety. */
02868     }
02869 
02870     if (pFilePath == NULL || pOpenMode == NULL || ppFile == NULL) {
02871         return DRWAV_INVALID_ARGS;
02872     }
02873 
02874 #if defined(DRWAV_HAS_WFOPEN)
02875     {
02876         /* Use _wfopen() on Windows. */
02877     #if defined(_MSC_VER) && _MSC_VER >= 1400
02878         errno_t err = _wfopen_s(ppFile, pFilePath, pOpenMode);
02879         if (err != 0) {
02880             return drwav_result_from_errno(err);
02881         }
02882     #else
02883         *ppFile = _wfopen(pFilePath, pOpenMode);
02884         if (*ppFile == NULL) {
02885             return drwav_result_from_errno(errno);
02886         }
02887     #endif
02888         (void)pAllocationCallbacks;
02889     }
02890 #else
02891     /*
02892     Use fopen() on anything other than Windows. Requires a conversion. This is annoying because fopen() is locale specific. The only real way I can
02893     think of to do this is with wcsrtombs(). Note that wcstombs() is apparently not thread-safe because it uses a static global mbstate_t object for
02894     maintaining state. I've checked this with -std=c89 and it works, but if somebody get's a compiler error I'll look into improving compatibility.
02895     */
02896     {
02897         mbstate_t mbs;
02898         size_t lenMB;
02899         const wchar_t* pFilePathTemp = pFilePath;
02900         char* pFilePathMB = NULL;
02901         char pOpenModeMB[32] = {0};
02902 
02903         /* Get the length first. */
02904         DRWAV_ZERO_OBJECT(&mbs);
02905         lenMB = wcsrtombs(NULL, &pFilePathTemp, 0, &mbs);
02906         if (lenMB == (size_t)-1) {
02907             return drwav_result_from_errno(errno);
02908         }
02909 
02910         pFilePathMB = (char*)drwav__malloc_from_callbacks(lenMB + 1, pAllocationCallbacks);
02911         if (pFilePathMB == NULL) {
02912             return DRWAV_OUT_OF_MEMORY;
02913         }
02914 
02915         pFilePathTemp = pFilePath;
02916         DRWAV_ZERO_OBJECT(&mbs);
02917         wcsrtombs(pFilePathMB, &pFilePathTemp, lenMB + 1, &mbs);
02918 
02919         /* The open mode should always consist of ASCII characters so we should be able to do a trivial conversion. */
02920         {
02921             size_t i = 0;
02922             for (;;) {
02923                 if (pOpenMode[i] == 0) {
02924                     pOpenModeMB[i] = '\0';
02925                     break;
02926                 }
02927 
02928                 pOpenModeMB[i] = (char)pOpenMode[i];
02929                 i += 1;
02930             }
02931         }
02932 
02933         *ppFile = fopen(pFilePathMB, pOpenModeMB);
02934 
02935         drwav__free_from_callbacks(pFilePathMB, pAllocationCallbacks);
02936     }
02937 
02938     if (*ppFile == NULL) {
02939         return DRWAV_ERROR;
02940     }
02941 #endif
02942 
02943     return DRWAV_SUCCESS;
02944 }
02945 
02946 
02947 static size_t drwav__on_read_stdio(void* pUserData, void* pBufferOut, size_t bytesToRead)
02948 {
02949     return fread(pBufferOut, 1, bytesToRead, (FILE*)pUserData);
02950 }
02951 
02952 static size_t drwav__on_write_stdio(void* pUserData, const void* pData, size_t bytesToWrite)
02953 {
02954     return fwrite(pData, 1, bytesToWrite, (FILE*)pUserData);
02955 }
02956 
02957 static drwav_bool32 drwav__on_seek_stdio(void* pUserData, int offset, drwav_seek_origin origin)
02958 {
02959     return fseek((FILE*)pUserData, offset, (origin == drwav_seek_origin_current) ? SEEK_CUR : SEEK_SET) == 0;
02960 }
02961 
02962 DRWAV_API drwav_bool32 drwav_init_file(drwav* pWav, const char* filename, const drwav_allocation_callbacks* pAllocationCallbacks)
02963 {
02964     return drwav_init_file_ex(pWav, filename, NULL, NULL, 0, pAllocationCallbacks);
02965 }
02966 
02967 
02968 static drwav_bool32 drwav_init_file__internal_FILE(drwav* pWav, FILE* pFile, drwav_chunk_proc onChunk, void* pChunkUserData, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks)
02969 {
02970     drwav_bool32 result;
02971 
02972     result = drwav_preinit(pWav, drwav__on_read_stdio, drwav__on_seek_stdio, (void*)pFile, pAllocationCallbacks);
02973     if (result != DRWAV_TRUE) {
02974         fclose(pFile);
02975         return result;
02976     }
02977 
02978     result = drwav_init__internal(pWav, onChunk, pChunkUserData, flags);
02979     if (result != DRWAV_TRUE) {
02980         fclose(pFile);
02981         return result;
02982     }
02983 
02984     return DRWAV_TRUE;
02985 }
02986 
02987 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)
02988 {
02989     FILE* pFile;
02990     if (drwav_fopen(&pFile, filename, "rb") != DRWAV_SUCCESS) {
02991         return DRWAV_FALSE;
02992     }
02993 
02994     /* This takes ownership of the FILE* object. */
02995     return drwav_init_file__internal_FILE(pWav, pFile, onChunk, pChunkUserData, flags, pAllocationCallbacks);
02996 }
02997 
02998 DRWAV_API drwav_bool32 drwav_init_file_w(drwav* pWav, const wchar_t* filename, const drwav_allocation_callbacks* pAllocationCallbacks)
02999 {
03000     return drwav_init_file_ex_w(pWav, filename, NULL, NULL, 0, pAllocationCallbacks);
03001 }
03002 
03003 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)
03004 {
03005     FILE* pFile;
03006     if (drwav_wfopen(&pFile, filename, L"rb", pAllocationCallbacks) != DRWAV_SUCCESS) {
03007         return DRWAV_FALSE;
03008     }
03009 
03010     /* This takes ownership of the FILE* object. */
03011     return drwav_init_file__internal_FILE(pWav, pFile, onChunk, pChunkUserData, flags, pAllocationCallbacks);
03012 }
03013 
03014 
03015 static drwav_bool32 drwav_init_file_write__internal_FILE(drwav* pWav, FILE* pFile, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount, drwav_bool32 isSequential, const drwav_allocation_callbacks* pAllocationCallbacks)
03016 {
03017     drwav_bool32 result;
03018 
03019     result = drwav_preinit_write(pWav, pFormat, isSequential, drwav__on_write_stdio, drwav__on_seek_stdio, (void*)pFile, pAllocationCallbacks);
03020     if (result != DRWAV_TRUE) {
03021         fclose(pFile);
03022         return result;
03023     }
03024 
03025     result = drwav_init_write__internal(pWav, pFormat, totalSampleCount);
03026     if (result != DRWAV_TRUE) {
03027         fclose(pFile);
03028         return result;
03029     }
03030 
03031     return DRWAV_TRUE;
03032 }
03033 
03034 static drwav_bool32 drwav_init_file_write__internal(drwav* pWav, const char* filename, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount, drwav_bool32 isSequential, const drwav_allocation_callbacks* pAllocationCallbacks)
03035 {
03036     FILE* pFile;
03037     if (drwav_fopen(&pFile, filename, "wb") != DRWAV_SUCCESS) {
03038         return DRWAV_FALSE;
03039     }
03040 
03041     /* This takes ownership of the FILE* object. */
03042     return drwav_init_file_write__internal_FILE(pWav, pFile, pFormat, totalSampleCount, isSequential, pAllocationCallbacks);
03043 }
03044 
03045 static drwav_bool32 drwav_init_file_write_w__internal(drwav* pWav, const wchar_t* filename, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount, drwav_bool32 isSequential, const drwav_allocation_callbacks* pAllocationCallbacks)
03046 {
03047     FILE* pFile;
03048     if (drwav_wfopen(&pFile, filename, L"wb", pAllocationCallbacks) != DRWAV_SUCCESS) {
03049         return DRWAV_FALSE;
03050     }
03051 
03052     /* This takes ownership of the FILE* object. */
03053     return drwav_init_file_write__internal_FILE(pWav, pFile, pFormat, totalSampleCount, isSequential, pAllocationCallbacks);
03054 }
03055 
03056 DRWAV_API drwav_bool32 drwav_init_file_write(drwav* pWav, const char* filename, const drwav_data_format* pFormat, const drwav_allocation_callbacks* pAllocationCallbacks)
03057 {
03058     return drwav_init_file_write__internal(pWav, filename, pFormat, 0, DRWAV_FALSE, pAllocationCallbacks);
03059 }
03060 
03061 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)
03062 {
03063     return drwav_init_file_write__internal(pWav, filename, pFormat, totalSampleCount, DRWAV_TRUE, pAllocationCallbacks);
03064 }
03065 
03066 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)
03067 {
03068     if (pFormat == NULL) {
03069         return DRWAV_FALSE;
03070     }
03071 
03072     return drwav_init_file_write_sequential(pWav, filename, pFormat, totalPCMFrameCount*pFormat->channels, pAllocationCallbacks);
03073 }
03074 
03075 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)
03076 {
03077     return drwav_init_file_write_w__internal(pWav, filename, pFormat, 0, DRWAV_FALSE, pAllocationCallbacks);
03078 }
03079 
03080 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)
03081 {
03082     return drwav_init_file_write_w__internal(pWav, filename, pFormat, totalSampleCount, DRWAV_TRUE, pAllocationCallbacks);
03083 }
03084 
03085 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)
03086 {
03087     if (pFormat == NULL) {
03088         return DRWAV_FALSE;
03089     }
03090 
03091     return drwav_init_file_write_sequential_w(pWav, filename, pFormat, totalPCMFrameCount*pFormat->channels, pAllocationCallbacks);
03092 }
03093 #endif  /* DR_WAV_NO_STDIO */
03094 
03095 
03096 static size_t drwav__on_read_memory(void* pUserData, void* pBufferOut, size_t bytesToRead)
03097 {
03098     drwav* pWav = (drwav*)pUserData;
03099     size_t bytesRemaining;
03100 
03101     DRWAV_ASSERT(pWav != NULL);
03102     DRWAV_ASSERT(pWav->memoryStream.dataSize >= pWav->memoryStream.currentReadPos);
03103 
03104     bytesRemaining = pWav->memoryStream.dataSize - pWav->memoryStream.currentReadPos;
03105     if (bytesToRead > bytesRemaining) {
03106         bytesToRead = bytesRemaining;
03107     }
03108 
03109     if (bytesToRead > 0) {
03110         DRWAV_COPY_MEMORY(pBufferOut, pWav->memoryStream.data + pWav->memoryStream.currentReadPos, bytesToRead);
03111         pWav->memoryStream.currentReadPos += bytesToRead;
03112     }
03113 
03114     return bytesToRead;
03115 }
03116 
03117 static drwav_bool32 drwav__on_seek_memory(void* pUserData, int offset, drwav_seek_origin origin)
03118 {
03119     drwav* pWav = (drwav*)pUserData;
03120     DRWAV_ASSERT(pWav != NULL);
03121 
03122     if (origin == drwav_seek_origin_current) {
03123         if (offset > 0) {
03124             if (pWav->memoryStream.currentReadPos + offset > pWav->memoryStream.dataSize) {
03125                 return DRWAV_FALSE; /* Trying to seek too far forward. */
03126             }
03127         } else {
03128             if (pWav->memoryStream.currentReadPos < (size_t)-offset) {
03129                 return DRWAV_FALSE; /* Trying to seek too far backwards. */
03130             }
03131         }
03132 
03133         /* This will never underflow thanks to the clamps above. */
03134         pWav->memoryStream.currentReadPos += offset;
03135     } else {
03136         if ((drwav_uint32)offset <= pWav->memoryStream.dataSize) {
03137             pWav->memoryStream.currentReadPos = offset;
03138         } else {
03139             return DRWAV_FALSE; /* Trying to seek too far forward. */
03140         }
03141     }
03142     
03143     return DRWAV_TRUE;
03144 }
03145 
03146 static size_t drwav__on_write_memory(void* pUserData, const void* pDataIn, size_t bytesToWrite)
03147 {
03148     drwav* pWav = (drwav*)pUserData;
03149     size_t bytesRemaining;
03150 
03151     DRWAV_ASSERT(pWav != NULL);
03152     DRWAV_ASSERT(pWav->memoryStreamWrite.dataCapacity >= pWav->memoryStreamWrite.currentWritePos);
03153 
03154     bytesRemaining = pWav->memoryStreamWrite.dataCapacity - pWav->memoryStreamWrite.currentWritePos;
03155     if (bytesRemaining < bytesToWrite) {
03156         /* Need to reallocate. */
03157         void* pNewData;
03158         size_t newDataCapacity = (pWav->memoryStreamWrite.dataCapacity == 0) ? 256 : pWav->memoryStreamWrite.dataCapacity * 2;
03159 
03160         /* If doubling wasn't enough, just make it the minimum required size to write the data. */
03161         if ((newDataCapacity - pWav->memoryStreamWrite.currentWritePos) < bytesToWrite) {
03162             newDataCapacity = pWav->memoryStreamWrite.currentWritePos + bytesToWrite;
03163         }
03164 
03165         pNewData = drwav__realloc_from_callbacks(*pWav->memoryStreamWrite.ppData, newDataCapacity, pWav->memoryStreamWrite.dataCapacity, &pWav->allocationCallbacks);
03166         if (pNewData == NULL) {
03167             return 0;
03168         }
03169 
03170         *pWav->memoryStreamWrite.ppData = pNewData;
03171         pWav->memoryStreamWrite.dataCapacity = newDataCapacity;
03172     }
03173 
03174     DRWAV_COPY_MEMORY(((drwav_uint8*)(*pWav->memoryStreamWrite.ppData)) + pWav->memoryStreamWrite.currentWritePos, pDataIn, bytesToWrite);
03175 
03176     pWav->memoryStreamWrite.currentWritePos += bytesToWrite;
03177     if (pWav->memoryStreamWrite.dataSize < pWav->memoryStreamWrite.currentWritePos) {
03178         pWav->memoryStreamWrite.dataSize = pWav->memoryStreamWrite.currentWritePos;
03179     }
03180 
03181     *pWav->memoryStreamWrite.pDataSize = pWav->memoryStreamWrite.dataSize;
03182 
03183     return bytesToWrite;
03184 }
03185 
03186 static drwav_bool32 drwav__on_seek_memory_write(void* pUserData, int offset, drwav_seek_origin origin)
03187 {
03188     drwav* pWav = (drwav*)pUserData;
03189     DRWAV_ASSERT(pWav != NULL);
03190 
03191     if (origin == drwav_seek_origin_current) {
03192         if (offset > 0) {
03193             if (pWav->memoryStreamWrite.currentWritePos + offset > pWav->memoryStreamWrite.dataSize) {
03194                 offset = (int)(pWav->memoryStreamWrite.dataSize - pWav->memoryStreamWrite.currentWritePos);  /* Trying to seek too far forward. */
03195             }
03196         } else {
03197             if (pWav->memoryStreamWrite.currentWritePos < (size_t)-offset) {
03198                 offset = -(int)pWav->memoryStreamWrite.currentWritePos;  /* Trying to seek too far backwards. */
03199             }
03200         }
03201 
03202         /* This will never underflow thanks to the clamps above. */
03203         pWav->memoryStreamWrite.currentWritePos += offset;
03204     } else {
03205         if ((drwav_uint32)offset <= pWav->memoryStreamWrite.dataSize) {
03206             pWav->memoryStreamWrite.currentWritePos = offset;
03207         } else {
03208             pWav->memoryStreamWrite.currentWritePos = pWav->memoryStreamWrite.dataSize;  /* Trying to seek too far forward. */
03209         }
03210     }
03211     
03212     return DRWAV_TRUE;
03213 }
03214 
03215 DRWAV_API drwav_bool32 drwav_init_memory(drwav* pWav, const void* data, size_t dataSize, const drwav_allocation_callbacks* pAllocationCallbacks)
03216 {
03217     return drwav_init_memory_ex(pWav, data, dataSize, NULL, NULL, 0, pAllocationCallbacks);
03218 }
03219 
03220 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)
03221 {
03222     if (data == NULL || dataSize == 0) {
03223         return DRWAV_FALSE;
03224     }
03225 
03226     if (!drwav_preinit(pWav, drwav__on_read_memory, drwav__on_seek_memory, pWav, pAllocationCallbacks)) {
03227         return DRWAV_FALSE;
03228     }
03229 
03230     pWav->memoryStream.data = (const drwav_uint8*)data;
03231     pWav->memoryStream.dataSize = dataSize;
03232     pWav->memoryStream.currentReadPos = 0;
03233 
03234     return drwav_init__internal(pWav, onChunk, pChunkUserData, flags);
03235 }
03236 
03237 
03238 static drwav_bool32 drwav_init_memory_write__internal(drwav* pWav, void** ppData, size_t* pDataSize, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount, drwav_bool32 isSequential, const drwav_allocation_callbacks* pAllocationCallbacks)
03239 {
03240     if (ppData == NULL || pDataSize == NULL) {
03241         return DRWAV_FALSE;
03242     }
03243 
03244     *ppData = NULL; /* Important because we're using realloc()! */
03245     *pDataSize = 0;
03246 
03247     if (!drwav_preinit_write(pWav, pFormat, isSequential, drwav__on_write_memory, drwav__on_seek_memory_write, pWav, pAllocationCallbacks)) {
03248         return DRWAV_FALSE;
03249     }
03250 
03251     pWav->memoryStreamWrite.ppData = ppData;
03252     pWav->memoryStreamWrite.pDataSize = pDataSize;
03253     pWav->memoryStreamWrite.dataSize = 0;
03254     pWav->memoryStreamWrite.dataCapacity = 0;
03255     pWav->memoryStreamWrite.currentWritePos = 0;
03256 
03257     return drwav_init_write__internal(pWav, pFormat, totalSampleCount);
03258 }
03259 
03260 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)
03261 {
03262     return drwav_init_memory_write__internal(pWav, ppData, pDataSize, pFormat, 0, DRWAV_FALSE, pAllocationCallbacks);
03263 }
03264 
03265 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)
03266 {
03267     return drwav_init_memory_write__internal(pWav, ppData, pDataSize, pFormat, totalSampleCount, DRWAV_TRUE, pAllocationCallbacks);
03268 }
03269 
03270 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)
03271 {
03272     if (pFormat == NULL) {
03273         return DRWAV_FALSE;
03274     }
03275 
03276     return drwav_init_memory_write_sequential(pWav, ppData, pDataSize, pFormat, totalPCMFrameCount*pFormat->channels, pAllocationCallbacks);
03277 }
03278 
03279 
03280 
03281 DRWAV_API drwav_result drwav_uninit(drwav* pWav)
03282 {
03283     drwav_result result = DRWAV_SUCCESS;
03284 
03285     if (pWav == NULL) {
03286         return DRWAV_INVALID_ARGS;
03287     }
03288 
03289     /*
03290     If the drwav object was opened in write mode we'll need to finalize a few things:
03291       - Make sure the "data" chunk is aligned to 16-bits for RIFF containers, or 64 bits for W64 containers.
03292       - Set the size of the "data" chunk.
03293     */
03294     if (pWav->onWrite != NULL) {
03295         drwav_uint32 paddingSize = 0;
03296 
03297         /* Padding. Do not adjust pWav->dataChunkDataSize - this should not include the padding. */
03298         if (pWav->container == drwav_container_riff) {
03299             paddingSize = drwav__chunk_padding_size_riff(pWav->dataChunkDataSize);
03300         } else {
03301             paddingSize = drwav__chunk_padding_size_w64(pWav->dataChunkDataSize);
03302         }
03303         
03304         if (paddingSize > 0) {
03305             drwav_uint64 paddingData = 0;
03306             pWav->onWrite(pWav->pUserData, &paddingData, paddingSize);
03307         }
03308 
03309         /*
03310         Chunk sizes. When using sequential mode, these will have been filled in at initialization time. We only need
03311         to do this when using non-sequential mode.
03312         */
03313         if (pWav->onSeek && !pWav->isSequentialWrite) {
03314             if (pWav->container == drwav_container_riff) {
03315                 /* The "RIFF" chunk size. */
03316                 if (pWav->onSeek(pWav->pUserData, 4, drwav_seek_origin_start)) {
03317                     drwav_uint32 riffChunkSize = drwav__riff_chunk_size_riff(pWav->dataChunkDataSize);
03318                     pWav->onWrite(pWav->pUserData, &riffChunkSize, 4);
03319                 }
03320 
03321                 /* the "data" chunk size. */
03322                 if (pWav->onSeek(pWav->pUserData, (int)pWav->dataChunkDataPos + 4, drwav_seek_origin_start)) {
03323                     drwav_uint32 dataChunkSize = drwav__data_chunk_size_riff(pWav->dataChunkDataSize);
03324                     pWav->onWrite(pWav->pUserData, &dataChunkSize, 4);
03325                 }
03326             } else {
03327                 /* The "RIFF" chunk size. */
03328                 if (pWav->onSeek(pWav->pUserData, 16, drwav_seek_origin_start)) {
03329                     drwav_uint64 riffChunkSize = drwav__riff_chunk_size_w64(pWav->dataChunkDataSize);
03330                     pWav->onWrite(pWav->pUserData, &riffChunkSize, 8);
03331                 }
03332 
03333                 /* The "data" chunk size. */
03334                 if (pWav->onSeek(pWav->pUserData, (int)pWav->dataChunkDataPos + 16, drwav_seek_origin_start)) {
03335                     drwav_uint64 dataChunkSize = drwav__data_chunk_size_w64(pWav->dataChunkDataSize);
03336                     pWav->onWrite(pWav->pUserData, &dataChunkSize, 8);
03337                 }
03338             }
03339         }
03340 
03341         /* Validation for sequential mode. */
03342         if (pWav->isSequentialWrite) {
03343             if (pWav->dataChunkDataSize != pWav->dataChunkDataSizeTargetWrite) {
03344                 result = DRWAV_INVALID_FILE;
03345             }
03346         }
03347     }
03348 
03349 #ifndef DR_WAV_NO_STDIO
03350     /*
03351     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()
03352     was used by looking at the onRead and onSeek callbacks.
03353     */
03354     if (pWav->onRead == drwav__on_read_stdio || pWav->onWrite == drwav__on_write_stdio) {
03355         fclose((FILE*)pWav->pUserData);
03356     }
03357 #endif
03358 
03359     return result;
03360 }
03361 
03362 
03363 
03364 DRWAV_API size_t drwav_read_raw(drwav* pWav, size_t bytesToRead, void* pBufferOut)
03365 {
03366     size_t bytesRead;
03367 
03368     if (pWav == NULL || bytesToRead == 0 || pBufferOut == NULL) {
03369         return 0;
03370     }
03371 
03372     if (bytesToRead > pWav->bytesRemaining) {
03373         bytesToRead = (size_t)pWav->bytesRemaining;
03374     }
03375 
03376     bytesRead = pWav->onRead(pWav->pUserData, pBufferOut, bytesToRead);
03377 
03378     pWav->bytesRemaining -= bytesRead;
03379     return bytesRead;
03380 }
03381 
03382 
03383 
03384 DRWAV_API drwav_uint64 drwav_read_pcm_frames_le(drwav* pWav, drwav_uint64 framesToRead, void* pBufferOut)
03385 {
03386     drwav_uint32 bytesPerFrame;
03387 
03388     if (pWav == NULL || framesToRead == 0 || pBufferOut == NULL) {
03389         return 0;
03390     }
03391 
03392     /* Cannot use this function for compressed formats. */
03393     if (drwav__is_compressed_format_tag(pWav->translatedFormatTag)) {
03394         return 0;
03395     }
03396 
03397     bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
03398     if (bytesPerFrame == 0) {
03399         return 0;
03400     }
03401 
03402     /* Don't try to read more samples than can potentially fit in the output buffer. */
03403     if (framesToRead * bytesPerFrame > DRWAV_SIZE_MAX) {
03404         framesToRead = DRWAV_SIZE_MAX / bytesPerFrame;
03405     }
03406 
03407     return drwav_read_raw(pWav, (size_t)(framesToRead * bytesPerFrame), pBufferOut) / bytesPerFrame;
03408 }
03409 
03410 DRWAV_API drwav_uint64 drwav_read_pcm_frames_be(drwav* pWav, drwav_uint64 framesToRead, void* pBufferOut)
03411 {
03412     drwav_uint64 framesRead = drwav_read_pcm_frames_le(pWav, framesToRead, pBufferOut);
03413     drwav__bswap_samples(pBufferOut, framesRead*pWav->channels, drwav_get_bytes_per_pcm_frame(pWav)/pWav->channels, pWav->translatedFormatTag);
03414 
03415     return framesRead;
03416 }
03417 
03418 DRWAV_API drwav_uint64 drwav_read_pcm_frames(drwav* pWav, drwav_uint64 framesToRead, void* pBufferOut)
03419 {
03420     if (drwav__is_little_endian()) {
03421         return drwav_read_pcm_frames_le(pWav, framesToRead, pBufferOut);
03422     } else {
03423         return drwav_read_pcm_frames_be(pWav, framesToRead, pBufferOut);
03424     }
03425 }
03426 
03427 
03428 
03429 DRWAV_API drwav_bool32 drwav_seek_to_first_pcm_frame(drwav* pWav)
03430 {
03431     if (pWav->onWrite != NULL) {
03432         return DRWAV_FALSE; /* No seeking in write mode. */
03433     }
03434 
03435     if (!pWav->onSeek(pWav->pUserData, (int)pWav->dataChunkDataPos, drwav_seek_origin_start)) {
03436         return DRWAV_FALSE;
03437     }
03438 
03439     if (drwav__is_compressed_format_tag(pWav->translatedFormatTag)) {
03440         pWav->compressed.iCurrentPCMFrame = 0;
03441     }
03442     
03443     pWav->bytesRemaining = pWav->dataChunkDataSize;
03444     return DRWAV_TRUE;
03445 }
03446 
03447 DRWAV_API drwav_bool32 drwav_seek_to_pcm_frame(drwav* pWav, drwav_uint64 targetFrameIndex)
03448 {
03449     /* Seeking should be compatible with wave files > 2GB. */
03450 
03451     if (pWav == NULL || pWav->onSeek == NULL) {
03452         return DRWAV_FALSE;
03453     }
03454 
03455     /* No seeking in write mode. */
03456     if (pWav->onWrite != NULL) {
03457         return DRWAV_FALSE;
03458     }
03459 
03460     /* If there are no samples, just return DRWAV_TRUE without doing anything. */
03461     if (pWav->totalPCMFrameCount == 0) {
03462         return DRWAV_TRUE;
03463     }
03464 
03465     /* Make sure the sample is clamped. */
03466     if (targetFrameIndex >= pWav->totalPCMFrameCount) {
03467         targetFrameIndex  = pWav->totalPCMFrameCount - 1;
03468     }
03469 
03470     /*
03471     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
03472     to seek back to the start.
03473     */
03474     if (drwav__is_compressed_format_tag(pWav->translatedFormatTag)) {
03475         /* TODO: This can be optimized. */
03476         
03477         /*
03478         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,
03479         we first need to seek back to the start and then just do the same thing as a forward seek.
03480         */
03481         if (targetFrameIndex < pWav->compressed.iCurrentPCMFrame) {
03482             if (!drwav_seek_to_first_pcm_frame(pWav)) {
03483                 return DRWAV_FALSE;
03484             }
03485         }
03486 
03487         if (targetFrameIndex > pWav->compressed.iCurrentPCMFrame) {
03488             drwav_uint64 offsetInFrames = targetFrameIndex - pWav->compressed.iCurrentPCMFrame;
03489 
03490             drwav_int16 devnull[2048];
03491             while (offsetInFrames > 0) {
03492                 drwav_uint64 framesRead = 0;
03493                 drwav_uint64 framesToRead = offsetInFrames;
03494                 if (framesToRead > drwav_countof(devnull)/pWav->channels) {
03495                     framesToRead = drwav_countof(devnull)/pWav->channels;
03496                 }
03497 
03498                 if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ADPCM) {
03499                     framesRead = drwav_read_pcm_frames_s16__msadpcm(pWav, framesToRead, devnull);
03500                 } else if (pWav->translatedFormatTag == DR_WAVE_FORMAT_DVI_ADPCM) {
03501                     framesRead = drwav_read_pcm_frames_s16__ima(pWav, framesToRead, devnull);
03502                 } else {
03503                     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. */
03504                 }
03505 
03506                 if (framesRead != framesToRead) {
03507                     return DRWAV_FALSE;
03508                 }
03509 
03510                 offsetInFrames -= framesRead;
03511             }
03512         }
03513     } else {
03514         drwav_uint64 totalSizeInBytes;
03515         drwav_uint64 currentBytePos;
03516         drwav_uint64 targetBytePos;
03517         drwav_uint64 offset;
03518 
03519         totalSizeInBytes = pWav->totalPCMFrameCount * drwav_get_bytes_per_pcm_frame(pWav);
03520         DRWAV_ASSERT(totalSizeInBytes >= pWav->bytesRemaining);
03521 
03522         currentBytePos = totalSizeInBytes - pWav->bytesRemaining;
03523         targetBytePos  = targetFrameIndex * drwav_get_bytes_per_pcm_frame(pWav);
03524 
03525         if (currentBytePos < targetBytePos) {
03526             /* Offset forwards. */
03527             offset = (targetBytePos - currentBytePos);
03528         } else {
03529             /* Offset backwards. */
03530             if (!drwav_seek_to_first_pcm_frame(pWav)) {
03531                 return DRWAV_FALSE;
03532             }
03533             offset = targetBytePos;
03534         }
03535 
03536         while (offset > 0) {
03537             int offset32 = ((offset > INT_MAX) ? INT_MAX : (int)offset);
03538             if (!pWav->onSeek(pWav->pUserData, offset32, drwav_seek_origin_current)) {
03539                 return DRWAV_FALSE;
03540             }
03541 
03542             pWav->bytesRemaining -= offset32;
03543             offset -= offset32;
03544         }
03545     }
03546 
03547     return DRWAV_TRUE;
03548 }
03549 
03550 
03551 DRWAV_API size_t drwav_write_raw(drwav* pWav, size_t bytesToWrite, const void* pData)
03552 {
03553     size_t bytesWritten;
03554 
03555     if (pWav == NULL || bytesToWrite == 0 || pData == NULL) {
03556         return 0;
03557     }
03558 
03559     bytesWritten = pWav->onWrite(pWav->pUserData, pData, bytesToWrite);
03560     pWav->dataChunkDataSize += bytesWritten;
03561 
03562     return bytesWritten;
03563 }
03564 
03565 
03566 DRWAV_API drwav_uint64 drwav_write_pcm_frames_le(drwav* pWav, drwav_uint64 framesToWrite, const void* pData)
03567 {
03568     drwav_uint64 bytesToWrite;
03569     drwav_uint64 bytesWritten;
03570     const drwav_uint8* pRunningData;
03571 
03572     if (pWav == NULL || framesToWrite == 0 || pData == NULL) {
03573         return 0;
03574     }
03575 
03576     bytesToWrite = ((framesToWrite * pWav->channels * pWav->bitsPerSample) / 8);
03577     if (bytesToWrite > DRWAV_SIZE_MAX) {
03578         return 0;
03579     }
03580 
03581     bytesWritten = 0;
03582     pRunningData = (const drwav_uint8*)pData;
03583 
03584     while (bytesToWrite > 0) {
03585         size_t bytesJustWritten;
03586         drwav_uint64 bytesToWriteThisIteration;
03587 
03588         bytesToWriteThisIteration = bytesToWrite;
03589         DRWAV_ASSERT(bytesToWriteThisIteration <= DRWAV_SIZE_MAX);  /* <-- This is checked above. */
03590 
03591         bytesJustWritten = drwav_write_raw(pWav, (size_t)bytesToWriteThisIteration, pRunningData);
03592         if (bytesJustWritten == 0) {
03593             break;
03594         }
03595 
03596         bytesToWrite -= bytesJustWritten;
03597         bytesWritten += bytesJustWritten;
03598         pRunningData += bytesJustWritten;
03599     }
03600 
03601     return (bytesWritten * 8) / pWav->bitsPerSample / pWav->channels;
03602 }
03603 
03604 DRWAV_API drwav_uint64 drwav_write_pcm_frames_be(drwav* pWav, drwav_uint64 framesToWrite, const void* pData)
03605 {
03606     drwav_uint64 bytesToWrite;
03607     drwav_uint64 bytesWritten;
03608     drwav_uint32 bytesPerSample;
03609     const drwav_uint8* pRunningData;
03610 
03611     if (pWav == NULL || framesToWrite == 0 || pData == NULL) {
03612         return 0;
03613     }
03614 
03615     bytesToWrite = ((framesToWrite * pWav->channels * pWav->bitsPerSample) / 8);
03616     if (bytesToWrite > DRWAV_SIZE_MAX) {
03617         return 0;
03618     }
03619 
03620     bytesWritten = 0;
03621     pRunningData = (const drwav_uint8*)pData;
03622 
03623     bytesPerSample = drwav_get_bytes_per_pcm_frame(pWav) / pWav->channels;
03624     
03625     while (bytesToWrite > 0) {
03626         drwav_uint8 temp[4096];
03627         drwav_uint32 sampleCount;
03628         size_t bytesJustWritten;
03629         drwav_uint64 bytesToWriteThisIteration;
03630 
03631         bytesToWriteThisIteration = bytesToWrite;
03632         DRWAV_ASSERT(bytesToWriteThisIteration <= DRWAV_SIZE_MAX);  /* <-- This is checked above. */
03633 
03634         /*
03635         WAV files are always little-endian. We need to byte swap on big-endian architectures. Since our input buffer is read-only we need
03636         to use an intermediary buffer for the conversion.
03637         */
03638         sampleCount = sizeof(temp)/bytesPerSample;
03639 
03640         if (bytesToWriteThisIteration > ((drwav_uint64)sampleCount)*bytesPerSample) {
03641             bytesToWriteThisIteration = ((drwav_uint64)sampleCount)*bytesPerSample;
03642         }
03643 
03644         DRWAV_COPY_MEMORY(temp, pRunningData, (size_t)bytesToWriteThisIteration);
03645         drwav__bswap_samples(temp, sampleCount, bytesPerSample, pWav->translatedFormatTag);
03646 
03647         bytesJustWritten = drwav_write_raw(pWav, (size_t)bytesToWriteThisIteration, temp);
03648         if (bytesJustWritten == 0) {
03649             break;
03650         }
03651 
03652         bytesToWrite -= bytesJustWritten;
03653         bytesWritten += bytesJustWritten;
03654         pRunningData += bytesJustWritten;
03655     }
03656 
03657     return (bytesWritten * 8) / pWav->bitsPerSample / pWav->channels;
03658 }
03659 
03660 DRWAV_API drwav_uint64 drwav_write_pcm_frames(drwav* pWav, drwav_uint64 framesToWrite, const void* pData)
03661 {
03662     if (drwav__is_little_endian()) {
03663         return drwav_write_pcm_frames_le(pWav, framesToWrite, pData);
03664     } else {
03665         return drwav_write_pcm_frames_be(pWav, framesToWrite, pData);
03666     }
03667 }
03668 
03669 
03670 static drwav_uint64 drwav_read_pcm_frames_s16__msadpcm(drwav* pWav, drwav_uint64 framesToRead, drwav_int16* pBufferOut)
03671 {
03672     drwav_uint64 totalFramesRead = 0;
03673 
03674     DRWAV_ASSERT(pWav != NULL);
03675     DRWAV_ASSERT(framesToRead > 0);
03676     DRWAV_ASSERT(pBufferOut != NULL);
03677 
03678     /* TODO: Lots of room for optimization here. */
03679 
03680     while (framesToRead > 0 && pWav->compressed.iCurrentPCMFrame < pWav->totalPCMFrameCount) {
03681         /* If there are no cached frames we need to load a new block. */
03682         if (pWav->msadpcm.cachedFrameCount == 0 && pWav->msadpcm.bytesRemainingInBlock == 0) {
03683             if (pWav->channels == 1) {
03684                 /* Mono. */
03685                 drwav_uint8 header[7];
03686                 if (pWav->onRead(pWav->pUserData, header, sizeof(header)) != sizeof(header)) {
03687                     return totalFramesRead;
03688                 }
03689                 pWav->msadpcm.bytesRemainingInBlock = pWav->fmt.blockAlign - sizeof(header);
03690 
03691                 pWav->msadpcm.predictor[0]     = header[0];
03692                 pWav->msadpcm.delta[0]         = drwav__bytes_to_s16(header + 1);
03693                 pWav->msadpcm.prevFrames[0][1] = (drwav_int32)drwav__bytes_to_s16(header + 3);
03694                 pWav->msadpcm.prevFrames[0][0] = (drwav_int32)drwav__bytes_to_s16(header + 5);
03695                 pWav->msadpcm.cachedFrames[2]  = pWav->msadpcm.prevFrames[0][0];
03696                 pWav->msadpcm.cachedFrames[3]  = pWav->msadpcm.prevFrames[0][1];
03697                 pWav->msadpcm.cachedFrameCount = 2;
03698             } else {
03699                 /* Stereo. */
03700                 drwav_uint8 header[14];
03701                 if (pWav->onRead(pWav->pUserData, header, sizeof(header)) != sizeof(header)) {
03702                     return totalFramesRead;
03703                 }
03704                 pWav->msadpcm.bytesRemainingInBlock = pWav->fmt.blockAlign - sizeof(header);
03705 
03706                 pWav->msadpcm.predictor[0] = header[0];
03707                 pWav->msadpcm.predictor[1] = header[1];
03708                 pWav->msadpcm.delta[0] = drwav__bytes_to_s16(header + 2);
03709                 pWav->msadpcm.delta[1] = drwav__bytes_to_s16(header + 4);
03710                 pWav->msadpcm.prevFrames[0][1] = (drwav_int32)drwav__bytes_to_s16(header + 6);
03711                 pWav->msadpcm.prevFrames[1][1] = (drwav_int32)drwav__bytes_to_s16(header + 8);
03712                 pWav->msadpcm.prevFrames[0][0] = (drwav_int32)drwav__bytes_to_s16(header + 10);
03713                 pWav->msadpcm.prevFrames[1][0] = (drwav_int32)drwav__bytes_to_s16(header + 12);
03714 
03715                 pWav->msadpcm.cachedFrames[0] = pWav->msadpcm.prevFrames[0][0];
03716                 pWav->msadpcm.cachedFrames[1] = pWav->msadpcm.prevFrames[1][0];
03717                 pWav->msadpcm.cachedFrames[2] = pWav->msadpcm.prevFrames[0][1];
03718                 pWav->msadpcm.cachedFrames[3] = pWav->msadpcm.prevFrames[1][1];
03719                 pWav->msadpcm.cachedFrameCount = 2;
03720             }
03721         }
03722 
03723         /* Output anything that's cached. */
03724         while (framesToRead > 0 && pWav->msadpcm.cachedFrameCount > 0 && pWav->compressed.iCurrentPCMFrame < pWav->totalPCMFrameCount) {
03725             drwav_uint32 iSample = 0;
03726             for (iSample = 0; iSample < pWav->channels; iSample += 1) {
03727                 pBufferOut[iSample] = (drwav_int16)pWav->msadpcm.cachedFrames[(drwav_countof(pWav->msadpcm.cachedFrames) - (pWav->msadpcm.cachedFrameCount*pWav->channels)) + iSample];
03728             }
03729 
03730             pBufferOut      += pWav->channels;
03731             framesToRead    -= 1;
03732             totalFramesRead += 1;
03733             pWav->compressed.iCurrentPCMFrame += 1;
03734             pWav->msadpcm.cachedFrameCount -= 1;
03735         }
03736 
03737         if (framesToRead == 0) {
03738             return totalFramesRead;
03739         }
03740 
03741 
03742         /*
03743         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
03744         loop iteration which will trigger the loading of a new block.
03745         */
03746         if (pWav->msadpcm.cachedFrameCount == 0) {
03747             if (pWav->msadpcm.bytesRemainingInBlock == 0) {
03748                 continue;
03749             } else {
03750                 static drwav_int32 adaptationTable[] = { 
03751                     230, 230, 230, 230, 307, 409, 512, 614, 
03752                     768, 614, 512, 409, 307, 230, 230, 230 
03753                 };
03754                 static drwav_int32 coeff1Table[] = { 256, 512, 0, 192, 240, 460,  392 };
03755                 static drwav_int32 coeff2Table[] = { 0,  -256, 0, 64,  0,  -208, -232 };
03756 
03757                 drwav_uint8 nibbles;
03758                 drwav_int32 nibble0;
03759                 drwav_int32 nibble1;
03760 
03761                 if (pWav->onRead(pWav->pUserData, &nibbles, 1) != 1) {
03762                     return totalFramesRead;
03763                 }
03764                 pWav->msadpcm.bytesRemainingInBlock -= 1;
03765 
03766                 /* TODO: Optimize away these if statements. */
03767                 nibble0 = ((nibbles & 0xF0) >> 4); if ((nibbles & 0x80)) { nibble0 |= 0xFFFFFFF0UL; }
03768                 nibble1 = ((nibbles & 0x0F) >> 0); if ((nibbles & 0x08)) { nibble1 |= 0xFFFFFFF0UL; }
03769 
03770                 if (pWav->channels == 1) {
03771                     /* Mono. */
03772                     drwav_int32 newSample0;
03773                     drwav_int32 newSample1;
03774 
03775                     newSample0  = ((pWav->msadpcm.prevFrames[0][1] * coeff1Table[pWav->msadpcm.predictor[0]]) + (pWav->msadpcm.prevFrames[0][0] * coeff2Table[pWav->msadpcm.predictor[0]])) >> 8;
03776                     newSample0 += nibble0 * pWav->msadpcm.delta[0];
03777                     newSample0  = drwav_clamp(newSample0, -32768, 32767);
03778 
03779                     pWav->msadpcm.delta[0] = (adaptationTable[((nibbles & 0xF0) >> 4)] * pWav->msadpcm.delta[0]) >> 8;
03780                     if (pWav->msadpcm.delta[0] < 16) {
03781                         pWav->msadpcm.delta[0] = 16;
03782                     }
03783 
03784                     pWav->msadpcm.prevFrames[0][0] = pWav->msadpcm.prevFrames[0][1];
03785                     pWav->msadpcm.prevFrames[0][1] = newSample0;
03786 
03787 
03788                     newSample1  = ((pWav->msadpcm.prevFrames[0][1] * coeff1Table[pWav->msadpcm.predictor[0]]) + (pWav->msadpcm.prevFrames[0][0] * coeff2Table[pWav->msadpcm.predictor[0]])) >> 8;
03789                     newSample1 += nibble1 * pWav->msadpcm.delta[0];
03790                     newSample1  = drwav_clamp(newSample1, -32768, 32767);
03791 
03792                     pWav->msadpcm.delta[0] = (adaptationTable[((nibbles & 0x0F) >> 0)] * pWav->msadpcm.delta[0]) >> 8;
03793                     if (pWav->msadpcm.delta[0] < 16) {
03794                         pWav->msadpcm.delta[0] = 16;
03795                     }
03796 
03797                     pWav->msadpcm.prevFrames[0][0] = pWav->msadpcm.prevFrames[0][1];
03798                     pWav->msadpcm.prevFrames[0][1] = newSample1;
03799 
03800 
03801                     pWav->msadpcm.cachedFrames[2] = newSample0;
03802                     pWav->msadpcm.cachedFrames[3] = newSample1;
03803                     pWav->msadpcm.cachedFrameCount = 2;
03804                 } else {
03805                     /* Stereo. */
03806                     drwav_int32 newSample0;
03807                     drwav_int32 newSample1;
03808 
03809                     /* Left. */
03810                     newSample0  = ((pWav->msadpcm.prevFrames[0][1] * coeff1Table[pWav->msadpcm.predictor[0]]) + (pWav->msadpcm.prevFrames[0][0] * coeff2Table[pWav->msadpcm.predictor[0]])) >> 8;
03811                     newSample0 += nibble0 * pWav->msadpcm.delta[0];
03812                     newSample0  = drwav_clamp(newSample0, -32768, 32767);
03813 
03814                     pWav->msadpcm.delta[0] = (adaptationTable[((nibbles & 0xF0) >> 4)] * pWav->msadpcm.delta[0]) >> 8;
03815                     if (pWav->msadpcm.delta[0] < 16) {
03816                         pWav->msadpcm.delta[0] = 16;
03817                     }
03818 
03819                     pWav->msadpcm.prevFrames[0][0] = pWav->msadpcm.prevFrames[0][1];
03820                     pWav->msadpcm.prevFrames[0][1] = newSample0;
03821 
03822 
03823                     /* Right. */
03824                     newSample1  = ((pWav->msadpcm.prevFrames[1][1] * coeff1Table[pWav->msadpcm.predictor[1]]) + (pWav->msadpcm.prevFrames[1][0] * coeff2Table[pWav->msadpcm.predictor[1]])) >> 8;
03825                     newSample1 += nibble1 * pWav->msadpcm.delta[1];
03826                     newSample1  = drwav_clamp(newSample1, -32768, 32767);
03827 
03828                     pWav->msadpcm.delta[1] = (adaptationTable[((nibbles & 0x0F) >> 0)] * pWav->msadpcm.delta[1]) >> 8;
03829                     if (pWav->msadpcm.delta[1] < 16) {
03830                         pWav->msadpcm.delta[1] = 16;
03831                     }
03832 
03833                     pWav->msadpcm.prevFrames[1][0] = pWav->msadpcm.prevFrames[1][1];
03834                     pWav->msadpcm.prevFrames[1][1] = newSample1;
03835 
03836                     pWav->msadpcm.cachedFrames[2] = newSample0;
03837                     pWav->msadpcm.cachedFrames[3] = newSample1;
03838                     pWav->msadpcm.cachedFrameCount = 1;
03839                 }
03840             }
03841         }
03842     }
03843 
03844     return totalFramesRead;
03845 }
03846 
03847 
03848 static drwav_uint64 drwav_read_pcm_frames_s16__ima(drwav* pWav, drwav_uint64 framesToRead, drwav_int16* pBufferOut)
03849 {
03850     drwav_uint64 totalFramesRead = 0;
03851 
03852     DRWAV_ASSERT(pWav != NULL);
03853     DRWAV_ASSERT(framesToRead > 0);
03854     DRWAV_ASSERT(pBufferOut != NULL);
03855 
03856     /* TODO: Lots of room for optimization here. */
03857 
03858     while (framesToRead > 0 && pWav->compressed.iCurrentPCMFrame < pWav->totalPCMFrameCount) {
03859         /* If there are no cached samples we need to load a new block. */
03860         if (pWav->ima.cachedFrameCount == 0 && pWav->ima.bytesRemainingInBlock == 0) {
03861             if (pWav->channels == 1) {
03862                 /* Mono. */
03863                 drwav_uint8 header[4];
03864                 if (pWav->onRead(pWav->pUserData, header, sizeof(header)) != sizeof(header)) {
03865                     return totalFramesRead;
03866                 }
03867                 pWav->ima.bytesRemainingInBlock = pWav->fmt.blockAlign - sizeof(header);
03868 
03869                 pWav->ima.predictor[0] = drwav__bytes_to_s16(header + 0);
03870                 pWav->ima.stepIndex[0] = header[2];
03871                 pWav->ima.cachedFrames[drwav_countof(pWav->ima.cachedFrames) - 1] = pWav->ima.predictor[0];
03872                 pWav->ima.cachedFrameCount = 1;
03873             } else {
03874                 /* Stereo. */
03875                 drwav_uint8 header[8];
03876                 if (pWav->onRead(pWav->pUserData, header, sizeof(header)) != sizeof(header)) {
03877                     return totalFramesRead;
03878                 }
03879                 pWav->ima.bytesRemainingInBlock = pWav->fmt.blockAlign - sizeof(header);
03880 
03881                 pWav->ima.predictor[0] = drwav__bytes_to_s16(header + 0);
03882                 pWav->ima.stepIndex[0] = header[2];
03883                 pWav->ima.predictor[1] = drwav__bytes_to_s16(header + 4);
03884                 pWav->ima.stepIndex[1] = header[6];
03885 
03886                 pWav->ima.cachedFrames[drwav_countof(pWav->ima.cachedFrames) - 2] = pWav->ima.predictor[0];
03887                 pWav->ima.cachedFrames[drwav_countof(pWav->ima.cachedFrames) - 1] = pWav->ima.predictor[1];
03888                 pWav->ima.cachedFrameCount = 1;
03889             }
03890         }
03891 
03892         /* Output anything that's cached. */
03893         while (framesToRead > 0 && pWav->ima.cachedFrameCount > 0 && pWav->compressed.iCurrentPCMFrame < pWav->totalPCMFrameCount) {
03894             drwav_uint32 iSample;
03895             for (iSample = 0; iSample < pWav->channels; iSample += 1) {
03896                 pBufferOut[iSample] = (drwav_int16)pWav->ima.cachedFrames[(drwav_countof(pWav->ima.cachedFrames) - (pWav->ima.cachedFrameCount*pWav->channels)) + iSample];
03897             }
03898 
03899             pBufferOut      += pWav->channels;
03900             framesToRead    -= 1;
03901             totalFramesRead += 1;
03902             pWav->compressed.iCurrentPCMFrame += 1;
03903             pWav->ima.cachedFrameCount -= 1;
03904         }
03905 
03906         if (framesToRead == 0) {
03907             return totalFramesRead;
03908         }
03909 
03910         /*
03911         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
03912         loop iteration which will trigger the loading of a new block.
03913         */
03914         if (pWav->ima.cachedFrameCount == 0) {
03915             if (pWav->ima.bytesRemainingInBlock == 0) {
03916                 continue;
03917             } else {
03918                 static drwav_int32 indexTable[16] = {
03919                     -1, -1, -1, -1, 2, 4, 6, 8,
03920                     -1, -1, -1, -1, 2, 4, 6, 8
03921                 };
03922 
03923                 static drwav_int32 stepTable[89] = {
03924                     7,     8,     9,     10,    11,    12,    13,    14,    16,    17, 
03925                     19,    21,    23,    25,    28,    31,    34,    37,    41,    45, 
03926                     50,    55,    60,    66,    73,    80,    88,    97,    107,   118, 
03927                     130,   143,   157,   173,   190,   209,   230,   253,   279,   307,
03928                     337,   371,   408,   449,   494,   544,   598,   658,   724,   796,
03929                     876,   963,   1060,  1166,  1282,  1411,  1552,  1707,  1878,  2066, 
03930                     2272,  2499,  2749,  3024,  3327,  3660,  4026,  4428,  4871,  5358,
03931                     5894,  6484,  7132,  7845,  8630,  9493,  10442, 11487, 12635, 13899, 
03932                     15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767 
03933                 };
03934 
03935                 drwav_uint32 iChannel;
03936 
03937                 /*
03938                 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
03939                 left channel, 4 bytes for the right channel.
03940                 */
03941                 pWav->ima.cachedFrameCount = 8;
03942                 for (iChannel = 0; iChannel < pWav->channels; ++iChannel) {
03943                     drwav_uint32 iByte;
03944                     drwav_uint8 nibbles[4];
03945                     if (pWav->onRead(pWav->pUserData, &nibbles, 4) != 4) {
03946                         pWav->ima.cachedFrameCount = 0;
03947                         return totalFramesRead;
03948                     }
03949                     pWav->ima.bytesRemainingInBlock -= 4;
03950 
03951                     for (iByte = 0; iByte < 4; ++iByte) {
03952                         drwav_uint8 nibble0 = ((nibbles[iByte] & 0x0F) >> 0);
03953                         drwav_uint8 nibble1 = ((nibbles[iByte] & 0xF0) >> 4);
03954 
03955                         drwav_int32 step      = stepTable[pWav->ima.stepIndex[iChannel]];
03956                         drwav_int32 predictor = pWav->ima.predictor[iChannel];
03957 
03958                         drwav_int32      diff  = step >> 3;
03959                         if (nibble0 & 1) diff += step >> 2;
03960                         if (nibble0 & 2) diff += step >> 1;
03961                         if (nibble0 & 4) diff += step;
03962                         if (nibble0 & 8) diff  = -diff;
03963 
03964                         predictor = drwav_clamp(predictor + diff, -32768, 32767);
03965                         pWav->ima.predictor[iChannel] = predictor;
03966                         pWav->ima.stepIndex[iChannel] = drwav_clamp(pWav->ima.stepIndex[iChannel] + indexTable[nibble0], 0, (drwav_int32)drwav_countof(stepTable)-1);
03967                         pWav->ima.cachedFrames[(drwav_countof(pWav->ima.cachedFrames) - (pWav->ima.cachedFrameCount*pWav->channels)) + (iByte*2+0)*pWav->channels + iChannel] = predictor;
03968 
03969 
03970                         step      = stepTable[pWav->ima.stepIndex[iChannel]];
03971                         predictor = pWav->ima.predictor[iChannel];
03972 
03973                                          diff  = step >> 3;
03974                         if (nibble1 & 1) diff += step >> 2;
03975                         if (nibble1 & 2) diff += step >> 1;
03976                         if (nibble1 & 4) diff += step;
03977                         if (nibble1 & 8) diff  = -diff;
03978 
03979                         predictor = drwav_clamp(predictor + diff, -32768, 32767);
03980                         pWav->ima.predictor[iChannel] = predictor;
03981                         pWav->ima.stepIndex[iChannel] = drwav_clamp(pWav->ima.stepIndex[iChannel] + indexTable[nibble1], 0, (drwav_int32)drwav_countof(stepTable)-1);
03982                         pWav->ima.cachedFrames[(drwav_countof(pWav->ima.cachedFrames) - (pWav->ima.cachedFrameCount*pWav->channels)) + (iByte*2+1)*pWav->channels + iChannel] = predictor;
03983                     }
03984                 }
03985             }
03986         }
03987     }
03988 
03989     return totalFramesRead;
03990 }
03991 
03992 
03993 #ifndef DR_WAV_NO_CONVERSION_API
03994 static unsigned short g_drwavAlawTable[256] = {
03995     0xEA80, 0xEB80, 0xE880, 0xE980, 0xEE80, 0xEF80, 0xEC80, 0xED80, 0xE280, 0xE380, 0xE080, 0xE180, 0xE680, 0xE780, 0xE480, 0xE580, 
03996     0xF540, 0xF5C0, 0xF440, 0xF4C0, 0xF740, 0xF7C0, 0xF640, 0xF6C0, 0xF140, 0xF1C0, 0xF040, 0xF0C0, 0xF340, 0xF3C0, 0xF240, 0xF2C0, 
03997     0xAA00, 0xAE00, 0xA200, 0xA600, 0xBA00, 0xBE00, 0xB200, 0xB600, 0x8A00, 0x8E00, 0x8200, 0x8600, 0x9A00, 0x9E00, 0x9200, 0x9600, 
03998     0xD500, 0xD700, 0xD100, 0xD300, 0xDD00, 0xDF00, 0xD900, 0xDB00, 0xC500, 0xC700, 0xC100, 0xC300, 0xCD00, 0xCF00, 0xC900, 0xCB00, 
03999     0xFEA8, 0xFEB8, 0xFE88, 0xFE98, 0xFEE8, 0xFEF8, 0xFEC8, 0xFED8, 0xFE28, 0xFE38, 0xFE08, 0xFE18, 0xFE68, 0xFE78, 0xFE48, 0xFE58, 
04000     0xFFA8, 0xFFB8, 0xFF88, 0xFF98, 0xFFE8, 0xFFF8, 0xFFC8, 0xFFD8, 0xFF28, 0xFF38, 0xFF08, 0xFF18, 0xFF68, 0xFF78, 0xFF48, 0xFF58, 
04001     0xFAA0, 0xFAE0, 0xFA20, 0xFA60, 0xFBA0, 0xFBE0, 0xFB20, 0xFB60, 0xF8A0, 0xF8E0, 0xF820, 0xF860, 0xF9A0, 0xF9E0, 0xF920, 0xF960, 
04002     0xFD50, 0xFD70, 0xFD10, 0xFD30, 0xFDD0, 0xFDF0, 0xFD90, 0xFDB0, 0xFC50, 0xFC70, 0xFC10, 0xFC30, 0xFCD0, 0xFCF0, 0xFC90, 0xFCB0, 
04003     0x1580, 0x1480, 0x1780, 0x1680, 0x1180, 0x1080, 0x1380, 0x1280, 0x1D80, 0x1C80, 0x1F80, 0x1E80, 0x1980, 0x1880, 0x1B80, 0x1A80, 
04004     0x0AC0, 0x0A40, 0x0BC0, 0x0B40, 0x08C0, 0x0840, 0x09C0, 0x0940, 0x0EC0, 0x0E40, 0x0FC0, 0x0F40, 0x0CC0, 0x0C40, 0x0DC0, 0x0D40, 
04005     0x5600, 0x5200, 0x5E00, 0x5A00, 0x4600, 0x4200, 0x4E00, 0x4A00, 0x7600, 0x7200, 0x7E00, 0x7A00, 0x6600, 0x6200, 0x6E00, 0x6A00, 
04006     0x2B00, 0x2900, 0x2F00, 0x2D00, 0x2300, 0x2100, 0x2700, 0x2500, 0x3B00, 0x3900, 0x3F00, 0x3D00, 0x3300, 0x3100, 0x3700, 0x3500, 
04007     0x0158, 0x0148, 0x0178, 0x0168, 0x0118, 0x0108, 0x0138, 0x0128, 0x01D8, 0x01C8, 0x01F8, 0x01E8, 0x0198, 0x0188, 0x01B8, 0x01A8, 
04008     0x0058, 0x0048, 0x0078, 0x0068, 0x0018, 0x0008, 0x0038, 0x0028, 0x00D8, 0x00C8, 0x00F8, 0x00E8, 0x0098, 0x0088, 0x00B8, 0x00A8, 
04009     0x0560, 0x0520, 0x05E0, 0x05A0, 0x0460, 0x0420, 0x04E0, 0x04A0, 0x0760, 0x0720, 0x07E0, 0x07A0, 0x0660, 0x0620, 0x06E0, 0x06A0, 
04010     0x02B0, 0x0290, 0x02F0, 0x02D0, 0x0230, 0x0210, 0x0270, 0x0250, 0x03B0, 0x0390, 0x03F0, 0x03D0, 0x0330, 0x0310, 0x0370, 0x0350
04011 };
04012 
04013 static unsigned short g_drwavMulawTable[256] = {
04014     0x8284, 0x8684, 0x8A84, 0x8E84, 0x9284, 0x9684, 0x9A84, 0x9E84, 0xA284, 0xA684, 0xAA84, 0xAE84, 0xB284, 0xB684, 0xBA84, 0xBE84, 
04015     0xC184, 0xC384, 0xC584, 0xC784, 0xC984, 0xCB84, 0xCD84, 0xCF84, 0xD184, 0xD384, 0xD584, 0xD784, 0xD984, 0xDB84, 0xDD84, 0xDF84, 
04016     0xE104, 0xE204, 0xE304, 0xE404, 0xE504, 0xE604, 0xE704, 0xE804, 0xE904, 0xEA04, 0xEB04, 0xEC04, 0xED04, 0xEE04, 0xEF04, 0xF004, 
04017     0xF0C4, 0xF144, 0xF1C4, 0xF244, 0xF2C4, 0xF344, 0xF3C4, 0xF444, 0xF4C4, 0xF544, 0xF5C4, 0xF644, 0xF6C4, 0xF744, 0xF7C4, 0xF844, 
04018     0xF8A4, 0xF8E4, 0xF924, 0xF964, 0xF9A4, 0xF9E4, 0xFA24, 0xFA64, 0xFAA4, 0xFAE4, 0xFB24, 0xFB64, 0xFBA4, 0xFBE4, 0xFC24, 0xFC64, 
04019     0xFC94, 0xFCB4, 0xFCD4, 0xFCF4, 0xFD14, 0xFD34, 0xFD54, 0xFD74, 0xFD94, 0xFDB4, 0xFDD4, 0xFDF4, 0xFE14, 0xFE34, 0xFE54, 0xFE74, 
04020     0xFE8C, 0xFE9C, 0xFEAC, 0xFEBC, 0xFECC, 0xFEDC, 0xFEEC, 0xFEFC, 0xFF0C, 0xFF1C, 0xFF2C, 0xFF3C, 0xFF4C, 0xFF5C, 0xFF6C, 0xFF7C, 
04021     0xFF88, 0xFF90, 0xFF98, 0xFFA0, 0xFFA8, 0xFFB0, 0xFFB8, 0xFFC0, 0xFFC8, 0xFFD0, 0xFFD8, 0xFFE0, 0xFFE8, 0xFFF0, 0xFFF8, 0x0000, 
04022     0x7D7C, 0x797C, 0x757C, 0x717C, 0x6D7C, 0x697C, 0x657C, 0x617C, 0x5D7C, 0x597C, 0x557C, 0x517C, 0x4D7C, 0x497C, 0x457C, 0x417C, 
04023     0x3E7C, 0x3C7C, 0x3A7C, 0x387C, 0x367C, 0x347C, 0x327C, 0x307C, 0x2E7C, 0x2C7C, 0x2A7C, 0x287C, 0x267C, 0x247C, 0x227C, 0x207C, 
04024     0x1EFC, 0x1DFC, 0x1CFC, 0x1BFC, 0x1AFC, 0x19FC, 0x18FC, 0x17FC, 0x16FC, 0x15FC, 0x14FC, 0x13FC, 0x12FC, 0x11FC, 0x10FC, 0x0FFC, 
04025     0x0F3C, 0x0EBC, 0x0E3C, 0x0DBC, 0x0D3C, 0x0CBC, 0x0C3C, 0x0BBC, 0x0B3C, 0x0ABC, 0x0A3C, 0x09BC, 0x093C, 0x08BC, 0x083C, 0x07BC, 
04026     0x075C, 0x071C, 0x06DC, 0x069C, 0x065C, 0x061C, 0x05DC, 0x059C, 0x055C, 0x051C, 0x04DC, 0x049C, 0x045C, 0x041C, 0x03DC, 0x039C, 
04027     0x036C, 0x034C, 0x032C, 0x030C, 0x02EC, 0x02CC, 0x02AC, 0x028C, 0x026C, 0x024C, 0x022C, 0x020C, 0x01EC, 0x01CC, 0x01AC, 0x018C, 
04028     0x0174, 0x0164, 0x0154, 0x0144, 0x0134, 0x0124, 0x0114, 0x0104, 0x00F4, 0x00E4, 0x00D4, 0x00C4, 0x00B4, 0x00A4, 0x0094, 0x0084, 
04029     0x0078, 0x0070, 0x0068, 0x0060, 0x0058, 0x0050, 0x0048, 0x0040, 0x0038, 0x0030, 0x0028, 0x0020, 0x0018, 0x0010, 0x0008, 0x0000
04030 };
04031 
04032 static DRWAV_INLINE drwav_int16 drwav__alaw_to_s16(drwav_uint8 sampleIn)
04033 {
04034     return (short)g_drwavAlawTable[sampleIn];
04035 }
04036 
04037 static DRWAV_INLINE drwav_int16 drwav__mulaw_to_s16(drwav_uint8 sampleIn)
04038 {
04039     return (short)g_drwavMulawTable[sampleIn];
04040 }
04041 
04042 
04043 
04044 static void drwav__pcm_to_s16(drwav_int16* pOut, const drwav_uint8* pIn, size_t totalSampleCount, unsigned int bytesPerSample)
04045 {
04046     unsigned int i;
04047 
04048     /* Special case for 8-bit sample data because it's treated as unsigned. */
04049     if (bytesPerSample == 1) {
04050         drwav_u8_to_s16(pOut, pIn, totalSampleCount);
04051         return;
04052     }
04053 
04054 
04055     /* Slightly more optimal implementation for common formats. */
04056     if (bytesPerSample == 2) {
04057         for (i = 0; i < totalSampleCount; ++i) {
04058            *pOut++ = ((const drwav_int16*)pIn)[i];
04059         }
04060         return;
04061     }
04062     if (bytesPerSample == 3) {
04063         drwav_s24_to_s16(pOut, pIn, totalSampleCount);
04064         return;
04065     }
04066     if (bytesPerSample == 4) {
04067         drwav_s32_to_s16(pOut, (const drwav_int32*)pIn, totalSampleCount);
04068         return;
04069     }
04070 
04071 
04072     /* Anything more than 64 bits per sample is not supported. */
04073     if (bytesPerSample > 8) {
04074         DRWAV_ZERO_MEMORY(pOut, totalSampleCount * sizeof(*pOut));
04075         return;
04076     }
04077 
04078 
04079     /* Generic, slow converter. */
04080     for (i = 0; i < totalSampleCount; ++i) {
04081         drwav_uint64 sample = 0;
04082         unsigned int shift  = (8 - bytesPerSample) * 8;
04083 
04084         unsigned int j;
04085         for (j = 0; j < bytesPerSample; j += 1) {
04086             DRWAV_ASSERT(j < 8);
04087             sample |= (drwav_uint64)(pIn[j]) << shift;
04088             shift  += 8;
04089         }
04090 
04091         pIn += j;
04092         *pOut++ = (drwav_int16)((drwav_int64)sample >> 48);
04093     }
04094 }
04095 
04096 static void drwav__ieee_to_s16(drwav_int16* pOut, const drwav_uint8* pIn, size_t totalSampleCount, unsigned int bytesPerSample)
04097 {
04098     if (bytesPerSample == 4) {
04099         drwav_f32_to_s16(pOut, (const float*)pIn, totalSampleCount);
04100         return;
04101     } else if (bytesPerSample == 8) {
04102         drwav_f64_to_s16(pOut, (const double*)pIn, totalSampleCount);
04103         return;
04104     } else {
04105         /* Only supporting 32- and 64-bit float. Output silence in all other cases. Contributions welcome for 16-bit float. */
04106         DRWAV_ZERO_MEMORY(pOut, totalSampleCount * sizeof(*pOut));
04107         return;
04108     }
04109 }
04110 
04111 static drwav_uint64 drwav_read_pcm_frames_s16__pcm(drwav* pWav, drwav_uint64 framesToRead, drwav_int16* pBufferOut)
04112 {
04113     drwav_uint32 bytesPerFrame;
04114     drwav_uint64 totalFramesRead;
04115     drwav_uint8 sampleData[4096];
04116 
04117     /* Fast path. */
04118     if (pWav->translatedFormatTag == DR_WAVE_FORMAT_PCM && pWav->bitsPerSample == 16) {
04119         return drwav_read_pcm_frames(pWav, framesToRead, pBufferOut);
04120     }
04121     
04122     bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
04123     if (bytesPerFrame == 0) {
04124         return 0;
04125     }
04126 
04127     totalFramesRead = 0;
04128     
04129     while (framesToRead > 0) {
04130         drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame), sampleData);
04131         if (framesRead == 0) {
04132             break;
04133         }
04134 
04135         drwav__pcm_to_s16(pBufferOut, sampleData, (size_t)(framesRead*pWav->channels), bytesPerFrame/pWav->channels);
04136 
04137         pBufferOut      += framesRead*pWav->channels;
04138         framesToRead    -= framesRead;
04139         totalFramesRead += framesRead;
04140     }
04141 
04142     return totalFramesRead;
04143 }
04144 
04145 static drwav_uint64 drwav_read_pcm_frames_s16__ieee(drwav* pWav, drwav_uint64 framesToRead, drwav_int16* pBufferOut)
04146 {
04147     drwav_uint64 totalFramesRead;
04148     drwav_uint8 sampleData[4096];
04149 
04150     drwav_uint32 bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
04151     if (bytesPerFrame == 0) {
04152         return 0;
04153     }
04154 
04155     totalFramesRead = 0;
04156     
04157     while (framesToRead > 0) {
04158         drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame), sampleData);
04159         if (framesRead == 0) {
04160             break;
04161         }
04162 
04163         drwav__ieee_to_s16(pBufferOut, sampleData, (size_t)(framesRead*pWav->channels), bytesPerFrame/pWav->channels);
04164 
04165         pBufferOut      += framesRead*pWav->channels;
04166         framesToRead    -= framesRead;
04167         totalFramesRead += framesRead;
04168     }
04169 
04170     return totalFramesRead;
04171 }
04172 
04173 static drwav_uint64 drwav_read_pcm_frames_s16__alaw(drwav* pWav, drwav_uint64 framesToRead, drwav_int16* pBufferOut)
04174 {
04175     drwav_uint64 totalFramesRead;
04176     drwav_uint8 sampleData[4096];
04177 
04178     drwav_uint32 bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
04179     if (bytesPerFrame == 0) {
04180         return 0;
04181     }
04182 
04183     totalFramesRead = 0;
04184     
04185     while (framesToRead > 0) {
04186         drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame), sampleData);
04187         if (framesRead == 0) {
04188             break;
04189         }
04190 
04191         drwav_alaw_to_s16(pBufferOut, sampleData, (size_t)(framesRead*pWav->channels));
04192 
04193         pBufferOut      += framesRead*pWav->channels;
04194         framesToRead    -= framesRead;
04195         totalFramesRead += framesRead;
04196     }
04197 
04198     return totalFramesRead;
04199 }
04200 
04201 static drwav_uint64 drwav_read_pcm_frames_s16__mulaw(drwav* pWav, drwav_uint64 framesToRead, drwav_int16* pBufferOut)
04202 {
04203     drwav_uint64 totalFramesRead;
04204     drwav_uint8 sampleData[4096];
04205 
04206     drwav_uint32 bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
04207     if (bytesPerFrame == 0) {
04208         return 0;
04209     }
04210 
04211     totalFramesRead = 0;
04212 
04213     while (framesToRead > 0) {
04214         drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame), sampleData);
04215         if (framesRead == 0) {
04216             break;
04217         }
04218 
04219         drwav_mulaw_to_s16(pBufferOut, sampleData, (size_t)(framesRead*pWav->channels));
04220 
04221         pBufferOut      += framesRead*pWav->channels;
04222         framesToRead    -= framesRead;
04223         totalFramesRead += framesRead;
04224     }
04225 
04226     return totalFramesRead;
04227 }
04228 
04229 DRWAV_API drwav_uint64 drwav_read_pcm_frames_s16(drwav* pWav, drwav_uint64 framesToRead, drwav_int16* pBufferOut)
04230 {
04231     if (pWav == NULL || framesToRead == 0 || pBufferOut == NULL) {
04232         return 0;
04233     }
04234 
04235     /* Don't try to read more samples than can potentially fit in the output buffer. */
04236     if (framesToRead * pWav->channels * sizeof(drwav_int16) > DRWAV_SIZE_MAX) {
04237         framesToRead = DRWAV_SIZE_MAX / sizeof(drwav_int16) / pWav->channels;
04238     }
04239 
04240     if (pWav->translatedFormatTag == DR_WAVE_FORMAT_PCM) {
04241         return drwav_read_pcm_frames_s16__pcm(pWav, framesToRead, pBufferOut);
04242     }
04243 
04244     if (pWav->translatedFormatTag == DR_WAVE_FORMAT_IEEE_FLOAT) {
04245         return drwav_read_pcm_frames_s16__ieee(pWav, framesToRead, pBufferOut);
04246     }
04247 
04248     if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ALAW) {
04249         return drwav_read_pcm_frames_s16__alaw(pWav, framesToRead, pBufferOut);
04250     }
04251 
04252     if (pWav->translatedFormatTag == DR_WAVE_FORMAT_MULAW) {
04253         return drwav_read_pcm_frames_s16__mulaw(pWav, framesToRead, pBufferOut);
04254     }
04255 
04256     if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ADPCM) {
04257         return drwav_read_pcm_frames_s16__msadpcm(pWav, framesToRead, pBufferOut);
04258     }
04259 
04260     if (pWav->translatedFormatTag == DR_WAVE_FORMAT_DVI_ADPCM) {
04261         return drwav_read_pcm_frames_s16__ima(pWav, framesToRead, pBufferOut);
04262     }
04263 
04264     return 0;
04265 }
04266 
04267 DRWAV_API drwav_uint64 drwav_read_pcm_frames_s16le(drwav* pWav, drwav_uint64 framesToRead, drwav_int16* pBufferOut)
04268 {
04269     drwav_uint64 framesRead = drwav_read_pcm_frames_s16(pWav, framesToRead, pBufferOut);
04270     if (!drwav__is_little_endian()) {
04271         drwav__bswap_samples_s16(pBufferOut, framesRead*pWav->channels);
04272     }
04273 
04274     return framesRead;
04275 }
04276 
04277 DRWAV_API drwav_uint64 drwav_read_pcm_frames_s16be(drwav* pWav, drwav_uint64 framesToRead, drwav_int16* pBufferOut)
04278 {
04279     drwav_uint64 framesRead = drwav_read_pcm_frames_s16(pWav, framesToRead, pBufferOut);
04280     if (drwav__is_little_endian()) {
04281         drwav__bswap_samples_s16(pBufferOut, framesRead*pWav->channels);
04282     }
04283 
04284     return framesRead;
04285 }
04286 
04287 
04288 DRWAV_API void drwav_u8_to_s16(drwav_int16* pOut, const drwav_uint8* pIn, size_t sampleCount)
04289 {
04290     int r;
04291     size_t i;
04292     for (i = 0; i < sampleCount; ++i) {
04293         int x = pIn[i];
04294         r = x << 8;
04295         r = r - 32768;
04296         pOut[i] = (short)r;
04297     }
04298 }
04299 
04300 DRWAV_API void drwav_s24_to_s16(drwav_int16* pOut, const drwav_uint8* pIn, size_t sampleCount)
04301 {
04302     int r;
04303     size_t i;
04304     for (i = 0; i < sampleCount; ++i) {
04305         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;
04306         r = x >> 8;
04307         pOut[i] = (short)r;
04308     }
04309 }
04310 
04311 DRWAV_API void drwav_s32_to_s16(drwav_int16* pOut, const drwav_int32* pIn, size_t sampleCount)
04312 {
04313     int r;
04314     size_t i;
04315     for (i = 0; i < sampleCount; ++i) {
04316         int x = pIn[i];
04317         r = x >> 16;
04318         pOut[i] = (short)r;
04319     }
04320 }
04321 
04322 DRWAV_API void drwav_f32_to_s16(drwav_int16* pOut, const float* pIn, size_t sampleCount)
04323 {
04324     int r;
04325     size_t i;
04326     for (i = 0; i < sampleCount; ++i) {
04327         float x = pIn[i];
04328         float c;
04329         c = ((x < -1) ? -1 : ((x > 1) ? 1 : x));
04330         c = c + 1;
04331         r = (int)(c * 32767.5f);
04332         r = r - 32768;
04333         pOut[i] = (short)r;
04334     }
04335 }
04336 
04337 DRWAV_API void drwav_f64_to_s16(drwav_int16* pOut, const double* pIn, size_t sampleCount)
04338 {
04339     int r;
04340     size_t i;
04341     for (i = 0; i < sampleCount; ++i) {
04342         double x = pIn[i];
04343         double c;
04344         c = ((x < -1) ? -1 : ((x > 1) ? 1 : x));
04345         c = c + 1;
04346         r = (int)(c * 32767.5);
04347         r = r - 32768;
04348         pOut[i] = (short)r;
04349     }
04350 }
04351 
04352 DRWAV_API void drwav_alaw_to_s16(drwav_int16* pOut, const drwav_uint8* pIn, size_t sampleCount)
04353 {
04354     size_t i;
04355     for (i = 0; i < sampleCount; ++i) {
04356         pOut[i] = drwav__alaw_to_s16(pIn[i]);
04357     }
04358 }
04359 
04360 DRWAV_API void drwav_mulaw_to_s16(drwav_int16* pOut, const drwav_uint8* pIn, size_t sampleCount)
04361 {
04362     size_t i;
04363     for (i = 0; i < sampleCount; ++i) {
04364         pOut[i] = drwav__mulaw_to_s16(pIn[i]);
04365     }
04366 }
04367 
04368 
04369 
04370 static void drwav__pcm_to_f32(float* pOut, const drwav_uint8* pIn, size_t sampleCount, unsigned int bytesPerSample)
04371 {
04372     unsigned int i;
04373 
04374     /* Special case for 8-bit sample data because it's treated as unsigned. */
04375     if (bytesPerSample == 1) {
04376         drwav_u8_to_f32(pOut, pIn, sampleCount);
04377         return;
04378     }
04379 
04380     /* Slightly more optimal implementation for common formats. */
04381     if (bytesPerSample == 2) {
04382         drwav_s16_to_f32(pOut, (const drwav_int16*)pIn, sampleCount);
04383         return;
04384     }
04385     if (bytesPerSample == 3) {
04386         drwav_s24_to_f32(pOut, pIn, sampleCount);
04387         return;
04388     }
04389     if (bytesPerSample == 4) {
04390         drwav_s32_to_f32(pOut, (const drwav_int32*)pIn, sampleCount);
04391         return;
04392     }
04393 
04394 
04395     /* Anything more than 64 bits per sample is not supported. */
04396     if (bytesPerSample > 8) {
04397         DRWAV_ZERO_MEMORY(pOut, sampleCount * sizeof(*pOut));
04398         return;
04399     }
04400 
04401 
04402     /* Generic, slow converter. */
04403     for (i = 0; i < sampleCount; ++i) {
04404         drwav_uint64 sample = 0;
04405         unsigned int shift  = (8 - bytesPerSample) * 8;
04406 
04407         unsigned int j;
04408         for (j = 0; j < bytesPerSample; j += 1) {
04409             DRWAV_ASSERT(j < 8);
04410             sample |= (drwav_uint64)(pIn[j]) << shift;
04411             shift  += 8;
04412         }
04413 
04414         pIn += j;
04415         *pOut++ = (float)((drwav_int64)sample / 9223372036854775807.0);
04416     }
04417 }
04418 
04419 static void drwav__ieee_to_f32(float* pOut, const drwav_uint8* pIn, size_t sampleCount, unsigned int bytesPerSample)
04420 {
04421     if (bytesPerSample == 4) {
04422         unsigned int i;
04423         for (i = 0; i < sampleCount; ++i) {
04424             *pOut++ = ((const float*)pIn)[i];
04425         }
04426         return;
04427     } else if (bytesPerSample == 8) {
04428         drwav_f64_to_f32(pOut, (const double*)pIn, sampleCount);
04429         return;
04430     } else {
04431         /* Only supporting 32- and 64-bit float. Output silence in all other cases. Contributions welcome for 16-bit float. */
04432         DRWAV_ZERO_MEMORY(pOut, sampleCount * sizeof(*pOut));
04433         return;
04434     }
04435 }
04436 
04437 
04438 static drwav_uint64 drwav_read_pcm_frames_f32__pcm(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut)
04439 {
04440     drwav_uint64 totalFramesRead;
04441     drwav_uint8 sampleData[4096];
04442 
04443     drwav_uint32 bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
04444     if (bytesPerFrame == 0) {
04445         return 0;
04446     }
04447 
04448     totalFramesRead = 0;
04449 
04450     while (framesToRead > 0) {
04451         drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame), sampleData);
04452         if (framesRead == 0) {
04453             break;
04454         }
04455 
04456         drwav__pcm_to_f32(pBufferOut, sampleData, (size_t)framesRead*pWav->channels, bytesPerFrame/pWav->channels);
04457 
04458         pBufferOut      += framesRead*pWav->channels;
04459         framesToRead    -= framesRead;
04460         totalFramesRead += framesRead;
04461     }
04462 
04463     return totalFramesRead;
04464 }
04465 
04466 static drwav_uint64 drwav_read_pcm_frames_f32__msadpcm(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut)
04467 {
04468     /*
04469     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
04470     want to duplicate that code.
04471     */
04472     drwav_uint64 totalFramesRead = 0;
04473     drwav_int16 samples16[2048];
04474     while (framesToRead > 0) {
04475         drwav_uint64 framesRead = drwav_read_pcm_frames_s16(pWav, drwav_min(framesToRead, drwav_countof(samples16)/pWav->channels), samples16);
04476         if (framesRead == 0) {
04477             break;
04478         }
04479 
04480         drwav_s16_to_f32(pBufferOut, samples16, (size_t)(framesRead*pWav->channels));   /* <-- Safe cast because we're clamping to 2048. */
04481 
04482         pBufferOut      += framesRead*pWav->channels;
04483         framesToRead    -= framesRead;
04484         totalFramesRead += framesRead;
04485     }
04486 
04487     return totalFramesRead;
04488 }
04489 
04490 static drwav_uint64 drwav_read_pcm_frames_f32__ima(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut)
04491 {
04492     /*
04493     We're just going to borrow the implementation from the drwav_read_s16() since IMA-ADPCM is a little bit more complicated than other formats and I don't
04494     want to duplicate that code.
04495     */
04496     drwav_uint64 totalFramesRead = 0;
04497     drwav_int16 samples16[2048];
04498     while (framesToRead > 0) {
04499         drwav_uint64 framesRead = drwav_read_pcm_frames_s16(pWav, drwav_min(framesToRead, drwav_countof(samples16)/pWav->channels), samples16);
04500         if (framesRead == 0) {
04501             break;
04502         }
04503 
04504         drwav_s16_to_f32(pBufferOut, samples16, (size_t)(framesRead*pWav->channels));   /* <-- Safe cast because we're clamping to 2048. */
04505 
04506         pBufferOut      += framesRead*pWav->channels;
04507         framesToRead    -= framesRead;
04508         totalFramesRead += framesRead;
04509     }
04510 
04511     return totalFramesRead;
04512 }
04513 
04514 static drwav_uint64 drwav_read_pcm_frames_f32__ieee(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut)
04515 {
04516     drwav_uint64 totalFramesRead;
04517     drwav_uint8 sampleData[4096];
04518     drwav_uint32 bytesPerFrame;
04519 
04520     /* Fast path. */
04521     if (pWav->translatedFormatTag == DR_WAVE_FORMAT_IEEE_FLOAT && pWav->bitsPerSample == 32) {
04522         return drwav_read_pcm_frames(pWav, framesToRead, pBufferOut);
04523     }
04524     
04525     bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
04526     if (bytesPerFrame == 0) {
04527         return 0;
04528     }
04529 
04530     totalFramesRead = 0;
04531 
04532     while (framesToRead > 0) {
04533         drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame), sampleData);
04534         if (framesRead == 0) {
04535             break;
04536         }
04537 
04538         drwav__ieee_to_f32(pBufferOut, sampleData, (size_t)(framesRead*pWav->channels), bytesPerFrame/pWav->channels);
04539 
04540         pBufferOut      += framesRead*pWav->channels;
04541         framesToRead    -= framesRead;
04542         totalFramesRead += framesRead;
04543     }
04544 
04545     return totalFramesRead;
04546 }
04547 
04548 static drwav_uint64 drwav_read_pcm_frames_f32__alaw(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut)
04549 {
04550     drwav_uint64 totalFramesRead;
04551     drwav_uint8 sampleData[4096];
04552     drwav_uint32 bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
04553     if (bytesPerFrame == 0) {
04554         return 0;
04555     }
04556 
04557     totalFramesRead = 0;
04558 
04559     while (framesToRead > 0) {
04560         drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame), sampleData);
04561         if (framesRead == 0) {
04562             break;
04563         }
04564 
04565         drwav_alaw_to_f32(pBufferOut, sampleData, (size_t)(framesRead*pWav->channels));
04566 
04567         pBufferOut      += framesRead*pWav->channels;
04568         framesToRead    -= framesRead;
04569         totalFramesRead += framesRead;
04570     }
04571 
04572     return totalFramesRead;
04573 }
04574 
04575 static drwav_uint64 drwav_read_pcm_frames_f32__mulaw(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut)
04576 {
04577     drwav_uint64 totalFramesRead;
04578     drwav_uint8 sampleData[4096];
04579 
04580     drwav_uint32 bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
04581     if (bytesPerFrame == 0) {
04582         return 0;
04583     }
04584 
04585     totalFramesRead = 0;
04586 
04587     while (framesToRead > 0) {
04588         drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame), sampleData);
04589         if (framesRead == 0) {
04590             break;
04591         }
04592 
04593         drwav_mulaw_to_f32(pBufferOut, sampleData, (size_t)(framesRead*pWav->channels));
04594 
04595         pBufferOut      += framesRead*pWav->channels;
04596         framesToRead    -= framesRead;
04597         totalFramesRead += framesRead;
04598     }
04599 
04600     return totalFramesRead;
04601 }
04602 
04603 DRWAV_API drwav_uint64 drwav_read_pcm_frames_f32(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut)
04604 {
04605     if (pWav == NULL || framesToRead == 0 || pBufferOut == NULL) {
04606         return 0;
04607     }
04608 
04609     /* Don't try to read more samples than can potentially fit in the output buffer. */
04610     if (framesToRead * pWav->channels * sizeof(float) > DRWAV_SIZE_MAX) {
04611         framesToRead = DRWAV_SIZE_MAX / sizeof(float) / pWav->channels;
04612     }
04613 
04614     if (pWav->translatedFormatTag == DR_WAVE_FORMAT_PCM) {
04615         return drwav_read_pcm_frames_f32__pcm(pWav, framesToRead, pBufferOut);
04616     }
04617 
04618     if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ADPCM) {
04619         return drwav_read_pcm_frames_f32__msadpcm(pWav, framesToRead, pBufferOut);
04620     }
04621 
04622     if (pWav->translatedFormatTag == DR_WAVE_FORMAT_IEEE_FLOAT) {
04623         return drwav_read_pcm_frames_f32__ieee(pWav, framesToRead, pBufferOut);
04624     }
04625 
04626     if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ALAW) {
04627         return drwav_read_pcm_frames_f32__alaw(pWav, framesToRead, pBufferOut);
04628     }
04629 
04630     if (pWav->translatedFormatTag == DR_WAVE_FORMAT_MULAW) {
04631         return drwav_read_pcm_frames_f32__mulaw(pWav, framesToRead, pBufferOut);
04632     }
04633 
04634     if (pWav->translatedFormatTag == DR_WAVE_FORMAT_DVI_ADPCM) {
04635         return drwav_read_pcm_frames_f32__ima(pWav, framesToRead, pBufferOut);
04636     }
04637 
04638     return 0;
04639 }
04640 
04641 DRWAV_API drwav_uint64 drwav_read_pcm_frames_f32le(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut)
04642 {
04643     drwav_uint64 framesRead = drwav_read_pcm_frames_f32(pWav, framesToRead, pBufferOut);
04644     if (!drwav__is_little_endian()) {
04645         drwav__bswap_samples_f32(pBufferOut, framesRead*pWav->channels);
04646     }
04647 
04648     return framesRead;
04649 }
04650 
04651 DRWAV_API drwav_uint64 drwav_read_pcm_frames_f32be(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut)
04652 {
04653     drwav_uint64 framesRead = drwav_read_pcm_frames_f32(pWav, framesToRead, pBufferOut);
04654     if (drwav__is_little_endian()) {
04655         drwav__bswap_samples_f32(pBufferOut, framesRead*pWav->channels);
04656     }
04657 
04658     return framesRead;
04659 }
04660 
04661 
04662 DRWAV_API void drwav_u8_to_f32(float* pOut, const drwav_uint8* pIn, size_t sampleCount)
04663 {
04664     size_t i;
04665 
04666     if (pOut == NULL || pIn == NULL) {
04667         return;
04668     }
04669 
04670 #ifdef DR_WAV_LIBSNDFILE_COMPAT
04671     /*
04672     It appears libsndfile uses slightly different logic for the u8 -> f32 conversion to dr_wav, which in my opinion is incorrect. It appears
04673     libsndfile performs the conversion something like "f32 = (u8 / 256) * 2 - 1", however I think it should be "f32 = (u8 / 255) * 2 - 1" (note
04674     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
04675     correctness testing. This is disabled by default.
04676     */
04677     for (i = 0; i < sampleCount; ++i) {
04678         *pOut++ = (pIn[i] / 256.0f) * 2 - 1;
04679     }
04680 #else
04681     for (i = 0; i < sampleCount; ++i) {
04682         float x = pIn[i];
04683         x = x * 0.00784313725490196078f;    /* 0..255 to 0..2 */
04684         x = x - 1;                          /* 0..2 to -1..1 */
04685 
04686         *pOut++ = x;
04687     }
04688 #endif
04689 }
04690 
04691 DRWAV_API void drwav_s16_to_f32(float* pOut, const drwav_int16* pIn, size_t sampleCount)
04692 {
04693     size_t i;
04694 
04695     if (pOut == NULL || pIn == NULL) {
04696         return;
04697     }
04698 
04699     for (i = 0; i < sampleCount; ++i) {
04700         *pOut++ = pIn[i] * 0.000030517578125f;
04701     }
04702 }
04703 
04704 DRWAV_API void drwav_s24_to_f32(float* pOut, const drwav_uint8* pIn, size_t sampleCount)
04705 {
04706     size_t i;
04707 
04708     if (pOut == NULL || pIn == NULL) {
04709         return;
04710     }
04711 
04712     for (i = 0; i < sampleCount; ++i) {
04713         double x = (double)(((drwav_int32)(((drwav_uint32)(pIn[i*3+0]) << 8) | ((drwav_uint32)(pIn[i*3+1]) << 16) | ((drwav_uint32)(pIn[i*3+2])) << 24)) >> 8);
04714         *pOut++ = (float)(x * 0.00000011920928955078125);
04715     }
04716 }
04717 
04718 DRWAV_API void drwav_s32_to_f32(float* pOut, const drwav_int32* pIn, size_t sampleCount)
04719 {
04720     size_t i;
04721     if (pOut == NULL || pIn == NULL) {
04722         return;
04723     }
04724 
04725     for (i = 0; i < sampleCount; ++i) {
04726         *pOut++ = (float)(pIn[i] / 2147483648.0);
04727     }
04728 }
04729 
04730 DRWAV_API void drwav_f64_to_f32(float* pOut, const double* pIn, size_t sampleCount)
04731 {
04732     size_t i;
04733 
04734     if (pOut == NULL || pIn == NULL) {
04735         return;
04736     }
04737 
04738     for (i = 0; i < sampleCount; ++i) {
04739         *pOut++ = (float)pIn[i];
04740     }
04741 }
04742 
04743 DRWAV_API void drwav_alaw_to_f32(float* pOut, const drwav_uint8* pIn, size_t sampleCount)
04744 {
04745     size_t i;
04746 
04747     if (pOut == NULL || pIn == NULL) {
04748         return;
04749     }
04750 
04751     for (i = 0; i < sampleCount; ++i) {
04752         *pOut++ = drwav__alaw_to_s16(pIn[i]) / 32768.0f;
04753     }
04754 }
04755 
04756 DRWAV_API void drwav_mulaw_to_f32(float* pOut, const drwav_uint8* pIn, size_t sampleCount)
04757 {
04758     size_t i;
04759 
04760     if (pOut == NULL || pIn == NULL) {
04761         return;
04762     }
04763 
04764     for (i = 0; i < sampleCount; ++i) {
04765         *pOut++ = drwav__mulaw_to_s16(pIn[i]) / 32768.0f;
04766     }
04767 }
04768 
04769 
04770 
04771 static void drwav__pcm_to_s32(drwav_int32* pOut, const drwav_uint8* pIn, size_t totalSampleCount, unsigned int bytesPerSample)
04772 {
04773     unsigned int i;
04774 
04775     /* Special case for 8-bit sample data because it's treated as unsigned. */
04776     if (bytesPerSample == 1) {
04777         drwav_u8_to_s32(pOut, pIn, totalSampleCount);
04778         return;
04779     }
04780 
04781     /* Slightly more optimal implementation for common formats. */
04782     if (bytesPerSample == 2) {
04783         drwav_s16_to_s32(pOut, (const drwav_int16*)pIn, totalSampleCount);
04784         return;
04785     }
04786     if (bytesPerSample == 3) {
04787         drwav_s24_to_s32(pOut, pIn, totalSampleCount);
04788         return;
04789     }
04790     if (bytesPerSample == 4) {
04791         for (i = 0; i < totalSampleCount; ++i) {
04792            *pOut++ = ((const drwav_int32*)pIn)[i];
04793         }
04794         return;
04795     }
04796 
04797 
04798     /* Anything more than 64 bits per sample is not supported. */
04799     if (bytesPerSample > 8) {
04800         DRWAV_ZERO_MEMORY(pOut, totalSampleCount * sizeof(*pOut));
04801         return;
04802     }
04803 
04804 
04805     /* Generic, slow converter. */
04806     for (i = 0; i < totalSampleCount; ++i) {
04807         drwav_uint64 sample = 0;
04808         unsigned int shift  = (8 - bytesPerSample) * 8;
04809 
04810         unsigned int j;
04811         for (j = 0; j < bytesPerSample; j += 1) {
04812             DRWAV_ASSERT(j < 8);
04813             sample |= (drwav_uint64)(pIn[j]) << shift;
04814             shift  += 8;
04815         }
04816 
04817         pIn += j;
04818         *pOut++ = (drwav_int32)((drwav_int64)sample >> 32);
04819     }
04820 }
04821 
04822 static void drwav__ieee_to_s32(drwav_int32* pOut, const drwav_uint8* pIn, size_t totalSampleCount, unsigned int bytesPerSample)
04823 {
04824     if (bytesPerSample == 4) {
04825         drwav_f32_to_s32(pOut, (const float*)pIn, totalSampleCount);
04826         return;
04827     } else if (bytesPerSample == 8) {
04828         drwav_f64_to_s32(pOut, (const double*)pIn, totalSampleCount);
04829         return;
04830     } else {
04831         /* Only supporting 32- and 64-bit float. Output silence in all other cases. Contributions welcome for 16-bit float. */
04832         DRWAV_ZERO_MEMORY(pOut, totalSampleCount * sizeof(*pOut));
04833         return;
04834     }
04835 }
04836 
04837 
04838 static drwav_uint64 drwav_read_pcm_frames_s32__pcm(drwav* pWav, drwav_uint64 framesToRead, drwav_int32* pBufferOut)
04839 {
04840     drwav_uint64 totalFramesRead;
04841     drwav_uint8 sampleData[4096];
04842     drwav_uint32 bytesPerFrame;
04843 
04844     /* Fast path. */
04845     if (pWav->translatedFormatTag == DR_WAVE_FORMAT_PCM && pWav->bitsPerSample == 32) {
04846         return drwav_read_pcm_frames(pWav, framesToRead, pBufferOut);
04847     }
04848     
04849     bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
04850     if (bytesPerFrame == 0) {
04851         return 0;
04852     }
04853 
04854     totalFramesRead = 0;
04855 
04856     while (framesToRead > 0) {
04857         drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame), sampleData);
04858         if (framesRead == 0) {
04859             break;
04860         }
04861 
04862         drwav__pcm_to_s32(pBufferOut, sampleData, (size_t)(framesRead*pWav->channels), bytesPerFrame/pWav->channels);
04863 
04864         pBufferOut      += framesRead*pWav->channels;
04865         framesToRead    -= framesRead;
04866         totalFramesRead += framesRead;
04867     }
04868 
04869     return totalFramesRead;
04870 }
04871 
04872 static drwav_uint64 drwav_read_pcm_frames_s32__msadpcm(drwav* pWav, drwav_uint64 framesToRead, drwav_int32* pBufferOut)
04873 {
04874     /*
04875     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
04876     want to duplicate that code.
04877     */
04878     drwav_uint64 totalFramesRead = 0;
04879     drwav_int16 samples16[2048];
04880     while (framesToRead > 0) {
04881         drwav_uint64 framesRead = drwav_read_pcm_frames_s16(pWav, drwav_min(framesToRead, drwav_countof(samples16)/pWav->channels), samples16);
04882         if (framesRead == 0) {
04883             break;
04884         }
04885 
04886         drwav_s16_to_s32(pBufferOut, samples16, (size_t)(framesRead*pWav->channels));   /* <-- Safe cast because we're clamping to 2048. */
04887 
04888         pBufferOut      += framesRead*pWav->channels;
04889         framesToRead    -= framesRead;
04890         totalFramesRead += framesRead;
04891     }
04892 
04893     return totalFramesRead;
04894 }
04895 
04896 static drwav_uint64 drwav_read_pcm_frames_s32__ima(drwav* pWav, drwav_uint64 framesToRead, drwav_int32* pBufferOut)
04897 {
04898     /*
04899     We're just going to borrow the implementation from the drwav_read_s16() since IMA-ADPCM is a little bit more complicated than other formats and I don't
04900     want to duplicate that code.
04901     */
04902     drwav_uint64 totalFramesRead = 0;
04903     drwav_int16 samples16[2048];
04904     while (framesToRead > 0) {
04905         drwav_uint64 framesRead = drwav_read_pcm_frames_s16(pWav, drwav_min(framesToRead, drwav_countof(samples16)/pWav->channels), samples16);
04906         if (framesRead == 0) {
04907             break;
04908         }
04909 
04910         drwav_s16_to_s32(pBufferOut, samples16, (size_t)(framesRead*pWav->channels));   /* <-- Safe cast because we're clamping to 2048. */
04911 
04912         pBufferOut      += framesRead*pWav->channels;
04913         framesToRead    -= framesRead;
04914         totalFramesRead += framesRead;
04915     }
04916 
04917     return totalFramesRead;
04918 }
04919 
04920 static drwav_uint64 drwav_read_pcm_frames_s32__ieee(drwav* pWav, drwav_uint64 framesToRead, drwav_int32* pBufferOut)
04921 {
04922     drwav_uint64 totalFramesRead;
04923     drwav_uint8 sampleData[4096];
04924 
04925     drwav_uint32 bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
04926     if (bytesPerFrame == 0) {
04927         return 0;
04928     }
04929 
04930     totalFramesRead = 0;
04931 
04932     while (framesToRead > 0) {
04933         drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame), sampleData);
04934         if (framesRead == 0) {
04935             break;
04936         }
04937 
04938         drwav__ieee_to_s32(pBufferOut, sampleData, (size_t)(framesRead*pWav->channels), bytesPerFrame/pWav->channels);
04939 
04940         pBufferOut      += framesRead*pWav->channels;
04941         framesToRead    -= framesRead;
04942         totalFramesRead += framesRead;
04943     }
04944 
04945     return totalFramesRead;
04946 }
04947 
04948 static drwav_uint64 drwav_read_pcm_frames_s32__alaw(drwav* pWav, drwav_uint64 framesToRead, drwav_int32* pBufferOut)
04949 {
04950     drwav_uint64 totalFramesRead;
04951     drwav_uint8 sampleData[4096];
04952 
04953     drwav_uint32 bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
04954     if (bytesPerFrame == 0) {
04955         return 0;
04956     }
04957 
04958     totalFramesRead = 0;
04959 
04960     while (framesToRead > 0) {
04961         drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame), sampleData);
04962         if (framesRead == 0) {
04963             break;
04964         }
04965 
04966         drwav_alaw_to_s32(pBufferOut, sampleData, (size_t)(framesRead*pWav->channels));
04967 
04968         pBufferOut      += framesRead*pWav->channels;
04969         framesToRead    -= framesRead;
04970         totalFramesRead += framesRead;
04971     }
04972 
04973     return totalFramesRead;
04974 }
04975 
04976 static drwav_uint64 drwav_read_pcm_frames_s32__mulaw(drwav* pWav, drwav_uint64 framesToRead, drwav_int32* pBufferOut)
04977 {
04978     drwav_uint64 totalFramesRead;
04979     drwav_uint8 sampleData[4096];
04980 
04981     drwav_uint32 bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
04982     if (bytesPerFrame == 0) {
04983         return 0;
04984     }
04985 
04986     totalFramesRead = 0;
04987 
04988     while (framesToRead > 0) {
04989         drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame), sampleData);
04990         if (framesRead == 0) {
04991             break;
04992         }
04993 
04994         drwav_mulaw_to_s32(pBufferOut, sampleData, (size_t)(framesRead*pWav->channels));
04995 
04996         pBufferOut      += framesRead*pWav->channels;
04997         framesToRead    -= framesRead;
04998         totalFramesRead += framesRead;
04999     }
05000 
05001     return totalFramesRead;
05002 }
05003 
05004 DRWAV_API drwav_uint64 drwav_read_pcm_frames_s32(drwav* pWav, drwav_uint64 framesToRead, drwav_int32* pBufferOut)
05005 {
05006     if (pWav == NULL || framesToRead == 0 || pBufferOut == NULL) {
05007         return 0;
05008     }
05009 
05010     /* Don't try to read more samples than can potentially fit in the output buffer. */
05011     if (framesToRead * pWav->channels * sizeof(drwav_int32) > DRWAV_SIZE_MAX) {
05012         framesToRead = DRWAV_SIZE_MAX / sizeof(drwav_int32) / pWav->channels;
05013     }
05014 
05015 
05016     if (pWav->translatedFormatTag == DR_WAVE_FORMAT_PCM) {
05017         return drwav_read_pcm_frames_s32__pcm(pWav, framesToRead, pBufferOut);
05018     }
05019 
05020     if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ADPCM) {
05021         return drwav_read_pcm_frames_s32__msadpcm(pWav, framesToRead, pBufferOut);
05022     }
05023 
05024     if (pWav->translatedFormatTag == DR_WAVE_FORMAT_IEEE_FLOAT) {
05025         return drwav_read_pcm_frames_s32__ieee(pWav, framesToRead, pBufferOut);
05026     }
05027 
05028     if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ALAW) {
05029         return drwav_read_pcm_frames_s32__alaw(pWav, framesToRead, pBufferOut);
05030     }
05031 
05032     if (pWav->translatedFormatTag == DR_WAVE_FORMAT_MULAW) {
05033         return drwav_read_pcm_frames_s32__mulaw(pWav, framesToRead, pBufferOut);
05034     }
05035 
05036     if (pWav->translatedFormatTag == DR_WAVE_FORMAT_DVI_ADPCM) {
05037         return drwav_read_pcm_frames_s32__ima(pWav, framesToRead, pBufferOut);
05038     }
05039 
05040     return 0;
05041 }
05042 
05043 DRWAV_API drwav_uint64 drwav_read_pcm_frames_s32le(drwav* pWav, drwav_uint64 framesToRead, drwav_int32* pBufferOut)
05044 {
05045     drwav_uint64 framesRead = drwav_read_pcm_frames_s32(pWav, framesToRead, pBufferOut);
05046     if (!drwav__is_little_endian()) {
05047         drwav__bswap_samples_s32(pBufferOut, framesRead*pWav->channels);
05048     }
05049 
05050     return framesRead;
05051 }
05052 
05053 DRWAV_API drwav_uint64 drwav_read_pcm_frames_s32be(drwav* pWav, drwav_uint64 framesToRead, drwav_int32* pBufferOut)
05054 {
05055     drwav_uint64 framesRead = drwav_read_pcm_frames_s32(pWav, framesToRead, pBufferOut);
05056     if (drwav__is_little_endian()) {
05057         drwav__bswap_samples_s32(pBufferOut, framesRead*pWav->channels);
05058     }
05059 
05060     return framesRead;
05061 }
05062 
05063 
05064 DRWAV_API void drwav_u8_to_s32(drwav_int32* pOut, const drwav_uint8* pIn, size_t sampleCount)
05065 {
05066     size_t i;
05067 
05068     if (pOut == NULL || pIn == NULL) {
05069         return;
05070     }
05071 
05072     for (i = 0; i < sampleCount; ++i) {
05073         *pOut++ = ((int)pIn[i] - 128) << 24;
05074     }
05075 }
05076 
05077 DRWAV_API void drwav_s16_to_s32(drwav_int32* pOut, const drwav_int16* pIn, size_t sampleCount)
05078 {
05079     size_t i;
05080 
05081     if (pOut == NULL || pIn == NULL) {
05082         return;
05083     }
05084 
05085     for (i = 0; i < sampleCount; ++i) {
05086         *pOut++ = pIn[i] << 16;
05087     }
05088 }
05089 
05090 DRWAV_API void drwav_s24_to_s32(drwav_int32* pOut, const drwav_uint8* pIn, size_t sampleCount)
05091 {
05092     size_t i;
05093 
05094     if (pOut == NULL || pIn == NULL) {
05095         return;
05096     }
05097 
05098     for (i = 0; i < sampleCount; ++i) {
05099         unsigned int s0 = pIn[i*3 + 0];
05100         unsigned int s1 = pIn[i*3 + 1];
05101         unsigned int s2 = pIn[i*3 + 2];
05102 
05103         drwav_int32 sample32 = (drwav_int32)((s0 << 8) | (s1 << 16) | (s2 << 24));
05104         *pOut++ = sample32;
05105     }
05106 }
05107 
05108 DRWAV_API void drwav_f32_to_s32(drwav_int32* pOut, const float* pIn, size_t sampleCount)
05109 {
05110     size_t i;
05111 
05112     if (pOut == NULL || pIn == NULL) {
05113         return;
05114     }
05115 
05116     for (i = 0; i < sampleCount; ++i) {
05117         *pOut++ = (drwav_int32)(2147483648.0 * pIn[i]);
05118     }
05119 }
05120 
05121 DRWAV_API void drwav_f64_to_s32(drwav_int32* pOut, const double* pIn, size_t sampleCount)
05122 {
05123     size_t i;
05124 
05125     if (pOut == NULL || pIn == NULL) {
05126         return;
05127     }
05128 
05129     for (i = 0; i < sampleCount; ++i) {
05130         *pOut++ = (drwav_int32)(2147483648.0 * pIn[i]);
05131     }
05132 }
05133 
05134 DRWAV_API void drwav_alaw_to_s32(drwav_int32* pOut, const drwav_uint8* pIn, size_t sampleCount)
05135 {
05136     size_t i;
05137 
05138     if (pOut == NULL || pIn == NULL) {
05139         return;
05140     }
05141 
05142     for (i = 0; i < sampleCount; ++i) {
05143         *pOut++ = ((drwav_int32)drwav__alaw_to_s16(pIn[i])) << 16;
05144     }
05145 }
05146 
05147 DRWAV_API void drwav_mulaw_to_s32(drwav_int32* pOut, const drwav_uint8* pIn, size_t sampleCount)
05148 {
05149     size_t i;
05150 
05151     if (pOut == NULL || pIn == NULL) {
05152         return;
05153     }
05154 
05155     for (i= 0; i < sampleCount; ++i) {
05156         *pOut++ = ((drwav_int32)drwav__mulaw_to_s16(pIn[i])) << 16;
05157     }
05158 }
05159 
05160 
05161 
05162 static drwav_int16* drwav__read_pcm_frames_and_close_s16(drwav* pWav, unsigned int* channels, unsigned int* sampleRate, drwav_uint64* totalFrameCount)
05163 {
05164     drwav_uint64 sampleDataSize;
05165     drwav_int16* pSampleData;
05166     drwav_uint64 framesRead;
05167 
05168     DRWAV_ASSERT(pWav != NULL);
05169 
05170     sampleDataSize = pWav->totalPCMFrameCount * pWav->channels * sizeof(drwav_int16);
05171     if (sampleDataSize > DRWAV_SIZE_MAX) {
05172         drwav_uninit(pWav);
05173         return NULL;    /* File's too big. */
05174     }
05175 
05176     pSampleData = (drwav_int16*)drwav__malloc_from_callbacks((size_t)sampleDataSize, &pWav->allocationCallbacks); /* <-- Safe cast due to the check above. */
05177     if (pSampleData == NULL) {
05178         drwav_uninit(pWav);
05179         return NULL;    /* Failed to allocate memory. */
05180     }
05181 
05182     framesRead = drwav_read_pcm_frames_s16(pWav, (size_t)pWav->totalPCMFrameCount, pSampleData);
05183     if (framesRead != pWav->totalPCMFrameCount) {
05184         drwav__free_from_callbacks(pSampleData, &pWav->allocationCallbacks);
05185         drwav_uninit(pWav);
05186         return NULL;    /* There was an error reading the samples. */
05187     }
05188 
05189     drwav_uninit(pWav);
05190 
05191     if (sampleRate) {
05192         *sampleRate = pWav->sampleRate;
05193     }
05194     if (channels) {
05195         *channels = pWav->channels;
05196     }
05197     if (totalFrameCount) {
05198         *totalFrameCount = pWav->totalPCMFrameCount;
05199     }
05200 
05201     return pSampleData;
05202 }
05203 
05204 static float* drwav__read_pcm_frames_and_close_f32(drwav* pWav, unsigned int* channels, unsigned int* sampleRate, drwav_uint64* totalFrameCount)
05205 {
05206     drwav_uint64 sampleDataSize;
05207     float* pSampleData;
05208     drwav_uint64 framesRead;
05209 
05210     DRWAV_ASSERT(pWav != NULL);
05211 
05212     sampleDataSize = pWav->totalPCMFrameCount * pWav->channels * sizeof(float);
05213     if (sampleDataSize > DRWAV_SIZE_MAX) {
05214         drwav_uninit(pWav);
05215         return NULL;    /* File's too big. */
05216     }
05217 
05218     pSampleData = (float*)drwav__malloc_from_callbacks((size_t)sampleDataSize, &pWav->allocationCallbacks); /* <-- Safe cast due to the check above. */
05219     if (pSampleData == NULL) {
05220         drwav_uninit(pWav);
05221         return NULL;    /* Failed to allocate memory. */
05222     }
05223 
05224     framesRead = drwav_read_pcm_frames_f32(pWav, (size_t)pWav->totalPCMFrameCount, pSampleData);
05225     if (framesRead != pWav->totalPCMFrameCount) {
05226         drwav__free_from_callbacks(pSampleData, &pWav->allocationCallbacks);
05227         drwav_uninit(pWav);
05228         return NULL;    /* There was an error reading the samples. */
05229     }
05230 
05231     drwav_uninit(pWav);
05232 
05233     if (sampleRate) {
05234         *sampleRate = pWav->sampleRate;
05235     }
05236     if (channels) {
05237         *channels = pWav->channels;
05238     }
05239     if (totalFrameCount) {
05240         *totalFrameCount = pWav->totalPCMFrameCount;
05241     }
05242 
05243     return pSampleData;
05244 }
05245 
05246 static drwav_int32* drwav__read_pcm_frames_and_close_s32(drwav* pWav, unsigned int* channels, unsigned int* sampleRate, drwav_uint64* totalFrameCount)
05247 {
05248     drwav_uint64 sampleDataSize;
05249     drwav_int32* pSampleData;
05250     drwav_uint64 framesRead;
05251 
05252     DRWAV_ASSERT(pWav != NULL);
05253 
05254     sampleDataSize = pWav->totalPCMFrameCount * pWav->channels * sizeof(drwav_int32);
05255     if (sampleDataSize > DRWAV_SIZE_MAX) {
05256         drwav_uninit(pWav);
05257         return NULL;    /* File's too big. */
05258     }
05259 
05260     pSampleData = (drwav_int32*)drwav__malloc_from_callbacks((size_t)sampleDataSize, &pWav->allocationCallbacks); /* <-- Safe cast due to the check above. */
05261     if (pSampleData == NULL) {
05262         drwav_uninit(pWav);
05263         return NULL;    /* Failed to allocate memory. */
05264     }
05265 
05266     framesRead = drwav_read_pcm_frames_s32(pWav, (size_t)pWav->totalPCMFrameCount, pSampleData);
05267     if (framesRead != pWav->totalPCMFrameCount) {
05268         drwav__free_from_callbacks(pSampleData, &pWav->allocationCallbacks);
05269         drwav_uninit(pWav);
05270         return NULL;    /* There was an error reading the samples. */
05271     }
05272 
05273     drwav_uninit(pWav);
05274 
05275     if (sampleRate) {
05276         *sampleRate = pWav->sampleRate;
05277     }
05278     if (channels) {
05279         *channels = pWav->channels;
05280     }
05281     if (totalFrameCount) {
05282         *totalFrameCount = pWav->totalPCMFrameCount;
05283     }
05284 
05285     return pSampleData;
05286 }
05287 
05288 
05289 
05290 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)
05291 {
05292     drwav wav;
05293 
05294     if (channelsOut) {
05295         *channelsOut = 0;
05296     }
05297     if (sampleRateOut) {
05298         *sampleRateOut = 0;
05299     }
05300     if (totalFrameCountOut) {
05301         *totalFrameCountOut = 0;
05302     }
05303 
05304     if (!drwav_init(&wav, onRead, onSeek, pUserData, pAllocationCallbacks)) {
05305         return NULL;
05306     }
05307 
05308     return drwav__read_pcm_frames_and_close_s16(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
05309 }
05310 
05311 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)
05312 {
05313     drwav wav;
05314 
05315     if (channelsOut) {
05316         *channelsOut = 0;
05317     }
05318     if (sampleRateOut) {
05319         *sampleRateOut = 0;
05320     }
05321     if (totalFrameCountOut) {
05322         *totalFrameCountOut = 0;
05323     }
05324 
05325     if (!drwav_init(&wav, onRead, onSeek, pUserData, pAllocationCallbacks)) {
05326         return NULL;
05327     }
05328 
05329     return drwav__read_pcm_frames_and_close_f32(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
05330 }
05331 
05332 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)
05333 {
05334     drwav wav;
05335 
05336     if (channelsOut) {
05337         *channelsOut = 0;
05338     }
05339     if (sampleRateOut) {
05340         *sampleRateOut = 0;
05341     }
05342     if (totalFrameCountOut) {
05343         *totalFrameCountOut = 0;
05344     }
05345 
05346     if (!drwav_init(&wav, onRead, onSeek, pUserData, pAllocationCallbacks)) {
05347         return NULL;
05348     }
05349 
05350     return drwav__read_pcm_frames_and_close_s32(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
05351 }
05352 
05353 #ifndef DR_WAV_NO_STDIO
05354 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)
05355 {
05356     drwav wav;
05357 
05358     if (channelsOut) {
05359         *channelsOut = 0;
05360     }
05361     if (sampleRateOut) {
05362         *sampleRateOut = 0;
05363     }
05364     if (totalFrameCountOut) {
05365         *totalFrameCountOut = 0;
05366     }
05367 
05368     if (!drwav_init_file(&wav, filename, pAllocationCallbacks)) {
05369         return NULL;
05370     }
05371 
05372     return drwav__read_pcm_frames_and_close_s16(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
05373 }
05374 
05375 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)
05376 {
05377     drwav wav;
05378 
05379     if (channelsOut) {
05380         *channelsOut = 0;
05381     }
05382     if (sampleRateOut) {
05383         *sampleRateOut = 0;
05384     }
05385     if (totalFrameCountOut) {
05386         *totalFrameCountOut = 0;
05387     }
05388 
05389     if (!drwav_init_file(&wav, filename, pAllocationCallbacks)) {
05390         return NULL;
05391     }
05392 
05393     return drwav__read_pcm_frames_and_close_f32(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
05394 }
05395 
05396 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)
05397 {
05398     drwav wav;
05399 
05400     if (channelsOut) {
05401         *channelsOut = 0;
05402     }
05403     if (sampleRateOut) {
05404         *sampleRateOut = 0;
05405     }
05406     if (totalFrameCountOut) {
05407         *totalFrameCountOut = 0;
05408     }
05409 
05410     if (!drwav_init_file(&wav, filename, pAllocationCallbacks)) {
05411         return NULL;
05412     }
05413 
05414     return drwav__read_pcm_frames_and_close_s32(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
05415 }
05416 
05417 
05418 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)
05419 {
05420     drwav wav;
05421 
05422     if (sampleRateOut) {
05423         *sampleRateOut = 0;
05424     }
05425     if (channelsOut) {
05426         *channelsOut = 0;
05427     }
05428     if (totalFrameCountOut) {
05429         *totalFrameCountOut = 0;
05430     }
05431 
05432     if (!drwav_init_file_w(&wav, filename, pAllocationCallbacks)) {
05433         return NULL;
05434     }
05435 
05436     return drwav__read_pcm_frames_and_close_s16(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
05437 }
05438 
05439 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)
05440 {
05441     drwav wav;
05442 
05443     if (sampleRateOut) {
05444         *sampleRateOut = 0;
05445     }
05446     if (channelsOut) {
05447         *channelsOut = 0;
05448     }
05449     if (totalFrameCountOut) {
05450         *totalFrameCountOut = 0;
05451     }
05452 
05453     if (!drwav_init_file_w(&wav, filename, pAllocationCallbacks)) {
05454         return NULL;
05455     }
05456 
05457     return drwav__read_pcm_frames_and_close_f32(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
05458 }
05459 
05460 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)
05461 {
05462     drwav wav;
05463 
05464     if (sampleRateOut) {
05465         *sampleRateOut = 0;
05466     }
05467     if (channelsOut) {
05468         *channelsOut = 0;
05469     }
05470     if (totalFrameCountOut) {
05471         *totalFrameCountOut = 0;
05472     }
05473 
05474     if (!drwav_init_file_w(&wav, filename, pAllocationCallbacks)) {
05475         return NULL;
05476     }
05477 
05478     return drwav__read_pcm_frames_and_close_s32(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
05479 }
05480 #endif
05481 
05482 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)
05483 {
05484     drwav wav;
05485 
05486     if (channelsOut) {
05487         *channelsOut = 0;
05488     }
05489     if (sampleRateOut) {
05490         *sampleRateOut = 0;
05491     }
05492     if (totalFrameCountOut) {
05493         *totalFrameCountOut = 0;
05494     }
05495 
05496     if (!drwav_init_memory(&wav, data, dataSize, pAllocationCallbacks)) {
05497         return NULL;
05498     }
05499 
05500     return drwav__read_pcm_frames_and_close_s16(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
05501 }
05502 
05503 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)
05504 {
05505     drwav wav;
05506 
05507     if (channelsOut) {
05508         *channelsOut = 0;
05509     }
05510     if (sampleRateOut) {
05511         *sampleRateOut = 0;
05512     }
05513     if (totalFrameCountOut) {
05514         *totalFrameCountOut = 0;
05515     }
05516 
05517     if (!drwav_init_memory(&wav, data, dataSize, pAllocationCallbacks)) {
05518         return NULL;
05519     }
05520 
05521     return drwav__read_pcm_frames_and_close_f32(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
05522 }
05523 
05524 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)
05525 {
05526     drwav wav;
05527 
05528     if (channelsOut) {
05529         *channelsOut = 0;
05530     }
05531     if (sampleRateOut) {
05532         *sampleRateOut = 0;
05533     }
05534     if (totalFrameCountOut) {
05535         *totalFrameCountOut = 0;
05536     }
05537 
05538     if (!drwav_init_memory(&wav, data, dataSize, pAllocationCallbacks)) {
05539         return NULL;
05540     }
05541 
05542     return drwav__read_pcm_frames_and_close_s32(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
05543 }
05544 #endif  /* DR_WAV_NO_CONVERSION_API */
05545 
05546 
05547 DRWAV_API void drwav_free(void* p, const drwav_allocation_callbacks* pAllocationCallbacks)
05548 {
05549     if (pAllocationCallbacks != NULL) {
05550         drwav__free_from_callbacks(p, pAllocationCallbacks);
05551     } else {
05552         drwav__free_default(p, NULL);
05553     }
05554 }
05555 
05556 DRWAV_API drwav_uint16 drwav_bytes_to_u16(const drwav_uint8* data)
05557 {
05558     return drwav__bytes_to_u16(data);
05559 }
05560 
05561 DRWAV_API drwav_int16 drwav_bytes_to_s16(const drwav_uint8* data)
05562 {
05563     return drwav__bytes_to_s16(data);
05564 }
05565 
05566 DRWAV_API drwav_uint32 drwav_bytes_to_u32(const drwav_uint8* data)
05567 {
05568     return drwav__bytes_to_u32(data);
05569 }
05570 
05571 DRWAV_API drwav_int32 drwav_bytes_to_s32(const drwav_uint8* data)
05572 {
05573     return drwav__bytes_to_s32(data);
05574 }
05575 
05576 DRWAV_API drwav_uint64 drwav_bytes_to_u64(const drwav_uint8* data)
05577 {
05578     return drwav__bytes_to_u64(data);
05579 }
05580 
05581 DRWAV_API drwav_int64 drwav_bytes_to_s64(const drwav_uint8* data)
05582 {
05583     return drwav__bytes_to_s64(data);
05584 }
05585 
05586 
05587 DRWAV_API drwav_bool32 drwav_guid_equal(const drwav_uint8 a[16], const drwav_uint8 b[16])
05588 {
05589     return drwav__guid_equal(a, b);
05590 }
05591 
05592 DRWAV_API drwav_bool32 drwav_fourcc_equal(const drwav_uint8* a, const char* b)
05593 {
05594     return drwav__fourcc_equal(a, b);
05595 }
05596 
05597 #endif  /* DR_WAV_IMPLEMENTATION */
05598 
05599 /*
05600 RELEASE NOTES - v0.11.0
05601 =======================
05602 Version 0.11.0 has breaking API changes.
05603 
05604 Improved Client-Defined Memory Allocation
05605 -----------------------------------------
05606 The main change with this release is the addition of a more flexible way of implementing custom memory allocation routines. The
05607 existing system of DRWAV_MALLOC, DRWAV_REALLOC and DRWAV_FREE are still in place and will be used by default when no custom
05608 allocation callbacks are specified.
05609 
05610 To use the new system, you pass in a pointer to a drwav_allocation_callbacks object to drwav_init() and family, like this:
05611 
05612     void* my_malloc(size_t sz, void* pUserData)
05613     {
05614         return malloc(sz);
05615     }
05616     void* my_realloc(void* p, size_t sz, void* pUserData)
05617     {
05618         return realloc(p, sz);
05619     }
05620     void my_free(void* p, void* pUserData)
05621     {
05622         free(p);
05623     }
05624 
05625     ...
05626 
05627     drwav_allocation_callbacks allocationCallbacks;
05628     allocationCallbacks.pUserData = &myData;
05629     allocationCallbacks.onMalloc  = my_malloc;
05630     allocationCallbacks.onRealloc = my_realloc;
05631     allocationCallbacks.onFree    = my_free;
05632     drwav_init_file(&wav, "my_file.wav", &allocationCallbacks);
05633 
05634 The advantage of this new system is that it allows you to specify user data which will be passed in to the allocation routines.
05635 
05636 Passing in null for the allocation callbacks object will cause dr_wav to use defaults which is the same as DRWAV_MALLOC,
05637 DRWAV_REALLOC and DRWAV_FREE and the equivalent of how it worked in previous versions.
05638 
05639 Every API that opens a drwav object now takes this extra parameter. These include the following:
05640 
05641     drwav_init()
05642     drwav_init_ex()
05643     drwav_init_file()
05644     drwav_init_file_ex()
05645     drwav_init_file_w()
05646     drwav_init_file_w_ex()
05647     drwav_init_memory()
05648     drwav_init_memory_ex()
05649     drwav_init_write()
05650     drwav_init_write_sequential()
05651     drwav_init_write_sequential_pcm_frames()
05652     drwav_init_file_write()
05653     drwav_init_file_write_sequential()
05654     drwav_init_file_write_sequential_pcm_frames()
05655     drwav_init_file_write_w()
05656     drwav_init_file_write_sequential_w()
05657     drwav_init_file_write_sequential_pcm_frames_w()
05658     drwav_init_memory_write()
05659     drwav_init_memory_write_sequential()
05660     drwav_init_memory_write_sequential_pcm_frames()
05661     drwav_open_and_read_pcm_frames_s16()
05662     drwav_open_and_read_pcm_frames_f32()
05663     drwav_open_and_read_pcm_frames_s32()
05664     drwav_open_file_and_read_pcm_frames_s16()
05665     drwav_open_file_and_read_pcm_frames_f32()
05666     drwav_open_file_and_read_pcm_frames_s32()
05667     drwav_open_file_and_read_pcm_frames_s16_w()
05668     drwav_open_file_and_read_pcm_frames_f32_w()
05669     drwav_open_file_and_read_pcm_frames_s32_w()
05670     drwav_open_memory_and_read_pcm_frames_s16()
05671     drwav_open_memory_and_read_pcm_frames_f32()
05672     drwav_open_memory_and_read_pcm_frames_s32()
05673 
05674 Endian Improvements
05675 -------------------
05676 Previously, the following APIs returned little-endian audio data. These now return native-endian data. This improves compatibility
05677 on big-endian architectures.
05678 
05679     drwav_read_pcm_frames()
05680     drwav_read_pcm_frames_s16()
05681     drwav_read_pcm_frames_s32()
05682     drwav_read_pcm_frames_f32()
05683     drwav_open_and_read_pcm_frames_s16()
05684     drwav_open_and_read_pcm_frames_s32()
05685     drwav_open_and_read_pcm_frames_f32()
05686     drwav_open_file_and_read_pcm_frames_s16()
05687     drwav_open_file_and_read_pcm_frames_s32()
05688     drwav_open_file_and_read_pcm_frames_f32()
05689     drwav_open_file_and_read_pcm_frames_s16_w()
05690     drwav_open_file_and_read_pcm_frames_s32_w()
05691     drwav_open_file_and_read_pcm_frames_f32_w()
05692     drwav_open_memory_and_read_pcm_frames_s16()
05693     drwav_open_memory_and_read_pcm_frames_s32()
05694     drwav_open_memory_and_read_pcm_frames_f32()
05695 
05696 APIs have been added to give you explicit control over whether or not audio data is read or written in big- or little-endian byte
05697 order:
05698 
05699     drwav_read_pcm_frames_le()
05700     drwav_read_pcm_frames_be()
05701     drwav_read_pcm_frames_s16le()
05702     drwav_read_pcm_frames_s16be()
05703     drwav_read_pcm_frames_f32le()
05704     drwav_read_pcm_frames_f32be()
05705     drwav_read_pcm_frames_s32le()
05706     drwav_read_pcm_frames_s32be()
05707     drwav_write_pcm_frames_le()
05708     drwav_write_pcm_frames_be()
05709 
05710 Removed APIs
05711 ------------
05712 The following APIs were deprecated in version 0.10.0 and have now been removed:
05713 
05714     drwav_open()
05715     drwav_open_ex()
05716     drwav_open_write()
05717     drwav_open_write_sequential()
05718     drwav_open_file()
05719     drwav_open_file_ex()
05720     drwav_open_file_write()
05721     drwav_open_file_write_sequential()
05722     drwav_open_memory()
05723     drwav_open_memory_ex()
05724     drwav_open_memory_write()
05725     drwav_open_memory_write_sequential()
05726     drwav_close()
05727 
05728 
05729 
05730 RELEASE NOTES - v0.10.0
05731 =======================
05732 Version 0.10.0 has breaking API changes. There are no significant bug fixes in this release, so if you are affected you do
05733 not need to upgrade.
05734 
05735 Removed APIs
05736 ------------
05737 The following APIs were deprecated in version 0.9.0 and have been completely removed in version 0.10.0:
05738 
05739     drwav_read()
05740     drwav_read_s16()
05741     drwav_read_f32()
05742     drwav_read_s32()
05743     drwav_seek_to_sample()
05744     drwav_write()
05745     drwav_open_and_read_s16()
05746     drwav_open_and_read_f32()
05747     drwav_open_and_read_s32()
05748     drwav_open_file_and_read_s16()
05749     drwav_open_file_and_read_f32()
05750     drwav_open_file_and_read_s32()
05751     drwav_open_memory_and_read_s16()
05752     drwav_open_memory_and_read_f32()
05753     drwav_open_memory_and_read_s32()
05754     drwav::totalSampleCount
05755 
05756 See release notes for version 0.9.0 at the bottom of this file for replacement APIs.
05757 
05758 Deprecated APIs
05759 ---------------
05760 The following APIs have been deprecated. There is a confusing and completely arbitrary difference between drwav_init*() and
05761 drwav_open*(), where drwav_init*() initializes a pre-allocated drwav object, whereas drwav_open*() will first allocated a
05762 drwav object on the heap and then initialize it. drwav_open*() has been deprecated which means you must now use a pre-
05763 allocated drwav object with drwav_init*(). If you need the previous functionality, you can just do a malloc() followed by
05764 a called to one of the drwav_init*() APIs.
05765 
05766     drwav_open()
05767     drwav_open_ex()
05768     drwav_open_write()
05769     drwav_open_write_sequential()
05770     drwav_open_file()
05771     drwav_open_file_ex()
05772     drwav_open_file_write()
05773     drwav_open_file_write_sequential()
05774     drwav_open_memory()
05775     drwav_open_memory_ex()
05776     drwav_open_memory_write()
05777     drwav_open_memory_write_sequential()
05778     drwav_close()
05779 
05780 These APIs will be removed completely in a future version. The rationale for this change is to remove confusion between the
05781 two different ways to initialize a drwav object.
05782 */
05783 
05784 /*
05785 REVISION HISTORY
05786 ================
05787 v0.12.4 - 2020-05-16
05788   - Replace assert() with DRWAV_ASSERT().
05789   - Add compile-time and run-time version querying.
05790     - DRWAV_VERSION_MINOR
05791     - DRWAV_VERSION_MAJOR
05792     - DRWAV_VERSION_REVISION
05793     - DRWAV_VERSION_STRING
05794     - drwav_version()
05795     - drwav_version_string()
05796 
05797 v0.12.3 - 2020-04-30
05798   - Fix compilation errors with VC6.
05799 
05800 v0.12.2 - 2020-04-21
05801   - Fix a bug where drwav_init_file() does not close the file handle after attempting to load an erroneous file.
05802 
05803 v0.12.1 - 2020-04-13
05804   - Fix some pedantic warnings.
05805 
05806 v0.12.0 - 2020-04-04
05807   - API CHANGE: Add container and format parameters to the chunk callback.
05808   - Minor documentation updates.
05809 
05810 v0.11.5 - 2020-03-07
05811   - Fix compilation error with Visual Studio .NET 2003.
05812 
05813 v0.11.4 - 2020-01-29
05814   - Fix some static analysis warnings.
05815   - Fix a bug when reading f32 samples from an A-law encoded stream.
05816 
05817 v0.11.3 - 2020-01-12
05818   - Minor changes to some f32 format conversion routines.
05819   - Minor bug fix for ADPCM conversion when end of file is reached.
05820 
05821 v0.11.2 - 2019-12-02
05822   - Fix a possible crash when using custom memory allocators without a custom realloc() implementation.
05823   - Fix an integer overflow bug.
05824   - Fix a null pointer dereference bug.
05825   - Add limits to sample rate, channels and bits per sample to tighten up some validation.
05826 
05827 v0.11.1 - 2019-10-07
05828   - Internal code clean up.
05829 
05830 v0.11.0 - 2019-10-06
05831   - API CHANGE: Add support for user defined memory allocation routines. This system allows the program to specify their own memory allocation
05832     routines with a user data pointer for client-specific contextual data. This adds an extra parameter to the end of the following APIs:
05833     - drwav_init()
05834     - drwav_init_ex()
05835     - drwav_init_file()
05836     - drwav_init_file_ex()
05837     - drwav_init_file_w()
05838     - drwav_init_file_w_ex()
05839     - drwav_init_memory()
05840     - drwav_init_memory_ex()
05841     - drwav_init_write()
05842     - drwav_init_write_sequential()
05843     - drwav_init_write_sequential_pcm_frames()
05844     - drwav_init_file_write()
05845     - drwav_init_file_write_sequential()
05846     - drwav_init_file_write_sequential_pcm_frames()
05847     - drwav_init_file_write_w()
05848     - drwav_init_file_write_sequential_w()
05849     - drwav_init_file_write_sequential_pcm_frames_w()
05850     - drwav_init_memory_write()
05851     - drwav_init_memory_write_sequential()
05852     - drwav_init_memory_write_sequential_pcm_frames()
05853     - drwav_open_and_read_pcm_frames_s16()
05854     - drwav_open_and_read_pcm_frames_f32()
05855     - drwav_open_and_read_pcm_frames_s32()
05856     - drwav_open_file_and_read_pcm_frames_s16()
05857     - drwav_open_file_and_read_pcm_frames_f32()
05858     - drwav_open_file_and_read_pcm_frames_s32()
05859     - drwav_open_file_and_read_pcm_frames_s16_w()
05860     - drwav_open_file_and_read_pcm_frames_f32_w()
05861     - drwav_open_file_and_read_pcm_frames_s32_w()
05862     - drwav_open_memory_and_read_pcm_frames_s16()
05863     - drwav_open_memory_and_read_pcm_frames_f32()
05864     - drwav_open_memory_and_read_pcm_frames_s32()
05865     Set this extra parameter to NULL to use defaults which is the same as the previous behaviour. Setting this NULL will use
05866     DRWAV_MALLOC, DRWAV_REALLOC and DRWAV_FREE.
05867   - Add support for reading and writing PCM frames in an explicit endianness. New APIs:
05868     - drwav_read_pcm_frames_le()
05869     - drwav_read_pcm_frames_be()
05870     - drwav_read_pcm_frames_s16le()
05871     - drwav_read_pcm_frames_s16be()
05872     - drwav_read_pcm_frames_f32le()
05873     - drwav_read_pcm_frames_f32be()
05874     - drwav_read_pcm_frames_s32le()
05875     - drwav_read_pcm_frames_s32be()
05876     - drwav_write_pcm_frames_le()
05877     - drwav_write_pcm_frames_be()
05878   - Remove deprecated APIs.
05879   - API CHANGE: The following APIs now return native-endian data. Previously they returned little-endian data.
05880     - drwav_read_pcm_frames()
05881     - drwav_read_pcm_frames_s16()
05882     - drwav_read_pcm_frames_s32()
05883     - drwav_read_pcm_frames_f32()
05884     - drwav_open_and_read_pcm_frames_s16()
05885     - drwav_open_and_read_pcm_frames_s32()
05886     - drwav_open_and_read_pcm_frames_f32()
05887     - drwav_open_file_and_read_pcm_frames_s16()
05888     - drwav_open_file_and_read_pcm_frames_s32()
05889     - drwav_open_file_and_read_pcm_frames_f32()
05890     - drwav_open_file_and_read_pcm_frames_s16_w()
05891     - drwav_open_file_and_read_pcm_frames_s32_w()
05892     - drwav_open_file_and_read_pcm_frames_f32_w()
05893     - drwav_open_memory_and_read_pcm_frames_s16()
05894     - drwav_open_memory_and_read_pcm_frames_s32()
05895     - drwav_open_memory_and_read_pcm_frames_f32()
05896 
05897 v0.10.1 - 2019-08-31
05898   - Correctly handle partial trailing ADPCM blocks.
05899 
05900 v0.10.0 - 2019-08-04
05901   - Remove deprecated APIs.
05902   - Add wchar_t variants for file loading APIs:
05903       drwav_init_file_w()
05904       drwav_init_file_ex_w()
05905       drwav_init_file_write_w()
05906       drwav_init_file_write_sequential_w()
05907   - Add drwav_target_write_size_bytes() which calculates the total size in bytes of a WAV file given a format and sample count.
05908   - Add APIs for specifying the PCM frame count instead of the sample count when opening in sequential write mode:
05909       drwav_init_write_sequential_pcm_frames()
05910       drwav_init_file_write_sequential_pcm_frames()
05911       drwav_init_file_write_sequential_pcm_frames_w()
05912       drwav_init_memory_write_sequential_pcm_frames()
05913   - Deprecate drwav_open*() and drwav_close():
05914       drwav_open()
05915       drwav_open_ex()
05916       drwav_open_write()
05917       drwav_open_write_sequential()
05918       drwav_open_file()
05919       drwav_open_file_ex()
05920       drwav_open_file_write()
05921       drwav_open_file_write_sequential()
05922       drwav_open_memory()
05923       drwav_open_memory_ex()
05924       drwav_open_memory_write()
05925       drwav_open_memory_write_sequential()
05926       drwav_close()
05927   - Minor documentation updates.
05928 
05929 v0.9.2 - 2019-05-21
05930   - Fix warnings.
05931 
05932 v0.9.1 - 2019-05-05
05933   - Add support for C89.
05934   - Change license to choice of public domain or MIT-0.
05935 
05936 v0.9.0 - 2018-12-16
05937   - API CHANGE: Add new reading APIs for reading by PCM frames instead of samples. Old APIs have been deprecated and
05938     will be removed in v0.10.0. Deprecated APIs and their replacements:
05939       drwav_read()                     -> drwav_read_pcm_frames()
05940       drwav_read_s16()                 -> drwav_read_pcm_frames_s16()
05941       drwav_read_f32()                 -> drwav_read_pcm_frames_f32()
05942       drwav_read_s32()                 -> drwav_read_pcm_frames_s32()
05943       drwav_seek_to_sample()           -> drwav_seek_to_pcm_frame()
05944       drwav_write()                    -> drwav_write_pcm_frames()
05945       drwav_open_and_read_s16()        -> drwav_open_and_read_pcm_frames_s16()
05946       drwav_open_and_read_f32()        -> drwav_open_and_read_pcm_frames_f32()
05947       drwav_open_and_read_s32()        -> drwav_open_and_read_pcm_frames_s32()
05948       drwav_open_file_and_read_s16()   -> drwav_open_file_and_read_pcm_frames_s16()
05949       drwav_open_file_and_read_f32()   -> drwav_open_file_and_read_pcm_frames_f32()
05950       drwav_open_file_and_read_s32()   -> drwav_open_file_and_read_pcm_frames_s32()
05951       drwav_open_memory_and_read_s16() -> drwav_open_memory_and_read_pcm_frames_s16()
05952       drwav_open_memory_and_read_f32() -> drwav_open_memory_and_read_pcm_frames_f32()
05953       drwav_open_memory_and_read_s32() -> drwav_open_memory_and_read_pcm_frames_s32()
05954       drwav::totalSampleCount          -> drwav::totalPCMFrameCount
05955   - API CHANGE: Rename drwav_open_and_read_file_*() to drwav_open_file_and_read_*().
05956   - API CHANGE: Rename drwav_open_and_read_memory_*() to drwav_open_memory_and_read_*().
05957   - Add built-in support for smpl chunks.
05958   - Add support for firing a callback for each chunk in the file at initialization time.
05959     - This is enabled through the drwav_init_ex(), etc. family of APIs.
05960   - Handle invalid FMT chunks more robustly.
05961 
05962 v0.8.5 - 2018-09-11
05963   - Const correctness.
05964   - Fix a potential stack overflow.
05965 
05966 v0.8.4 - 2018-08-07
05967   - Improve 64-bit detection.
05968 
05969 v0.8.3 - 2018-08-05
05970   - Fix C++ build on older versions of GCC.
05971 
05972 v0.8.2 - 2018-08-02
05973   - Fix some big-endian bugs.
05974 
05975 v0.8.1 - 2018-06-29
05976   - Add support for sequential writing APIs.
05977   - Disable seeking in write mode.
05978   - Fix bugs with Wave64.
05979   - Fix typos.
05980 
05981 v0.8 - 2018-04-27
05982   - Bug fix.
05983   - Start using major.minor.revision versioning.
05984 
05985 v0.7f - 2018-02-05
05986   - Restrict ADPCM formats to a maximum of 2 channels.
05987 
05988 v0.7e - 2018-02-02
05989   - Fix a crash.
05990 
05991 v0.7d - 2018-02-01
05992   - Fix a crash.
05993 
05994 v0.7c - 2018-02-01
05995   - Set drwav.bytesPerSample to 0 for all compressed formats.
05996   - Fix a crash when reading 16-bit floating point WAV files. In this case dr_wav will output silence for
05997     all format conversion reading APIs (*_s16, *_s32, *_f32 APIs).
05998   - Fix some divide-by-zero errors.
05999 
06000 v0.7b - 2018-01-22
06001   - Fix errors with seeking of compressed formats.
06002   - Fix compilation error when DR_WAV_NO_CONVERSION_API
06003 
06004 v0.7a - 2017-11-17
06005   - Fix some GCC warnings.
06006 
06007 v0.7 - 2017-11-04
06008   - Add writing APIs.
06009 
06010 v0.6 - 2017-08-16
06011   - API CHANGE: Rename dr_* types to drwav_*.
06012   - Add support for custom implementations of malloc(), realloc(), etc.
06013   - Add support for Microsoft ADPCM.
06014   - Add support for IMA ADPCM (DVI, format code 0x11).
06015   - Optimizations to drwav_read_s16().
06016   - Bug fixes.
06017 
06018 v0.5g - 2017-07-16
06019   - Change underlying type for booleans to unsigned.
06020 
06021 v0.5f - 2017-04-04
06022   - Fix a minor bug with drwav_open_and_read_s16() and family.
06023 
06024 v0.5e - 2016-12-29
06025   - Added support for reading samples as signed 16-bit integers. Use the _s16() family of APIs for this.
06026   - Minor fixes to documentation.
06027 
06028 v0.5d - 2016-12-28
06029   - Use drwav_int* and drwav_uint* sized types to improve compiler support.
06030 
06031 v0.5c - 2016-11-11
06032   - Properly handle JUNK chunks that come before the FMT chunk.
06033 
06034 v0.5b - 2016-10-23
06035   - A minor change to drwav_bool8 and drwav_bool32 types.
06036 
06037 v0.5a - 2016-10-11
06038   - Fixed a bug with drwav_open_and_read() and family due to incorrect argument ordering.
06039   - Improve A-law and mu-law efficiency.
06040 
06041 v0.5 - 2016-09-29
06042   - API CHANGE. Swap the order of "channels" and "sampleRate" parameters in drwav_open_and_read*(). Rationale for this is to
06043     keep it consistent with dr_audio and dr_flac.
06044 
06045 v0.4b - 2016-09-18
06046   - Fixed a typo in documentation.
06047 
06048 v0.4a - 2016-09-18
06049   - Fixed a typo.
06050   - Change date format to ISO 8601 (YYYY-MM-DD)
06051 
06052 v0.4 - 2016-07-13
06053   - API CHANGE. Make onSeek consistent with dr_flac.
06054   - API CHANGE. Rename drwav_seek() to drwav_seek_to_sample() for clarity and consistency with dr_flac.
06055   - Added support for Sony Wave64.
06056 
06057 v0.3a - 2016-05-28
06058   - API CHANGE. Return drwav_bool32 instead of int in onSeek callback.
06059   - Fixed a memory leak.
06060 
06061 v0.3 - 2016-05-22
06062   - Lots of API changes for consistency.
06063 
06064 v0.2a - 2016-05-16
06065   - Fixed Linux/GCC build.
06066 
06067 v0.2 - 2016-05-11
06068   - Added support for reading data as signed 32-bit PCM for consistency with dr_flac.
06069 
06070 v0.1a - 2016-05-07
06071   - Fixed a bug in drwav_open_file() where the file handle would not be closed if the loader failed to initialize.
06072 
06073 v0.1 - 2016-05-04
06074   - Initial versioned release.
06075 */
06076 
06077 /*
06078 This software is available as a choice of the following licenses. Choose
06079 whichever you prefer.
06080 
06081 ===============================================================================
06082 ALTERNATIVE 1 - Public Domain (www.unlicense.org)
06083 ===============================================================================
06084 This is free and unencumbered software released into the public domain.
06085 
06086 Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
06087 software, either in source code form or as a compiled binary, for any purpose,
06088 commercial or non-commercial, and by any means.
06089 
06090 In jurisdictions that recognize copyright laws, the author or authors of this
06091 software dedicate any and all copyright interest in the software to the public
06092 domain. We make this dedication for the benefit of the public at large and to
06093 the detriment of our heirs and successors. We intend this dedication to be an
06094 overt act of relinquishment in perpetuity of all present and future rights to
06095 this software under copyright law.
06096 
06097 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
06098 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
06099 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
06100 AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
06101 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
06102 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
06103 
06104 For more information, please refer to <http://unlicense.org/>
06105 
06106 ===============================================================================
06107 ALTERNATIVE 2 - MIT No Attribution
06108 ===============================================================================
06109 Copyright 2020 David Reid
06110 
06111 Permission is hereby granted, free of charge, to any person obtaining a copy of
06112 this software and associated documentation files (the "Software"), to deal in
06113 the Software without restriction, including without limitation the rights to
06114 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
06115 of the Software, and to permit persons to whom the Software is furnished to do
06116 so.
06117 
06118 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
06119 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
06120 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
06121 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
06122 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
06123 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
06124 SOFTWARE.
06125 */