mirror of
https://github.com/mackron/miniaudio.git
synced 2026-04-23 16:54:03 +02:00
Begin work on integration of the new channel converter.
This commit is contained in:
@@ -16,7 +16,7 @@ typedef struct
|
|||||||
float weights[MA_MAX_CHANNELS][MA_MAX_CHANNELS]; /* [in][out]. Only used when mixingMode is set to ma_channel_mix_mode_custom_weights. */
|
float weights[MA_MAX_CHANNELS][MA_MAX_CHANNELS]; /* [in][out]. Only used when mixingMode is set to ma_channel_mix_mode_custom_weights. */
|
||||||
} ma_channel_converter_config;
|
} ma_channel_converter_config;
|
||||||
|
|
||||||
ma_channel_converter_config ma_channel_converter_config_init(ma_format format, ma_uint32 channelsIn, const ma_channel channelMapIn[MA_MAX_CHANNELS], ma_uint32 channelsOut, const ma_channel channelMapOut[MA_MAX_CHANNELS], ma_channel_mix_mode mixingMode);
|
ma_channel_converter_config ma_channel_converter_config_init(ma_format format, ma_uint32 channelsIn, const ma_channel channelMapIn[MA_MAX_CHANNELS], ma_uint32 channelsOut, const ma_channel channelMapOut[MA_MAX_CHANNELS], ma_channel_mix_mode mixingMode, const float weights[MA_MAX_CHANNELS][MA_MAX_CHANNELS]);
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
@@ -51,9 +51,13 @@ typedef struct
|
|||||||
ma_uint32 channelsOut;
|
ma_uint32 channelsOut;
|
||||||
ma_uint32 sampleRateIn;
|
ma_uint32 sampleRateIn;
|
||||||
ma_uint32 sampleRateOut;
|
ma_uint32 sampleRateOut;
|
||||||
|
ma_channel channelMapIn[MA_MAX_CHANNELS];
|
||||||
|
ma_channel channelMapOut[MA_MAX_CHANNELS];
|
||||||
ma_dither_mode ditherMode;
|
ma_dither_mode ditherMode;
|
||||||
ma_resample_algorithm resampleAlgorithm;
|
ma_resample_algorithm resampleAlgorithm;
|
||||||
ma_bool32 dynamicSampleRate;
|
ma_bool32 allowDynamicSampleRate;
|
||||||
|
ma_channel_mix_mode channelMixMode;
|
||||||
|
float channelWeights[MA_MAX_CHANNELS][MA_MAX_CHANNELS]; /* [in][out]. Only used when channelMixMode is set to ma_channel_mix_mode_custom_weights. */
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
struct
|
struct
|
||||||
@@ -73,10 +77,11 @@ ma_data_converter_config ma_data_converter_config_init(ma_format formatIn, ma_fo
|
|||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
ma_data_converter_config config;
|
ma_data_converter_config config;
|
||||||
|
ma_channel_converter channelConverter;
|
||||||
ma_resampler resampler;
|
ma_resampler resampler;
|
||||||
ma_bool32 hasPreFormatConversion : 1;
|
ma_bool32 hasPreFormatConversion : 1;
|
||||||
ma_bool32 hasPostFormatConversion : 1;
|
ma_bool32 hasPostFormatConversion : 1;
|
||||||
ma_bool32 hasChannelRouter : 1;
|
ma_bool32 hasChannelConverter : 1;
|
||||||
ma_bool32 hasResampler : 1;
|
ma_bool32 hasResampler : 1;
|
||||||
ma_bool32 isPassthrough : 1;
|
ma_bool32 isPassthrough : 1;
|
||||||
} ma_data_converter;
|
} ma_data_converter;
|
||||||
@@ -103,7 +108,7 @@ ma_uint64 ma_data_converter_get_output_latency(ma_data_converter* pConverter);
|
|||||||
#define MA_CHANNEL_CONVERTER_FIXED_POINT_SHIFT 12
|
#define MA_CHANNEL_CONVERTER_FIXED_POINT_SHIFT 12
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ma_channel_converter_config ma_channel_converter_config_init(ma_format format, ma_uint32 channelsIn, const ma_channel channelMapIn[MA_MAX_CHANNELS], ma_uint32 channelsOut, const ma_channel channelMapOut[MA_MAX_CHANNELS], ma_channel_mix_mode mixingMode)
|
ma_channel_converter_config ma_channel_converter_config_init(ma_format format, ma_uint32 channelsIn, const ma_channel channelMapIn[MA_MAX_CHANNELS], ma_uint32 channelsOut, const ma_channel channelMapOut[MA_MAX_CHANNELS], ma_channel_mix_mode mixingMode, const float weights[MA_MAX_CHANNELS][MA_MAX_CHANNELS])
|
||||||
{
|
{
|
||||||
ma_channel_converter_config config;
|
ma_channel_converter_config config;
|
||||||
MA_ZERO_OBJECT(&config);
|
MA_ZERO_OBJECT(&config);
|
||||||
@@ -114,6 +119,17 @@ ma_channel_converter_config ma_channel_converter_config_init(ma_format format, m
|
|||||||
ma_channel_map_copy(config.channelMapOut, channelMapOut, channelsOut);
|
ma_channel_map_copy(config.channelMapOut, channelMapOut, channelsOut);
|
||||||
config.mixingMode = mixingMode;
|
config.mixingMode = mixingMode;
|
||||||
|
|
||||||
|
if (weights != NULL) {
|
||||||
|
ma_uint32 iChannelIn;
|
||||||
|
ma_uint32 iChannelOut;
|
||||||
|
|
||||||
|
for (iChannelIn = 0; iChannelIn < channelsIn; iChannelIn += 1) {
|
||||||
|
for (iChannelOut = 0; iChannelOut < channelsOut; iChannelOut += 1) {
|
||||||
|
config.weights[iChannelIn][iChannelOut] = weights[iChannelIn][iChannelOut];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -638,15 +654,15 @@ ma_data_converter_config ma_data_converter_config_init(ma_format formatIn, ma_fo
|
|||||||
{
|
{
|
||||||
ma_data_converter_config config;
|
ma_data_converter_config config;
|
||||||
MA_ZERO_OBJECT(&config);
|
MA_ZERO_OBJECT(&config);
|
||||||
config.formatIn = formatIn;
|
config.formatIn = formatIn;
|
||||||
config.formatOut = formatOut;
|
config.formatOut = formatOut;
|
||||||
config.channelsIn = channelsIn;
|
config.channelsIn = channelsIn;
|
||||||
config.channelsOut = channelsOut;
|
config.channelsOut = channelsOut;
|
||||||
config.sampleRateIn = sampleRateIn;
|
config.sampleRateIn = sampleRateIn;
|
||||||
config.sampleRateOut = sampleRateOut;
|
config.sampleRateOut = sampleRateOut;
|
||||||
config.ditherMode = ma_dither_mode_none;
|
config.ditherMode = ma_dither_mode_none;
|
||||||
config.resampleAlgorithm = ma_resample_algorithm_linear;
|
config.resampleAlgorithm = ma_resample_algorithm_linear;
|
||||||
config.dynamicSampleRate = MA_TRUE; /* Enable dynamic sample rates by default. An optimization is to disable this when the sample rate is the same, but that will disable ma_data_converter_set_rate(). */
|
config.allowDynamicSampleRate = MA_TRUE; /* Enable dynamic sample rates by default. An optimization is to disable this when the sample rate is the same, but that will disable ma_data_converter_set_rate(). */
|
||||||
|
|
||||||
/* Linear resampling defaults. */
|
/* Linear resampling defaults. */
|
||||||
config.resampling.linear.lpfCount = 1;
|
config.resampling.linear.lpfCount = 1;
|
||||||
@@ -683,19 +699,37 @@ ma_result ma_data_converter_init(const ma_data_converter_config* pConfig, ma_dat
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Channel router. */
|
/* Channel converter. We always initialize this, but we check if it configures itself as a passthrough to determine whether or not it's needed. */
|
||||||
if (pConverter->config.channelsIn != pConverter->config.channelsOut) {
|
{
|
||||||
pConverter->hasChannelRouter = MA_TRUE;
|
ma_channel_converter_config channelConverterConfig;
|
||||||
|
ma_format channelConverterFormat;
|
||||||
|
|
||||||
|
if (pConverter->config.formatIn == ma_format_s16) {
|
||||||
|
channelConverterFormat = ma_format_s16;
|
||||||
|
} else {
|
||||||
|
channelConverterFormat = ma_format_f32;
|
||||||
|
}
|
||||||
|
|
||||||
|
channelConverterConfig = ma_channel_converter_config_init(channelConverterFormat, pConverter->config.channelsIn, pConverter->config.channelMapIn, pConverter->config.channelsOut, pConverter->config.channelMapOut, pConverter->config.channelMixMode, pConverter->config.channelWeights);
|
||||||
|
result = ma_channel_converter_init(&channelConverterConfig, &pConverter->channelConverter);
|
||||||
|
if (result != MA_SUCCESS) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the channel converter is not a passthrough we need to enable it. Otherwise we can skip it. */
|
||||||
|
if (pConverter->channelConverter.isPassthrough == MA_FALSE) {
|
||||||
|
pConverter->hasChannelConverter = MA_TRUE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Always enable dynamic sample rates if the input sample rate is different because we're always going to need a resampler in this case anyway. */
|
/* Always enable dynamic sample rates if the input sample rate is different because we're always going to need a resampler in this case anyway. */
|
||||||
if (pConverter->config.dynamicSampleRate == MA_FALSE) {
|
if (pConverter->config.allowDynamicSampleRate == MA_FALSE) {
|
||||||
pConverter->config.dynamicSampleRate = pConverter->config.sampleRateIn != pConverter->config.sampleRateOut;
|
pConverter->config.allowDynamicSampleRate = pConverter->config.sampleRateIn != pConverter->config.sampleRateOut;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Resampler. */
|
/* Resampler. */
|
||||||
if (pConverter->config.dynamicSampleRate) {
|
if (pConverter->config.allowDynamicSampleRate) {
|
||||||
ma_resampler_config resamplerConfig;
|
ma_resampler_config resamplerConfig;
|
||||||
ma_format resamplerFormat;
|
ma_format resamplerFormat;
|
||||||
ma_uint32 resamplerChannels;
|
ma_uint32 resamplerChannels;
|
||||||
@@ -729,7 +763,7 @@ ma_result ma_data_converter_init(const ma_data_converter_config* pConfig, ma_dat
|
|||||||
/* We can enable passthrough optimizations if applicable. Note that we'll only be able to do this if the sample rate is static. */
|
/* We can enable passthrough optimizations if applicable. Note that we'll only be able to do this if the sample rate is static. */
|
||||||
if (pConverter->hasPreFormatConversion == MA_FALSE &&
|
if (pConverter->hasPreFormatConversion == MA_FALSE &&
|
||||||
pConverter->hasPostFormatConversion == MA_FALSE &&
|
pConverter->hasPostFormatConversion == MA_FALSE &&
|
||||||
pConverter->hasChannelRouter == MA_FALSE &&
|
pConverter->hasChannelConverter == MA_FALSE &&
|
||||||
pConverter->hasResampler == MA_FALSE) {
|
pConverter->hasResampler == MA_FALSE) {
|
||||||
pConverter->isPassthrough = MA_TRUE;
|
pConverter->isPassthrough = MA_TRUE;
|
||||||
}
|
}
|
||||||
@@ -1004,7 +1038,7 @@ ma_result ma_data_converter_process_pcm_frames(ma_data_converter* pConverter, co
|
|||||||
*/
|
*/
|
||||||
if (pConverter->config.channelsIn < pConverter->config.channelsOut) {
|
if (pConverter->config.channelsIn < pConverter->config.channelsOut) {
|
||||||
/* Do resampling first, if necessary. */
|
/* Do resampling first, if necessary. */
|
||||||
MA_ASSERT(pConverter->hasChannelRouter == MA_TRUE);
|
MA_ASSERT(pConverter->hasChannelConverter == MA_TRUE);
|
||||||
|
|
||||||
if (pConverter->hasResampler) {
|
if (pConverter->hasResampler) {
|
||||||
/* Channel routing first. */
|
/* Channel routing first. */
|
||||||
@@ -1015,7 +1049,7 @@ ma_result ma_data_converter_process_pcm_frames(ma_data_converter* pConverter, co
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Do channel conversion first, if necessary. */
|
/* Do channel conversion first, if necessary. */
|
||||||
if (pConverter->hasChannelRouter) {
|
if (pConverter->hasChannelConverter) {
|
||||||
if (pConverter->hasResampler) {
|
if (pConverter->hasResampler) {
|
||||||
/* Resampling first. */
|
/* Resampling first. */
|
||||||
return ma_data_converter_process_pcm_frames__resampling_first(pConverter, pFramesIn, pFrameCountIn, pFramesOut, pFrameCountOut);
|
return ma_data_converter_process_pcm_frames__resampling_first(pConverter, pFramesIn, pFrameCountIn, pFramesOut, pFrameCountOut);
|
||||||
|
|||||||
Reference in New Issue
Block a user