145#define DRWAV_STRINGIFY(x) #x
146#define DRWAV_XSTRINGIFY(x) DRWAV_STRINGIFY(x)
148#define DRWAV_VERSION_MAJOR 0
149#define DRWAV_VERSION_MINOR 13
150#define DRWAV_VERSION_REVISION 16
151#define DRWAV_VERSION_STRING DRWAV_XSTRINGIFY(DRWAV_VERSION_MAJOR) "." DRWAV_XSTRINGIFY(DRWAV_VERSION_MINOR) "." DRWAV_XSTRINGIFY(DRWAV_VERSION_REVISION)
156typedef signed char drwav_int8;
157typedef unsigned char drwav_uint8;
158typedef signed short drwav_int16;
159typedef unsigned short drwav_uint16;
160typedef signed int drwav_int32;
161typedef unsigned int drwav_uint32;
162#if defined(_MSC_VER) && !defined(__clang__)
163 typedef signed __int64 drwav_int64;
164 typedef unsigned __int64 drwav_uint64;
166 #if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))
167 #pragma GCC diagnostic push
168 #pragma GCC diagnostic ignored "-Wlong-long"
169 #if defined(__clang__)
170 #pragma GCC diagnostic ignored "-Wc++11-long-long"
173 typedef signed long long drwav_int64;
174 typedef unsigned long long drwav_uint64;
175 #if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))
176 #pragma GCC diagnostic pop
179#if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__)) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(_M_ARM64) || defined(__powerpc64__)
180 typedef drwav_uint64 drwav_uintptr;
182 typedef drwav_uint32 drwav_uintptr;
184typedef drwav_uint8 drwav_bool8;
185typedef drwav_uint32 drwav_bool32;
191#if !defined(DRWAV_API)
192 #if defined(DRWAV_DLL)
194 #define DRWAV_DLL_IMPORT __declspec(dllimport)
195 #define DRWAV_DLL_EXPORT __declspec(dllexport)
196 #define DRWAV_DLL_PRIVATE static
198 #if defined(__GNUC__) && __GNUC__ >= 4
199 #define DRWAV_DLL_IMPORT __attribute__((visibility("default")))
200 #define DRWAV_DLL_EXPORT __attribute__((visibility("default")))
201 #define DRWAV_DLL_PRIVATE __attribute__((visibility("hidden")))
203 #define DRWAV_DLL_IMPORT
204 #define DRWAV_DLL_EXPORT
205 #define DRWAV_DLL_PRIVATE static
209 #if defined(DR_WAV_IMPLEMENTATION) || defined(DRWAV_IMPLEMENTATION)
210 #define DRWAV_API DRWAV_DLL_EXPORT
212 #define DRWAV_API DRWAV_DLL_IMPORT
214 #define DRWAV_PRIVATE DRWAV_DLL_PRIVATE
216 #define DRWAV_API extern
217 #define DRWAV_PRIVATE static
223typedef drwav_int32 drwav_result;
224#define DRWAV_SUCCESS 0
225#define DRWAV_ERROR -1
226#define DRWAV_INVALID_ARGS -2
227#define DRWAV_INVALID_OPERATION -3
228#define DRWAV_OUT_OF_MEMORY -4
229#define DRWAV_OUT_OF_RANGE -5
230#define DRWAV_ACCESS_DENIED -6
231#define DRWAV_DOES_NOT_EXIST -7
232#define DRWAV_ALREADY_EXISTS -8
233#define DRWAV_TOO_MANY_OPEN_FILES -9
234#define DRWAV_INVALID_FILE -10
235#define DRWAV_TOO_BIG -11
236#define DRWAV_PATH_TOO_LONG -12
237#define DRWAV_NAME_TOO_LONG -13
238#define DRWAV_NOT_DIRECTORY -14
239#define DRWAV_IS_DIRECTORY -15
240#define DRWAV_DIRECTORY_NOT_EMPTY -16
241#define DRWAV_END_OF_FILE -17
242#define DRWAV_NO_SPACE -18
243#define DRWAV_BUSY -19
244#define DRWAV_IO_ERROR -20
245#define DRWAV_INTERRUPT -21
246#define DRWAV_UNAVAILABLE -22
247#define DRWAV_ALREADY_IN_USE -23
248#define DRWAV_BAD_ADDRESS -24
249#define DRWAV_BAD_SEEK -25
250#define DRWAV_BAD_PIPE -26
251#define DRWAV_DEADLOCK -27
252#define DRWAV_TOO_MANY_LINKS -28
253#define DRWAV_NOT_IMPLEMENTED -29
254#define DRWAV_NO_MESSAGE -30
255#define DRWAV_BAD_MESSAGE -31
256#define DRWAV_NO_DATA_AVAILABLE -32
257#define DRWAV_INVALID_DATA -33
258#define DRWAV_TIMEOUT -34
259#define DRWAV_NO_NETWORK -35
260#define DRWAV_NOT_UNIQUE -36
261#define DRWAV_NOT_SOCKET -37
262#define DRWAV_NO_ADDRESS -38
263#define DRWAV_BAD_PROTOCOL -39
264#define DRWAV_PROTOCOL_UNAVAILABLE -40
265#define DRWAV_PROTOCOL_NOT_SUPPORTED -41
266#define DRWAV_PROTOCOL_FAMILY_NOT_SUPPORTED -42
267#define DRWAV_ADDRESS_FAMILY_NOT_SUPPORTED -43
268#define DRWAV_SOCKET_NOT_SUPPORTED -44
269#define DRWAV_CONNECTION_RESET -45
270#define DRWAV_ALREADY_CONNECTED -46
271#define DRWAV_NOT_CONNECTED -47
272#define DRWAV_CONNECTION_REFUSED -48
273#define DRWAV_NO_HOST -49
274#define DRWAV_IN_PROGRESS -50
275#define DRWAV_CANCELLED -51
276#define DRWAV_MEMORY_ALREADY_MAPPED -52
277#define DRWAV_AT_END -53
281#define DR_WAVE_FORMAT_PCM 0x1
282#define DR_WAVE_FORMAT_ADPCM 0x2
283#define DR_WAVE_FORMAT_IEEE_FLOAT 0x3
284#define DR_WAVE_FORMAT_ALAW 0x6
285#define DR_WAVE_FORMAT_MULAW 0x7
286#define DR_WAVE_FORMAT_DVI_ADPCM 0x11
287#define DR_WAVE_FORMAT_EXTENSIBLE 0xFFFE
290#define DRWAV_SEQUENTIAL 0x00000001
291#define DRWAV_WITH_METADATA 0x00000002
293DRWAV_API
void drwav_version(drwav_uint32* pMajor, drwav_uint32* pMinor, drwav_uint32* pRevision);
294DRWAV_API
const char* drwav_version_string(
void);
300 void* (* onMalloc)(
size_t sz,
void* pUserData);
301 void* (* onRealloc)(
void* p,
size_t sz,
void* pUserData);
302 void (* onFree)(
void* p,
void* pUserData);
308 drwav_seek_origin_start,
309 drwav_seek_origin_current
314 drwav_container_riff,
315 drwav_container_rifx,
317 drwav_container_rf64,
325 drwav_uint8 fourcc[4];
326 drwav_uint8 guid[16];
330 drwav_uint64 sizeInBytes;
336 unsigned int paddingSize;
345 drwav_uint16 formatTag;
348 drwav_uint16 channels;
351 drwav_uint32 sampleRate;
354 drwav_uint32 avgBytesPerSec;
357 drwav_uint16 blockAlign;
360 drwav_uint16 bitsPerSample;
363 drwav_uint16 extendedSize;
370 drwav_uint16 validBitsPerSample;
373 drwav_uint32 channelMask;
376 drwav_uint8 subFormat[16];
379DRWAV_API drwav_uint16 drwav_fmt_get_format(
const drwav_fmt* pFMT);
394typedef size_t (* drwav_read_proc)(
void* pUserData,
void* pBufferOut,
size_t bytesToRead);
407typedef size_t (* drwav_write_proc)(
void* pUserData,
const void* pData,
size_t bytesToWrite);
421typedef drwav_bool32 (* drwav_seek_proc)(
void* pUserData,
int offset, drwav_seek_origin origin);
447typedef drwav_uint64 (* drwav_chunk_proc)(
void* pChunkUserData, drwav_read_proc onRead, drwav_seek_proc onSeek,
void* pReadSeekUserData,
const drwav_chunk_header* pChunkHeader, drwav_container container,
const drwav_fmt* pFMT);
453 const drwav_uint8* data;
455 size_t currentReadPos;
465 size_t currentWritePos;
470 drwav_container container;
472 drwav_uint32 channels;
473 drwav_uint32 sampleRate;
474 drwav_uint32 bitsPerSample;
479 drwav_metadata_type_none = 0,
488 drwav_metadata_type_unknown = 1 << 0,
491 drwav_metadata_type_smpl = 1 << 1,
492 drwav_metadata_type_inst = 1 << 2,
493 drwav_metadata_type_cue = 1 << 3,
494 drwav_metadata_type_acid = 1 << 4,
495 drwav_metadata_type_bext = 1 << 5,
504 drwav_metadata_type_list_label = 1 << 6,
505 drwav_metadata_type_list_note = 1 << 7,
506 drwav_metadata_type_list_labelled_cue_region = 1 << 8,
508 drwav_metadata_type_list_info_software = 1 << 9,
509 drwav_metadata_type_list_info_copyright = 1 << 10,
510 drwav_metadata_type_list_info_title = 1 << 11,
511 drwav_metadata_type_list_info_artist = 1 << 12,
512 drwav_metadata_type_list_info_comment = 1 << 13,
513 drwav_metadata_type_list_info_date = 1 << 14,
514 drwav_metadata_type_list_info_genre = 1 << 15,
515 drwav_metadata_type_list_info_album = 1 << 16,
516 drwav_metadata_type_list_info_tracknumber = 1 << 17,
519 drwav_metadata_type_list_all_info_strings = drwav_metadata_type_list_info_software
520 | drwav_metadata_type_list_info_copyright
521 | drwav_metadata_type_list_info_title
522 | drwav_metadata_type_list_info_artist
523 | drwav_metadata_type_list_info_comment
524 | drwav_metadata_type_list_info_date
525 | drwav_metadata_type_list_info_genre
526 | drwav_metadata_type_list_info_album
527 | drwav_metadata_type_list_info_tracknumber,
529 drwav_metadata_type_list_all_adtl = drwav_metadata_type_list_label
530 | drwav_metadata_type_list_note
531 | drwav_metadata_type_list_labelled_cue_region,
533 drwav_metadata_type_all = -2,
534 drwav_metadata_type_all_including_unknown = -1
535} drwav_metadata_type;
545 drwav_smpl_loop_type_forward = 0,
546 drwav_smpl_loop_type_pingpong = 1,
547 drwav_smpl_loop_type_backward = 2
548} drwav_smpl_loop_type;
553 drwav_uint32 cuePointId;
559 drwav_uint32 firstSampleByteOffset;
562 drwav_uint32 lastSampleByteOffset;
565 drwav_uint32 sampleFraction;
568 drwav_uint32 playCount;
574 drwav_uint32 manufacturerId;
575 drwav_uint32 productId;
578 drwav_uint32 samplePeriodNanoseconds;
581 drwav_uint32 midiUnityNote;
584 drwav_uint32 midiPitchFraction;
587 drwav_uint32 smpteFormat;
588 drwav_uint32 smpteOffset;
591 drwav_uint32 sampleLoopCount;
594 drwav_uint32 samplerSpecificDataSizeInBytes;
597 drwav_uint8* pSamplerSpecificData;
608 drwav_int8 midiUnityNote;
609 drwav_int8 fineTuneCents;
610 drwav_int8 gainDecibels;
613 drwav_int8 lowVelocity;
614 drwav_int8 highVelocity;
629 drwav_uint32 playOrderPosition;
632 drwav_uint8 dataChunkId[4];
635 drwav_uint32 chunkStart;
638 drwav_uint32 blockStart;
641 drwav_uint32 sampleByteOffset;
646 drwav_uint32 cuePointCount;
657 drwav_acid_flag_one_shot = 1,
658 drwav_acid_flag_root_note_set = 2,
659 drwav_acid_flag_stretch = 4,
660 drwav_acid_flag_disk_based = 8,
661 drwav_acid_flag_acidizer = 16
670 drwav_uint16 midiUnityNote;
673 drwav_uint16 reserved1;
677 drwav_uint32 numBeats;
680 drwav_uint16 meterDenominator;
681 drwav_uint16 meterNumerator;
697 drwav_uint32 cuePointId;
700 drwav_uint32 stringLength;
720 char* pOriginatorName;
721 char* pOriginatorReference;
722 char pOriginationDate[10];
723 char pOriginationTime[8];
724 drwav_uint64 timeReference;
725 drwav_uint16 version;
731 char* pCodingHistory;
732 drwav_uint32 codingHistorySize;
738 drwav_uint16 loudnessValue;
739 drwav_uint16 loudnessRange;
740 drwav_uint16 maxTruePeakLevel;
741 drwav_uint16 maxMomentaryLoudness;
742 drwav_uint16 maxShortTermLoudness;
755 drwav_uint32 stringLength;
770 drwav_uint32 cuePointId;
773 drwav_uint32 sampleLength;
776 drwav_uint8 purposeId[4];
779 drwav_uint16 country;
780 drwav_uint16 language;
781 drwav_uint16 dialect;
782 drwav_uint16 codePage;
785 drwav_uint32 stringLength;
802 drwav_metadata_location_invalid,
803 drwav_metadata_location_top_level,
804 drwav_metadata_location_inside_info_list,
805 drwav_metadata_location_inside_adtl_list
806} drwav_metadata_location;
811 drwav_metadata_location chunkLocation;
812 drwav_uint32 dataSizeInBytes;
822 drwav_metadata_type type;
841 drwav_read_proc onRead;
844 drwav_write_proc onWrite;
847 drwav_seek_proc onSeek;
857 drwav_container container;
864 drwav_uint32 sampleRate;
867 drwav_uint16 channels;
870 drwav_uint16 bitsPerSample;
873 drwav_uint16 translatedFormatTag;
876 drwav_uint64 totalPCMFrameCount;
880 drwav_uint64 dataChunkDataSize;
883 drwav_uint64 dataChunkDataPos;
886 drwav_uint64 bytesRemaining;
889 drwav_uint64 readCursorInPCMFrames;
896 drwav_uint64 dataChunkDataSizeTargetWrite;
899 drwav_bool32 isSequentialWrite;
904 drwav_uint32 metadataCount;
915 drwav_uint32 bytesRemainingInBlock;
916 drwav_uint16 predictor[2];
917 drwav_int32 delta[2];
918 drwav_int32 cachedFrames[4];
919 drwav_uint32 cachedFrameCount;
920 drwav_int32 prevFrames[2][2];
926 drwav_uint32 bytesRemainingInBlock;
927 drwav_int32 predictor[2];
928 drwav_int32 stepIndex[2];
929 drwav_int32 cachedFrames[16];
930 drwav_uint32 cachedFrameCount;
937 drwav_bool8 isUnsigned;
971DRWAV_API drwav_bool32 drwav_init(
drwav* pWav, drwav_read_proc onRead, drwav_seek_proc onSeek,
void* pUserData,
const drwav_allocation_callbacks* pAllocationCallbacks);
972DRWAV_API drwav_bool32 drwav_init_ex(
drwav* pWav, drwav_read_proc onRead, drwav_seek_proc onSeek, drwav_chunk_proc onChunk,
void* pReadSeekUserData,
void* pChunkUserData, drwav_uint32 flags,
const drwav_allocation_callbacks* pAllocationCallbacks);
973DRWAV_API drwav_bool32 drwav_init_with_metadata(
drwav* pWav, drwav_read_proc onRead, drwav_seek_proc onSeek,
void* pUserData, drwav_uint32 flags,
const drwav_allocation_callbacks* pAllocationCallbacks);
997DRWAV_API drwav_bool32 drwav_init_write_sequential_pcm_frames(
drwav* pWav,
const drwav_data_format* pFormat, drwav_uint64 totalPCMFrameCount, drwav_write_proc onWrite,
void* pUserData,
const drwav_allocation_callbacks* pAllocationCallbacks);
1013DRWAV_API drwav_uint64 drwav_target_write_size_bytes(
const drwav_data_format* pFormat, drwav_uint64 totalFrameCount,
drwav_metadata* pMetadata, drwav_uint32 metadataCount);
1029DRWAV_API drwav_result drwav_uninit(
drwav* pWav);
1045DRWAV_API
size_t drwav_read_raw(
drwav* pWav,
size_t bytesToRead,
void* pBufferOut);
1061DRWAV_API drwav_uint64 drwav_read_pcm_frames(
drwav* pWav, drwav_uint64 framesToRead,
void* pBufferOut);
1062DRWAV_API drwav_uint64 drwav_read_pcm_frames_le(
drwav* pWav, drwav_uint64 framesToRead,
void* pBufferOut);
1063DRWAV_API drwav_uint64 drwav_read_pcm_frames_be(
drwav* pWav, drwav_uint64 framesToRead,
void* pBufferOut);
1070DRWAV_API drwav_bool32 drwav_seek_to_pcm_frame(
drwav* pWav, drwav_uint64 targetFrameIndex);
1075DRWAV_API drwav_result drwav_get_cursor_in_pcm_frames(
drwav* pWav, drwav_uint64* pCursor);
1080DRWAV_API drwav_result drwav_get_length_in_pcm_frames(
drwav* pWav, drwav_uint64* pLength);
1088DRWAV_API
size_t drwav_write_raw(
drwav* pWav,
size_t bytesToWrite,
const void* pData);
1098DRWAV_API drwav_uint64 drwav_write_pcm_frames(
drwav* pWav, drwav_uint64 framesToWrite,
const void* pData);
1099DRWAV_API drwav_uint64 drwav_write_pcm_frames_le(
drwav* pWav, drwav_uint64 framesToWrite,
const void* pData);
1100DRWAV_API drwav_uint64 drwav_write_pcm_frames_be(
drwav* pWav, drwav_uint64 framesToWrite,
const void* pData);
1103#ifndef DR_WAV_NO_CONVERSION_API
1114DRWAV_API drwav_uint64 drwav_read_pcm_frames_s16(
drwav* pWav, drwav_uint64 framesToRead, drwav_int16* pBufferOut);
1115DRWAV_API drwav_uint64 drwav_read_pcm_frames_s16le(
drwav* pWav, drwav_uint64 framesToRead, drwav_int16* pBufferOut);
1116DRWAV_API drwav_uint64 drwav_read_pcm_frames_s16be(
drwav* pWav, drwav_uint64 framesToRead, drwav_int16* pBufferOut);
1119DRWAV_API
void drwav_u8_to_s16(drwav_int16* pOut,
const drwav_uint8* pIn,
size_t sampleCount);
1122DRWAV_API
void drwav_s24_to_s16(drwav_int16* pOut,
const drwav_uint8* pIn,
size_t sampleCount);
1125DRWAV_API
void drwav_s32_to_s16(drwav_int16* pOut,
const drwav_int32* pIn,
size_t sampleCount);
1128DRWAV_API
void drwav_f32_to_s16(drwav_int16* pOut,
const float* pIn,
size_t sampleCount);
1131DRWAV_API
void drwav_f64_to_s16(drwav_int16* pOut,
const double* pIn,
size_t sampleCount);
1134DRWAV_API
void drwav_alaw_to_s16(drwav_int16* pOut,
const drwav_uint8* pIn,
size_t sampleCount);
1137DRWAV_API
void drwav_mulaw_to_s16(drwav_int16* pOut,
const drwav_uint8* pIn,
size_t sampleCount);
1149DRWAV_API drwav_uint64 drwav_read_pcm_frames_f32(
drwav* pWav, drwav_uint64 framesToRead,
float* pBufferOut);
1150DRWAV_API drwav_uint64 drwav_read_pcm_frames_f32le(
drwav* pWav, drwav_uint64 framesToRead,
float* pBufferOut);
1151DRWAV_API drwav_uint64 drwav_read_pcm_frames_f32be(
drwav* pWav, drwav_uint64 framesToRead,
float* pBufferOut);
1154DRWAV_API
void drwav_u8_to_f32(
float* pOut,
const drwav_uint8* pIn,
size_t sampleCount);
1157DRWAV_API
void drwav_s16_to_f32(
float* pOut,
const drwav_int16* pIn,
size_t sampleCount);
1160DRWAV_API
void drwav_s24_to_f32(
float* pOut,
const drwav_uint8* pIn,
size_t sampleCount);
1163DRWAV_API
void drwav_s32_to_f32(
float* pOut,
const drwav_int32* pIn,
size_t sampleCount);
1166DRWAV_API
void drwav_f64_to_f32(
float* pOut,
const double* pIn,
size_t sampleCount);
1169DRWAV_API
void drwav_alaw_to_f32(
float* pOut,
const drwav_uint8* pIn,
size_t sampleCount);
1172DRWAV_API
void drwav_mulaw_to_f32(
float* pOut,
const drwav_uint8* pIn,
size_t sampleCount);
1184DRWAV_API drwav_uint64 drwav_read_pcm_frames_s32(
drwav* pWav, drwav_uint64 framesToRead, drwav_int32* pBufferOut);
1185DRWAV_API drwav_uint64 drwav_read_pcm_frames_s32le(
drwav* pWav, drwav_uint64 framesToRead, drwav_int32* pBufferOut);
1186DRWAV_API drwav_uint64 drwav_read_pcm_frames_s32be(
drwav* pWav, drwav_uint64 framesToRead, drwav_int32* pBufferOut);
1189DRWAV_API
void drwav_u8_to_s32(drwav_int32* pOut,
const drwav_uint8* pIn,
size_t sampleCount);
1192DRWAV_API
void drwav_s16_to_s32(drwav_int32* pOut,
const drwav_int16* pIn,
size_t sampleCount);
1195DRWAV_API
void drwav_s24_to_s32(drwav_int32* pOut,
const drwav_uint8* pIn,
size_t sampleCount);
1198DRWAV_API
void drwav_f32_to_s32(drwav_int32* pOut,
const float* pIn,
size_t sampleCount);
1201DRWAV_API
void drwav_f64_to_s32(drwav_int32* pOut,
const double* pIn,
size_t sampleCount);
1204DRWAV_API
void drwav_alaw_to_s32(drwav_int32* pOut,
const drwav_uint8* pIn,
size_t sampleCount);
1207DRWAV_API
void drwav_mulaw_to_s32(drwav_int32* pOut,
const drwav_uint8* pIn,
size_t sampleCount);
1214#ifndef DR_WAV_NO_STDIO
1223DRWAV_API drwav_bool32 drwav_init_file_ex(
drwav* pWav,
const char* filename, drwav_chunk_proc onChunk,
void* pChunkUserData, drwav_uint32 flags,
const drwav_allocation_callbacks* pAllocationCallbacks);
1225DRWAV_API drwav_bool32 drwav_init_file_ex_w(
drwav* pWav,
const wchar_t* filename, drwav_chunk_proc onChunk,
void* pChunkUserData, drwav_uint32 flags,
const drwav_allocation_callbacks* pAllocationCallbacks);
1226DRWAV_API drwav_bool32 drwav_init_file_with_metadata(
drwav* pWav,
const char* filename, drwav_uint32 flags,
const drwav_allocation_callbacks* pAllocationCallbacks);
1227DRWAV_API drwav_bool32 drwav_init_file_with_metadata_w(
drwav* pWav,
const wchar_t* filename, drwav_uint32 flags,
const drwav_allocation_callbacks* pAllocationCallbacks);
1254DRWAV_API drwav_bool32 drwav_init_memory_ex(
drwav* pWav,
const void* data,
size_t dataSize, drwav_chunk_proc onChunk,
void* pChunkUserData, drwav_uint32 flags,
const drwav_allocation_callbacks* pAllocationCallbacks);
1255DRWAV_API drwav_bool32 drwav_init_memory_with_metadata(
drwav* pWav,
const void* data,
size_t dataSize, drwav_uint32 flags,
const drwav_allocation_callbacks* pAllocationCallbacks);
1267DRWAV_API drwav_bool32 drwav_init_memory_write_sequential_pcm_frames(
drwav* pWav,
void** ppData,
size_t* pDataSize,
const drwav_data_format* pFormat, drwav_uint64 totalPCMFrameCount,
const drwav_allocation_callbacks* pAllocationCallbacks);
1270#ifndef DR_WAV_NO_CONVERSION_API
1276DRWAV_API drwav_int16* drwav_open_and_read_pcm_frames_s16(drwav_read_proc onRead, drwav_seek_proc onSeek,
void* pUserData,
unsigned int* channelsOut,
unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut,
const drwav_allocation_callbacks* pAllocationCallbacks);
1277DRWAV_API
float* drwav_open_and_read_pcm_frames_f32(drwav_read_proc onRead, drwav_seek_proc onSeek,
void* pUserData,
unsigned int* channelsOut,
unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut,
const drwav_allocation_callbacks* pAllocationCallbacks);
1278DRWAV_API drwav_int32* drwav_open_and_read_pcm_frames_s32(drwav_read_proc onRead, drwav_seek_proc onSeek,
void* pUserData,
unsigned int* channelsOut,
unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut,
const drwav_allocation_callbacks* pAllocationCallbacks);
1279#ifndef DR_WAV_NO_STDIO
1285DRWAV_API drwav_int16* drwav_open_file_and_read_pcm_frames_s16(
const char* filename,
unsigned int* channelsOut,
unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut,
const drwav_allocation_callbacks* pAllocationCallbacks);
1286DRWAV_API
float* drwav_open_file_and_read_pcm_frames_f32(
const char* filename,
unsigned int* channelsOut,
unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut,
const drwav_allocation_callbacks* pAllocationCallbacks);
1287DRWAV_API drwav_int32* drwav_open_file_and_read_pcm_frames_s32(
const char* filename,
unsigned int* channelsOut,
unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut,
const drwav_allocation_callbacks* pAllocationCallbacks);
1288DRWAV_API drwav_int16* drwav_open_file_and_read_pcm_frames_s16_w(
const wchar_t* filename,
unsigned int* channelsOut,
unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut,
const drwav_allocation_callbacks* pAllocationCallbacks);
1289DRWAV_API
float* drwav_open_file_and_read_pcm_frames_f32_w(
const wchar_t* filename,
unsigned int* channelsOut,
unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut,
const drwav_allocation_callbacks* pAllocationCallbacks);
1290DRWAV_API drwav_int32* drwav_open_file_and_read_pcm_frames_s32_w(
const wchar_t* filename,
unsigned int* channelsOut,
unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut,
const drwav_allocation_callbacks* pAllocationCallbacks);
1297DRWAV_API drwav_int16* drwav_open_memory_and_read_pcm_frames_s16(
const void* data,
size_t dataSize,
unsigned int* channelsOut,
unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut,
const drwav_allocation_callbacks* pAllocationCallbacks);
1298DRWAV_API
float* drwav_open_memory_and_read_pcm_frames_f32(
const void* data,
size_t dataSize,
unsigned int* channelsOut,
unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut,
const drwav_allocation_callbacks* pAllocationCallbacks);
1299DRWAV_API drwav_int32* drwav_open_memory_and_read_pcm_frames_s32(
const void* data,
size_t dataSize,
unsigned int* channelsOut,
unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut,
const drwav_allocation_callbacks* pAllocationCallbacks);
1306DRWAV_API drwav_uint16 drwav_bytes_to_u16(
const drwav_uint8* data);
1307DRWAV_API drwav_int16 drwav_bytes_to_s16(
const drwav_uint8* data);
1308DRWAV_API drwav_uint32 drwav_bytes_to_u32(
const drwav_uint8* data);
1309DRWAV_API drwav_int32 drwav_bytes_to_s32(
const drwav_uint8* data);
1310DRWAV_API drwav_uint64 drwav_bytes_to_u64(
const drwav_uint8* data);
1311DRWAV_API drwav_int64 drwav_bytes_to_s64(
const drwav_uint8* data);
1312DRWAV_API
float drwav_bytes_to_f32(
const drwav_uint8* data);
1315DRWAV_API drwav_bool32 drwav_guid_equal(
const drwav_uint8 a[16],
const drwav_uint8 b[16]);
1318DRWAV_API drwav_bool32 drwav_fourcc_equal(
const drwav_uint8* a,
const char* b);
1333#if defined(DR_WAV_IMPLEMENTATION) || defined(DRWAV_IMPLEMENTATION)
1339#pragma options opt off
1346#ifndef DR_WAV_NO_STDIO
1348#ifndef DR_WAV_NO_WCHAR
1356#define DRWAV_ASSERT(expression) assert(expression)
1359#define DRWAV_MALLOC(sz) malloc((sz))
1361#ifndef DRWAV_REALLOC
1362#define DRWAV_REALLOC(p, sz) realloc((p), (sz))
1365#define DRWAV_FREE(p) free((p))
1367#ifndef DRWAV_COPY_MEMORY
1368#define DRWAV_COPY_MEMORY(dst, src, sz) memcpy((dst), (src), (sz))
1370#ifndef DRWAV_ZERO_MEMORY
1371#define DRWAV_ZERO_MEMORY(p, sz) memset((p), 0, (sz))
1373#ifndef DRWAV_ZERO_OBJECT
1374#define DRWAV_ZERO_OBJECT(p) DRWAV_ZERO_MEMORY((p), sizeof(*p))
1377#define drwav_countof(x) (sizeof(x) / sizeof(x[0]))
1378#define drwav_align(x, a) ((((x) + (a) - 1) / (a)) * (a))
1379#define drwav_min(a, b) (((a) < (b)) ? (a) : (b))
1380#define drwav_max(a, b) (((a) > (b)) ? (a) : (b))
1381#define drwav_clamp(x, lo, hi) (drwav_max((lo), drwav_min((hi), (x))))
1382#define drwav_offset_ptr(p, offset) (((drwav_uint8*)(p)) + (offset))
1384#define DRWAV_MAX_SIMD_VECTOR_SIZE 32
1387#if defined(__x86_64__) || defined(_M_X64)
1389#elif defined(__i386) || defined(_M_IX86)
1391#elif defined(__arm__) || defined(_M_ARM)
1398 #define DRWAV_INLINE __forceinline
1399#elif defined(__GNUC__)
1407 #if defined(__STRICT_ANSI__)
1408 #define DRWAV_GNUC_INLINE_HINT __inline__
1410 #define DRWAV_GNUC_INLINE_HINT inline
1413 #if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 2)) || defined(__clang__)
1414 #define DRWAV_INLINE DRWAV_GNUC_INLINE_HINT __attribute__((always_inline))
1416 #define DRWAV_INLINE DRWAV_GNUC_INLINE_HINT
1418#elif defined(__WATCOMC__)
1419 #define DRWAV_INLINE __inline
1421 #define DRWAV_INLINE
1426#if defined(SIZE_MAX)
1427 #define DRWAV_SIZE_MAX SIZE_MAX
1429 #if defined(_WIN64) || defined(_LP64) || defined(__LP64__)
1430 #define DRWAV_SIZE_MAX ((drwav_uint64)0xFFFFFFFFFFFFFFFF)
1432 #define DRWAV_SIZE_MAX 0xFFFFFFFF
1438#define DRWAV_INT64_MIN ((drwav_int64) ((drwav_uint64)0x80000000 << 32))
1439#define DRWAV_INT64_MAX ((drwav_int64)(((drwav_uint64)0x7FFFFFFF << 32) | 0xFFFFFFFF))
1441#if defined(_MSC_VER) && _MSC_VER >= 1400
1442 #define DRWAV_HAS_BYTESWAP16_INTRINSIC
1443 #define DRWAV_HAS_BYTESWAP32_INTRINSIC
1444 #define DRWAV_HAS_BYTESWAP64_INTRINSIC
1445#elif defined(__clang__)
1446 #if defined(__has_builtin)
1447 #if __has_builtin(__builtin_bswap16)
1448 #define DRWAV_HAS_BYTESWAP16_INTRINSIC
1450 #if __has_builtin(__builtin_bswap32)
1451 #define DRWAV_HAS_BYTESWAP32_INTRINSIC
1453 #if __has_builtin(__builtin_bswap64)
1454 #define DRWAV_HAS_BYTESWAP64_INTRINSIC
1457#elif defined(__GNUC__)
1458 #if ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
1459 #define DRWAV_HAS_BYTESWAP32_INTRINSIC
1460 #define DRWAV_HAS_BYTESWAP64_INTRINSIC
1462 #if ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))
1463 #define DRWAV_HAS_BYTESWAP16_INTRINSIC
1467DRWAV_API
void drwav_version(drwav_uint32* pMajor, drwav_uint32* pMinor, drwav_uint32* pRevision)
1470 *pMajor = DRWAV_VERSION_MAJOR;
1474 *pMinor = DRWAV_VERSION_MINOR;
1478 *pRevision = DRWAV_VERSION_REVISION;
1482DRWAV_API
const char* drwav_version_string(
void)
1484 return DRWAV_VERSION_STRING;
1491#ifndef DRWAV_MAX_SAMPLE_RATE
1492#define DRWAV_MAX_SAMPLE_RATE 384000
1494#ifndef DRWAV_MAX_CHANNELS
1495#define DRWAV_MAX_CHANNELS 256
1497#ifndef DRWAV_MAX_BITS_PER_SAMPLE
1498#define DRWAV_MAX_BITS_PER_SAMPLE 64
1501static const drwav_uint8 drwavGUID_W64_RIFF[16] = {0x72,0x69,0x66,0x66, 0x2E,0x91, 0xCF,0x11, 0xA5,0xD6, 0x28,0xDB,0x04,0xC1,0x00,0x00};
1502static const drwav_uint8 drwavGUID_W64_WAVE[16] = {0x77,0x61,0x76,0x65, 0xF3,0xAC, 0xD3,0x11, 0x8C,0xD1, 0x00,0xC0,0x4F,0x8E,0xDB,0x8A};
1504static const drwav_uint8 drwavGUID_W64_FMT [16] = {0x66,0x6D,0x74,0x20, 0xF3,0xAC, 0xD3,0x11, 0x8C,0xD1, 0x00,0xC0,0x4F,0x8E,0xDB,0x8A};
1505static const drwav_uint8 drwavGUID_W64_FACT[16] = {0x66,0x61,0x63,0x74, 0xF3,0xAC, 0xD3,0x11, 0x8C,0xD1, 0x00,0xC0,0x4F,0x8E,0xDB,0x8A};
1506static const drwav_uint8 drwavGUID_W64_DATA[16] = {0x64,0x61,0x74,0x61, 0xF3,0xAC, 0xD3,0x11, 0x8C,0xD1, 0x00,0xC0,0x4F,0x8E,0xDB,0x8A};
1510static DRWAV_INLINE
int drwav__is_little_endian(
void)
1512#if defined(DRWAV_X86) || defined(DRWAV_X64)
1514#elif defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && __BYTE_ORDER == __LITTLE_ENDIAN
1518 return (*(
char*)&n) == 1;
1523static DRWAV_INLINE
void drwav_bytes_to_guid(
const drwav_uint8* data, drwav_uint8* guid)
1526 for (i = 0; i < 16; ++i) {
1532static DRWAV_INLINE drwav_uint16 drwav__bswap16(drwav_uint16 n)
1534#ifdef DRWAV_HAS_BYTESWAP16_INTRINSIC
1535 #if defined(_MSC_VER)
1536 return _byteswap_ushort(n);
1537 #elif defined(__GNUC__) || defined(__clang__)
1538 return __builtin_bswap16(n);
1540 #error "This compiler does not support the byte swap intrinsic."
1543 return ((n & 0xFF00) >> 8) |
1544 ((n & 0x00FF) << 8);
1548static DRWAV_INLINE drwav_uint32 drwav__bswap32(drwav_uint32 n)
1550#ifdef DRWAV_HAS_BYTESWAP32_INTRINSIC
1551 #if defined(_MSC_VER)
1552 return _byteswap_ulong(n);
1553 #elif defined(__GNUC__) || defined(__clang__)
1554 #if defined(DRWAV_ARM) && (defined(__ARM_ARCH) && __ARM_ARCH >= 6) && !defined(DRWAV_64BIT)
1557 __asm__ __volatile__ (
1558 #
if defined(DRWAV_64BIT)
1559 "rev %w[out], %w[in]" : [out]
"=r"(r) : [in]
"r"(n)
1561 "rev %[out], %[in]" : [out]
"=r"(r) : [in]
"r"(n)
1566 return __builtin_bswap32(n);
1569 #error "This compiler does not support the byte swap intrinsic."
1572 return ((n & 0xFF000000) >> 24) |
1573 ((n & 0x00FF0000) >> 8) |
1574 ((n & 0x0000FF00) << 8) |
1575 ((n & 0x000000FF) << 24);
1579static DRWAV_INLINE drwav_uint64 drwav__bswap64(drwav_uint64 n)
1581#ifdef DRWAV_HAS_BYTESWAP64_INTRINSIC
1582 #if defined(_MSC_VER)
1583 return _byteswap_uint64(n);
1584 #elif defined(__GNUC__) || defined(__clang__)
1585 return __builtin_bswap64(n);
1587 #error "This compiler does not support the byte swap intrinsic."
1591 return ((n & ((drwav_uint64)0xFF000000 << 32)) >> 56) |
1592 ((n & ((drwav_uint64)0x00FF0000 << 32)) >> 40) |
1593 ((n & ((drwav_uint64)0x0000FF00 << 32)) >> 24) |
1594 ((n & ((drwav_uint64)0x000000FF << 32)) >> 8) |
1595 ((n & ((drwav_uint64)0xFF000000 )) << 8) |
1596 ((n & ((drwav_uint64)0x00FF0000 )) << 24) |
1597 ((n & ((drwav_uint64)0x0000FF00 )) << 40) |
1598 ((n & ((drwav_uint64)0x000000FF )) << 56);
1603static DRWAV_INLINE drwav_int16 drwav__bswap_s16(drwav_int16 n)
1605 return (drwav_int16)drwav__bswap16((drwav_uint16)n);
1608static DRWAV_INLINE
void drwav__bswap_samples_s16(drwav_int16* pSamples, drwav_uint64 sampleCount)
1610 drwav_uint64 iSample;
1611 for (iSample = 0; iSample < sampleCount; iSample += 1) {
1612 pSamples[iSample] = drwav__bswap_s16(pSamples[iSample]);
1617static DRWAV_INLINE
void drwav__bswap_s24(drwav_uint8* p)
1625static DRWAV_INLINE
void drwav__bswap_samples_s24(drwav_uint8* pSamples, drwav_uint64 sampleCount)
1627 drwav_uint64 iSample;
1628 for (iSample = 0; iSample < sampleCount; iSample += 1) {
1629 drwav_uint8* pSample = pSamples + (iSample*3);
1630 drwav__bswap_s24(pSample);
1635static DRWAV_INLINE drwav_int32 drwav__bswap_s32(drwav_int32 n)
1637 return (drwav_int32)drwav__bswap32((drwav_uint32)n);
1640static DRWAV_INLINE
void drwav__bswap_samples_s32(drwav_int32* pSamples, drwav_uint64 sampleCount)
1642 drwav_uint64 iSample;
1643 for (iSample = 0; iSample < sampleCount; iSample += 1) {
1644 pSamples[iSample] = drwav__bswap_s32(pSamples[iSample]);
1649static DRWAV_INLINE drwav_int64 drwav__bswap_s64(drwav_int64 n)
1651 return (drwav_int64)drwav__bswap64((drwav_uint64)n);
1654static DRWAV_INLINE
void drwav__bswap_samples_s64(drwav_int64* pSamples, drwav_uint64 sampleCount)
1656 drwav_uint64 iSample;
1657 for (iSample = 0; iSample < sampleCount; iSample += 1) {
1658 pSamples[iSample] = drwav__bswap_s64(pSamples[iSample]);
1663static DRWAV_INLINE
float drwav__bswap_f32(
float n)
1670 x.i = drwav__bswap32(x.i);
1675static DRWAV_INLINE
void drwav__bswap_samples_f32(
float* pSamples, drwav_uint64 sampleCount)
1677 drwav_uint64 iSample;
1678 for (iSample = 0; iSample < sampleCount; iSample += 1) {
1679 pSamples[iSample] = drwav__bswap_f32(pSamples[iSample]);
1684static DRWAV_INLINE
void drwav__bswap_samples(
void* pSamples, drwav_uint64 sampleCount, drwav_uint32 bytesPerSample)
1686 switch (bytesPerSample)
1694 drwav__bswap_samples_s16((drwav_int16*)pSamples, sampleCount);
1698 drwav__bswap_samples_s24((drwav_uint8*)pSamples, sampleCount);
1702 drwav__bswap_samples_s32((drwav_int32*)pSamples, sampleCount);
1706 drwav__bswap_samples_s64((drwav_int64*)pSamples, sampleCount);
1711 DRWAV_ASSERT(DRWAV_FALSE);
1718DRWAV_PRIVATE DRWAV_INLINE drwav_bool32 drwav_is_container_be(drwav_container container)
1720 if (container == drwav_container_rifx || container == drwav_container_aiff) {
1728DRWAV_PRIVATE DRWAV_INLINE drwav_uint16 drwav_bytes_to_u16_le(
const drwav_uint8* data)
1730 return ((drwav_uint16)data[0] << 0) | ((drwav_uint16)data[1] << 8);
1733DRWAV_PRIVATE DRWAV_INLINE drwav_uint16 drwav_bytes_to_u16_be(
const drwav_uint8* data)
1735 return ((drwav_uint16)data[1] << 0) | ((drwav_uint16)data[0] << 8);
1738DRWAV_PRIVATE DRWAV_INLINE drwav_uint16 drwav_bytes_to_u16_ex(
const drwav_uint8* data, drwav_container container)
1740 if (drwav_is_container_be(container)) {
1741 return drwav_bytes_to_u16_be(data);
1743 return drwav_bytes_to_u16_le(data);
1748DRWAV_PRIVATE DRWAV_INLINE drwav_uint32 drwav_bytes_to_u32_le(
const drwav_uint8* data)
1750 return ((drwav_uint32)data[0] << 0) | ((drwav_uint32)data[1] << 8) | ((drwav_uint32)data[2] << 16) | ((drwav_uint32)data[3] << 24);
1753DRWAV_PRIVATE DRWAV_INLINE drwav_uint32 drwav_bytes_to_u32_be(
const drwav_uint8* data)
1755 return ((drwav_uint32)data[3] << 0) | ((drwav_uint32)data[2] << 8) | ((drwav_uint32)data[1] << 16) | ((drwav_uint32)data[0] << 24);
1758DRWAV_PRIVATE DRWAV_INLINE drwav_uint32 drwav_bytes_to_u32_ex(
const drwav_uint8* data, drwav_container container)
1760 if (drwav_is_container_be(container)) {
1761 return drwav_bytes_to_u32_be(data);
1763 return drwav_bytes_to_u32_le(data);
1769DRWAV_PRIVATE drwav_int64 drwav_aiff_extented_to_s64(
const drwav_uint8* data)
1771 drwav_uint32 exponent = ((drwav_uint32)data[0] << 8) | data[1];
1772 drwav_uint64 hi = ((drwav_uint64)data[2] << 24) | ((drwav_uint64)data[3] << 16) | ((drwav_uint64)data[4] << 8) | ((drwav_uint64)data[5] << 0);
1773 drwav_uint64 lo = ((drwav_uint64)data[6] << 24) | ((drwav_uint64)data[7] << 16) | ((drwav_uint64)data[8] << 8) | ((drwav_uint64)data[9] << 0);
1774 drwav_uint64 significand = (hi << 32) | lo;
1775 int sign = exponent >> 15;
1781 if (exponent == 0 && significand == 0) {
1783 }
else if (exponent == 0x7FFF) {
1784 return sign ? DRWAV_INT64_MIN : DRWAV_INT64_MAX;
1789 if (exponent > 63) {
1790 return sign ? DRWAV_INT64_MIN : DRWAV_INT64_MAX;
1791 }
else if (exponent < 1) {
1795 significand >>= (63 - exponent);
1798 return -(drwav_int64)significand;
1800 return (drwav_int64)significand;
1805DRWAV_PRIVATE
void* drwav__malloc_default(
size_t sz,
void* pUserData)
1808 return DRWAV_MALLOC(sz);
1811DRWAV_PRIVATE
void* drwav__realloc_default(
void* p,
size_t sz,
void* pUserData)
1814 return DRWAV_REALLOC(p, sz);
1817DRWAV_PRIVATE
void drwav__free_default(
void* p,
void* pUserData)
1826 if (pAllocationCallbacks == NULL) {
1830 if (pAllocationCallbacks->onMalloc != NULL) {
1831 return pAllocationCallbacks->onMalloc(sz, pAllocationCallbacks->pUserData);
1835 if (pAllocationCallbacks->onRealloc != NULL) {
1836 return pAllocationCallbacks->onRealloc(NULL, sz, pAllocationCallbacks->pUserData);
1842DRWAV_PRIVATE
void* drwav__realloc_from_callbacks(
void* p,
size_t szNew,
size_t szOld,
const drwav_allocation_callbacks* pAllocationCallbacks)
1844 if (pAllocationCallbacks == NULL) {
1848 if (pAllocationCallbacks->onRealloc != NULL) {
1849 return pAllocationCallbacks->onRealloc(p, szNew, pAllocationCallbacks->pUserData);
1853 if (pAllocationCallbacks->onMalloc != NULL && pAllocationCallbacks->onFree != NULL) {
1856 p2 = pAllocationCallbacks->onMalloc(szNew, pAllocationCallbacks->pUserData);
1862 DRWAV_COPY_MEMORY(p2, p, szOld);
1863 pAllocationCallbacks->onFree(p, pAllocationCallbacks->pUserData);
1874 if (p == NULL || pAllocationCallbacks == NULL) {
1878 if (pAllocationCallbacks->onFree != NULL) {
1879 pAllocationCallbacks->onFree(p, pAllocationCallbacks->pUserData);
1886 if (pAllocationCallbacks != NULL) {
1888 return *pAllocationCallbacks;
1892 allocationCallbacks.pUserData = NULL;
1893 allocationCallbacks.onMalloc = drwav__malloc_default;
1894 allocationCallbacks.onRealloc = drwav__realloc_default;
1895 allocationCallbacks.onFree = drwav__free_default;
1896 return allocationCallbacks;
1901static DRWAV_INLINE drwav_bool32 drwav__is_compressed_format_tag(drwav_uint16 formatTag)
1904 formatTag == DR_WAVE_FORMAT_ADPCM ||
1905 formatTag == DR_WAVE_FORMAT_DVI_ADPCM;
1908DRWAV_PRIVATE
unsigned int drwav__chunk_padding_size_riff(drwav_uint64 chunkSize)
1910 return (
unsigned int)(chunkSize % 2);
1913DRWAV_PRIVATE
unsigned int drwav__chunk_padding_size_w64(drwav_uint64 chunkSize)
1915 return (
unsigned int)(chunkSize % 8);
1918DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__msadpcm(
drwav* pWav, drwav_uint64 samplesToRead, drwav_int16* pBufferOut);
1919DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__ima(
drwav* pWav, drwav_uint64 samplesToRead, drwav_int16* pBufferOut);
1920DRWAV_PRIVATE drwav_bool32 drwav_init_write__internal(
drwav* pWav,
const drwav_data_format* pFormat, drwav_uint64 totalSampleCount);
1922DRWAV_PRIVATE drwav_result drwav__read_chunk_header(drwav_read_proc onRead,
void* pUserData, drwav_container container, drwav_uint64* pRunningBytesReadOut,
drwav_chunk_header* pHeaderOut)
1924 if (container == drwav_container_riff || container == drwav_container_rifx || container == drwav_container_rf64 || container == drwav_container_aiff) {
1925 drwav_uint8 sizeInBytes[4];
1927 if (onRead(pUserData, pHeaderOut->id.fourcc, 4) != 4) {
1928 return DRWAV_AT_END;
1931 if (onRead(pUserData, sizeInBytes, 4) != 4) {
1932 return DRWAV_INVALID_FILE;
1935 pHeaderOut->sizeInBytes = drwav_bytes_to_u32_ex(sizeInBytes, container);
1936 pHeaderOut->paddingSize = drwav__chunk_padding_size_riff(pHeaderOut->sizeInBytes);
1938 *pRunningBytesReadOut += 8;
1939 }
else if (container == drwav_container_w64) {
1940 drwav_uint8 sizeInBytes[8];
1942 if (onRead(pUserData, pHeaderOut->id.guid, 16) != 16) {
1943 return DRWAV_AT_END;
1946 if (onRead(pUserData, sizeInBytes, 8) != 8) {
1947 return DRWAV_INVALID_FILE;
1950 pHeaderOut->sizeInBytes = drwav_bytes_to_u64(sizeInBytes) - 24;
1951 pHeaderOut->paddingSize = drwav__chunk_padding_size_w64(pHeaderOut->sizeInBytes);
1952 *pRunningBytesReadOut += 24;
1954 return DRWAV_INVALID_FILE;
1957 return DRWAV_SUCCESS;
1960DRWAV_PRIVATE drwav_bool32 drwav__seek_forward(drwav_seek_proc onSeek, drwav_uint64 offset,
void* pUserData)
1962 drwav_uint64 bytesRemainingToSeek = offset;
1963 while (bytesRemainingToSeek > 0) {
1964 if (bytesRemainingToSeek > 0x7FFFFFFF) {
1965 if (!onSeek(pUserData, 0x7FFFFFFF, drwav_seek_origin_current)) {
1968 bytesRemainingToSeek -= 0x7FFFFFFF;
1970 if (!onSeek(pUserData, (
int)bytesRemainingToSeek, drwav_seek_origin_current)) {
1973 bytesRemainingToSeek = 0;
1980DRWAV_PRIVATE drwav_bool32 drwav__seek_from_start(drwav_seek_proc onSeek, drwav_uint64 offset,
void* pUserData)
1982 if (offset <= 0x7FFFFFFF) {
1983 return onSeek(pUserData, (
int)offset, drwav_seek_origin_start);
1987 if (!onSeek(pUserData, 0x7FFFFFFF, drwav_seek_origin_start)) {
1990 offset -= 0x7FFFFFFF;
1993 if (offset <= 0x7FFFFFFF) {
1994 return onSeek(pUserData, (
int)offset, drwav_seek_origin_current);
1997 if (!onSeek(pUserData, 0x7FFFFFFF, drwav_seek_origin_current)) {
2000 offset -= 0x7FFFFFFF;
2009DRWAV_PRIVATE
size_t drwav__on_read(drwav_read_proc onRead,
void* pUserData,
void* pBufferOut,
size_t bytesToRead, drwav_uint64* pCursor)
2013 DRWAV_ASSERT(onRead != NULL);
2014 DRWAV_ASSERT(pCursor != NULL);
2016 bytesRead = onRead(pUserData, pBufferOut, bytesToRead);
2017 *pCursor += bytesRead;
2022DRWAV_PRIVATE drwav_bool32 drwav__on_seek(drwav_seek_proc onSeek,
void* pUserData,
int offset, drwav_seek_origin origin, drwav_uint64* pCursor)
2024 DRWAV_ASSERT(onSeek != NULL);
2025 DRWAV_ASSERT(pCursor != NULL);
2027 if (!onSeek(pUserData, offset, origin)) {
2031 if (origin == drwav_seek_origin_start) {
2042#define DRWAV_SMPL_BYTES 36
2043#define DRWAV_SMPL_LOOP_BYTES 24
2044#define DRWAV_INST_BYTES 7
2045#define DRWAV_ACID_BYTES 24
2046#define DRWAV_CUE_BYTES 4
2047#define DRWAV_BEXT_BYTES 602
2048#define DRWAV_BEXT_DESCRIPTION_BYTES 256
2049#define DRWAV_BEXT_ORIGINATOR_NAME_BYTES 32
2050#define DRWAV_BEXT_ORIGINATOR_REF_BYTES 32
2051#define DRWAV_BEXT_RESERVED_BYTES 180
2052#define DRWAV_BEXT_UMID_BYTES 64
2053#define DRWAV_CUE_POINT_BYTES 24
2054#define DRWAV_LIST_LABEL_OR_NOTE_BYTES 4
2055#define DRWAV_LIST_LABELLED_TEXT_BYTES 20
2057#define DRWAV_METADATA_ALIGNMENT 8
2061 drwav__metadata_parser_stage_count,
2062 drwav__metadata_parser_stage_read
2063} drwav__metadata_parser_stage;
2067 drwav_read_proc onRead;
2068 drwav_seek_proc onSeek;
2069 void *pReadSeekUserData;
2070 drwav__metadata_parser_stage stage;
2072 drwav_uint32 metadataCount;
2074 drwav_uint8 *pDataCursor;
2075 drwav_uint64 metadataCursor;
2076 drwav_uint64 extraCapacity;
2077} drwav__metadata_parser;
2079DRWAV_PRIVATE
size_t drwav__metadata_memory_capacity(drwav__metadata_parser* pParser)
2081 drwav_uint64 cap =
sizeof(
drwav_metadata) * (drwav_uint64)pParser->metadataCount + pParser->extraCapacity;
2082 if (cap > DRWAV_SIZE_MAX) {
2089DRWAV_PRIVATE drwav_uint8* drwav__metadata_get_memory(drwav__metadata_parser* pParser,
size_t size,
size_t align)
2091 drwav_uint8* pResult;
2094 drwav_uintptr modulo = (drwav_uintptr)pParser->pDataCursor % align;
2096 pParser->pDataCursor += align - modulo;
2100 pResult = pParser->pDataCursor;
2106 DRWAV_ASSERT((pResult + size) <= (pParser->pData + drwav__metadata_memory_capacity(pParser)));
2108 pParser->pDataCursor += size;
2112DRWAV_PRIVATE
void drwav__metadata_request_extra_memory_for_stage_2(drwav__metadata_parser* pParser,
size_t bytes,
size_t align)
2114 size_t extra =
bytes + (align ? (align - 1) : 0);
2115 pParser->extraCapacity += extra;
2118DRWAV_PRIVATE drwav_result drwav__metadata_alloc(drwav__metadata_parser* pParser,
drwav_allocation_callbacks* pAllocationCallbacks)
2120 if (pParser->extraCapacity != 0 || pParser->metadataCount != 0) {
2121 pAllocationCallbacks->onFree(pParser->pData, pAllocationCallbacks->pUserData);
2123 pParser->pData = (drwav_uint8*)pAllocationCallbacks->onMalloc(drwav__metadata_memory_capacity(pParser), pAllocationCallbacks->pUserData);
2124 pParser->pDataCursor = pParser->pData;
2126 if (pParser->pData == NULL) {
2127 return DRWAV_OUT_OF_MEMORY;
2136 pParser->metadataCursor = 0;
2139 return DRWAV_SUCCESS;
2142DRWAV_PRIVATE
size_t drwav__metadata_parser_read(drwav__metadata_parser* pParser,
void* pBufferOut,
size_t bytesToRead, drwav_uint64* pCursor)
2144 if (pCursor != NULL) {
2145 return drwav__on_read(pParser->onRead, pParser->pReadSeekUserData, pBufferOut, bytesToRead, pCursor);
2147 return pParser->onRead(pParser->pReadSeekUserData, pBufferOut, bytesToRead);
2151DRWAV_PRIVATE drwav_uint64 drwav__read_smpl_to_metadata_obj(drwav__metadata_parser* pParser,
const drwav_chunk_header* pChunkHeader,
drwav_metadata* pMetadata)
2153 drwav_uint8 smplHeaderData[DRWAV_SMPL_BYTES];
2154 drwav_uint64 totalBytesRead = 0;
2155 size_t bytesJustRead;
2157 if (pMetadata == NULL) {
2161 bytesJustRead = drwav__metadata_parser_read(pParser, smplHeaderData,
sizeof(smplHeaderData), &totalBytesRead);
2163 DRWAV_ASSERT(pParser->stage == drwav__metadata_parser_stage_read);
2164 DRWAV_ASSERT(pChunkHeader != NULL);
2166 if (pMetadata != NULL && bytesJustRead ==
sizeof(smplHeaderData)) {
2167 drwav_uint32 iSampleLoop;
2169 pMetadata->type = drwav_metadata_type_smpl;
2170 pMetadata->data.smpl.manufacturerId = drwav_bytes_to_u32(smplHeaderData + 0);
2171 pMetadata->data.smpl.productId = drwav_bytes_to_u32(smplHeaderData + 4);
2172 pMetadata->data.smpl.samplePeriodNanoseconds = drwav_bytes_to_u32(smplHeaderData + 8);
2173 pMetadata->data.smpl.midiUnityNote = drwav_bytes_to_u32(smplHeaderData + 12);
2174 pMetadata->data.smpl.midiPitchFraction = drwav_bytes_to_u32(smplHeaderData + 16);
2175 pMetadata->data.smpl.smpteFormat = drwav_bytes_to_u32(smplHeaderData + 20);
2176 pMetadata->data.smpl.smpteOffset = drwav_bytes_to_u32(smplHeaderData + 24);
2177 pMetadata->data.smpl.sampleLoopCount = drwav_bytes_to_u32(smplHeaderData + 28);
2178 pMetadata->data.smpl.samplerSpecificDataSizeInBytes = drwav_bytes_to_u32(smplHeaderData + 32);
2184 if (pMetadata->data.smpl.sampleLoopCount == (pChunkHeader->sizeInBytes - DRWAV_SMPL_BYTES) / DRWAV_SMPL_LOOP_BYTES) {
2185 pMetadata->data.smpl.pLoops = (
drwav_smpl_loop*)drwav__metadata_get_memory(pParser,
sizeof(
drwav_smpl_loop) * pMetadata->data.smpl.sampleLoopCount, DRWAV_METADATA_ALIGNMENT);
2187 for (iSampleLoop = 0; iSampleLoop < pMetadata->data.smpl.sampleLoopCount; ++iSampleLoop) {
2188 drwav_uint8 smplLoopData[DRWAV_SMPL_LOOP_BYTES];
2189 bytesJustRead = drwav__metadata_parser_read(pParser, smplLoopData,
sizeof(smplLoopData), &totalBytesRead);
2191 if (bytesJustRead ==
sizeof(smplLoopData)) {
2192 pMetadata->data.smpl.pLoops[iSampleLoop].cuePointId = drwav_bytes_to_u32(smplLoopData + 0);
2193 pMetadata->data.smpl.pLoops[iSampleLoop].type = drwav_bytes_to_u32(smplLoopData + 4);
2194 pMetadata->data.smpl.pLoops[iSampleLoop].firstSampleByteOffset = drwav_bytes_to_u32(smplLoopData + 8);
2195 pMetadata->data.smpl.pLoops[iSampleLoop].lastSampleByteOffset = drwav_bytes_to_u32(smplLoopData + 12);
2196 pMetadata->data.smpl.pLoops[iSampleLoop].sampleFraction = drwav_bytes_to_u32(smplLoopData + 16);
2197 pMetadata->data.smpl.pLoops[iSampleLoop].playCount = drwav_bytes_to_u32(smplLoopData + 20);
2203 if (pMetadata->data.smpl.samplerSpecificDataSizeInBytes > 0) {
2204 pMetadata->data.smpl.pSamplerSpecificData = drwav__metadata_get_memory(pParser, pMetadata->data.smpl.samplerSpecificDataSizeInBytes, 1);
2205 DRWAV_ASSERT(pMetadata->data.smpl.pSamplerSpecificData != NULL);
2207 drwav__metadata_parser_read(pParser, pMetadata->data.smpl.pSamplerSpecificData, pMetadata->data.smpl.samplerSpecificDataSizeInBytes, &totalBytesRead);
2212 return totalBytesRead;
2215DRWAV_PRIVATE drwav_uint64 drwav__read_cue_to_metadata_obj(drwav__metadata_parser* pParser,
const drwav_chunk_header* pChunkHeader,
drwav_metadata* pMetadata)
2217 drwav_uint8 cueHeaderSectionData[DRWAV_CUE_BYTES];
2218 drwav_uint64 totalBytesRead = 0;
2219 size_t bytesJustRead;
2221 if (pMetadata == NULL) {
2225 bytesJustRead = drwav__metadata_parser_read(pParser, cueHeaderSectionData,
sizeof(cueHeaderSectionData), &totalBytesRead);
2227 DRWAV_ASSERT(pParser->stage == drwav__metadata_parser_stage_read);
2229 if (bytesJustRead ==
sizeof(cueHeaderSectionData)) {
2230 pMetadata->type = drwav_metadata_type_cue;
2231 pMetadata->data.cue.cuePointCount = drwav_bytes_to_u32(cueHeaderSectionData);
2237 if (pMetadata->data.cue.cuePointCount == (pChunkHeader->sizeInBytes - DRWAV_CUE_BYTES) / DRWAV_CUE_POINT_BYTES) {
2238 pMetadata->data.cue.pCuePoints = (
drwav_cue_point*)drwav__metadata_get_memory(pParser,
sizeof(
drwav_cue_point) * pMetadata->data.cue.cuePointCount, DRWAV_METADATA_ALIGNMENT);
2239 DRWAV_ASSERT(pMetadata->data.cue.pCuePoints != NULL);
2241 if (pMetadata->data.cue.cuePointCount > 0) {
2242 drwav_uint32 iCuePoint;
2244 for (iCuePoint = 0; iCuePoint < pMetadata->data.cue.cuePointCount; ++iCuePoint) {
2245 drwav_uint8 cuePointData[DRWAV_CUE_POINT_BYTES];
2246 bytesJustRead = drwav__metadata_parser_read(pParser, cuePointData,
sizeof(cuePointData), &totalBytesRead);
2248 if (bytesJustRead ==
sizeof(cuePointData)) {
2249 pMetadata->data.cue.pCuePoints[iCuePoint].id = drwav_bytes_to_u32(cuePointData + 0);
2250 pMetadata->data.cue.pCuePoints[iCuePoint].playOrderPosition = drwav_bytes_to_u32(cuePointData + 4);
2251 pMetadata->data.cue.pCuePoints[iCuePoint].dataChunkId[0] = cuePointData[8];
2252 pMetadata->data.cue.pCuePoints[iCuePoint].dataChunkId[1] = cuePointData[9];
2253 pMetadata->data.cue.pCuePoints[iCuePoint].dataChunkId[2] = cuePointData[10];
2254 pMetadata->data.cue.pCuePoints[iCuePoint].dataChunkId[3] = cuePointData[11];
2255 pMetadata->data.cue.pCuePoints[iCuePoint].chunkStart = drwav_bytes_to_u32(cuePointData + 12);
2256 pMetadata->data.cue.pCuePoints[iCuePoint].blockStart = drwav_bytes_to_u32(cuePointData + 16);
2257 pMetadata->data.cue.pCuePoints[iCuePoint].sampleByteOffset = drwav_bytes_to_u32(cuePointData + 20);
2266 return totalBytesRead;
2269DRWAV_PRIVATE drwav_uint64 drwav__read_inst_to_metadata_obj(drwav__metadata_parser* pParser,
drwav_metadata* pMetadata)
2271 drwav_uint8 instData[DRWAV_INST_BYTES];
2272 drwav_uint64 bytesRead;
2274 if (pMetadata == NULL) {
2278 bytesRead = drwav__metadata_parser_read(pParser, instData,
sizeof(instData), NULL);
2280 DRWAV_ASSERT(pParser->stage == drwav__metadata_parser_stage_read);
2282 if (bytesRead ==
sizeof(instData)) {
2283 pMetadata->type = drwav_metadata_type_inst;
2284 pMetadata->data.inst.midiUnityNote = (drwav_int8)instData[0];
2285 pMetadata->data.inst.fineTuneCents = (drwav_int8)instData[1];
2286 pMetadata->data.inst.gainDecibels = (drwav_int8)instData[2];
2287 pMetadata->data.inst.lowNote = (drwav_int8)instData[3];
2288 pMetadata->data.inst.highNote = (drwav_int8)instData[4];
2289 pMetadata->data.inst.lowVelocity = (drwav_int8)instData[5];
2290 pMetadata->data.inst.highVelocity = (drwav_int8)instData[6];
2296DRWAV_PRIVATE drwav_uint64 drwav__read_acid_to_metadata_obj(drwav__metadata_parser* pParser,
drwav_metadata* pMetadata)
2298 drwav_uint8 acidData[DRWAV_ACID_BYTES];
2299 drwav_uint64 bytesRead;
2301 if (pMetadata == NULL) {
2305 bytesRead = drwav__metadata_parser_read(pParser, acidData,
sizeof(acidData), NULL);
2307 DRWAV_ASSERT(pParser->stage == drwav__metadata_parser_stage_read);
2309 if (bytesRead ==
sizeof(acidData)) {
2310 pMetadata->type = drwav_metadata_type_acid;
2311 pMetadata->data.acid.flags = drwav_bytes_to_u32(acidData + 0);
2312 pMetadata->data.acid.midiUnityNote = drwav_bytes_to_u16(acidData + 4);
2313 pMetadata->data.acid.reserved1 = drwav_bytes_to_u16(acidData + 6);
2314 pMetadata->data.acid.reserved2 = drwav_bytes_to_f32(acidData + 8);
2315 pMetadata->data.acid.numBeats = drwav_bytes_to_u32(acidData + 12);
2316 pMetadata->data.acid.meterDenominator = drwav_bytes_to_u16(acidData + 16);
2317 pMetadata->data.acid.meterNumerator = drwav_bytes_to_u16(acidData + 18);
2318 pMetadata->data.acid.tempo = drwav_bytes_to_f32(acidData + 20);
2324DRWAV_PRIVATE
size_t drwav__strlen(
const char* str)
2335DRWAV_PRIVATE
size_t drwav__strlen_clamped(
const char* str,
size_t maxToRead)
2339 while (*str++ && result < maxToRead) {
2346DRWAV_PRIVATE
char* drwav__metadata_copy_string(drwav__metadata_parser* pParser,
const char* str,
size_t maxToRead)
2348 size_t len = drwav__strlen_clamped(str, maxToRead);
2351 char* result = (
char*)drwav__metadata_get_memory(pParser, len + 1, 1);
2352 DRWAV_ASSERT(result != NULL);
2354 DRWAV_COPY_MEMORY(result, str, len);
2365 const void* pBuffer;
2368} drwav_buffer_reader;
2370DRWAV_PRIVATE drwav_result drwav_buffer_reader_init(
const void* pBuffer,
size_t sizeInBytes, drwav_buffer_reader* pReader)
2372 DRWAV_ASSERT(pBuffer != NULL);
2373 DRWAV_ASSERT(pReader != NULL);
2375 DRWAV_ZERO_OBJECT(pReader);
2377 pReader->pBuffer = pBuffer;
2378 pReader->sizeInBytes = sizeInBytes;
2379 pReader->cursor = 0;
2381 return DRWAV_SUCCESS;
2384DRWAV_PRIVATE
const void* drwav_buffer_reader_ptr(
const drwav_buffer_reader* pReader)
2386 DRWAV_ASSERT(pReader != NULL);
2388 return drwav_offset_ptr(pReader->pBuffer, pReader->cursor);
2391DRWAV_PRIVATE drwav_result drwav_buffer_reader_seek(drwav_buffer_reader* pReader,
size_t bytesToSeek)
2393 DRWAV_ASSERT(pReader != NULL);
2395 if (pReader->cursor + bytesToSeek > pReader->sizeInBytes) {
2396 return DRWAV_BAD_SEEK;
2399 pReader->cursor += bytesToSeek;
2401 return DRWAV_SUCCESS;
2404DRWAV_PRIVATE drwav_result drwav_buffer_reader_read(drwav_buffer_reader* pReader,
void* pDst,
size_t bytesToRead,
size_t* pBytesRead)
2406 drwav_result result = DRWAV_SUCCESS;
2407 size_t bytesRemaining;
2409 DRWAV_ASSERT(pReader != NULL);
2411 if (pBytesRead != NULL) {
2415 bytesRemaining = (pReader->sizeInBytes - pReader->cursor);
2416 if (bytesToRead > bytesRemaining) {
2417 bytesToRead = bytesRemaining;
2422 result = drwav_buffer_reader_seek(pReader, bytesToRead);
2425 DRWAV_COPY_MEMORY(pDst, drwav_buffer_reader_ptr(pReader), bytesToRead);
2426 pReader->cursor += bytesToRead;
2429 DRWAV_ASSERT(pReader->cursor <= pReader->sizeInBytes);
2431 if (result == DRWAV_SUCCESS) {
2432 if (pBytesRead != NULL) {
2433 *pBytesRead = bytesToRead;
2437 return DRWAV_SUCCESS;
2440DRWAV_PRIVATE drwav_result drwav_buffer_reader_read_u16(drwav_buffer_reader* pReader, drwav_uint16* pDst)
2442 drwav_result result;
2444 drwav_uint8 data[2];
2446 DRWAV_ASSERT(pReader != NULL);
2447 DRWAV_ASSERT(pDst != NULL);
2451 result = drwav_buffer_reader_read(pReader, data,
sizeof(*pDst), &bytesRead);
2452 if (result != DRWAV_SUCCESS || bytesRead !=
sizeof(*pDst)) {
2456 *pDst = drwav_bytes_to_u16(data);
2458 return DRWAV_SUCCESS;
2461DRWAV_PRIVATE drwav_result drwav_buffer_reader_read_u32(drwav_buffer_reader* pReader, drwav_uint32* pDst)
2463 drwav_result result;
2465 drwav_uint8 data[4];
2467 DRWAV_ASSERT(pReader != NULL);
2468 DRWAV_ASSERT(pDst != NULL);
2472 result = drwav_buffer_reader_read(pReader, data,
sizeof(*pDst), &bytesRead);
2473 if (result != DRWAV_SUCCESS || bytesRead !=
sizeof(*pDst)) {
2477 *pDst = drwav_bytes_to_u32(data);
2479 return DRWAV_SUCCESS;
2484DRWAV_PRIVATE drwav_uint64 drwav__read_bext_to_metadata_obj(drwav__metadata_parser* pParser,
drwav_metadata* pMetadata, drwav_uint64 chunkSize)
2486 drwav_uint8 bextData[DRWAV_BEXT_BYTES];
2487 size_t bytesRead = drwav__metadata_parser_read(pParser, bextData,
sizeof(bextData), NULL);
2489 DRWAV_ASSERT(pParser->stage == drwav__metadata_parser_stage_read);
2491 if (bytesRead ==
sizeof(bextData)) {
2492 drwav_buffer_reader reader;
2493 drwav_uint32 timeReferenceLow;
2494 drwav_uint32 timeReferenceHigh;
2497 pMetadata->type = drwav_metadata_type_bext;
2499 if (drwav_buffer_reader_init(bextData, bytesRead, &reader) == DRWAV_SUCCESS) {
2500 pMetadata->data.bext.pDescription = drwav__metadata_copy_string(pParser, (
const char*)drwav_buffer_reader_ptr(&reader), DRWAV_BEXT_DESCRIPTION_BYTES);
2501 drwav_buffer_reader_seek(&reader, DRWAV_BEXT_DESCRIPTION_BYTES);
2503 pMetadata->data.bext.pOriginatorName = drwav__metadata_copy_string(pParser, (
const char*)drwav_buffer_reader_ptr(&reader), DRWAV_BEXT_ORIGINATOR_NAME_BYTES);
2504 drwav_buffer_reader_seek(&reader, DRWAV_BEXT_ORIGINATOR_NAME_BYTES);
2506 pMetadata->data.bext.pOriginatorReference = drwav__metadata_copy_string(pParser, (
const char*)drwav_buffer_reader_ptr(&reader), DRWAV_BEXT_ORIGINATOR_REF_BYTES);
2507 drwav_buffer_reader_seek(&reader, DRWAV_BEXT_ORIGINATOR_REF_BYTES);
2509 drwav_buffer_reader_read(&reader, pMetadata->data.bext.pOriginationDate,
sizeof(pMetadata->data.bext.pOriginationDate), NULL);
2510 drwav_buffer_reader_read(&reader, pMetadata->data.bext.pOriginationTime,
sizeof(pMetadata->data.bext.pOriginationTime), NULL);
2512 drwav_buffer_reader_read_u32(&reader, &timeReferenceLow);
2513 drwav_buffer_reader_read_u32(&reader, &timeReferenceHigh);
2514 pMetadata->data.bext.timeReference = ((drwav_uint64)timeReferenceHigh << 32) + timeReferenceLow;
2516 drwav_buffer_reader_read_u16(&reader, &pMetadata->data.bext.version);
2518 pMetadata->data.bext.pUMID = drwav__metadata_get_memory(pParser, DRWAV_BEXT_UMID_BYTES, 1);
2519 drwav_buffer_reader_read(&reader, pMetadata->data.bext.pUMID, DRWAV_BEXT_UMID_BYTES, NULL);
2521 drwav_buffer_reader_read_u16(&reader, &pMetadata->data.bext.loudnessValue);
2522 drwav_buffer_reader_read_u16(&reader, &pMetadata->data.bext.loudnessRange);
2523 drwav_buffer_reader_read_u16(&reader, &pMetadata->data.bext.maxTruePeakLevel);
2524 drwav_buffer_reader_read_u16(&reader, &pMetadata->data.bext.maxMomentaryLoudness);
2525 drwav_buffer_reader_read_u16(&reader, &pMetadata->data.bext.maxShortTermLoudness);
2527 DRWAV_ASSERT((drwav_offset_ptr(drwav_buffer_reader_ptr(&reader), DRWAV_BEXT_RESERVED_BYTES)) == (bextData + DRWAV_BEXT_BYTES));
2529 extraBytes = (size_t)(chunkSize - DRWAV_BEXT_BYTES);
2530 if (extraBytes > 0) {
2531 pMetadata->data.bext.pCodingHistory = (
char*)drwav__metadata_get_memory(pParser, extraBytes + 1, 1);
2532 DRWAV_ASSERT(pMetadata->data.bext.pCodingHistory != NULL);
2534 bytesRead += drwav__metadata_parser_read(pParser, pMetadata->data.bext.pCodingHistory, extraBytes, NULL);
2535 pMetadata->data.bext.codingHistorySize = (drwav_uint32)drwav__strlen(pMetadata->data.bext.pCodingHistory);
2537 pMetadata->data.bext.pCodingHistory = NULL;
2538 pMetadata->data.bext.codingHistorySize = 0;
2546DRWAV_PRIVATE drwav_uint64 drwav__read_list_label_or_note_to_metadata_obj(drwav__metadata_parser* pParser,
drwav_metadata* pMetadata, drwav_uint64 chunkSize, drwav_metadata_type type)
2548 drwav_uint8 cueIDBuffer[DRWAV_LIST_LABEL_OR_NOTE_BYTES];
2549 drwav_uint64 totalBytesRead = 0;
2550 size_t bytesJustRead = drwav__metadata_parser_read(pParser, cueIDBuffer,
sizeof(cueIDBuffer), &totalBytesRead);
2552 DRWAV_ASSERT(pParser->stage == drwav__metadata_parser_stage_read);
2554 if (bytesJustRead ==
sizeof(cueIDBuffer)) {
2555 drwav_uint32 sizeIncludingNullTerminator;
2557 pMetadata->type = type;
2558 pMetadata->data.labelOrNote.cuePointId = drwav_bytes_to_u32(cueIDBuffer);
2560 sizeIncludingNullTerminator = (drwav_uint32)chunkSize - DRWAV_LIST_LABEL_OR_NOTE_BYTES;
2561 if (sizeIncludingNullTerminator > 0) {
2562 pMetadata->data.labelOrNote.stringLength = sizeIncludingNullTerminator - 1;
2563 pMetadata->data.labelOrNote.pString = (
char*)drwav__metadata_get_memory(pParser, sizeIncludingNullTerminator, 1);
2564 DRWAV_ASSERT(pMetadata->data.labelOrNote.pString != NULL);
2566 drwav__metadata_parser_read(pParser, pMetadata->data.labelOrNote.pString, sizeIncludingNullTerminator, &totalBytesRead);
2568 pMetadata->data.labelOrNote.stringLength = 0;
2569 pMetadata->data.labelOrNote.pString = NULL;
2573 return totalBytesRead;
2576DRWAV_PRIVATE drwav_uint64 drwav__read_list_labelled_cue_region_to_metadata_obj(drwav__metadata_parser* pParser,
drwav_metadata* pMetadata, drwav_uint64 chunkSize)
2578 drwav_uint8 buffer[DRWAV_LIST_LABELLED_TEXT_BYTES];
2579 drwav_uint64 totalBytesRead = 0;
2580 size_t bytesJustRead = drwav__metadata_parser_read(pParser, buffer,
sizeof(buffer), &totalBytesRead);
2582 DRWAV_ASSERT(pParser->stage == drwav__metadata_parser_stage_read);
2584 if (bytesJustRead ==
sizeof(buffer)) {
2585 drwav_uint32 sizeIncludingNullTerminator;
2587 pMetadata->type = drwav_metadata_type_list_labelled_cue_region;
2588 pMetadata->data.labelledCueRegion.cuePointId = drwav_bytes_to_u32(buffer + 0);
2589 pMetadata->data.labelledCueRegion.sampleLength = drwav_bytes_to_u32(buffer + 4);
2590 pMetadata->data.labelledCueRegion.purposeId[0] = buffer[8];
2591 pMetadata->data.labelledCueRegion.purposeId[1] = buffer[9];
2592 pMetadata->data.labelledCueRegion.purposeId[2] = buffer[10];
2593 pMetadata->data.labelledCueRegion.purposeId[3] = buffer[11];
2594 pMetadata->data.labelledCueRegion.country = drwav_bytes_to_u16(buffer + 12);
2595 pMetadata->data.labelledCueRegion.language = drwav_bytes_to_u16(buffer + 14);
2596 pMetadata->data.labelledCueRegion.dialect = drwav_bytes_to_u16(buffer + 16);
2597 pMetadata->data.labelledCueRegion.codePage = drwav_bytes_to_u16(buffer + 18);
2599 sizeIncludingNullTerminator = (drwav_uint32)chunkSize - DRWAV_LIST_LABELLED_TEXT_BYTES;
2600 if (sizeIncludingNullTerminator > 0) {
2601 pMetadata->data.labelledCueRegion.stringLength = sizeIncludingNullTerminator - 1;
2602 pMetadata->data.labelledCueRegion.pString = (
char*)drwav__metadata_get_memory(pParser, sizeIncludingNullTerminator, 1);
2603 DRWAV_ASSERT(pMetadata->data.labelledCueRegion.pString != NULL);
2605 drwav__metadata_parser_read(pParser, pMetadata->data.labelledCueRegion.pString, sizeIncludingNullTerminator, &totalBytesRead);
2607 pMetadata->data.labelledCueRegion.stringLength = 0;
2608 pMetadata->data.labelledCueRegion.pString = NULL;
2612 return totalBytesRead;
2615DRWAV_PRIVATE drwav_uint64 drwav__metadata_process_info_text_chunk(drwav__metadata_parser* pParser, drwav_uint64 chunkSize, drwav_metadata_type type)
2617 drwav_uint64 bytesRead = 0;
2618 drwav_uint32 stringSizeWithNullTerminator = (drwav_uint32)chunkSize;
2620 if (pParser->stage == drwav__metadata_parser_stage_count) {
2621 pParser->metadataCount += 1;
2622 drwav__metadata_request_extra_memory_for_stage_2(pParser, stringSizeWithNullTerminator, 1);
2624 drwav_metadata* pMetadata = &pParser->pMetadata[pParser->metadataCursor];
2625 pMetadata->type = type;
2626 if (stringSizeWithNullTerminator > 0) {
2627 pMetadata->data.infoText.stringLength = stringSizeWithNullTerminator - 1;
2628 pMetadata->data.infoText.pString = (
char*)drwav__metadata_get_memory(pParser, stringSizeWithNullTerminator, 1);
2629 DRWAV_ASSERT(pMetadata->data.infoText.pString != NULL);
2631 bytesRead = drwav__metadata_parser_read(pParser, pMetadata->data.infoText.pString, (
size_t)stringSizeWithNullTerminator, NULL);
2632 if (bytesRead == chunkSize) {
2633 pParser->metadataCursor += 1;
2638 pMetadata->data.infoText.stringLength = 0;
2639 pMetadata->data.infoText.pString = NULL;
2640 pParser->metadataCursor += 1;
2647DRWAV_PRIVATE drwav_uint64 drwav__metadata_process_unknown_chunk(drwav__metadata_parser* pParser,
const drwav_uint8* pChunkId, drwav_uint64 chunkSize, drwav_metadata_location location)
2649 drwav_uint64 bytesRead = 0;
2651 if (location == drwav_metadata_location_invalid) {
2655 if (drwav_fourcc_equal(pChunkId,
"data") || drwav_fourcc_equal(pChunkId,
"fmt ") || drwav_fourcc_equal(pChunkId,
"fact")) {
2659 if (pParser->stage == drwav__metadata_parser_stage_count) {
2660 pParser->metadataCount += 1;
2661 drwav__metadata_request_extra_memory_for_stage_2(pParser, (
size_t)chunkSize, 1);
2663 drwav_metadata* pMetadata = &pParser->pMetadata[pParser->metadataCursor];
2664 pMetadata->type = drwav_metadata_type_unknown;
2665 pMetadata->data.unknown.chunkLocation = location;
2666 pMetadata->data.unknown.id[0] = pChunkId[0];
2667 pMetadata->data.unknown.id[1] = pChunkId[1];
2668 pMetadata->data.unknown.id[2] = pChunkId[2];
2669 pMetadata->data.unknown.id[3] = pChunkId[3];
2670 pMetadata->data.unknown.dataSizeInBytes = (drwav_uint32)chunkSize;
2671 pMetadata->data.unknown.pData = (drwav_uint8 *)drwav__metadata_get_memory(pParser, (
size_t)chunkSize, 1);
2672 DRWAV_ASSERT(pMetadata->data.unknown.pData != NULL);
2674 bytesRead = drwav__metadata_parser_read(pParser, pMetadata->data.unknown.pData, pMetadata->data.unknown.dataSizeInBytes, NULL);
2675 if (bytesRead == pMetadata->data.unknown.dataSizeInBytes) {
2676 pParser->metadataCursor += 1;
2685DRWAV_PRIVATE drwav_bool32 drwav__chunk_matches(drwav_metadata_type allowedMetadataTypes,
const drwav_uint8* pChunkID, drwav_metadata_type type,
const char* pID)
2687 return (allowedMetadataTypes & type) && drwav_fourcc_equal(pChunkID, pID);
2690DRWAV_PRIVATE drwav_uint64 drwav__metadata_process_chunk(drwav__metadata_parser* pParser,
const drwav_chunk_header* pChunkHeader, drwav_metadata_type allowedMetadataTypes)
2692 const drwav_uint8 *pChunkID = pChunkHeader->id.fourcc;
2693 drwav_uint64 bytesRead = 0;
2695 if (drwav__chunk_matches(allowedMetadataTypes, pChunkID, drwav_metadata_type_smpl,
"smpl")) {
2696 if (pChunkHeader->sizeInBytes >= DRWAV_SMPL_BYTES) {
2697 if (pParser->stage == drwav__metadata_parser_stage_count) {
2698 drwav_uint8 buffer[4];
2699 size_t bytesJustRead;
2701 if (!pParser->onSeek(pParser->pReadSeekUserData, 28, drwav_seek_origin_current)) {
2706 bytesJustRead = drwav__metadata_parser_read(pParser, buffer,
sizeof(buffer), &bytesRead);
2707 if (bytesJustRead ==
sizeof(buffer)) {
2708 drwav_uint32 loopCount = drwav_bytes_to_u32(buffer);
2709 drwav_uint64 calculatedLoopCount;
2712 calculatedLoopCount = (pChunkHeader->sizeInBytes - DRWAV_SMPL_BYTES) / DRWAV_SMPL_LOOP_BYTES;
2713 if (calculatedLoopCount == loopCount) {
2714 bytesJustRead = drwav__metadata_parser_read(pParser, buffer,
sizeof(buffer), &bytesRead);
2715 if (bytesJustRead ==
sizeof(buffer)) {
2716 drwav_uint32 samplerSpecificDataSizeInBytes = drwav_bytes_to_u32(buffer);
2718 pParser->metadataCount += 1;
2719 drwav__metadata_request_extra_memory_for_stage_2(pParser,
sizeof(
drwav_smpl_loop) * loopCount, DRWAV_METADATA_ALIGNMENT);
2720 drwav__metadata_request_extra_memory_for_stage_2(pParser, samplerSpecificDataSizeInBytes, 1);
2727 bytesRead = drwav__read_smpl_to_metadata_obj(pParser, pChunkHeader, &pParser->pMetadata[pParser->metadataCursor]);
2728 if (bytesRead == pChunkHeader->sizeInBytes) {
2729 pParser->metadataCursor += 1;
2737 }
else if (drwav__chunk_matches(allowedMetadataTypes, pChunkID, drwav_metadata_type_inst,
"inst")) {
2738 if (pChunkHeader->sizeInBytes == DRWAV_INST_BYTES) {
2739 if (pParser->stage == drwav__metadata_parser_stage_count) {
2740 pParser->metadataCount += 1;
2742 bytesRead = drwav__read_inst_to_metadata_obj(pParser, &pParser->pMetadata[pParser->metadataCursor]);
2743 if (bytesRead == pChunkHeader->sizeInBytes) {
2744 pParser->metadataCursor += 1;
2752 }
else if (drwav__chunk_matches(allowedMetadataTypes, pChunkID, drwav_metadata_type_acid,
"acid")) {
2753 if (pChunkHeader->sizeInBytes == DRWAV_ACID_BYTES) {
2754 if (pParser->stage == drwav__metadata_parser_stage_count) {
2755 pParser->metadataCount += 1;
2757 bytesRead = drwav__read_acid_to_metadata_obj(pParser, &pParser->pMetadata[pParser->metadataCursor]);
2758 if (bytesRead == pChunkHeader->sizeInBytes) {
2759 pParser->metadataCursor += 1;
2767 }
else if (drwav__chunk_matches(allowedMetadataTypes, pChunkID, drwav_metadata_type_cue,
"cue ")) {
2768 if (pChunkHeader->sizeInBytes >= DRWAV_CUE_BYTES) {
2769 if (pParser->stage == drwav__metadata_parser_stage_count) {
2772 pParser->metadataCount += 1;
2773 cueCount = (size_t)(pChunkHeader->sizeInBytes - DRWAV_CUE_BYTES) / DRWAV_CUE_POINT_BYTES;
2774 drwav__metadata_request_extra_memory_for_stage_2(pParser,
sizeof(
drwav_cue_point) * cueCount, DRWAV_METADATA_ALIGNMENT);
2776 bytesRead = drwav__read_cue_to_metadata_obj(pParser, pChunkHeader, &pParser->pMetadata[pParser->metadataCursor]);
2777 if (bytesRead == pChunkHeader->sizeInBytes) {
2778 pParser->metadataCursor += 1;
2786 }
else if (drwav__chunk_matches(allowedMetadataTypes, pChunkID, drwav_metadata_type_bext,
"bext")) {
2787 if (pChunkHeader->sizeInBytes >= DRWAV_BEXT_BYTES) {
2788 if (pParser->stage == drwav__metadata_parser_stage_count) {
2790 char buffer[DRWAV_BEXT_DESCRIPTION_BYTES + 1];
2791 size_t allocSizeNeeded = DRWAV_BEXT_UMID_BYTES;
2792 size_t bytesJustRead;
2794 buffer[DRWAV_BEXT_DESCRIPTION_BYTES] =
'\0';
2795 bytesJustRead = drwav__metadata_parser_read(pParser, buffer, DRWAV_BEXT_DESCRIPTION_BYTES, &bytesRead);
2796 if (bytesJustRead != DRWAV_BEXT_DESCRIPTION_BYTES) {
2799 allocSizeNeeded += drwav__strlen(buffer) + 1;
2801 buffer[DRWAV_BEXT_ORIGINATOR_NAME_BYTES] =
'\0';
2802 bytesJustRead = drwav__metadata_parser_read(pParser, buffer, DRWAV_BEXT_ORIGINATOR_NAME_BYTES, &bytesRead);
2803 if (bytesJustRead != DRWAV_BEXT_ORIGINATOR_NAME_BYTES) {
2806 allocSizeNeeded += drwav__strlen(buffer) + 1;
2808 buffer[DRWAV_BEXT_ORIGINATOR_REF_BYTES] =
'\0';
2809 bytesJustRead = drwav__metadata_parser_read(pParser, buffer, DRWAV_BEXT_ORIGINATOR_REF_BYTES, &bytesRead);
2810 if (bytesJustRead != DRWAV_BEXT_ORIGINATOR_REF_BYTES) {
2813 allocSizeNeeded += drwav__strlen(buffer) + 1;
2814 allocSizeNeeded += (size_t)pChunkHeader->sizeInBytes - DRWAV_BEXT_BYTES;
2816 drwav__metadata_request_extra_memory_for_stage_2(pParser, allocSizeNeeded, 1);
2818 pParser->metadataCount += 1;
2820 bytesRead = drwav__read_bext_to_metadata_obj(pParser, &pParser->pMetadata[pParser->metadataCursor], pChunkHeader->sizeInBytes);
2821 if (bytesRead == pChunkHeader->sizeInBytes) {
2822 pParser->metadataCursor += 1;
2830 }
else if (drwav_fourcc_equal(pChunkID,
"LIST") || drwav_fourcc_equal(pChunkID,
"list")) {
2831 drwav_metadata_location listType = drwav_metadata_location_invalid;
2832 while (bytesRead < pChunkHeader->sizeInBytes) {
2833 drwav_uint8 subchunkId[4];
2834 drwav_uint8 subchunkSizeBuffer[4];
2835 drwav_uint64 subchunkDataSize;
2836 drwav_uint64 subchunkBytesRead = 0;
2837 drwav_uint64 bytesJustRead = drwav__metadata_parser_read(pParser, subchunkId,
sizeof(subchunkId), &bytesRead);
2838 if (bytesJustRead !=
sizeof(subchunkId)) {
2853 if (drwav_fourcc_equal(subchunkId,
"adtl")) {
2854 listType = drwav_metadata_location_inside_adtl_list;
2856 }
else if (drwav_fourcc_equal(subchunkId,
"INFO")) {
2857 listType = drwav_metadata_location_inside_info_list;
2861 bytesJustRead = drwav__metadata_parser_read(pParser, subchunkSizeBuffer,
sizeof(subchunkSizeBuffer), &bytesRead);
2862 if (bytesJustRead !=
sizeof(subchunkSizeBuffer)) {
2865 subchunkDataSize = drwav_bytes_to_u32(subchunkSizeBuffer);
2867 if (drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_label,
"labl") || drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_note,
"note")) {
2868 if (subchunkDataSize >= DRWAV_LIST_LABEL_OR_NOTE_BYTES) {
2869 drwav_uint64 stringSizeWithNullTerm = subchunkDataSize - DRWAV_LIST_LABEL_OR_NOTE_BYTES;
2870 if (pParser->stage == drwav__metadata_parser_stage_count) {
2871 pParser->metadataCount += 1;
2872 drwav__metadata_request_extra_memory_for_stage_2(pParser, (
size_t)stringSizeWithNullTerm, 1);
2874 subchunkBytesRead = drwav__read_list_label_or_note_to_metadata_obj(pParser, &pParser->pMetadata[pParser->metadataCursor], subchunkDataSize, drwav_fourcc_equal(subchunkId,
"labl") ? drwav_metadata_type_list_label : drwav_metadata_type_list_note);
2875 if (subchunkBytesRead == subchunkDataSize) {
2876 pParser->metadataCursor += 1;
2884 }
else if (drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_labelled_cue_region,
"ltxt")) {
2885 if (subchunkDataSize >= DRWAV_LIST_LABELLED_TEXT_BYTES) {
2886 drwav_uint64 stringSizeWithNullTerminator = subchunkDataSize - DRWAV_LIST_LABELLED_TEXT_BYTES;
2887 if (pParser->stage == drwav__metadata_parser_stage_count) {
2888 pParser->metadataCount += 1;
2889 drwav__metadata_request_extra_memory_for_stage_2(pParser, (
size_t)stringSizeWithNullTerminator, 1);
2891 subchunkBytesRead = drwav__read_list_labelled_cue_region_to_metadata_obj(pParser, &pParser->pMetadata[pParser->metadataCursor], subchunkDataSize);
2892 if (subchunkBytesRead == subchunkDataSize) {
2893 pParser->metadataCursor += 1;
2901 }
else if (drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_info_software,
"ISFT")) {
2902 subchunkBytesRead = drwav__metadata_process_info_text_chunk(pParser, subchunkDataSize, drwav_metadata_type_list_info_software);
2903 }
else if (drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_info_copyright,
"ICOP")) {
2904 subchunkBytesRead = drwav__metadata_process_info_text_chunk(pParser, subchunkDataSize, drwav_metadata_type_list_info_copyright);
2905 }
else if (drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_info_title,
"INAM")) {
2906 subchunkBytesRead = drwav__metadata_process_info_text_chunk(pParser, subchunkDataSize, drwav_metadata_type_list_info_title);
2907 }
else if (drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_info_artist,
"IART")) {
2908 subchunkBytesRead = drwav__metadata_process_info_text_chunk(pParser, subchunkDataSize, drwav_metadata_type_list_info_artist);
2909 }
else if (drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_info_comment,
"ICMT")) {
2910 subchunkBytesRead = drwav__metadata_process_info_text_chunk(pParser, subchunkDataSize, drwav_metadata_type_list_info_comment);
2911 }
else if (drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_info_date,
"ICRD")) {
2912 subchunkBytesRead = drwav__metadata_process_info_text_chunk(pParser, subchunkDataSize, drwav_metadata_type_list_info_date);
2913 }
else if (drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_info_genre,
"IGNR")) {
2914 subchunkBytesRead = drwav__metadata_process_info_text_chunk(pParser, subchunkDataSize, drwav_metadata_type_list_info_genre);
2915 }
else if (drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_info_album,
"IPRD")) {
2916 subchunkBytesRead = drwav__metadata_process_info_text_chunk(pParser, subchunkDataSize, drwav_metadata_type_list_info_album);
2917 }
else if (drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_info_tracknumber,
"ITRK")) {
2918 subchunkBytesRead = drwav__metadata_process_info_text_chunk(pParser, subchunkDataSize, drwav_metadata_type_list_info_tracknumber);
2919 }
else if ((allowedMetadataTypes & drwav_metadata_type_unknown) != 0) {
2920 subchunkBytesRead = drwav__metadata_process_unknown_chunk(pParser, subchunkId, subchunkDataSize, listType);
2923 bytesRead += subchunkBytesRead;
2924 DRWAV_ASSERT(subchunkBytesRead <= subchunkDataSize);
2926 if (subchunkBytesRead < subchunkDataSize) {
2927 drwav_uint64 bytesToSeek = subchunkDataSize - subchunkBytesRead;
2929 if (!pParser->onSeek(pParser->pReadSeekUserData, (
int)bytesToSeek, drwav_seek_origin_current)) {
2932 bytesRead += bytesToSeek;
2935 if ((subchunkDataSize % 2) == 1) {
2936 if (!pParser->onSeek(pParser->pReadSeekUserData, 1, drwav_seek_origin_current)) {
2942 }
else if ((allowedMetadataTypes & drwav_metadata_type_unknown) != 0) {
2943 bytesRead = drwav__metadata_process_unknown_chunk(pParser, pChunkID, pChunkHeader->sizeInBytes, drwav_metadata_location_top_level);
2950DRWAV_PRIVATE drwav_uint32 drwav_get_bytes_per_pcm_frame(
drwav* pWav)
2952 drwav_uint32 bytesPerFrame;
2958 if ((pWav->bitsPerSample & 0x7) == 0) {
2960 bytesPerFrame = (pWav->bitsPerSample * pWav->fmt.channels) >> 3;
2962 bytesPerFrame = pWav->fmt.blockAlign;
2966 if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ALAW || pWav->translatedFormatTag == DR_WAVE_FORMAT_MULAW) {
2967 if (bytesPerFrame != pWav->fmt.channels) {
2972 return bytesPerFrame;
2975DRWAV_API drwav_uint16 drwav_fmt_get_format(
const drwav_fmt* pFMT)
2981 if (pFMT->formatTag != DR_WAVE_FORMAT_EXTENSIBLE) {
2982 return pFMT->formatTag;
2984 return drwav_bytes_to_u16(pFMT->subFormat);
2988DRWAV_PRIVATE drwav_bool32 drwav_preinit(
drwav* pWav, drwav_read_proc onRead, drwav_seek_proc onSeek,
void* pReadSeekUserData,
const drwav_allocation_callbacks* pAllocationCallbacks)
2990 if (pWav == NULL || onRead == NULL || onSeek == NULL) {
2994 DRWAV_ZERO_MEMORY(pWav,
sizeof(*pWav));
2995 pWav->onRead = onRead;
2996 pWav->onSeek = onSeek;
2997 pWav->pUserData = pReadSeekUserData;
2998 pWav->allocationCallbacks = drwav_copy_allocation_callbacks_or_defaults(pAllocationCallbacks);
3000 if (pWav->allocationCallbacks.onFree == NULL || (pWav->allocationCallbacks.onMalloc == NULL && pWav->allocationCallbacks.onRealloc == NULL)) {
3007DRWAV_PRIVATE drwav_bool32 drwav_init__internal(
drwav* pWav, drwav_chunk_proc onChunk,
void* pChunkUserData, drwav_uint32 flags)
3010 drwav_result result;
3011 drwav_uint64 cursor;
3012 drwav_bool32 sequential;
3013 drwav_uint8 riff[4];
3015 unsigned short translatedFormatTag;
3016 drwav_uint64 dataChunkSize = 0;
3017 drwav_uint64 sampleCountFromFactChunk = 0;
3018 drwav_uint64 metadataStartPos;
3019 drwav__metadata_parser metadataParser;
3020 drwav_bool8 isProcessingMetadata = DRWAV_FALSE;
3021 drwav_bool8 foundChunk_fmt = DRWAV_FALSE;
3022 drwav_bool8 foundChunk_data = DRWAV_FALSE;
3023 drwav_bool8 isAIFCFormType = DRWAV_FALSE;
3024 drwav_uint64 aiffFrameCount = 0;
3027 sequential = (flags & DRWAV_SEQUENTIAL) != 0;
3028 DRWAV_ZERO_OBJECT(&fmt);
3031 if (drwav__on_read(pWav->onRead, pWav->pUserData, riff,
sizeof(riff), &cursor) !=
sizeof(riff)) {
3039 if (drwav_fourcc_equal(riff,
"RIFF")) {
3040 pWav->container = drwav_container_riff;
3041 }
else if (drwav_fourcc_equal(riff,
"RIFX")) {
3042 pWav->container = drwav_container_rifx;
3043 }
else if (drwav_fourcc_equal(riff,
"riff")) {
3045 drwav_uint8 riff2[12];
3047 pWav->container = drwav_container_w64;
3050 if (drwav__on_read(pWav->onRead, pWav->pUserData, riff2,
sizeof(riff2), &cursor) !=
sizeof(riff2)) {
3054 for (i = 0; i < 12; ++i) {
3055 if (riff2[i] != drwavGUID_W64_RIFF[i+4]) {
3059 }
else if (drwav_fourcc_equal(riff,
"RF64")) {
3060 pWav->container = drwav_container_rf64;
3061 }
else if (drwav_fourcc_equal(riff,
"FORM")) {
3062 pWav->container = drwav_container_aiff;
3068 if (pWav->container == drwav_container_riff || pWav->container == drwav_container_rifx || pWav->container == drwav_container_rf64) {
3069 drwav_uint8 chunkSizeBytes[4];
3070 drwav_uint8 wave[4];
3072 if (drwav__on_read(pWav->onRead, pWav->pUserData, chunkSizeBytes,
sizeof(chunkSizeBytes), &cursor) !=
sizeof(chunkSizeBytes)) {
3076 if (pWav->container == drwav_container_riff || pWav->container == drwav_container_rifx) {
3077 if (drwav_bytes_to_u32_ex(chunkSizeBytes, pWav->container) < 36) {
3086 }
else if (pWav->container == drwav_container_rf64) {
3087 if (drwav_bytes_to_u32_le(chunkSizeBytes) != 0xFFFFFFFF) {
3094 if (drwav__on_read(pWav->onRead, pWav->pUserData, wave,
sizeof(wave), &cursor) !=
sizeof(wave)) {
3098 if (!drwav_fourcc_equal(wave,
"WAVE")) {
3101 }
else if (pWav->container == drwav_container_w64) {
3102 drwav_uint8 chunkSizeBytes[8];
3103 drwav_uint8 wave[16];
3105 if (drwav__on_read(pWav->onRead, pWav->pUserData, chunkSizeBytes,
sizeof(chunkSizeBytes), &cursor) !=
sizeof(chunkSizeBytes)) {
3109 if (drwav_bytes_to_u64(chunkSizeBytes) < 80) {
3113 if (drwav__on_read(pWav->onRead, pWav->pUserData, wave,
sizeof(wave), &cursor) !=
sizeof(wave)) {
3117 if (!drwav_guid_equal(wave, drwavGUID_W64_WAVE)) {
3120 }
else if (pWav->container == drwav_container_aiff) {
3121 drwav_uint8 chunkSizeBytes[4];
3122 drwav_uint8 aiff[4];
3124 if (drwav__on_read(pWav->onRead, pWav->pUserData, chunkSizeBytes,
sizeof(chunkSizeBytes), &cursor) !=
sizeof(chunkSizeBytes)) {
3128 if (drwav_bytes_to_u32_be(chunkSizeBytes) < 18) {
3132 if (drwav__on_read(pWav->onRead, pWav->pUserData, aiff,
sizeof(aiff), &cursor) !=
sizeof(aiff)) {
3136 if (drwav_fourcc_equal(aiff,
"AIFF")) {
3137 isAIFCFormType = DRWAV_FALSE;
3138 }
else if (drwav_fourcc_equal(aiff,
"AIFC")) {
3139 isAIFCFormType = DRWAV_TRUE;
3149 if (pWav->container == drwav_container_rf64) {
3150 drwav_uint8 sizeBytes[8];
3151 drwav_uint64 bytesRemainingInChunk;
3153 result = drwav__read_chunk_header(pWav->onRead, pWav->pUserData, pWav->container, &cursor, &header);
3154 if (result != DRWAV_SUCCESS) {
3158 if (!drwav_fourcc_equal(header.id.fourcc,
"ds64")) {
3162 bytesRemainingInChunk = header.sizeInBytes + header.paddingSize;
3165 if (!drwav__seek_forward(pWav->onSeek, 8, pWav->pUserData)) {
3168 bytesRemainingInChunk -= 8;
3173 if (drwav__on_read(pWav->onRead, pWav->pUserData, sizeBytes,
sizeof(sizeBytes), &cursor) !=
sizeof(sizeBytes)) {
3176 bytesRemainingInChunk -= 8;
3177 dataChunkSize = drwav_bytes_to_u64(sizeBytes);
3181 if (drwav__on_read(pWav->onRead, pWav->pUserData, sizeBytes,
sizeof(sizeBytes), &cursor) !=
sizeof(sizeBytes)) {
3184 bytesRemainingInChunk -= 8;
3185 sampleCountFromFactChunk = drwav_bytes_to_u64(sizeBytes);
3189 if (!drwav__seek_forward(pWav->onSeek, bytesRemainingInChunk, pWav->pUserData)) {
3192 cursor += bytesRemainingInChunk;
3196 metadataStartPos = cursor;
3205 isProcessingMetadata = !sequential && ((flags & DRWAV_WITH_METADATA) != 0);
3208 if (pWav->container != drwav_container_riff && pWav->container != drwav_container_rf64) {
3209 isProcessingMetadata = DRWAV_FALSE;
3212 DRWAV_ZERO_MEMORY(&metadataParser,
sizeof(metadataParser));
3213 if (isProcessingMetadata) {
3214 metadataParser.onRead = pWav->onRead;
3215 metadataParser.onSeek = pWav->onSeek;
3216 metadataParser.pReadSeekUserData = pWav->pUserData;
3217 metadataParser.stage = drwav__metadata_parser_stage_count;
3228 drwav_uint64 chunkSize;
3230 result = drwav__read_chunk_header(pWav->onRead, pWav->pUserData, pWav->container, &cursor, &header);
3231 if (result != DRWAV_SUCCESS) {
3235 chunkSize = header.sizeInBytes;
3242 if (!sequential && onChunk != NULL) {
3243 drwav_uint64 callbackBytesRead = onChunk(pChunkUserData, pWav->onRead, pWav->onSeek, pWav->pUserData, &header, pWav->container, &fmt);
3249 if (callbackBytesRead > 0) {
3250 if (drwav__seek_from_start(pWav->onSeek, cursor, pWav->pUserData) == DRWAV_FALSE) {
3260 if (((pWav->container == drwav_container_riff || pWav->container == drwav_container_rifx || pWav->container == drwav_container_rf64) && drwav_fourcc_equal(header.id.fourcc,
"fmt ")) ||
3261 ((pWav->container == drwav_container_w64) && drwav_guid_equal(header.id.guid, drwavGUID_W64_FMT))) {
3262 drwav_uint8 fmtData[16];
3264 foundChunk_fmt = DRWAV_TRUE;
3266 if (pWav->onRead(pWav->pUserData, fmtData,
sizeof(fmtData)) !=
sizeof(fmtData)) {
3269 cursor +=
sizeof(fmtData);
3271 fmt.formatTag = drwav_bytes_to_u16_ex(fmtData + 0, pWav->container);
3272 fmt.channels = drwav_bytes_to_u16_ex(fmtData + 2, pWav->container);
3273 fmt.sampleRate = drwav_bytes_to_u32_ex(fmtData + 4, pWav->container);
3274 fmt.avgBytesPerSec = drwav_bytes_to_u32_ex(fmtData + 8, pWav->container);
3275 fmt.blockAlign = drwav_bytes_to_u16_ex(fmtData + 12, pWav->container);
3276 fmt.bitsPerSample = drwav_bytes_to_u16_ex(fmtData + 14, pWav->container);
3278 fmt.extendedSize = 0;
3279 fmt.validBitsPerSample = 0;
3280 fmt.channelMask = 0;
3281 DRWAV_ZERO_MEMORY(fmt.subFormat,
sizeof(fmt.subFormat));
3283 if (header.sizeInBytes > 16) {
3284 drwav_uint8 fmt_cbSize[2];
3285 int bytesReadSoFar = 0;
3287 if (pWav->onRead(pWav->pUserData, fmt_cbSize,
sizeof(fmt_cbSize)) !=
sizeof(fmt_cbSize)) {
3290 cursor +=
sizeof(fmt_cbSize);
3292 bytesReadSoFar = 18;
3294 fmt.extendedSize = drwav_bytes_to_u16_ex(fmt_cbSize, pWav->container);
3295 if (fmt.extendedSize > 0) {
3297 if (fmt.formatTag == DR_WAVE_FORMAT_EXTENSIBLE) {
3298 if (fmt.extendedSize != 22) {
3303 if (fmt.formatTag == DR_WAVE_FORMAT_EXTENSIBLE) {
3304 drwav_uint8 fmtext[22];
3306 if (pWav->onRead(pWav->pUserData, fmtext, fmt.extendedSize) != fmt.extendedSize) {
3310 fmt.validBitsPerSample = drwav_bytes_to_u16_ex(fmtext + 0, pWav->container);
3311 fmt.channelMask = drwav_bytes_to_u32_ex(fmtext + 2, pWav->container);
3312 drwav_bytes_to_guid(fmtext + 6, fmt.subFormat);
3314 if (pWav->onSeek(pWav->pUserData, fmt.extendedSize, drwav_seek_origin_current) == DRWAV_FALSE) {
3318 cursor += fmt.extendedSize;
3320 bytesReadSoFar += fmt.extendedSize;
3324 if (pWav->onSeek(pWav->pUserData, (
int)(header.sizeInBytes - bytesReadSoFar), drwav_seek_origin_current) == DRWAV_FALSE) {
3327 cursor += (header.sizeInBytes - bytesReadSoFar);
3330 if (header.paddingSize > 0) {
3331 if (drwav__seek_forward(pWav->onSeek, header.paddingSize, pWav->pUserData) == DRWAV_FALSE) {
3334 cursor += header.paddingSize;
3342 if (((pWav->container == drwav_container_riff || pWav->container == drwav_container_rifx || pWav->container == drwav_container_rf64) && drwav_fourcc_equal(header.id.fourcc,
"data")) ||
3343 ((pWav->container == drwav_container_w64) && drwav_guid_equal(header.id.guid, drwavGUID_W64_DATA))) {
3344 foundChunk_data = DRWAV_TRUE;
3346 pWav->dataChunkDataPos = cursor;
3348 if (pWav->container != drwav_container_rf64) {
3349 dataChunkSize = chunkSize;
3353 if (sequential || !isProcessingMetadata) {
3356 chunkSize += header.paddingSize;
3357 if (drwav__seek_forward(pWav->onSeek, chunkSize, pWav->pUserData) == DRWAV_FALSE) {
3360 cursor += chunkSize;
3367 if (((pWav->container == drwav_container_riff || pWav->container == drwav_container_rifx || pWav->container == drwav_container_rf64) && drwav_fourcc_equal(header.id.fourcc,
"fact")) ||
3368 ((pWav->container == drwav_container_w64) && drwav_guid_equal(header.id.guid, drwavGUID_W64_FACT))) {
3369 if (pWav->container == drwav_container_riff || pWav->container == drwav_container_rifx) {
3370 drwav_uint8 sampleCount[4];
3371 if (drwav__on_read(pWav->onRead, pWav->pUserData, &sampleCount, 4, &cursor) != 4) {
3381 if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ADPCM) {
3382 sampleCountFromFactChunk = drwav_bytes_to_u32_ex(sampleCount, pWav->container);
3384 sampleCountFromFactChunk = 0;
3386 }
else if (pWav->container == drwav_container_w64) {
3387 if (drwav__on_read(pWav->onRead, pWav->pUserData, &sampleCountFromFactChunk, 8, &cursor) != 8) {
3392 }
else if (pWav->container == drwav_container_rf64) {
3397 chunkSize += header.paddingSize;
3398 if (drwav__seek_forward(pWav->onSeek, chunkSize, pWav->pUserData) == DRWAV_FALSE) {
3401 cursor += chunkSize;
3408 if (pWav->container == drwav_container_aiff && drwav_fourcc_equal(header.id.fourcc,
"COMM")) {
3409 drwav_uint8 commData[24];
3410 drwav_uint32 commDataBytesToRead;
3411 drwav_uint16 channels;
3412 drwav_uint32 frameCount;
3413 drwav_uint16 sampleSizeInBits;
3414 drwav_int64 sampleRate;
3415 drwav_uint16 compressionFormat;
3417 foundChunk_fmt = DRWAV_TRUE;
3419 if (isAIFCFormType) {
3420 commDataBytesToRead = 24;
3421 if (header.sizeInBytes < commDataBytesToRead) {
3425 commDataBytesToRead = 18;
3426 if (header.sizeInBytes != commDataBytesToRead) {
3431 if (drwav__on_read(pWav->onRead, pWav->pUserData, commData, commDataBytesToRead, &cursor) != commDataBytesToRead) {
3436 channels = drwav_bytes_to_u16_ex (commData + 0, pWav->container);
3437 frameCount = drwav_bytes_to_u32_ex (commData + 2, pWav->container);
3438 sampleSizeInBits = drwav_bytes_to_u16_ex (commData + 6, pWav->container);
3439 sampleRate = drwav_aiff_extented_to_s64(commData + 8);
3441 if (sampleRate < 0 || sampleRate > 0xFFFFFFFF) {
3445 if (isAIFCFormType) {
3446 const drwav_uint8* type = commData + 18;
3448 if (drwav_fourcc_equal(type,
"NONE")) {
3449 compressionFormat = DR_WAVE_FORMAT_PCM;
3450 }
else if (drwav_fourcc_equal(type,
"raw ")) {
3451 compressionFormat = DR_WAVE_FORMAT_PCM;
3454 if (sampleSizeInBits == 8) {
3455 pWav->aiff.isUnsigned = DRWAV_TRUE;
3457 }
else if (drwav_fourcc_equal(type,
"sowt")) {
3458 compressionFormat = DR_WAVE_FORMAT_PCM;
3459 pWav->aiff.isLE = DRWAV_TRUE;
3460 }
else if (drwav_fourcc_equal(type,
"fl32") || drwav_fourcc_equal(type,
"fl64") || drwav_fourcc_equal(type,
"FL32") || drwav_fourcc_equal(type,
"FL64")) {
3461 compressionFormat = DR_WAVE_FORMAT_IEEE_FLOAT;
3462 }
else if (drwav_fourcc_equal(type,
"alaw") || drwav_fourcc_equal(type,
"ALAW")) {
3463 compressionFormat = DR_WAVE_FORMAT_ALAW;
3464 }
else if (drwav_fourcc_equal(type,
"ulaw") || drwav_fourcc_equal(type,
"ULAW")) {
3465 compressionFormat = DR_WAVE_FORMAT_MULAW;
3466 }
else if (drwav_fourcc_equal(type,
"ima4")) {
3467 compressionFormat = DR_WAVE_FORMAT_DVI_ADPCM;
3468 sampleSizeInBits = 4;
3479 compressionFormat = DR_WAVE_FORMAT_PCM;
3483 aiffFrameCount = frameCount;
3486 fmt.formatTag = compressionFormat;
3487 fmt.channels = channels;
3488 fmt.sampleRate = (drwav_uint32)sampleRate;
3489 fmt.bitsPerSample = sampleSizeInBits;
3490 fmt.blockAlign = (drwav_uint16)(fmt.channels * fmt.bitsPerSample / 8);
3491 fmt.avgBytesPerSec = fmt.blockAlign * fmt.sampleRate;
3493 if (fmt.blockAlign == 0 && compressionFormat == DR_WAVE_FORMAT_DVI_ADPCM) {
3494 fmt.blockAlign = 34 * fmt.channels;
3501 if (compressionFormat == DR_WAVE_FORMAT_ALAW || compressionFormat == DR_WAVE_FORMAT_MULAW) {
3502 if (fmt.bitsPerSample > 8) {
3503 fmt.bitsPerSample = 8;
3504 fmt.blockAlign = fmt.channels;
3509 fmt.bitsPerSample += (fmt.bitsPerSample & 7);
3513 if (isAIFCFormType) {
3514 if (drwav__seek_forward(pWav->onSeek, (chunkSize - commDataBytesToRead), pWav->pUserData) == DRWAV_FALSE) {
3517 cursor += (chunkSize - commDataBytesToRead);
3526 if (pWav->container == drwav_container_aiff && drwav_fourcc_equal(header.id.fourcc,
"SSND")) {
3527 drwav_uint8 offsetAndBlockSizeData[8];
3528 drwav_uint32 offset;
3530 foundChunk_data = DRWAV_TRUE;
3532 if (drwav__on_read(pWav->onRead, pWav->pUserData, offsetAndBlockSizeData,
sizeof(offsetAndBlockSizeData), &cursor) !=
sizeof(offsetAndBlockSizeData)) {
3537 offset = drwav_bytes_to_u32_ex(offsetAndBlockSizeData + 0, pWav->container);
3538 if (drwav__seek_forward(pWav->onSeek, offset, pWav->pUserData) == DRWAV_FALSE) {
3543 pWav->dataChunkDataPos = cursor;
3544 dataChunkSize = chunkSize;
3547 if (sequential || !isProcessingMetadata) {
3550 if (drwav__seek_forward(pWav->onSeek, chunkSize, pWav->pUserData) == DRWAV_FALSE) {
3553 cursor += chunkSize;
3562 if (isProcessingMetadata) {
3563 drwav__metadata_process_chunk(&metadataParser, &header, drwav_metadata_type_all_including_unknown);
3566 if (drwav__seek_from_start(pWav->onSeek, cursor, pWav->pUserData) == DRWAV_FALSE) {
3573 chunkSize += header.paddingSize;
3574 if (drwav__seek_forward(pWav->onSeek, chunkSize, pWav->pUserData) == DRWAV_FALSE) {
3577 cursor += chunkSize;
3581 if (!foundChunk_fmt || !foundChunk_data) {
3586 if ((fmt.sampleRate == 0 || fmt.sampleRate > DRWAV_MAX_SAMPLE_RATE ) ||
3587 (fmt.channels == 0 || fmt.channels > DRWAV_MAX_CHANNELS ) ||
3588 (fmt.bitsPerSample == 0 || fmt.bitsPerSample > DRWAV_MAX_BITS_PER_SAMPLE) ||
3589 fmt.blockAlign == 0) {
3594 translatedFormatTag = fmt.formatTag;
3595 if (translatedFormatTag == DR_WAVE_FORMAT_EXTENSIBLE) {
3596 translatedFormatTag = drwav_bytes_to_u16_ex(fmt.subFormat + 0, pWav->container);
3601 if (!drwav__seek_from_start(pWav->onSeek, pWav->dataChunkDataPos, pWav->pUserData)) {
3604 cursor = pWav->dataChunkDataPos;
3615 if (isProcessingMetadata && metadataParser.metadataCount > 0) {
3616 if (drwav__seek_from_start(pWav->onSeek, metadataStartPos, pWav->pUserData) == DRWAV_FALSE) {
3620 result = drwav__metadata_alloc(&metadataParser, &pWav->allocationCallbacks);
3621 if (result != DRWAV_SUCCESS) {
3625 metadataParser.stage = drwav__metadata_parser_stage_read;
3629 drwav_uint64 metadataBytesRead;
3631 result = drwav__read_chunk_header(pWav->onRead, pWav->pUserData, pWav->container, &cursor, &header);
3632 if (result != DRWAV_SUCCESS) {
3636 metadataBytesRead = drwav__metadata_process_chunk(&metadataParser, &header, drwav_metadata_type_all_including_unknown);
3639 if (drwav__seek_forward(pWav->onSeek, (header.sizeInBytes + header.paddingSize) - metadataBytesRead, pWav->pUserData) == DRWAV_FALSE) {
3640 drwav_free(metadataParser.pMetadata, &pWav->allocationCallbacks);
3646 pWav->pMetadata = metadataParser.pMetadata;
3647 pWav->metadataCount = metadataParser.metadataCount;
3659 if (dataChunkSize == 0xFFFFFFFF && (pWav->container == drwav_container_riff || pWav->container == drwav_container_rifx) && pWav->isSequentialWrite == DRWAV_FALSE) {
3663 drwav_uint8 temp[4096];
3664 size_t bytesRead = pWav->onRead(pWav->pUserData, temp,
sizeof(temp));
3665 dataChunkSize += bytesRead;
3667 if (bytesRead <
sizeof(temp)) {
3673 if (drwav__seek_from_start(pWav->onSeek, pWav->dataChunkDataPos, pWav->pUserData) == DRWAV_FALSE) {
3674 drwav_free(pWav->pMetadata, &pWav->allocationCallbacks);
3680 pWav->sampleRate = fmt.sampleRate;
3681 pWav->channels = fmt.channels;
3682 pWav->bitsPerSample = fmt.bitsPerSample;
3683 pWav->bytesRemaining = dataChunkSize;
3684 pWav->translatedFormatTag = translatedFormatTag;
3685 pWav->dataChunkDataSize = dataChunkSize;
3687 if (sampleCountFromFactChunk != 0) {
3688 pWav->totalPCMFrameCount = sampleCountFromFactChunk;
3689 }
else if (aiffFrameCount != 0) {
3690 pWav->totalPCMFrameCount = aiffFrameCount;
3692 drwav_uint32 bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
3693 if (bytesPerFrame == 0) {
3694 drwav_free(pWav->pMetadata, &pWav->allocationCallbacks);
3698 pWav->totalPCMFrameCount = dataChunkSize / bytesPerFrame;
3700 if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ADPCM) {
3701 drwav_uint64 totalBlockHeaderSizeInBytes;
3702 drwav_uint64 blockCount = dataChunkSize / fmt.blockAlign;
3705 if ((blockCount * fmt.blockAlign) < dataChunkSize) {
3710 totalBlockHeaderSizeInBytes = blockCount * (6*fmt.channels);
3711 pWav->totalPCMFrameCount = ((dataChunkSize - totalBlockHeaderSizeInBytes) * 2) / fmt.channels;
3713 if (pWav->translatedFormatTag == DR_WAVE_FORMAT_DVI_ADPCM) {
3714 drwav_uint64 totalBlockHeaderSizeInBytes;
3715 drwav_uint64 blockCount = dataChunkSize / fmt.blockAlign;
3718 if ((blockCount * fmt.blockAlign) < dataChunkSize) {
3723 totalBlockHeaderSizeInBytes = blockCount * (4*fmt.channels);
3724 pWav->totalPCMFrameCount = ((dataChunkSize - totalBlockHeaderSizeInBytes) * 2) / fmt.channels;
3727 pWav->totalPCMFrameCount += blockCount;
3732 if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ADPCM || pWav->translatedFormatTag == DR_WAVE_FORMAT_DVI_ADPCM) {
3733 if (pWav->channels > 2) {
3734 drwav_free(pWav->pMetadata, &pWav->allocationCallbacks);
3740 if (drwav_get_bytes_per_pcm_frame(pWav) == 0) {
3741 drwav_free(pWav->pMetadata, &pWav->allocationCallbacks);
3745#ifdef DR_WAV_LIBSNDFILE_COMPAT
3754 if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ADPCM) {
3755 drwav_uint64 blockCount = dataChunkSize / fmt.blockAlign;
3756 pWav->totalPCMFrameCount = (((blockCount * (fmt.blockAlign - (6*pWav->channels))) * 2)) / fmt.channels;
3758 if (pWav->translatedFormatTag == DR_WAVE_FORMAT_DVI_ADPCM) {
3759 drwav_uint64 blockCount = dataChunkSize / fmt.blockAlign;
3760 pWav->totalPCMFrameCount = (((blockCount * (fmt.blockAlign - (4*pWav->channels))) * 2) + (blockCount * pWav->channels)) / fmt.channels;
3767DRWAV_API drwav_bool32 drwav_init(
drwav* pWav, drwav_read_proc onRead, drwav_seek_proc onSeek,
void* pUserData,
const drwav_allocation_callbacks* pAllocationCallbacks)
3769 return drwav_init_ex(pWav, onRead, onSeek, NULL, pUserData, NULL, 0, pAllocationCallbacks);
3772DRWAV_API drwav_bool32 drwav_init_ex(
drwav* pWav, drwav_read_proc onRead, drwav_seek_proc onSeek, drwav_chunk_proc onChunk,
void* pReadSeekUserData,
void* pChunkUserData, drwav_uint32 flags,
const drwav_allocation_callbacks* pAllocationCallbacks)
3774 if (!drwav_preinit(pWav, onRead, onSeek, pReadSeekUserData, pAllocationCallbacks)) {
3778 return drwav_init__internal(pWav, onChunk, pChunkUserData, flags);
3781DRWAV_API drwav_bool32 drwav_init_with_metadata(
drwav* pWav, drwav_read_proc onRead, drwav_seek_proc onSeek,
void* pUserData, drwav_uint32 flags,
const drwav_allocation_callbacks* pAllocationCallbacks)
3783 if (!drwav_preinit(pWav, onRead, onSeek, pUserData, pAllocationCallbacks)) {
3787 return drwav_init__internal(pWav, NULL, NULL, flags | DRWAV_WITH_METADATA);
3794 pWav->pMetadata = NULL;
3795 pWav->metadataCount = 0;
3801DRWAV_PRIVATE
size_t drwav__write(
drwav* pWav,
const void* pData,
size_t dataSize)
3803 DRWAV_ASSERT(pWav != NULL);
3804 DRWAV_ASSERT(pWav->onWrite != NULL);
3807 return pWav->onWrite(pWav->pUserData, pData, dataSize);
3810DRWAV_PRIVATE
size_t drwav__write_byte(
drwav* pWav, drwav_uint8
byte)
3812 DRWAV_ASSERT(pWav != NULL);
3813 DRWAV_ASSERT(pWav->onWrite != NULL);
3815 return pWav->onWrite(pWav->pUserData, &
byte, 1);
3818DRWAV_PRIVATE
size_t drwav__write_u16ne_to_le(
drwav* pWav, drwav_uint16 value)
3820 DRWAV_ASSERT(pWav != NULL);
3821 DRWAV_ASSERT(pWav->onWrite != NULL);
3823 if (!drwav__is_little_endian()) {
3824 value = drwav__bswap16(value);
3827 return drwav__write(pWav, &value, 2);
3830DRWAV_PRIVATE
size_t drwav__write_u32ne_to_le(
drwav* pWav, drwav_uint32 value)
3832 DRWAV_ASSERT(pWav != NULL);
3833 DRWAV_ASSERT(pWav->onWrite != NULL);
3835 if (!drwav__is_little_endian()) {
3836 value = drwav__bswap32(value);
3839 return drwav__write(pWav, &value, 4);
3842DRWAV_PRIVATE
size_t drwav__write_u64ne_to_le(
drwav* pWav, drwav_uint64 value)
3844 DRWAV_ASSERT(pWav != NULL);
3845 DRWAV_ASSERT(pWav->onWrite != NULL);
3847 if (!drwav__is_little_endian()) {
3848 value = drwav__bswap64(value);
3851 return drwav__write(pWav, &value, 8);
3854DRWAV_PRIVATE
size_t drwav__write_f32ne_to_le(
drwav* pWav,
float value)
3861 DRWAV_ASSERT(pWav != NULL);
3862 DRWAV_ASSERT(pWav->onWrite != NULL);
3866 if (!drwav__is_little_endian()) {
3867 u.u32 = drwav__bswap32(u.u32);
3870 return drwav__write(pWav, &u.u32, 4);
3873DRWAV_PRIVATE
size_t drwav__write_or_count(
drwav* pWav,
const void* pData,
size_t dataSize)
3879 return drwav__write(pWav, pData, dataSize);
3882DRWAV_PRIVATE
size_t drwav__write_or_count_byte(
drwav* pWav, drwav_uint8
byte)
3888 return drwav__write_byte(pWav,
byte);
3891DRWAV_PRIVATE
size_t drwav__write_or_count_u16ne_to_le(
drwav* pWav, drwav_uint16 value)
3897 return drwav__write_u16ne_to_le(pWav, value);
3900DRWAV_PRIVATE
size_t drwav__write_or_count_u32ne_to_le(
drwav* pWav, drwav_uint32 value)
3906 return drwav__write_u32ne_to_le(pWav, value);
3910DRWAV_PRIVATE
size_t drwav__write_or_count_u64ne_to_le(
drwav* pWav, drwav_uint64 value)
3916 return drwav__write_u64ne_to_le(pWav, value);
3920DRWAV_PRIVATE
size_t drwav__write_or_count_f32ne_to_le(
drwav* pWav,
float value)
3926 return drwav__write_f32ne_to_le(pWav, value);
3929DRWAV_PRIVATE
size_t drwav__write_or_count_string_to_fixed_size_buf(
drwav* pWav,
char* str,
size_t bufFixedSize)
3934 return bufFixedSize;
3937 len = drwav__strlen_clamped(str, bufFixedSize);
3938 drwav__write_or_count(pWav, str, len);
3940 if (len < bufFixedSize) {
3942 for (i = 0; i < bufFixedSize - len; ++i) {
3943 drwav__write_byte(pWav, 0);
3947 return bufFixedSize;
3952DRWAV_PRIVATE
size_t drwav__write_or_count_metadata(
drwav* pWav,
drwav_metadata* pMetadatas, drwav_uint32 metadataCount)
3954 size_t bytesWritten = 0;
3955 drwav_bool32 hasListAdtl = DRWAV_FALSE;
3956 drwav_bool32 hasListInfo = DRWAV_FALSE;
3957 drwav_uint32 iMetadata;
3959 if (pMetadatas == NULL || metadataCount == 0) {
3963 for (iMetadata = 0; iMetadata < metadataCount; ++iMetadata) {
3965 drwav_uint32 chunkSize = 0;
3967 if ((pMetadata->type & drwav_metadata_type_list_all_info_strings) || (pMetadata->type == drwav_metadata_type_unknown && pMetadata->data.unknown.chunkLocation == drwav_metadata_location_inside_info_list)) {
3968 hasListInfo = DRWAV_TRUE;
3971 if ((pMetadata->type & drwav_metadata_type_list_all_adtl) || (pMetadata->type == drwav_metadata_type_unknown && pMetadata->data.unknown.chunkLocation == drwav_metadata_location_inside_adtl_list)) {
3972 hasListAdtl = DRWAV_TRUE;
3975 switch (pMetadata->type) {
3976 case drwav_metadata_type_smpl:
3980 chunkSize = DRWAV_SMPL_BYTES + DRWAV_SMPL_LOOP_BYTES * pMetadata->data.smpl.sampleLoopCount + pMetadata->data.smpl.samplerSpecificDataSizeInBytes;
3982 bytesWritten += drwav__write_or_count(pWav,
"smpl", 4);
3983 bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, chunkSize);
3985 bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.manufacturerId);
3986 bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.productId);
3987 bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.samplePeriodNanoseconds);
3988 bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.midiUnityNote);
3989 bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.midiPitchFraction);
3990 bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.smpteFormat);
3991 bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.smpteOffset);
3992 bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.sampleLoopCount);
3993 bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.samplerSpecificDataSizeInBytes);
3995 for (iLoop = 0; iLoop < pMetadata->data.smpl.sampleLoopCount; ++iLoop) {
3996 bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.pLoops[iLoop].cuePointId);
3997 bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.pLoops[iLoop].type);
3998 bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.pLoops[iLoop].firstSampleByteOffset);
3999 bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.pLoops[iLoop].lastSampleByteOffset);
4000 bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.pLoops[iLoop].sampleFraction);
4001 bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.pLoops[iLoop].playCount);
4004 if (pMetadata->data.smpl.samplerSpecificDataSizeInBytes > 0) {
4005 bytesWritten += drwav__write_or_count(pWav, pMetadata->data.smpl.pSamplerSpecificData, pMetadata->data.smpl.samplerSpecificDataSizeInBytes);
4009 case drwav_metadata_type_inst:
4011 chunkSize = DRWAV_INST_BYTES;
4013 bytesWritten += drwav__write_or_count(pWav,
"inst", 4);
4014 bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, chunkSize);
4015 bytesWritten += drwav__write_or_count(pWav, &pMetadata->data.inst.midiUnityNote, 1);
4016 bytesWritten += drwav__write_or_count(pWav, &pMetadata->data.inst.fineTuneCents, 1);
4017 bytesWritten += drwav__write_or_count(pWav, &pMetadata->data.inst.gainDecibels, 1);
4018 bytesWritten += drwav__write_or_count(pWav, &pMetadata->data.inst.lowNote, 1);
4019 bytesWritten += drwav__write_or_count(pWav, &pMetadata->data.inst.highNote, 1);
4020 bytesWritten += drwav__write_or_count(pWav, &pMetadata->data.inst.lowVelocity, 1);
4021 bytesWritten += drwav__write_or_count(pWav, &pMetadata->data.inst.highVelocity, 1);
4024 case drwav_metadata_type_cue:
4026 drwav_uint32 iCuePoint;
4028 chunkSize = DRWAV_CUE_BYTES + DRWAV_CUE_POINT_BYTES * pMetadata->data.cue.cuePointCount;
4030 bytesWritten += drwav__write_or_count(pWav,
"cue ", 4);
4031 bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, chunkSize);
4032 bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.cue.cuePointCount);
4033 for (iCuePoint = 0; iCuePoint < pMetadata->data.cue.cuePointCount; ++iCuePoint) {
4034 bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.cue.pCuePoints[iCuePoint].id);
4035 bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.cue.pCuePoints[iCuePoint].playOrderPosition);
4036 bytesWritten += drwav__write_or_count(pWav, pMetadata->data.cue.pCuePoints[iCuePoint].dataChunkId, 4);
4037 bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.cue.pCuePoints[iCuePoint].chunkStart);
4038 bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.cue.pCuePoints[iCuePoint].blockStart);
4039 bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.cue.pCuePoints[iCuePoint].sampleByteOffset);
4043 case drwav_metadata_type_acid:
4045 chunkSize = DRWAV_ACID_BYTES;
4047 bytesWritten += drwav__write_or_count(pWav,
"acid", 4);
4048 bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, chunkSize);
4049 bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.acid.flags);
4050 bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.acid.midiUnityNote);
4051 bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.acid.reserved1);
4052 bytesWritten += drwav__write_or_count_f32ne_to_le(pWav, pMetadata->data.acid.reserved2);
4053 bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.acid.numBeats);
4054 bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.acid.meterDenominator);
4055 bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.acid.meterNumerator);
4056 bytesWritten += drwav__write_or_count_f32ne_to_le(pWav, pMetadata->data.acid.tempo);
4059 case drwav_metadata_type_bext:
4061 char reservedBuf[DRWAV_BEXT_RESERVED_BYTES];
4062 drwav_uint32 timeReferenceLow;
4063 drwav_uint32 timeReferenceHigh;
4065 chunkSize = DRWAV_BEXT_BYTES + pMetadata->data.bext.codingHistorySize;
4067 bytesWritten += drwav__write_or_count(pWav,
"bext", 4);
4068 bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, chunkSize);
4070 bytesWritten += drwav__write_or_count_string_to_fixed_size_buf(pWav, pMetadata->data.bext.pDescription, DRWAV_BEXT_DESCRIPTION_BYTES);
4071 bytesWritten += drwav__write_or_count_string_to_fixed_size_buf(pWav, pMetadata->data.bext.pOriginatorName, DRWAV_BEXT_ORIGINATOR_NAME_BYTES);
4072 bytesWritten += drwav__write_or_count_string_to_fixed_size_buf(pWav, pMetadata->data.bext.pOriginatorReference, DRWAV_BEXT_ORIGINATOR_REF_BYTES);
4073 bytesWritten += drwav__write_or_count(pWav, pMetadata->data.bext.pOriginationDate,
sizeof(pMetadata->data.bext.pOriginationDate));
4074 bytesWritten += drwav__write_or_count(pWav, pMetadata->data.bext.pOriginationTime,
sizeof(pMetadata->data.bext.pOriginationTime));
4076 timeReferenceLow = (drwav_uint32)(pMetadata->data.bext.timeReference & 0xFFFFFFFF);
4077 timeReferenceHigh = (drwav_uint32)(pMetadata->data.bext.timeReference >> 32);
4078 bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, timeReferenceLow);
4079 bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, timeReferenceHigh);
4081 bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.bext.version);
4082 bytesWritten += drwav__write_or_count(pWav, pMetadata->data.bext.pUMID, DRWAV_BEXT_UMID_BYTES);
4083 bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.bext.loudnessValue);
4084 bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.bext.loudnessRange);
4085 bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.bext.maxTruePeakLevel);
4086 bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.bext.maxMomentaryLoudness);
4087 bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.bext.maxShortTermLoudness);
4089 DRWAV_ZERO_MEMORY(reservedBuf,
sizeof(reservedBuf));
4090 bytesWritten += drwav__write_or_count(pWav, reservedBuf,
sizeof(reservedBuf));
4092 if (pMetadata->data.bext.codingHistorySize > 0) {
4093 bytesWritten += drwav__write_or_count(pWav, pMetadata->data.bext.pCodingHistory, pMetadata->data.bext.codingHistorySize);
4097 case drwav_metadata_type_unknown:
4099 if (pMetadata->data.unknown.chunkLocation == drwav_metadata_location_top_level) {
4100 chunkSize = pMetadata->data.unknown.dataSizeInBytes;
4102 bytesWritten += drwav__write_or_count(pWav, pMetadata->data.unknown.id, 4);
4103 bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, chunkSize);
4104 bytesWritten += drwav__write_or_count(pWav, pMetadata->data.unknown.pData, pMetadata->data.unknown.dataSizeInBytes);
4110 if ((chunkSize % 2) != 0) {
4111 bytesWritten += drwav__write_or_count_byte(pWav, 0);
4116 drwav_uint32 chunkSize = 4;
4117 for (iMetadata = 0; iMetadata < metadataCount; ++iMetadata) {
4120 if ((pMetadata->type & drwav_metadata_type_list_all_info_strings)) {
4122 chunkSize += pMetadata->data.infoText.stringLength + 1;
4123 }
else if (pMetadata->type == drwav_metadata_type_unknown && pMetadata->data.unknown.chunkLocation == drwav_metadata_location_inside_info_list) {
4125 chunkSize += pMetadata->data.unknown.dataSizeInBytes;
4128 if ((chunkSize % 2) != 0) {
4133 bytesWritten += drwav__write_or_count(pWav,
"LIST", 4);
4134 bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, chunkSize);
4135 bytesWritten += drwav__write_or_count(pWav,
"INFO", 4);
4137 for (iMetadata = 0; iMetadata < metadataCount; ++iMetadata) {
4139 drwav_uint32 subchunkSize = 0;
4141 if (pMetadata->type & drwav_metadata_type_list_all_info_strings) {
4142 const char* pID = NULL;
4144 switch (pMetadata->type) {
4145 case drwav_metadata_type_list_info_software: pID =
"ISFT";
break;
4146 case drwav_metadata_type_list_info_copyright: pID =
"ICOP";
break;
4147 case drwav_metadata_type_list_info_title: pID =
"INAM";
break;
4148 case drwav_metadata_type_list_info_artist: pID =
"IART";
break;
4149 case drwav_metadata_type_list_info_comment: pID =
"ICMT";
break;
4150 case drwav_metadata_type_list_info_date: pID =
"ICRD";
break;
4151 case drwav_metadata_type_list_info_genre: pID =
"IGNR";
break;
4152 case drwav_metadata_type_list_info_album: pID =
"IPRD";
break;
4153 case drwav_metadata_type_list_info_tracknumber: pID =
"ITRK";
break;
4157 DRWAV_ASSERT(pID != NULL);
4159 if (pMetadata->data.infoText.stringLength) {
4160 subchunkSize = pMetadata->data.infoText.stringLength + 1;
4161 bytesWritten += drwav__write_or_count(pWav, pID, 4);
4162 bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, subchunkSize);
4163 bytesWritten += drwav__write_or_count(pWav, pMetadata->data.infoText.pString, pMetadata->data.infoText.stringLength);
4164 bytesWritten += drwav__write_or_count_byte(pWav,
'\0');
4166 }
else if (pMetadata->type == drwav_metadata_type_unknown && pMetadata->data.unknown.chunkLocation == drwav_metadata_location_inside_info_list) {
4167 if (pMetadata->data.unknown.dataSizeInBytes) {
4168 subchunkSize = pMetadata->data.unknown.dataSizeInBytes;
4170 bytesWritten += drwav__write_or_count(pWav, pMetadata->data.unknown.id, 4);
4171 bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.unknown.dataSizeInBytes);
4172 bytesWritten += drwav__write_or_count(pWav, pMetadata->data.unknown.pData, subchunkSize);
4176 if ((subchunkSize % 2) != 0) {
4177 bytesWritten += drwav__write_or_count_byte(pWav, 0);
4183 drwav_uint32 chunkSize = 4;
4185 for (iMetadata = 0; iMetadata < metadataCount; ++iMetadata) {
4188 switch (pMetadata->type)
4190 case drwav_metadata_type_list_label:
4191 case drwav_metadata_type_list_note:
4194 chunkSize += DRWAV_LIST_LABEL_OR_NOTE_BYTES;
4196 if (pMetadata->data.labelOrNote.stringLength > 0) {
4197 chunkSize += pMetadata->data.labelOrNote.stringLength + 1;
4201 case drwav_metadata_type_list_labelled_cue_region:
4204 chunkSize += DRWAV_LIST_LABELLED_TEXT_BYTES;
4206 if (pMetadata->data.labelledCueRegion.stringLength > 0) {
4207 chunkSize += pMetadata->data.labelledCueRegion.stringLength + 1;
4211 case drwav_metadata_type_unknown:
4213 if (pMetadata->data.unknown.chunkLocation == drwav_metadata_location_inside_adtl_list) {
4215 chunkSize += pMetadata->data.unknown.dataSizeInBytes;
4222 if ((chunkSize % 2) != 0) {
4227 bytesWritten += drwav__write_or_count(pWav,
"LIST", 4);
4228 bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, chunkSize);
4229 bytesWritten += drwav__write_or_count(pWav,
"adtl", 4);
4231 for (iMetadata = 0; iMetadata < metadataCount; ++iMetadata) {
4233 drwav_uint32 subchunkSize = 0;
4235 switch (pMetadata->type)
4237 case drwav_metadata_type_list_label:
4238 case drwav_metadata_type_list_note:
4240 if (pMetadata->data.labelOrNote.stringLength > 0) {
4241 const char *pID = NULL;
4243 if (pMetadata->type == drwav_metadata_type_list_label) {
4246 else if (pMetadata->type == drwav_metadata_type_list_note) {
4250 DRWAV_ASSERT(pID != NULL);
4251 DRWAV_ASSERT(pMetadata->data.labelOrNote.pString != NULL);
4253 subchunkSize = DRWAV_LIST_LABEL_OR_NOTE_BYTES;
4255 bytesWritten += drwav__write_or_count(pWav, pID, 4);
4256 subchunkSize += pMetadata->data.labelOrNote.stringLength + 1;
4257 bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, subchunkSize);
4259 bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.labelOrNote.cuePointId);
4260 bytesWritten += drwav__write_or_count(pWav, pMetadata->data.labelOrNote.pString, pMetadata->data.labelOrNote.stringLength);
4261 bytesWritten += drwav__write_or_count_byte(pWav,
'\0');
4265 case drwav_metadata_type_list_labelled_cue_region:
4267 subchunkSize = DRWAV_LIST_LABELLED_TEXT_BYTES;
4269 bytesWritten += drwav__write_or_count(pWav,
"ltxt", 4);
4270 if (pMetadata->data.labelledCueRegion.stringLength > 0) {
4271 subchunkSize += pMetadata->data.labelledCueRegion.stringLength + 1;
4273 bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, subchunkSize);
4274 bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.labelledCueRegion.cuePointId);
4275 bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.labelledCueRegion.sampleLength);
4276 bytesWritten += drwav__write_or_count(pWav, pMetadata->data.labelledCueRegion.purposeId, 4);
4277 bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.labelledCueRegion.country);
4278 bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.labelledCueRegion.language);
4279 bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.labelledCueRegion.dialect);
4280 bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.labelledCueRegion.codePage);
4282 if (pMetadata->data.labelledCueRegion.stringLength > 0) {
4283 DRWAV_ASSERT(pMetadata->data.labelledCueRegion.pString != NULL);
4285 bytesWritten += drwav__write_or_count(pWav, pMetadata->data.labelledCueRegion.pString, pMetadata->data.labelledCueRegion.stringLength);
4286 bytesWritten += drwav__write_or_count_byte(pWav,
'\0');
4290 case drwav_metadata_type_unknown:
4292 if (pMetadata->data.unknown.chunkLocation == drwav_metadata_location_inside_adtl_list) {
4293 subchunkSize = pMetadata->data.unknown.dataSizeInBytes;
4295 DRWAV_ASSERT(pMetadata->data.unknown.pData != NULL);
4296 bytesWritten += drwav__write_or_count(pWav, pMetadata->data.unknown.id, 4);
4297 bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, subchunkSize);
4298 bytesWritten += drwav__write_or_count(pWav, pMetadata->data.unknown.pData, subchunkSize);
4305 if ((subchunkSize % 2) != 0) {
4306 bytesWritten += drwav__write_or_count_byte(pWav, 0);
4311 DRWAV_ASSERT((bytesWritten % 2) == 0);
4313 return bytesWritten;
4316DRWAV_PRIVATE drwav_uint32 drwav__riff_chunk_size_riff(drwav_uint64 dataChunkSize,
drwav_metadata* pMetadata, drwav_uint32 metadataCount)
4318 drwav_uint64 chunkSize = 4 + 24 + (drwav_uint64)drwav__write_or_count_metadata(NULL, pMetadata, metadataCount) + 8 + dataChunkSize + drwav__chunk_padding_size_riff(dataChunkSize);
4319 if (chunkSize > 0xFFFFFFFFUL) {
4320 chunkSize = 0xFFFFFFFFUL;
4323 return (drwav_uint32)chunkSize;
4326DRWAV_PRIVATE drwav_uint32 drwav__data_chunk_size_riff(drwav_uint64 dataChunkSize)
4328 if (dataChunkSize <= 0xFFFFFFFFUL) {
4329 return (drwav_uint32)dataChunkSize;
4331 return 0xFFFFFFFFUL;
4335DRWAV_PRIVATE drwav_uint64 drwav__riff_chunk_size_w64(drwav_uint64 dataChunkSize)
4337 drwav_uint64 dataSubchunkPaddingSize = drwav__chunk_padding_size_w64(dataChunkSize);
4339 return 80 + 24 + dataChunkSize + dataSubchunkPaddingSize;
4342DRWAV_PRIVATE drwav_uint64 drwav__data_chunk_size_w64(drwav_uint64 dataChunkSize)
4344 return 24 + dataChunkSize;
4347DRWAV_PRIVATE drwav_uint64 drwav__riff_chunk_size_rf64(drwav_uint64 dataChunkSize,
drwav_metadata *metadata, drwav_uint32 numMetadata)
4349 drwav_uint64 chunkSize = 4 + 36 + 24 + (drwav_uint64)drwav__write_or_count_metadata(NULL, metadata, numMetadata) + 8 + dataChunkSize + drwav__chunk_padding_size_riff(dataChunkSize);
4350 if (chunkSize > 0xFFFFFFFFUL) {
4351 chunkSize = 0xFFFFFFFFUL;
4357DRWAV_PRIVATE drwav_uint64 drwav__data_chunk_size_rf64(drwav_uint64 dataChunkSize)
4359 return dataChunkSize;
4364DRWAV_PRIVATE drwav_bool32 drwav_preinit_write(
drwav* pWav,
const drwav_data_format* pFormat, drwav_bool32 isSequential, drwav_write_proc onWrite, drwav_seek_proc onSeek,
void* pUserData,
const drwav_allocation_callbacks* pAllocationCallbacks)
4366 if (pWav == NULL || onWrite == NULL) {
4370 if (!isSequential && onSeek == NULL) {
4375 if (pFormat->format == DR_WAVE_FORMAT_EXTENSIBLE) {
4378 if (pFormat->format == DR_WAVE_FORMAT_ADPCM || pFormat->format == DR_WAVE_FORMAT_DVI_ADPCM) {
4382 DRWAV_ZERO_MEMORY(pWav,
sizeof(*pWav));
4383 pWav->onWrite = onWrite;
4384 pWav->onSeek = onSeek;
4385 pWav->pUserData = pUserData;
4386 pWav->allocationCallbacks = drwav_copy_allocation_callbacks_or_defaults(pAllocationCallbacks);
4388 if (pWav->allocationCallbacks.onFree == NULL || (pWav->allocationCallbacks.onMalloc == NULL && pWav->allocationCallbacks.onRealloc == NULL)) {
4392 pWav->fmt.formatTag = (drwav_uint16)pFormat->format;
4393 pWav->fmt.channels = (drwav_uint16)pFormat->channels;
4394 pWav->fmt.sampleRate = pFormat->sampleRate;
4395 pWav->fmt.avgBytesPerSec = (drwav_uint32)((pFormat->bitsPerSample * pFormat->sampleRate * pFormat->channels) / 8);
4396 pWav->fmt.blockAlign = (drwav_uint16)((pFormat->channels * pFormat->bitsPerSample) / 8);
4397 pWav->fmt.bitsPerSample = (drwav_uint16)pFormat->bitsPerSample;
4398 pWav->fmt.extendedSize = 0;
4399 pWav->isSequentialWrite = isSequential;
4405DRWAV_PRIVATE drwav_bool32 drwav_init_write__internal(
drwav* pWav,
const drwav_data_format* pFormat, drwav_uint64 totalSampleCount)
4409 size_t runningPos = 0;
4410 drwav_uint64 initialDataChunkSize = 0;
4411 drwav_uint64 chunkSizeFMT;
4418 if (pWav->isSequentialWrite) {
4419 initialDataChunkSize = (totalSampleCount * pWav->fmt.bitsPerSample) / 8;
4425 if (pFormat->container == drwav_container_riff) {
4426 if (initialDataChunkSize > (0xFFFFFFFFUL - 36)) {
4432 pWav->dataChunkDataSizeTargetWrite = initialDataChunkSize;
4436 if (pFormat->container == drwav_container_riff) {
4437 drwav_uint32 chunkSizeRIFF = 28 + (drwav_uint32)initialDataChunkSize;
4438 runningPos += drwav__write(pWav,
"RIFF", 4);
4439 runningPos += drwav__write_u32ne_to_le(pWav, chunkSizeRIFF);
4440 runningPos += drwav__write(pWav,
"WAVE", 4);
4441 }
else if (pFormat->container == drwav_container_w64) {
4442 drwav_uint64 chunkSizeRIFF = 80 + 24 + initialDataChunkSize;
4443 runningPos += drwav__write(pWav, drwavGUID_W64_RIFF, 16);
4444 runningPos += drwav__write_u64ne_to_le(pWav, chunkSizeRIFF);
4445 runningPos += drwav__write(pWav, drwavGUID_W64_WAVE, 16);
4446 }
else if (pFormat->container == drwav_container_rf64) {
4447 runningPos += drwav__write(pWav,
"RF64", 4);
4448 runningPos += drwav__write_u32ne_to_le(pWav, 0xFFFFFFFF);
4449 runningPos += drwav__write(pWav,
"WAVE", 4);
4456 if (pFormat->container == drwav_container_rf64) {
4457 drwav_uint32 initialds64ChunkSize = 28;
4458 drwav_uint64 initialRiffChunkSize = 8 + initialds64ChunkSize + initialDataChunkSize;
4460 runningPos += drwav__write(pWav,
"ds64", 4);
4461 runningPos += drwav__write_u32ne_to_le(pWav, initialds64ChunkSize);
4462 runningPos += drwav__write_u64ne_to_le(pWav, initialRiffChunkSize);
4463 runningPos += drwav__write_u64ne_to_le(pWav, initialDataChunkSize);
4464 runningPos += drwav__write_u64ne_to_le(pWav, totalSampleCount);
4465 runningPos += drwav__write_u32ne_to_le(pWav, 0);
4470 if (pFormat->container == drwav_container_riff || pFormat->container == drwav_container_rf64) {
4472 runningPos += drwav__write(pWav,
"fmt ", 4);
4473 runningPos += drwav__write_u32ne_to_le(pWav, (drwav_uint32)chunkSizeFMT);
4474 }
else if (pFormat->container == drwav_container_w64) {
4476 runningPos += drwav__write(pWav, drwavGUID_W64_FMT, 16);
4477 runningPos += drwav__write_u64ne_to_le(pWav, chunkSizeFMT);
4480 runningPos += drwav__write_u16ne_to_le(pWav, pWav->fmt.formatTag);
4481 runningPos += drwav__write_u16ne_to_le(pWav, pWav->fmt.channels);
4482 runningPos += drwav__write_u32ne_to_le(pWav, pWav->fmt.sampleRate);
4483 runningPos += drwav__write_u32ne_to_le(pWav, pWav->fmt.avgBytesPerSec);
4484 runningPos += drwav__write_u16ne_to_le(pWav, pWav->fmt.blockAlign);
4485 runningPos += drwav__write_u16ne_to_le(pWav, pWav->fmt.bitsPerSample);
4489 if (!pWav->isSequentialWrite && pWav->pMetadata != NULL && pWav->metadataCount > 0 && (pFormat->container == drwav_container_riff || pFormat->container == drwav_container_rf64)) {
4490 runningPos += drwav__write_or_count_metadata(pWav, pWav->pMetadata, pWav->metadataCount);
4493 pWav->dataChunkDataPos = runningPos;
4496 if (pFormat->container == drwav_container_riff) {
4497 drwav_uint32 chunkSizeDATA = (drwav_uint32)initialDataChunkSize;
4498 runningPos += drwav__write(pWav,
"data", 4);
4499 runningPos += drwav__write_u32ne_to_le(pWav, chunkSizeDATA);
4500 }
else if (pFormat->container == drwav_container_w64) {
4501 drwav_uint64 chunkSizeDATA = 24 + initialDataChunkSize;
4502 runningPos += drwav__write(pWav, drwavGUID_W64_DATA, 16);
4503 runningPos += drwav__write_u64ne_to_le(pWav, chunkSizeDATA);
4504 }
else if (pFormat->container == drwav_container_rf64) {
4505 runningPos += drwav__write(pWav,
"data", 4);
4506 runningPos += drwav__write_u32ne_to_le(pWav, 0xFFFFFFFF);
4510 pWav->container = pFormat->container;
4511 pWav->channels = (drwav_uint16)pFormat->channels;
4512 pWav->sampleRate = pFormat->sampleRate;
4513 pWav->bitsPerSample = (drwav_uint16)pFormat->bitsPerSample;
4514 pWav->translatedFormatTag = (drwav_uint16)pFormat->format;
4515 pWav->dataChunkDataPos = runningPos;
4523 if (!drwav_preinit_write(pWav, pFormat, DRWAV_FALSE, onWrite, onSeek, pUserData, pAllocationCallbacks)) {
4527 return drwav_init_write__internal(pWav, pFormat, 0);
4532 if (!drwav_preinit_write(pWav, pFormat, DRWAV_TRUE, onWrite, NULL, pUserData, pAllocationCallbacks)) {
4536 return drwav_init_write__internal(pWav, pFormat, totalSampleCount);
4539DRWAV_API drwav_bool32 drwav_init_write_sequential_pcm_frames(
drwav* pWav,
const drwav_data_format* pFormat, drwav_uint64 totalPCMFrameCount, drwav_write_proc onWrite,
void* pUserData,
const drwav_allocation_callbacks* pAllocationCallbacks)
4541 if (pFormat == NULL) {
4545 return drwav_init_write_sequential(pWav, pFormat, totalPCMFrameCount*pFormat->channels, onWrite, pUserData, pAllocationCallbacks);
4550 if (!drwav_preinit_write(pWav, pFormat, DRWAV_FALSE, onWrite, onSeek, pUserData, pAllocationCallbacks)) {
4554 pWav->pMetadata = pMetadata;
4555 pWav->metadataCount = metadataCount;
4557 return drwav_init_write__internal(pWav, pFormat, 0);
4561DRWAV_API drwav_uint64 drwav_target_write_size_bytes(
const drwav_data_format* pFormat, drwav_uint64 totalFrameCount,
drwav_metadata* pMetadata, drwav_uint32 metadataCount)
4564 drwav_uint64 targetDataSizeBytes = (drwav_uint64)((drwav_int64)totalFrameCount * pFormat->channels * pFormat->bitsPerSample/8.0);
4565 drwav_uint64 riffChunkSizeBytes;
4566 drwav_uint64 fileSizeBytes = 0;
4568 if (pFormat->container == drwav_container_riff) {
4569 riffChunkSizeBytes = drwav__riff_chunk_size_riff(targetDataSizeBytes, pMetadata, metadataCount);
4570 fileSizeBytes = (8 + riffChunkSizeBytes);
4571 }
else if (pFormat->container == drwav_container_w64) {
4572 riffChunkSizeBytes = drwav__riff_chunk_size_w64(targetDataSizeBytes);
4573 fileSizeBytes = riffChunkSizeBytes;
4574 }
else if (pFormat->container == drwav_container_rf64) {
4575 riffChunkSizeBytes = drwav__riff_chunk_size_rf64(targetDataSizeBytes, pMetadata, metadataCount);
4576 fileSizeBytes = (8 + riffChunkSizeBytes);
4579 return fileSizeBytes;
4583#ifndef DR_WAV_NO_STDIO
4588DRWAV_PRIVATE drwav_result drwav_result_from_errno(
int e)
4592 case 0:
return DRWAV_SUCCESS;
4594 case EPERM:
return DRWAV_INVALID_OPERATION;
4597 case ENOENT:
return DRWAV_DOES_NOT_EXIST;
4600 case ESRCH:
return DRWAV_DOES_NOT_EXIST;
4603 case EINTR:
return DRWAV_INTERRUPT;
4606 case EIO:
return DRWAV_IO_ERROR;
4609 case ENXIO:
return DRWAV_DOES_NOT_EXIST;
4612 case E2BIG:
return DRWAV_INVALID_ARGS;
4615 case ENOEXEC:
return DRWAV_INVALID_FILE;
4618 case EBADF:
return DRWAV_INVALID_FILE;
4621 case ECHILD:
return DRWAV_ERROR;
4624 case EAGAIN:
return DRWAV_UNAVAILABLE;
4627 case ENOMEM:
return DRWAV_OUT_OF_MEMORY;
4630 case EACCES:
return DRWAV_ACCESS_DENIED;
4633 case EFAULT:
return DRWAV_BAD_ADDRESS;
4636 case ENOTBLK:
return DRWAV_ERROR;
4639 case EBUSY:
return DRWAV_BUSY;
4642 case EEXIST:
return DRWAV_ALREADY_EXISTS;
4645 case EXDEV:
return DRWAV_ERROR;
4648 case ENODEV:
return DRWAV_DOES_NOT_EXIST;
4651 case ENOTDIR:
return DRWAV_NOT_DIRECTORY;
4654 case EISDIR:
return DRWAV_IS_DIRECTORY;
4657 case EINVAL:
return DRWAV_INVALID_ARGS;
4660 case ENFILE:
return DRWAV_TOO_MANY_OPEN_FILES;
4663 case EMFILE:
return DRWAV_TOO_MANY_OPEN_FILES;
4666 case ENOTTY:
return DRWAV_INVALID_OPERATION;
4669 case ETXTBSY:
return DRWAV_BUSY;
4672 case EFBIG:
return DRWAV_TOO_BIG;
4675 case ENOSPC:
return DRWAV_NO_SPACE;
4678 case ESPIPE:
return DRWAV_BAD_SEEK;
4681 case EROFS:
return DRWAV_ACCESS_DENIED;
4684 case EMLINK:
return DRWAV_TOO_MANY_LINKS;
4687 case EPIPE:
return DRWAV_BAD_PIPE;
4690 case EDOM:
return DRWAV_OUT_OF_RANGE;
4693 case ERANGE:
return DRWAV_OUT_OF_RANGE;
4696 case EDEADLK:
return DRWAV_DEADLOCK;
4699 case ENAMETOOLONG:
return DRWAV_PATH_TOO_LONG;
4702 case ENOLCK:
return DRWAV_ERROR;
4705 case ENOSYS:
return DRWAV_NOT_IMPLEMENTED;
4708 case ENOTEMPTY:
return DRWAV_DIRECTORY_NOT_EMPTY;
4711 case ELOOP:
return DRWAV_TOO_MANY_LINKS;
4714 case ENOMSG:
return DRWAV_NO_MESSAGE;
4717 case EIDRM:
return DRWAV_ERROR;
4720 case ECHRNG:
return DRWAV_ERROR;
4723 case EL2NSYNC:
return DRWAV_ERROR;
4726 case EL3HLT:
return DRWAV_ERROR;
4729 case EL3RST:
return DRWAV_ERROR;
4732 case ELNRNG:
return DRWAV_OUT_OF_RANGE;
4735 case EUNATCH:
return DRWAV_ERROR;
4738 case ENOCSI:
return DRWAV_ERROR;
4741 case EL2HLT:
return DRWAV_ERROR;
4744 case EBADE:
return DRWAV_ERROR;
4747 case EBADR:
return DRWAV_ERROR;
4750 case EXFULL:
return DRWAV_ERROR;
4753 case ENOANO:
return DRWAV_ERROR;
4756 case EBADRQC:
return DRWAV_ERROR;
4759 case EBADSLT:
return DRWAV_ERROR;
4762 case EBFONT:
return DRWAV_INVALID_FILE;
4765 case ENOSTR:
return DRWAV_ERROR;
4768 case ENODATA:
return DRWAV_NO_DATA_AVAILABLE;
4771 case ETIME:
return DRWAV_TIMEOUT;
4774 case ENOSR:
return DRWAV_NO_DATA_AVAILABLE;
4777 case ENONET:
return DRWAV_NO_NETWORK;
4780 case ENOPKG:
return DRWAV_ERROR;
4783 case EREMOTE:
return DRWAV_ERROR;
4786 case ENOLINK:
return DRWAV_ERROR;
4789 case EADV:
return DRWAV_ERROR;
4792 case ESRMNT:
return DRWAV_ERROR;
4795 case ECOMM:
return DRWAV_ERROR;
4798 case EPROTO:
return DRWAV_ERROR;
4801 case EMULTIHOP:
return DRWAV_ERROR;
4804 case EDOTDOT:
return DRWAV_ERROR;
4807 case EBADMSG:
return DRWAV_BAD_MESSAGE;
4810 case EOVERFLOW:
return DRWAV_TOO_BIG;
4813 case ENOTUNIQ:
return DRWAV_NOT_UNIQUE;
4816 case EBADFD:
return DRWAV_ERROR;
4819 case EREMCHG:
return DRWAV_ERROR;
4822 case ELIBACC:
return DRWAV_ACCESS_DENIED;
4825 case ELIBBAD:
return DRWAV_INVALID_FILE;
4828 case ELIBSCN:
return DRWAV_INVALID_FILE;
4831 case ELIBMAX:
return DRWAV_ERROR;
4834 case ELIBEXEC:
return DRWAV_ERROR;
4837 case EILSEQ:
return DRWAV_INVALID_DATA;
4840 case ERESTART:
return DRWAV_ERROR;
4843 case ESTRPIPE:
return DRWAV_ERROR;
4846 case EUSERS:
return DRWAV_ERROR;
4849 case ENOTSOCK:
return DRWAV_NOT_SOCKET;
4852 case EDESTADDRREQ:
return DRWAV_NO_ADDRESS;
4855 case EMSGSIZE:
return DRWAV_TOO_BIG;
4858 case EPROTOTYPE:
return DRWAV_BAD_PROTOCOL;
4861 case ENOPROTOOPT:
return DRWAV_PROTOCOL_UNAVAILABLE;
4863 #ifdef EPROTONOSUPPORT
4864 case EPROTONOSUPPORT:
return DRWAV_PROTOCOL_NOT_SUPPORTED;
4866 #ifdef ESOCKTNOSUPPORT
4867 case ESOCKTNOSUPPORT:
return DRWAV_SOCKET_NOT_SUPPORTED;
4870 case EOPNOTSUPP:
return DRWAV_INVALID_OPERATION;
4873 case EPFNOSUPPORT:
return DRWAV_PROTOCOL_FAMILY_NOT_SUPPORTED;
4876 case EAFNOSUPPORT:
return DRWAV_ADDRESS_FAMILY_NOT_SUPPORTED;
4879 case EADDRINUSE:
return DRWAV_ALREADY_IN_USE;
4881 #ifdef EADDRNOTAVAIL
4882 case EADDRNOTAVAIL:
return DRWAV_ERROR;
4885 case ENETDOWN:
return DRWAV_NO_NETWORK;
4888 case ENETUNREACH:
return DRWAV_NO_NETWORK;
4891 case ENETRESET:
return DRWAV_NO_NETWORK;
4894 case ECONNABORTED:
return DRWAV_NO_NETWORK;
4897 case ECONNRESET:
return DRWAV_CONNECTION_RESET;
4900 case ENOBUFS:
return DRWAV_NO_SPACE;
4903 case EISCONN:
return DRWAV_ALREADY_CONNECTED;
4906 case ENOTCONN:
return DRWAV_NOT_CONNECTED;
4909 case ESHUTDOWN:
return DRWAV_ERROR;
4912 case ETOOMANYREFS:
return DRWAV_ERROR;
4915 case ETIMEDOUT:
return DRWAV_TIMEOUT;
4918 case ECONNREFUSED:
return DRWAV_CONNECTION_REFUSED;
4921 case EHOSTDOWN:
return DRWAV_NO_HOST;
4924 case EHOSTUNREACH:
return DRWAV_NO_HOST;
4927 case EALREADY:
return DRWAV_IN_PROGRESS;
4930 case EINPROGRESS:
return DRWAV_IN_PROGRESS;
4933 case ESTALE:
return DRWAV_INVALID_FILE;
4936 case EUCLEAN:
return DRWAV_ERROR;
4939 case ENOTNAM:
return DRWAV_ERROR;
4942 case ENAVAIL:
return DRWAV_ERROR;
4945 case EISNAM:
return DRWAV_ERROR;
4948 case EREMOTEIO:
return DRWAV_IO_ERROR;
4951 case EDQUOT:
return DRWAV_NO_SPACE;
4954 case ENOMEDIUM:
return DRWAV_DOES_NOT_EXIST;
4957 case EMEDIUMTYPE:
return DRWAV_ERROR;
4960 case ECANCELED:
return DRWAV_CANCELLED;
4963 case ENOKEY:
return DRWAV_ERROR;
4966 case EKEYEXPIRED:
return DRWAV_ERROR;
4969 case EKEYREVOKED:
return DRWAV_ERROR;
4972 case EKEYREJECTED:
return DRWAV_ERROR;
4975 case EOWNERDEAD:
return DRWAV_ERROR;
4977 #ifdef ENOTRECOVERABLE
4978 case ENOTRECOVERABLE:
return DRWAV_ERROR;
4981 case ERFKILL:
return DRWAV_ERROR;
4984 case EHWPOISON:
return DRWAV_ERROR;
4986 default:
return DRWAV_ERROR;
4992DRWAV_PRIVATE drwav_result drwav_fopen(FILE** ppFile,
const char* pFilePath,
const char* pOpenMode)
4994#if defined(_MSC_VER) && _MSC_VER >= 1400
4998 if (ppFile != NULL) {
5002 if (pFilePath == NULL || pOpenMode == NULL || ppFile == NULL) {
5003 return DRWAV_INVALID_ARGS;
5006#if defined(_MSC_VER) && _MSC_VER >= 1400
5007 err = fopen_s(ppFile, pFilePath, pOpenMode);
5009 return drwav_result_from_errno(err);
5012#if defined(_WIN32) || defined(__APPLE__)
5013 *ppFile = fopen(pFilePath, pOpenMode);
5015 #if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64 && defined(_LARGEFILE64_SOURCE)
5016 *ppFile = fopen64(pFilePath, pOpenMode);
5018 *ppFile = fopen(pFilePath, pOpenMode);
5021 if (*ppFile == NULL) {
5022 drwav_result result = drwav_result_from_errno(errno);
5023 if (result == DRWAV_SUCCESS) {
5024 result = DRWAV_ERROR;
5031 return DRWAV_SUCCESS;
5047 #if defined(_MSC_VER) || defined(__MINGW64__) || (!defined(__STRICT_ANSI__) && !defined(_NO_EXT_KEYS))
5048 #define DRWAV_HAS_WFOPEN
5052#ifndef DR_WAV_NO_WCHAR
5053DRWAV_PRIVATE drwav_result drwav_wfopen(FILE** ppFile,
const wchar_t* pFilePath,
const wchar_t* pOpenMode,
const drwav_allocation_callbacks* pAllocationCallbacks)
5055 if (ppFile != NULL) {
5059 if (pFilePath == NULL || pOpenMode == NULL || ppFile == NULL) {
5060 return DRWAV_INVALID_ARGS;
5063#if defined(DRWAV_HAS_WFOPEN)
5066 #if defined(_MSC_VER) && _MSC_VER >= 1400
5067 errno_t err = _wfopen_s(ppFile, pFilePath, pOpenMode);
5069 return drwav_result_from_errno(err);
5072 *ppFile = _wfopen(pFilePath, pOpenMode);
5073 if (*ppFile == NULL) {
5074 return drwav_result_from_errno(errno);
5077 (void)pAllocationCallbacks;
5093 #if defined(__DJGPP__)
5101 const wchar_t* pFilePathTemp = pFilePath;
5102 char* pFilePathMB = NULL;
5103 char pOpenModeMB[32] = {0};
5106 DRWAV_ZERO_OBJECT(&mbs);
5107 lenMB = wcsrtombs(NULL, &pFilePathTemp, 0, &mbs);
5108 if (lenMB == (
size_t)-1) {
5109 return drwav_result_from_errno(errno);
5112 pFilePathMB = (
char*)drwav__malloc_from_callbacks(lenMB + 1, pAllocationCallbacks);
5113 if (pFilePathMB == NULL) {
5114 return DRWAV_OUT_OF_MEMORY;
5117 pFilePathTemp = pFilePath;
5118 DRWAV_ZERO_OBJECT(&mbs);
5119 wcsrtombs(pFilePathMB, &pFilePathTemp, lenMB + 1, &mbs);
5125 if (pOpenMode[i] == 0) {
5126 pOpenModeMB[i] =
'\0';
5130 pOpenModeMB[i] = (char)pOpenMode[i];
5135 *ppFile = fopen(pFilePathMB, pOpenModeMB);
5137 drwav__free_from_callbacks(pFilePathMB, pAllocationCallbacks);
5141 if (*ppFile == NULL) {
5146 return DRWAV_SUCCESS;
5152DRWAV_PRIVATE
size_t drwav__on_read_stdio(
void* pUserData,
void* pBufferOut,
size_t bytesToRead)
5154 return fread(pBufferOut, 1, bytesToRead, (FILE*)pUserData);
5157DRWAV_PRIVATE
size_t drwav__on_write_stdio(
void* pUserData,
const void* pData,
size_t bytesToWrite)
5159 return fwrite(pData, 1, bytesToWrite, (FILE*)pUserData);
5162DRWAV_PRIVATE drwav_bool32 drwav__on_seek_stdio(
void* pUserData,
int offset, drwav_seek_origin origin)
5164 return fseek((FILE*)pUserData, offset, (origin == drwav_seek_origin_current) ? SEEK_CUR : SEEK_SET) == 0;
5169 return drwav_init_file_ex(pWav, filename, NULL, NULL, 0, pAllocationCallbacks);
5173DRWAV_PRIVATE drwav_bool32 drwav_init_file__internal_FILE(
drwav* pWav, FILE* pFile, drwav_chunk_proc onChunk,
void* pChunkUserData, drwav_uint32 flags,
const drwav_allocation_callbacks* pAllocationCallbacks)
5175 drwav_bool32 result;
5177 result = drwav_preinit(pWav, drwav__on_read_stdio, drwav__on_seek_stdio, (
void*)pFile, pAllocationCallbacks);
5178 if (result != DRWAV_TRUE) {
5183 result = drwav_init__internal(pWav, onChunk, pChunkUserData, flags);
5184 if (result != DRWAV_TRUE) {
5192DRWAV_API drwav_bool32 drwav_init_file_ex(
drwav* pWav,
const char* filename, drwav_chunk_proc onChunk,
void* pChunkUserData, drwav_uint32 flags,
const drwav_allocation_callbacks* pAllocationCallbacks)
5195 if (drwav_fopen(&pFile, filename,
"rb") != DRWAV_SUCCESS) {
5200 return drwav_init_file__internal_FILE(pWav, pFile, onChunk, pChunkUserData, flags, pAllocationCallbacks);
5203#ifndef DR_WAV_NO_WCHAR
5206 return drwav_init_file_ex_w(pWav, filename, NULL, NULL, 0, pAllocationCallbacks);
5209DRWAV_API drwav_bool32 drwav_init_file_ex_w(
drwav* pWav,
const wchar_t* filename, drwav_chunk_proc onChunk,
void* pChunkUserData, drwav_uint32 flags,
const drwav_allocation_callbacks* pAllocationCallbacks)
5212 if (drwav_wfopen(&pFile, filename, L
"rb", pAllocationCallbacks) != DRWAV_SUCCESS) {
5217 return drwav_init_file__internal_FILE(pWav, pFile, onChunk, pChunkUserData, flags, pAllocationCallbacks);
5221DRWAV_API drwav_bool32 drwav_init_file_with_metadata(
drwav* pWav,
const char* filename, drwav_uint32 flags,
const drwav_allocation_callbacks* pAllocationCallbacks)
5224 if (drwav_fopen(&pFile, filename,
"rb") != DRWAV_SUCCESS) {
5229 return drwav_init_file__internal_FILE(pWav, pFile, NULL, NULL, flags | DRWAV_WITH_METADATA, pAllocationCallbacks);
5232#ifndef DR_WAV_NO_WCHAR
5233DRWAV_API drwav_bool32 drwav_init_file_with_metadata_w(
drwav* pWav,
const wchar_t* filename, drwav_uint32 flags,
const drwav_allocation_callbacks* pAllocationCallbacks)
5236 if (drwav_wfopen(&pFile, filename, L
"rb", pAllocationCallbacks) != DRWAV_SUCCESS) {
5241 return drwav_init_file__internal_FILE(pWav, pFile, NULL, NULL, flags | DRWAV_WITH_METADATA, pAllocationCallbacks);
5246DRWAV_PRIVATE drwav_bool32 drwav_init_file_write__internal_FILE(
drwav* pWav, FILE* pFile,
const drwav_data_format* pFormat, drwav_uint64 totalSampleCount, drwav_bool32 isSequential,
const drwav_allocation_callbacks* pAllocationCallbacks)
5248 drwav_bool32 result;
5250 result = drwav_preinit_write(pWav, pFormat, isSequential, drwav__on_write_stdio, drwav__on_seek_stdio, (
void*)pFile, pAllocationCallbacks);
5251 if (result != DRWAV_TRUE) {
5256 result = drwav_init_write__internal(pWav, pFormat, totalSampleCount);
5257 if (result != DRWAV_TRUE) {
5265DRWAV_PRIVATE drwav_bool32 drwav_init_file_write__internal(
drwav* pWav,
const char* filename,
const drwav_data_format* pFormat, drwav_uint64 totalSampleCount, drwav_bool32 isSequential,
const drwav_allocation_callbacks* pAllocationCallbacks)
5268 if (drwav_fopen(&pFile, filename,
"wb") != DRWAV_SUCCESS) {
5273 return drwav_init_file_write__internal_FILE(pWav, pFile, pFormat, totalSampleCount, isSequential, pAllocationCallbacks);
5276#ifndef DR_WAV_NO_WCHAR
5277DRWAV_PRIVATE drwav_bool32 drwav_init_file_write_w__internal(
drwav* pWav,
const wchar_t* filename,
const drwav_data_format* pFormat, drwav_uint64 totalSampleCount, drwav_bool32 isSequential,
const drwav_allocation_callbacks* pAllocationCallbacks)
5280 if (drwav_wfopen(&pFile, filename, L
"wb", pAllocationCallbacks) != DRWAV_SUCCESS) {
5285 return drwav_init_file_write__internal_FILE(pWav, pFile, pFormat, totalSampleCount, isSequential, pAllocationCallbacks);
5291 return drwav_init_file_write__internal(pWav, filename, pFormat, 0, DRWAV_FALSE, pAllocationCallbacks);
5296 return drwav_init_file_write__internal(pWav, filename, pFormat, totalSampleCount, DRWAV_TRUE, pAllocationCallbacks);
5301 if (pFormat == NULL) {
5305 return drwav_init_file_write_sequential(pWav, filename, pFormat, totalPCMFrameCount*pFormat->channels, pAllocationCallbacks);
5308#ifndef DR_WAV_NO_WCHAR
5311 return drwav_init_file_write_w__internal(pWav, filename, pFormat, 0, DRWAV_FALSE, pAllocationCallbacks);
5316 return drwav_init_file_write_w__internal(pWav, filename, pFormat, totalSampleCount, DRWAV_TRUE, pAllocationCallbacks);
5321 if (pFormat == NULL) {
5325 return drwav_init_file_write_sequential_w(pWav, filename, pFormat, totalPCMFrameCount*pFormat->channels, pAllocationCallbacks);
5331DRWAV_PRIVATE
size_t drwav__on_read_memory(
void* pUserData,
void* pBufferOut,
size_t bytesToRead)
5334 size_t bytesRemaining;
5336 DRWAV_ASSERT(pWav != NULL);
5337 DRWAV_ASSERT(pWav->memoryStream.dataSize >= pWav->memoryStream.currentReadPos);
5339 bytesRemaining = pWav->memoryStream.dataSize - pWav->memoryStream.currentReadPos;
5340 if (bytesToRead > bytesRemaining) {
5341 bytesToRead = bytesRemaining;
5344 if (bytesToRead > 0) {
5345 DRWAV_COPY_MEMORY(pBufferOut, pWav->memoryStream.data + pWav->memoryStream.currentReadPos, bytesToRead);
5346 pWav->memoryStream.currentReadPos += bytesToRead;
5352DRWAV_PRIVATE drwav_bool32 drwav__on_seek_memory(
void* pUserData,
int offset, drwav_seek_origin origin)
5355 DRWAV_ASSERT(pWav != NULL);
5357 if (origin == drwav_seek_origin_current) {
5359 if (pWav->memoryStream.currentReadPos + offset > pWav->memoryStream.dataSize) {
5363 if (pWav->memoryStream.currentReadPos < (
size_t)-offset) {
5369 pWav->memoryStream.currentReadPos += offset;
5371 if ((drwav_uint32)offset <= pWav->memoryStream.dataSize) {
5372 pWav->memoryStream.currentReadPos = offset;
5381DRWAV_PRIVATE
size_t drwav__on_write_memory(
void* pUserData,
const void* pDataIn,
size_t bytesToWrite)
5384 size_t bytesRemaining;
5386 DRWAV_ASSERT(pWav != NULL);
5387 DRWAV_ASSERT(pWav->memoryStreamWrite.dataCapacity >= pWav->memoryStreamWrite.currentWritePos);
5389 bytesRemaining = pWav->memoryStreamWrite.dataCapacity - pWav->memoryStreamWrite.currentWritePos;
5390 if (bytesRemaining < bytesToWrite) {
5393 size_t newDataCapacity = (pWav->memoryStreamWrite.dataCapacity == 0) ? 256 : pWav->memoryStreamWrite.dataCapacity * 2;
5396 if ((newDataCapacity - pWav->memoryStreamWrite.currentWritePos) < bytesToWrite) {
5397 newDataCapacity = pWav->memoryStreamWrite.currentWritePos + bytesToWrite;
5400 pNewData = drwav__realloc_from_callbacks(*pWav->memoryStreamWrite.ppData, newDataCapacity, pWav->memoryStreamWrite.dataCapacity, &pWav->allocationCallbacks);
5401 if (pNewData == NULL) {
5405 *pWav->memoryStreamWrite.ppData = pNewData;
5406 pWav->memoryStreamWrite.dataCapacity = newDataCapacity;
5409 DRWAV_COPY_MEMORY(((drwav_uint8*)(*pWav->memoryStreamWrite.ppData)) + pWav->memoryStreamWrite.currentWritePos, pDataIn, bytesToWrite);
5411 pWav->memoryStreamWrite.currentWritePos += bytesToWrite;
5412 if (pWav->memoryStreamWrite.dataSize < pWav->memoryStreamWrite.currentWritePos) {
5413 pWav->memoryStreamWrite.dataSize = pWav->memoryStreamWrite.currentWritePos;
5416 *pWav->memoryStreamWrite.pDataSize = pWav->memoryStreamWrite.dataSize;
5418 return bytesToWrite;
5421DRWAV_PRIVATE drwav_bool32 drwav__on_seek_memory_write(
void* pUserData,
int offset, drwav_seek_origin origin)
5424 DRWAV_ASSERT(pWav != NULL);
5426 if (origin == drwav_seek_origin_current) {
5428 if (pWav->memoryStreamWrite.currentWritePos + offset > pWav->memoryStreamWrite.dataSize) {
5429 offset = (int)(pWav->memoryStreamWrite.dataSize - pWav->memoryStreamWrite.currentWritePos);
5432 if (pWav->memoryStreamWrite.currentWritePos < (
size_t)-offset) {
5433 offset = -(int)pWav->memoryStreamWrite.currentWritePos;
5438 pWav->memoryStreamWrite.currentWritePos += offset;
5440 if ((drwav_uint32)offset <= pWav->memoryStreamWrite.dataSize) {
5441 pWav->memoryStreamWrite.currentWritePos = offset;
5443 pWav->memoryStreamWrite.currentWritePos = pWav->memoryStreamWrite.dataSize;
5452 return drwav_init_memory_ex(pWav, data, dataSize, NULL, NULL, 0, pAllocationCallbacks);
5455DRWAV_API drwav_bool32 drwav_init_memory_ex(
drwav* pWav,
const void* data,
size_t dataSize, drwav_chunk_proc onChunk,
void* pChunkUserData, drwav_uint32 flags,
const drwav_allocation_callbacks* pAllocationCallbacks)
5457 if (data == NULL || dataSize == 0) {
5461 if (!drwav_preinit(pWav, drwav__on_read_memory, drwav__on_seek_memory, pWav, pAllocationCallbacks)) {
5465 pWav->memoryStream.data = (
const drwav_uint8*)data;
5466 pWav->memoryStream.dataSize = dataSize;
5467 pWav->memoryStream.currentReadPos = 0;
5469 return drwav_init__internal(pWav, onChunk, pChunkUserData, flags);
5472DRWAV_API drwav_bool32 drwav_init_memory_with_metadata(
drwav* pWav,
const void* data,
size_t dataSize, drwav_uint32 flags,
const drwav_allocation_callbacks* pAllocationCallbacks)
5474 if (data == NULL || dataSize == 0) {
5478 if (!drwav_preinit(pWav, drwav__on_read_memory, drwav__on_seek_memory, pWav, pAllocationCallbacks)) {
5482 pWav->memoryStream.data = (
const drwav_uint8*)data;
5483 pWav->memoryStream.dataSize = dataSize;
5484 pWav->memoryStream.currentReadPos = 0;
5486 return drwav_init__internal(pWav, NULL, NULL, flags | DRWAV_WITH_METADATA);
5490DRWAV_PRIVATE drwav_bool32 drwav_init_memory_write__internal(
drwav* pWav,
void** ppData,
size_t* pDataSize,
const drwav_data_format* pFormat, drwav_uint64 totalSampleCount, drwav_bool32 isSequential,
const drwav_allocation_callbacks* pAllocationCallbacks)
5492 if (ppData == NULL || pDataSize == NULL) {
5499 if (!drwav_preinit_write(pWav, pFormat, isSequential, drwav__on_write_memory, drwav__on_seek_memory_write, pWav, pAllocationCallbacks)) {
5503 pWav->memoryStreamWrite.ppData = ppData;
5504 pWav->memoryStreamWrite.pDataSize = pDataSize;
5505 pWav->memoryStreamWrite.dataSize = 0;
5506 pWav->memoryStreamWrite.dataCapacity = 0;
5507 pWav->memoryStreamWrite.currentWritePos = 0;
5509 return drwav_init_write__internal(pWav, pFormat, totalSampleCount);
5514 return drwav_init_memory_write__internal(pWav, ppData, pDataSize, pFormat, 0, DRWAV_FALSE, pAllocationCallbacks);
5519 return drwav_init_memory_write__internal(pWav, ppData, pDataSize, pFormat, totalSampleCount, DRWAV_TRUE, pAllocationCallbacks);
5522DRWAV_API drwav_bool32 drwav_init_memory_write_sequential_pcm_frames(
drwav* pWav,
void** ppData,
size_t* pDataSize,
const drwav_data_format* pFormat, drwav_uint64 totalPCMFrameCount,
const drwav_allocation_callbacks* pAllocationCallbacks)
5524 if (pFormat == NULL) {
5528 return drwav_init_memory_write_sequential(pWav, ppData, pDataSize, pFormat, totalPCMFrameCount*pFormat->channels, pAllocationCallbacks);
5533DRWAV_API drwav_result drwav_uninit(
drwav* pWav)
5535 drwav_result result = DRWAV_SUCCESS;
5538 return DRWAV_INVALID_ARGS;
5546 if (pWav->onWrite != NULL) {
5547 drwav_uint32 paddingSize = 0;
5550 if (pWav->container == drwav_container_riff || pWav->container == drwav_container_rf64) {
5551 paddingSize = drwav__chunk_padding_size_riff(pWav->dataChunkDataSize);
5553 paddingSize = drwav__chunk_padding_size_w64(pWav->dataChunkDataSize);
5556 if (paddingSize > 0) {
5557 drwav_uint64 paddingData = 0;
5558 drwav__write(pWav, &paddingData, paddingSize);
5565 if (pWav->onSeek && !pWav->isSequentialWrite) {
5566 if (pWav->container == drwav_container_riff) {
5568 if (pWav->onSeek(pWav->pUserData, 4, drwav_seek_origin_start)) {
5569 drwav_uint32 riffChunkSize = drwav__riff_chunk_size_riff(pWav->dataChunkDataSize, pWav->pMetadata, pWav->metadataCount);
5570 drwav__write_u32ne_to_le(pWav, riffChunkSize);
5574 if (pWav->onSeek(pWav->pUserData, (
int)pWav->dataChunkDataPos - 4, drwav_seek_origin_start)) {
5575 drwav_uint32 dataChunkSize = drwav__data_chunk_size_riff(pWav->dataChunkDataSize);
5576 drwav__write_u32ne_to_le(pWav, dataChunkSize);
5578 }
else if (pWav->container == drwav_container_w64) {
5580 if (pWav->onSeek(pWav->pUserData, 16, drwav_seek_origin_start)) {
5581 drwav_uint64 riffChunkSize = drwav__riff_chunk_size_w64(pWav->dataChunkDataSize);
5582 drwav__write_u64ne_to_le(pWav, riffChunkSize);
5586 if (pWav->onSeek(pWav->pUserData, (
int)pWav->dataChunkDataPos - 8, drwav_seek_origin_start)) {
5587 drwav_uint64 dataChunkSize = drwav__data_chunk_size_w64(pWav->dataChunkDataSize);
5588 drwav__write_u64ne_to_le(pWav, dataChunkSize);
5590 }
else if (pWav->container == drwav_container_rf64) {
5592 int ds64BodyPos = 12 + 8;
5595 if (pWav->onSeek(pWav->pUserData, ds64BodyPos + 0, drwav_seek_origin_start)) {
5596 drwav_uint64 riffChunkSize = drwav__riff_chunk_size_rf64(pWav->dataChunkDataSize, pWav->pMetadata, pWav->metadataCount);
5597 drwav__write_u64ne_to_le(pWav, riffChunkSize);
5601 if (pWav->onSeek(pWav->pUserData, ds64BodyPos + 8, drwav_seek_origin_start)) {
5602 drwav_uint64 dataChunkSize = drwav__data_chunk_size_rf64(pWav->dataChunkDataSize);
5603 drwav__write_u64ne_to_le(pWav, dataChunkSize);
5609 if (pWav->isSequentialWrite) {
5610 if (pWav->dataChunkDataSize != pWav->dataChunkDataSizeTargetWrite) {
5611 result = DRWAV_INVALID_FILE;
5615 drwav_free(pWav->pMetadata, &pWav->allocationCallbacks);
5618#ifndef DR_WAV_NO_STDIO
5623 if (pWav->onRead == drwav__on_read_stdio || pWav->onWrite == drwav__on_write_stdio) {
5624 fclose((FILE*)pWav->pUserData);
5633DRWAV_API
size_t drwav_read_raw(
drwav* pWav,
size_t bytesToRead,
void* pBufferOut)
5636 drwav_uint32 bytesPerFrame;
5638 if (pWav == NULL || bytesToRead == 0) {
5642 if (bytesToRead > pWav->bytesRemaining) {
5643 bytesToRead = (size_t)pWav->bytesRemaining;
5646 if (bytesToRead == 0) {
5650 bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
5651 if (bytesPerFrame == 0) {
5655 if (pBufferOut != NULL) {
5656 bytesRead = pWav->onRead(pWav->pUserData, pBufferOut, bytesToRead);
5660 while (bytesRead < bytesToRead) {
5661 size_t bytesToSeek = (bytesToRead - bytesRead);
5662 if (bytesToSeek > 0x7FFFFFFF) {
5663 bytesToSeek = 0x7FFFFFFF;
5666 if (pWav->onSeek(pWav->pUserData, (
int)bytesToSeek, drwav_seek_origin_current) == DRWAV_FALSE) {
5670 bytesRead += bytesToSeek;
5674 while (bytesRead < bytesToRead) {
5675 drwav_uint8 buffer[4096];
5677 size_t bytesToSeek = (bytesToRead - bytesRead);
5678 if (bytesToSeek >
sizeof(buffer)) {
5679 bytesToSeek =
sizeof(buffer);
5682 bytesSeeked = pWav->onRead(pWav->pUserData, buffer, bytesToSeek);
5683 bytesRead += bytesSeeked;
5685 if (bytesSeeked < bytesToSeek) {
5691 pWav->readCursorInPCMFrames += bytesRead / bytesPerFrame;
5693 pWav->bytesRemaining -= bytesRead;
5699DRWAV_API drwav_uint64 drwav_read_pcm_frames_le(
drwav* pWav, drwav_uint64 framesToRead,
void* pBufferOut)
5701 drwav_uint32 bytesPerFrame;
5702 drwav_uint64 bytesToRead;
5703 drwav_uint64 framesRemainingInFile;
5705 if (pWav == NULL || framesToRead == 0) {
5710 if (drwav__is_compressed_format_tag(pWav->translatedFormatTag)) {
5714 framesRemainingInFile = pWav->totalPCMFrameCount - pWav->readCursorInPCMFrames;
5715 if (framesToRead > framesRemainingInFile) {
5716 framesToRead = framesRemainingInFile;
5719 bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
5720 if (bytesPerFrame == 0) {
5725 bytesToRead = framesToRead * bytesPerFrame;
5726 if (bytesToRead > DRWAV_SIZE_MAX) {
5727 bytesToRead = (DRWAV_SIZE_MAX / bytesPerFrame) * bytesPerFrame;
5734 if (bytesToRead == 0) {
5738 return drwav_read_raw(pWav, (
size_t)bytesToRead, pBufferOut) / bytesPerFrame;
5741DRWAV_API drwav_uint64 drwav_read_pcm_frames_be(
drwav* pWav, drwav_uint64 framesToRead,
void* pBufferOut)
5743 drwav_uint64 framesRead = drwav_read_pcm_frames_le(pWav, framesToRead, pBufferOut);
5745 if (pBufferOut != NULL) {
5746 drwav_uint32 bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
5747 if (bytesPerFrame == 0) {
5751 drwav__bswap_samples(pBufferOut, framesRead*pWav->channels, bytesPerFrame/pWav->channels);
5757DRWAV_API drwav_uint64 drwav_read_pcm_frames(
drwav* pWav, drwav_uint64 framesToRead,
void* pBufferOut)
5759 drwav_uint64 framesRead = 0;
5761 if (drwav_is_container_be(pWav->container)) {
5767 if (pWav->container != drwav_container_aiff || pWav->aiff.isLE == DRWAV_FALSE) {
5768 if (drwav__is_little_endian()) {
5769 framesRead = drwav_read_pcm_frames_be(pWav, framesToRead, pBufferOut);
5771 framesRead = drwav_read_pcm_frames_le(pWav, framesToRead, pBufferOut);
5779 if (drwav__is_little_endian()) {
5780 framesRead = drwav_read_pcm_frames_le(pWav, framesToRead, pBufferOut);
5782 framesRead = drwav_read_pcm_frames_be(pWav, framesToRead, pBufferOut);
5791 if (pWav->container == drwav_container_aiff && pWav->bitsPerSample == 8 && pWav->aiff.isUnsigned == DRWAV_FALSE) {
5792 if (pBufferOut != NULL) {
5793 drwav_uint64 iSample;
5795 for (iSample = 0; iSample < framesRead * pWav->channels; iSample += 1) {
5796 ((drwav_uint8*)pBufferOut)[iSample] += 128;
5807DRWAV_PRIVATE drwav_bool32 drwav_seek_to_first_pcm_frame(
drwav* pWav)
5809 if (pWav->onWrite != NULL) {
5813 if (!pWav->onSeek(pWav->pUserData, (
int)pWav->dataChunkDataPos, drwav_seek_origin_start)) {
5817 if (drwav__is_compressed_format_tag(pWav->translatedFormatTag)) {
5819 if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ADPCM) {
5820 DRWAV_ZERO_OBJECT(&pWav->msadpcm);
5821 }
else if (pWav->translatedFormatTag == DR_WAVE_FORMAT_DVI_ADPCM) {
5822 DRWAV_ZERO_OBJECT(&pWav->ima);
5824 DRWAV_ASSERT(DRWAV_FALSE);
5828 pWav->readCursorInPCMFrames = 0;
5829 pWav->bytesRemaining = pWav->dataChunkDataSize;
5834DRWAV_API drwav_bool32 drwav_seek_to_pcm_frame(
drwav* pWav, drwav_uint64 targetFrameIndex)
5838 if (pWav == NULL || pWav->onSeek == NULL) {
5843 if (pWav->onWrite != NULL) {
5848 if (pWav->totalPCMFrameCount == 0) {
5853 if (targetFrameIndex > pWav->totalPCMFrameCount) {
5854 targetFrameIndex = pWav->totalPCMFrameCount;
5861 if (drwav__is_compressed_format_tag(pWav->translatedFormatTag)) {
5868 if (targetFrameIndex < pWav->readCursorInPCMFrames) {
5869 if (!drwav_seek_to_first_pcm_frame(pWav)) {
5874 if (targetFrameIndex > pWav->readCursorInPCMFrames) {
5875 drwav_uint64 offsetInFrames = targetFrameIndex - pWav->readCursorInPCMFrames;
5877 drwav_int16 devnull[2048];
5878 while (offsetInFrames > 0) {
5879 drwav_uint64 framesRead = 0;
5880 drwav_uint64 framesToRead = offsetInFrames;
5881 if (framesToRead > drwav_countof(devnull)/pWav->channels) {
5882 framesToRead = drwav_countof(devnull)/pWav->channels;
5885 if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ADPCM) {
5886 framesRead = drwav_read_pcm_frames_s16__msadpcm(pWav, framesToRead, devnull);
5887 }
else if (pWav->translatedFormatTag == DR_WAVE_FORMAT_DVI_ADPCM) {
5888 framesRead = drwav_read_pcm_frames_s16__ima(pWav, framesToRead, devnull);
5890 DRWAV_ASSERT(DRWAV_FALSE);
5893 if (framesRead != framesToRead) {
5897 offsetInFrames -= framesRead;
5901 drwav_uint64 totalSizeInBytes;
5902 drwav_uint64 currentBytePos;
5903 drwav_uint64 targetBytePos;
5904 drwav_uint64 offset;
5905 drwav_uint32 bytesPerFrame;
5907 bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
5908 if (bytesPerFrame == 0) {
5912 totalSizeInBytes = pWav->totalPCMFrameCount * bytesPerFrame;
5915 currentBytePos = totalSizeInBytes - pWav->bytesRemaining;
5916 targetBytePos = targetFrameIndex * bytesPerFrame;
5918 if (currentBytePos < targetBytePos) {
5920 offset = (targetBytePos - currentBytePos);
5923 if (!drwav_seek_to_first_pcm_frame(pWav)) {
5926 offset = targetBytePos;
5929 while (offset > 0) {
5930 int offset32 = ((offset > INT_MAX) ? INT_MAX : (int)offset);
5931 if (!pWav->onSeek(pWav->pUserData, offset32, drwav_seek_origin_current)) {
5935 pWav->readCursorInPCMFrames += offset32 / bytesPerFrame;
5936 pWav->bytesRemaining -= offset32;
5944DRWAV_API drwav_result drwav_get_cursor_in_pcm_frames(
drwav* pWav, drwav_uint64* pCursor)
5946 if (pCursor == NULL) {
5947 return DRWAV_INVALID_ARGS;
5953 return DRWAV_INVALID_ARGS;
5956 *pCursor = pWav->readCursorInPCMFrames;
5958 return DRWAV_SUCCESS;
5961DRWAV_API drwav_result drwav_get_length_in_pcm_frames(
drwav* pWav, drwav_uint64* pLength)
5963 if (pLength == NULL) {
5964 return DRWAV_INVALID_ARGS;
5970 return DRWAV_INVALID_ARGS;
5973 *pLength = pWav->totalPCMFrameCount;
5975 return DRWAV_SUCCESS;
5979DRWAV_API
size_t drwav_write_raw(
drwav* pWav,
size_t bytesToWrite,
const void* pData)
5981 size_t bytesWritten;
5983 if (pWav == NULL || bytesToWrite == 0 || pData == NULL) {
5987 bytesWritten = pWav->onWrite(pWav->pUserData, pData, bytesToWrite);
5988 pWav->dataChunkDataSize += bytesWritten;
5990 return bytesWritten;
5993DRWAV_API drwav_uint64 drwav_write_pcm_frames_le(
drwav* pWav, drwav_uint64 framesToWrite,
const void* pData)
5995 drwav_uint64 bytesToWrite;
5996 drwav_uint64 bytesWritten;
5997 const drwav_uint8* pRunningData;
5999 if (pWav == NULL || framesToWrite == 0 || pData == NULL) {
6003 bytesToWrite = ((framesToWrite * pWav->channels * pWav->bitsPerSample) / 8);
6004 if (bytesToWrite > DRWAV_SIZE_MAX) {
6009 pRunningData = (
const drwav_uint8*)pData;
6011 while (bytesToWrite > 0) {
6012 size_t bytesJustWritten;
6013 drwav_uint64 bytesToWriteThisIteration;
6015 bytesToWriteThisIteration = bytesToWrite;
6016 DRWAV_ASSERT(bytesToWriteThisIteration <= DRWAV_SIZE_MAX);
6018 bytesJustWritten = drwav_write_raw(pWav, (
size_t)bytesToWriteThisIteration, pRunningData);
6019 if (bytesJustWritten == 0) {
6023 bytesToWrite -= bytesJustWritten;
6024 bytesWritten += bytesJustWritten;
6025 pRunningData += bytesJustWritten;
6028 return (bytesWritten * 8) / pWav->bitsPerSample / pWav->channels;
6031DRWAV_API drwav_uint64 drwav_write_pcm_frames_be(
drwav* pWav, drwav_uint64 framesToWrite,
const void* pData)
6033 drwav_uint64 bytesToWrite;
6034 drwav_uint64 bytesWritten;
6035 drwav_uint32 bytesPerSample;
6036 const drwav_uint8* pRunningData;
6038 if (pWav == NULL || framesToWrite == 0 || pData == NULL) {
6042 bytesToWrite = ((framesToWrite * pWav->channels * pWav->bitsPerSample) / 8);
6043 if (bytesToWrite > DRWAV_SIZE_MAX) {
6048 pRunningData = (
const drwav_uint8*)pData;
6050 bytesPerSample = drwav_get_bytes_per_pcm_frame(pWav) / pWav->channels;
6051 if (bytesPerSample == 0) {
6055 while (bytesToWrite > 0) {
6056 drwav_uint8 temp[4096];
6057 drwav_uint32 sampleCount;
6058 size_t bytesJustWritten;
6059 drwav_uint64 bytesToWriteThisIteration;
6061 bytesToWriteThisIteration = bytesToWrite;
6062 DRWAV_ASSERT(bytesToWriteThisIteration <= DRWAV_SIZE_MAX);
6068 sampleCount =
sizeof(temp)/bytesPerSample;
6070 if (bytesToWriteThisIteration > ((drwav_uint64)sampleCount)*bytesPerSample) {
6071 bytesToWriteThisIteration = ((drwav_uint64)sampleCount)*bytesPerSample;
6074 DRWAV_COPY_MEMORY(temp, pRunningData, (
size_t)bytesToWriteThisIteration);
6075 drwav__bswap_samples(temp, sampleCount, bytesPerSample);
6077 bytesJustWritten = drwav_write_raw(pWav, (
size_t)bytesToWriteThisIteration, temp);
6078 if (bytesJustWritten == 0) {
6082 bytesToWrite -= bytesJustWritten;
6083 bytesWritten += bytesJustWritten;
6084 pRunningData += bytesJustWritten;
6087 return (bytesWritten * 8) / pWav->bitsPerSample / pWav->channels;
6090DRWAV_API drwav_uint64 drwav_write_pcm_frames(
drwav* pWav, drwav_uint64 framesToWrite,
const void* pData)
6092 if (drwav__is_little_endian()) {
6093 return drwav_write_pcm_frames_le(pWav, framesToWrite, pData);
6095 return drwav_write_pcm_frames_be(pWav, framesToWrite, pData);
6100DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__msadpcm(
drwav* pWav, drwav_uint64 framesToRead, drwav_int16* pBufferOut)
6102 drwav_uint64 totalFramesRead = 0;
6104 DRWAV_ASSERT(pWav != NULL);
6105 DRWAV_ASSERT(framesToRead > 0);
6109 while (pWav->readCursorInPCMFrames < pWav->totalPCMFrameCount) {
6110 DRWAV_ASSERT(framesToRead > 0);
6113 if (pWav->msadpcm.cachedFrameCount == 0 && pWav->msadpcm.bytesRemainingInBlock == 0) {
6114 if (pWav->channels == 1) {
6116 drwav_uint8 header[7];
6117 if (pWav->onRead(pWav->pUserData, header,
sizeof(header)) !=
sizeof(header)) {
6118 return totalFramesRead;
6120 pWav->msadpcm.bytesRemainingInBlock = pWav->fmt.blockAlign -
sizeof(header);
6122 pWav->msadpcm.predictor[0] = header[0];
6123 pWav->msadpcm.delta[0] = drwav_bytes_to_s16(header + 1);
6124 pWav->msadpcm.prevFrames[0][1] = (drwav_int32)drwav_bytes_to_s16(header + 3);
6125 pWav->msadpcm.prevFrames[0][0] = (drwav_int32)drwav_bytes_to_s16(header + 5);
6126 pWav->msadpcm.cachedFrames[2] = pWav->msadpcm.prevFrames[0][0];
6127 pWav->msadpcm.cachedFrames[3] = pWav->msadpcm.prevFrames[0][1];
6128 pWav->msadpcm.cachedFrameCount = 2;
6131 drwav_uint8 header[14];
6132 if (pWav->onRead(pWav->pUserData, header,
sizeof(header)) !=
sizeof(header)) {
6133 return totalFramesRead;
6135 pWav->msadpcm.bytesRemainingInBlock = pWav->fmt.blockAlign -
sizeof(header);
6137 pWav->msadpcm.predictor[0] = header[0];
6138 pWav->msadpcm.predictor[1] = header[1];
6139 pWav->msadpcm.delta[0] = drwav_bytes_to_s16(header + 2);
6140 pWav->msadpcm.delta[1] = drwav_bytes_to_s16(header + 4);
6141 pWav->msadpcm.prevFrames[0][1] = (drwav_int32)drwav_bytes_to_s16(header + 6);
6142 pWav->msadpcm.prevFrames[1][1] = (drwav_int32)drwav_bytes_to_s16(header + 8);
6143 pWav->msadpcm.prevFrames[0][0] = (drwav_int32)drwav_bytes_to_s16(header + 10);
6144 pWav->msadpcm.prevFrames[1][0] = (drwav_int32)drwav_bytes_to_s16(header + 12);
6146 pWav->msadpcm.cachedFrames[0] = pWav->msadpcm.prevFrames[0][0];
6147 pWav->msadpcm.cachedFrames[1] = pWav->msadpcm.prevFrames[1][0];
6148 pWav->msadpcm.cachedFrames[2] = pWav->msadpcm.prevFrames[0][1];
6149 pWav->msadpcm.cachedFrames[3] = pWav->msadpcm.prevFrames[1][1];
6150 pWav->msadpcm.cachedFrameCount = 2;
6155 while (framesToRead > 0 && pWav->msadpcm.cachedFrameCount > 0 && pWav->readCursorInPCMFrames < pWav->totalPCMFrameCount) {
6156 if (pBufferOut != NULL) {
6157 drwav_uint32 iSample = 0;
6158 for (iSample = 0; iSample < pWav->channels; iSample += 1) {
6159 pBufferOut[iSample] = (drwav_int16)pWav->msadpcm.cachedFrames[(drwav_countof(pWav->msadpcm.cachedFrames) - (pWav->msadpcm.cachedFrameCount*pWav->channels)) + iSample];
6162 pBufferOut += pWav->channels;
6166 totalFramesRead += 1;
6167 pWav->readCursorInPCMFrames += 1;
6168 pWav->msadpcm.cachedFrameCount -= 1;
6171 if (framesToRead == 0) {
6180 if (pWav->msadpcm.cachedFrameCount == 0) {
6181 if (pWav->msadpcm.bytesRemainingInBlock == 0) {
6184 static drwav_int32 adaptationTable[] = {
6185 230, 230, 230, 230, 307, 409, 512, 614,
6186 768, 614, 512, 409, 307, 230, 230, 230
6188 static drwav_int32 coeff1Table[] = { 256, 512, 0, 192, 240, 460, 392 };
6189 static drwav_int32 coeff2Table[] = { 0, -256, 0, 64, 0, -208, -232 };
6191 drwav_uint8 nibbles;
6192 drwav_int32 nibble0;
6193 drwav_int32 nibble1;
6195 if (pWav->onRead(pWav->pUserData, &nibbles, 1) != 1) {
6196 return totalFramesRead;
6198 pWav->msadpcm.bytesRemainingInBlock -= 1;
6201 nibble0 = ((nibbles & 0xF0) >> 4);
if ((nibbles & 0x80)) { nibble0 |= 0xFFFFFFF0UL; }
6202 nibble1 = ((nibbles & 0x0F) >> 0);
if ((nibbles & 0x08)) { nibble1 |= 0xFFFFFFF0UL; }
6204 if (pWav->channels == 1) {
6206 drwav_int32 newSample0;
6207 drwav_int32 newSample1;
6209 newSample0 = ((pWav->msadpcm.prevFrames[0][1] * coeff1Table[pWav->msadpcm.predictor[0]]) + (pWav->msadpcm.prevFrames[0][0] * coeff2Table[pWav->msadpcm.predictor[0]])) >> 8;
6210 newSample0 += nibble0 * pWav->msadpcm.delta[0];
6211 newSample0 = drwav_clamp(newSample0, -32768, 32767);
6213 pWav->msadpcm.delta[0] = (adaptationTable[((nibbles & 0xF0) >> 4)] * pWav->msadpcm.delta[0]) >> 8;
6214 if (pWav->msadpcm.delta[0] < 16) {
6215 pWav->msadpcm.delta[0] = 16;
6218 pWav->msadpcm.prevFrames[0][0] = pWav->msadpcm.prevFrames[0][1];
6219 pWav->msadpcm.prevFrames[0][1] = newSample0;
6222 newSample1 = ((pWav->msadpcm.prevFrames[0][1] * coeff1Table[pWav->msadpcm.predictor[0]]) + (pWav->msadpcm.prevFrames[0][0] * coeff2Table[pWav->msadpcm.predictor[0]])) >> 8;
6223 newSample1 += nibble1 * pWav->msadpcm.delta[0];
6224 newSample1 = drwav_clamp(newSample1, -32768, 32767);
6226 pWav->msadpcm.delta[0] = (adaptationTable[((nibbles & 0x0F) >> 0)] * pWav->msadpcm.delta[0]) >> 8;
6227 if (pWav->msadpcm.delta[0] < 16) {
6228 pWav->msadpcm.delta[0] = 16;
6231 pWav->msadpcm.prevFrames[0][0] = pWav->msadpcm.prevFrames[0][1];
6232 pWav->msadpcm.prevFrames[0][1] = newSample1;
6235 pWav->msadpcm.cachedFrames[2] = newSample0;
6236 pWav->msadpcm.cachedFrames[3] = newSample1;
6237 pWav->msadpcm.cachedFrameCount = 2;
6240 drwav_int32 newSample0;
6241 drwav_int32 newSample1;
6244 newSample0 = ((pWav->msadpcm.prevFrames[0][1] * coeff1Table[pWav->msadpcm.predictor[0]]) + (pWav->msadpcm.prevFrames[0][0] * coeff2Table[pWav->msadpcm.predictor[0]])) >> 8;
6245 newSample0 += nibble0 * pWav->msadpcm.delta[0];
6246 newSample0 = drwav_clamp(newSample0, -32768, 32767);
6248 pWav->msadpcm.delta[0] = (adaptationTable[((nibbles & 0xF0) >> 4)] * pWav->msadpcm.delta[0]) >> 8;
6249 if (pWav->msadpcm.delta[0] < 16) {
6250 pWav->msadpcm.delta[0] = 16;
6253 pWav->msadpcm.prevFrames[0][0] = pWav->msadpcm.prevFrames[0][1];
6254 pWav->msadpcm.prevFrames[0][1] = newSample0;
6258 newSample1 = ((pWav->msadpcm.prevFrames[1][1] * coeff1Table[pWav->msadpcm.predictor[1]]) + (pWav->msadpcm.prevFrames[1][0] * coeff2Table[pWav->msadpcm.predictor[1]])) >> 8;
6259 newSample1 += nibble1 * pWav->msadpcm.delta[1];
6260 newSample1 = drwav_clamp(newSample1, -32768, 32767);
6262 pWav->msadpcm.delta[1] = (adaptationTable[((nibbles & 0x0F) >> 0)] * pWav->msadpcm.delta[1]) >> 8;
6263 if (pWav->msadpcm.delta[1] < 16) {
6264 pWav->msadpcm.delta[1] = 16;
6267 pWav->msadpcm.prevFrames[1][0] = pWav->msadpcm.prevFrames[1][1];
6268 pWav->msadpcm.prevFrames[1][1] = newSample1;
6270 pWav->msadpcm.cachedFrames[2] = newSample0;
6271 pWav->msadpcm.cachedFrames[3] = newSample1;
6272 pWav->msadpcm.cachedFrameCount = 1;
6278 return totalFramesRead;
6282DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__ima(
drwav* pWav, drwav_uint64 framesToRead, drwav_int16* pBufferOut)
6284 drwav_uint64 totalFramesRead = 0;
6285 drwav_uint32 iChannel;
6287 static drwav_int32 indexTable[16] = {
6288 -1, -1, -1, -1, 2, 4, 6, 8,
6289 -1, -1, -1, -1, 2, 4, 6, 8
6292 static drwav_int32 stepTable[89] = {
6293 7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
6294 19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
6295 50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
6296 130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
6297 337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
6298 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
6299 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
6300 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
6301 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
6304 DRWAV_ASSERT(pWav != NULL);
6305 DRWAV_ASSERT(framesToRead > 0);
6309 while (pWav->readCursorInPCMFrames < pWav->totalPCMFrameCount) {
6310 DRWAV_ASSERT(framesToRead > 0);
6313 if (pWav->ima.cachedFrameCount == 0 && pWav->ima.bytesRemainingInBlock == 0) {
6314 if (pWav->channels == 1) {
6316 drwav_uint8 header[4];
6317 if (pWav->onRead(pWav->pUserData, header,
sizeof(header)) !=
sizeof(header)) {
6318 return totalFramesRead;
6320 pWav->ima.bytesRemainingInBlock = pWav->fmt.blockAlign -
sizeof(header);
6322 if (header[2] >= drwav_countof(stepTable)) {
6323 pWav->onSeek(pWav->pUserData, pWav->ima.bytesRemainingInBlock, drwav_seek_origin_current);
6324 pWav->ima.bytesRemainingInBlock = 0;
6325 return totalFramesRead;
6328 pWav->ima.predictor[0] = (drwav_int16)drwav_bytes_to_u16(header + 0);
6329 pWav->ima.stepIndex[0] = drwav_clamp(header[2], 0, (drwav_int32)drwav_countof(stepTable)-1);
6330 pWav->ima.cachedFrames[drwav_countof(pWav->ima.cachedFrames) - 1] = pWav->ima.predictor[0];
6331 pWav->ima.cachedFrameCount = 1;
6334 drwav_uint8 header[8];
6335 if (pWav->onRead(pWav->pUserData, header,
sizeof(header)) !=
sizeof(header)) {
6336 return totalFramesRead;
6338 pWav->ima.bytesRemainingInBlock = pWav->fmt.blockAlign -
sizeof(header);
6340 if (header[2] >= drwav_countof(stepTable) || header[6] >= drwav_countof(stepTable)) {
6341 pWav->onSeek(pWav->pUserData, pWav->ima.bytesRemainingInBlock, drwav_seek_origin_current);
6342 pWav->ima.bytesRemainingInBlock = 0;
6343 return totalFramesRead;
6346 pWav->ima.predictor[0] = drwav_bytes_to_s16(header + 0);
6347 pWav->ima.stepIndex[0] = drwav_clamp(header[2], 0, (drwav_int32)drwav_countof(stepTable)-1);
6348 pWav->ima.predictor[1] = drwav_bytes_to_s16(header + 4);
6349 pWav->ima.stepIndex[1] = drwav_clamp(header[6], 0, (drwav_int32)drwav_countof(stepTable)-1);
6351 pWav->ima.cachedFrames[drwav_countof(pWav->ima.cachedFrames) - 2] = pWav->ima.predictor[0];
6352 pWav->ima.cachedFrames[drwav_countof(pWav->ima.cachedFrames) - 1] = pWav->ima.predictor[1];
6353 pWav->ima.cachedFrameCount = 1;
6358 while (framesToRead > 0 && pWav->ima.cachedFrameCount > 0 && pWav->readCursorInPCMFrames < pWav->totalPCMFrameCount) {
6359 if (pBufferOut != NULL) {
6360 drwav_uint32 iSample;
6361 for (iSample = 0; iSample < pWav->channels; iSample += 1) {
6362 pBufferOut[iSample] = (drwav_int16)pWav->ima.cachedFrames[(drwav_countof(pWav->ima.cachedFrames) - (pWav->ima.cachedFrameCount*pWav->channels)) + iSample];
6364 pBufferOut += pWav->channels;
6368 totalFramesRead += 1;
6369 pWav->readCursorInPCMFrames += 1;
6370 pWav->ima.cachedFrameCount -= 1;
6373 if (framesToRead == 0) {
6381 if (pWav->ima.cachedFrameCount == 0) {
6382 if (pWav->ima.bytesRemainingInBlock == 0) {
6389 pWav->ima.cachedFrameCount = 8;
6390 for (iChannel = 0; iChannel < pWav->channels; ++iChannel) {
6392 drwav_uint8 nibbles[4];
6393 if (pWav->onRead(pWav->pUserData, &nibbles, 4) != 4) {
6394 pWav->ima.cachedFrameCount = 0;
6395 return totalFramesRead;
6397 pWav->ima.bytesRemainingInBlock -= 4;
6399 for (iByte = 0; iByte < 4; ++iByte) {
6400 drwav_uint8 nibble0 = ((nibbles[iByte] & 0x0F) >> 0);
6401 drwav_uint8 nibble1 = ((nibbles[iByte] & 0xF0) >> 4);
6403 drwav_int32 step = stepTable[pWav->ima.stepIndex[iChannel]];
6404 drwav_int32 predictor = pWav->ima.predictor[iChannel];
6406 drwav_int32 diff = step >> 3;
6407 if (nibble0 & 1) diff += step >> 2;
6408 if (nibble0 & 2) diff += step >> 1;
6409 if (nibble0 & 4) diff += step;
6410 if (nibble0 & 8) diff = -diff;
6412 predictor = drwav_clamp(predictor + diff, -32768, 32767);
6413 pWav->ima.predictor[iChannel] = predictor;
6414 pWav->ima.stepIndex[iChannel] = drwav_clamp(pWav->ima.stepIndex[iChannel] + indexTable[nibble0], 0, (drwav_int32)drwav_countof(stepTable)-1);
6415 pWav->ima.cachedFrames[(drwav_countof(pWav->ima.cachedFrames) - (pWav->ima.cachedFrameCount*pWav->channels)) + (iByte*2+0)*pWav->channels + iChannel] = predictor;
6418 step = stepTable[pWav->ima.stepIndex[iChannel]];
6419 predictor = pWav->ima.predictor[iChannel];
6422 if (nibble1 & 1) diff += step >> 2;
6423 if (nibble1 & 2) diff += step >> 1;
6424 if (nibble1 & 4) diff += step;
6425 if (nibble1 & 8) diff = -diff;
6427 predictor = drwav_clamp(predictor + diff, -32768, 32767);
6428 pWav->ima.predictor[iChannel] = predictor;
6429 pWav->ima.stepIndex[iChannel] = drwav_clamp(pWav->ima.stepIndex[iChannel] + indexTable[nibble1], 0, (drwav_int32)drwav_countof(stepTable)-1);
6430 pWav->ima.cachedFrames[(drwav_countof(pWav->ima.cachedFrames) - (pWav->ima.cachedFrameCount*pWav->channels)) + (iByte*2+1)*pWav->channels + iChannel] = predictor;
6437 return totalFramesRead;
6441#ifndef DR_WAV_NO_CONVERSION_API
6442static unsigned short g_drwavAlawTable[256] = {
6443 0xEA80, 0xEB80, 0xE880, 0xE980, 0xEE80, 0xEF80, 0xEC80, 0xED80, 0xE280, 0xE380, 0xE080, 0xE180, 0xE680, 0xE780, 0xE480, 0xE580,
6444 0xF540, 0xF5C0, 0xF440, 0xF4C0, 0xF740, 0xF7C0, 0xF640, 0xF6C0, 0xF140, 0xF1C0, 0xF040, 0xF0C0, 0xF340, 0xF3C0, 0xF240, 0xF2C0,
6445 0xAA00, 0xAE00, 0xA200, 0xA600, 0xBA00, 0xBE00, 0xB200, 0xB600, 0x8A00, 0x8E00, 0x8200, 0x8600, 0x9A00, 0x9E00, 0x9200, 0x9600,
6446 0xD500, 0xD700, 0xD100, 0xD300, 0xDD00, 0xDF00, 0xD900, 0xDB00, 0xC500, 0xC700, 0xC100, 0xC300, 0xCD00, 0xCF00, 0xC900, 0xCB00,
6447 0xFEA8, 0xFEB8, 0xFE88, 0xFE98, 0xFEE8, 0xFEF8, 0xFEC8, 0xFED8, 0xFE28, 0xFE38, 0xFE08, 0xFE18, 0xFE68, 0xFE78, 0xFE48, 0xFE58,
6448 0xFFA8, 0xFFB8, 0xFF88, 0xFF98, 0xFFE8, 0xFFF8, 0xFFC8, 0xFFD8, 0xFF28, 0xFF38, 0xFF08, 0xFF18, 0xFF68, 0xFF78, 0xFF48, 0xFF58,
6449 0xFAA0, 0xFAE0, 0xFA20, 0xFA60, 0xFBA0, 0xFBE0, 0xFB20, 0xFB60, 0xF8A0, 0xF8E0, 0xF820, 0xF860, 0xF9A0, 0xF9E0, 0xF920, 0xF960,
6450 0xFD50, 0xFD70, 0xFD10, 0xFD30, 0xFDD0, 0xFDF0, 0xFD90, 0xFDB0, 0xFC50, 0xFC70, 0xFC10, 0xFC30, 0xFCD0, 0xFCF0, 0xFC90, 0xFCB0,
6451 0x1580, 0x1480, 0x1780, 0x1680, 0x1180, 0x1080, 0x1380, 0x1280, 0x1D80, 0x1C80, 0x1F80, 0x1E80, 0x1980, 0x1880, 0x1B80, 0x1A80,
6452 0x0AC0, 0x0A40, 0x0BC0, 0x0B40, 0x08C0, 0x0840, 0x09C0, 0x0940, 0x0EC0, 0x0E40, 0x0FC0, 0x0F40, 0x0CC0, 0x0C40, 0x0DC0, 0x0D40,
6453 0x5600, 0x5200, 0x5E00, 0x5A00, 0x4600, 0x4200, 0x4E00, 0x4A00, 0x7600, 0x7200, 0x7E00, 0x7A00, 0x6600, 0x6200, 0x6E00, 0x6A00,
6454 0x2B00, 0x2900, 0x2F00, 0x2D00, 0x2300, 0x2100, 0x2700, 0x2500, 0x3B00, 0x3900, 0x3F00, 0x3D00, 0x3300, 0x3100, 0x3700, 0x3500,
6455 0x0158, 0x0148, 0x0178, 0x0168, 0x0118, 0x0108, 0x0138, 0x0128, 0x01D8, 0x01C8, 0x01F8, 0x01E8, 0x0198, 0x0188, 0x01B8, 0x01A8,
6456 0x0058, 0x0048, 0x0078, 0x0068, 0x0018, 0x0008, 0x0038, 0x0028, 0x00D8, 0x00C8, 0x00F8, 0x00E8, 0x0098, 0x0088, 0x00B8, 0x00A8,
6457 0x0560, 0x0520, 0x05E0, 0x05A0, 0x0460, 0x0420, 0x04E0, 0x04A0, 0x0760, 0x0720, 0x07E0, 0x07A0, 0x0660, 0x0620, 0x06E0, 0x06A0,
6458 0x02B0, 0x0290, 0x02F0, 0x02D0, 0x0230, 0x0210, 0x0270, 0x0250, 0x03B0, 0x0390, 0x03F0, 0x03D0, 0x0330, 0x0310, 0x0370, 0x0350
6461static unsigned short g_drwavMulawTable[256] = {
6462 0x8284, 0x8684, 0x8A84, 0x8E84, 0x9284, 0x9684, 0x9A84, 0x9E84, 0xA284, 0xA684, 0xAA84, 0xAE84, 0xB284, 0xB684, 0xBA84, 0xBE84,
6463 0xC184, 0xC384, 0xC584, 0xC784, 0xC984, 0xCB84, 0xCD84, 0xCF84, 0xD184, 0xD384, 0xD584, 0xD784, 0xD984, 0xDB84, 0xDD84, 0xDF84,
6464 0xE104, 0xE204, 0xE304, 0xE404, 0xE504, 0xE604, 0xE704, 0xE804, 0xE904, 0xEA04, 0xEB04, 0xEC04, 0xED04, 0xEE04, 0xEF04, 0xF004,
6465 0xF0C4, 0xF144, 0xF1C4, 0xF244, 0xF2C4, 0xF344, 0xF3C4, 0xF444, 0xF4C4, 0xF544, 0xF5C4, 0xF644, 0xF6C4, 0xF744, 0xF7C4, 0xF844,
6466 0xF8A4, 0xF8E4, 0xF924, 0xF964, 0xF9A4, 0xF9E4, 0xFA24, 0xFA64, 0xFAA4, 0xFAE4, 0xFB24, 0xFB64, 0xFBA4, 0xFBE4, 0xFC24, 0xFC64,
6467 0xFC94, 0xFCB4, 0xFCD4, 0xFCF4, 0xFD14, 0xFD34, 0xFD54, 0xFD74, 0xFD94, 0xFDB4, 0xFDD4, 0xFDF4, 0xFE14, 0xFE34, 0xFE54, 0xFE74,
6468 0xFE8C, 0xFE9C, 0xFEAC, 0xFEBC, 0xFECC, 0xFEDC, 0xFEEC, 0xFEFC, 0xFF0C, 0xFF1C, 0xFF2C, 0xFF3C, 0xFF4C, 0xFF5C, 0xFF6C, 0xFF7C,
6469 0xFF88, 0xFF90, 0xFF98, 0xFFA0, 0xFFA8, 0xFFB0, 0xFFB8, 0xFFC0, 0xFFC8, 0xFFD0, 0xFFD8, 0xFFE0, 0xFFE8, 0xFFF0, 0xFFF8, 0x0000,
6470 0x7D7C, 0x797C, 0x757C, 0x717C, 0x6D7C, 0x697C, 0x657C, 0x617C, 0x5D7C, 0x597C, 0x557C, 0x517C, 0x4D7C, 0x497C, 0x457C, 0x417C,
6471 0x3E7C, 0x3C7C, 0x3A7C, 0x387C, 0x367C, 0x347C, 0x327C, 0x307C, 0x2E7C, 0x2C7C, 0x2A7C, 0x287C, 0x267C, 0x247C, 0x227C, 0x207C,
6472 0x1EFC, 0x1DFC, 0x1CFC, 0x1BFC, 0x1AFC, 0x19FC, 0x18FC, 0x17FC, 0x16FC, 0x15FC, 0x14FC, 0x13FC, 0x12FC, 0x11FC, 0x10FC, 0x0FFC,
6473 0x0F3C, 0x0EBC, 0x0E3C, 0x0DBC, 0x0D3C, 0x0CBC, 0x0C3C, 0x0BBC, 0x0B3C, 0x0ABC, 0x0A3C, 0x09BC, 0x093C, 0x08BC, 0x083C, 0x07BC,
6474 0x075C, 0x071C, 0x06DC, 0x069C, 0x065C, 0x061C, 0x05DC, 0x059C, 0x055C, 0x051C, 0x04DC, 0x049C, 0x045C, 0x041C, 0x03DC, 0x039C,
6475 0x036C, 0x034C, 0x032C, 0x030C, 0x02EC, 0x02CC, 0x02AC, 0x028C, 0x026C, 0x024C, 0x022C, 0x020C, 0x01EC, 0x01CC, 0x01AC, 0x018C,
6476 0x0174, 0x0164, 0x0154, 0x0144, 0x0134, 0x0124, 0x0114, 0x0104, 0x00F4, 0x00E4, 0x00D4, 0x00C4, 0x00B4, 0x00A4, 0x0094, 0x0084,
6477 0x0078, 0x0070, 0x0068, 0x0060, 0x0058, 0x0050, 0x0048, 0x0040, 0x0038, 0x0030, 0x0028, 0x0020, 0x0018, 0x0010, 0x0008, 0x0000
6480static DRWAV_INLINE drwav_int16 drwav__alaw_to_s16(drwav_uint8 sampleIn)
6482 return (
short)g_drwavAlawTable[sampleIn];
6485static DRWAV_INLINE drwav_int16 drwav__mulaw_to_s16(drwav_uint8 sampleIn)
6487 return (
short)g_drwavMulawTable[sampleIn];
6492DRWAV_PRIVATE
void drwav__pcm_to_s16(drwav_int16* pOut,
const drwav_uint8* pIn,
size_t totalSampleCount,
unsigned int bytesPerSample)
6497 if (bytesPerSample == 1) {
6498 drwav_u8_to_s16(pOut, pIn, totalSampleCount);
6504 if (bytesPerSample == 2) {
6505 for (i = 0; i < totalSampleCount; ++i) {
6506 *pOut++ = ((
const drwav_int16*)pIn)[i];
6510 if (bytesPerSample == 3) {
6511 drwav_s24_to_s16(pOut, pIn, totalSampleCount);
6514 if (bytesPerSample == 4) {
6515 drwav_s32_to_s16(pOut, (
const drwav_int32*)pIn, totalSampleCount);
6521 if (bytesPerSample > 8) {
6522 DRWAV_ZERO_MEMORY(pOut, totalSampleCount *
sizeof(*pOut));
6528 for (i = 0; i < totalSampleCount; ++i) {
6529 drwav_uint64 sample = 0;
6530 unsigned int shift = (8 - bytesPerSample) * 8;
6533 for (j = 0; j < bytesPerSample; j += 1) {
6534 DRWAV_ASSERT(j < 8);
6535 sample |= (drwav_uint64)(pIn[j]) << shift;
6540 *pOut++ = (drwav_int16)((drwav_int64)sample >> 48);
6544DRWAV_PRIVATE
void drwav__ieee_to_s16(drwav_int16* pOut,
const drwav_uint8* pIn,
size_t totalSampleCount,
unsigned int bytesPerSample)
6546 if (bytesPerSample == 4) {
6547 drwav_f32_to_s16(pOut, (
const float*)pIn, totalSampleCount);
6549 }
else if (bytesPerSample == 8) {
6550 drwav_f64_to_s16(pOut, (
const double*)pIn, totalSampleCount);
6554 DRWAV_ZERO_MEMORY(pOut, totalSampleCount *
sizeof(*pOut));
6559DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__pcm(
drwav* pWav, drwav_uint64 framesToRead, drwav_int16* pBufferOut)
6561 drwav_uint64 totalFramesRead;
6562 drwav_uint8 sampleData[4096] = {0};
6563 drwav_uint32 bytesPerFrame;
6564 drwav_uint32 bytesPerSample;
6565 drwav_uint64 samplesRead;
6568 if ((pWav->translatedFormatTag == DR_WAVE_FORMAT_PCM && pWav->bitsPerSample == 16) || pBufferOut == NULL) {
6569 return drwav_read_pcm_frames(pWav, framesToRead, pBufferOut);
6572 bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
6573 if (bytesPerFrame == 0) {
6577 bytesPerSample = bytesPerFrame / pWav->channels;
6578 if (bytesPerSample == 0 || (bytesPerFrame % pWav->channels) != 0) {
6582 totalFramesRead = 0;
6584 while (framesToRead > 0) {
6585 drwav_uint64 framesToReadThisIteration = drwav_min(framesToRead,
sizeof(sampleData)/bytesPerFrame);
6586 drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, framesToReadThisIteration, sampleData);
6587 if (framesRead == 0) {
6591 DRWAV_ASSERT(framesRead <= framesToReadThisIteration);
6594 samplesRead = framesRead * pWav->channels;
6595 if ((samplesRead * bytesPerSample) >
sizeof(sampleData)) {
6596 DRWAV_ASSERT(DRWAV_FALSE);
6600 drwav__pcm_to_s16(pBufferOut, sampleData, (
size_t)samplesRead, bytesPerSample);
6602 pBufferOut += samplesRead;
6603 framesToRead -= framesRead;
6604 totalFramesRead += framesRead;
6607 return totalFramesRead;
6610DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__ieee(
drwav* pWav, drwav_uint64 framesToRead, drwav_int16* pBufferOut)
6612 drwav_uint64 totalFramesRead;
6613 drwav_uint8 sampleData[4096] = {0};
6614 drwav_uint32 bytesPerFrame;
6615 drwav_uint32 bytesPerSample;
6616 drwav_uint64 samplesRead;
6618 if (pBufferOut == NULL) {
6619 return drwav_read_pcm_frames(pWav, framesToRead, NULL);
6622 bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
6623 if (bytesPerFrame == 0) {
6627 bytesPerSample = bytesPerFrame / pWav->channels;
6628 if (bytesPerSample == 0 || (bytesPerFrame % pWav->channels) != 0) {
6632 totalFramesRead = 0;
6634 while (framesToRead > 0) {
6635 drwav_uint64 framesToReadThisIteration = drwav_min(framesToRead,
sizeof(sampleData)/bytesPerFrame);
6636 drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, framesToReadThisIteration, sampleData);
6637 if (framesRead == 0) {
6641 DRWAV_ASSERT(framesRead <= framesToReadThisIteration);
6644 samplesRead = framesRead * pWav->channels;
6645 if ((samplesRead * bytesPerSample) >
sizeof(sampleData)) {
6646 DRWAV_ASSERT(DRWAV_FALSE);
6650 drwav__ieee_to_s16(pBufferOut, sampleData, (
size_t)samplesRead, bytesPerSample);
6652 pBufferOut += samplesRead;
6653 framesToRead -= framesRead;
6654 totalFramesRead += framesRead;
6657 return totalFramesRead;
6660DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__alaw(
drwav* pWav, drwav_uint64 framesToRead, drwav_int16* pBufferOut)
6662 drwav_uint64 totalFramesRead;
6663 drwav_uint8 sampleData[4096] = {0};
6664 drwav_uint32 bytesPerFrame;
6665 drwav_uint32 bytesPerSample;
6666 drwav_uint64 samplesRead;
6668 if (pBufferOut == NULL) {
6669 return drwav_read_pcm_frames(pWav, framesToRead, NULL);
6672 bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
6673 if (bytesPerFrame == 0) {
6677 bytesPerSample = bytesPerFrame / pWav->channels;
6678 if (bytesPerSample == 0 || (bytesPerFrame % pWav->channels) != 0) {
6682 totalFramesRead = 0;
6684 while (framesToRead > 0) {
6685 drwav_uint64 framesToReadThisIteration = drwav_min(framesToRead,
sizeof(sampleData)/bytesPerFrame);
6686 drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, framesToReadThisIteration, sampleData);
6687 if (framesRead == 0) {
6691 DRWAV_ASSERT(framesRead <= framesToReadThisIteration);
6694 samplesRead = framesRead * pWav->channels;
6695 if ((samplesRead * bytesPerSample) >
sizeof(sampleData)) {
6696 DRWAV_ASSERT(DRWAV_FALSE);
6700 drwav_alaw_to_s16(pBufferOut, sampleData, (
size_t)samplesRead);
6708 #ifdef DR_WAV_LIBSNDFILE_COMPAT
6710 if (pWav->container == drwav_container_aiff) {
6711 drwav_uint64 iSample;
6712 for (iSample = 0; iSample < samplesRead; iSample += 1) {
6713 pBufferOut[iSample] = -pBufferOut[iSample];
6719 pBufferOut += samplesRead;
6720 framesToRead -= framesRead;
6721 totalFramesRead += framesRead;
6724 return totalFramesRead;
6727DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__mulaw(
drwav* pWav, drwav_uint64 framesToRead, drwav_int16* pBufferOut)
6729 drwav_uint64 totalFramesRead;
6730 drwav_uint8 sampleData[4096] = {0};
6731 drwav_uint32 bytesPerFrame;
6732 drwav_uint32 bytesPerSample;
6733 drwav_uint64 samplesRead;
6735 if (pBufferOut == NULL) {
6736 return drwav_read_pcm_frames(pWav, framesToRead, NULL);
6739 bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
6740 if (bytesPerFrame == 0) {
6744 bytesPerSample = bytesPerFrame / pWav->channels;
6745 if (bytesPerSample == 0 || (bytesPerFrame % pWav->channels) != 0) {
6749 totalFramesRead = 0;
6751 while (framesToRead > 0) {
6752 drwav_uint64 framesToReadThisIteration = drwav_min(framesToRead,
sizeof(sampleData)/bytesPerFrame);
6753 drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, framesToReadThisIteration, sampleData);
6754 if (framesRead == 0) {
6758 DRWAV_ASSERT(framesRead <= framesToReadThisIteration);
6761 samplesRead = framesRead * pWav->channels;
6762 if ((samplesRead * bytesPerSample) >
sizeof(sampleData)) {
6763 DRWAV_ASSERT(DRWAV_FALSE);
6767 drwav_mulaw_to_s16(pBufferOut, sampleData, (
size_t)samplesRead);
6773 #ifdef DR_WAV_LIBSNDFILE_COMPAT
6775 if (pWav->container == drwav_container_aiff) {
6776 drwav_uint64 iSample;
6777 for (iSample = 0; iSample < samplesRead; iSample += 1) {
6778 pBufferOut[iSample] = -pBufferOut[iSample];
6784 pBufferOut += samplesRead;
6785 framesToRead -= framesRead;
6786 totalFramesRead += framesRead;
6789 return totalFramesRead;
6792DRWAV_API drwav_uint64 drwav_read_pcm_frames_s16(
drwav* pWav, drwav_uint64 framesToRead, drwav_int16* pBufferOut)
6794 if (pWav == NULL || framesToRead == 0) {
6798 if (pBufferOut == NULL) {
6799 return drwav_read_pcm_frames(pWav, framesToRead, NULL);
6803 if (framesToRead * pWav->channels *
sizeof(drwav_int16) > DRWAV_SIZE_MAX) {
6804 framesToRead = DRWAV_SIZE_MAX /
sizeof(drwav_int16) / pWav->channels;
6807 if (pWav->translatedFormatTag == DR_WAVE_FORMAT_PCM) {
6808 return drwav_read_pcm_frames_s16__pcm(pWav, framesToRead, pBufferOut);
6811 if (pWav->translatedFormatTag == DR_WAVE_FORMAT_IEEE_FLOAT) {
6812 return drwav_read_pcm_frames_s16__ieee(pWav, framesToRead, pBufferOut);
6815 if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ALAW) {
6816 return drwav_read_pcm_frames_s16__alaw(pWav, framesToRead, pBufferOut);
6819 if (pWav->translatedFormatTag == DR_WAVE_FORMAT_MULAW) {
6820 return drwav_read_pcm_frames_s16__mulaw(pWav, framesToRead, pBufferOut);
6823 if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ADPCM) {
6824 return drwav_read_pcm_frames_s16__msadpcm(pWav, framesToRead, pBufferOut);
6827 if (pWav->translatedFormatTag == DR_WAVE_FORMAT_DVI_ADPCM) {
6828 return drwav_read_pcm_frames_s16__ima(pWav, framesToRead, pBufferOut);
6834DRWAV_API drwav_uint64 drwav_read_pcm_frames_s16le(
drwav* pWav, drwav_uint64 framesToRead, drwav_int16* pBufferOut)
6836 drwav_uint64 framesRead = drwav_read_pcm_frames_s16(pWav, framesToRead, pBufferOut);
6837 if (pBufferOut != NULL && drwav__is_little_endian() == DRWAV_FALSE) {
6838 drwav__bswap_samples_s16(pBufferOut, framesRead*pWav->channels);
6844DRWAV_API drwav_uint64 drwav_read_pcm_frames_s16be(
drwav* pWav, drwav_uint64 framesToRead, drwav_int16* pBufferOut)
6846 drwav_uint64 framesRead = drwav_read_pcm_frames_s16(pWav, framesToRead, pBufferOut);
6847 if (pBufferOut != NULL && drwav__is_little_endian() == DRWAV_TRUE) {
6848 drwav__bswap_samples_s16(pBufferOut, framesRead*pWav->channels);
6855DRWAV_API
void drwav_u8_to_s16(drwav_int16* pOut,
const drwav_uint8* pIn,
size_t sampleCount)
6859 for (i = 0; i < sampleCount; ++i) {
6867DRWAV_API
void drwav_s24_to_s16(drwav_int16* pOut,
const drwav_uint8* pIn,
size_t sampleCount)
6871 for (i = 0; i < sampleCount; ++i) {
6872 int x = ((int)(((
unsigned int)(((
const drwav_uint8*)pIn)[i*3+0]) << 8) | ((
unsigned int)(((
const drwav_uint8*)pIn)[i*3+1]) << 16) | ((
unsigned int)(((
const drwav_uint8*)pIn)[i*3+2])) << 24)) >> 8;
6878DRWAV_API
void drwav_s32_to_s16(drwav_int16* pOut,
const drwav_int32* pIn,
size_t sampleCount)
6882 for (i = 0; i < sampleCount; ++i) {
6889DRWAV_API
void drwav_f32_to_s16(drwav_int16* pOut,
const float* pIn,
size_t sampleCount)
6893 for (i = 0; i < sampleCount; ++i) {
6896 c = ((x < -1) ? -1 : ((x > 1) ? 1 : x));
6898 r = (int)(c * 32767.5f);
6904DRWAV_API
void drwav_f64_to_s16(drwav_int16* pOut,
const double* pIn,
size_t sampleCount)
6908 for (i = 0; i < sampleCount; ++i) {
6911 c = ((x < -1) ? -1 : ((x > 1) ? 1 : x));
6913 r = (int)(c * 32767.5);
6919DRWAV_API
void drwav_alaw_to_s16(drwav_int16* pOut,
const drwav_uint8* pIn,
size_t sampleCount)
6922 for (i = 0; i < sampleCount; ++i) {
6923 pOut[i] = drwav__alaw_to_s16(pIn[i]);
6927DRWAV_API
void drwav_mulaw_to_s16(drwav_int16* pOut,
const drwav_uint8* pIn,
size_t sampleCount)
6930 for (i = 0; i < sampleCount; ++i) {
6931 pOut[i] = drwav__mulaw_to_s16(pIn[i]);
6936DRWAV_PRIVATE
void drwav__pcm_to_f32(
float* pOut,
const drwav_uint8* pIn,
size_t sampleCount,
unsigned int bytesPerSample)
6941 if (bytesPerSample == 1) {
6942 drwav_u8_to_f32(pOut, pIn, sampleCount);
6947 if (bytesPerSample == 2) {
6948 drwav_s16_to_f32(pOut, (
const drwav_int16*)pIn, sampleCount);
6951 if (bytesPerSample == 3) {
6952 drwav_s24_to_f32(pOut, pIn, sampleCount);
6955 if (bytesPerSample == 4) {
6956 drwav_s32_to_f32(pOut, (
const drwav_int32*)pIn, sampleCount);
6962 if (bytesPerSample > 8) {
6963 DRWAV_ZERO_MEMORY(pOut, sampleCount *
sizeof(*pOut));
6969 for (i = 0; i < sampleCount; ++i) {
6970 drwav_uint64 sample = 0;
6971 unsigned int shift = (8 - bytesPerSample) * 8;
6974 for (j = 0; j < bytesPerSample; j += 1) {
6975 DRWAV_ASSERT(j < 8);
6976 sample |= (drwav_uint64)(pIn[j]) << shift;
6981 *pOut++ = (float)((drwav_int64)sample / 9223372036854775807.0);
6985DRWAV_PRIVATE
void drwav__ieee_to_f32(
float* pOut,
const drwav_uint8* pIn,
size_t sampleCount,
unsigned int bytesPerSample)
6987 if (bytesPerSample == 4) {
6989 for (i = 0; i < sampleCount; ++i) {
6990 *pOut++ = ((
const float*)pIn)[i];
6993 }
else if (bytesPerSample == 8) {
6994 drwav_f64_to_f32(pOut, (
const double*)pIn, sampleCount);
6998 DRWAV_ZERO_MEMORY(pOut, sampleCount *
sizeof(*pOut));
7004DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_f32__pcm(
drwav* pWav, drwav_uint64 framesToRead,
float* pBufferOut)
7006 drwav_uint64 totalFramesRead;
7007 drwav_uint8 sampleData[4096] = {0};
7008 drwav_uint32 bytesPerFrame;
7009 drwav_uint32 bytesPerSample;
7010 drwav_uint64 samplesRead;
7012 bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
7013 if (bytesPerFrame == 0) {
7017 bytesPerSample = bytesPerFrame / pWav->channels;
7018 if (bytesPerSample == 0 || (bytesPerFrame % pWav->channels) != 0) {
7022 totalFramesRead = 0;
7024 while (framesToRead > 0) {
7025 drwav_uint64 framesToReadThisIteration = drwav_min(framesToRead,
sizeof(sampleData)/bytesPerFrame);
7026 drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, framesToReadThisIteration, sampleData);
7027 if (framesRead == 0) {
7031 DRWAV_ASSERT(framesRead <= framesToReadThisIteration);
7034 samplesRead = framesRead * pWav->channels;
7035 if ((samplesRead * bytesPerSample) >
sizeof(sampleData)) {
7036 DRWAV_ASSERT(DRWAV_FALSE);
7040 drwav__pcm_to_f32(pBufferOut, sampleData, (
size_t)samplesRead, bytesPerSample);
7042 pBufferOut += samplesRead;
7043 framesToRead -= framesRead;
7044 totalFramesRead += framesRead;
7047 return totalFramesRead;
7050DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_f32__msadpcm_ima(
drwav* pWav, drwav_uint64 framesToRead,
float* pBufferOut)
7056 drwav_uint64 totalFramesRead;
7057 drwav_int16 samples16[2048];
7059 totalFramesRead = 0;
7061 while (framesToRead > 0) {
7062 drwav_uint64 framesToReadThisIteration = drwav_min(framesToRead, drwav_countof(samples16)/pWav->channels);
7063 drwav_uint64 framesRead = drwav_read_pcm_frames_s16(pWav, framesToReadThisIteration, samples16);
7064 if (framesRead == 0) {
7068 DRWAV_ASSERT(framesRead <= framesToReadThisIteration);
7070 drwav_s16_to_f32(pBufferOut, samples16, (
size_t)(framesRead*pWav->channels));
7072 pBufferOut += framesRead*pWav->channels;
7073 framesToRead -= framesRead;
7074 totalFramesRead += framesRead;
7077 return totalFramesRead;
7080DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_f32__ieee(
drwav* pWav, drwav_uint64 framesToRead,
float* pBufferOut)
7082 drwav_uint64 totalFramesRead;
7083 drwav_uint8 sampleData[4096] = {0};
7084 drwav_uint32 bytesPerFrame;
7085 drwav_uint32 bytesPerSample;
7086 drwav_uint64 samplesRead;
7089 if (pWav->translatedFormatTag == DR_WAVE_FORMAT_IEEE_FLOAT && pWav->bitsPerSample == 32) {
7090 return drwav_read_pcm_frames(pWav, framesToRead, pBufferOut);
7093 bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
7094 if (bytesPerFrame == 0) {
7098 bytesPerSample = bytesPerFrame / pWav->channels;
7099 if (bytesPerSample == 0 || (bytesPerFrame % pWav->channels) != 0) {
7103 totalFramesRead = 0;
7105 while (framesToRead > 0) {
7106 drwav_uint64 framesToReadThisIteration = drwav_min(framesToRead,
sizeof(sampleData)/bytesPerFrame);
7107 drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, framesToReadThisIteration, sampleData);
7108 if (framesRead == 0) {
7112 DRWAV_ASSERT(framesRead <= framesToReadThisIteration);
7115 samplesRead = framesRead * pWav->channels;
7116 if ((samplesRead * bytesPerSample) >
sizeof(sampleData)) {
7117 DRWAV_ASSERT(DRWAV_FALSE);
7121 drwav__ieee_to_f32(pBufferOut, sampleData, (
size_t)samplesRead, bytesPerSample);
7123 pBufferOut += samplesRead;
7124 framesToRead -= framesRead;
7125 totalFramesRead += framesRead;
7128 return totalFramesRead;
7131DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_f32__alaw(
drwav* pWav, drwav_uint64 framesToRead,
float* pBufferOut)
7133 drwav_uint64 totalFramesRead;
7134 drwav_uint8 sampleData[4096] = {0};
7135 drwav_uint32 bytesPerFrame;
7136 drwav_uint32 bytesPerSample;
7137 drwav_uint64 samplesRead;
7139 bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
7140 if (bytesPerFrame == 0) {
7144 bytesPerSample = bytesPerFrame / pWav->channels;
7145 if (bytesPerSample == 0 || (bytesPerFrame % pWav->channels) != 0) {
7149 totalFramesRead = 0;
7151 while (framesToRead > 0) {
7152 drwav_uint64 framesToReadThisIteration = drwav_min(framesToRead,
sizeof(sampleData)/bytesPerFrame);
7153 drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, framesToReadThisIteration, sampleData);
7154 if (framesRead == 0) {
7158 DRWAV_ASSERT(framesRead <= framesToReadThisIteration);
7161 samplesRead = framesRead * pWav->channels;
7162 if ((samplesRead * bytesPerSample) >
sizeof(sampleData)) {
7163 DRWAV_ASSERT(DRWAV_FALSE);
7167 drwav_alaw_to_f32(pBufferOut, sampleData, (
size_t)samplesRead);
7169 #ifdef DR_WAV_LIBSNDFILE_COMPAT
7171 if (pWav->container == drwav_container_aiff) {
7172 drwav_uint64 iSample;
7173 for (iSample = 0; iSample < samplesRead; iSample += 1) {
7174 pBufferOut[iSample] = -pBufferOut[iSample];
7180 pBufferOut += samplesRead;
7181 framesToRead -= framesRead;
7182 totalFramesRead += framesRead;
7185 return totalFramesRead;
7188DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_f32__mulaw(
drwav* pWav, drwav_uint64 framesToRead,
float* pBufferOut)
7190 drwav_uint64 totalFramesRead;
7191 drwav_uint8 sampleData[4096] = {0};
7192 drwav_uint32 bytesPerFrame;
7193 drwav_uint32 bytesPerSample;
7194 drwav_uint64 samplesRead;
7196 bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
7197 if (bytesPerFrame == 0) {
7201 bytesPerSample = bytesPerFrame / pWav->channels;
7202 if (bytesPerSample == 0 || (bytesPerFrame % pWav->channels) != 0) {
7206 totalFramesRead = 0;
7208 while (framesToRead > 0) {
7209 drwav_uint64 framesToReadThisIteration = drwav_min(framesToRead,
sizeof(sampleData)/bytesPerFrame);
7210 drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, framesToReadThisIteration, sampleData);
7211 if (framesRead == 0) {
7215 DRWAV_ASSERT(framesRead <= framesToReadThisIteration);
7218 samplesRead = framesRead * pWav->channels;
7219 if ((samplesRead * bytesPerSample) >
sizeof(sampleData)) {
7220 DRWAV_ASSERT(DRWAV_FALSE);
7224 drwav_mulaw_to_f32(pBufferOut, sampleData, (
size_t)samplesRead);
7226 #ifdef DR_WAV_LIBSNDFILE_COMPAT
7228 if (pWav->container == drwav_container_aiff) {
7229 drwav_uint64 iSample;
7230 for (iSample = 0; iSample < samplesRead; iSample += 1) {
7231 pBufferOut[iSample] = -pBufferOut[iSample];
7237 pBufferOut += samplesRead;
7238 framesToRead -= framesRead;
7239 totalFramesRead += framesRead;
7242 return totalFramesRead;
7245DRWAV_API drwav_uint64 drwav_read_pcm_frames_f32(
drwav* pWav, drwav_uint64 framesToRead,
float* pBufferOut)
7247 if (pWav == NULL || framesToRead == 0) {
7251 if (pBufferOut == NULL) {
7252 return drwav_read_pcm_frames(pWav, framesToRead, NULL);
7256 if (framesToRead * pWav->channels *
sizeof(
float) > DRWAV_SIZE_MAX) {
7257 framesToRead = DRWAV_SIZE_MAX /
sizeof(float) / pWav->channels;
7260 if (pWav->translatedFormatTag == DR_WAVE_FORMAT_PCM) {
7261 return drwav_read_pcm_frames_f32__pcm(pWav, framesToRead, pBufferOut);
7264 if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ADPCM || pWav->translatedFormatTag == DR_WAVE_FORMAT_DVI_ADPCM) {
7265 return drwav_read_pcm_frames_f32__msadpcm_ima(pWav, framesToRead, pBufferOut);
7268 if (pWav->translatedFormatTag == DR_WAVE_FORMAT_IEEE_FLOAT) {
7269 return drwav_read_pcm_frames_f32__ieee(pWav, framesToRead, pBufferOut);
7272 if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ALAW) {
7273 return drwav_read_pcm_frames_f32__alaw(pWav, framesToRead, pBufferOut);
7276 if (pWav->translatedFormatTag == DR_WAVE_FORMAT_MULAW) {
7277 return drwav_read_pcm_frames_f32__mulaw(pWav, framesToRead, pBufferOut);
7283DRWAV_API drwav_uint64 drwav_read_pcm_frames_f32le(
drwav* pWav, drwav_uint64 framesToRead,
float* pBufferOut)
7285 drwav_uint64 framesRead = drwav_read_pcm_frames_f32(pWav, framesToRead, pBufferOut);
7286 if (pBufferOut != NULL && drwav__is_little_endian() == DRWAV_FALSE) {
7287 drwav__bswap_samples_f32(pBufferOut, framesRead*pWav->channels);
7293DRWAV_API drwav_uint64 drwav_read_pcm_frames_f32be(
drwav* pWav, drwav_uint64 framesToRead,
float* pBufferOut)
7295 drwav_uint64 framesRead = drwav_read_pcm_frames_f32(pWav, framesToRead, pBufferOut);
7296 if (pBufferOut != NULL && drwav__is_little_endian() == DRWAV_TRUE) {
7297 drwav__bswap_samples_f32(pBufferOut, framesRead*pWav->channels);
7304DRWAV_API
void drwav_u8_to_f32(
float* pOut,
const drwav_uint8* pIn,
size_t sampleCount)
7308 if (pOut == NULL || pIn == NULL) {
7312#ifdef DR_WAV_LIBSNDFILE_COMPAT
7319 for (i = 0; i < sampleCount; ++i) {
7320 *pOut++ = (pIn[i] / 256.0f) * 2 - 1;
7323 for (i = 0; i < sampleCount; ++i) {
7325 x = x * 0.00784313725490196078f;
7333DRWAV_API
void drwav_s16_to_f32(
float* pOut,
const drwav_int16* pIn,
size_t sampleCount)
7337 if (pOut == NULL || pIn == NULL) {
7341 for (i = 0; i < sampleCount; ++i) {
7342 *pOut++ = pIn[i] * 0.000030517578125f;
7346DRWAV_API
void drwav_s24_to_f32(
float* pOut,
const drwav_uint8* pIn,
size_t sampleCount)
7350 if (pOut == NULL || pIn == NULL) {
7354 for (i = 0; i < sampleCount; ++i) {
7356 drwav_uint32 a = ((drwav_uint32)(pIn[i*3+0]) << 8);
7357 drwav_uint32 b = ((drwav_uint32)(pIn[i*3+1]) << 16);
7358 drwav_uint32 c = ((drwav_uint32)(pIn[i*3+2]) << 24);
7360 x = (double)((drwav_int32)(a | b | c) >> 8);
7361 *pOut++ = (float)(x * 0.00000011920928955078125);
7365DRWAV_API
void drwav_s32_to_f32(
float* pOut,
const drwav_int32* pIn,
size_t sampleCount)
7368 if (pOut == NULL || pIn == NULL) {
7372 for (i = 0; i < sampleCount; ++i) {
7373 *pOut++ = (float)(pIn[i] / 2147483648.0);
7377DRWAV_API
void drwav_f64_to_f32(
float* pOut,
const double* pIn,
size_t sampleCount)
7381 if (pOut == NULL || pIn == NULL) {
7385 for (i = 0; i < sampleCount; ++i) {
7386 *pOut++ = (float)pIn[i];
7390DRWAV_API
void drwav_alaw_to_f32(
float* pOut,
const drwav_uint8* pIn,
size_t sampleCount)
7394 if (pOut == NULL || pIn == NULL) {
7398 for (i = 0; i < sampleCount; ++i) {
7399 *pOut++ = drwav__alaw_to_s16(pIn[i]) / 32768.0f;
7403DRWAV_API
void drwav_mulaw_to_f32(
float* pOut,
const drwav_uint8* pIn,
size_t sampleCount)
7407 if (pOut == NULL || pIn == NULL) {
7411 for (i = 0; i < sampleCount; ++i) {
7412 *pOut++ = drwav__mulaw_to_s16(pIn[i]) / 32768.0f;
7418DRWAV_PRIVATE
void drwav__pcm_to_s32(drwav_int32* pOut,
const drwav_uint8* pIn,
size_t totalSampleCount,
unsigned int bytesPerSample)
7423 if (bytesPerSample == 1) {
7424 drwav_u8_to_s32(pOut, pIn, totalSampleCount);
7429 if (bytesPerSample == 2) {
7430 drwav_s16_to_s32(pOut, (
const drwav_int16*)pIn, totalSampleCount);
7433 if (bytesPerSample == 3) {
7434 drwav_s24_to_s32(pOut, pIn, totalSampleCount);
7437 if (bytesPerSample == 4) {
7438 for (i = 0; i < totalSampleCount; ++i) {
7439 *pOut++ = ((
const drwav_int32*)pIn)[i];
7446 if (bytesPerSample > 8) {
7447 DRWAV_ZERO_MEMORY(pOut, totalSampleCount *
sizeof(*pOut));
7453 for (i = 0; i < totalSampleCount; ++i) {
7454 drwav_uint64 sample = 0;
7455 unsigned int shift = (8 - bytesPerSample) * 8;
7458 for (j = 0; j < bytesPerSample; j += 1) {
7459 DRWAV_ASSERT(j < 8);
7460 sample |= (drwav_uint64)(pIn[j]) << shift;
7465 *pOut++ = (drwav_int32)((drwav_int64)sample >> 32);
7469DRWAV_PRIVATE
void drwav__ieee_to_s32(drwav_int32* pOut,
const drwav_uint8* pIn,
size_t totalSampleCount,
unsigned int bytesPerSample)
7471 if (bytesPerSample == 4) {
7472 drwav_f32_to_s32(pOut, (
const float*)pIn, totalSampleCount);
7474 }
else if (bytesPerSample == 8) {
7475 drwav_f64_to_s32(pOut, (
const double*)pIn, totalSampleCount);
7479 DRWAV_ZERO_MEMORY(pOut, totalSampleCount *
sizeof(*pOut));
7485DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s32__pcm(
drwav* pWav, drwav_uint64 framesToRead, drwav_int32* pBufferOut)
7487 drwav_uint64 totalFramesRead;
7488 drwav_uint8 sampleData[4096] = {0};
7489 drwav_uint32 bytesPerFrame;
7490 drwav_uint32 bytesPerSample;
7491 drwav_uint64 samplesRead;
7494 if (pWav->translatedFormatTag == DR_WAVE_FORMAT_PCM && pWav->bitsPerSample == 32) {
7495 return drwav_read_pcm_frames(pWav, framesToRead, pBufferOut);
7498 bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
7499 if (bytesPerFrame == 0) {
7503 bytesPerSample = bytesPerFrame / pWav->channels;
7504 if (bytesPerSample == 0 || (bytesPerFrame % pWav->channels) != 0) {
7508 totalFramesRead = 0;
7510 while (framesToRead > 0) {
7511 drwav_uint64 framesToReadThisIteration = drwav_min(framesToRead,
sizeof(sampleData)/bytesPerFrame);
7512 drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, framesToReadThisIteration, sampleData);
7513 if (framesRead == 0) {
7517 DRWAV_ASSERT(framesRead <= framesToReadThisIteration);
7520 samplesRead = framesRead * pWav->channels;
7521 if ((samplesRead * bytesPerSample) >
sizeof(sampleData)) {
7522 DRWAV_ASSERT(DRWAV_FALSE);
7526 drwav__pcm_to_s32(pBufferOut, sampleData, (
size_t)samplesRead, bytesPerSample);
7528 pBufferOut += samplesRead;
7529 framesToRead -= framesRead;
7530 totalFramesRead += framesRead;
7533 return totalFramesRead;
7536DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s32__msadpcm_ima(
drwav* pWav, drwav_uint64 framesToRead, drwav_int32* pBufferOut)
7542 drwav_uint64 totalFramesRead = 0;
7543 drwav_int16 samples16[2048];
7545 while (framesToRead > 0) {
7546 drwav_uint64 framesToReadThisIteration = drwav_min(framesToRead, drwav_countof(samples16)/pWav->channels);
7547 drwav_uint64 framesRead = drwav_read_pcm_frames_s16(pWav, framesToReadThisIteration, samples16);
7548 if (framesRead == 0) {
7552 DRWAV_ASSERT(framesRead <= framesToReadThisIteration);
7554 drwav_s16_to_s32(pBufferOut, samples16, (
size_t)(framesRead*pWav->channels));
7556 pBufferOut += framesRead*pWav->channels;
7557 framesToRead -= framesRead;
7558 totalFramesRead += framesRead;
7561 return totalFramesRead;
7564DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s32__ieee(
drwav* pWav, drwav_uint64 framesToRead, drwav_int32* pBufferOut)
7566 drwav_uint64 totalFramesRead;
7567 drwav_uint8 sampleData[4096] = {0};
7568 drwav_uint32 bytesPerFrame;
7569 drwav_uint32 bytesPerSample;
7570 drwav_uint64 samplesRead;
7572 bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
7573 if (bytesPerFrame == 0) {
7577 bytesPerSample = bytesPerFrame / pWav->channels;
7578 if (bytesPerSample == 0 || (bytesPerFrame % pWav->channels) != 0) {
7582 totalFramesRead = 0;
7584 while (framesToRead > 0) {
7585 drwav_uint64 framesToReadThisIteration = drwav_min(framesToRead,
sizeof(sampleData)/bytesPerFrame);
7586 drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, framesToReadThisIteration, sampleData);
7587 if (framesRead == 0) {
7591 DRWAV_ASSERT(framesRead <= framesToReadThisIteration);
7594 samplesRead = framesRead * pWav->channels;
7595 if ((samplesRead * bytesPerSample) >
sizeof(sampleData)) {
7596 DRWAV_ASSERT(DRWAV_FALSE);
7600 drwav__ieee_to_s32(pBufferOut, sampleData, (
size_t)samplesRead, bytesPerSample);
7602 pBufferOut += samplesRead;
7603 framesToRead -= framesRead;
7604 totalFramesRead += framesRead;
7607 return totalFramesRead;
7610DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s32__alaw(
drwav* pWav, drwav_uint64 framesToRead, drwav_int32* pBufferOut)
7612 drwav_uint64 totalFramesRead;
7613 drwav_uint8 sampleData[4096] = {0};
7614 drwav_uint32 bytesPerFrame;
7615 drwav_uint32 bytesPerSample;
7616 drwav_uint64 samplesRead;
7618 bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
7619 if (bytesPerFrame == 0) {
7623 bytesPerSample = bytesPerFrame / pWav->channels;
7624 if (bytesPerSample == 0 || (bytesPerFrame % pWav->channels) != 0) {
7628 totalFramesRead = 0;
7630 while (framesToRead > 0) {
7631 drwav_uint64 framesToReadThisIteration = drwav_min(framesToRead,
sizeof(sampleData)/bytesPerFrame);
7632 drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, framesToReadThisIteration, sampleData);
7633 if (framesRead == 0) {
7637 DRWAV_ASSERT(framesRead <= framesToReadThisIteration);
7640 samplesRead = framesRead * pWav->channels;
7641 if ((samplesRead * bytesPerSample) >
sizeof(sampleData)) {
7642 DRWAV_ASSERT(DRWAV_FALSE);
7646 drwav_alaw_to_s32(pBufferOut, sampleData, (
size_t)samplesRead);
7648 #ifdef DR_WAV_LIBSNDFILE_COMPAT
7650 if (pWav->container == drwav_container_aiff) {
7651 drwav_uint64 iSample;
7652 for (iSample = 0; iSample < samplesRead; iSample += 1) {
7653 pBufferOut[iSample] = -pBufferOut[iSample];
7659 pBufferOut += samplesRead;
7660 framesToRead -= framesRead;
7661 totalFramesRead += framesRead;
7664 return totalFramesRead;
7667DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s32__mulaw(
drwav* pWav, drwav_uint64 framesToRead, drwav_int32* pBufferOut)
7669 drwav_uint64 totalFramesRead;
7670 drwav_uint8 sampleData[4096] = {0};
7671 drwav_uint32 bytesPerFrame;
7672 drwav_uint32 bytesPerSample;
7673 drwav_uint64 samplesRead;
7675 bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
7676 if (bytesPerFrame == 0) {
7680 bytesPerSample = bytesPerFrame / pWav->channels;
7681 if (bytesPerSample == 0 || (bytesPerFrame % pWav->channels) != 0) {
7685 totalFramesRead = 0;
7687 while (framesToRead > 0) {
7688 drwav_uint64 framesToReadThisIteration = drwav_min(framesToRead,
sizeof(sampleData)/bytesPerFrame);
7689 drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, framesToReadThisIteration, sampleData);
7690 if (framesRead == 0) {
7694 DRWAV_ASSERT(framesRead <= framesToReadThisIteration);
7697 samplesRead = framesRead * pWav->channels;
7698 if ((samplesRead * bytesPerSample) >
sizeof(sampleData)) {
7699 DRWAV_ASSERT(DRWAV_FALSE);
7703 drwav_mulaw_to_s32(pBufferOut, sampleData, (
size_t)samplesRead);
7705 #ifdef DR_WAV_LIBSNDFILE_COMPAT
7707 if (pWav->container == drwav_container_aiff) {
7708 drwav_uint64 iSample;
7709 for (iSample = 0; iSample < samplesRead; iSample += 1) {
7710 pBufferOut[iSample] = -pBufferOut[iSample];
7716 pBufferOut += samplesRead;
7717 framesToRead -= framesRead;
7718 totalFramesRead += framesRead;
7721 return totalFramesRead;
7724DRWAV_API drwav_uint64 drwav_read_pcm_frames_s32(
drwav* pWav, drwav_uint64 framesToRead, drwav_int32* pBufferOut)
7726 if (pWav == NULL || framesToRead == 0) {
7730 if (pBufferOut == NULL) {
7731 return drwav_read_pcm_frames(pWav, framesToRead, NULL);
7735 if (framesToRead * pWav->channels *
sizeof(drwav_int32) > DRWAV_SIZE_MAX) {
7736 framesToRead = DRWAV_SIZE_MAX /
sizeof(drwav_int32) / pWav->channels;
7739 if (pWav->translatedFormatTag == DR_WAVE_FORMAT_PCM) {
7740 return drwav_read_pcm_frames_s32__pcm(pWav, framesToRead, pBufferOut);
7743 if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ADPCM || pWav->translatedFormatTag == DR_WAVE_FORMAT_DVI_ADPCM) {
7744 return drwav_read_pcm_frames_s32__msadpcm_ima(pWav, framesToRead, pBufferOut);
7747 if (pWav->translatedFormatTag == DR_WAVE_FORMAT_IEEE_FLOAT) {
7748 return drwav_read_pcm_frames_s32__ieee(pWav, framesToRead, pBufferOut);
7751 if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ALAW) {
7752 return drwav_read_pcm_frames_s32__alaw(pWav, framesToRead, pBufferOut);
7755 if (pWav->translatedFormatTag == DR_WAVE_FORMAT_MULAW) {
7756 return drwav_read_pcm_frames_s32__mulaw(pWav, framesToRead, pBufferOut);
7762DRWAV_API drwav_uint64 drwav_read_pcm_frames_s32le(
drwav* pWav, drwav_uint64 framesToRead, drwav_int32* pBufferOut)
7764 drwav_uint64 framesRead = drwav_read_pcm_frames_s32(pWav, framesToRead, pBufferOut);
7765 if (pBufferOut != NULL && drwav__is_little_endian() == DRWAV_FALSE) {
7766 drwav__bswap_samples_s32(pBufferOut, framesRead*pWav->channels);
7772DRWAV_API drwav_uint64 drwav_read_pcm_frames_s32be(
drwav* pWav, drwav_uint64 framesToRead, drwav_int32* pBufferOut)
7774 drwav_uint64 framesRead = drwav_read_pcm_frames_s32(pWav, framesToRead, pBufferOut);
7775 if (pBufferOut != NULL && drwav__is_little_endian() == DRWAV_TRUE) {
7776 drwav__bswap_samples_s32(pBufferOut, framesRead*pWav->channels);
7783DRWAV_API
void drwav_u8_to_s32(drwav_int32* pOut,
const drwav_uint8* pIn,
size_t sampleCount)
7787 if (pOut == NULL || pIn == NULL) {
7791 for (i = 0; i < sampleCount; ++i) {
7792 *pOut++ = ((int)pIn[i] - 128) << 24;
7796DRWAV_API
void drwav_s16_to_s32(drwav_int32* pOut,
const drwav_int16* pIn,
size_t sampleCount)
7800 if (pOut == NULL || pIn == NULL) {
7804 for (i = 0; i < sampleCount; ++i) {
7805 *pOut++ = pIn[i] << 16;
7809DRWAV_API
void drwav_s24_to_s32(drwav_int32* pOut,
const drwav_uint8* pIn,
size_t sampleCount)
7813 if (pOut == NULL || pIn == NULL) {
7817 for (i = 0; i < sampleCount; ++i) {
7818 unsigned int s0 = pIn[i*3 + 0];
7819 unsigned int s1 = pIn[i*3 + 1];
7820 unsigned int s2 = pIn[i*3 + 2];
7822 drwav_int32 sample32 = (drwav_int32)((s0 << 8) | (s1 << 16) | (s2 << 24));
7827DRWAV_API
void drwav_f32_to_s32(drwav_int32* pOut,
const float* pIn,
size_t sampleCount)
7831 if (pOut == NULL || pIn == NULL) {
7835 for (i = 0; i < sampleCount; ++i) {
7836 *pOut++ = (drwav_int32)(2147483648.0f * pIn[i]);
7840DRWAV_API
void drwav_f64_to_s32(drwav_int32* pOut,
const double* pIn,
size_t sampleCount)
7844 if (pOut == NULL || pIn == NULL) {
7848 for (i = 0; i < sampleCount; ++i) {
7849 *pOut++ = (drwav_int32)(2147483648.0 * pIn[i]);
7853DRWAV_API
void drwav_alaw_to_s32(drwav_int32* pOut,
const drwav_uint8* pIn,
size_t sampleCount)
7857 if (pOut == NULL || pIn == NULL) {
7861 for (i = 0; i < sampleCount; ++i) {
7862 *pOut++ = ((drwav_int32)drwav__alaw_to_s16(pIn[i])) << 16;
7866DRWAV_API
void drwav_mulaw_to_s32(drwav_int32* pOut,
const drwav_uint8* pIn,
size_t sampleCount)
7870 if (pOut == NULL || pIn == NULL) {
7874 for (i= 0; i < sampleCount; ++i) {
7875 *pOut++ = ((drwav_int32)drwav__mulaw_to_s16(pIn[i])) << 16;
7881DRWAV_PRIVATE drwav_int16* drwav__read_pcm_frames_and_close_s16(
drwav* pWav,
unsigned int* channels,
unsigned int* sampleRate, drwav_uint64* totalFrameCount)
7883 drwav_uint64 sampleDataSize;
7884 drwav_int16* pSampleData;
7885 drwav_uint64 framesRead;
7887 DRWAV_ASSERT(pWav != NULL);
7889 sampleDataSize = pWav->totalPCMFrameCount * pWav->channels *
sizeof(drwav_int16);
7890 if (sampleDataSize > DRWAV_SIZE_MAX) {
7895 pSampleData = (drwav_int16*)drwav__malloc_from_callbacks((
size_t)sampleDataSize, &pWav->allocationCallbacks);
7896 if (pSampleData == NULL) {
7901 framesRead = drwav_read_pcm_frames_s16(pWav, (
size_t)pWav->totalPCMFrameCount, pSampleData);
7902 if (framesRead != pWav->totalPCMFrameCount) {
7903 drwav__free_from_callbacks(pSampleData, &pWav->allocationCallbacks);
7911 *sampleRate = pWav->sampleRate;
7914 *channels = pWav->channels;
7916 if (totalFrameCount) {
7917 *totalFrameCount = pWav->totalPCMFrameCount;
7923DRWAV_PRIVATE
float* drwav__read_pcm_frames_and_close_f32(
drwav* pWav,
unsigned int* channels,
unsigned int* sampleRate, drwav_uint64* totalFrameCount)
7925 drwav_uint64 sampleDataSize;
7927 drwav_uint64 framesRead;
7929 DRWAV_ASSERT(pWav != NULL);
7931 sampleDataSize = pWav->totalPCMFrameCount * pWav->channels *
sizeof(float);
7932 if (sampleDataSize > DRWAV_SIZE_MAX) {
7937 pSampleData = (
float*)drwav__malloc_from_callbacks((
size_t)sampleDataSize, &pWav->allocationCallbacks);
7938 if (pSampleData == NULL) {
7943 framesRead = drwav_read_pcm_frames_f32(pWav, (
size_t)pWav->totalPCMFrameCount, pSampleData);
7944 if (framesRead != pWav->totalPCMFrameCount) {
7945 drwav__free_from_callbacks(pSampleData, &pWav->allocationCallbacks);
7953 *sampleRate = pWav->sampleRate;
7956 *channels = pWav->channels;
7958 if (totalFrameCount) {
7959 *totalFrameCount = pWav->totalPCMFrameCount;
7965DRWAV_PRIVATE drwav_int32* drwav__read_pcm_frames_and_close_s32(
drwav* pWav,
unsigned int* channels,
unsigned int* sampleRate, drwav_uint64* totalFrameCount)
7967 drwav_uint64 sampleDataSize;
7968 drwav_int32* pSampleData;
7969 drwav_uint64 framesRead;
7971 DRWAV_ASSERT(pWav != NULL);
7973 sampleDataSize = pWav->totalPCMFrameCount * pWav->channels *
sizeof(drwav_int32);
7974 if (sampleDataSize > DRWAV_SIZE_MAX) {
7979 pSampleData = (drwav_int32*)drwav__malloc_from_callbacks((
size_t)sampleDataSize, &pWav->allocationCallbacks);
7980 if (pSampleData == NULL) {
7985 framesRead = drwav_read_pcm_frames_s32(pWav, (
size_t)pWav->totalPCMFrameCount, pSampleData);
7986 if (framesRead != pWav->totalPCMFrameCount) {
7987 drwav__free_from_callbacks(pSampleData, &pWav->allocationCallbacks);
7995 *sampleRate = pWav->sampleRate;
7998 *channels = pWav->channels;
8000 if (totalFrameCount) {
8001 *totalFrameCount = pWav->totalPCMFrameCount;
8009DRWAV_API drwav_int16* drwav_open_and_read_pcm_frames_s16(drwav_read_proc onRead, drwav_seek_proc onSeek,
void* pUserData,
unsigned int* channelsOut,
unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut,
const drwav_allocation_callbacks* pAllocationCallbacks)
8016 if (sampleRateOut) {
8019 if (totalFrameCountOut) {
8020 *totalFrameCountOut = 0;
8023 if (!drwav_init(&wav, onRead, onSeek, pUserData, pAllocationCallbacks)) {
8027 return drwav__read_pcm_frames_and_close_s16(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
8030DRWAV_API
float* drwav_open_and_read_pcm_frames_f32(drwav_read_proc onRead, drwav_seek_proc onSeek,
void* pUserData,
unsigned int* channelsOut,
unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut,
const drwav_allocation_callbacks* pAllocationCallbacks)
8037 if (sampleRateOut) {
8040 if (totalFrameCountOut) {
8041 *totalFrameCountOut = 0;
8044 if (!drwav_init(&wav, onRead, onSeek, pUserData, pAllocationCallbacks)) {
8048 return drwav__read_pcm_frames_and_close_f32(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
8051DRWAV_API drwav_int32* drwav_open_and_read_pcm_frames_s32(drwav_read_proc onRead, drwav_seek_proc onSeek,
void* pUserData,
unsigned int* channelsOut,
unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut,
const drwav_allocation_callbacks* pAllocationCallbacks)
8058 if (sampleRateOut) {
8061 if (totalFrameCountOut) {
8062 *totalFrameCountOut = 0;
8065 if (!drwav_init(&wav, onRead, onSeek, pUserData, pAllocationCallbacks)) {
8069 return drwav__read_pcm_frames_and_close_s32(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
8072#ifndef DR_WAV_NO_STDIO
8073DRWAV_API drwav_int16* drwav_open_file_and_read_pcm_frames_s16(
const char* filename,
unsigned int* channelsOut,
unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut,
const drwav_allocation_callbacks* pAllocationCallbacks)
8080 if (sampleRateOut) {
8083 if (totalFrameCountOut) {
8084 *totalFrameCountOut = 0;
8087 if (!drwav_init_file(&wav, filename, pAllocationCallbacks)) {
8091 return drwav__read_pcm_frames_and_close_s16(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
8094DRWAV_API
float* drwav_open_file_and_read_pcm_frames_f32(
const char* filename,
unsigned int* channelsOut,
unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut,
const drwav_allocation_callbacks* pAllocationCallbacks)
8101 if (sampleRateOut) {
8104 if (totalFrameCountOut) {
8105 *totalFrameCountOut = 0;
8108 if (!drwav_init_file(&wav, filename, pAllocationCallbacks)) {
8112 return drwav__read_pcm_frames_and_close_f32(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
8115DRWAV_API drwav_int32* drwav_open_file_and_read_pcm_frames_s32(
const char* filename,
unsigned int* channelsOut,
unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut,
const drwav_allocation_callbacks* pAllocationCallbacks)
8122 if (sampleRateOut) {
8125 if (totalFrameCountOut) {
8126 *totalFrameCountOut = 0;
8129 if (!drwav_init_file(&wav, filename, pAllocationCallbacks)) {
8133 return drwav__read_pcm_frames_and_close_s32(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
8137#ifndef DR_WAV_NO_WCHAR
8138DRWAV_API drwav_int16* drwav_open_file_and_read_pcm_frames_s16_w(
const wchar_t* filename,
unsigned int* channelsOut,
unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut,
const drwav_allocation_callbacks* pAllocationCallbacks)
8142 if (sampleRateOut) {
8148 if (totalFrameCountOut) {
8149 *totalFrameCountOut = 0;
8152 if (!drwav_init_file_w(&wav, filename, pAllocationCallbacks)) {
8156 return drwav__read_pcm_frames_and_close_s16(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
8159DRWAV_API
float* drwav_open_file_and_read_pcm_frames_f32_w(
const wchar_t* filename,
unsigned int* channelsOut,
unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut,
const drwav_allocation_callbacks* pAllocationCallbacks)
8163 if (sampleRateOut) {
8169 if (totalFrameCountOut) {
8170 *totalFrameCountOut = 0;
8173 if (!drwav_init_file_w(&wav, filename, pAllocationCallbacks)) {
8177 return drwav__read_pcm_frames_and_close_f32(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
8180DRWAV_API drwav_int32* drwav_open_file_and_read_pcm_frames_s32_w(
const wchar_t* filename,
unsigned int* channelsOut,
unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut,
const drwav_allocation_callbacks* pAllocationCallbacks)
8184 if (sampleRateOut) {
8190 if (totalFrameCountOut) {
8191 *totalFrameCountOut = 0;
8194 if (!drwav_init_file_w(&wav, filename, pAllocationCallbacks)) {
8198 return drwav__read_pcm_frames_and_close_s32(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
8203DRWAV_API drwav_int16* drwav_open_memory_and_read_pcm_frames_s16(
const void* data,
size_t dataSize,
unsigned int* channelsOut,
unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut,
const drwav_allocation_callbacks* pAllocationCallbacks)
8210 if (sampleRateOut) {
8213 if (totalFrameCountOut) {
8214 *totalFrameCountOut = 0;
8217 if (!drwav_init_memory(&wav, data, dataSize, pAllocationCallbacks)) {
8221 return drwav__read_pcm_frames_and_close_s16(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
8224DRWAV_API
float* drwav_open_memory_and_read_pcm_frames_f32(
const void* data,
size_t dataSize,
unsigned int* channelsOut,
unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut,
const drwav_allocation_callbacks* pAllocationCallbacks)
8231 if (sampleRateOut) {
8234 if (totalFrameCountOut) {
8235 *totalFrameCountOut = 0;
8238 if (!drwav_init_memory(&wav, data, dataSize, pAllocationCallbacks)) {
8242 return drwav__read_pcm_frames_and_close_f32(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
8245DRWAV_API drwav_int32* drwav_open_memory_and_read_pcm_frames_s32(
const void* data,
size_t dataSize,
unsigned int* channelsOut,
unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut,
const drwav_allocation_callbacks* pAllocationCallbacks)
8252 if (sampleRateOut) {
8255 if (totalFrameCountOut) {
8256 *totalFrameCountOut = 0;
8259 if (!drwav_init_memory(&wav, data, dataSize, pAllocationCallbacks)) {
8263 return drwav__read_pcm_frames_and_close_s32(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
8270 if (pAllocationCallbacks != NULL) {
8271 drwav__free_from_callbacks(p, pAllocationCallbacks);
8273 drwav__free_default(p, NULL);
8277DRWAV_API drwav_uint16 drwav_bytes_to_u16(
const drwav_uint8* data)
8279 return ((drwav_uint16)data[0] << 0) | ((drwav_uint16)data[1] << 8);
8282DRWAV_API drwav_int16 drwav_bytes_to_s16(
const drwav_uint8* data)
8284 return (drwav_int16)drwav_bytes_to_u16(data);
8287DRWAV_API drwav_uint32 drwav_bytes_to_u32(
const drwav_uint8* data)
8289 return drwav_bytes_to_u32_le(data);
8292DRWAV_API
float drwav_bytes_to_f32(
const drwav_uint8* data)
8299 value.u32 = drwav_bytes_to_u32(data);
8303DRWAV_API drwav_int32 drwav_bytes_to_s32(
const drwav_uint8* data)
8305 return (drwav_int32)drwav_bytes_to_u32(data);
8308DRWAV_API drwav_uint64 drwav_bytes_to_u64(
const drwav_uint8* data)
8311 ((drwav_uint64)data[0] << 0) | ((drwav_uint64)data[1] << 8) | ((drwav_uint64)data[2] << 16) | ((drwav_uint64)data[3] << 24) |
8312 ((drwav_uint64)data[4] << 32) | ((drwav_uint64)data[5] << 40) | ((drwav_uint64)data[6] << 48) | ((drwav_uint64)data[7] << 56);
8315DRWAV_API drwav_int64 drwav_bytes_to_s64(
const drwav_uint8* data)
8317 return (drwav_int64)drwav_bytes_to_u64(data);
8321DRWAV_API drwav_bool32 drwav_guid_equal(
const drwav_uint8 a[16],
const drwav_uint8 b[16])
8324 for (i = 0; i < 16; i += 1) {
8333DRWAV_API drwav_bool32 drwav_fourcc_equal(
const drwav_uint8* a,
const char* b)
8344#pragma options opt reset
float f32
Definition fwd.hpp:152
uint32 u32
Definition fwd.hpp:122