Commit 7ce6a5fb authored by David Reid's avatar David Reid

Add support for WAV files to the decoder API.

parent ec2ca9a3
...@@ -426,6 +426,8 @@ typedef mal_uint8 mal_channel; ...@@ -426,6 +426,8 @@ typedef mal_uint8 mal_channel;
#define MAL_CHANNEL_TOP_BACK_LEFT 16 #define MAL_CHANNEL_TOP_BACK_LEFT 16
#define MAL_CHANNEL_TOP_BACK_CENTER 17 #define MAL_CHANNEL_TOP_BACK_CENTER 17
#define MAL_CHANNEL_TOP_BACK_RIGHT 18 #define MAL_CHANNEL_TOP_BACK_RIGHT 18
#define MAL_CHANNEL_LEFT MAL_CHANNEL_FRONT_LEFT
#define MAL_CHANNEL_RIGHT MAL_CHANNEL_FRONT_RIGHT
#define MAL_CHANNEL_MONO MAL_CHANNEL_FRONT_CENTER #define MAL_CHANNEL_MONO MAL_CHANNEL_FRONT_CENTER
#define MAL_MAX_CHANNELS 18 #define MAL_MAX_CHANNELS 18
...@@ -1583,11 +1585,10 @@ struct mal_decoder ...@@ -1583,11 +1585,10 @@ struct mal_decoder
mal_uint32 outputChannels; mal_uint32 outputChannels;
mal_uint32 outputSampleRate; mal_uint32 outputSampleRate;
mal_channel outputChannelMap[MAL_MAX_CHANNELS]; mal_channel outputChannelMap[MAL_MAX_CHANNELS];
mal_dsp dsp; // <-- Format conversion is achieved by running samples through this. mal_dsp dsp; // <-- Format conversion is achieved by running frames through this.
mal_dsp_read_proc onReadFrames;
mal_decoder_seek_to_frame_proc onSeekToFrame; mal_decoder_seek_to_frame_proc onSeekToFrame;
mal_decoder_uninit_proc onUninit; mal_decoder_uninit_proc onUninit;
void* pInternalDecoder; // <-- The drwav/drflac/stb_vorbis/etc. objects.
struct struct
{ {
const mal_uint8* pData; const mal_uint8* pData;
...@@ -1596,6 +1597,8 @@ struct mal_decoder ...@@ -1596,6 +1597,8 @@ struct mal_decoder
} memory; // Only used for decoders that were opened against a block of memory. } memory; // Only used for decoders that were opened against a block of memory.
}; };
mal_decoder_config mal_decoder_config_init(mal_format outputFormat, mal_uint32 outputChannels, mal_uint32 outputSampleRate);
mal_result mal_decoder_init(mal_decoder_read_proc onRead, mal_decoder_seek_proc onSeek, void* pUserData, const mal_decoder_config* pConfig, mal_decoder* pDecoder); mal_result mal_decoder_init(mal_decoder_read_proc onRead, mal_decoder_seek_proc onSeek, void* pUserData, const mal_decoder_config* pConfig, mal_decoder* pDecoder);
mal_result mal_decoder_init_wav(mal_decoder_read_proc onRead, mal_decoder_seek_proc onSeek, void* pUserData, const mal_decoder_config* pConfig, mal_decoder* pDecoder); mal_result mal_decoder_init_wav(mal_decoder_read_proc onRead, mal_decoder_seek_proc onSeek, void* pUserData, const mal_decoder_config* pConfig, mal_decoder* pDecoder);
mal_result mal_decoder_init_flac(mal_decoder_read_proc onRead, mal_decoder_seek_proc onSeek, void* pUserData, const mal_decoder_config* pConfig, mal_decoder* pDecoder); mal_result mal_decoder_init_flac(mal_decoder_read_proc onRead, mal_decoder_seek_proc onSeek, void* pUserData, const mal_decoder_config* pConfig, mal_decoder* pDecoder);
...@@ -9058,11 +9061,14 @@ mal_bool32 mal__is_channel_map_valid(const mal_channel* channelMap, mal_uint32 c ...@@ -9058,11 +9061,14 @@ mal_bool32 mal__is_channel_map_valid(const mal_channel* channelMap, mal_uint32 c
{ {
mal_assert(channels > 0); mal_assert(channels > 0);
// A channel cannot be present in the channel map more than once. // A blank channel map should be allowed, in which case it should use an appropriate default which will depend on context.
for (mal_uint32 iChannel = 0; iChannel < channels; ++iChannel) { if (channelMap[0] != MAL_CHANNEL_NONE) {
for (mal_uint32 jChannel = iChannel + 1; jChannel < channels; ++jChannel) { // A channel cannot be present in the channel map more than once.
if (channelMap[iChannel] == channelMap[jChannel]) { for (mal_uint32 iChannel = 0; iChannel < channels; ++iChannel) {
return MAL_FALSE; for (mal_uint32 jChannel = iChannel + 1; jChannel < channels; ++jChannel) {
if (channelMap[iChannel] == channelMap[jChannel]) {
return MAL_FALSE;
}
} }
} }
} }
...@@ -10178,74 +10184,65 @@ mal_context_config mal_context_config_init(mal_log_proc onLog) ...@@ -10178,74 +10184,65 @@ mal_context_config mal_context_config_init(mal_log_proc onLog)
return config; return config;
} }
mal_device_config mal_device_config_init(mal_format format, mal_uint32 channels, mal_uint32 sampleRate, mal_recv_proc onRecvCallback, mal_send_proc onSendCallback) static void mal_get_default_device_config_channel_map(mal_uint32 channels, mal_uint8 channelMap[MAL_MAX_CHANNELS])
{ {
mal_device_config config;
mal_zero_object(&config);
config.format = format;
config.channels = channels;
config.sampleRate = sampleRate;
config.onRecvCallback = onRecvCallback;
config.onSendCallback = onSendCallback;
switch (channels) switch (channels)
{ {
case 1: case 1:
{ {
config.channelMap[0] = MAL_CHANNEL_FRONT_CENTER; channelMap[0] = MAL_CHANNEL_FRONT_CENTER;
} break; } break;
case 2: case 2:
{ {
config.channelMap[0] = MAL_CHANNEL_FRONT_LEFT; channelMap[0] = MAL_CHANNEL_FRONT_LEFT;
config.channelMap[1] = MAL_CHANNEL_FRONT_RIGHT; channelMap[1] = MAL_CHANNEL_FRONT_RIGHT;
} break; } break;
case 3: case 3:
{ {
config.channelMap[0] = MAL_CHANNEL_FRONT_LEFT; channelMap[0] = MAL_CHANNEL_FRONT_LEFT;
config.channelMap[1] = MAL_CHANNEL_FRONT_RIGHT; channelMap[1] = MAL_CHANNEL_FRONT_RIGHT;
config.channelMap[2] = MAL_CHANNEL_LFE; channelMap[2] = MAL_CHANNEL_LFE;
} break; } break;
case 4: case 4:
{ {
config.channelMap[0] = MAL_CHANNEL_FRONT_LEFT; channelMap[0] = MAL_CHANNEL_FRONT_LEFT;
config.channelMap[1] = MAL_CHANNEL_FRONT_RIGHT; channelMap[1] = MAL_CHANNEL_FRONT_RIGHT;
config.channelMap[2] = MAL_CHANNEL_BACK_LEFT; channelMap[2] = MAL_CHANNEL_BACK_LEFT;
config.channelMap[3] = MAL_CHANNEL_BACK_RIGHT; channelMap[3] = MAL_CHANNEL_BACK_RIGHT;
} break; } break;
case 5: case 5:
{ {
config.channelMap[0] = MAL_CHANNEL_FRONT_LEFT; channelMap[0] = MAL_CHANNEL_FRONT_LEFT;
config.channelMap[1] = MAL_CHANNEL_FRONT_RIGHT; channelMap[1] = MAL_CHANNEL_FRONT_RIGHT;
config.channelMap[2] = MAL_CHANNEL_BACK_LEFT; channelMap[2] = MAL_CHANNEL_BACK_LEFT;
config.channelMap[3] = MAL_CHANNEL_BACK_RIGHT; channelMap[3] = MAL_CHANNEL_BACK_RIGHT;
config.channelMap[4] = MAL_CHANNEL_LFE; channelMap[4] = MAL_CHANNEL_LFE;
} break; } break;
case 6: case 6:
{ {
config.channelMap[0] = MAL_CHANNEL_FRONT_LEFT; channelMap[0] = MAL_CHANNEL_FRONT_LEFT;
config.channelMap[1] = MAL_CHANNEL_FRONT_RIGHT; channelMap[1] = MAL_CHANNEL_FRONT_RIGHT;
config.channelMap[2] = MAL_CHANNEL_FRONT_CENTER; channelMap[2] = MAL_CHANNEL_FRONT_CENTER;
config.channelMap[3] = MAL_CHANNEL_LFE; channelMap[3] = MAL_CHANNEL_LFE;
config.channelMap[4] = MAL_CHANNEL_BACK_LEFT; channelMap[4] = MAL_CHANNEL_BACK_LEFT;
config.channelMap[5] = MAL_CHANNEL_BACK_RIGHT; channelMap[5] = MAL_CHANNEL_BACK_RIGHT;
} break; } break;
case 8: case 8:
{ {
config.channelMap[0] = MAL_CHANNEL_FRONT_LEFT; channelMap[0] = MAL_CHANNEL_FRONT_LEFT;
config.channelMap[1] = MAL_CHANNEL_FRONT_RIGHT; channelMap[1] = MAL_CHANNEL_FRONT_RIGHT;
config.channelMap[2] = MAL_CHANNEL_FRONT_CENTER; channelMap[2] = MAL_CHANNEL_FRONT_CENTER;
config.channelMap[3] = MAL_CHANNEL_LFE; channelMap[3] = MAL_CHANNEL_LFE;
config.channelMap[4] = MAL_CHANNEL_BACK_LEFT; channelMap[4] = MAL_CHANNEL_BACK_LEFT;
config.channelMap[5] = MAL_CHANNEL_BACK_RIGHT; channelMap[5] = MAL_CHANNEL_BACK_RIGHT;
config.channelMap[6] = MAL_CHANNEL_SIDE_LEFT; channelMap[6] = MAL_CHANNEL_SIDE_LEFT;
config.channelMap[7] = MAL_CHANNEL_SIDE_RIGHT; channelMap[7] = MAL_CHANNEL_SIDE_RIGHT;
} break; } break;
default: default:
...@@ -10253,6 +10250,19 @@ mal_device_config mal_device_config_init(mal_format format, mal_uint32 channels, ...@@ -10253,6 +10250,19 @@ mal_device_config mal_device_config_init(mal_format format, mal_uint32 channels,
// Just leave it all blank in this case. This will use the same mapping as the device's native mapping. // Just leave it all blank in this case. This will use the same mapping as the device's native mapping.
} break; } break;
} }
}
mal_device_config mal_device_config_init(mal_format format, mal_uint32 channels, mal_uint32 sampleRate, mal_recv_proc onRecvCallback, mal_send_proc onSendCallback)
{
mal_device_config config;
mal_zero_object(&config);
config.format = format;
config.channels = channels;
config.sampleRate = sampleRate;
config.onRecvCallback = onRecvCallback;
config.onSendCallback = onSendCallback;
mal_get_default_device_config_channel_map(channels, config.channelMap);
return config; return config;
} }
...@@ -11338,17 +11348,179 @@ void mal_blend_f32(float* pOut, float* pInA, float* pInB, float factor, mal_uint ...@@ -11338,17 +11348,179 @@ void mal_blend_f32(float* pOut, float* pInA, float* pInB, float factor, mal_uint
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#ifndef MAL_NO_DECODING #ifndef MAL_NO_DECODING
mal_decoder_config mal_decoder_config_init(mal_format outputFormat, mal_uint32 outputChannels, mal_uint32 outputSampleRate)
{
mal_decoder_config config;
mal_zero_object(&config);
config.outputFormat = outputFormat;
config.outputChannels = outputChannels;
config.outputSampleRate = outputSampleRate;
return config;
}
mal_decoder_config mal_decoder_config_init_copy(const mal_decoder_config* pConfig)
{
mal_decoder_config config;
if (pConfig != NULL) {
config = *pConfig;
} else {
mal_zero_object(&config);
}
return config;
}
// WAV // WAV
#ifdef dr_wav_h #ifdef dr_wav_h
#define MAL_HAS_WAV #define MAL_HAS_WAV
static size_t mal_decoder_internal_on_read__wav(void* pUserData, void* pBufferOut, size_t bytesToRead)
{
mal_decoder* pDecoder = (mal_decoder*)pUserData;
mal_assert(pDecoder != NULL);
mal_assert(pDecoder->onRead != NULL);
return pDecoder->onRead(pDecoder, pBufferOut, bytesToRead);
}
static drwav_bool32 mal_decoder_internal_on_seek__wav(void* pUserData, int offset, drwav_seek_origin origin)
{
mal_decoder* pDecoder = (mal_decoder*)pUserData;
mal_assert(pDecoder != NULL);
mal_assert(pDecoder->onSeek != NULL);
return pDecoder->onSeek(pDecoder, offset, (origin == drwav_seek_origin_start) ? mal_seek_origin_start : mal_seek_origin_current);
}
static mal_result mal_decoder_internal_on_seek_to_frame__wav(mal_decoder* pDecoder, mal_uint64 frameIndex)
{
drwav* pWav = (drwav*)pDecoder->pInternalDecoder;
mal_assert(pWav != NULL);
drwav_bool32 result = drwav_seek_to_sample(pWav, frameIndex*pWav->channels);
if (result) {
return MAL_SUCCESS;
} else {
return MAL_ERROR;
}
}
static mal_result mal_decoder_internal_on_uninit__wav(mal_decoder* pDecoder)
{
drwav_close((drwav*)pDecoder->pInternalDecoder);
return MAL_SUCCESS;
}
static mal_uint32 mal_decoder_internal_on_read_frames__wav(mal_dsp* pDSP, mal_uint32 frameCount, void* pSamplesOut, void* pUserData)
{
(void)pDSP;
mal_decoder* pDecoder = (mal_decoder*)pUserData;
mal_assert(pDecoder != NULL);
drwav* pWav = (drwav*)pDecoder->pInternalDecoder;
mal_assert(pWav != NULL);
switch (pDecoder->internalFormat) {
case mal_format_s16: return (mal_uint32)drwav_read_s16(pWav, frameCount*pDecoder->internalChannels, (drwav_int16*)pSamplesOut) / pDecoder->internalChannels;
case mal_format_s32: return (mal_uint32)drwav_read_s32(pWav, frameCount*pDecoder->internalChannels, (drwav_int32*)pSamplesOut) / pDecoder->internalChannels;
case mal_format_f32: return (mal_uint32)drwav_read_f32(pWav, frameCount*pDecoder->internalChannels, (float*)pSamplesOut) / pDecoder->internalChannels;
}
// Should never get here. If we do, it means the internal format was not set correctly at initialization time.
mal_assert(MAL_FALSE);
return 0;
}
mal_result mal_decoder_init_wav__internal(const mal_decoder_config* pConfig, mal_decoder* pDecoder) mal_result mal_decoder_init_wav__internal(const mal_decoder_config* pConfig, mal_decoder* pDecoder)
{ {
mal_assert(pConfig != NULL);
mal_assert(pDecoder != NULL); mal_assert(pDecoder != NULL);
(void)pConfig; // Try opening the decoder first.
(void)pDecoder; drwav* pWav = drwav_open(mal_decoder_internal_on_read__wav, mal_decoder_internal_on_seek__wav, pDecoder);
return MAL_ERROR; if (pWav == NULL) {
return MAL_ERROR;
}
// If we get here it means we successfully initialized the WAV decoder. We can now initialize the rest of the mal_decoder.
pDecoder->onSeekToFrame = mal_decoder_internal_on_seek_to_frame__wav;
pDecoder->onUninit = mal_decoder_internal_on_uninit__wav;
pDecoder->pInternalDecoder = pWav;
// Try to be as optimal as possible for the internal format. If mini_al does not support a format we will fall back to f32.
pDecoder->internalFormat = mal_format_unknown;
switch (pWav->translatedFormatTag) {
case DR_WAVE_FORMAT_PCM:
{
if (pWav->bitsPerSample == 8) {
pDecoder->internalFormat = mal_format_s16;
} else if (pWav->bitsPerSample == 16) {
pDecoder->internalFormat = mal_format_s16;
} else if (pWav->bitsPerSample == 32) {
pDecoder->internalFormat = mal_format_s32;
}
} break;
case DR_WAVE_FORMAT_IEEE_FLOAT:
{
if (pWav->bitsPerSample == 32) {
pDecoder->internalFormat = mal_format_f32;
}
} break;
case DR_WAVE_FORMAT_ALAW:
case DR_WAVE_FORMAT_MULAW:
case DR_WAVE_FORMAT_ADPCM:
case DR_WAVE_FORMAT_DVI_ADPCM:
{
pDecoder->internalFormat = mal_format_s16;
} break;
}
if (pDecoder->internalFormat == mal_format_unknown) {
pDecoder->internalFormat = mal_format_f32;
}
pDecoder->internalChannels = pWav->channels;
pDecoder->internalSampleRate = pWav->sampleRate;
mal_get_default_device_config_channel_map(pDecoder->internalChannels, pDecoder->internalChannelMap); // For WAV files we are currently making an assumption on the channel map.
// Output format.
if (pConfig->outputFormat == mal_format_unknown) {
pDecoder->outputFormat = pDecoder->internalFormat;
} else {
pDecoder->outputFormat = pConfig->outputFormat;
}
if (pConfig->outputChannels == 0) {
pDecoder->outputChannels = pDecoder->internalChannels;
} else {
pDecoder->outputChannels = pConfig->outputChannels;
}
if (pConfig->outputSampleRate == 0) {
pDecoder->outputSampleRate = pDecoder->internalSampleRate;
} else {
pDecoder->outputSampleRate = pConfig->outputSampleRate;
}
mal_copy_memory(pDecoder->outputChannelMap, pConfig->outputChannelMap, sizeof(pConfig->outputChannelMap));
// DSP.
mal_dsp_config dspConfig = mal_dsp_config_init(pDecoder->internalFormat, pDecoder->internalChannels, pDecoder->internalSampleRate, pDecoder->outputFormat, pDecoder->outputChannels, pDecoder->outputSampleRate);
mal_copy_memory(dspConfig.channelMapIn, pDecoder->internalChannelMap, sizeof(pDecoder->internalChannelMap));
mal_copy_memory(dspConfig.channelMapOut, pDecoder->outputChannelMap, sizeof(pDecoder->outputChannelMap));
mal_result result = mal_dsp_init(&dspConfig, mal_decoder_internal_on_read_frames__wav, pDecoder, &pDecoder->dsp);
if (result != MAL_SUCCESS) {
drwav_close(pWav);
return result;
}
return MAL_SUCCESS;
} }
#endif #endif
...@@ -11358,6 +11530,7 @@ mal_result mal_decoder_init_wav__internal(const mal_decoder_config* pConfig, mal ...@@ -11358,6 +11530,7 @@ mal_result mal_decoder_init_wav__internal(const mal_decoder_config* pConfig, mal
mal_result mal_decoder_init_flac__internal(const mal_decoder_config* pConfig, mal_decoder* pDecoder) mal_result mal_decoder_init_flac__internal(const mal_decoder_config* pConfig, mal_decoder* pDecoder)
{ {
mal_assert(pConfig != NULL);
mal_assert(pDecoder != NULL); mal_assert(pDecoder != NULL);
(void)pConfig; (void)pConfig;
...@@ -11372,6 +11545,7 @@ mal_result mal_decoder_init_flac__internal(const mal_decoder_config* pConfig, ma ...@@ -11372,6 +11545,7 @@ mal_result mal_decoder_init_flac__internal(const mal_decoder_config* pConfig, ma
mal_result mal_decoder_init_vorbis__internal(const mal_decoder_config* pConfig, mal_decoder* pDecoder) mal_result mal_decoder_init_vorbis__internal(const mal_decoder_config* pConfig, mal_decoder* pDecoder)
{ {
mal_assert(pConfig != NULL);
mal_assert(pDecoder != NULL); mal_assert(pDecoder != NULL);
(void)pConfig; (void)pConfig;
...@@ -11382,6 +11556,8 @@ mal_result mal_decoder_init_vorbis__internal(const mal_decoder_config* pConfig, ...@@ -11382,6 +11556,8 @@ mal_result mal_decoder_init_vorbis__internal(const mal_decoder_config* pConfig,
mal_result mal_decoder__preinit(mal_decoder_read_proc onRead, mal_decoder_seek_proc onSeek, void* pUserData, const mal_decoder_config* pConfig, mal_decoder* pDecoder) mal_result mal_decoder__preinit(mal_decoder_read_proc onRead, mal_decoder_seek_proc onSeek, void* pUserData, const mal_decoder_config* pConfig, mal_decoder* pDecoder)
{ {
mal_assert(pConfig != NULL);
if (pDecoder == NULL) return MAL_INVALID_ARGS; if (pDecoder == NULL) return MAL_INVALID_ARGS;
mal_zero_object(pDecoder); mal_zero_object(pDecoder);
...@@ -11399,13 +11575,15 @@ mal_result mal_decoder__preinit(mal_decoder_read_proc onRead, mal_decoder_seek_p ...@@ -11399,13 +11575,15 @@ mal_result mal_decoder__preinit(mal_decoder_read_proc onRead, mal_decoder_seek_p
mal_result mal_decoder_init_wav(mal_decoder_read_proc onRead, mal_decoder_seek_proc onSeek, void* pUserData, const mal_decoder_config* pConfig, mal_decoder* pDecoder) mal_result mal_decoder_init_wav(mal_decoder_read_proc onRead, mal_decoder_seek_proc onSeek, void* pUserData, const mal_decoder_config* pConfig, mal_decoder* pDecoder)
{ {
mal_result result = mal_decoder__preinit(onRead, onSeek, pUserData, pConfig, pDecoder); mal_decoder_config config = mal_decoder_config_init_copy(pConfig);
mal_result result = mal_decoder__preinit(onRead, onSeek, pUserData, &config, pDecoder);
if (result != MAL_SUCCESS) { if (result != MAL_SUCCESS) {
return result; return result;
} }
#ifdef MAL_HAS_WAV #ifdef MAL_HAS_WAV
return mal_decoder_init_wav__internal(pConfig, pDecoder); return mal_decoder_init_wav__internal(&config, pDecoder);
#else #else
return MAL_NO_BACKEND; return MAL_NO_BACKEND;
#endif #endif
...@@ -11413,7 +11591,9 @@ mal_result mal_decoder_init_wav(mal_decoder_read_proc onRead, mal_decoder_seek_p ...@@ -11413,7 +11591,9 @@ mal_result mal_decoder_init_wav(mal_decoder_read_proc onRead, mal_decoder_seek_p
mal_result mal_decoder_init_flac(mal_decoder_read_proc onRead, mal_decoder_seek_proc onSeek, void* pUserData, const mal_decoder_config* pConfig, mal_decoder* pDecoder) mal_result mal_decoder_init_flac(mal_decoder_read_proc onRead, mal_decoder_seek_proc onSeek, void* pUserData, const mal_decoder_config* pConfig, mal_decoder* pDecoder)
{ {
mal_result result = mal_decoder__preinit(onRead, onSeek, pUserData, pConfig, pDecoder); mal_decoder_config config = mal_decoder_config_init_copy(pConfig);
mal_result result = mal_decoder__preinit(onRead, onSeek, pUserData, &config, pDecoder);
if (result != MAL_SUCCESS) { if (result != MAL_SUCCESS) {
return result; return result;
} }
...@@ -11427,13 +11607,15 @@ mal_result mal_decoder_init_flac(mal_decoder_read_proc onRead, mal_decoder_seek_ ...@@ -11427,13 +11607,15 @@ mal_result mal_decoder_init_flac(mal_decoder_read_proc onRead, mal_decoder_seek_
mal_result mal_decoder_init_vorbis(mal_decoder_read_proc onRead, mal_decoder_seek_proc onSeek, void* pUserData, const mal_decoder_config* pConfig, mal_decoder* pDecoder) mal_result mal_decoder_init_vorbis(mal_decoder_read_proc onRead, mal_decoder_seek_proc onSeek, void* pUserData, const mal_decoder_config* pConfig, mal_decoder* pDecoder)
{ {
mal_result result = mal_decoder__preinit(onRead, onSeek, pUserData, pConfig, pDecoder); mal_decoder_config config = mal_decoder_config_init_copy(pConfig);
mal_result result = mal_decoder__preinit(onRead, onSeek, pUserData, &config, pDecoder);
if (result != MAL_SUCCESS) { if (result != MAL_SUCCESS) {
return result; return result;
} }
#ifdef MAL_HAS_VORBIS #ifdef MAL_HAS_VORBIS
return mal_decoder_init_vorbis__internal(pConfig, pDecoder); return mal_decoder_init_vorbis__internal(&config, pDecoder);
#else #else
return MAL_NO_BACKEND; return MAL_NO_BACKEND;
#endif #endif
...@@ -11441,7 +11623,9 @@ mal_result mal_decoder_init_vorbis(mal_decoder_read_proc onRead, mal_decoder_see ...@@ -11441,7 +11623,9 @@ mal_result mal_decoder_init_vorbis(mal_decoder_read_proc onRead, mal_decoder_see
mal_result mal_decoder_init(mal_decoder_read_proc onRead, mal_decoder_seek_proc onSeek, void* pUserData, const mal_decoder_config* pConfig, mal_decoder* pDecoder) mal_result mal_decoder_init(mal_decoder_read_proc onRead, mal_decoder_seek_proc onSeek, void* pUserData, const mal_decoder_config* pConfig, mal_decoder* pDecoder)
{ {
mal_result result = mal_decoder__preinit(onRead, onSeek, pUserData, pConfig, pDecoder); mal_decoder_config config = mal_decoder_config_init_copy(pConfig);
mal_result result = mal_decoder__preinit(onRead, onSeek, pUserData, &config, pDecoder);
if (result != MAL_SUCCESS) { if (result != MAL_SUCCESS) {
return result; return result;
} }
...@@ -11451,7 +11635,7 @@ mal_result mal_decoder_init(mal_decoder_read_proc onRead, mal_decoder_seek_proc ...@@ -11451,7 +11635,7 @@ mal_result mal_decoder_init(mal_decoder_read_proc onRead, mal_decoder_seek_proc
#ifdef MAL_HAS_WAV #ifdef MAL_HAS_WAV
if (result != MAL_SUCCESS) { if (result != MAL_SUCCESS) {
result = mal_decoder_init_wav__internal(pConfig, pDecoder); result = mal_decoder_init_wav__internal(&config, pDecoder);
if (result != MAL_SUCCESS) { if (result != MAL_SUCCESS) {
onSeek(pDecoder, 0, mal_seek_origin_start); onSeek(pDecoder, 0, mal_seek_origin_start);
} }
...@@ -11459,7 +11643,7 @@ mal_result mal_decoder_init(mal_decoder_read_proc onRead, mal_decoder_seek_proc ...@@ -11459,7 +11643,7 @@ mal_result mal_decoder_init(mal_decoder_read_proc onRead, mal_decoder_seek_proc
#endif #endif
#ifdef MAL_HAS_VORBIS #ifdef MAL_HAS_VORBIS
if (result != MAL_SUCCESS) { if (result != MAL_SUCCESS) {
result = mal_decoder_init_vorbis__internal(pConfig, pDecoder); result = mal_decoder_init_vorbis__internal(&config, pDecoder);
if (result != MAL_SUCCESS) { if (result != MAL_SUCCESS) {
onSeek(pDecoder, 0, mal_seek_origin_start); onSeek(pDecoder, 0, mal_seek_origin_start);
} }
...@@ -11467,7 +11651,7 @@ mal_result mal_decoder_init(mal_decoder_read_proc onRead, mal_decoder_seek_proc ...@@ -11467,7 +11651,7 @@ mal_result mal_decoder_init(mal_decoder_read_proc onRead, mal_decoder_seek_proc
#endif #endif
#ifdef MAL_HAS_FLAC #ifdef MAL_HAS_FLAC
if (result != MAL_SUCCESS) { if (result != MAL_SUCCESS) {
result = mal_decoder_init_flac__internal(pConfig, pDecoder); result = mal_decoder_init_flac__internal(&config, pDecoder);
if (result != MAL_SUCCESS) { if (result != MAL_SUCCESS) {
onSeek(pDecoder, 0, mal_seek_origin_start); onSeek(pDecoder, 0, mal_seek_origin_start);
} }
...@@ -12031,7 +12215,7 @@ void mal_pcm_f32_to_s32(int* pOut, const float* pIn, unsigned int count) ...@@ -12031,7 +12215,7 @@ void mal_pcm_f32_to_s32(int* pOut, const float* pIn, unsigned int count)
// ================ // ================
// //
// v0.xx - 2018-xx-xx // v0.xx - 2018-xx-xx
// - // - Add decoder APIs for loading WAV files.
// //
// v0.6c - 2018-02-12 // v0.6c - 2018-02-12
// - Fix build errors with BSD/OSS. // - Fix build errors with BSD/OSS.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment