Update external audio libraries.
This commit is contained in:
parent
f5ebbfb6bc
commit
0febaa2446
19
src/audio.c
19
src/audio.c
@ -296,7 +296,7 @@ static mal_uint32 OnSendAudioDataToDevice(mal_device *pDevice, mal_uint32 frameC
|
|||||||
(void)pDevice;
|
(void)pDevice;
|
||||||
|
|
||||||
// Mixing is basically just an accumulation. We need to initialize the output buffer to 0.
|
// Mixing is basically just an accumulation. We need to initialize the output buffer to 0.
|
||||||
memset(pFramesOut, 0, frameCount*pDevice->channels*mal_get_sample_size_in_bytes(pDevice->format));
|
memset(pFramesOut, 0, frameCount*pDevice->channels*mal_get_bytes_per_sample(pDevice->format));
|
||||||
|
|
||||||
// Using a mutex here for thread-safety which makes things not real-time. This is unlikely to be necessary for this project, but may
|
// Using a mutex here for thread-safety which makes things not real-time. This is unlikely to be necessary for this project, but may
|
||||||
// want to consider how you might want to avoid this.
|
// want to consider how you might want to avoid this.
|
||||||
@ -334,7 +334,7 @@ static mal_uint32 OnSendAudioDataToDevice(mal_device *pDevice, mal_uint32 frameC
|
|||||||
// last few samples.
|
// last few samples.
|
||||||
bool flushDSP = !audioBuffer->looping;
|
bool flushDSP = !audioBuffer->looping;
|
||||||
|
|
||||||
mal_uint32 framesJustRead = mal_dsp_read_frames_ex(&audioBuffer->dsp, framesToReadRightNow, tempBuffer, flushDSP);
|
mal_uint32 framesJustRead = mal_dsp_read_ex(&audioBuffer->dsp, framesToReadRightNow, tempBuffer, flushDSP, audioBuffer->dsp.pUserData);
|
||||||
if (framesJustRead > 0)
|
if (framesJustRead > 0)
|
||||||
{
|
{
|
||||||
float *framesOut = (float *)pFramesOut + (framesRead*device.channels);
|
float *framesOut = (float *)pFramesOut + (framesRead*device.channels);
|
||||||
@ -394,7 +394,7 @@ static mal_uint32 OnAudioBufferDSPRead(mal_dsp *pDSP, mal_uint32 frameCount, voi
|
|||||||
isSubBufferProcessed[0] = audioBuffer->isSubBufferProcessed[0];
|
isSubBufferProcessed[0] = audioBuffer->isSubBufferProcessed[0];
|
||||||
isSubBufferProcessed[1] = audioBuffer->isSubBufferProcessed[1];
|
isSubBufferProcessed[1] = audioBuffer->isSubBufferProcessed[1];
|
||||||
|
|
||||||
mal_uint32 frameSizeInBytes = mal_get_sample_size_in_bytes(audioBuffer->dsp.config.formatIn)*audioBuffer->dsp.config.channelsIn;
|
mal_uint32 frameSizeInBytes = mal_get_bytes_per_sample(audioBuffer->dsp.formatConverterIn.config.formatIn)*audioBuffer->dsp.formatConverterIn.config.channels;
|
||||||
|
|
||||||
// Fill out every frame until we find a buffer that's marked as processed. Then fill the remainder with 0.
|
// Fill out every frame until we find a buffer that's marked as processed. Then fill the remainder with 0.
|
||||||
mal_uint32 framesRead = 0;
|
mal_uint32 framesRead = 0;
|
||||||
@ -640,7 +640,7 @@ void SetMasterVolume(float volume)
|
|||||||
// Create a new audio buffer. Initially filled with silence
|
// Create a new audio buffer. Initially filled with silence
|
||||||
AudioBuffer *CreateAudioBuffer(mal_format format, mal_uint32 channels, mal_uint32 sampleRate, mal_uint32 bufferSizeInFrames, AudioBufferUsage usage)
|
AudioBuffer *CreateAudioBuffer(mal_format format, mal_uint32 channels, mal_uint32 sampleRate, mal_uint32 bufferSizeInFrames, AudioBufferUsage usage)
|
||||||
{
|
{
|
||||||
AudioBuffer *audioBuffer = (AudioBuffer *)calloc(sizeof(*audioBuffer) + (bufferSizeInFrames*channels*mal_get_sample_size_in_bytes(format)), 1);
|
AudioBuffer *audioBuffer = (AudioBuffer *)calloc(sizeof(*audioBuffer) + (bufferSizeInFrames*channels*mal_get_bytes_per_sample(format)), 1);
|
||||||
if (audioBuffer == NULL)
|
if (audioBuffer == NULL)
|
||||||
{
|
{
|
||||||
TraceLog(LOG_ERROR, "CreateAudioBuffer() : Failed to allocate memory for audio buffer");
|
TraceLog(LOG_ERROR, "CreateAudioBuffer() : Failed to allocate memory for audio buffer");
|
||||||
@ -656,7 +656,10 @@ AudioBuffer *CreateAudioBuffer(mal_format format, mal_uint32 channels, mal_uint3
|
|||||||
dspConfig.channelsOut = DEVICE_CHANNELS;
|
dspConfig.channelsOut = DEVICE_CHANNELS;
|
||||||
dspConfig.sampleRateIn = sampleRate;
|
dspConfig.sampleRateIn = sampleRate;
|
||||||
dspConfig.sampleRateOut = DEVICE_SAMPLE_RATE;
|
dspConfig.sampleRateOut = DEVICE_SAMPLE_RATE;
|
||||||
mal_result resultMAL = mal_dsp_init(&dspConfig, OnAudioBufferDSPRead, audioBuffer, &audioBuffer->dsp);
|
dspConfig.onRead = OnAudioBufferDSPRead;
|
||||||
|
dspConfig.pUserData = audioBuffer;
|
||||||
|
dspConfig.allowDynamicSampleRate = MAL_TRUE; // <-- Required for pitch shifting.
|
||||||
|
mal_result resultMAL = mal_dsp_init(&dspConfig, &audioBuffer->dsp);
|
||||||
if (resultMAL != MAL_SUCCESS)
|
if (resultMAL != MAL_SUCCESS)
|
||||||
{
|
{
|
||||||
TraceLog(LOG_ERROR, "LoadSoundFromWave() : Failed to create data conversion pipeline");
|
TraceLog(LOG_ERROR, "LoadSoundFromWave() : Failed to create data conversion pipeline");
|
||||||
@ -791,7 +794,7 @@ void SetAudioBufferPitch(AudioBuffer *audioBuffer, float pitch)
|
|||||||
|
|
||||||
// Pitching is just an adjustment of the sample rate. Note that this changes the duration of the sound - higher pitches
|
// Pitching is just an adjustment of the sample rate. Note that this changes the duration of the sound - higher pitches
|
||||||
// will make the sound faster; lower pitches make it slower.
|
// will make the sound faster; lower pitches make it slower.
|
||||||
mal_uint32 newOutputSampleRate = (mal_uint32)((((float)audioBuffer->dsp.config.sampleRateOut / (float)audioBuffer->dsp.config.sampleRateIn) / pitch) * audioBuffer->dsp.config.sampleRateIn);
|
mal_uint32 newOutputSampleRate = (mal_uint32)((((float)audioBuffer->dsp.src.config.sampleRateOut / (float)audioBuffer->dsp.src.config.sampleRateIn) / pitch) * audioBuffer->dsp.src.config.sampleRateIn);
|
||||||
mal_dsp_set_output_sample_rate(&audioBuffer->dsp, newOutputSampleRate);
|
mal_dsp_set_output_sample_rate(&audioBuffer->dsp, newOutputSampleRate);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -913,7 +916,7 @@ Sound LoadSoundFromWave(Wave wave)
|
|||||||
AudioBuffer* audioBuffer = CreateAudioBuffer(DEVICE_FORMAT, DEVICE_CHANNELS, DEVICE_SAMPLE_RATE, frameCount, AUDIO_BUFFER_USAGE_STATIC);
|
AudioBuffer* audioBuffer = CreateAudioBuffer(DEVICE_FORMAT, DEVICE_CHANNELS, DEVICE_SAMPLE_RATE, frameCount, AUDIO_BUFFER_USAGE_STATIC);
|
||||||
if (audioBuffer == NULL) TraceLog(LOG_WARNING, "LoadSoundFromWave() : Failed to create audio buffer");
|
if (audioBuffer == NULL) TraceLog(LOG_WARNING, "LoadSoundFromWave() : Failed to create audio buffer");
|
||||||
|
|
||||||
frameCount = mal_convert_frames(audioBuffer->buffer, audioBuffer->dsp.config.formatIn, audioBuffer->dsp.config.channelsIn, audioBuffer->dsp.config.sampleRateIn, wave.data, formatIn, wave.channels, wave.sampleRate, frameCountIn);
|
frameCount = mal_convert_frames(audioBuffer->buffer, audioBuffer->dsp.formatConverterIn.config.formatIn, audioBuffer->dsp.formatConverterIn.config.channels, audioBuffer->dsp.src.config.sampleRateIn, wave.data, formatIn, wave.channels, wave.sampleRate, frameCountIn);
|
||||||
if (frameCount == 0) TraceLog(LOG_WARNING, "LoadSoundFromWave() : Format conversion failed");
|
if (frameCount == 0) TraceLog(LOG_WARNING, "LoadSoundFromWave() : Format conversion failed");
|
||||||
|
|
||||||
sound.audioBuffer = audioBuffer;
|
sound.audioBuffer = audioBuffer;
|
||||||
@ -1015,7 +1018,7 @@ void UpdateSound(Sound sound, const void *data, int samplesCount)
|
|||||||
StopAudioBuffer(audioBuffer);
|
StopAudioBuffer(audioBuffer);
|
||||||
|
|
||||||
// TODO: May want to lock/unlock this since this data buffer is read at mixing time.
|
// TODO: May want to lock/unlock this since this data buffer is read at mixing time.
|
||||||
memcpy(audioBuffer->buffer, data, samplesCount*audioBuffer->dsp.config.channelsIn*mal_get_sample_size_in_bytes(audioBuffer->dsp.config.formatIn));
|
memcpy(audioBuffer->buffer, data, samplesCount*audioBuffer->dsp.formatConverterIn.config.channels*mal_get_bytes_per_sample(audioBuffer->dsp.formatConverterIn.config.formatIn));
|
||||||
#else
|
#else
|
||||||
ALint sampleRate, sampleSize, channels;
|
ALint sampleRate, sampleSize, channels;
|
||||||
alGetBufferi(sound.buffer, AL_FREQUENCY, &sampleRate);
|
alGetBufferi(sound.buffer, AL_FREQUENCY, &sampleRate);
|
||||||
|
44
src/external/dr_flac.h
vendored
44
src/external/dr_flac.h
vendored
@ -1,5 +1,5 @@
|
|||||||
// FLAC audio decoder. Public domain. See "unlicense" statement at the end of this file.
|
// FLAC audio decoder. Public domain. See "unlicense" statement at the end of this file.
|
||||||
// dr_flac - v0.8d - 2017-09-22
|
// dr_flac - v0.8g - 2018-04-19
|
||||||
//
|
//
|
||||||
// David Reid - mackron@gmail.com
|
// David Reid - mackron@gmail.com
|
||||||
|
|
||||||
@ -106,6 +106,7 @@
|
|||||||
//
|
//
|
||||||
//
|
//
|
||||||
// QUICK NOTES
|
// QUICK NOTES
|
||||||
|
// - dr_flac does not currently support changing the sample rate nor channel count mid stream.
|
||||||
// - Audio data is output as signed 32-bit PCM, regardless of the bits per sample the FLAC stream is encoded as.
|
// - Audio data is output as signed 32-bit PCM, regardless of the bits per sample the FLAC stream is encoded as.
|
||||||
// - This has not been tested on big-endian architectures.
|
// - This has not been tested on big-endian architectures.
|
||||||
// - Rice codes in unencoded binary form (see https://xiph.org/flac/format.html#rice_partition) has not been tested. If anybody
|
// - Rice codes in unencoded binary form (see https://xiph.org/flac/format.html#rice_partition) has not been tested. If anybody
|
||||||
@ -759,6 +760,8 @@ const char* drflac_next_vorbis_comment(drflac_vorbis_comment_iterator* pIter, dr
|
|||||||
#define DRFLAC_X64
|
#define DRFLAC_X64
|
||||||
#elif defined(__i386) || defined(_M_IX86)
|
#elif defined(__i386) || defined(_M_IX86)
|
||||||
#define DRFLAC_X86
|
#define DRFLAC_X86
|
||||||
|
#elif defined(__arm__) || defined(_M_ARM)
|
||||||
|
#define DRFLAC_ARM
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Compile-time CPU feature support.
|
// Compile-time CPU feature support.
|
||||||
@ -806,7 +809,7 @@ const char* drflac_next_vorbis_comment(drflac_vorbis_comment_iterator* pIter, dr
|
|||||||
#include <endian.h>
|
#include <endian.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(_MSC_VER) && _MSC_VER >= 1500
|
#if defined(_MSC_VER) && _MSC_VER >= 1500 && (defined(DRFLAC_X86) || defined(DRFLAC_X64))
|
||||||
#define DRFLAC_HAS_LZCNT_INTRINSIC
|
#define DRFLAC_HAS_LZCNT_INTRINSIC
|
||||||
#elif (defined(__GNUC__) && ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)))
|
#elif (defined(__GNUC__) && ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)))
|
||||||
#define DRFLAC_HAS_LZCNT_INTRINSIC
|
#define DRFLAC_HAS_LZCNT_INTRINSIC
|
||||||
@ -1694,7 +1697,7 @@ static drflac_bool32 drflac__find_and_seek_to_next_sync_code(drflac_bs* bs)
|
|||||||
#if !defined(DR_FLAC_NO_SIMD) && defined(DRFLAC_HAS_LZCNT_INTRINSIC)
|
#if !defined(DR_FLAC_NO_SIMD) && defined(DRFLAC_HAS_LZCNT_INTRINSIC)
|
||||||
#define DRFLAC_IMPLEMENT_CLZ_LZCNT
|
#define DRFLAC_IMPLEMENT_CLZ_LZCNT
|
||||||
#endif
|
#endif
|
||||||
#if defined(_MSC_VER) && _MSC_VER >= 1400
|
#if defined(_MSC_VER) && _MSC_VER >= 1400 && (defined(DRFLAC_X64) || defined(DRFLAC_X86))
|
||||||
#define DRFLAC_IMPLEMENT_CLZ_MSVC
|
#define DRFLAC_IMPLEMENT_CLZ_MSVC
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -2402,6 +2405,16 @@ static drflac_bool32 drflac__decode_samples_with_residual(drflac_bs* bs, drflac_
|
|||||||
return DRFLAC_FALSE;
|
return DRFLAC_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// From the FLAC spec:
|
||||||
|
// The Rice partition order in a Rice-coded residual section must be less than or equal to 8.
|
||||||
|
if (partitionOrder > 8) {
|
||||||
|
return DRFLAC_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validation check.
|
||||||
|
if ((blockSize / (1 << partitionOrder)) <= order) {
|
||||||
|
return DRFLAC_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
drflac_uint32 samplesInPartition = (blockSize / (1 << partitionOrder)) - order;
|
drflac_uint32 samplesInPartition = (blockSize / (1 << partitionOrder)) - order;
|
||||||
drflac_uint32 partitionsRemaining = (1 << partitionOrder);
|
drflac_uint32 partitionsRemaining = (1 << partitionOrder);
|
||||||
@ -2446,7 +2459,10 @@ static drflac_bool32 drflac__decode_samples_with_residual(drflac_bs* bs, drflac_
|
|||||||
}
|
}
|
||||||
|
|
||||||
partitionsRemaining -= 1;
|
partitionsRemaining -= 1;
|
||||||
samplesInPartition = blockSize / (1 << partitionOrder);
|
|
||||||
|
if (partitionOrder != 0) {
|
||||||
|
samplesInPartition = blockSize / (1 << partitionOrder);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return DRFLAC_TRUE;
|
return DRFLAC_TRUE;
|
||||||
@ -2982,7 +2998,17 @@ static drflac_result drflac__decode_frame(drflac* pFlac)
|
|||||||
// This function should be called while the stream is sitting on the first byte after the frame header.
|
// This function should be called while the stream is sitting on the first byte after the frame header.
|
||||||
drflac_zero_memory(pFlac->currentFrame.subframes, sizeof(pFlac->currentFrame.subframes));
|
drflac_zero_memory(pFlac->currentFrame.subframes, sizeof(pFlac->currentFrame.subframes));
|
||||||
|
|
||||||
|
// The frame block size must never be larger than the maximum block size defined by the FLAC stream.
|
||||||
|
if (pFlac->currentFrame.header.blockSize > pFlac->maxBlockSize) {
|
||||||
|
return DRFLAC_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The number of channels in the frame must match the channel count from the STREAMINFO block.
|
||||||
int channelCount = drflac__get_channel_count_from_channel_assignment(pFlac->currentFrame.header.channelAssignment);
|
int channelCount = drflac__get_channel_count_from_channel_assignment(pFlac->currentFrame.header.channelAssignment);
|
||||||
|
if (channelCount != (int)pFlac->channels) {
|
||||||
|
return DRFLAC_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < channelCount; ++i) {
|
for (int i = 0; i < channelCount; ++i) {
|
||||||
if (!drflac__decode_subframe(&pFlac->bs, &pFlac->currentFrame, i, pFlac->pDecodedSamples + (pFlac->currentFrame.header.blockSize * i))) {
|
if (!drflac__decode_subframe(&pFlac->bs, &pFlac->currentFrame, i, pFlac->pDecodedSamples + (pFlac->currentFrame.header.blockSize * i))) {
|
||||||
return DRFLAC_ERROR;
|
return DRFLAC_ERROR;
|
||||||
@ -5498,6 +5524,16 @@ const char* drflac_next_vorbis_comment(drflac_vorbis_comment_iterator* pIter, dr
|
|||||||
|
|
||||||
// REVISION HISTORY
|
// REVISION HISTORY
|
||||||
//
|
//
|
||||||
|
// v0.8g - 2018-04-19
|
||||||
|
// - Fix build on non-x86/x64 architectures.
|
||||||
|
//
|
||||||
|
// v0.8f - 2018-02-02
|
||||||
|
// - Stop pretending to support changing rate/channels mid stream.
|
||||||
|
//
|
||||||
|
// v0.8e - 2018-02-01
|
||||||
|
// - Fix a crash when the block size of a frame is larger than the maximum block size defined by the FLAC stream.
|
||||||
|
// - Fix a crash the the Rice partition order is invalid.
|
||||||
|
//
|
||||||
// v0.8d - 2017-09-22
|
// v0.8d - 2017-09-22
|
||||||
// - Add support for decoding streams with ID3 tags. ID3 tags are just skipped.
|
// - Add support for decoding streams with ID3 tags. ID3 tags are just skipped.
|
||||||
//
|
//
|
||||||
|
464
src/external/dr_wav.h
vendored
464
src/external/dr_wav.h
vendored
@ -1,5 +1,5 @@
|
|||||||
// WAV audio loader and writer. Public domain. See "unlicense" statement at the end of this file.
|
// WAV audio loader and writer. Public domain. See "unlicense" statement at the end of this file.
|
||||||
// dr_wav - v0.7a - 2017-11-17
|
// dr_wav - v0.7f - 2018-02-05
|
||||||
//
|
//
|
||||||
// David Reid - mackron@gmail.com
|
// David Reid - mackron@gmail.com
|
||||||
|
|
||||||
@ -103,8 +103,8 @@
|
|||||||
// - Signed 16-bit PCM
|
// - Signed 16-bit PCM
|
||||||
// - Signed 24-bit PCM
|
// - Signed 24-bit PCM
|
||||||
// - Signed 32-bit PCM
|
// - Signed 32-bit PCM
|
||||||
// - IEEE 32-bit floating point.
|
// - IEEE 32-bit floating point
|
||||||
// - IEEE 64-bit floating point.
|
// - IEEE 64-bit floating point
|
||||||
// - A-law and u-law
|
// - A-law and u-law
|
||||||
// - Microsoft ADPCM
|
// - Microsoft ADPCM
|
||||||
// - IMA ADPCM (DVI, format code 0x11)
|
// - IMA ADPCM (DVI, format code 0x11)
|
||||||
@ -643,13 +643,13 @@ drwav_int16* drwav_open_and_read_s16(drwav_read_proc onRead, drwav_seek_proc onS
|
|||||||
float* drwav_open_and_read_f32(drwav_read_proc onRead, drwav_seek_proc onSeek, void* pUserData, unsigned int* channels, unsigned int* sampleRate, drwav_uint64* totalSampleCount);
|
float* drwav_open_and_read_f32(drwav_read_proc onRead, drwav_seek_proc onSeek, void* pUserData, unsigned int* channels, unsigned int* sampleRate, drwav_uint64* totalSampleCount);
|
||||||
drwav_int32* drwav_open_and_read_s32(drwav_read_proc onRead, drwav_seek_proc onSeek, void* pUserData, unsigned int* channels, unsigned int* sampleRate, drwav_uint64* totalSampleCount);
|
drwav_int32* drwav_open_and_read_s32(drwav_read_proc onRead, drwav_seek_proc onSeek, void* pUserData, unsigned int* channels, unsigned int* sampleRate, drwav_uint64* totalSampleCount);
|
||||||
#ifndef DR_WAV_NO_STDIO
|
#ifndef DR_WAV_NO_STDIO
|
||||||
// Opens an decodes a wav file in a single operation.
|
// Opens and decodes a wav file in a single operation.
|
||||||
drwav_int16* drwav_open_and_read_file_s16(const char* filename, unsigned int* channels, unsigned int* sampleRate, drwav_uint64* totalSampleCount);
|
drwav_int16* drwav_open_and_read_file_s16(const char* filename, unsigned int* channels, unsigned int* sampleRate, drwav_uint64* totalSampleCount);
|
||||||
float* drwav_open_and_read_file_f32(const char* filename, unsigned int* channels, unsigned int* sampleRate, drwav_uint64* totalSampleCount);
|
float* drwav_open_and_read_file_f32(const char* filename, unsigned int* channels, unsigned int* sampleRate, drwav_uint64* totalSampleCount);
|
||||||
drwav_int32* drwav_open_and_read_file_s32(const char* filename, unsigned int* channels, unsigned int* sampleRate, drwav_uint64* totalSampleCount);
|
drwav_int32* drwav_open_and_read_file_s32(const char* filename, unsigned int* channels, unsigned int* sampleRate, drwav_uint64* totalSampleCount);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Opens an decodes a wav file from a block of memory in a single operation.
|
// Opens and decodes a wav file from a block of memory in a single operation.
|
||||||
drwav_int16* drwav_open_and_read_memory_s16(const void* data, size_t dataSize, unsigned int* channels, unsigned int* sampleRate, drwav_uint64* totalSampleCount);
|
drwav_int16* drwav_open_and_read_memory_s16(const void* data, size_t dataSize, unsigned int* channels, unsigned int* sampleRate, drwav_uint64* totalSampleCount);
|
||||||
float* drwav_open_and_read_memory_f32(const void* data, size_t dataSize, unsigned int* channels, unsigned int* sampleRate, drwav_uint64* totalSampleCount);
|
float* drwav_open_and_read_memory_f32(const void* data, size_t dataSize, unsigned int* channels, unsigned int* sampleRate, drwav_uint64* totalSampleCount);
|
||||||
drwav_int32* drwav_open_and_read_memory_s32(const void* data, size_t dataSize, unsigned int* channels, unsigned int* sampleRate, drwav_uint64* totalSampleCount);
|
drwav_int32* drwav_open_and_read_memory_s32(const void* data, size_t dataSize, unsigned int* channels, unsigned int* sampleRate, drwav_uint64* totalSampleCount);
|
||||||
@ -820,6 +820,9 @@ static DRWAV_INLINE drwav_bool32 drwav__is_compressed_format_tag(drwav_uint16 fo
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
drwav_uint64 drwav_read_s16__msadpcm(drwav* pWav, drwav_uint64 samplesToRead, drwav_int16* pBufferOut);
|
||||||
|
drwav_uint64 drwav_read_s16__ima(drwav* pWav, drwav_uint64 samplesToRead, drwav_int16* pBufferOut);
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
union
|
union
|
||||||
@ -1395,6 +1398,11 @@ drwav_bool32 drwav_init(drwav* pWav, drwav_read_proc onRead, drwav_seek_proc onS
|
|||||||
return DRWAV_FALSE; // Failed to read the "fmt " chunk.
|
return DRWAV_FALSE; // Failed to read the "fmt " chunk.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Basic validation.
|
||||||
|
if (fmt.sampleRate == 0 || fmt.channels == 0 || fmt.bitsPerSample == 0 || fmt.blockAlign == 0) {
|
||||||
|
return DRWAV_FALSE; // Invalid channel count. Probably an invalid WAV file.
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Translate the internal format.
|
// Translate the internal format.
|
||||||
unsigned short translatedFormatTag = fmt.formatTag;
|
unsigned short translatedFormatTag = fmt.formatTag;
|
||||||
@ -1470,11 +1478,16 @@ drwav_bool32 drwav_init(drwav* pWav, drwav_read_proc onRead, drwav_seek_proc onS
|
|||||||
pWav->sampleRate = fmt.sampleRate;
|
pWav->sampleRate = fmt.sampleRate;
|
||||||
pWav->channels = fmt.channels;
|
pWav->channels = fmt.channels;
|
||||||
pWav->bitsPerSample = fmt.bitsPerSample;
|
pWav->bitsPerSample = fmt.bitsPerSample;
|
||||||
pWav->bytesPerSample = (unsigned int)(fmt.blockAlign / fmt.channels);
|
pWav->bytesPerSample = fmt.blockAlign / fmt.channels;
|
||||||
pWav->bytesRemaining = dataSize;
|
pWav->bytesRemaining = dataSize;
|
||||||
pWav->translatedFormatTag = translatedFormatTag;
|
pWav->translatedFormatTag = translatedFormatTag;
|
||||||
pWav->dataChunkDataSize = dataSize;
|
pWav->dataChunkDataSize = dataSize;
|
||||||
|
|
||||||
|
// The bytes per sample should never be 0 at this point. This would indicate an invalid WAV file.
|
||||||
|
if (pWav->bytesPerSample == 0) {
|
||||||
|
return DRWAV_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
if (sampleCountFromFactChunk != 0) {
|
if (sampleCountFromFactChunk != 0) {
|
||||||
pWav->totalSampleCount = sampleCountFromFactChunk * fmt.channels;
|
pWav->totalSampleCount = sampleCountFromFactChunk * fmt.channels;
|
||||||
} else {
|
} else {
|
||||||
@ -1490,17 +1503,25 @@ drwav_bool32 drwav_init(drwav* pWav, drwav_read_proc onRead, drwav_seek_proc onS
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ADPCM) {
|
// The way we calculate the bytes per sample does not make sense for compressed formats so we just set it to 0.
|
||||||
|
if (drwav__is_compressed_format_tag(pWav->translatedFormatTag)) {
|
||||||
pWav->bytesPerSample = 0;
|
pWav->bytesPerSample = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Some formats only support a certain number of channels.
|
||||||
|
if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ADPCM || pWav->translatedFormatTag == DR_WAVE_FORMAT_DVI_ADPCM) {
|
||||||
|
if (pWav->channels > 2) {
|
||||||
|
return DRWAV_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef DR_WAV_LIBSNDFILE_COMPAT
|
#ifdef DR_WAV_LIBSNDFILE_COMPAT
|
||||||
// I use libsndfile as a benchmark for testing, however in the version I'm using (from the Windows installer on the libsndfile website),
|
// I use libsndfile as a benchmark for testing, however in the version I'm using (from the Windows installer on the libsndfile website),
|
||||||
// it appears the total sample count libsndfile uses for MS-ADPCM is incorrect. It would seem they are computing the total sample count
|
// it appears the total sample count libsndfile uses for MS-ADPCM is incorrect. It would seem they are computing the total sample count
|
||||||
// from the number of blocks, however this results in the inclusion of the extra silent samples at the end of the last block. The correct
|
// from the number of blocks, however this results in the inclusion of the extra silent samples at the end of the last block. The correct
|
||||||
// way to know the total sample count is to inspect the "fact" chunk which should always be present for compressed formats, and should
|
// way to know the total sample count is to inspect the "fact" chunk which should always be present for compressed formats, and should
|
||||||
// always include the sample count. This little block of code below is only used to emulate the libsndfile logic so I can properly run my
|
// always include the sample count. This little block of code below is only used to emulate the libsndfile logic so I can properly run my
|
||||||
// correctness tests against libsndfile and is disabled by default.
|
// correctness tests against libsndfile, and is disabled by default.
|
||||||
if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ADPCM) {
|
if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ADPCM) {
|
||||||
drwav_uint64 blockCount = dataSize / fmt.blockAlign;
|
drwav_uint64 blockCount = dataSize / fmt.blockAlign;
|
||||||
pWav->totalSampleCount = (blockCount * (fmt.blockAlign - (6*pWav->channels))) * 2; // x2 because two samples per byte.
|
pWav->totalSampleCount = (blockCount * (fmt.blockAlign - (6*pWav->channels))) * 2; // x2 because two samples per byte.
|
||||||
@ -1798,27 +1819,40 @@ drwav_bool32 drwav_seek_to_sample(drwav* pWav, drwav_uint64 sample)
|
|||||||
// to seek back to the start.
|
// to seek back to the start.
|
||||||
if (drwav__is_compressed_format_tag(pWav->translatedFormatTag)) {
|
if (drwav__is_compressed_format_tag(pWav->translatedFormatTag)) {
|
||||||
// TODO: This can be optimized.
|
// TODO: This can be optimized.
|
||||||
|
|
||||||
|
// If we're seeking forward it's simple - just keep reading samples until we hit the sample we're requesting. If we're seeking backwards,
|
||||||
|
// we first need to seek back to the start and then just do the same thing as a forward seek.
|
||||||
|
if (sample < pWav->compressed.iCurrentSample) {
|
||||||
|
if (!drwav_seek_to_first_sample(pWav)) {
|
||||||
|
return DRWAV_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (sample > pWav->compressed.iCurrentSample) {
|
if (sample > pWav->compressed.iCurrentSample) {
|
||||||
// Seeking forward - just move from the current position.
|
|
||||||
drwav_uint64 offset = sample - pWav->compressed.iCurrentSample;
|
drwav_uint64 offset = sample - pWav->compressed.iCurrentSample;
|
||||||
|
|
||||||
drwav_int16 devnull[2048];
|
drwav_int16 devnull[2048];
|
||||||
while (offset > 0) {
|
while (offset > 0) {
|
||||||
drwav_uint64 samplesToRead = sample;
|
drwav_uint64 samplesToRead = offset;
|
||||||
if (samplesToRead > 2048) {
|
if (samplesToRead > 2048) {
|
||||||
samplesToRead = 2048;
|
samplesToRead = 2048;
|
||||||
}
|
}
|
||||||
|
|
||||||
drwav_uint64 samplesRead = drwav_read_s16(pWav, samplesToRead, devnull);
|
drwav_uint64 samplesRead = 0;
|
||||||
|
if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ADPCM) {
|
||||||
|
samplesRead = drwav_read_s16__msadpcm(pWav, samplesToRead, devnull);
|
||||||
|
} else if (pWav->translatedFormatTag == DR_WAVE_FORMAT_DVI_ADPCM) {
|
||||||
|
samplesRead = drwav_read_s16__ima(pWav, samplesToRead, devnull);
|
||||||
|
} else {
|
||||||
|
assert(DRWAV_FALSE); // If this assertion is triggered it means I've implemented a new compressed format but forgot to add a branch for it here.
|
||||||
|
}
|
||||||
|
|
||||||
if (samplesRead != samplesToRead) {
|
if (samplesRead != samplesToRead) {
|
||||||
return DRWAV_FALSE;
|
return DRWAV_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
offset -= samplesRead;
|
offset -= samplesRead;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// Seeking backwards. Just use the fallback.
|
|
||||||
goto fallback;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
drwav_uint64 totalSizeInBytes = pWav->totalSampleCount * pWav->bytesPerSample;
|
drwav_uint64 totalSizeInBytes = pWav->totalSampleCount * pWav->bytesPerSample;
|
||||||
@ -1850,30 +1884,6 @@ drwav_bool32 drwav_seek_to_sample(drwav* pWav, drwav_uint64 sample)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return DRWAV_TRUE;
|
|
||||||
|
|
||||||
fallback:
|
|
||||||
// This is a generic seek implementation that just continuously reads samples into a temporary buffer. This should work for all supported
|
|
||||||
// formats, but it is not efficient. This should be used as a fall back.
|
|
||||||
if (!drwav_seek_to_first_sample(pWav)) {
|
|
||||||
return DRWAV_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
drwav_int16 devnull[2048];
|
|
||||||
while (sample > 0) {
|
|
||||||
drwav_uint64 samplesToRead = sample;
|
|
||||||
if (samplesToRead > 2048) {
|
|
||||||
samplesToRead = 2048;
|
|
||||||
}
|
|
||||||
|
|
||||||
drwav_uint64 samplesRead = drwav_read_s16(pWav, samplesToRead, devnull);
|
|
||||||
if (samplesRead != samplesToRead) {
|
|
||||||
return DRWAV_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
sample -= samplesRead;
|
|
||||||
}
|
|
||||||
|
|
||||||
return DRWAV_TRUE;
|
return DRWAV_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1906,132 +1916,6 @@ drwav_uint64 drwav_write(drwav* pWav, drwav_uint64 samplesToWrite, const void* p
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifndef DR_WAV_NO_CONVERSION_API
|
|
||||||
static unsigned short g_drwavAlawTable[256] = {
|
|
||||||
0xEA80, 0xEB80, 0xE880, 0xE980, 0xEE80, 0xEF80, 0xEC80, 0xED80, 0xE280, 0xE380, 0xE080, 0xE180, 0xE680, 0xE780, 0xE480, 0xE580,
|
|
||||||
0xF540, 0xF5C0, 0xF440, 0xF4C0, 0xF740, 0xF7C0, 0xF640, 0xF6C0, 0xF140, 0xF1C0, 0xF040, 0xF0C0, 0xF340, 0xF3C0, 0xF240, 0xF2C0,
|
|
||||||
0xAA00, 0xAE00, 0xA200, 0xA600, 0xBA00, 0xBE00, 0xB200, 0xB600, 0x8A00, 0x8E00, 0x8200, 0x8600, 0x9A00, 0x9E00, 0x9200, 0x9600,
|
|
||||||
0xD500, 0xD700, 0xD100, 0xD300, 0xDD00, 0xDF00, 0xD900, 0xDB00, 0xC500, 0xC700, 0xC100, 0xC300, 0xCD00, 0xCF00, 0xC900, 0xCB00,
|
|
||||||
0xFEA8, 0xFEB8, 0xFE88, 0xFE98, 0xFEE8, 0xFEF8, 0xFEC8, 0xFED8, 0xFE28, 0xFE38, 0xFE08, 0xFE18, 0xFE68, 0xFE78, 0xFE48, 0xFE58,
|
|
||||||
0xFFA8, 0xFFB8, 0xFF88, 0xFF98, 0xFFE8, 0xFFF8, 0xFFC8, 0xFFD8, 0xFF28, 0xFF38, 0xFF08, 0xFF18, 0xFF68, 0xFF78, 0xFF48, 0xFF58,
|
|
||||||
0xFAA0, 0xFAE0, 0xFA20, 0xFA60, 0xFBA0, 0xFBE0, 0xFB20, 0xFB60, 0xF8A0, 0xF8E0, 0xF820, 0xF860, 0xF9A0, 0xF9E0, 0xF920, 0xF960,
|
|
||||||
0xFD50, 0xFD70, 0xFD10, 0xFD30, 0xFDD0, 0xFDF0, 0xFD90, 0xFDB0, 0xFC50, 0xFC70, 0xFC10, 0xFC30, 0xFCD0, 0xFCF0, 0xFC90, 0xFCB0,
|
|
||||||
0x1580, 0x1480, 0x1780, 0x1680, 0x1180, 0x1080, 0x1380, 0x1280, 0x1D80, 0x1C80, 0x1F80, 0x1E80, 0x1980, 0x1880, 0x1B80, 0x1A80,
|
|
||||||
0x0AC0, 0x0A40, 0x0BC0, 0x0B40, 0x08C0, 0x0840, 0x09C0, 0x0940, 0x0EC0, 0x0E40, 0x0FC0, 0x0F40, 0x0CC0, 0x0C40, 0x0DC0, 0x0D40,
|
|
||||||
0x5600, 0x5200, 0x5E00, 0x5A00, 0x4600, 0x4200, 0x4E00, 0x4A00, 0x7600, 0x7200, 0x7E00, 0x7A00, 0x6600, 0x6200, 0x6E00, 0x6A00,
|
|
||||||
0x2B00, 0x2900, 0x2F00, 0x2D00, 0x2300, 0x2100, 0x2700, 0x2500, 0x3B00, 0x3900, 0x3F00, 0x3D00, 0x3300, 0x3100, 0x3700, 0x3500,
|
|
||||||
0x0158, 0x0148, 0x0178, 0x0168, 0x0118, 0x0108, 0x0138, 0x0128, 0x01D8, 0x01C8, 0x01F8, 0x01E8, 0x0198, 0x0188, 0x01B8, 0x01A8,
|
|
||||||
0x0058, 0x0048, 0x0078, 0x0068, 0x0018, 0x0008, 0x0038, 0x0028, 0x00D8, 0x00C8, 0x00F8, 0x00E8, 0x0098, 0x0088, 0x00B8, 0x00A8,
|
|
||||||
0x0560, 0x0520, 0x05E0, 0x05A0, 0x0460, 0x0420, 0x04E0, 0x04A0, 0x0760, 0x0720, 0x07E0, 0x07A0, 0x0660, 0x0620, 0x06E0, 0x06A0,
|
|
||||||
0x02B0, 0x0290, 0x02F0, 0x02D0, 0x0230, 0x0210, 0x0270, 0x0250, 0x03B0, 0x0390, 0x03F0, 0x03D0, 0x0330, 0x0310, 0x0370, 0x0350
|
|
||||||
};
|
|
||||||
|
|
||||||
static unsigned short g_drwavMulawTable[256] = {
|
|
||||||
0x8284, 0x8684, 0x8A84, 0x8E84, 0x9284, 0x9684, 0x9A84, 0x9E84, 0xA284, 0xA684, 0xAA84, 0xAE84, 0xB284, 0xB684, 0xBA84, 0xBE84,
|
|
||||||
0xC184, 0xC384, 0xC584, 0xC784, 0xC984, 0xCB84, 0xCD84, 0xCF84, 0xD184, 0xD384, 0xD584, 0xD784, 0xD984, 0xDB84, 0xDD84, 0xDF84,
|
|
||||||
0xE104, 0xE204, 0xE304, 0xE404, 0xE504, 0xE604, 0xE704, 0xE804, 0xE904, 0xEA04, 0xEB04, 0xEC04, 0xED04, 0xEE04, 0xEF04, 0xF004,
|
|
||||||
0xF0C4, 0xF144, 0xF1C4, 0xF244, 0xF2C4, 0xF344, 0xF3C4, 0xF444, 0xF4C4, 0xF544, 0xF5C4, 0xF644, 0xF6C4, 0xF744, 0xF7C4, 0xF844,
|
|
||||||
0xF8A4, 0xF8E4, 0xF924, 0xF964, 0xF9A4, 0xF9E4, 0xFA24, 0xFA64, 0xFAA4, 0xFAE4, 0xFB24, 0xFB64, 0xFBA4, 0xFBE4, 0xFC24, 0xFC64,
|
|
||||||
0xFC94, 0xFCB4, 0xFCD4, 0xFCF4, 0xFD14, 0xFD34, 0xFD54, 0xFD74, 0xFD94, 0xFDB4, 0xFDD4, 0xFDF4, 0xFE14, 0xFE34, 0xFE54, 0xFE74,
|
|
||||||
0xFE8C, 0xFE9C, 0xFEAC, 0xFEBC, 0xFECC, 0xFEDC, 0xFEEC, 0xFEFC, 0xFF0C, 0xFF1C, 0xFF2C, 0xFF3C, 0xFF4C, 0xFF5C, 0xFF6C, 0xFF7C,
|
|
||||||
0xFF88, 0xFF90, 0xFF98, 0xFFA0, 0xFFA8, 0xFFB0, 0xFFB8, 0xFFC0, 0xFFC8, 0xFFD0, 0xFFD8, 0xFFE0, 0xFFE8, 0xFFF0, 0xFFF8, 0x0000,
|
|
||||||
0x7D7C, 0x797C, 0x757C, 0x717C, 0x6D7C, 0x697C, 0x657C, 0x617C, 0x5D7C, 0x597C, 0x557C, 0x517C, 0x4D7C, 0x497C, 0x457C, 0x417C,
|
|
||||||
0x3E7C, 0x3C7C, 0x3A7C, 0x387C, 0x367C, 0x347C, 0x327C, 0x307C, 0x2E7C, 0x2C7C, 0x2A7C, 0x287C, 0x267C, 0x247C, 0x227C, 0x207C,
|
|
||||||
0x1EFC, 0x1DFC, 0x1CFC, 0x1BFC, 0x1AFC, 0x19FC, 0x18FC, 0x17FC, 0x16FC, 0x15FC, 0x14FC, 0x13FC, 0x12FC, 0x11FC, 0x10FC, 0x0FFC,
|
|
||||||
0x0F3C, 0x0EBC, 0x0E3C, 0x0DBC, 0x0D3C, 0x0CBC, 0x0C3C, 0x0BBC, 0x0B3C, 0x0ABC, 0x0A3C, 0x09BC, 0x093C, 0x08BC, 0x083C, 0x07BC,
|
|
||||||
0x075C, 0x071C, 0x06DC, 0x069C, 0x065C, 0x061C, 0x05DC, 0x059C, 0x055C, 0x051C, 0x04DC, 0x049C, 0x045C, 0x041C, 0x03DC, 0x039C,
|
|
||||||
0x036C, 0x034C, 0x032C, 0x030C, 0x02EC, 0x02CC, 0x02AC, 0x028C, 0x026C, 0x024C, 0x022C, 0x020C, 0x01EC, 0x01CC, 0x01AC, 0x018C,
|
|
||||||
0x0174, 0x0164, 0x0154, 0x0144, 0x0134, 0x0124, 0x0114, 0x0104, 0x00F4, 0x00E4, 0x00D4, 0x00C4, 0x00B4, 0x00A4, 0x0094, 0x0084,
|
|
||||||
0x0078, 0x0070, 0x0068, 0x0060, 0x0058, 0x0050, 0x0048, 0x0040, 0x0038, 0x0030, 0x0028, 0x0020, 0x0018, 0x0010, 0x0008, 0x0000
|
|
||||||
};
|
|
||||||
|
|
||||||
static DRWAV_INLINE drwav_int16 drwav__alaw_to_s16(drwav_uint8 sampleIn)
|
|
||||||
{
|
|
||||||
return (short)g_drwavAlawTable[sampleIn];
|
|
||||||
}
|
|
||||||
|
|
||||||
static DRWAV_INLINE drwav_int16 drwav__mulaw_to_s16(drwav_uint8 sampleIn)
|
|
||||||
{
|
|
||||||
return (short)g_drwavMulawTable[sampleIn];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void drwav__pcm_to_s16(drwav_int16* pOut, const unsigned char* pIn, size_t totalSampleCount, unsigned short bytesPerSample)
|
|
||||||
{
|
|
||||||
// Special case for 8-bit sample data because it's treated as unsigned.
|
|
||||||
if (bytesPerSample == 1) {
|
|
||||||
drwav_u8_to_s16(pOut, pIn, totalSampleCount);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Slightly more optimal implementation for common formats.
|
|
||||||
if (bytesPerSample == 2) {
|
|
||||||
for (unsigned int i = 0; i < totalSampleCount; ++i) {
|
|
||||||
*pOut++ = ((drwav_int16*)pIn)[i];
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (bytesPerSample == 3) {
|
|
||||||
drwav_s24_to_s16(pOut, pIn, totalSampleCount);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (bytesPerSample == 4) {
|
|
||||||
drwav_s32_to_s16(pOut, (const drwav_int32*)pIn, totalSampleCount);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Generic, slow converter.
|
|
||||||
for (unsigned int i = 0; i < totalSampleCount; ++i) {
|
|
||||||
unsigned short sample = 0;
|
|
||||||
unsigned short shift = (8 - bytesPerSample) * 8;
|
|
||||||
for (unsigned short j = 0; j < bytesPerSample && j < 2; ++j) {
|
|
||||||
sample |= (unsigned short)(pIn[j]) << shift;
|
|
||||||
shift += 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
pIn += bytesPerSample;
|
|
||||||
*pOut++ = sample;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void drwav__ieee_to_s16(drwav_int16* pOut, const unsigned char* pIn, size_t totalSampleCount, unsigned short bytesPerSample)
|
|
||||||
{
|
|
||||||
if (bytesPerSample == 4) {
|
|
||||||
drwav_f32_to_s16(pOut, (float*)pIn, totalSampleCount);
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
drwav_f64_to_s16(pOut, (double*)pIn, totalSampleCount);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
drwav_uint64 drwav_read_s16__pcm(drwav* pWav, drwav_uint64 samplesToRead, drwav_int16* pBufferOut)
|
|
||||||
{
|
|
||||||
// Fast path.
|
|
||||||
if (pWav->bytesPerSample == 2) {
|
|
||||||
return drwav_read(pWav, samplesToRead, pBufferOut);
|
|
||||||
}
|
|
||||||
|
|
||||||
drwav_uint64 totalSamplesRead = 0;
|
|
||||||
unsigned char sampleData[4096];
|
|
||||||
while (samplesToRead > 0) {
|
|
||||||
drwav_uint64 samplesRead = drwav_read(pWav, drwav_min(samplesToRead, sizeof(sampleData)/pWav->bytesPerSample), sampleData);
|
|
||||||
if (samplesRead == 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
drwav__pcm_to_s16(pBufferOut, sampleData, (size_t)samplesRead, pWav->bytesPerSample);
|
|
||||||
|
|
||||||
pBufferOut += samplesRead;
|
|
||||||
samplesToRead -= samplesRead;
|
|
||||||
totalSamplesRead += samplesRead;
|
|
||||||
}
|
|
||||||
|
|
||||||
return totalSamplesRead;
|
|
||||||
}
|
|
||||||
|
|
||||||
drwav_uint64 drwav_read_s16__msadpcm(drwav* pWav, drwav_uint64 samplesToRead, drwav_int16* pBufferOut)
|
drwav_uint64 drwav_read_s16__msadpcm(drwav* pWav, drwav_uint64 samplesToRead, drwav_int16* pBufferOut)
|
||||||
{
|
{
|
||||||
@ -2334,6 +2218,147 @@ drwav_uint64 drwav_read_s16__ima(drwav* pWav, drwav_uint64 samplesToRead, drwav_
|
|||||||
return totalSamplesRead;
|
return totalSamplesRead;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef DR_WAV_NO_CONVERSION_API
|
||||||
|
static unsigned short g_drwavAlawTable[256] = {
|
||||||
|
0xEA80, 0xEB80, 0xE880, 0xE980, 0xEE80, 0xEF80, 0xEC80, 0xED80, 0xE280, 0xE380, 0xE080, 0xE180, 0xE680, 0xE780, 0xE480, 0xE580,
|
||||||
|
0xF540, 0xF5C0, 0xF440, 0xF4C0, 0xF740, 0xF7C0, 0xF640, 0xF6C0, 0xF140, 0xF1C0, 0xF040, 0xF0C0, 0xF340, 0xF3C0, 0xF240, 0xF2C0,
|
||||||
|
0xAA00, 0xAE00, 0xA200, 0xA600, 0xBA00, 0xBE00, 0xB200, 0xB600, 0x8A00, 0x8E00, 0x8200, 0x8600, 0x9A00, 0x9E00, 0x9200, 0x9600,
|
||||||
|
0xD500, 0xD700, 0xD100, 0xD300, 0xDD00, 0xDF00, 0xD900, 0xDB00, 0xC500, 0xC700, 0xC100, 0xC300, 0xCD00, 0xCF00, 0xC900, 0xCB00,
|
||||||
|
0xFEA8, 0xFEB8, 0xFE88, 0xFE98, 0xFEE8, 0xFEF8, 0xFEC8, 0xFED8, 0xFE28, 0xFE38, 0xFE08, 0xFE18, 0xFE68, 0xFE78, 0xFE48, 0xFE58,
|
||||||
|
0xFFA8, 0xFFB8, 0xFF88, 0xFF98, 0xFFE8, 0xFFF8, 0xFFC8, 0xFFD8, 0xFF28, 0xFF38, 0xFF08, 0xFF18, 0xFF68, 0xFF78, 0xFF48, 0xFF58,
|
||||||
|
0xFAA0, 0xFAE0, 0xFA20, 0xFA60, 0xFBA0, 0xFBE0, 0xFB20, 0xFB60, 0xF8A0, 0xF8E0, 0xF820, 0xF860, 0xF9A0, 0xF9E0, 0xF920, 0xF960,
|
||||||
|
0xFD50, 0xFD70, 0xFD10, 0xFD30, 0xFDD0, 0xFDF0, 0xFD90, 0xFDB0, 0xFC50, 0xFC70, 0xFC10, 0xFC30, 0xFCD0, 0xFCF0, 0xFC90, 0xFCB0,
|
||||||
|
0x1580, 0x1480, 0x1780, 0x1680, 0x1180, 0x1080, 0x1380, 0x1280, 0x1D80, 0x1C80, 0x1F80, 0x1E80, 0x1980, 0x1880, 0x1B80, 0x1A80,
|
||||||
|
0x0AC0, 0x0A40, 0x0BC0, 0x0B40, 0x08C0, 0x0840, 0x09C0, 0x0940, 0x0EC0, 0x0E40, 0x0FC0, 0x0F40, 0x0CC0, 0x0C40, 0x0DC0, 0x0D40,
|
||||||
|
0x5600, 0x5200, 0x5E00, 0x5A00, 0x4600, 0x4200, 0x4E00, 0x4A00, 0x7600, 0x7200, 0x7E00, 0x7A00, 0x6600, 0x6200, 0x6E00, 0x6A00,
|
||||||
|
0x2B00, 0x2900, 0x2F00, 0x2D00, 0x2300, 0x2100, 0x2700, 0x2500, 0x3B00, 0x3900, 0x3F00, 0x3D00, 0x3300, 0x3100, 0x3700, 0x3500,
|
||||||
|
0x0158, 0x0148, 0x0178, 0x0168, 0x0118, 0x0108, 0x0138, 0x0128, 0x01D8, 0x01C8, 0x01F8, 0x01E8, 0x0198, 0x0188, 0x01B8, 0x01A8,
|
||||||
|
0x0058, 0x0048, 0x0078, 0x0068, 0x0018, 0x0008, 0x0038, 0x0028, 0x00D8, 0x00C8, 0x00F8, 0x00E8, 0x0098, 0x0088, 0x00B8, 0x00A8,
|
||||||
|
0x0560, 0x0520, 0x05E0, 0x05A0, 0x0460, 0x0420, 0x04E0, 0x04A0, 0x0760, 0x0720, 0x07E0, 0x07A0, 0x0660, 0x0620, 0x06E0, 0x06A0,
|
||||||
|
0x02B0, 0x0290, 0x02F0, 0x02D0, 0x0230, 0x0210, 0x0270, 0x0250, 0x03B0, 0x0390, 0x03F0, 0x03D0, 0x0330, 0x0310, 0x0370, 0x0350
|
||||||
|
};
|
||||||
|
|
||||||
|
static unsigned short g_drwavMulawTable[256] = {
|
||||||
|
0x8284, 0x8684, 0x8A84, 0x8E84, 0x9284, 0x9684, 0x9A84, 0x9E84, 0xA284, 0xA684, 0xAA84, 0xAE84, 0xB284, 0xB684, 0xBA84, 0xBE84,
|
||||||
|
0xC184, 0xC384, 0xC584, 0xC784, 0xC984, 0xCB84, 0xCD84, 0xCF84, 0xD184, 0xD384, 0xD584, 0xD784, 0xD984, 0xDB84, 0xDD84, 0xDF84,
|
||||||
|
0xE104, 0xE204, 0xE304, 0xE404, 0xE504, 0xE604, 0xE704, 0xE804, 0xE904, 0xEA04, 0xEB04, 0xEC04, 0xED04, 0xEE04, 0xEF04, 0xF004,
|
||||||
|
0xF0C4, 0xF144, 0xF1C4, 0xF244, 0xF2C4, 0xF344, 0xF3C4, 0xF444, 0xF4C4, 0xF544, 0xF5C4, 0xF644, 0xF6C4, 0xF744, 0xF7C4, 0xF844,
|
||||||
|
0xF8A4, 0xF8E4, 0xF924, 0xF964, 0xF9A4, 0xF9E4, 0xFA24, 0xFA64, 0xFAA4, 0xFAE4, 0xFB24, 0xFB64, 0xFBA4, 0xFBE4, 0xFC24, 0xFC64,
|
||||||
|
0xFC94, 0xFCB4, 0xFCD4, 0xFCF4, 0xFD14, 0xFD34, 0xFD54, 0xFD74, 0xFD94, 0xFDB4, 0xFDD4, 0xFDF4, 0xFE14, 0xFE34, 0xFE54, 0xFE74,
|
||||||
|
0xFE8C, 0xFE9C, 0xFEAC, 0xFEBC, 0xFECC, 0xFEDC, 0xFEEC, 0xFEFC, 0xFF0C, 0xFF1C, 0xFF2C, 0xFF3C, 0xFF4C, 0xFF5C, 0xFF6C, 0xFF7C,
|
||||||
|
0xFF88, 0xFF90, 0xFF98, 0xFFA0, 0xFFA8, 0xFFB0, 0xFFB8, 0xFFC0, 0xFFC8, 0xFFD0, 0xFFD8, 0xFFE0, 0xFFE8, 0xFFF0, 0xFFF8, 0x0000,
|
||||||
|
0x7D7C, 0x797C, 0x757C, 0x717C, 0x6D7C, 0x697C, 0x657C, 0x617C, 0x5D7C, 0x597C, 0x557C, 0x517C, 0x4D7C, 0x497C, 0x457C, 0x417C,
|
||||||
|
0x3E7C, 0x3C7C, 0x3A7C, 0x387C, 0x367C, 0x347C, 0x327C, 0x307C, 0x2E7C, 0x2C7C, 0x2A7C, 0x287C, 0x267C, 0x247C, 0x227C, 0x207C,
|
||||||
|
0x1EFC, 0x1DFC, 0x1CFC, 0x1BFC, 0x1AFC, 0x19FC, 0x18FC, 0x17FC, 0x16FC, 0x15FC, 0x14FC, 0x13FC, 0x12FC, 0x11FC, 0x10FC, 0x0FFC,
|
||||||
|
0x0F3C, 0x0EBC, 0x0E3C, 0x0DBC, 0x0D3C, 0x0CBC, 0x0C3C, 0x0BBC, 0x0B3C, 0x0ABC, 0x0A3C, 0x09BC, 0x093C, 0x08BC, 0x083C, 0x07BC,
|
||||||
|
0x075C, 0x071C, 0x06DC, 0x069C, 0x065C, 0x061C, 0x05DC, 0x059C, 0x055C, 0x051C, 0x04DC, 0x049C, 0x045C, 0x041C, 0x03DC, 0x039C,
|
||||||
|
0x036C, 0x034C, 0x032C, 0x030C, 0x02EC, 0x02CC, 0x02AC, 0x028C, 0x026C, 0x024C, 0x022C, 0x020C, 0x01EC, 0x01CC, 0x01AC, 0x018C,
|
||||||
|
0x0174, 0x0164, 0x0154, 0x0144, 0x0134, 0x0124, 0x0114, 0x0104, 0x00F4, 0x00E4, 0x00D4, 0x00C4, 0x00B4, 0x00A4, 0x0094, 0x0084,
|
||||||
|
0x0078, 0x0070, 0x0068, 0x0060, 0x0058, 0x0050, 0x0048, 0x0040, 0x0038, 0x0030, 0x0028, 0x0020, 0x0018, 0x0010, 0x0008, 0x0000
|
||||||
|
};
|
||||||
|
|
||||||
|
static DRWAV_INLINE drwav_int16 drwav__alaw_to_s16(drwav_uint8 sampleIn)
|
||||||
|
{
|
||||||
|
return (short)g_drwavAlawTable[sampleIn];
|
||||||
|
}
|
||||||
|
|
||||||
|
static DRWAV_INLINE drwav_int16 drwav__mulaw_to_s16(drwav_uint8 sampleIn)
|
||||||
|
{
|
||||||
|
return (short)g_drwavMulawTable[sampleIn];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void drwav__pcm_to_s16(drwav_int16* pOut, const unsigned char* pIn, size_t totalSampleCount, unsigned short bytesPerSample)
|
||||||
|
{
|
||||||
|
// Special case for 8-bit sample data because it's treated as unsigned.
|
||||||
|
if (bytesPerSample == 1) {
|
||||||
|
drwav_u8_to_s16(pOut, pIn, totalSampleCount);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Slightly more optimal implementation for common formats.
|
||||||
|
if (bytesPerSample == 2) {
|
||||||
|
for (unsigned int i = 0; i < totalSampleCount; ++i) {
|
||||||
|
*pOut++ = ((drwav_int16*)pIn)[i];
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (bytesPerSample == 3) {
|
||||||
|
drwav_s24_to_s16(pOut, pIn, totalSampleCount);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (bytesPerSample == 4) {
|
||||||
|
drwav_s32_to_s16(pOut, (const drwav_int32*)pIn, totalSampleCount);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Anything more than 64 bits per sample is not supported.
|
||||||
|
if (bytesPerSample > 8) {
|
||||||
|
drwav_zero_memory(pOut, totalSampleCount * sizeof(*pOut));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Generic, slow converter.
|
||||||
|
for (unsigned int i = 0; i < totalSampleCount; ++i) {
|
||||||
|
drwav_uint64 sample = 0;
|
||||||
|
unsigned int shift = (8 - bytesPerSample) * 8;
|
||||||
|
|
||||||
|
unsigned int j;
|
||||||
|
for (j = 0; j < bytesPerSample && j < 8; j += 1) {
|
||||||
|
sample |= (drwav_uint64)(pIn[j]) << shift;
|
||||||
|
shift += 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
pIn += j;
|
||||||
|
*pOut++ = (drwav_int16)((drwav_int64)sample >> 48);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void drwav__ieee_to_s16(drwav_int16* pOut, const unsigned char* pIn, size_t totalSampleCount, unsigned short bytesPerSample)
|
||||||
|
{
|
||||||
|
if (bytesPerSample == 4) {
|
||||||
|
drwav_f32_to_s16(pOut, (float*)pIn, totalSampleCount);
|
||||||
|
return;
|
||||||
|
} else if (bytesPerSample == 8) {
|
||||||
|
drwav_f64_to_s16(pOut, (double*)pIn, totalSampleCount);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
// Only supporting 32- and 64-bit float. Output silence in all other cases. Contributions welcome for 16-bit float.
|
||||||
|
drwav_zero_memory(pOut, totalSampleCount * sizeof(*pOut));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
drwav_uint64 drwav_read_s16__pcm(drwav* pWav, drwav_uint64 samplesToRead, drwav_int16* pBufferOut)
|
||||||
|
{
|
||||||
|
// Fast path.
|
||||||
|
if (pWav->bytesPerSample == 2) {
|
||||||
|
return drwav_read(pWav, samplesToRead, pBufferOut);
|
||||||
|
}
|
||||||
|
|
||||||
|
drwav_uint64 totalSamplesRead = 0;
|
||||||
|
unsigned char sampleData[4096];
|
||||||
|
while (samplesToRead > 0) {
|
||||||
|
drwav_uint64 samplesRead = drwav_read(pWav, drwav_min(samplesToRead, sizeof(sampleData)/pWav->bytesPerSample), sampleData);
|
||||||
|
if (samplesRead == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
drwav__pcm_to_s16(pBufferOut, sampleData, (size_t)samplesRead, pWav->bytesPerSample);
|
||||||
|
|
||||||
|
pBufferOut += samplesRead;
|
||||||
|
samplesToRead -= samplesRead;
|
||||||
|
totalSamplesRead += samplesRead;
|
||||||
|
}
|
||||||
|
|
||||||
|
return totalSamplesRead;
|
||||||
|
}
|
||||||
|
|
||||||
drwav_uint64 drwav_read_s16__ieee(drwav* pWav, drwav_uint64 samplesToRead, drwav_int16* pBufferOut)
|
drwav_uint64 drwav_read_s16__ieee(drwav* pWav, drwav_uint64 samplesToRead, drwav_int16* pBufferOut)
|
||||||
{
|
{
|
||||||
drwav_uint64 totalSamplesRead = 0;
|
drwav_uint64 totalSamplesRead = 0;
|
||||||
@ -2529,17 +2554,27 @@ static void drwav__pcm_to_f32(float* pOut, const unsigned char* pIn, size_t samp
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Anything more than 64 bits per sample is not supported.
|
||||||
|
if (bytesPerSample > 8) {
|
||||||
|
drwav_zero_memory(pOut, sampleCount * sizeof(*pOut));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Generic, slow converter.
|
// Generic, slow converter.
|
||||||
for (unsigned int i = 0; i < sampleCount; ++i) {
|
for (unsigned int i = 0; i < sampleCount; ++i) {
|
||||||
unsigned int sample = 0;
|
drwav_uint64 sample = 0;
|
||||||
unsigned int shift = (8 - bytesPerSample) * 8;
|
unsigned int shift = (8 - bytesPerSample) * 8;
|
||||||
for (unsigned short j = 0; j < bytesPerSample && j < 4; ++j) {
|
|
||||||
sample |= (unsigned int)(pIn[j]) << shift;
|
unsigned int j;
|
||||||
|
for (j = 0; j < bytesPerSample && j < 8; j += 1) {
|
||||||
|
sample |= (drwav_uint64)(pIn[j]) << shift;
|
||||||
shift += 8;
|
shift += 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
pIn += bytesPerSample;
|
pIn += j;
|
||||||
*pOut++ = (float)((int)sample / 2147483648.0);
|
*pOut++ = (float)((drwav_int64)sample / 9223372036854775807.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2550,15 +2585,23 @@ static void drwav__ieee_to_f32(float* pOut, const unsigned char* pIn, size_t sam
|
|||||||
*pOut++ = ((float*)pIn)[i];
|
*pOut++ = ((float*)pIn)[i];
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
} else {
|
} else if (bytesPerSample == 8) {
|
||||||
drwav_f64_to_f32(pOut, (double*)pIn, sampleCount);
|
drwav_f64_to_f32(pOut, (double*)pIn, sampleCount);
|
||||||
return;
|
return;
|
||||||
|
} else {
|
||||||
|
// Only supporting 32- and 64-bit float. Output silence in all other cases. Contributions welcome for 16-bit float.
|
||||||
|
drwav_zero_memory(pOut, sampleCount * sizeof(*pOut));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
drwav_uint64 drwav_read_f32__pcm(drwav* pWav, drwav_uint64 samplesToRead, float* pBufferOut)
|
drwav_uint64 drwav_read_f32__pcm(drwav* pWav, drwav_uint64 samplesToRead, float* pBufferOut)
|
||||||
{
|
{
|
||||||
|
if (pWav->bytesPerSample == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
drwav_uint64 totalSamplesRead = 0;
|
drwav_uint64 totalSamplesRead = 0;
|
||||||
unsigned char sampleData[4096];
|
unsigned char sampleData[4096];
|
||||||
while (samplesToRead > 0) {
|
while (samplesToRead > 0) {
|
||||||
@ -2628,6 +2671,10 @@ drwav_uint64 drwav_read_f32__ieee(drwav* pWav, drwav_uint64 samplesToRead, float
|
|||||||
return drwav_read(pWav, samplesToRead, pBufferOut);
|
return drwav_read(pWav, samplesToRead, pBufferOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pWav->bytesPerSample == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
drwav_uint64 totalSamplesRead = 0;
|
drwav_uint64 totalSamplesRead = 0;
|
||||||
unsigned char sampleData[4096];
|
unsigned char sampleData[4096];
|
||||||
while (samplesToRead > 0) {
|
while (samplesToRead > 0) {
|
||||||
@ -2648,6 +2695,10 @@ drwav_uint64 drwav_read_f32__ieee(drwav* pWav, drwav_uint64 samplesToRead, float
|
|||||||
|
|
||||||
drwav_uint64 drwav_read_f32__alaw(drwav* pWav, drwav_uint64 samplesToRead, float* pBufferOut)
|
drwav_uint64 drwav_read_f32__alaw(drwav* pWav, drwav_uint64 samplesToRead, float* pBufferOut)
|
||||||
{
|
{
|
||||||
|
if (pWav->bytesPerSample == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
drwav_uint64 totalSamplesRead = 0;
|
drwav_uint64 totalSamplesRead = 0;
|
||||||
unsigned char sampleData[4096];
|
unsigned char sampleData[4096];
|
||||||
while (samplesToRead > 0) {
|
while (samplesToRead > 0) {
|
||||||
@ -2668,6 +2719,10 @@ drwav_uint64 drwav_read_f32__alaw(drwav* pWav, drwav_uint64 samplesToRead, float
|
|||||||
|
|
||||||
drwav_uint64 drwav_read_f32__mulaw(drwav* pWav, drwav_uint64 samplesToRead, float* pBufferOut)
|
drwav_uint64 drwav_read_f32__mulaw(drwav* pWav, drwav_uint64 samplesToRead, float* pBufferOut)
|
||||||
{
|
{
|
||||||
|
if (pWav->bytesPerSample == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
drwav_uint64 totalSamplesRead = 0;
|
drwav_uint64 totalSamplesRead = 0;
|
||||||
unsigned char sampleData[4096];
|
unsigned char sampleData[4096];
|
||||||
while (samplesToRead > 0) {
|
while (samplesToRead > 0) {
|
||||||
@ -2842,17 +2897,27 @@ static void drwav__pcm_to_s32(drwav_int32* pOut, const unsigned char* pIn, size_
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Anything more than 64 bits per sample is not supported.
|
||||||
|
if (bytesPerSample > 8) {
|
||||||
|
drwav_zero_memory(pOut, totalSampleCount * sizeof(*pOut));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Generic, slow converter.
|
// Generic, slow converter.
|
||||||
for (unsigned int i = 0; i < totalSampleCount; ++i) {
|
for (unsigned int i = 0; i < totalSampleCount; ++i) {
|
||||||
unsigned int sample = 0;
|
drwav_uint64 sample = 0;
|
||||||
unsigned int shift = (8 - bytesPerSample) * 8;
|
unsigned int shift = (8 - bytesPerSample) * 8;
|
||||||
for (unsigned short j = 0; j < bytesPerSample && j < 4; ++j) {
|
|
||||||
sample |= (unsigned int)(pIn[j]) << shift;
|
unsigned int j;
|
||||||
|
for (j = 0; j < bytesPerSample && j < 8; j += 1) {
|
||||||
|
sample |= (drwav_uint64)(pIn[j]) << shift;
|
||||||
shift += 8;
|
shift += 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
pIn += bytesPerSample;
|
pIn += j;
|
||||||
*pOut++ = sample;
|
*pOut++ = (drwav_int32)((drwav_int64)sample >> 32);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2861,9 +2926,13 @@ static void drwav__ieee_to_s32(drwav_int32* pOut, const unsigned char* pIn, size
|
|||||||
if (bytesPerSample == 4) {
|
if (bytesPerSample == 4) {
|
||||||
drwav_f32_to_s32(pOut, (float*)pIn, totalSampleCount);
|
drwav_f32_to_s32(pOut, (float*)pIn, totalSampleCount);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else if (bytesPerSample == 8) {
|
||||||
drwav_f64_to_s32(pOut, (double*)pIn, totalSampleCount);
|
drwav_f64_to_s32(pOut, (double*)pIn, totalSampleCount);
|
||||||
return;
|
return;
|
||||||
|
} else {
|
||||||
|
// Only supporting 32- and 64-bit float. Output silence in all other cases. Contributions welcome for 16-bit float.
|
||||||
|
drwav_zero_memory(pOut, totalSampleCount * sizeof(*pOut));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2875,6 +2944,10 @@ drwav_uint64 drwav_read_s32__pcm(drwav* pWav, drwav_uint64 samplesToRead, drwav_
|
|||||||
return drwav_read(pWav, samplesToRead, pBufferOut);
|
return drwav_read(pWav, samplesToRead, pBufferOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pWav->bytesPerSample == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
drwav_uint64 totalSamplesRead = 0;
|
drwav_uint64 totalSamplesRead = 0;
|
||||||
unsigned char sampleData[4096];
|
unsigned char sampleData[4096];
|
||||||
while (samplesToRead > 0) {
|
while (samplesToRead > 0) {
|
||||||
@ -2939,6 +3012,10 @@ drwav_uint64 drwav_read_s32__ima(drwav* pWav, drwav_uint64 samplesToRead, drwav_
|
|||||||
|
|
||||||
drwav_uint64 drwav_read_s32__ieee(drwav* pWav, drwav_uint64 samplesToRead, drwav_int32* pBufferOut)
|
drwav_uint64 drwav_read_s32__ieee(drwav* pWav, drwav_uint64 samplesToRead, drwav_int32* pBufferOut)
|
||||||
{
|
{
|
||||||
|
if (pWav->bytesPerSample == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
drwav_uint64 totalSamplesRead = 0;
|
drwav_uint64 totalSamplesRead = 0;
|
||||||
unsigned char sampleData[4096];
|
unsigned char sampleData[4096];
|
||||||
while (samplesToRead > 0) {
|
while (samplesToRead > 0) {
|
||||||
@ -2959,6 +3036,10 @@ drwav_uint64 drwav_read_s32__ieee(drwav* pWav, drwav_uint64 samplesToRead, drwav
|
|||||||
|
|
||||||
drwav_uint64 drwav_read_s32__alaw(drwav* pWav, drwav_uint64 samplesToRead, drwav_int32* pBufferOut)
|
drwav_uint64 drwav_read_s32__alaw(drwav* pWav, drwav_uint64 samplesToRead, drwav_int32* pBufferOut)
|
||||||
{
|
{
|
||||||
|
if (pWav->bytesPerSample == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
drwav_uint64 totalSamplesRead = 0;
|
drwav_uint64 totalSamplesRead = 0;
|
||||||
unsigned char sampleData[4096];
|
unsigned char sampleData[4096];
|
||||||
while (samplesToRead > 0) {
|
while (samplesToRead > 0) {
|
||||||
@ -2979,6 +3060,10 @@ drwav_uint64 drwav_read_s32__alaw(drwav* pWav, drwav_uint64 samplesToRead, drwav
|
|||||||
|
|
||||||
drwav_uint64 drwav_read_s32__mulaw(drwav* pWav, drwav_uint64 samplesToRead, drwav_int32* pBufferOut)
|
drwav_uint64 drwav_read_s32__mulaw(drwav* pWav, drwav_uint64 samplesToRead, drwav_int32* pBufferOut)
|
||||||
{
|
{
|
||||||
|
if (pWav->bytesPerSample == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
drwav_uint64 totalSamplesRead = 0;
|
drwav_uint64 totalSamplesRead = 0;
|
||||||
unsigned char sampleData[4096];
|
unsigned char sampleData[4096];
|
||||||
while (samplesToRead > 0) {
|
while (samplesToRead > 0) {
|
||||||
@ -3354,6 +3439,25 @@ void drwav_free(void* pDataReturnedByOpenAndRead)
|
|||||||
|
|
||||||
// REVISION HISTORY
|
// REVISION HISTORY
|
||||||
//
|
//
|
||||||
|
// v0.7f - 2018-02-05
|
||||||
|
// - Restrict ADPCM formats to a maximum of 2 channels.
|
||||||
|
//
|
||||||
|
// v0.7e - 2018-02-02
|
||||||
|
// - Fix a crash.
|
||||||
|
//
|
||||||
|
// v0.7d - 2018-02-01
|
||||||
|
// - Fix a crash.
|
||||||
|
//
|
||||||
|
// v0.7c - 2018-02-01
|
||||||
|
// - Set drwav.bytesPerSample to 0 for all compressed formats.
|
||||||
|
// - Fix a crash when reading 16-bit floating point WAV files. In this case dr_wav will output silence for
|
||||||
|
// all format conversion reading APIs (*_s16, *_s32, *_f32 APIs).
|
||||||
|
// - Fix some divide-by-zero errors.
|
||||||
|
//
|
||||||
|
// v0.7b - 2018-01-22
|
||||||
|
// - Fix errors with seeking of compressed formats.
|
||||||
|
// - Fix compilation error when DR_WAV_NO_CONVERSION_API
|
||||||
|
//
|
||||||
// v0.7a - 2017-11-17
|
// v0.7a - 2017-11-17
|
||||||
// - Fix some GCC warnings.
|
// - Fix some GCC warnings.
|
||||||
//
|
//
|
||||||
@ -3393,7 +3497,7 @@ void drwav_free(void* pDataReturnedByOpenAndRead)
|
|||||||
//
|
//
|
||||||
// v0.5 - 2016-09-29
|
// v0.5 - 2016-09-29
|
||||||
// - API CHANGE. Swap the order of "channels" and "sampleRate" parameters in drwav_open_and_read*(). Rationale for this is to
|
// - API CHANGE. Swap the order of "channels" and "sampleRate" parameters in drwav_open_and_read*(). Rationale for this is to
|
||||||
// keep it consistent with dr_audio and drwav_flac.
|
// keep it consistent with dr_audio and dr_flac.
|
||||||
//
|
//
|
||||||
// v0.4b - 2016-09-18
|
// v0.4b - 2016-09-18
|
||||||
// - Fixed a typo in documentation.
|
// - Fixed a typo in documentation.
|
||||||
@ -3403,8 +3507,8 @@ void drwav_free(void* pDataReturnedByOpenAndRead)
|
|||||||
// - Change date format to ISO 8601 (YYYY-MM-DD)
|
// - Change date format to ISO 8601 (YYYY-MM-DD)
|
||||||
//
|
//
|
||||||
// v0.4 - 2016-07-13
|
// v0.4 - 2016-07-13
|
||||||
// - API CHANGE. Make onSeek consistent with drwav_flac.
|
// - API CHANGE. Make onSeek consistent with dr_flac.
|
||||||
// - API CHANGE. Rename drwav_seek() to drwav_seek_to_sample() for clarity and consistency with drwav_flac.
|
// - API CHANGE. Rename drwav_seek() to drwav_seek_to_sample() for clarity and consistency with dr_flac.
|
||||||
// - Added support for Sony Wave64.
|
// - Added support for Sony Wave64.
|
||||||
//
|
//
|
||||||
// v0.3a - 2016-05-28
|
// v0.3a - 2016-05-28
|
||||||
@ -3418,7 +3522,7 @@ void drwav_free(void* pDataReturnedByOpenAndRead)
|
|||||||
// - Fixed Linux/GCC build.
|
// - Fixed Linux/GCC build.
|
||||||
//
|
//
|
||||||
// v0.2 - 2016-05-11
|
// v0.2 - 2016-05-11
|
||||||
// - Added support for reading data as signed 32-bit PCM for consistency with drwav_flac.
|
// - Added support for reading data as signed 32-bit PCM for consistency with dr_flac.
|
||||||
//
|
//
|
||||||
// v0.1a - 2016-05-07
|
// v0.1a - 2016-05-07
|
||||||
// - Fixed a bug in drwav_open_file() where the file handle would not be closed if the loader failed to initialize.
|
// - Fixed a bug in drwav_open_file() where the file handle would not be closed if the loader failed to initialize.
|
||||||
|
16262
src/external/mini_al.h
vendored
16262
src/external/mini_al.h
vendored
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user