github.com/Konstantin8105/c4go@v0.0.0-20240505174241-768bb1c65a51/tests/raylib/external/dr_wav.h (about)

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