Commit ff22dc3c authored by David Reid's avatar David Reid

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.
parent 400aaf58
...@@ -48,7 +48,7 @@ int main(int argc, char** argv) ...@@ -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) {
......
...@@ -1487,22 +1487,20 @@ MA_API ma_result ma_panner_set_pan(ma_panner* pPanner, float pan); ...@@ -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,17 +8426,16 @@ MA_API ma_result ma_panner_set_pan(ma_panner* pPanner, float pan) ...@@ -8428,17 +8426,16 @@ 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);
return config; return config;
} }
...@@ -8464,12 +8461,23 @@ static ma_result ma_spatializer_effect__on_process_pcm_frames(ma_effect* pEffect ...@@ -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,14 +8498,13 @@ MA_API ma_result ma_spatializer_init(const ma_spatializer_config* pConfig, ma_sp ...@@ -8490,14 +8498,13 @@ 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;
return MA_SUCCESS; return MA_SUCCESS;
} }
...@@ -8508,8 +8515,12 @@ MA_API ma_result ma_spatializer_process_pcm_frames(ma_spatializer* pSpatializer, ...@@ -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 ...@@ -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, ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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) ...@@ -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)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment