Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
M
miniaudio
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Packages
Packages
List
Container Registry
Analytics
Analytics
CI / CD
Code Review
Insights
Issues
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
MyCard
miniaudio
Commits
e01b60a8
Commit
e01b60a8
authored
May 12, 2018
by
David Reid
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add support for decoding from raw PCM data.
parent
ecf34e45
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
329 additions
and
41 deletions
+329
-41
mini_al.h
mini_al.h
+329
-41
No files found.
mini_al.h
View file @
e01b60a8
...
@@ -640,6 +640,7 @@ typedef int mal_result;
...
@@ -640,6 +640,7 @@ typedef int mal_result;
#define MAL_FAILED_TO_CREATE_THREAD -28
#define MAL_FAILED_TO_CREATE_THREAD -28
#define MAL_INVALID_DEVICE_CONFIG -29
#define MAL_INVALID_DEVICE_CONFIG -29
#define MAL_ACCESS_DENIED -30
#define MAL_ACCESS_DENIED -30
#define MAL_TOO_LARGE -31
typedef void (* mal_log_proc) (mal_context* pContext, mal_device* pDevice, const char* message);
typedef void (* mal_log_proc) (mal_context* pContext, mal_device* pDevice, const char* message);
typedef void (* mal_recv_proc)(mal_device* pDevice, mal_uint32 frameCount, const void* pSamples);
typedef void (* mal_recv_proc)(mal_device* pDevice, mal_uint32 frameCount, const void* pSamples);
...
@@ -1914,7 +1915,7 @@ static MAL_INLINE mal_device_config mal_device_config_init_playback(mal_format f
...
@@ -1914,7 +1915,7 @@ static MAL_INLINE mal_device_config mal_device_config_init_playback(mal_format f
void mal_get_standard_channel_map(mal_standard_channel_map standardChannelMap, mal_uint32 channels, mal_channel channelMap[MAL_MAX_CHANNELS]);
void mal_get_standard_channel_map(mal_standard_channel_map standardChannelMap, mal_uint32 channels, mal_channel channelMap[MAL_MAX_CHANNELS]);
// Copies a channel map.
// Copies a channel map.
void
mal_channel_map_copy
(
mal_channel
*
pOut
,
mal_channel
*
pIn
,
mal_uint32
channels
);
void mal_channel_map_copy(mal_channel* pOut,
const
mal_channel* pIn, mal_uint32 channels);
// Determines whether or not a channel map is valid.
// Determines whether or not a channel map is valid.
...
@@ -2264,10 +2265,10 @@ typedef mal_result (* mal_decoder_uninit_proc) (mal_decoder* pDecoder);
...
@@ -2264,10 +2265,10 @@ typedef mal_result (* mal_decoder_uninit_proc) (mal_decoder* pDecoder);
typedef struct
typedef struct
{
{
mal_format
outputF
ormat
;
// Set to 0 or mal_format_unknown to use the stream's internal format.
mal_format
f
ormat; // Set to 0 or mal_format_unknown to use the stream's internal format.
mal_uint32
outputC
hannels
;
// Set to 0 to use the stream's internal channels.
mal_uint32
c
hannels; // Set to 0 to use the stream's internal channels.
mal_uint32
outputS
ampleRate
;
// Set to 0 to use the stream's internal sample rate.
mal_uint32
s
ampleRate; // Set to 0 to use the stream's internal sample rate.
mal_channel
outputC
hannelMap
[
MAL_MAX_CHANNELS
];
mal_channel
c
hannelMap[MAL_MAX_CHANNELS];
} mal_decoder_config;
} mal_decoder_config;
struct mal_decoder
struct mal_decoder
...
@@ -2302,12 +2303,14 @@ mal_result mal_decoder_init_wav(mal_decoder_read_proc onRead, mal_decoder_seek_p
...
@@ -2302,12 +2303,14 @@ 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 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 mal_decoder_init_mp3(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_mp3(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_raw(mal_decoder_read_proc onRead, mal_decoder_seek_proc onSeek, void* pUserData, const mal_decoder_config* pConfigIn, const mal_decoder_config* pConfigOut, mal_decoder* pDecoder);
mal_result mal_decoder_init_memory(const void* pData, size_t dataSize, const mal_decoder_config* pConfig, mal_decoder* pDecoder);
mal_result mal_decoder_init_memory(const void* pData, size_t dataSize, const mal_decoder_config* pConfig, mal_decoder* pDecoder);
mal_result mal_decoder_init_memory_wav(const void* pData, size_t dataSize, const mal_decoder_config* pConfig, mal_decoder* pDecoder);
mal_result mal_decoder_init_memory_wav(const void* pData, size_t dataSize, const mal_decoder_config* pConfig, mal_decoder* pDecoder);
mal_result mal_decoder_init_memory_flac(const void* pData, size_t dataSize, const mal_decoder_config* pConfig, mal_decoder* pDecoder);
mal_result mal_decoder_init_memory_flac(const void* pData, size_t dataSize, const mal_decoder_config* pConfig, mal_decoder* pDecoder);
mal_result mal_decoder_init_memory_vorbis(const void* pData, size_t dataSize, const mal_decoder_config* pConfig, mal_decoder* pDecoder);
mal_result mal_decoder_init_memory_vorbis(const void* pData, size_t dataSize, const mal_decoder_config* pConfig, mal_decoder* pDecoder);
mal_result mal_decoder_init_memory_mp3(const void* pData, size_t dataSize, const mal_decoder_config* pConfig, mal_decoder* pDecoder);
mal_result mal_decoder_init_memory_mp3(const void* pData, size_t dataSize, const mal_decoder_config* pConfig, mal_decoder* pDecoder);
mal_result mal_decoder_init_memory_raw(const void* pData, size_t dataSize, const mal_decoder_config* pConfigIn, const mal_decoder_config* pConfigOut, mal_decoder* pDecoder);
#ifndef MAL_NO_STDIO
#ifndef MAL_NO_STDIO
mal_result mal_decoder_init_file(const char* pFilePath, const mal_decoder_config* pConfig, mal_decoder* pDecoder);
mal_result mal_decoder_init_file(const char* pFilePath, const mal_decoder_config* pConfig, mal_decoder* pDecoder);
...
@@ -2319,6 +2322,14 @@ mal_result mal_decoder_uninit(mal_decoder* pDecoder);
...
@@ -2319,6 +2322,14 @@ mal_result mal_decoder_uninit(mal_decoder* pDecoder);
mal_uint64 mal_decoder_read(mal_decoder* pDecoder, mal_uint64 frameCount, void* pFramesOut);
mal_uint64 mal_decoder_read(mal_decoder* pDecoder, mal_uint64 frameCount, void* pFramesOut);
mal_result mal_decoder_seek_to_frame(mal_decoder* pDecoder, mal_uint64 frameIndex);
mal_result mal_decoder_seek_to_frame(mal_decoder* pDecoder, mal_uint64 frameIndex);
// Helper for opening and decoding a file into a heap allocated block of memory. Free the returned pointer with mal_free(). On input,
// pConfig should be set to what you want. On output it will be set to what you got.
#ifndef MAL_NO_STDIO
mal_result mal_decode_file(const char* pFilePath, mal_decoder_config* pConfig, mal_uint64* pFrameCountOut, void** ppDataOut);
#endif
mal_result mal_decode_memory(const void* pData, size_t dataSize, mal_decoder_config* pConfig, mal_uint64* pFrameCountOut, void** ppDataOut);
#endif // MAL_NO_DECODING
#endif // MAL_NO_DECODING
...
@@ -3134,6 +3145,19 @@ static MAL_INLINE float mal_mix_f32(float x, float y, float a)
...
@@ -3134,6 +3145,19 @@ static MAL_INLINE float mal_mix_f32(float x, float y, float a)
{
{
return x*(1-a) + y*a;
return x*(1-a) + y*a;
}
}
static MAL_INLINE float mal_mix_f32_fast(float x, float y, float a)
{
return x + (y - x)*a;
}
static MAL_INLINE double mal_mix_f64(double x, double y, double a)
{
return x*(1-a) + y*a;
}
static MAL_INLINE double mal_mix_f64_fast(double x, double y, double a)
{
return x + (y - x)*a;
}
static MAL_INLINE float mal_scale_to_range_f32(float x, float lo, float hi)
static MAL_INLINE float mal_scale_to_range_f32(float x, float lo, float hi)
{
{
...
@@ -16996,7 +17020,7 @@ void mal_get_standard_channel_map(mal_standard_channel_map standardChannelMap, m
...
@@ -16996,7 +17020,7 @@ void mal_get_standard_channel_map(mal_standard_channel_map standardChannelMap, m
}
}
}
}
void
mal_channel_map_copy
(
mal_channel
*
pOut
,
mal_channel
*
pIn
,
mal_uint32
channels
)
void mal_channel_map_copy(mal_channel* pOut,
const
mal_channel* pIn, mal_uint32 channels)
{
{
if (pOut != NULL && pIn != NULL && channels > 0) {
if (pOut != NULL && pIn != NULL && channels > 0) {
mal_copy_memory(pOut, pIn, sizeof(*pOut) * channels);
mal_copy_memory(pOut, pIn, sizeof(*pOut) * channels);
...
@@ -19970,7 +19994,7 @@ mal_uint32 mal_dsp__post_format_converter_on_read_deinterleaved(mal_format_conve
...
@@ -19970,7 +19994,7 @@ mal_uint32 mal_dsp__post_format_converter_on_read_deinterleaved(mal_format_conve
if (pDSP->isSRCRequired) {
if (pDSP->isSRCRequired) {
return (mal_uint32)mal_src_read_deinterleaved_ex(&pDSP->src, frameCount, ppSamplesOut, pData->flush, pUserData);
return (mal_uint32)mal_src_read_deinterleaved_ex(&pDSP->src, frameCount, ppSamplesOut, pData->flush, pUserData);
} else {
} else {
return
(
mal_uint32
)
mal_
format_converter_read_deinterleaved
(
&
pDSP
->
formatConverterIn
,
frameCount
,
ppSamplesOut
,
pUserData
);
return (mal_uint32)mal_
channel_router_read_deinterleaved(&pDSP->channelRouter
, frameCount, ppSamplesOut, pUserData);
}
}
}
}
}
}
...
@@ -20610,10 +20634,10 @@ mal_decoder_config mal_decoder_config_init(mal_format outputFormat, mal_uint32 o
...
@@ -20610,10 +20634,10 @@ mal_decoder_config mal_decoder_config_init(mal_format outputFormat, mal_uint32 o
{
{
mal_decoder_config config;
mal_decoder_config config;
mal_zero_object(&config);
mal_zero_object(&config);
config
.
outputF
ormat
=
outputFormat
;
config.
f
ormat = outputFormat;
config
.
outputC
hannels
=
outputChannels
;
config.
c
hannels = outputChannels;
config
.
outputS
ampleRate
=
outputSampleRate
;
config.
s
ampleRate = outputSampleRate;
mal_get_standard_channel_map
(
mal_standard_channel_map_default
,
config
.
outputChannels
,
config
.
outputC
hannelMap
);
mal_get_standard_channel_map(mal_standard_channel_map_default, config.
channels, config.c
hannelMap);
return config;
return config;
}
}
...
@@ -20635,28 +20659,28 @@ mal_result mal_decoder__init_dsp(mal_decoder* pDecoder, const mal_decoder_config
...
@@ -20635,28 +20659,28 @@ mal_result mal_decoder__init_dsp(mal_decoder* pDecoder, const mal_decoder_config
mal_assert(pDecoder != NULL);
mal_assert(pDecoder != NULL);
// Output format.
// Output format.
if
(
pConfig
->
outputF
ormat
==
mal_format_unknown
)
{
if (pConfig->
f
ormat == mal_format_unknown) {
pDecoder->outputFormat = pDecoder->internalFormat;
pDecoder->outputFormat = pDecoder->internalFormat;
} else {
} else {
pDecoder
->
outputFormat
=
pConfig
->
outputF
ormat
;
pDecoder->outputFormat = pConfig->
f
ormat;
}
}
if
(
pConfig
->
outputC
hannels
==
0
)
{
if (pConfig->
c
hannels == 0) {
pDecoder->outputChannels = pDecoder->internalChannels;
pDecoder->outputChannels = pDecoder->internalChannels;
} else {
} else {
pDecoder
->
outputChannels
=
pConfig
->
outputC
hannels
;
pDecoder->outputChannels = pConfig->
c
hannels;
}
}
if
(
pConfig
->
outputS
ampleRate
==
0
)
{
if (pConfig->
s
ampleRate == 0) {
pDecoder->outputSampleRate = pDecoder->internalSampleRate;
pDecoder->outputSampleRate = pDecoder->internalSampleRate;
} else {
} else {
pDecoder
->
outputSampleRate
=
pConfig
->
outputS
ampleRate
;
pDecoder->outputSampleRate = pConfig->
s
ampleRate;
}
}
if
(
mal_channel_map_blank
(
pDecoder
->
outputChannels
,
pConfig
->
outputC
hannelMap
))
{
if (mal_channel_map_blank(pDecoder->outputChannels, pConfig->
c
hannelMap)) {
mal_get_standard_channel_map(mal_standard_channel_map_default, pDecoder->outputChannels, pDecoder->outputChannelMap);
mal_get_standard_channel_map(mal_standard_channel_map_default, pDecoder->outputChannels, pDecoder->outputChannelMap);
} else {
} else {
mal_copy_memory
(
pDecoder
->
outputChannelMap
,
pConfig
->
outputChannelMap
,
sizeof
(
pConfig
->
outputC
hannelMap
));
mal_copy_memory(pDecoder->outputChannelMap, pConfig->
channelMap, sizeof(pConfig->c
hannelMap));
}
}
...
@@ -21237,7 +21261,7 @@ mal_result mal_decoder_init_mp3__internal(const mal_decoder_config* pConfig, mal
...
@@ -21237,7 +21261,7 @@ mal_result mal_decoder_init_mp3__internal(const mal_decoder_config* pConfig, mal
drmp3_config mp3Config;
drmp3_config mp3Config;
mal_zero_object(&mp3Config);
mal_zero_object(&mp3Config);
mp3Config.outputChannels = 2;
mp3Config.outputChannels = 2;
mp3Config
.
outputSampleRate
=
(
pConfig
->
outputSampleRate
!=
0
)
?
pConfig
->
outputS
ampleRate
:
44100
;
mp3Config.outputSampleRate = (pConfig->
sampleRate != 0) ? pConfig->s
ampleRate : 44100;
if (!drmp3_init(pMP3, mal_decoder_internal_on_read__mp3, mal_decoder_internal_on_seek__mp3, pDecoder, &mp3Config)) {
if (!drmp3_init(pMP3, mal_decoder_internal_on_read__mp3, mal_decoder_internal_on_seek__mp3, pDecoder, &mp3Config)) {
return MAL_ERROR;
return MAL_ERROR;
}
}
...
@@ -21263,6 +21287,92 @@ mal_result mal_decoder_init_mp3__internal(const mal_decoder_config* pConfig, mal
...
@@ -21263,6 +21287,92 @@ mal_result mal_decoder_init_mp3__internal(const mal_decoder_config* pConfig, mal
}
}
#endif
#endif
// Raw
mal_result mal_decoder_internal_on_seek_to_frame__raw(mal_decoder* pDecoder, mal_uint64 frameIndex)
{
mal_assert(pDecoder != NULL);
if (pDecoder->onSeek == NULL) {
return MAL_ERROR;
}
mal_bool32 result = MAL_FALSE;
// The callback uses a 32 bit integer whereas we use a 64 bit unsigned integer. We just need to continuously seek until we're at the correct position.
mal_uint64 totalBytesToSeek = frameIndex * mal_get_bytes_per_frame(pDecoder->internalFormat, pDecoder->internalChannels);
if (totalBytesToSeek < 0x7FFFFFFF) {
// Simple case.
result = pDecoder->onSeek(pDecoder, (int)(frameIndex * mal_get_bytes_per_frame(pDecoder->internalFormat, pDecoder->internalChannels)), mal_seek_origin_start);
} else {
// Complex case. Start by doing a seek relative to the start. Then keep looping using offset seeking.
result = pDecoder->onSeek(pDecoder, 0x7FFFFFFF, mal_seek_origin_start);
if (result == MAL_TRUE) {
totalBytesToSeek -= 0x7FFFFFFF;
while (totalBytesToSeek > 0) {
mal_uint64 bytesToSeekThisIteration = totalBytesToSeek;
if (bytesToSeekThisIteration > 0x7FFFFFFF) {
bytesToSeekThisIteration = 0x7FFFFFFF;
}
result = pDecoder->onSeek(pDecoder, (int)bytesToSeekThisIteration, mal_seek_origin_current);
if (result != MAL_TRUE) {
break;
}
totalBytesToSeek -= bytesToSeekThisIteration;
}
}
}
if (result) {
return MAL_SUCCESS;
} else {
return MAL_ERROR;
}
}
mal_result mal_decoder_internal_on_uninit__raw(mal_decoder* pDecoder)
{
(void)pDecoder;
return MAL_SUCCESS;
}
mal_uint32 mal_decoder_internal_on_read_frames__raw(mal_dsp* pDSP, mal_uint32 frameCount, void* pSamplesOut, void* pUserData)
{
(void)pDSP;
mal_decoder* pDecoder = (mal_decoder*)pUserData;
mal_assert(pDecoder != NULL);
// For raw decoding we just read directly from the decoder's callbacks.
mal_uint32 bpf = mal_get_bytes_per_frame(pDecoder->internalFormat, pDecoder->internalChannels);
return pDecoder->onRead(pDecoder, pSamplesOut, frameCount * bpf) / bpf;
}
mal_result mal_decoder_init_raw__internal(const mal_decoder_config* pConfigIn, const mal_decoder_config* pConfigOut, mal_decoder* pDecoder)
{
mal_assert(pConfigIn != NULL);
mal_assert(pConfigOut != NULL);
mal_assert(pDecoder != NULL);
pDecoder->onSeekToFrame = mal_decoder_internal_on_seek_to_frame__raw;
pDecoder->onUninit = mal_decoder_internal_on_uninit__raw;
// Internal format.
pDecoder->internalFormat = pConfigIn->format;
pDecoder->internalChannels = pConfigIn->channels;
pDecoder->internalSampleRate = pConfigIn->sampleRate;
mal_channel_map_copy(pDecoder->internalChannelMap, pConfigIn->channelMap, pConfigIn->channels);
mal_result result = mal_decoder__init_dsp(pDecoder, pConfigOut, mal_decoder_internal_on_read_frames__raw);
if (result != MAL_SUCCESS) {
return result;
}
return MAL_SUCCESS;
}
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);
mal_assert(pConfig != NULL);
...
@@ -21349,21 +21459,29 @@ mal_result mal_decoder_init_mp3(mal_decoder_read_proc onRead, mal_decoder_seek_p
...
@@ -21349,21 +21459,29 @@ mal_result mal_decoder_init_mp3(mal_decoder_read_proc onRead, mal_decoder_seek_p
#endif
#endif
}
}
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
_raw(mal_decoder_read_proc onRead, mal_decoder_seek_proc onSeek, void* pUserData, const mal_decoder_config* pConfigIn, const mal_decoder_config* pConfigOut
, mal_decoder* pDecoder)
{
{
mal_decoder_config
config
=
mal_decoder_config_init_copy
(
pConfig
);
mal_decoder_config config = mal_decoder_config_init_copy(pConfig
Out
);
mal_result result = mal_decoder__preinit(onRead, onSeek, pUserData, &config, pDecoder);
mal_result result = mal_decoder__preinit(onRead, onSeek, pUserData, &config, pDecoder);
if (result != MAL_SUCCESS) {
if (result != MAL_SUCCESS) {
return result;
return result;
}
}
return mal_decoder_init_raw__internal(pConfigIn, &config, pDecoder);
}
mal_result mal_decoder_init__internal(mal_decoder_read_proc onRead, mal_decoder_seek_proc onSeek, void* pUserData, const mal_decoder_config* pConfig, mal_decoder* pDecoder)
{
mal_assert(pConfig != NULL);
mal_assert(pDecoder != NULL);
// We use trial and error to open a decoder.
// We use trial and error to open a decoder.
result
=
MAL_NO_BACKEND
;
mal_result
result = MAL_NO_BACKEND;
#ifdef MAL_HAS_WAV
#ifdef MAL_HAS_WAV
if (result != MAL_SUCCESS) {
if (result != MAL_SUCCESS) {
result
=
mal_decoder_init_wav__internal
(
&
c
onfig
,
pDecoder
);
result = mal_decoder_init_wav__internal(
pC
onfig, pDecoder);
if (result != MAL_SUCCESS) {
if (result != MAL_SUCCESS) {
onSeek(pDecoder, 0, mal_seek_origin_start);
onSeek(pDecoder, 0, mal_seek_origin_start);
}
}
...
@@ -21371,7 +21489,7 @@ mal_result mal_decoder_init(mal_decoder_read_proc onRead, mal_decoder_seek_proc
...
@@ -21371,7 +21489,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
(
&
c
onfig
,
pDecoder
);
result = mal_decoder_init_flac__internal(
pC
onfig, pDecoder);
if (result != MAL_SUCCESS) {
if (result != MAL_SUCCESS) {
onSeek(pDecoder, 0, mal_seek_origin_start);
onSeek(pDecoder, 0, mal_seek_origin_start);
}
}
...
@@ -21379,7 +21497,7 @@ mal_result mal_decoder_init(mal_decoder_read_proc onRead, mal_decoder_seek_proc
...
@@ -21379,7 +21497,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
(
&
c
onfig
,
pDecoder
);
result = mal_decoder_init_vorbis__internal(
pC
onfig, pDecoder);
if (result != MAL_SUCCESS) {
if (result != MAL_SUCCESS) {
onSeek(pDecoder, 0, mal_seek_origin_start);
onSeek(pDecoder, 0, mal_seek_origin_start);
}
}
...
@@ -21387,7 +21505,7 @@ mal_result mal_decoder_init(mal_decoder_read_proc onRead, mal_decoder_seek_proc
...
@@ -21387,7 +21505,7 @@ mal_result mal_decoder_init(mal_decoder_read_proc onRead, mal_decoder_seek_proc
#endif
#endif
#ifdef MAL_HAS_MP3
#ifdef MAL_HAS_MP3
if (result != MAL_SUCCESS) {
if (result != MAL_SUCCESS) {
result
=
mal_decoder_init_mp3__internal
(
&
c
onfig
,
pDecoder
);
result = mal_decoder_init_mp3__internal(
pC
onfig, pDecoder);
if (result != MAL_SUCCESS) {
if (result != MAL_SUCCESS) {
onSeek(pDecoder, 0, mal_seek_origin_start);
onSeek(pDecoder, 0, mal_seek_origin_start);
}
}
...
@@ -21401,6 +21519,18 @@ mal_result mal_decoder_init(mal_decoder_read_proc onRead, mal_decoder_seek_proc
...
@@ -21401,6 +21519,18 @@ mal_result mal_decoder_init(mal_decoder_read_proc onRead, mal_decoder_seek_proc
return result;
return result;
}
}
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_decoder_config config = mal_decoder_config_init_copy(pConfig);
mal_result result = mal_decoder__preinit(onRead, onSeek, pUserData, &config, pDecoder);
if (result != MAL_SUCCESS) {
return result;
}
return mal_decoder_init__internal(onRead, onSeek, pUserData, &config, pDecoder);
}
size_t mal_decoder__on_read_memory(mal_decoder* pDecoder, void* pBufferOut, size_t bytesToRead)
size_t mal_decoder__on_read_memory(mal_decoder* pDecoder, void* pBufferOut, size_t bytesToRead)
{
{
...
@@ -21447,12 +21577,11 @@ mal_bool32 mal_decoder__on_seek_memory(mal_decoder* pDecoder, int byteOffset, ma
...
@@ -21447,12 +21577,11 @@ mal_bool32 mal_decoder__on_seek_memory(mal_decoder* pDecoder, int byteOffset, ma
mal_result mal_decoder__preinit_memory(const void* pData, size_t dataSize, const mal_decoder_config* pConfig, mal_decoder* pDecoder)
mal_result mal_decoder__preinit_memory(const void* pData, size_t dataSize, const mal_decoder_config* pConfig, mal_decoder* pDecoder)
{
{
if
(
pDecoder
==
NULL
)
{
mal_result result = mal_decoder__preinit(mal_decoder__on_read_memory, mal_decoder__on_seek_memory, NULL, pConfig, pDecoder);
return
MAL_INVALID_ARGS
;
if (result != MAL_SUCCESS) {
return result;
}
}
mal_zero_object
(
pDecoder
);
if (pData == NULL || dataSize == 0) {
if (pData == NULL || dataSize == 0) {
return MAL_INVALID_ARGS;
return MAL_INVALID_ARGS;
}
}
...
@@ -21467,52 +21596,90 @@ mal_result mal_decoder__preinit_memory(const void* pData, size_t dataSize, const
...
@@ -21467,52 +21596,90 @@ mal_result mal_decoder__preinit_memory(const void* pData, size_t dataSize, const
mal_result mal_decoder_init_memory(const void* pData, size_t dataSize, const mal_decoder_config* pConfig, mal_decoder* pDecoder)
mal_result mal_decoder_init_memory(const void* pData, size_t dataSize, const mal_decoder_config* pConfig, mal_decoder* pDecoder)
{
{
mal_result
result
=
mal_decoder__preinit_memory
(
pData
,
dataSize
,
pConfig
,
pDecoder
);
mal_decoder_config config = mal_decoder_config_init_copy(pConfig); // Make sure the config is not NULL.
mal_result result = mal_decoder__preinit_memory(pData, dataSize, &config, pDecoder);
if (result != MAL_SUCCESS) {
if (result != MAL_SUCCESS) {
return result;
return result;
}
}
return
mal_decoder_init
(
mal_decoder__on_read_memory
,
mal_decoder__on_seek_memory
,
NULL
,
pC
onfig
,
pDecoder
);
return mal_decoder_init
__internal(mal_decoder__on_read_memory, mal_decoder__on_seek_memory, NULL, &c
onfig, pDecoder);
}
}
mal_result mal_decoder_init_memory_wav(const void* pData, size_t dataSize, const mal_decoder_config* pConfig, mal_decoder* pDecoder)
mal_result mal_decoder_init_memory_wav(const void* pData, size_t dataSize, const mal_decoder_config* pConfig, mal_decoder* pDecoder)
{
{
mal_result
result
=
mal_decoder__preinit_memory
(
pData
,
dataSize
,
pConfig
,
pDecoder
);
mal_decoder_config config = mal_decoder_config_init_copy(pConfig); // Make sure the config is not NULL.
mal_result result = mal_decoder__preinit_memory(pData, dataSize, &config, pDecoder);
if (result != MAL_SUCCESS) {
if (result != MAL_SUCCESS) {
return result;
return result;
}
}
return
mal_decoder_init_wav
(
mal_decoder__on_read_memory
,
mal_decoder__on_seek_memory
,
NULL
,
pConfig
,
pDecoder
);
#ifdef MAL_HAS_WAV
return mal_decoder_init_wav__internal(&config, pDecoder);
#else
return MAL_NO_BACKEND;
#endif
}
}
mal_result mal_decoder_init_memory_flac(const void* pData, size_t dataSize, const mal_decoder_config* pConfig, mal_decoder* pDecoder)
mal_result mal_decoder_init_memory_flac(const void* pData, size_t dataSize, const mal_decoder_config* pConfig, mal_decoder* pDecoder)
{
{
mal_result
result
=
mal_decoder__preinit_memory
(
pData
,
dataSize
,
pConfig
,
pDecoder
);
mal_decoder_config config = mal_decoder_config_init_copy(pConfig); // Make sure the config is not NULL.
mal_result result = mal_decoder__preinit_memory(pData, dataSize, &config, pDecoder);
if (result != MAL_SUCCESS) {
if (result != MAL_SUCCESS) {
return result;
return result;
}
}
return
mal_decoder_init_flac
(
mal_decoder__on_read_memory
,
mal_decoder__on_seek_memory
,
NULL
,
pConfig
,
pDecoder
);
#ifdef MAL_HAS_FLAC
return mal_decoder_init_flac__internal(&config, pDecoder);
#else
return MAL_NO_BACKEND;
#endif
}
}
mal_result mal_decoder_init_memory_vorbis(const void* pData, size_t dataSize, const mal_decoder_config* pConfig, mal_decoder* pDecoder)
mal_result mal_decoder_init_memory_vorbis(const void* pData, size_t dataSize, const mal_decoder_config* pConfig, mal_decoder* pDecoder)
{
{
mal_result
result
=
mal_decoder__preinit_memory
(
pData
,
dataSize
,
pConfig
,
pDecoder
);
mal_decoder_config config = mal_decoder_config_init_copy(pConfig); // Make sure the config is not NULL.
mal_result result = mal_decoder__preinit_memory(pData, dataSize, &config, pDecoder);
if (result != MAL_SUCCESS) {
if (result != MAL_SUCCESS) {
return result;
return result;
}
}
return
mal_decoder_init_vorbis
(
mal_decoder__on_read_memory
,
mal_decoder__on_seek_memory
,
NULL
,
pConfig
,
pDecoder
);
#ifdef MAL_HAS_VORBIS
return mal_decoder_init_vorbis__internal(&config, pDecoder);
#else
return MAL_NO_BACKEND;
#endif
}
}
mal_result mal_decoder_init_memory_mp3(const void* pData, size_t dataSize, const mal_decoder_config* pConfig, mal_decoder* pDecoder)
mal_result mal_decoder_init_memory_mp3(const void* pData, size_t dataSize, const mal_decoder_config* pConfig, mal_decoder* pDecoder)
{
{
mal_result
result
=
mal_decoder__preinit_memory
(
pData
,
dataSize
,
pConfig
,
pDecoder
);
mal_decoder_config config = mal_decoder_config_init_copy(pConfig); // Make sure the config is not NULL.
mal_result result = mal_decoder__preinit_memory(pData, dataSize, &config, pDecoder);
if (result != MAL_SUCCESS) {
if (result != MAL_SUCCESS) {
return result;
return result;
}
}
return
mal_decoder_init_mp3
(
mal_decoder__on_read_memory
,
mal_decoder__on_seek_memory
,
NULL
,
pConfig
,
pDecoder
);
#ifdef MAL_HAS_MP3
return mal_decoder_init_mp3__internal(&config, pDecoder);
#else
return MAL_NO_BACKEND;
#endif
}
mal_result mal_decoder_init_memory_raw(const void* pData, size_t dataSize, const mal_decoder_config* pConfigIn, const mal_decoder_config* pConfigOut, mal_decoder* pDecoder)
{
mal_decoder_config config = mal_decoder_config_init_copy(pConfigOut); // Make sure the config is not NULL.
mal_result result = mal_decoder__preinit_memory(pData, dataSize, &config, pDecoder);
if (result != MAL_SUCCESS) {
return result;
}
return mal_decoder_init_raw__internal(pConfigIn, &config, pDecoder);
}
}
#ifndef MAL_NO_STDIO
#ifndef MAL_NO_STDIO
...
@@ -21745,6 +21912,125 @@ mal_result mal_decoder_seek_to_frame(mal_decoder* pDecoder, mal_uint64 frameInde
...
@@ -21745,6 +21912,125 @@ mal_result mal_decoder_seek_to_frame(mal_decoder* pDecoder, mal_uint64 frameInde
// Should never get here, but if we do it means onSeekToFrame was not set by the backend.
// Should never get here, but if we do it means onSeekToFrame was not set by the backend.
return MAL_INVALID_ARGS;
return MAL_INVALID_ARGS;
}
}
mal_result mal_decoder__full_decode_and_uninit(mal_decoder* pDecoder, mal_decoder_config* pConfigOut, mal_uint64* pFrameCountOut, void** ppDataOut)
{
mal_assert(pDecoder != NULL);
mal_uint64 totalFrameCount = 0;
mal_uint64 bpf = mal_get_bytes_per_frame(pDecoder->outputFormat, pDecoder->outputChannels);
// The frame count is unknown until we try reading. Thus, we just run in a loop.
mal_uint64 dataCapInFrames = 0;
void* pDataOut = NULL;
for (;;) {
// Make room if there's not enough.
if (totalFrameCount == dataCapInFrames) {
mal_uint64 newDataCapInFrames = dataCapInFrames*2;
if (newDataCapInFrames == 0) {
newDataCapInFrames = 4096;
}
if ((newDataCapInFrames * bpf) > SIZE_MAX) {
mal_free(pDataOut);
return MAL_TOO_LARGE;
}
void* pNewDataOut = (void*)mal_realloc(pDataOut, (size_t)(newDataCapInFrames * bpf));
if (pNewDataOut == NULL) {
mal_free(pDataOut);
return MAL_OUT_OF_MEMORY;
}
dataCapInFrames = newDataCapInFrames;
pDataOut = pNewDataOut;
}
mal_uint64 frameCountToTryReading = dataCapInFrames - totalFrameCount;
mal_assert(frameCountToTryReading > 0);
mal_uint64 framesJustRead = mal_decoder_read(pDecoder, frameCountToTryReading, (mal_uint8*)pDataOut + (totalFrameCount * bpf));
totalFrameCount += framesJustRead;
if (framesJustRead < frameCountToTryReading) {
break;
}
}
if (pConfigOut != NULL) {
pConfigOut->format = pDecoder->outputFormat;
pConfigOut->channels = pDecoder->outputChannels;
pConfigOut->sampleRate = pDecoder->outputSampleRate;
mal_channel_map_copy(pConfigOut->channelMap, pDecoder->outputChannelMap, pDecoder->outputChannels);
}
if (ppDataOut != NULL) {
*ppDataOut = pDataOut;
} else {
mal_free(pDataOut);
}
if (pFrameCountOut != NULL) {
*pFrameCountOut = totalFrameCount;
}
mal_decoder_uninit(pDecoder);
return MAL_SUCCESS;
}
#ifndef MAL_NO_STDIO
mal_result mal_decode_file(const char* pFilePath, mal_decoder_config* pConfig, mal_uint64* pFrameCountOut, void** ppDataOut)
{
if (pFrameCountOut != NULL) {
*pFrameCountOut = 0;
}
if (ppDataOut != NULL) {
*ppDataOut = NULL;
}
if (pFilePath == NULL) {
return MAL_INVALID_ARGS;
}
mal_decoder_config config = mal_decoder_config_init_copy(pConfig);
mal_decoder decoder;
mal_result result = mal_decoder_init_file(pFilePath, &config, &decoder);
if (result != MAL_SUCCESS) {
return result;
}
return mal_decoder__full_decode_and_uninit(&decoder, pConfig, pFrameCountOut, ppDataOut);
}
#endif
mal_result mal_decode_memory(const void* pData, size_t dataSize, mal_decoder_config* pConfig, mal_uint64* pFrameCountOut, void** ppDataOut)
{
if (pFrameCountOut != NULL) {
*pFrameCountOut = 0;
}
if (ppDataOut != NULL) {
*ppDataOut = NULL;
}
if (pData == NULL || dataSize == 0) {
return MAL_INVALID_ARGS;
}
mal_decoder_config config = mal_decoder_config_init_copy(pConfig);
mal_decoder decoder;
mal_result result = mal_decoder_init_memory(pData, dataSize, &config, &decoder);
if (result != MAL_SUCCESS) {
return result;
}
return mal_decoder__full_decode_and_uninit(&decoder, pConfig, pFrameCountOut, ppDataOut);
}
#endif // MAL_NO_DECODING
#endif // MAL_NO_DECODING
...
@@ -21848,6 +22134,8 @@ mal_uint64 mal_sine_wave_read(mal_sine_wave* pSineWave, mal_uint64 count, float*
...
@@ -21848,6 +22134,8 @@ mal_uint64 mal_sine_wave_read(mal_sine_wave* pSineWave, mal_uint64 count, float*
// - Make some APIs more const-correct.
// - Make some APIs more const-correct.
// - Fix errors with OpenAL detection.
// - Fix errors with OpenAL detection.
// - Fix some memory leaks.
// - Fix some memory leaks.
// - Fix a bug with opening decoders from memory.
// - Add support for decoding from raw PCM data (mal_decoder_init_raw(), etc.)
// - Miscellaneous bug fixes.
// - Miscellaneous bug fixes.
// - Documentation updates.
// - Documentation updates.
//
//
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment