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