-
Notifications
You must be signed in to change notification settings - Fork 0
/
dr_wav.h
6404 lines (5238 loc) · 235 KB
/
dr_wav.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
WAV audio loader and writer. Choice of public domain or MIT-0. See license statements at the end of this file.
dr_wav - v0.12.17 - 2021-01-17
David Reid - [email protected]
GitHub: https://github.com/mackron/dr_libs
*/
/*
RELEASE NOTES - VERSION 0.12
============================
Version 0.12 includes breaking changes to custom chunk handling.
Changes to Chunk Callback
-------------------------
dr_wav supports the ability to fire a callback when a chunk is encounted (except for WAVE and FMT chunks). The callback has been updated to include both the
container (RIFF or Wave64) and the FMT chunk which contains information about the format of the data in the wave file.
Previously, there was no direct way to determine the container, and therefore no way to discriminate against the different IDs in the chunk header (RIFF and
Wave64 containers encode chunk ID's differently). The `container` parameter can be used to know which ID to use.
Sometimes it can be useful to know the data format at the time the chunk callback is fired. A pointer to a `drwav_fmt` object is now passed into the chunk
callback which will give you information about the data format. To determine the sample format, use `drwav_fmt_get_format()`. This will return one of the
`DR_WAVE_FORMAT_*` tokens.
*/
/*
Introduction
============
This is a single file library. To use it, do something like the following in one .c file.
```c
#define DR_WAV_IMPLEMENTATION
#include "dr_wav.h"
```
You can then #include this file in other parts of the program as you would with any other header file. Do something like the following to read audio data:
```c
drwav wav;
if (!drwav_init_file(&wav, "my_song.wav", NULL)) {
// Error opening WAV file.
}
drwav_int32* pDecodedInterleavedPCMFrames = malloc(wav.totalPCMFrameCount * wav.channels * sizeof(drwav_int32));
size_t numberOfSamplesActuallyDecoded = drwav_read_pcm_frames_s32(&wav, wav.totalPCMFrameCount, pDecodedInterleavedPCMFrames);
...
drwav_uninit(&wav);
```
If you just want to quickly open and read the audio data in a single operation you can do something like this:
```c
unsigned int channels;
unsigned int sampleRate;
drwav_uint64 totalPCMFrameCount;
float* pSampleData = drwav_open_file_and_read_pcm_frames_f32("my_song.wav", &channels, &sampleRate, &totalPCMFrameCount, NULL);
if (pSampleData == NULL) {
// Error opening and reading WAV file.
}
...
drwav_free(pSampleData, NULL);
```
The examples above use versions of the API that convert the audio data to a consistent format (32-bit signed PCM, in this case), but you can still output the
audio data in its internal format (see notes below for supported formats):
```c
size_t framesRead = drwav_read_pcm_frames(&wav, wav.totalPCMFrameCount, pDecodedInterleavedPCMFrames);
```
You can also read the raw bytes of audio data, which could be useful if dr_wav does not have native support for a particular data format:
```c
size_t bytesRead = drwav_read_raw(&wav, bytesToRead, pRawDataBuffer);
```
dr_wav can also be used to output WAV files. This does not currently support compressed formats. To use this, look at `drwav_init_write()`,
`drwav_init_file_write()`, etc. Use `drwav_write_pcm_frames()` to write samples, or `drwav_write_raw()` to write raw data in the "data" chunk.
```c
drwav_data_format format;
format.container = drwav_container_riff; // <-- drwav_container_riff = normal WAV files, drwav_container_w64 = Sony Wave64.
format.format = DR_WAVE_FORMAT_PCM; // <-- Any of the DR_WAVE_FORMAT_* codes.
format.channels = 2;
format.sampleRate = 44100;
format.bitsPerSample = 16;
drwav_init_file_write(&wav, "data/recording.wav", &format, NULL);
...
drwav_uint64 framesWritten = drwav_write_pcm_frames(pWav, frameCount, pSamples);
```
dr_wav has seamless support the Sony Wave64 format. The decoder will automatically detect it and it should Just Work without any manual intervention.
Build Options
=============
#define these options before including this file.
#define DR_WAV_NO_CONVERSION_API
Disables conversion APIs such as `drwav_read_pcm_frames_f32()` and `drwav_s16_to_f32()`.
#define DR_WAV_NO_STDIO
Disables APIs that initialize a decoder from a file such as `drwav_init_file()`, `drwav_init_file_write()`, etc.
Notes
=====
- Samples are always interleaved.
- The default read function does not do any data conversion. Use `drwav_read_pcm_frames_f32()`, `drwav_read_pcm_frames_s32()` and `drwav_read_pcm_frames_s16()`
to read and convert audio data to 32-bit floating point, signed 32-bit integer and signed 16-bit integer samples respectively. Tested and supported internal
formats include the following:
- Unsigned 8-bit PCM
- Signed 12-bit PCM
- Signed 16-bit PCM
- Signed 24-bit PCM
- Signed 32-bit PCM
- IEEE 32-bit floating point
- IEEE 64-bit floating point
- A-law and u-law
- Microsoft ADPCM
- IMA ADPCM (DVI, format code 0x11)
- dr_wav will try to read the WAV file as best it can, even if it's not strictly conformant to the WAV format.
*/
#ifndef dr_wav_h
#define dr_wav_h
#ifdef __cplusplus
extern "C" {
#endif
#define DRWAV_STRINGIFY(x) #x
#define DRWAV_XSTRINGIFY(x) DRWAV_STRINGIFY(x)
#define DRWAV_VERSION_MAJOR 0
#define DRWAV_VERSION_MINOR 12
#define DRWAV_VERSION_REVISION 17
#define DRWAV_VERSION_STRING DRWAV_XSTRINGIFY(DRWAV_VERSION_MAJOR) "." DRWAV_XSTRINGIFY(DRWAV_VERSION_MINOR) "." DRWAV_XSTRINGIFY(DRWAV_VERSION_REVISION)
#include <stddef.h> /* For size_t. */
/* Sized types. */
typedef signed char drwav_int8;
typedef unsigned char drwav_uint8;
typedef signed short drwav_int16;
typedef unsigned short drwav_uint16;
typedef signed int drwav_int32;
typedef unsigned int drwav_uint32;
#if defined(_MSC_VER)
typedef signed __int64 drwav_int64;
typedef unsigned __int64 drwav_uint64;
#else
#if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wlong-long"
#if defined(__clang__)
#pragma GCC diagnostic ignored "-Wc++11-long-long"
#endif
#endif
typedef signed long long drwav_int64;
typedef unsigned long long drwav_uint64;
#if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))
#pragma GCC diagnostic pop
#endif
#endif
#if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__)) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__)
typedef drwav_uint64 drwav_uintptr;
#else
typedef drwav_uint32 drwav_uintptr;
#endif
typedef drwav_uint8 drwav_bool8;
typedef drwav_uint32 drwav_bool32;
#define DRWAV_TRUE 1
#define DRWAV_FALSE 0
#if !defined(DRWAV_API)
#if defined(DRWAV_DLL)
#if defined(_WIN32)
#define DRWAV_DLL_IMPORT __declspec(dllimport)
#define DRWAV_DLL_EXPORT __declspec(dllexport)
#define DRWAV_DLL_PRIVATE static
#else
#if defined(__GNUC__) && __GNUC__ >= 4
#define DRWAV_DLL_IMPORT __attribute__((visibility("default")))
#define DRWAV_DLL_EXPORT __attribute__((visibility("default")))
#define DRWAV_DLL_PRIVATE __attribute__((visibility("hidden")))
#else
#define DRWAV_DLL_IMPORT
#define DRWAV_DLL_EXPORT
#define DRWAV_DLL_PRIVATE static
#endif
#endif
#if defined(DR_WAV_IMPLEMENTATION) || defined(DRWAV_IMPLEMENTATION)
#define DRWAV_API DRWAV_DLL_EXPORT
#else
#define DRWAV_API DRWAV_DLL_IMPORT
#endif
#define DRWAV_PRIVATE DRWAV_DLL_PRIVATE
#else
#define DRWAV_API extern
#define DRWAV_PRIVATE static
#endif
#endif
typedef drwav_int32 drwav_result;
#define DRWAV_SUCCESS 0
#define DRWAV_ERROR -1 /* A generic error. */
#define DRWAV_INVALID_ARGS -2
#define DRWAV_INVALID_OPERATION -3
#define DRWAV_OUT_OF_MEMORY -4
#define DRWAV_OUT_OF_RANGE -5
#define DRWAV_ACCESS_DENIED -6
#define DRWAV_DOES_NOT_EXIST -7
#define DRWAV_ALREADY_EXISTS -8
#define DRWAV_TOO_MANY_OPEN_FILES -9
#define DRWAV_INVALID_FILE -10
#define DRWAV_TOO_BIG -11
#define DRWAV_PATH_TOO_LONG -12
#define DRWAV_NAME_TOO_LONG -13
#define DRWAV_NOT_DIRECTORY -14
#define DRWAV_IS_DIRECTORY -15
#define DRWAV_DIRECTORY_NOT_EMPTY -16
#define DRWAV_END_OF_FILE -17
#define DRWAV_NO_SPACE -18
#define DRWAV_BUSY -19
#define DRWAV_IO_ERROR -20
#define DRWAV_INTERRUPT -21
#define DRWAV_UNAVAILABLE -22
#define DRWAV_ALREADY_IN_USE -23
#define DRWAV_BAD_ADDRESS -24
#define DRWAV_BAD_SEEK -25
#define DRWAV_BAD_PIPE -26
#define DRWAV_DEADLOCK -27
#define DRWAV_TOO_MANY_LINKS -28
#define DRWAV_NOT_IMPLEMENTED -29
#define DRWAV_NO_MESSAGE -30
#define DRWAV_BAD_MESSAGE -31
#define DRWAV_NO_DATA_AVAILABLE -32
#define DRWAV_INVALID_DATA -33
#define DRWAV_TIMEOUT -34
#define DRWAV_NO_NETWORK -35
#define DRWAV_NOT_UNIQUE -36
#define DRWAV_NOT_SOCKET -37
#define DRWAV_NO_ADDRESS -38
#define DRWAV_BAD_PROTOCOL -39
#define DRWAV_PROTOCOL_UNAVAILABLE -40
#define DRWAV_PROTOCOL_NOT_SUPPORTED -41
#define DRWAV_PROTOCOL_FAMILY_NOT_SUPPORTED -42
#define DRWAV_ADDRESS_FAMILY_NOT_SUPPORTED -43
#define DRWAV_SOCKET_NOT_SUPPORTED -44
#define DRWAV_CONNECTION_RESET -45
#define DRWAV_ALREADY_CONNECTED -46
#define DRWAV_NOT_CONNECTED -47
#define DRWAV_CONNECTION_REFUSED -48
#define DRWAV_NO_HOST -49
#define DRWAV_IN_PROGRESS -50
#define DRWAV_CANCELLED -51
#define DRWAV_MEMORY_ALREADY_MAPPED -52
#define DRWAV_AT_END -53
/* Common data formats. */
#define DR_WAVE_FORMAT_PCM 0x1
#define DR_WAVE_FORMAT_ADPCM 0x2
#define DR_WAVE_FORMAT_IEEE_FLOAT 0x3
#define DR_WAVE_FORMAT_ALAW 0x6
#define DR_WAVE_FORMAT_MULAW 0x7
#define DR_WAVE_FORMAT_DVI_ADPCM 0x11
#define DR_WAVE_FORMAT_EXTENSIBLE 0xFFFE
/* Constants. */
#ifndef DRWAV_MAX_SMPL_LOOPS
#define DRWAV_MAX_SMPL_LOOPS 1
#endif
/* Flags to pass into drwav_init_ex(), etc. */
#define DRWAV_SEQUENTIAL 0x00000001
DRWAV_API void drwav_version(drwav_uint32* pMajor, drwav_uint32* pMinor, drwav_uint32* pRevision);
DRWAV_API const char* drwav_version_string(void);
typedef enum
{
drwav_seek_origin_start,
drwav_seek_origin_current
} drwav_seek_origin;
typedef enum
{
drwav_container_riff,
drwav_container_w64,
drwav_container_rf64
} drwav_container;
typedef struct
{
union
{
drwav_uint8 fourcc[4];
drwav_uint8 guid[16];
} id;
/* The size in bytes of the chunk. */
drwav_uint64 sizeInBytes;
/*
RIFF = 2 byte alignment.
W64 = 8 byte alignment.
*/
unsigned int paddingSize;
} drwav_chunk_header;
typedef struct
{
/*
The format tag exactly as specified in the wave file's "fmt" chunk. This can be used by applications
that require support for data formats not natively supported by dr_wav.
*/
drwav_uint16 formatTag;
/* The number of channels making up the audio data. When this is set to 1 it is mono, 2 is stereo, etc. */
drwav_uint16 channels;
/* The sample rate. Usually set to something like 44100. */
drwav_uint32 sampleRate;
/* Average bytes per second. You probably don't need this, but it's left here for informational purposes. */
drwav_uint32 avgBytesPerSec;
/* Block align. This is equal to the number of channels * bytes per sample. */
drwav_uint16 blockAlign;
/* Bits per sample. */
drwav_uint16 bitsPerSample;
/* The size of the extended data. Only used internally for validation, but left here for informational purposes. */
drwav_uint16 extendedSize;
/*
The number of valid bits per sample. When <formatTag> is equal to WAVE_FORMAT_EXTENSIBLE, <bitsPerSample>
is always rounded up to the nearest multiple of 8. This variable contains information about exactly how
many bits are valid per sample. Mainly used for informational purposes.
*/
drwav_uint16 validBitsPerSample;
/* The channel mask. Not used at the moment. */
drwav_uint32 channelMask;
/* The sub-format, exactly as specified by the wave file. */
drwav_uint8 subFormat[16];
} drwav_fmt;
DRWAV_API drwav_uint16 drwav_fmt_get_format(const drwav_fmt* pFMT);
/*
Callback for when data is read. Return value is the number of bytes actually read.
pUserData [in] The user data that was passed to drwav_init() and family.
pBufferOut [out] The output buffer.
bytesToRead [in] The number of bytes to read.
Returns the number of bytes actually read.
A return value of less than bytesToRead indicates the end of the stream. Do _not_ return from this callback until
either the entire bytesToRead is filled or you have reached the end of the stream.
*/
typedef size_t (* drwav_read_proc)(void* pUserData, void* pBufferOut, size_t bytesToRead);
/*
Callback for when data is written. Returns value is the number of bytes actually written.
pUserData [in] The user data that was passed to drwav_init_write() and family.
pData [out] A pointer to the data to write.
bytesToWrite [in] The number of bytes to write.
Returns the number of bytes actually written.
If the return value differs from bytesToWrite, it indicates an error.
*/
typedef size_t (* drwav_write_proc)(void* pUserData, const void* pData, size_t bytesToWrite);
/*
Callback for when data needs to be seeked.
pUserData [in] The user data that was passed to drwav_init() and family.
offset [in] The number of bytes to move, relative to the origin. Will never be negative.
origin [in] The origin of the seek - the current position or the start of the stream.
Returns whether or not the seek was successful.
Whether or not it is relative to the beginning or current position is determined by the "origin" parameter which will be either drwav_seek_origin_start or
drwav_seek_origin_current.
*/
typedef drwav_bool32 (* drwav_seek_proc)(void* pUserData, int offset, drwav_seek_origin origin);
/*
Callback for when drwav_init_ex() finds a chunk.
pChunkUserData [in] The user data that was passed to the pChunkUserData parameter of drwav_init_ex() and family.
onRead [in] A pointer to the function to call when reading.
onSeek [in] A pointer to the function to call when seeking.
pReadSeekUserData [in] The user data that was passed to the pReadSeekUserData parameter of drwav_init_ex() and family.
pChunkHeader [in] A pointer to an object containing basic header information about the chunk. Use this to identify the chunk.
container [in] Whether or not the WAV file is a RIFF or Wave64 container. If you're unsure of the difference, assume RIFF.
pFMT [in] A pointer to the object containing the contents of the "fmt" chunk.
Returns the number of bytes read + seeked.
To read data from the chunk, call onRead(), passing in pReadSeekUserData as the first parameter. Do the same for seeking with onSeek(). The return value must
be the total number of bytes you have read _plus_ seeked.
Use the `container` argument to discriminate the fields in `pChunkHeader->id`. If the container is `drwav_container_riff` or `drwav_container_rf64` you should
use `id.fourcc`, otherwise you should use `id.guid`.
The `pFMT` parameter can be used to determine the data format of the wave file. Use `drwav_fmt_get_format()` to get the sample format, which will be one of the
`DR_WAVE_FORMAT_*` identifiers.
The read pointer will be sitting on the first byte after the chunk's header. You must not attempt to read beyond the boundary of the chunk.
*/
typedef drwav_uint64 (* drwav_chunk_proc)(void* pChunkUserData, drwav_read_proc onRead, drwav_seek_proc onSeek, void* pReadSeekUserData, const drwav_chunk_header* pChunkHeader, drwav_container container, const drwav_fmt* pFMT);
typedef struct
{
void* pUserData;
void* (* onMalloc)(size_t sz, void* pUserData);
void* (* onRealloc)(void* p, size_t sz, void* pUserData);
void (* onFree)(void* p, void* pUserData);
} drwav_allocation_callbacks;
/* Structure for internal use. Only used for loaders opened with drwav_init_memory(). */
typedef struct
{
const drwav_uint8* data;
size_t dataSize;
size_t currentReadPos;
} drwav__memory_stream;
/* Structure for internal use. Only used for writers opened with drwav_init_memory_write(). */
typedef struct
{
void** ppData;
size_t* pDataSize;
size_t dataSize;
size_t dataCapacity;
size_t currentWritePos;
} drwav__memory_stream_write;
typedef struct
{
drwav_container container; /* RIFF, W64. */
drwav_uint32 format; /* DR_WAVE_FORMAT_* */
drwav_uint32 channels;
drwav_uint32 sampleRate;
drwav_uint32 bitsPerSample;
} drwav_data_format;
/* See the following for details on the 'smpl' chunk: https://sites.google.com/site/musicgapi/technical-documents/wav-file-format#smpl */
typedef struct
{
drwav_uint32 cuePointId;
drwav_uint32 type;
drwav_uint32 start;
drwav_uint32 end;
drwav_uint32 fraction;
drwav_uint32 playCount;
} drwav_smpl_loop;
typedef struct
{
drwav_uint32 manufacturer;
drwav_uint32 product;
drwav_uint32 samplePeriod;
drwav_uint32 midiUnityNotes;
drwav_uint32 midiPitchFraction;
drwav_uint32 smpteFormat;
drwav_uint32 smpteOffset;
drwav_uint32 numSampleLoops;
drwav_uint32 samplerData;
drwav_smpl_loop loops[DRWAV_MAX_SMPL_LOOPS];
} drwav_smpl;
typedef struct
{
/* A pointer to the function to call when more data is needed. */
drwav_read_proc onRead;
/* A pointer to the function to call when data needs to be written. Only used when the drwav object is opened in write mode. */
drwav_write_proc onWrite;
/* A pointer to the function to call when the wav file needs to be seeked. */
drwav_seek_proc onSeek;
/* The user data to pass to callbacks. */
void* pUserData;
/* Allocation callbacks. */
drwav_allocation_callbacks allocationCallbacks;
/* Whether or not the WAV file is formatted as a standard RIFF file or W64. */
drwav_container container;
/* Structure containing format information exactly as specified by the wav file. */
drwav_fmt fmt;
/* The sample rate. Will be set to something like 44100. */
drwav_uint32 sampleRate;
/* The number of channels. This will be set to 1 for monaural streams, 2 for stereo, etc. */
drwav_uint16 channels;
/* The bits per sample. Will be set to something like 16, 24, etc. */
drwav_uint16 bitsPerSample;
/* Equal to fmt.formatTag, or the value specified by fmt.subFormat if fmt.formatTag is equal to 65534 (WAVE_FORMAT_EXTENSIBLE). */
drwav_uint16 translatedFormatTag;
/* The total number of PCM frames making up the audio data. */
drwav_uint64 totalPCMFrameCount;
/* The size in bytes of the data chunk. */
drwav_uint64 dataChunkDataSize;
/* The position in the stream of the first byte of the data chunk. This is used for seeking. */
drwav_uint64 dataChunkDataPos;
/* The number of bytes remaining in the data chunk. */
drwav_uint64 bytesRemaining;
/*
Only used in sequential write mode. Keeps track of the desired size of the "data" chunk at the point of initialization time. Always
set to 0 for non-sequential writes and when the drwav object is opened in read mode. Used for validation.
*/
drwav_uint64 dataChunkDataSizeTargetWrite;
/* Keeps track of whether or not the wav writer was initialized in sequential mode. */
drwav_bool32 isSequentialWrite;
/* smpl chunk. */
drwav_smpl smpl;
/* A hack to avoid a DRWAV_MALLOC() when opening a decoder with drwav_init_memory(). */
drwav__memory_stream memoryStream;
drwav__memory_stream_write memoryStreamWrite;
/* Generic data for compressed formats. This data is shared across all block-compressed formats. */
struct
{
drwav_uint64 iCurrentPCMFrame; /* The index of the next PCM frame that will be read by drwav_read_*(). This is used with "totalPCMFrameCount" to ensure we don't read excess samples at the end of the last block. */
} compressed;
/* Microsoft ADPCM specific data. */
struct
{
drwav_uint32 bytesRemainingInBlock;
drwav_uint16 predictor[2];
drwav_int32 delta[2];
drwav_int32 cachedFrames[4]; /* Samples are stored in this cache during decoding. */
drwav_uint32 cachedFrameCount;
drwav_int32 prevFrames[2][2]; /* The previous 2 samples for each channel (2 channels at most). */
} msadpcm;
/* IMA ADPCM specific data. */
struct
{
drwav_uint32 bytesRemainingInBlock;
drwav_int32 predictor[2];
drwav_int32 stepIndex[2];
drwav_int32 cachedFrames[16]; /* Samples are stored in this cache during decoding. */
drwav_uint32 cachedFrameCount;
} ima;
} drwav;
/*
Initializes a pre-allocated drwav object for reading.
pWav [out] A pointer to the drwav object being initialized.
onRead [in] The function to call when data needs to be read from the client.
onSeek [in] The function to call when the read position of the client data needs to move.
onChunk [in, optional] The function to call when a chunk is enumerated at initialized time.
pUserData, pReadSeekUserData [in, optional] A pointer to application defined data that will be passed to onRead and onSeek.
pChunkUserData [in, optional] A pointer to application defined data that will be passed to onChunk.
flags [in, optional] A set of flags for controlling how things are loaded.
Returns true if successful; false otherwise.
Close the loader with drwav_uninit().
This is the lowest level function for initializing a WAV file. You can also use drwav_init_file() and drwav_init_memory()
to open the stream from a file or from a block of memory respectively.
Possible values for flags:
DRWAV_SEQUENTIAL: Never perform a backwards seek while loading. This disables the chunk callback and will cause this function
to return as soon as the data chunk is found. Any chunks after the data chunk will be ignored.
drwav_init() is equivalent to "drwav_init_ex(pWav, onRead, onSeek, NULL, pUserData, NULL, 0);".
The onChunk callback is not called for the WAVE or FMT chunks. The contents of the FMT chunk can be read from pWav->fmt
after the function returns.
See also: drwav_init_file(), drwav_init_memory(), drwav_uninit()
*/
DRWAV_API drwav_bool32 drwav_init(drwav* pWav, drwav_read_proc onRead, drwav_seek_proc onSeek, void* pUserData, const drwav_allocation_callbacks* pAllocationCallbacks);
DRWAV_API drwav_bool32 drwav_init_ex(drwav* pWav, drwav_read_proc onRead, drwav_seek_proc onSeek, drwav_chunk_proc onChunk, void* pReadSeekUserData, void* pChunkUserData, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks);
/*
Initializes a pre-allocated drwav object for writing.
onWrite [in] The function to call when data needs to be written.
onSeek [in] The function to call when the write position needs to move.
pUserData [in, optional] A pointer to application defined data that will be passed to onWrite and onSeek.
Returns true if successful; false otherwise.
Close the writer with drwav_uninit().
This is the lowest level function for initializing a WAV file. You can also use drwav_init_file_write() and drwav_init_memory_write()
to open the stream from a file or from a block of memory respectively.
If the total sample count is known, you can use drwav_init_write_sequential(). This avoids the need for dr_wav to perform
a post-processing step for storing the total sample count and the size of the data chunk which requires a backwards seek.
See also: drwav_init_file_write(), drwav_init_memory_write(), drwav_uninit()
*/
DRWAV_API drwav_bool32 drwav_init_write(drwav* pWav, const drwav_data_format* pFormat, drwav_write_proc onWrite, drwav_seek_proc onSeek, void* pUserData, const drwav_allocation_callbacks* pAllocationCallbacks);
DRWAV_API drwav_bool32 drwav_init_write_sequential(drwav* pWav, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount, drwav_write_proc onWrite, void* pUserData, const drwav_allocation_callbacks* pAllocationCallbacks);
DRWAV_API drwav_bool32 drwav_init_write_sequential_pcm_frames(drwav* pWav, const drwav_data_format* pFormat, drwav_uint64 totalPCMFrameCount, drwav_write_proc onWrite, void* pUserData, const drwav_allocation_callbacks* pAllocationCallbacks);
/*
Utility function to determine the target size of the entire data to be written (including all headers and chunks).
Returns the target size in bytes.
Useful if the application needs to know the size to allocate.
Only writing to the RIFF chunk and one data chunk is currently supported.
See also: drwav_init_write(), drwav_init_file_write(), drwav_init_memory_write()
*/
DRWAV_API drwav_uint64 drwav_target_write_size_bytes(const drwav_data_format* pFormat, drwav_uint64 totalSampleCount);
/*
Uninitializes the given drwav object.
Use this only for objects initialized with drwav_init*() functions (drwav_init(), drwav_init_ex(), drwav_init_write(), drwav_init_write_sequential()).
*/
DRWAV_API drwav_result drwav_uninit(drwav* pWav);
/*
Reads raw audio data.
This is the lowest level function for reading audio data. It simply reads the given number of
bytes of the raw internal sample data.
Consider using drwav_read_pcm_frames_s16(), drwav_read_pcm_frames_s32() or drwav_read_pcm_frames_f32() for
reading sample data in a consistent format.
pBufferOut can be NULL in which case a seek will be performed.
Returns the number of bytes actually read.
*/
DRWAV_API size_t drwav_read_raw(drwav* pWav, size_t bytesToRead, void* pBufferOut);
/*
Reads up to the specified number of PCM frames from the WAV file.
The output data will be in the file's internal format, converted to native-endian byte order. Use
drwav_read_pcm_frames_s16/f32/s32() to read data in a specific format.
If the return value is less than <framesToRead> it means the end of the file has been reached or
you have requested more PCM frames than can possibly fit in the output buffer.
This function will only work when sample data is of a fixed size and uncompressed. If you are
using a compressed format consider using drwav_read_raw() or drwav_read_pcm_frames_s16/s32/f32().
pBufferOut can be NULL in which case a seek will be performed.
*/
DRWAV_API drwav_uint64 drwav_read_pcm_frames(drwav* pWav, drwav_uint64 framesToRead, void* pBufferOut);
DRWAV_API drwav_uint64 drwav_read_pcm_frames_le(drwav* pWav, drwav_uint64 framesToRead, void* pBufferOut);
DRWAV_API drwav_uint64 drwav_read_pcm_frames_be(drwav* pWav, drwav_uint64 framesToRead, void* pBufferOut);
/*
Seeks to the given PCM frame.
Returns true if successful; false otherwise.
*/
DRWAV_API drwav_bool32 drwav_seek_to_pcm_frame(drwav* pWav, drwav_uint64 targetFrameIndex);
/*
Writes raw audio data.
Returns the number of bytes actually written. If this differs from bytesToWrite, it indicates an error.
*/
DRWAV_API size_t drwav_write_raw(drwav* pWav, size_t bytesToWrite, const void* pData);
/*
Writes PCM frames.
Returns the number of PCM frames written.
Input samples need to be in native-endian byte order. On big-endian architectures the input data will be converted to
little-endian. Use drwav_write_raw() to write raw audio data without performing any conversion.
*/
DRWAV_API drwav_uint64 drwav_write_pcm_frames(drwav* pWav, drwav_uint64 framesToWrite, const void* pData);
DRWAV_API drwav_uint64 drwav_write_pcm_frames_le(drwav* pWav, drwav_uint64 framesToWrite, const void* pData);
DRWAV_API drwav_uint64 drwav_write_pcm_frames_be(drwav* pWav, drwav_uint64 framesToWrite, const void* pData);
/* Conversion Utilities */
#ifndef DR_WAV_NO_CONVERSION_API
/*
Reads a chunk of audio data and converts it to signed 16-bit PCM samples.
pBufferOut can be NULL in which case a seek will be performed.
Returns the number of PCM frames actually read.
If the return value is less than <framesToRead> it means the end of the file has been reached.
*/
DRWAV_API drwav_uint64 drwav_read_pcm_frames_s16(drwav* pWav, drwav_uint64 framesToRead, drwav_int16* pBufferOut);
DRWAV_API drwav_uint64 drwav_read_pcm_frames_s16le(drwav* pWav, drwav_uint64 framesToRead, drwav_int16* pBufferOut);
DRWAV_API drwav_uint64 drwav_read_pcm_frames_s16be(drwav* pWav, drwav_uint64 framesToRead, drwav_int16* pBufferOut);
/* Low-level function for converting unsigned 8-bit PCM samples to signed 16-bit PCM samples. */
DRWAV_API void drwav_u8_to_s16(drwav_int16* pOut, const drwav_uint8* pIn, size_t sampleCount);
/* Low-level function for converting signed 24-bit PCM samples to signed 16-bit PCM samples. */
DRWAV_API void drwav_s24_to_s16(drwav_int16* pOut, const drwav_uint8* pIn, size_t sampleCount);
/* Low-level function for converting signed 32-bit PCM samples to signed 16-bit PCM samples. */
DRWAV_API void drwav_s32_to_s16(drwav_int16* pOut, const drwav_int32* pIn, size_t sampleCount);
/* Low-level function for converting IEEE 32-bit floating point samples to signed 16-bit PCM samples. */
DRWAV_API void drwav_f32_to_s16(drwav_int16* pOut, const float* pIn, size_t sampleCount);
/* Low-level function for converting IEEE 64-bit floating point samples to signed 16-bit PCM samples. */
DRWAV_API void drwav_f64_to_s16(drwav_int16* pOut, const double* pIn, size_t sampleCount);
/* Low-level function for converting A-law samples to signed 16-bit PCM samples. */
DRWAV_API void drwav_alaw_to_s16(drwav_int16* pOut, const drwav_uint8* pIn, size_t sampleCount);
/* Low-level function for converting u-law samples to signed 16-bit PCM samples. */
DRWAV_API void drwav_mulaw_to_s16(drwav_int16* pOut, const drwav_uint8* pIn, size_t sampleCount);
/*
Reads a chunk of audio data and converts it to IEEE 32-bit floating point samples.
pBufferOut can be NULL in which case a seek will be performed.
Returns the number of PCM frames actually read.
If the return value is less than <framesToRead> it means the end of the file has been reached.
*/
DRWAV_API drwav_uint64 drwav_read_pcm_frames_f32(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut);
DRWAV_API drwav_uint64 drwav_read_pcm_frames_f32le(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut);
DRWAV_API drwav_uint64 drwav_read_pcm_frames_f32be(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut);
/* Low-level function for converting unsigned 8-bit PCM samples to IEEE 32-bit floating point samples. */
DRWAV_API void drwav_u8_to_f32(float* pOut, const drwav_uint8* pIn, size_t sampleCount);
/* Low-level function for converting signed 16-bit PCM samples to IEEE 32-bit floating point samples. */
DRWAV_API void drwav_s16_to_f32(float* pOut, const drwav_int16* pIn, size_t sampleCount);
/* Low-level function for converting signed 24-bit PCM samples to IEEE 32-bit floating point samples. */
DRWAV_API void drwav_s24_to_f32(float* pOut, const drwav_uint8* pIn, size_t sampleCount);
/* Low-level function for converting signed 32-bit PCM samples to IEEE 32-bit floating point samples. */
DRWAV_API void drwav_s32_to_f32(float* pOut, const drwav_int32* pIn, size_t sampleCount);
/* Low-level function for converting IEEE 64-bit floating point samples to IEEE 32-bit floating point samples. */
DRWAV_API void drwav_f64_to_f32(float* pOut, const double* pIn, size_t sampleCount);
/* Low-level function for converting A-law samples to IEEE 32-bit floating point samples. */
DRWAV_API void drwav_alaw_to_f32(float* pOut, const drwav_uint8* pIn, size_t sampleCount);
/* Low-level function for converting u-law samples to IEEE 32-bit floating point samples. */
DRWAV_API void drwav_mulaw_to_f32(float* pOut, const drwav_uint8* pIn, size_t sampleCount);
/*
Reads a chunk of audio data and converts it to signed 32-bit PCM samples.
pBufferOut can be NULL in which case a seek will be performed.
Returns the number of PCM frames actually read.
If the return value is less than <framesToRead> it means the end of the file has been reached.
*/
DRWAV_API drwav_uint64 drwav_read_pcm_frames_s32(drwav* pWav, drwav_uint64 framesToRead, drwav_int32* pBufferOut);
DRWAV_API drwav_uint64 drwav_read_pcm_frames_s32le(drwav* pWav, drwav_uint64 framesToRead, drwav_int32* pBufferOut);
DRWAV_API drwav_uint64 drwav_read_pcm_frames_s32be(drwav* pWav, drwav_uint64 framesToRead, drwav_int32* pBufferOut);
/* Low-level function for converting unsigned 8-bit PCM samples to signed 32-bit PCM samples. */
DRWAV_API void drwav_u8_to_s32(drwav_int32* pOut, const drwav_uint8* pIn, size_t sampleCount);
/* Low-level function for converting signed 16-bit PCM samples to signed 32-bit PCM samples. */
DRWAV_API void drwav_s16_to_s32(drwav_int32* pOut, const drwav_int16* pIn, size_t sampleCount);
/* Low-level function for converting signed 24-bit PCM samples to signed 32-bit PCM samples. */
DRWAV_API void drwav_s24_to_s32(drwav_int32* pOut, const drwav_uint8* pIn, size_t sampleCount);
/* Low-level function for converting IEEE 32-bit floating point samples to signed 32-bit PCM samples. */
DRWAV_API void drwav_f32_to_s32(drwav_int32* pOut, const float* pIn, size_t sampleCount);
/* Low-level function for converting IEEE 64-bit floating point samples to signed 32-bit PCM samples. */
DRWAV_API void drwav_f64_to_s32(drwav_int32* pOut, const double* pIn, size_t sampleCount);
/* Low-level function for converting A-law samples to signed 32-bit PCM samples. */
DRWAV_API void drwav_alaw_to_s32(drwav_int32* pOut, const drwav_uint8* pIn, size_t sampleCount);
/* Low-level function for converting u-law samples to signed 32-bit PCM samples. */
DRWAV_API void drwav_mulaw_to_s32(drwav_int32* pOut, const drwav_uint8* pIn, size_t sampleCount);
#endif /* DR_WAV_NO_CONVERSION_API */
/* High-Level Convenience Helpers */
#ifndef DR_WAV_NO_STDIO
/*
Helper for initializing a wave file for reading using stdio.
This holds the internal FILE object until drwav_uninit() is called. Keep this in mind if you're caching drwav
objects because the operating system may restrict the number of file handles an application can have open at
any given time.
*/
DRWAV_API drwav_bool32 drwav_init_file(drwav* pWav, const char* filename, const drwav_allocation_callbacks* pAllocationCallbacks);
DRWAV_API drwav_bool32 drwav_init_file_ex(drwav* pWav, const char* filename, drwav_chunk_proc onChunk, void* pChunkUserData, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks);
DRWAV_API drwav_bool32 drwav_init_file_w(drwav* pWav, const wchar_t* filename, const drwav_allocation_callbacks* pAllocationCallbacks);
DRWAV_API drwav_bool32 drwav_init_file_ex_w(drwav* pWav, const wchar_t* filename, drwav_chunk_proc onChunk, void* pChunkUserData, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks);
/*
Helper for initializing a wave file for writing using stdio.
This holds the internal FILE object until drwav_uninit() is called. Keep this in mind if you're caching drwav
objects because the operating system may restrict the number of file handles an application can have open at
any given time.
*/
DRWAV_API drwav_bool32 drwav_init_file_write(drwav* pWav, const char* filename, const drwav_data_format* pFormat, const drwav_allocation_callbacks* pAllocationCallbacks);
DRWAV_API drwav_bool32 drwav_init_file_write_sequential(drwav* pWav, const char* filename, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount, const drwav_allocation_callbacks* pAllocationCallbacks);
DRWAV_API drwav_bool32 drwav_init_file_write_sequential_pcm_frames(drwav* pWav, const char* filename, const drwav_data_format* pFormat, drwav_uint64 totalPCMFrameCount, const drwav_allocation_callbacks* pAllocationCallbacks);
DRWAV_API drwav_bool32 drwav_init_file_write_w(drwav* pWav, const wchar_t* filename, const drwav_data_format* pFormat, const drwav_allocation_callbacks* pAllocationCallbacks);
DRWAV_API drwav_bool32 drwav_init_file_write_sequential_w(drwav* pWav, const wchar_t* filename, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount, const drwav_allocation_callbacks* pAllocationCallbacks);
DRWAV_API drwav_bool32 drwav_init_file_write_sequential_pcm_frames_w(drwav* pWav, const wchar_t* filename, const drwav_data_format* pFormat, drwav_uint64 totalPCMFrameCount, const drwav_allocation_callbacks* pAllocationCallbacks);
#endif /* DR_WAV_NO_STDIO */
/*
Helper for initializing a loader from a pre-allocated memory buffer.
This does not create a copy of the data. It is up to the application to ensure the buffer remains valid for
the lifetime of the drwav object.
The buffer should contain the contents of the entire wave file, not just the sample data.
*/
DRWAV_API drwav_bool32 drwav_init_memory(drwav* pWav, const void* data, size_t dataSize, const drwav_allocation_callbacks* pAllocationCallbacks);
DRWAV_API drwav_bool32 drwav_init_memory_ex(drwav* pWav, const void* data, size_t dataSize, drwav_chunk_proc onChunk, void* pChunkUserData, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks);
/*
Helper for initializing a writer which outputs data to a memory buffer.
dr_wav will manage the memory allocations, however it is up to the caller to free the data with drwav_free().
The buffer will remain allocated even after drwav_uninit() is called. The buffer should not be considered valid
until after drwav_uninit() has been called.
*/
DRWAV_API drwav_bool32 drwav_init_memory_write(drwav* pWav, void** ppData, size_t* pDataSize, const drwav_data_format* pFormat, const drwav_allocation_callbacks* pAllocationCallbacks);
DRWAV_API drwav_bool32 drwav_init_memory_write_sequential(drwav* pWav, void** ppData, size_t* pDataSize, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount, const drwav_allocation_callbacks* pAllocationCallbacks);
DRWAV_API drwav_bool32 drwav_init_memory_write_sequential_pcm_frames(drwav* pWav, void** ppData, size_t* pDataSize, const drwav_data_format* pFormat, drwav_uint64 totalPCMFrameCount, const drwav_allocation_callbacks* pAllocationCallbacks);
#ifndef DR_WAV_NO_CONVERSION_API
/*
Opens and reads an entire wav file in a single operation.
The return value is a heap-allocated buffer containing the audio data. Use drwav_free() to free the buffer.
*/
DRWAV_API drwav_int16* drwav_open_and_read_pcm_frames_s16(drwav_read_proc onRead, drwav_seek_proc onSeek, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks);
DRWAV_API float* drwav_open_and_read_pcm_frames_f32(drwav_read_proc onRead, drwav_seek_proc onSeek, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks);
DRWAV_API drwav_int32* drwav_open_and_read_pcm_frames_s32(drwav_read_proc onRead, drwav_seek_proc onSeek, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks);
#ifndef DR_WAV_NO_STDIO
/*
Opens and decodes an entire wav file in a single operation.
The return value is a heap-allocated buffer containing the audio data. Use drwav_free() to free the buffer.
*/
DRWAV_API drwav_int16* drwav_open_file_and_read_pcm_frames_s16(const char* filename, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks);
DRWAV_API float* drwav_open_file_and_read_pcm_frames_f32(const char* filename, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks);
DRWAV_API drwav_int32* drwav_open_file_and_read_pcm_frames_s32(const char* filename, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks);
DRWAV_API drwav_int16* drwav_open_file_and_read_pcm_frames_s16_w(const wchar_t* filename, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks);
DRWAV_API float* drwav_open_file_and_read_pcm_frames_f32_w(const wchar_t* filename, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks);
DRWAV_API drwav_int32* drwav_open_file_and_read_pcm_frames_s32_w(const wchar_t* filename, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks);
#endif
/*
Opens and decodes an entire wav file from a block of memory in a single operation.
The return value is a heap-allocated buffer containing the audio data. Use drwav_free() to free the buffer.
*/
DRWAV_API drwav_int16* drwav_open_memory_and_read_pcm_frames_s16(const void* data, size_t dataSize, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks);
DRWAV_API float* drwav_open_memory_and_read_pcm_frames_f32(const void* data, size_t dataSize, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks);
DRWAV_API drwav_int32* drwav_open_memory_and_read_pcm_frames_s32(const void* data, size_t dataSize, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks);
#endif
/* Frees data that was allocated internally by dr_wav. */
DRWAV_API void drwav_free(void* p, const drwav_allocation_callbacks* pAllocationCallbacks);
/* Converts bytes from a wav stream to a sized type of native endian. */
DRWAV_API drwav_uint16 drwav_bytes_to_u16(const drwav_uint8* data);
DRWAV_API drwav_int16 drwav_bytes_to_s16(const drwav_uint8* data);
DRWAV_API drwav_uint32 drwav_bytes_to_u32(const drwav_uint8* data);
DRWAV_API drwav_int32 drwav_bytes_to_s32(const drwav_uint8* data);
DRWAV_API drwav_uint64 drwav_bytes_to_u64(const drwav_uint8* data);
DRWAV_API drwav_int64 drwav_bytes_to_s64(const drwav_uint8* data);
/* Compares a GUID for the purpose of checking the type of a Wave64 chunk. */
DRWAV_API drwav_bool32 drwav_guid_equal(const drwav_uint8 a[16], const drwav_uint8 b[16]);
/* Compares a four-character-code for the purpose of checking the type of a RIFF chunk. */
DRWAV_API drwav_bool32 drwav_fourcc_equal(const drwav_uint8* a, const char* b);
#ifdef __cplusplus
}
#endif
#endif /* dr_wav_h */
/************************************************************************************************************************************************************
************************************************************************************************************************************************************
IMPLEMENTATION
************************************************************************************************************************************************************
************************************************************************************************************************************************************/
#if defined(DR_WAV_IMPLEMENTATION) || defined(DRWAV_IMPLEMENTATION)
#ifndef dr_wav_c
#define dr_wav_c
#include <stdlib.h>
#include <string.h> /* For memcpy(), memset() */
#include <limits.h> /* For INT_MAX */
#ifndef DR_WAV_NO_STDIO
#include <stdio.h>
#include <wchar.h>
#endif
/* Standard library stuff. */
#ifndef DRWAV_ASSERT
#include <assert.h>
#define DRWAV_ASSERT(expression) assert(expression)
#endif
#ifndef DRWAV_MALLOC
#define DRWAV_MALLOC(sz) malloc((sz))
#endif
#ifndef DRWAV_REALLOC
#define DRWAV_REALLOC(p, sz) realloc((p), (sz))
#endif
#ifndef DRWAV_FREE
#define DRWAV_FREE(p) free((p))
#endif
#ifndef DRWAV_COPY_MEMORY
#define DRWAV_COPY_MEMORY(dst, src, sz) memcpy((dst), (src), (sz))
#endif
#ifndef DRWAV_ZERO_MEMORY
#define DRWAV_ZERO_MEMORY(p, sz) memset((p), 0, (sz))
#endif
#ifndef DRWAV_ZERO_OBJECT
#define DRWAV_ZERO_OBJECT(p) DRWAV_ZERO_MEMORY((p), sizeof(*p))
#endif
#define drwav_countof(x) (sizeof(x) / sizeof(x[0]))
#define drwav_align(x, a) ((((x) + (a) - 1) / (a)) * (a))
#define drwav_min(a, b) (((a) < (b)) ? (a) : (b))
#define drwav_max(a, b) (((a) > (b)) ? (a) : (b))
#define drwav_clamp(x, lo, hi) (drwav_max((lo), drwav_min((hi), (x))))
#define DRWAV_MAX_SIMD_VECTOR_SIZE 64 /* 64 for AVX-512 in the future. */
/* CPU architecture. */