mirror of
https://github.com/mackron/miniaudio.git
synced 2026-04-22 16:24:04 +02:00
Fix a bug when trying to play a sound with inconsistent channel counts.
This bug happens when the channel count of the data source does not match the channel count of the engine.
This commit is contained in:
@@ -48,7 +48,7 @@ int main(int argc, char** argv)
|
|||||||
|
|
||||||
resourceManagerConfig = ma_resource_manager_config_init();
|
resourceManagerConfig = ma_resource_manager_config_init();
|
||||||
resourceManagerConfig.decodedFormat = ma_format_f32;
|
resourceManagerConfig.decodedFormat = ma_format_f32;
|
||||||
resourceManagerConfig.decodedChannels = 2;
|
//resourceManagerConfig.decodedChannels = 2;
|
||||||
resourceManagerConfig.decodedSampleRate = 48000;
|
resourceManagerConfig.decodedSampleRate = 48000;
|
||||||
result = ma_resource_manager_init(&resourceManagerConfig, &resourceManager);
|
result = ma_resource_manager_init(&resourceManagerConfig, &resourceManager);
|
||||||
if (result != MA_SUCCESS) {
|
if (result != MA_SUCCESS) {
|
||||||
|
|||||||
+45
-31
@@ -1487,22 +1487,20 @@ MA_API ma_result ma_panner_set_pan(ma_panner* pPanner, float pan);
|
|||||||
/* Spatializer. */
|
/* Spatializer. */
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
ma_engine* pEngine;
|
ma_uint32 channelsIn;
|
||||||
ma_format format;
|
ma_uint32 channelsOut;
|
||||||
ma_uint32 channels;
|
|
||||||
ma_vec3 position;
|
ma_vec3 position;
|
||||||
ma_quat rotation;
|
ma_quat rotation;
|
||||||
} ma_spatializer_config;
|
} ma_spatializer_config;
|
||||||
|
|
||||||
MA_API ma_spatializer_config ma_spatializer_config_init(ma_engine* pEngine, ma_format format, ma_uint32 channels);
|
MA_API ma_spatializer_config ma_spatializer_config_init(ma_uint32 channelsIn, ma_uint32 channelsOut);
|
||||||
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
ma_effect_base effect;
|
ma_effect_base effect;
|
||||||
ma_engine* pEngine; /* For accessing global, per-engine data such as the listener position and environmental information. */
|
ma_uint32 channelsIn;
|
||||||
ma_format format;
|
ma_uint32 channelsOut;
|
||||||
ma_uint32 channels;
|
|
||||||
ma_vec3 position;
|
ma_vec3 position;
|
||||||
ma_quat rotation;
|
ma_quat rotation;
|
||||||
} ma_spatializer;
|
} ma_spatializer;
|
||||||
@@ -8428,15 +8426,14 @@ MA_API ma_result ma_panner_set_pan(ma_panner* pPanner, float pan)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
MA_API ma_spatializer_config ma_spatializer_config_init(ma_engine* pEngine, ma_format format, ma_uint32 channels)
|
MA_API ma_spatializer_config ma_spatializer_config_init(ma_uint32 channelsIn, ma_uint32 channelsOut)
|
||||||
{
|
{
|
||||||
ma_spatializer_config config;
|
ma_spatializer_config config;
|
||||||
|
|
||||||
MA_ZERO_OBJECT(&config);
|
MA_ZERO_OBJECT(&config);
|
||||||
|
|
||||||
config.pEngine = pEngine;
|
config.channelsIn = channelsIn;
|
||||||
config.format = format;
|
config.channelsOut = channelsOut;
|
||||||
config.channels = channels;
|
|
||||||
config.position = ma_vec3f(0, 0, 0);
|
config.position = ma_vec3f(0, 0, 0);
|
||||||
config.rotation = ma_quatf(0, 0, 0, 1);
|
config.rotation = ma_quatf(0, 0, 0, 1);
|
||||||
|
|
||||||
@@ -8464,12 +8461,23 @@ static ma_result ma_spatializer_effect__on_process_pcm_frames(ma_effect* pEffect
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ma_result ma_spatializer_effect__on_get_data_format(ma_effect* pEffect, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate)
|
static ma_result ma_spatializer_effect__on_get_data_format_in(ma_effect* pEffect, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate)
|
||||||
{
|
{
|
||||||
ma_spatializer* pSpatializer = (ma_spatializer*)pEffect;
|
ma_spatializer* pSpatializer = (ma_spatializer*)pEffect;
|
||||||
|
|
||||||
*pFormat = pSpatializer->format;
|
*pFormat = ma_format_f32;
|
||||||
*pChannels = pSpatializer->channels;
|
*pChannels = pSpatializer->channelsIn;
|
||||||
|
*pSampleRate = 0; /* There's no notion of sample rate with this effect. */
|
||||||
|
|
||||||
|
return MA_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ma_result ma_spatializer_effect__on_get_data_format_out(ma_effect* pEffect, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate)
|
||||||
|
{
|
||||||
|
ma_spatializer* pSpatializer = (ma_spatializer*)pEffect;
|
||||||
|
|
||||||
|
*pFormat = ma_format_f32;
|
||||||
|
*pChannels = pSpatializer->channelsOut;
|
||||||
*pSampleRate = 0; /* There's no notion of sample rate with this effect. */
|
*pSampleRate = 0; /* There's no notion of sample rate with this effect. */
|
||||||
|
|
||||||
return MA_SUCCESS;
|
return MA_SUCCESS;
|
||||||
@@ -8490,12 +8498,11 @@ MA_API ma_result ma_spatializer_init(const ma_spatializer_config* pConfig, ma_sp
|
|||||||
pSpatializer->effect.onProcessPCMFrames = ma_spatializer_effect__on_process_pcm_frames;
|
pSpatializer->effect.onProcessPCMFrames = ma_spatializer_effect__on_process_pcm_frames;
|
||||||
pSpatializer->effect.onGetRequiredInputFrameCount = NULL;
|
pSpatializer->effect.onGetRequiredInputFrameCount = NULL;
|
||||||
pSpatializer->effect.onGetExpectedOutputFrameCount = NULL;
|
pSpatializer->effect.onGetExpectedOutputFrameCount = NULL;
|
||||||
pSpatializer->effect.onGetInputDataFormat = ma_spatializer_effect__on_get_data_format; /* Same format for both input and output. */
|
pSpatializer->effect.onGetInputDataFormat = ma_spatializer_effect__on_get_data_format_in;
|
||||||
pSpatializer->effect.onGetOutputDataFormat = ma_spatializer_effect__on_get_data_format;
|
pSpatializer->effect.onGetOutputDataFormat = ma_spatializer_effect__on_get_data_format_out;
|
||||||
|
|
||||||
pSpatializer->pEngine = pConfig->pEngine;
|
pSpatializer->channelsIn = pConfig->channelsIn;
|
||||||
pSpatializer->format = pConfig->format;
|
pSpatializer->channelsOut = pConfig->channelsOut;
|
||||||
pSpatializer->channels = pConfig->channels;
|
|
||||||
pSpatializer->position = pConfig->position;
|
pSpatializer->position = pConfig->position;
|
||||||
pSpatializer->rotation = pConfig->rotation;
|
pSpatializer->rotation = pConfig->rotation;
|
||||||
|
|
||||||
@@ -8508,8 +8515,12 @@ MA_API ma_result ma_spatializer_process_pcm_frames(ma_spatializer* pSpatializer,
|
|||||||
return MA_INVALID_ARGS;
|
return MA_INVALID_ARGS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: Implement me. Just copying for now. */
|
/* Spatialization is not yet implemented. However, do do need to do channel conversion here. */
|
||||||
ma_copy_pcm_frames(pFramesOut, pFramesIn, frameCount, pSpatializer->format, pSpatializer->channels);
|
if (pSpatializer->channelsIn == pSpatializer->channelsOut) {
|
||||||
|
ma_copy_pcm_frames(pFramesOut, pFramesIn, frameCount, ma_format_f32, pSpatializer->channelsIn);
|
||||||
|
} else {
|
||||||
|
ma_convert_pcm_frames_channels_f32(pFramesOut, pSpatializer->channelsOut, pFramesIn, pSpatializer->channelsIn, frameCount);
|
||||||
|
}
|
||||||
|
|
||||||
return MA_SUCCESS;
|
return MA_SUCCESS;
|
||||||
}
|
}
|
||||||
@@ -8761,7 +8772,10 @@ static ma_result ma_engine_effect__on_process_pcm_frames__no_pre_effect_no_pitch
|
|||||||
|
|
||||||
/* Spatialization. */
|
/* Spatialization. */
|
||||||
if (pEngineEffect->isSpatial == MA_FALSE) {
|
if (pEngineEffect->isSpatial == MA_FALSE) {
|
||||||
/* Fast path. No spatialization. */
|
/* Fast path. No spatialization, but may still need to use it for channel conversion. */
|
||||||
|
if (pEngineEffect->spatializer.channelsIn != pEngineEffect->spatializer.channelsOut) {
|
||||||
|
pSubEffect[subEffectCount++] = &pEngineEffect->spatializer;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Slow path. Spatialization required. */
|
/* Slow path. Spatialization required. */
|
||||||
pSubEffect[subEffectCount++] = &pEngineEffect->spatializer;
|
pSubEffect[subEffectCount++] = &pEngineEffect->spatializer;
|
||||||
@@ -8925,7 +8939,7 @@ static ma_result ma_engine_effect__on_get_output_data_format(ma_effect* pEffect,
|
|||||||
return MA_SUCCESS;
|
return MA_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ma_result ma_engine_effect_init(ma_engine* pEngine, ma_engine_effect* pEffect)
|
static ma_result ma_engine_effect_init(ma_engine* pEngine, ma_uint32 inputChannels, ma_engine_effect* pEffect)
|
||||||
{
|
{
|
||||||
ma_result result;
|
ma_result result;
|
||||||
ma_panner_config pannerConfig;
|
ma_panner_config pannerConfig;
|
||||||
@@ -8948,25 +8962,25 @@ static ma_result ma_engine_effect_init(ma_engine* pEngine, ma_engine_effect* pEf
|
|||||||
pEffect->pitch = 1;
|
pEffect->pitch = 1;
|
||||||
pEffect->oldPitch = 1;
|
pEffect->oldPitch = 1;
|
||||||
|
|
||||||
pannerConfig = ma_panner_config_init(ma_format_f32, pEngine->channels);
|
pannerConfig = ma_panner_config_init(ma_format_f32, inputChannels);
|
||||||
result = ma_panner_init(&pannerConfig, &pEffect->panner);
|
result = ma_panner_init(&pannerConfig, &pEffect->panner);
|
||||||
if (result != MA_SUCCESS) {
|
if (result != MA_SUCCESS) {
|
||||||
return result; /* Failed to create the panner. */
|
return result; /* Failed to create the panner. */
|
||||||
}
|
}
|
||||||
|
|
||||||
spatializerConfig = ma_spatializer_config_init(pEngine, ma_format_f32, pEngine->channels);
|
spatializerConfig = ma_spatializer_config_init(inputChannels, pEngine->channels);
|
||||||
result = ma_spatializer_init(&spatializerConfig, &pEffect->spatializer);
|
result = ma_spatializer_init(&spatializerConfig, &pEffect->spatializer);
|
||||||
if (result != MA_SUCCESS) {
|
if (result != MA_SUCCESS) {
|
||||||
return result; /* Failed to create the spatializer. */
|
return result; /* Failed to create the spatializer. */
|
||||||
}
|
}
|
||||||
|
|
||||||
faderConfig = ma_fader_config_init(ma_format_f32, pEngine->channels, pEngine->sampleRate);
|
faderConfig = ma_fader_config_init(ma_format_f32, inputChannels, pEngine->sampleRate);
|
||||||
result = ma_fader_init(&faderConfig, &pEffect->fader);
|
result = ma_fader_init(&faderConfig, &pEffect->fader);
|
||||||
if (result != MA_SUCCESS) {
|
if (result != MA_SUCCESS) {
|
||||||
return result; /* Failed to create the fader. */
|
return result; /* Failed to create the fader. */
|
||||||
}
|
}
|
||||||
|
|
||||||
converterConfig = ma_data_converter_config_init(ma_format_f32, ma_format_f32, pEngine->channels, pEngine->channels, pEngine->sampleRate, pEngine->sampleRate);
|
converterConfig = ma_data_converter_config_init(ma_format_f32, ma_format_f32, inputChannels, pEngine->channels, pEngine->sampleRate, pEngine->sampleRate);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
TODO: A few things to figure out with the resampler:
|
TODO: A few things to figure out with the resampler:
|
||||||
@@ -8997,7 +9011,7 @@ static void ma_engine_effect_uninit(ma_engine* pEngine, ma_engine_effect* pEffec
|
|||||||
ma_data_converter_uninit(&pEffect->converter);
|
ma_data_converter_uninit(&pEffect->converter);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ma_result ma_engine_effect_reinit(ma_engine* pEngine, ma_engine_effect* pEffect)
|
static ma_result ma_engine_effect_reinit(ma_engine* pEngine, ma_uint32 channels, ma_engine_effect* pEffect)
|
||||||
{
|
{
|
||||||
/* This function assumes the data converter was previously initialized and needs to be uninitialized. */
|
/* This function assumes the data converter was previously initialized and needs to be uninitialized. */
|
||||||
MA_ASSERT(pEngine != NULL);
|
MA_ASSERT(pEngine != NULL);
|
||||||
@@ -9005,7 +9019,7 @@ static ma_result ma_engine_effect_reinit(ma_engine* pEngine, ma_engine_effect* p
|
|||||||
|
|
||||||
ma_engine_effect_uninit(pEngine, pEffect);
|
ma_engine_effect_uninit(pEngine, pEffect);
|
||||||
|
|
||||||
return ma_engine_effect_init(pEngine, pEffect);
|
return ma_engine_effect_init(pEngine, channels, pEffect);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Not used at the moment, but might re-enable this later. */
|
/* Not used at the moment, but might re-enable this later. */
|
||||||
@@ -9239,7 +9253,7 @@ MA_API ma_result ma_engine_node_init(const ma_engine_node_config* pConfig, const
|
|||||||
pEngineNode->pEngine = pConfig->pEngine;
|
pEngineNode->pEngine = pConfig->pEngine;
|
||||||
|
|
||||||
/* We need to initialize the engine effect. This is what will be applying our pan/pitch/fade/etc. This is temporary until we migrate away from the old ma_engine stuff. */
|
/* We need to initialize the engine effect. This is what will be applying our pan/pitch/fade/etc. This is temporary until we migrate away from the old ma_engine stuff. */
|
||||||
result = ma_engine_effect_init(pEngineNode->pEngine, &pEngineNode->effect);
|
result = ma_engine_effect_init(pEngineNode->pEngine, baseNodeConfig.inputChannels[0], &pEngineNode->effect);
|
||||||
if (result != MA_SUCCESS) {
|
if (result != MA_SUCCESS) {
|
||||||
ma_node_uninit(&pEngineNode->baseNode, pAllocationCallbacks);
|
ma_node_uninit(&pEngineNode->baseNode, pAllocationCallbacks);
|
||||||
return result;
|
return result;
|
||||||
@@ -9268,7 +9282,7 @@ MA_API ma_result ma_engine_node_reset(ma_engine_node* pEngineNode)
|
|||||||
|
|
||||||
/* The effect needs to be reset. This is temporary while we're in the process of migrating away from ma_effect. Later on it'll be a more streamlined reset. */
|
/* The effect needs to be reset. This is temporary while we're in the process of migrating away from ma_effect. Later on it'll be a more streamlined reset. */
|
||||||
ma_engine_effect_uninit(pEngineNode->pEngine, &pEngineNode->effect);
|
ma_engine_effect_uninit(pEngineNode->pEngine, &pEngineNode->effect);
|
||||||
return ma_engine_effect_init(pEngineNode->pEngine, &pEngineNode->effect);
|
return ma_engine_effect_init(pEngineNode->pEngine, pEngineNode->effect.spatializer.channelsIn, &pEngineNode->effect);
|
||||||
}
|
}
|
||||||
|
|
||||||
MA_API ma_result ma_engine_node_set_time(ma_engine_node* pEngineNode, ma_uint64 timeInFrames)
|
MA_API ma_result ma_engine_node_set_time(ma_engine_node* pEngineNode, ma_uint64 timeInFrames)
|
||||||
|
|||||||
Reference in New Issue
Block a user