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