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