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


picovoice_driver
Author(s):
autogenerated on Fri Apr 1 2022 02:13:55