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


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