mirror of
https://github.com/mackron/miniaudio.git
synced 2026-04-22 00:06:59 +02:00
API CHANGE: Remove ma_format_converter.
Use the following APIs as alternatives: * ma_pcm_*_to_*() * ma_pcm_convert() * ma_convert_pcm_frames()
This commit is contained in:
+22
-908
@@ -1411,41 +1411,6 @@ ma_uint64 ma_data_converter_get_output_latency(ma_data_converter* pConverter);
|
||||
|
||||
|
||||
|
||||
typedef struct ma_format_converter ma_format_converter;
|
||||
typedef ma_uint32 (* ma_format_converter_read_proc) (ma_format_converter* pConverter, ma_uint32 frameCount, void* pFramesOut, void* pUserData);
|
||||
typedef ma_uint32 (* ma_format_converter_read_deinterleaved_proc)(ma_format_converter* pConverter, ma_uint32 frameCount, void** ppSamplesOut, void* pUserData);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ma_format formatIn;
|
||||
ma_format formatOut;
|
||||
ma_uint32 channels;
|
||||
ma_stream_format streamFormatIn;
|
||||
ma_stream_format streamFormatOut;
|
||||
ma_dither_mode ditherMode;
|
||||
ma_bool32 noSSE2 : 1;
|
||||
ma_bool32 noAVX2 : 1;
|
||||
ma_bool32 noAVX512 : 1;
|
||||
ma_bool32 noNEON : 1;
|
||||
ma_format_converter_read_proc onRead;
|
||||
ma_format_converter_read_deinterleaved_proc onReadDeinterleaved;
|
||||
void* pUserData;
|
||||
} ma_format_converter_config;
|
||||
|
||||
struct ma_format_converter
|
||||
{
|
||||
ma_format_converter_config config;
|
||||
ma_bool32 useSSE2 : 1;
|
||||
ma_bool32 useAVX2 : 1;
|
||||
ma_bool32 useAVX512 : 1;
|
||||
ma_bool32 useNEON : 1;
|
||||
void (* onConvertPCM)(void* dst, const void* src, ma_uint64 count, ma_dither_mode ditherMode);
|
||||
void (* onInterleavePCM)(void* dst, const void** src, ma_uint64 frameCount, ma_uint32 channels);
|
||||
void (* onDeinterleavePCM)(void** dst, const void* src, ma_uint64 frameCount, ma_uint32 channels);
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/************************************************************************************************************************************************************
|
||||
*************************************************************************************************************************************************************
|
||||
@@ -1560,68 +1525,6 @@ Helper for determining whether or not a channel is present in the given channel
|
||||
ma_bool32 ma_channel_map_contains_channel_position(ma_uint32 channels, const ma_channel channelMap[MA_MAX_CHANNELS], ma_channel channelPosition);
|
||||
|
||||
|
||||
/************************************************************************************************************************************************************
|
||||
|
||||
Format Conversion
|
||||
=================
|
||||
The format converter serves two purposes:
|
||||
1) Conversion between data formats (u8 to f32, etc.)
|
||||
2) Interleaving and deinterleaving
|
||||
|
||||
When initializing a converter, you specify the input and output formats (u8, s16, etc.) and read callbacks. There are two read callbacks - one for
|
||||
interleaved input data (onRead) and another for deinterleaved input data (onReadDeinterleaved). You implement whichever is most convenient for you. You
|
||||
can implement both, but it's not recommended as it just introduces unnecessary complexity.
|
||||
|
||||
To read data as interleaved samples, use ma_format_converter_read(). Otherwise use ma_format_converter_read_deinterleaved().
|
||||
|
||||
Dithering
|
||||
---------
|
||||
The format converter also supports dithering. Dithering can be set using ditherMode variable in the config, like so.
|
||||
|
||||
pConfig->ditherMode = ma_dither_mode_rectangle;
|
||||
|
||||
The different dithering modes include the following, in order of efficiency:
|
||||
- None: ma_dither_mode_none
|
||||
- Rectangle: ma_dither_mode_rectangle
|
||||
- Triangle: ma_dither_mode_triangle
|
||||
|
||||
Note that even if the dither mode is set to something other than ma_dither_mode_none, it will be ignored for conversions where dithering is not needed.
|
||||
Dithering is available for the following conversions:
|
||||
- s16 -> u8
|
||||
- s24 -> u8
|
||||
- s32 -> u8
|
||||
- f32 -> u8
|
||||
- s24 -> s16
|
||||
- s32 -> s16
|
||||
- f32 -> s16
|
||||
|
||||
Note that it is not an error to pass something other than ma_dither_mode_none for conversions where dither is not used. It will just be ignored.
|
||||
|
||||
************************************************************************************************************************************************************/
|
||||
|
||||
/*
|
||||
Initializes a format converter.
|
||||
*/
|
||||
ma_result ma_format_converter_init(const ma_format_converter_config* pConfig, ma_format_converter* pConverter);
|
||||
|
||||
/*
|
||||
Reads data from the format converter as interleaved channels.
|
||||
*/
|
||||
ma_uint64 ma_format_converter_read(ma_format_converter* pConverter, ma_uint64 frameCount, void* pFramesOut, void* pUserData);
|
||||
|
||||
/*
|
||||
Reads data from the format converter as deinterleaved channels.
|
||||
*/
|
||||
ma_uint64 ma_format_converter_read_deinterleaved(ma_format_converter* pConverter, ma_uint64 frameCount, void** ppSamplesOut, void* pUserData);
|
||||
|
||||
/*
|
||||
Helper for initializing a format converter config.
|
||||
*/
|
||||
ma_format_converter_config ma_format_converter_config_init_new(void);
|
||||
ma_format_converter_config ma_format_converter_config_init(ma_format formatIn, ma_format formatOut, ma_uint32 channels, ma_format_converter_read_proc onRead, void* pUserData);
|
||||
ma_format_converter_config ma_format_converter_config_init_deinterleaved(ma_format formatIn, ma_format formatOut, ma_uint32 channels, ma_format_converter_read_deinterleaved_proc onReadDeinterleaved, void* pUserData);
|
||||
|
||||
|
||||
/************************************************************************************************************************************************************
|
||||
|
||||
Conversion
|
||||
@@ -1813,6 +1716,28 @@ const char* ma_log_level_to_string(ma_uint32 logLevel);
|
||||
/************************************************************************************************************************************************************
|
||||
|
||||
Format Conversion
|
||||
=================
|
||||
|
||||
Dithering
|
||||
---------
|
||||
Dithering can be set using ditherMode parmater.
|
||||
|
||||
The different dithering modes include the following, in order of efficiency:
|
||||
- None: ma_dither_mode_none
|
||||
- Rectangle: ma_dither_mode_rectangle
|
||||
- Triangle: ma_dither_mode_triangle
|
||||
|
||||
Note that even if the dither mode is set to something other than ma_dither_mode_none, it will be ignored for conversions where dithering is not needed.
|
||||
Dithering is available for the following conversions:
|
||||
- s16 -> u8
|
||||
- s24 -> u8
|
||||
- s32 -> u8
|
||||
- f32 -> u8
|
||||
- s24 -> s16
|
||||
- s32 -> s16
|
||||
- f32 -> s16
|
||||
|
||||
Note that it is not an error to pass something other than ma_dither_mode_none for conversions where dither is not used. It will just be ignored.
|
||||
|
||||
************************************************************************************************************************************************************/
|
||||
void ma_pcm_u8_to_s16(void* pOut, const void* pIn, ma_uint64 count, ma_dither_mode ditherMode);
|
||||
@@ -33223,817 +33148,6 @@ void ma_pcm_deinterleave_f32(void** dst, const void* src, ma_uint64 frameCount,
|
||||
}
|
||||
|
||||
|
||||
void ma_format_converter_init_callbacks__default(ma_format_converter* pConverter)
|
||||
{
|
||||
ma_assert(pConverter != NULL);
|
||||
|
||||
switch (pConverter->config.formatIn)
|
||||
{
|
||||
case ma_format_u8:
|
||||
{
|
||||
if (pConverter->config.formatOut == ma_format_u8) {
|
||||
pConverter->onConvertPCM = ma_pcm_u8_to_u8;
|
||||
} else if (pConverter->config.formatOut == ma_format_s16) {
|
||||
pConverter->onConvertPCM = ma_pcm_u8_to_s16;
|
||||
} else if (pConverter->config.formatOut == ma_format_s24) {
|
||||
pConverter->onConvertPCM = ma_pcm_u8_to_s24;
|
||||
} else if (pConverter->config.formatOut == ma_format_s32) {
|
||||
pConverter->onConvertPCM = ma_pcm_u8_to_s32;
|
||||
} else if (pConverter->config.formatOut == ma_format_f32) {
|
||||
pConverter->onConvertPCM = ma_pcm_u8_to_f32;
|
||||
}
|
||||
} break;
|
||||
|
||||
case ma_format_s16:
|
||||
{
|
||||
if (pConverter->config.formatOut == ma_format_u8) {
|
||||
pConverter->onConvertPCM = ma_pcm_s16_to_u8;
|
||||
} else if (pConverter->config.formatOut == ma_format_s16) {
|
||||
pConverter->onConvertPCM = ma_pcm_s16_to_s16;
|
||||
} else if (pConverter->config.formatOut == ma_format_s24) {
|
||||
pConverter->onConvertPCM = ma_pcm_s16_to_s24;
|
||||
} else if (pConverter->config.formatOut == ma_format_s32) {
|
||||
pConverter->onConvertPCM = ma_pcm_s16_to_s32;
|
||||
} else if (pConverter->config.formatOut == ma_format_f32) {
|
||||
pConverter->onConvertPCM = ma_pcm_s16_to_f32;
|
||||
}
|
||||
} break;
|
||||
|
||||
case ma_format_s24:
|
||||
{
|
||||
if (pConverter->config.formatOut == ma_format_u8) {
|
||||
pConverter->onConvertPCM = ma_pcm_s24_to_u8;
|
||||
} else if (pConverter->config.formatOut == ma_format_s16) {
|
||||
pConverter->onConvertPCM = ma_pcm_s24_to_s16;
|
||||
} else if (pConverter->config.formatOut == ma_format_s24) {
|
||||
pConverter->onConvertPCM = ma_pcm_s24_to_s24;
|
||||
} else if (pConverter->config.formatOut == ma_format_s32) {
|
||||
pConverter->onConvertPCM = ma_pcm_s24_to_s32;
|
||||
} else if (pConverter->config.formatOut == ma_format_f32) {
|
||||
pConverter->onConvertPCM = ma_pcm_s24_to_f32;
|
||||
}
|
||||
} break;
|
||||
|
||||
case ma_format_s32:
|
||||
{
|
||||
if (pConverter->config.formatOut == ma_format_u8) {
|
||||
pConverter->onConvertPCM = ma_pcm_s32_to_u8;
|
||||
} else if (pConverter->config.formatOut == ma_format_s16) {
|
||||
pConverter->onConvertPCM = ma_pcm_s32_to_s16;
|
||||
} else if (pConverter->config.formatOut == ma_format_s24) {
|
||||
pConverter->onConvertPCM = ma_pcm_s32_to_s24;
|
||||
} else if (pConverter->config.formatOut == ma_format_s32) {
|
||||
pConverter->onConvertPCM = ma_pcm_s32_to_s32;
|
||||
} else if (pConverter->config.formatOut == ma_format_f32) {
|
||||
pConverter->onConvertPCM = ma_pcm_s32_to_f32;
|
||||
}
|
||||
} break;
|
||||
|
||||
case ma_format_f32:
|
||||
default:
|
||||
{
|
||||
if (pConverter->config.formatOut == ma_format_u8) {
|
||||
pConverter->onConvertPCM = ma_pcm_f32_to_u8;
|
||||
} else if (pConverter->config.formatOut == ma_format_s16) {
|
||||
pConverter->onConvertPCM = ma_pcm_f32_to_s16;
|
||||
} else if (pConverter->config.formatOut == ma_format_s24) {
|
||||
pConverter->onConvertPCM = ma_pcm_f32_to_s24;
|
||||
} else if (pConverter->config.formatOut == ma_format_s32) {
|
||||
pConverter->onConvertPCM = ma_pcm_f32_to_s32;
|
||||
} else if (pConverter->config.formatOut == ma_format_f32) {
|
||||
pConverter->onConvertPCM = ma_pcm_f32_to_f32;
|
||||
}
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(MA_SUPPORT_SSE2)
|
||||
void ma_format_converter_init_callbacks__sse2(ma_format_converter* pConverter)
|
||||
{
|
||||
ma_assert(pConverter != NULL);
|
||||
|
||||
switch (pConverter->config.formatIn)
|
||||
{
|
||||
case ma_format_u8:
|
||||
{
|
||||
if (pConverter->config.formatOut == ma_format_u8) {
|
||||
pConverter->onConvertPCM = ma_pcm_u8_to_u8;
|
||||
} else if (pConverter->config.formatOut == ma_format_s16) {
|
||||
pConverter->onConvertPCM = ma_pcm_u8_to_s16__sse2;
|
||||
} else if (pConverter->config.formatOut == ma_format_s24) {
|
||||
pConverter->onConvertPCM = ma_pcm_u8_to_s24__sse2;
|
||||
} else if (pConverter->config.formatOut == ma_format_s32) {
|
||||
pConverter->onConvertPCM = ma_pcm_u8_to_s32__sse2;
|
||||
} else if (pConverter->config.formatOut == ma_format_f32) {
|
||||
pConverter->onConvertPCM = ma_pcm_u8_to_f32__sse2;
|
||||
}
|
||||
} break;
|
||||
|
||||
case ma_format_s16:
|
||||
{
|
||||
if (pConverter->config.formatOut == ma_format_u8) {
|
||||
pConverter->onConvertPCM = ma_pcm_s16_to_u8__sse2;
|
||||
} else if (pConverter->config.formatOut == ma_format_s16) {
|
||||
pConverter->onConvertPCM = ma_pcm_s16_to_s16;
|
||||
} else if (pConverter->config.formatOut == ma_format_s24) {
|
||||
pConverter->onConvertPCM = ma_pcm_s16_to_s24__sse2;
|
||||
} else if (pConverter->config.formatOut == ma_format_s32) {
|
||||
pConverter->onConvertPCM = ma_pcm_s16_to_s32__sse2;
|
||||
} else if (pConverter->config.formatOut == ma_format_f32) {
|
||||
pConverter->onConvertPCM = ma_pcm_s16_to_f32__sse2;
|
||||
}
|
||||
} break;
|
||||
|
||||
case ma_format_s24:
|
||||
{
|
||||
if (pConverter->config.formatOut == ma_format_u8) {
|
||||
pConverter->onConvertPCM = ma_pcm_s24_to_u8__sse2;
|
||||
} else if (pConverter->config.formatOut == ma_format_s16) {
|
||||
pConverter->onConvertPCM = ma_pcm_s24_to_s16__sse2;
|
||||
} else if (pConverter->config.formatOut == ma_format_s24) {
|
||||
pConverter->onConvertPCM = ma_pcm_s24_to_s24;
|
||||
} else if (pConverter->config.formatOut == ma_format_s32) {
|
||||
pConverter->onConvertPCM = ma_pcm_s24_to_s32__sse2;
|
||||
} else if (pConverter->config.formatOut == ma_format_f32) {
|
||||
pConverter->onConvertPCM = ma_pcm_s24_to_f32__sse2;
|
||||
}
|
||||
} break;
|
||||
|
||||
case ma_format_s32:
|
||||
{
|
||||
if (pConverter->config.formatOut == ma_format_u8) {
|
||||
pConverter->onConvertPCM = ma_pcm_s32_to_u8__sse2;
|
||||
} else if (pConverter->config.formatOut == ma_format_s16) {
|
||||
pConverter->onConvertPCM = ma_pcm_s32_to_s16__sse2;
|
||||
} else if (pConverter->config.formatOut == ma_format_s24) {
|
||||
pConverter->onConvertPCM = ma_pcm_s32_to_s24__sse2;
|
||||
} else if (pConverter->config.formatOut == ma_format_s32) {
|
||||
pConverter->onConvertPCM = ma_pcm_s32_to_s32;
|
||||
} else if (pConverter->config.formatOut == ma_format_f32) {
|
||||
pConverter->onConvertPCM = ma_pcm_s32_to_f32__sse2;
|
||||
}
|
||||
} break;
|
||||
|
||||
case ma_format_f32:
|
||||
default:
|
||||
{
|
||||
if (pConverter->config.formatOut == ma_format_u8) {
|
||||
pConverter->onConvertPCM = ma_pcm_f32_to_u8__sse2;
|
||||
} else if (pConverter->config.formatOut == ma_format_s16) {
|
||||
pConverter->onConvertPCM = ma_pcm_f32_to_s16__sse2;
|
||||
} else if (pConverter->config.formatOut == ma_format_s24) {
|
||||
pConverter->onConvertPCM = ma_pcm_f32_to_s24__sse2;
|
||||
} else if (pConverter->config.formatOut == ma_format_s32) {
|
||||
pConverter->onConvertPCM = ma_pcm_f32_to_s32__sse2;
|
||||
} else if (pConverter->config.formatOut == ma_format_f32) {
|
||||
pConverter->onConvertPCM = ma_pcm_f32_to_f32;
|
||||
}
|
||||
} break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(MA_SUPPORT_AVX2)
|
||||
void ma_format_converter_init_callbacks__avx2(ma_format_converter* pConverter)
|
||||
{
|
||||
ma_assert(pConverter != NULL);
|
||||
|
||||
switch (pConverter->config.formatIn)
|
||||
{
|
||||
case ma_format_u8:
|
||||
{
|
||||
if (pConverter->config.formatOut == ma_format_u8) {
|
||||
pConverter->onConvertPCM = ma_pcm_u8_to_u8;
|
||||
} else if (pConverter->config.formatOut == ma_format_s16) {
|
||||
pConverter->onConvertPCM = ma_pcm_u8_to_s16__avx2;
|
||||
} else if (pConverter->config.formatOut == ma_format_s24) {
|
||||
pConverter->onConvertPCM = ma_pcm_u8_to_s24__avx2;
|
||||
} else if (pConverter->config.formatOut == ma_format_s32) {
|
||||
pConverter->onConvertPCM = ma_pcm_u8_to_s32__avx2;
|
||||
} else if (pConverter->config.formatOut == ma_format_f32) {
|
||||
pConverter->onConvertPCM = ma_pcm_u8_to_f32__avx2;
|
||||
}
|
||||
} break;
|
||||
|
||||
case ma_format_s16:
|
||||
{
|
||||
if (pConverter->config.formatOut == ma_format_u8) {
|
||||
pConverter->onConvertPCM = ma_pcm_s16_to_u8__avx2;
|
||||
} else if (pConverter->config.formatOut == ma_format_s16) {
|
||||
pConverter->onConvertPCM = ma_pcm_s16_to_s16;
|
||||
} else if (pConverter->config.formatOut == ma_format_s24) {
|
||||
pConverter->onConvertPCM = ma_pcm_s16_to_s24__avx2;
|
||||
} else if (pConverter->config.formatOut == ma_format_s32) {
|
||||
pConverter->onConvertPCM = ma_pcm_s16_to_s32__avx2;
|
||||
} else if (pConverter->config.formatOut == ma_format_f32) {
|
||||
pConverter->onConvertPCM = ma_pcm_s16_to_f32__avx2;
|
||||
}
|
||||
} break;
|
||||
|
||||
case ma_format_s24:
|
||||
{
|
||||
if (pConverter->config.formatOut == ma_format_u8) {
|
||||
pConverter->onConvertPCM = ma_pcm_s24_to_u8__avx2;
|
||||
} else if (pConverter->config.formatOut == ma_format_s16) {
|
||||
pConverter->onConvertPCM = ma_pcm_s24_to_s16__avx2;
|
||||
} else if (pConverter->config.formatOut == ma_format_s24) {
|
||||
pConverter->onConvertPCM = ma_pcm_s24_to_s24;
|
||||
} else if (pConverter->config.formatOut == ma_format_s32) {
|
||||
pConverter->onConvertPCM = ma_pcm_s24_to_s32__avx2;
|
||||
} else if (pConverter->config.formatOut == ma_format_f32) {
|
||||
pConverter->onConvertPCM = ma_pcm_s24_to_f32__avx2;
|
||||
}
|
||||
} break;
|
||||
|
||||
case ma_format_s32:
|
||||
{
|
||||
if (pConverter->config.formatOut == ma_format_u8) {
|
||||
pConverter->onConvertPCM = ma_pcm_s32_to_u8__avx2;
|
||||
} else if (pConverter->config.formatOut == ma_format_s16) {
|
||||
pConverter->onConvertPCM = ma_pcm_s32_to_s16__avx2;
|
||||
} else if (pConverter->config.formatOut == ma_format_s24) {
|
||||
pConverter->onConvertPCM = ma_pcm_s32_to_s24__avx2;
|
||||
} else if (pConverter->config.formatOut == ma_format_s32) {
|
||||
pConverter->onConvertPCM = ma_pcm_s32_to_s32;
|
||||
} else if (pConverter->config.formatOut == ma_format_f32) {
|
||||
pConverter->onConvertPCM = ma_pcm_s32_to_f32__avx2;
|
||||
}
|
||||
} break;
|
||||
|
||||
case ma_format_f32:
|
||||
default:
|
||||
{
|
||||
if (pConverter->config.formatOut == ma_format_u8) {
|
||||
pConverter->onConvertPCM = ma_pcm_f32_to_u8__avx2;
|
||||
} else if (pConverter->config.formatOut == ma_format_s16) {
|
||||
pConverter->onConvertPCM = ma_pcm_f32_to_s16__avx2;
|
||||
} else if (pConverter->config.formatOut == ma_format_s24) {
|
||||
pConverter->onConvertPCM = ma_pcm_f32_to_s24__avx2;
|
||||
} else if (pConverter->config.formatOut == ma_format_s32) {
|
||||
pConverter->onConvertPCM = ma_pcm_f32_to_s32__avx2;
|
||||
} else if (pConverter->config.formatOut == ma_format_f32) {
|
||||
pConverter->onConvertPCM = ma_pcm_f32_to_f32;
|
||||
}
|
||||
} break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(MA_SUPPORT_AVX512)
|
||||
void ma_format_converter_init_callbacks__avx512(ma_format_converter* pConverter)
|
||||
{
|
||||
ma_assert(pConverter != NULL);
|
||||
|
||||
switch (pConverter->config.formatIn)
|
||||
{
|
||||
case ma_format_u8:
|
||||
{
|
||||
if (pConverter->config.formatOut == ma_format_u8) {
|
||||
pConverter->onConvertPCM = ma_pcm_u8_to_u8;
|
||||
} else if (pConverter->config.formatOut == ma_format_s16) {
|
||||
pConverter->onConvertPCM = ma_pcm_u8_to_s16__avx512;
|
||||
} else if (pConverter->config.formatOut == ma_format_s24) {
|
||||
pConverter->onConvertPCM = ma_pcm_u8_to_s24__avx512;
|
||||
} else if (pConverter->config.formatOut == ma_format_s32) {
|
||||
pConverter->onConvertPCM = ma_pcm_u8_to_s32__avx512;
|
||||
} else if (pConverter->config.formatOut == ma_format_f32) {
|
||||
pConverter->onConvertPCM = ma_pcm_u8_to_f32__avx512;
|
||||
}
|
||||
} break;
|
||||
|
||||
case ma_format_s16:
|
||||
{
|
||||
if (pConverter->config.formatOut == ma_format_u8) {
|
||||
pConverter->onConvertPCM = ma_pcm_s16_to_u8__avx512;
|
||||
} else if (pConverter->config.formatOut == ma_format_s16) {
|
||||
pConverter->onConvertPCM = ma_pcm_s16_to_s16;
|
||||
} else if (pConverter->config.formatOut == ma_format_s24) {
|
||||
pConverter->onConvertPCM = ma_pcm_s16_to_s24__avx512;
|
||||
} else if (pConverter->config.formatOut == ma_format_s32) {
|
||||
pConverter->onConvertPCM = ma_pcm_s16_to_s32__avx512;
|
||||
} else if (pConverter->config.formatOut == ma_format_f32) {
|
||||
pConverter->onConvertPCM = ma_pcm_s16_to_f32__avx512;
|
||||
}
|
||||
} break;
|
||||
|
||||
case ma_format_s24:
|
||||
{
|
||||
if (pConverter->config.formatOut == ma_format_u8) {
|
||||
pConverter->onConvertPCM = ma_pcm_s24_to_u8__avx512;
|
||||
} else if (pConverter->config.formatOut == ma_format_s16) {
|
||||
pConverter->onConvertPCM = ma_pcm_s24_to_s16__avx512;
|
||||
} else if (pConverter->config.formatOut == ma_format_s24) {
|
||||
pConverter->onConvertPCM = ma_pcm_s24_to_s24;
|
||||
} else if (pConverter->config.formatOut == ma_format_s32) {
|
||||
pConverter->onConvertPCM = ma_pcm_s24_to_s32__avx512;
|
||||
} else if (pConverter->config.formatOut == ma_format_f32) {
|
||||
pConverter->onConvertPCM = ma_pcm_s24_to_f32__avx512;
|
||||
}
|
||||
} break;
|
||||
|
||||
case ma_format_s32:
|
||||
{
|
||||
if (pConverter->config.formatOut == ma_format_u8) {
|
||||
pConverter->onConvertPCM = ma_pcm_s32_to_u8__avx512;
|
||||
} else if (pConverter->config.formatOut == ma_format_s16) {
|
||||
pConverter->onConvertPCM = ma_pcm_s32_to_s16__avx512;
|
||||
} else if (pConverter->config.formatOut == ma_format_s24) {
|
||||
pConverter->onConvertPCM = ma_pcm_s32_to_s24__avx512;
|
||||
} else if (pConverter->config.formatOut == ma_format_s32) {
|
||||
pConverter->onConvertPCM = ma_pcm_s32_to_s32;
|
||||
} else if (pConverter->config.formatOut == ma_format_f32) {
|
||||
pConverter->onConvertPCM = ma_pcm_s32_to_f32__avx512;
|
||||
}
|
||||
} break;
|
||||
|
||||
case ma_format_f32:
|
||||
default:
|
||||
{
|
||||
if (pConverter->config.formatOut == ma_format_u8) {
|
||||
pConverter->onConvertPCM = ma_pcm_f32_to_u8__avx512;
|
||||
} else if (pConverter->config.formatOut == ma_format_s16) {
|
||||
pConverter->onConvertPCM = ma_pcm_f32_to_s16__avx512;
|
||||
} else if (pConverter->config.formatOut == ma_format_s24) {
|
||||
pConverter->onConvertPCM = ma_pcm_f32_to_s24__avx512;
|
||||
} else if (pConverter->config.formatOut == ma_format_s32) {
|
||||
pConverter->onConvertPCM = ma_pcm_f32_to_s32__avx512;
|
||||
} else if (pConverter->config.formatOut == ma_format_f32) {
|
||||
pConverter->onConvertPCM = ma_pcm_f32_to_f32;
|
||||
}
|
||||
} break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(MA_SUPPORT_NEON)
|
||||
void ma_format_converter_init_callbacks__neon(ma_format_converter* pConverter)
|
||||
{
|
||||
ma_assert(pConverter != NULL);
|
||||
|
||||
switch (pConverter->config.formatIn)
|
||||
{
|
||||
case ma_format_u8:
|
||||
{
|
||||
if (pConverter->config.formatOut == ma_format_u8) {
|
||||
pConverter->onConvertPCM = ma_pcm_u8_to_u8;
|
||||
} else if (pConverter->config.formatOut == ma_format_s16) {
|
||||
pConverter->onConvertPCM = ma_pcm_u8_to_s16__neon;
|
||||
} else if (pConverter->config.formatOut == ma_format_s24) {
|
||||
pConverter->onConvertPCM = ma_pcm_u8_to_s24__neon;
|
||||
} else if (pConverter->config.formatOut == ma_format_s32) {
|
||||
pConverter->onConvertPCM = ma_pcm_u8_to_s32__neon;
|
||||
} else if (pConverter->config.formatOut == ma_format_f32) {
|
||||
pConverter->onConvertPCM = ma_pcm_u8_to_f32__neon;
|
||||
}
|
||||
} break;
|
||||
|
||||
case ma_format_s16:
|
||||
{
|
||||
if (pConverter->config.formatOut == ma_format_u8) {
|
||||
pConverter->onConvertPCM = ma_pcm_s16_to_u8__neon;
|
||||
} else if (pConverter->config.formatOut == ma_format_s16) {
|
||||
pConverter->onConvertPCM = ma_pcm_s16_to_s16;
|
||||
} else if (pConverter->config.formatOut == ma_format_s24) {
|
||||
pConverter->onConvertPCM = ma_pcm_s16_to_s24__neon;
|
||||
} else if (pConverter->config.formatOut == ma_format_s32) {
|
||||
pConverter->onConvertPCM = ma_pcm_s16_to_s32__neon;
|
||||
} else if (pConverter->config.formatOut == ma_format_f32) {
|
||||
pConverter->onConvertPCM = ma_pcm_s16_to_f32__neon;
|
||||
}
|
||||
} break;
|
||||
|
||||
case ma_format_s24:
|
||||
{
|
||||
if (pConverter->config.formatOut == ma_format_u8) {
|
||||
pConverter->onConvertPCM = ma_pcm_s24_to_u8__neon;
|
||||
} else if (pConverter->config.formatOut == ma_format_s16) {
|
||||
pConverter->onConvertPCM = ma_pcm_s24_to_s16__neon;
|
||||
} else if (pConverter->config.formatOut == ma_format_s24) {
|
||||
pConverter->onConvertPCM = ma_pcm_s24_to_s24;
|
||||
} else if (pConverter->config.formatOut == ma_format_s32) {
|
||||
pConverter->onConvertPCM = ma_pcm_s24_to_s32__neon;
|
||||
} else if (pConverter->config.formatOut == ma_format_f32) {
|
||||
pConverter->onConvertPCM = ma_pcm_s24_to_f32__neon;
|
||||
}
|
||||
} break;
|
||||
|
||||
case ma_format_s32:
|
||||
{
|
||||
if (pConverter->config.formatOut == ma_format_u8) {
|
||||
pConverter->onConvertPCM = ma_pcm_s32_to_u8__neon;
|
||||
} else if (pConverter->config.formatOut == ma_format_s16) {
|
||||
pConverter->onConvertPCM = ma_pcm_s32_to_s16__neon;
|
||||
} else if (pConverter->config.formatOut == ma_format_s24) {
|
||||
pConverter->onConvertPCM = ma_pcm_s32_to_s24__neon;
|
||||
} else if (pConverter->config.formatOut == ma_format_s32) {
|
||||
pConverter->onConvertPCM = ma_pcm_s32_to_s32;
|
||||
} else if (pConverter->config.formatOut == ma_format_f32) {
|
||||
pConverter->onConvertPCM = ma_pcm_s32_to_f32__neon;
|
||||
}
|
||||
} break;
|
||||
|
||||
case ma_format_f32:
|
||||
default:
|
||||
{
|
||||
if (pConverter->config.formatOut == ma_format_u8) {
|
||||
pConverter->onConvertPCM = ma_pcm_f32_to_u8__neon;
|
||||
} else if (pConverter->config.formatOut == ma_format_s16) {
|
||||
pConverter->onConvertPCM = ma_pcm_f32_to_s16__neon;
|
||||
} else if (pConverter->config.formatOut == ma_format_s24) {
|
||||
pConverter->onConvertPCM = ma_pcm_f32_to_s24__neon;
|
||||
} else if (pConverter->config.formatOut == ma_format_s32) {
|
||||
pConverter->onConvertPCM = ma_pcm_f32_to_s32__neon;
|
||||
} else if (pConverter->config.formatOut == ma_format_f32) {
|
||||
pConverter->onConvertPCM = ma_pcm_f32_to_f32;
|
||||
}
|
||||
} break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
ma_result ma_format_converter_init(const ma_format_converter_config* pConfig, ma_format_converter* pConverter)
|
||||
{
|
||||
if (pConverter == NULL) {
|
||||
return MA_INVALID_ARGS;
|
||||
}
|
||||
ma_zero_object(pConverter);
|
||||
|
||||
if (pConfig == NULL) {
|
||||
return MA_INVALID_ARGS;
|
||||
}
|
||||
|
||||
pConverter->config = *pConfig;
|
||||
|
||||
/* SIMD */
|
||||
pConverter->useSSE2 = ma_has_sse2() && !pConfig->noSSE2;
|
||||
pConverter->useAVX2 = ma_has_avx2() && !pConfig->noAVX2;
|
||||
pConverter->useAVX512 = ma_has_avx512f() && !pConfig->noAVX512;
|
||||
pConverter->useNEON = ma_has_neon() && !pConfig->noNEON;
|
||||
|
||||
#if defined(MA_SUPPORT_AVX512)
|
||||
if (pConverter->useAVX512) {
|
||||
ma_format_converter_init_callbacks__avx512(pConverter);
|
||||
} else
|
||||
#endif
|
||||
#if defined(MA_SUPPORT_AVX2)
|
||||
if (pConverter->useAVX2) {
|
||||
ma_format_converter_init_callbacks__avx2(pConverter);
|
||||
} else
|
||||
#endif
|
||||
#if defined(MA_SUPPORT_SSE2)
|
||||
if (pConverter->useSSE2) {
|
||||
ma_format_converter_init_callbacks__sse2(pConverter);
|
||||
} else
|
||||
#endif
|
||||
#if defined(MA_SUPPORT_NEON)
|
||||
if (pConverter->useNEON) {
|
||||
ma_format_converter_init_callbacks__neon(pConverter);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
ma_format_converter_init_callbacks__default(pConverter);
|
||||
}
|
||||
|
||||
switch (pConfig->formatOut)
|
||||
{
|
||||
case ma_format_u8:
|
||||
{
|
||||
pConverter->onInterleavePCM = ma_pcm_interleave_u8;
|
||||
pConverter->onDeinterleavePCM = ma_pcm_deinterleave_u8;
|
||||
} break;
|
||||
case ma_format_s16:
|
||||
{
|
||||
pConverter->onInterleavePCM = ma_pcm_interleave_s16;
|
||||
pConverter->onDeinterleavePCM = ma_pcm_deinterleave_s16;
|
||||
} break;
|
||||
case ma_format_s24:
|
||||
{
|
||||
pConverter->onInterleavePCM = ma_pcm_interleave_s24;
|
||||
pConverter->onDeinterleavePCM = ma_pcm_deinterleave_s24;
|
||||
} break;
|
||||
case ma_format_s32:
|
||||
{
|
||||
pConverter->onInterleavePCM = ma_pcm_interleave_s32;
|
||||
pConverter->onDeinterleavePCM = ma_pcm_deinterleave_s32;
|
||||
} break;
|
||||
case ma_format_f32:
|
||||
default:
|
||||
{
|
||||
pConverter->onInterleavePCM = ma_pcm_interleave_f32;
|
||||
pConverter->onDeinterleavePCM = ma_pcm_deinterleave_f32;
|
||||
} break;
|
||||
}
|
||||
|
||||
return MA_SUCCESS;
|
||||
}
|
||||
|
||||
ma_uint64 ma_format_converter_read(ma_format_converter* pConverter, ma_uint64 frameCount, void* pFramesOut, void* pUserData)
|
||||
{
|
||||
ma_uint64 totalFramesRead;
|
||||
ma_uint32 sampleSizeIn;
|
||||
ma_uint32 sampleSizeOut;
|
||||
ma_uint32 frameSizeOut;
|
||||
ma_uint8* pNextFramesOut;
|
||||
|
||||
if (pConverter == NULL || pFramesOut == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
totalFramesRead = 0;
|
||||
sampleSizeIn = ma_get_bytes_per_sample(pConverter->config.formatIn);
|
||||
sampleSizeOut = ma_get_bytes_per_sample(pConverter->config.formatOut);
|
||||
/*frameSizeIn = sampleSizeIn * pConverter->config.channels;*/
|
||||
frameSizeOut = sampleSizeOut * pConverter->config.channels;
|
||||
pNextFramesOut = (ma_uint8*)pFramesOut;
|
||||
|
||||
if (pConverter->config.onRead != NULL) {
|
||||
/* Input data is interleaved. */
|
||||
if (pConverter->config.formatIn == pConverter->config.formatOut) {
|
||||
/* Pass through. */
|
||||
while (totalFramesRead < frameCount) {
|
||||
ma_uint32 framesJustRead;
|
||||
ma_uint64 framesRemaining = (frameCount - totalFramesRead);
|
||||
ma_uint64 framesToReadRightNow = framesRemaining;
|
||||
if (framesToReadRightNow > 0xFFFFFFFF) {
|
||||
framesToReadRightNow = 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
framesJustRead = (ma_uint32)pConverter->config.onRead(pConverter, (ma_uint32)framesToReadRightNow, pNextFramesOut, pUserData);
|
||||
if (framesJustRead == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
totalFramesRead += framesJustRead;
|
||||
pNextFramesOut += framesJustRead * frameSizeOut;
|
||||
|
||||
if (framesJustRead < framesToReadRightNow) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Conversion required. */
|
||||
ma_uint32 maxFramesToReadAtATime;
|
||||
|
||||
MA_ALIGN(MA_SIMD_ALIGNMENT) ma_uint8 temp[MA_MAX_CHANNELS * MA_MAX_PCM_SAMPLE_SIZE_IN_BYTES * 128];
|
||||
ma_assert(sizeof(temp) <= 0xFFFFFFFF);
|
||||
|
||||
maxFramesToReadAtATime = sizeof(temp) / sampleSizeIn / pConverter->config.channels;
|
||||
|
||||
while (totalFramesRead < frameCount) {
|
||||
ma_uint32 framesJustRead;
|
||||
ma_uint64 framesRemaining = (frameCount - totalFramesRead);
|
||||
ma_uint64 framesToReadRightNow = framesRemaining;
|
||||
if (framesToReadRightNow > maxFramesToReadAtATime) {
|
||||
framesToReadRightNow = maxFramesToReadAtATime;
|
||||
}
|
||||
|
||||
framesJustRead = (ma_uint32)pConverter->config.onRead(pConverter, (ma_uint32)framesToReadRightNow, temp, pUserData);
|
||||
if (framesJustRead == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
pConverter->onConvertPCM(pNextFramesOut, temp, framesJustRead*pConverter->config.channels, pConverter->config.ditherMode);
|
||||
|
||||
totalFramesRead += framesJustRead;
|
||||
pNextFramesOut += framesJustRead * frameSizeOut;
|
||||
|
||||
if (framesJustRead < framesToReadRightNow) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Input data is deinterleaved. If a conversion is required we need to do an intermediary step. */
|
||||
void* ppTempSamplesOfOutFormat[MA_MAX_CHANNELS];
|
||||
size_t splitBufferSizeOut;
|
||||
ma_uint32 maxFramesToReadAtATime;
|
||||
|
||||
MA_ALIGN(MA_SIMD_ALIGNMENT) ma_uint8 tempSamplesOfOutFormat[MA_MAX_CHANNELS * MA_MAX_PCM_SAMPLE_SIZE_IN_BYTES * 128];
|
||||
ma_assert(sizeof(tempSamplesOfOutFormat) <= 0xFFFFFFFF);
|
||||
|
||||
ma_split_buffer(tempSamplesOfOutFormat, sizeof(tempSamplesOfOutFormat), pConverter->config.channels, MA_SIMD_ALIGNMENT, (void**)&ppTempSamplesOfOutFormat, &splitBufferSizeOut);
|
||||
|
||||
maxFramesToReadAtATime = (ma_uint32)(splitBufferSizeOut / sampleSizeIn);
|
||||
|
||||
while (totalFramesRead < frameCount) {
|
||||
ma_uint32 framesJustRead;
|
||||
ma_uint64 framesRemaining = (frameCount - totalFramesRead);
|
||||
ma_uint64 framesToReadRightNow = framesRemaining;
|
||||
if (framesToReadRightNow > maxFramesToReadAtATime) {
|
||||
framesToReadRightNow = maxFramesToReadAtATime;
|
||||
}
|
||||
|
||||
if (pConverter->config.formatIn == pConverter->config.formatOut) {
|
||||
/* Only interleaving. */
|
||||
framesJustRead = (ma_uint32)pConverter->config.onReadDeinterleaved(pConverter, (ma_uint32)framesToReadRightNow, ppTempSamplesOfOutFormat, pUserData);
|
||||
if (framesJustRead == 0) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/* Interleaving + Conversion. Convert first, then interleave. */
|
||||
void* ppTempSamplesOfInFormat[MA_MAX_CHANNELS];
|
||||
size_t splitBufferSizeIn;
|
||||
ma_uint32 iChannel;
|
||||
|
||||
MA_ALIGN(MA_SIMD_ALIGNMENT) ma_uint8 tempSamplesOfInFormat[MA_MAX_CHANNELS * MA_MAX_PCM_SAMPLE_SIZE_IN_BYTES * 128];
|
||||
|
||||
ma_split_buffer(tempSamplesOfInFormat, sizeof(tempSamplesOfInFormat), pConverter->config.channels, MA_SIMD_ALIGNMENT, (void**)&ppTempSamplesOfInFormat, &splitBufferSizeIn);
|
||||
|
||||
if (framesToReadRightNow > (splitBufferSizeIn / sampleSizeIn)) {
|
||||
framesToReadRightNow = (splitBufferSizeIn / sampleSizeIn);
|
||||
}
|
||||
|
||||
framesJustRead = (ma_uint32)pConverter->config.onReadDeinterleaved(pConverter, (ma_uint32)framesToReadRightNow, ppTempSamplesOfInFormat, pUserData);
|
||||
if (framesJustRead == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
for (iChannel = 0; iChannel < pConverter->config.channels; iChannel += 1) {
|
||||
pConverter->onConvertPCM(ppTempSamplesOfOutFormat[iChannel], ppTempSamplesOfInFormat[iChannel], framesJustRead, pConverter->config.ditherMode);
|
||||
}
|
||||
}
|
||||
|
||||
pConverter->onInterleavePCM(pNextFramesOut, (const void**)ppTempSamplesOfOutFormat, framesJustRead, pConverter->config.channels);
|
||||
|
||||
totalFramesRead += framesJustRead;
|
||||
pNextFramesOut += framesJustRead * frameSizeOut;
|
||||
|
||||
if (framesJustRead < framesToReadRightNow) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return totalFramesRead;
|
||||
}
|
||||
|
||||
ma_uint64 ma_format_converter_read_deinterleaved(ma_format_converter* pConverter, ma_uint64 frameCount, void** ppSamplesOut, void* pUserData)
|
||||
{
|
||||
ma_uint64 totalFramesRead;
|
||||
ma_uint32 sampleSizeIn;
|
||||
ma_uint32 sampleSizeOut;
|
||||
ma_uint8* ppNextSamplesOut[MA_MAX_CHANNELS];
|
||||
|
||||
if (pConverter == NULL || ppSamplesOut == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
totalFramesRead = 0;
|
||||
sampleSizeIn = ma_get_bytes_per_sample(pConverter->config.formatIn);
|
||||
sampleSizeOut = ma_get_bytes_per_sample(pConverter->config.formatOut);
|
||||
|
||||
ma_copy_memory(ppNextSamplesOut, ppSamplesOut, sizeof(void*) * pConverter->config.channels);
|
||||
|
||||
if (pConverter->config.onRead != NULL) {
|
||||
/* Input data is interleaved. */
|
||||
ma_uint32 maxFramesToReadAtATime;
|
||||
|
||||
MA_ALIGN(MA_SIMD_ALIGNMENT) ma_uint8 tempSamplesOfOutFormat[MA_MAX_CHANNELS * MA_MAX_PCM_SAMPLE_SIZE_IN_BYTES * 128];
|
||||
ma_assert(sizeof(tempSamplesOfOutFormat) <= 0xFFFFFFFF);
|
||||
|
||||
maxFramesToReadAtATime = sizeof(tempSamplesOfOutFormat) / sampleSizeIn / pConverter->config.channels;
|
||||
|
||||
while (totalFramesRead < frameCount) {
|
||||
ma_uint32 iChannel;
|
||||
ma_uint32 framesJustRead;
|
||||
ma_uint64 framesRemaining = (frameCount - totalFramesRead);
|
||||
ma_uint64 framesToReadRightNow = framesRemaining;
|
||||
if (framesToReadRightNow > maxFramesToReadAtATime) {
|
||||
framesToReadRightNow = maxFramesToReadAtATime;
|
||||
}
|
||||
|
||||
if (pConverter->config.formatIn == pConverter->config.formatOut) {
|
||||
/* Only de-interleaving. */
|
||||
framesJustRead = (ma_uint32)pConverter->config.onRead(pConverter, (ma_uint32)framesToReadRightNow, tempSamplesOfOutFormat, pUserData);
|
||||
if (framesJustRead == 0) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/* De-interleaving + Conversion. Convert first, then de-interleave. */
|
||||
MA_ALIGN(MA_SIMD_ALIGNMENT) ma_uint8 tempSamplesOfInFormat[sizeof(tempSamplesOfOutFormat)];
|
||||
|
||||
framesJustRead = (ma_uint32)pConverter->config.onRead(pConverter, (ma_uint32)framesToReadRightNow, tempSamplesOfInFormat, pUserData);
|
||||
if (framesJustRead == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
pConverter->onConvertPCM(tempSamplesOfOutFormat, tempSamplesOfInFormat, framesJustRead * pConverter->config.channels, pConverter->config.ditherMode);
|
||||
}
|
||||
|
||||
pConverter->onDeinterleavePCM((void**)ppNextSamplesOut, tempSamplesOfOutFormat, framesJustRead, pConverter->config.channels);
|
||||
|
||||
totalFramesRead += framesJustRead;
|
||||
for (iChannel = 0; iChannel < pConverter->config.channels; ++iChannel) {
|
||||
ppNextSamplesOut[iChannel] += framesJustRead * sampleSizeOut;
|
||||
}
|
||||
|
||||
if (framesJustRead < framesToReadRightNow) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Input data is deinterleaved. */
|
||||
if (pConverter->config.formatIn == pConverter->config.formatOut) {
|
||||
/* Pass through. */
|
||||
while (totalFramesRead < frameCount) {
|
||||
ma_uint32 iChannel;
|
||||
ma_uint32 framesJustRead;
|
||||
ma_uint64 framesRemaining = (frameCount - totalFramesRead);
|
||||
ma_uint64 framesToReadRightNow = framesRemaining;
|
||||
if (framesToReadRightNow > 0xFFFFFFFF) {
|
||||
framesToReadRightNow = 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
framesJustRead = (ma_uint32)pConverter->config.onReadDeinterleaved(pConverter, (ma_uint32)framesToReadRightNow, (void**)ppNextSamplesOut, pUserData);
|
||||
if (framesJustRead == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
totalFramesRead += framesJustRead;
|
||||
for (iChannel = 0; iChannel < pConverter->config.channels; ++iChannel) {
|
||||
ppNextSamplesOut[iChannel] += framesJustRead * sampleSizeOut;
|
||||
}
|
||||
|
||||
if (framesJustRead < framesToReadRightNow) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Conversion required. */
|
||||
void* ppTemp[MA_MAX_CHANNELS];
|
||||
size_t splitBufferSize;
|
||||
ma_uint32 maxFramesToReadAtATime;
|
||||
|
||||
MA_ALIGN(MA_SIMD_ALIGNMENT) ma_uint8 temp[MA_MAX_CHANNELS][MA_MAX_PCM_SAMPLE_SIZE_IN_BYTES * 128];
|
||||
ma_assert(sizeof(temp) <= 0xFFFFFFFF);
|
||||
|
||||
ma_split_buffer(temp, sizeof(temp), pConverter->config.channels, MA_SIMD_ALIGNMENT, (void**)&ppTemp, &splitBufferSize);
|
||||
|
||||
maxFramesToReadAtATime = (ma_uint32)(splitBufferSize / sampleSizeIn);
|
||||
|
||||
while (totalFramesRead < frameCount) {
|
||||
ma_uint32 iChannel;
|
||||
ma_uint32 framesJustRead;
|
||||
ma_uint64 framesRemaining = (frameCount - totalFramesRead);
|
||||
ma_uint64 framesToReadRightNow = framesRemaining;
|
||||
if (framesToReadRightNow > maxFramesToReadAtATime) {
|
||||
framesToReadRightNow = maxFramesToReadAtATime;
|
||||
}
|
||||
|
||||
framesJustRead = (ma_uint32)pConverter->config.onReadDeinterleaved(pConverter, (ma_uint32)framesToReadRightNow, ppTemp, pUserData);
|
||||
if (framesJustRead == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
for (iChannel = 0; iChannel < pConverter->config.channels; iChannel += 1) {
|
||||
pConverter->onConvertPCM(ppNextSamplesOut[iChannel], ppTemp[iChannel], framesJustRead, pConverter->config.ditherMode);
|
||||
ppNextSamplesOut[iChannel] += framesJustRead * sampleSizeOut;
|
||||
}
|
||||
|
||||
totalFramesRead += framesJustRead;
|
||||
|
||||
if (framesJustRead < framesToReadRightNow) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return totalFramesRead;
|
||||
}
|
||||
|
||||
|
||||
ma_format_converter_config ma_format_converter_config_init_new()
|
||||
{
|
||||
ma_format_converter_config config;
|
||||
ma_zero_object(&config);
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
ma_format_converter_config ma_format_converter_config_init(ma_format formatIn, ma_format formatOut, ma_uint32 channels, ma_format_converter_read_proc onRead, void* pUserData)
|
||||
{
|
||||
ma_format_converter_config config = ma_format_converter_config_init_new();
|
||||
config.formatIn = formatIn;
|
||||
config.formatOut = formatOut;
|
||||
config.channels = channels;
|
||||
config.onRead = onRead;
|
||||
config.onReadDeinterleaved = NULL;
|
||||
config.pUserData = pUserData;
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
ma_format_converter_config ma_format_converter_config_init_deinterleaved(ma_format formatIn, ma_format formatOut, ma_uint32 channels, ma_format_converter_read_deinterleaved_proc onReadDeinterleaved, void* pUserData)
|
||||
{
|
||||
ma_format_converter_config config = ma_format_converter_config_init(formatIn, formatOut, channels, NULL, pUserData);
|
||||
config.onReadDeinterleaved = onReadDeinterleaved;
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**************************************************************************************************************************************************************
|
||||
|
||||
Format Conversion
|
||||
|
||||
Reference in New Issue
Block a user