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