Commit 042e1b95 authored by David Reid's avatar David Reid

Add support for panning to sound groups.

parent 340dbcc3
...@@ -34,15 +34,17 @@ int main(int argc, char** argv) ...@@ -34,15 +34,17 @@ int main(int argc, char** argv)
} }
/*ma_data_source_seek_to_pcm_frame(sound.pDataSource, 5000000);*/ /*ma_data_source_seek_to_pcm_frame(sound.pDataSource, 5000000);*/
ma_engine_sound_group_set_pan(&engine, NULL, -1);
/*ma_engine_sound_set_volume(&engine, &sound, 0.25f);*/ /*ma_engine_sound_set_volume(&engine, &sound, 0.25f);*/
ma_engine_sound_set_pitch(&engine, &sound, 1.0f); ma_engine_sound_set_pitch(&engine, &sound, 1.0f);
ma_engine_sound_set_pan(&engine, &sound, 0.0f); ma_engine_sound_set_pan(&engine, &sound, 0.0f);
ma_engine_sound_set_looping(&engine, &sound, MA_TRUE); ma_engine_sound_set_looping(&engine, &sound, MA_TRUE);
//ma_engine_sound_seek_to_pcm_frame(&engine, &sound, 6000000); //ma_engine_sound_seek_to_pcm_frame(&engine, &sound, 6000000);
ma_engine_sound_set_start_delay(&engine, &sound, 1110); //ma_engine_sound_set_start_delay(&engine, &sound, 1110);
ma_engine_sound_set_fade_in(&engine, &sound, 2000); //ma_engine_sound_set_fade_in(&engine, &sound, 2000);
ma_engine_sound_set_fade_out(&engine, &sound, 2000); //ma_engine_sound_set_fade_out(&engine, &sound, 2000);
ma_engine_sound_start(&engine, &sound); ma_engine_sound_start(&engine, &sound);
ma_sleep(5000); ma_sleep(5000);
......
...@@ -910,6 +910,7 @@ struct ma_sound_group ...@@ -910,6 +910,7 @@ struct ma_sound_group
ma_sound_group* pPrevSibling; ma_sound_group* pPrevSibling;
ma_sound_group* pNextSibling; ma_sound_group* pNextSibling;
ma_sound* pFirstSoundInGroup; ma_sound* pFirstSoundInGroup;
ma_engine_effect effect; /* The main effect for panning, etc. This is set on the mixer at initialisation time. */
ma_mixer mixer; ma_mixer mixer;
ma_mutex lock; /* Only used by ma_engine_sound_init_*() and ma_engine_sound_uninit(). Not used in the mixing thread. */ ma_mutex lock; /* Only used by ma_engine_sound_init_*() and ma_engine_sound_uninit(). Not used in the mixing thread. */
ma_bool32 isPlaying; /* True by default. Sound groups can be stopped with ma_engine_sound_stop() and resumed with ma_engine_sound_start(). Also affects children. */ ma_bool32 isPlaying; /* True by default. Sound groups can be stopped with ma_engine_sound_stop() and resumed with ma_engine_sound_start(). Also affects children. */
...@@ -971,11 +972,11 @@ MA_API ma_result ma_engine_sound_start(ma_engine* pEngine, ma_sound* pSound); ...@@ -971,11 +972,11 @@ MA_API ma_result ma_engine_sound_start(ma_engine* pEngine, ma_sound* pSound);
MA_API ma_result ma_engine_sound_stop(ma_engine* pEngine, ma_sound* pSound); MA_API ma_result ma_engine_sound_stop(ma_engine* pEngine, ma_sound* pSound);
MA_API ma_result ma_engine_sound_set_volume(ma_engine* pEngine, ma_sound* pSound, float volume); MA_API ma_result ma_engine_sound_set_volume(ma_engine* pEngine, ma_sound* pSound, float volume);
MA_API ma_result ma_engine_sound_set_gain_db(ma_engine* pEngine, ma_sound* pSound, float gainDB); MA_API ma_result ma_engine_sound_set_gain_db(ma_engine* pEngine, ma_sound* pSound, float gainDB);
MA_API ma_result ma_engine_sound_set_effect(ma_engine* pEngine, ma_sound* pSound, ma_effect* pEffect);
MA_API ma_result ma_engine_sound_set_pan(ma_engine* pEngine, ma_sound* pSound, float pan); MA_API ma_result ma_engine_sound_set_pan(ma_engine* pEngine, ma_sound* pSound, float pan);
MA_API ma_result ma_engine_sound_set_pitch(ma_engine* pEngine, ma_sound* pSound, float pitch); MA_API ma_result ma_engine_sound_set_pitch(ma_engine* pEngine, ma_sound* pSound, float pitch);
MA_API ma_result ma_engine_sound_set_position(ma_engine* pEngine, ma_sound* pSound, ma_vec3 position); MA_API ma_result ma_engine_sound_set_position(ma_engine* pEngine, ma_sound* pSound, ma_vec3 position);
MA_API ma_result ma_engine_sound_set_rotation(ma_engine* pEngine, ma_sound* pSound, ma_quat rotation); MA_API ma_result ma_engine_sound_set_rotation(ma_engine* pEngine, ma_sound* pSound, ma_quat rotation);
MA_API ma_result ma_engine_sound_set_effect(ma_engine* pEngine, ma_sound* pSound, ma_effect* pEffect);
MA_API ma_result ma_engine_sound_set_looping(ma_engine* pEngine, ma_sound* pSound, ma_bool32 isLooping); MA_API ma_result ma_engine_sound_set_looping(ma_engine* pEngine, ma_sound* pSound, ma_bool32 isLooping);
MA_API ma_result ma_engine_sound_set_fade_in(ma_engine* pEngine, ma_sound* pSound, ma_uint64 fadeTimeInMilliseconds); MA_API ma_result ma_engine_sound_set_fade_in(ma_engine* pEngine, ma_sound* pSound, ma_uint64 fadeTimeInMilliseconds);
MA_API ma_result ma_engine_sound_set_fade_out(ma_engine* pEngine, ma_sound* pSound, ma_uint64 fadeTimeInMilliseconds); MA_API ma_result ma_engine_sound_set_fade_out(ma_engine* pEngine, ma_sound* pSound, ma_uint64 fadeTimeInMilliseconds);
...@@ -994,6 +995,7 @@ MA_API ma_result ma_engine_sound_group_stop(ma_engine* pEngine, ma_sound_group* ...@@ -994,6 +995,7 @@ MA_API ma_result ma_engine_sound_group_stop(ma_engine* pEngine, ma_sound_group*
MA_API ma_result ma_engine_sound_group_set_volume(ma_engine* pEngine, ma_sound_group* pGroup, float volume); MA_API ma_result ma_engine_sound_group_set_volume(ma_engine* pEngine, ma_sound_group* pGroup, float volume);
MA_API ma_result ma_engine_sound_group_set_gain_db(ma_engine* pEngine, ma_sound_group* pGroup, float gainDB); MA_API ma_result ma_engine_sound_group_set_gain_db(ma_engine* pEngine, ma_sound_group* pGroup, float gainDB);
MA_API ma_result ma_engine_sound_group_set_effect(ma_engine* pEngine, ma_sound_group* pGroup, ma_effect* pEffect); MA_API ma_result ma_engine_sound_group_set_effect(ma_engine* pEngine, ma_sound_group* pGroup, ma_effect* pEffect);
MA_API ma_result ma_engine_sound_group_set_pan(ma_engine* pEngine, ma_sound_group* pGroup, float pan);
MA_API ma_result ma_engine_listener_set_position(ma_engine* pEngine, ma_vec3 position); MA_API ma_result ma_engine_listener_set_position(ma_engine* pEngine, ma_vec3 position);
MA_API ma_result ma_engine_listener_set_rotation(ma_engine* pEngine, ma_quat rotation); MA_API ma_result ma_engine_listener_set_rotation(ma_engine* pEngine, ma_quat rotation);
...@@ -4279,13 +4281,27 @@ static void ma_stereo_balance_pcm_frames_f32(float* pFramesOut, const float* pFr ...@@ -4279,13 +4281,27 @@ static void ma_stereo_balance_pcm_frames_f32(float* pFramesOut, const float* pFr
if (pan > 0) { if (pan > 0) {
float factor = 1.0f - pan; float factor = 1.0f - pan;
for (iFrame = 0; iFrame < frameCount; iFrame += 1) { if (pFramesOut == pFramesIn) {
pFramesOut[iFrame*2 + 0] = pFramesIn[iFrame*2 + 0] * factor; for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
pFramesOut[iFrame*2 + 0] = pFramesIn[iFrame*2 + 0] * factor;
}
} else {
for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
pFramesOut[iFrame*2 + 0] = pFramesIn[iFrame*2 + 0] * factor;
pFramesOut[iFrame*2 + 1] = pFramesIn[iFrame*2 + 1];
}
} }
} else { } else {
float factor = 1.0f + pan; float factor = 1.0f + pan;
for (iFrame = 0; iFrame < frameCount; iFrame += 1) { if (pFramesOut == pFramesIn) {
pFramesOut[iFrame*2 + 1] = pFramesIn[iFrame*2 + 1] * factor; for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
pFramesOut[iFrame*2 + 1] = pFramesIn[iFrame*2 + 1] * factor;
}
} else {
for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
pFramesOut[iFrame*2 + 0] = pFramesIn[iFrame*2 + 0];
pFramesOut[iFrame*2 + 1] = pFramesIn[iFrame*2 + 1] * factor;
}
} }
} }
} }
...@@ -4880,7 +4896,11 @@ static ma_result ma_engine_effect__on_process_pcm_frames__no_pre_effect_no_pitch ...@@ -4880,7 +4896,11 @@ static ma_result ma_engine_effect__on_process_pcm_frames__no_pre_effect_no_pitch
static ma_result ma_engine_effect__on_process_pcm_frames__no_pre_effect(ma_engine_effect* pEngineEffect, const void* pFramesIn, ma_uint64* pFrameCountIn, void* pFramesOut, ma_uint64* pFrameCountOut) static ma_result ma_engine_effect__on_process_pcm_frames__no_pre_effect(ma_engine_effect* pEngineEffect, const void* pFramesIn, ma_uint64* pFrameCountIn, void* pFramesOut, ma_uint64* pFrameCountOut)
{ {
ma_bool32 isPitchingRequired = MA_TRUE; ma_bool32 isPitchingRequired = MA_FALSE;
if (pEngineEffect->converter.hasResampler && pEngineEffect->pitch != 1) {
isPitchingRequired = MA_TRUE;
}
/* /*
This will be called if either there is no pre-effect or the pre-effect has already been processed. We can safely assume the input and output data in the engine's format so no This will be called if either there is no pre-effect or the pre-effect has already been processed. We can safely assume the input and output data in the engine's format so no
...@@ -5954,6 +5974,17 @@ MA_API ma_result ma_engine_sound_set_gain_db(ma_engine* pEngine, ma_sound* pSoun ...@@ -5954,6 +5974,17 @@ MA_API ma_result ma_engine_sound_set_gain_db(ma_engine* pEngine, ma_sound* pSoun
return ma_engine_sound_set_volume(pEngine, pSound, ma_gain_db_to_factor(gainDB)); return ma_engine_sound_set_volume(pEngine, pSound, ma_gain_db_to_factor(gainDB));
} }
MA_API ma_result ma_engine_sound_set_effect(ma_engine* pEngine, ma_sound* pSound, ma_effect* pEffect)
{
if (pEngine == NULL || pSound == NULL) {
return MA_INVALID_ARGS;
}
pSound->effect.pPreEffect = pEffect;
return MA_SUCCESS;
}
MA_API ma_result ma_engine_sound_set_pitch(ma_engine* pEngine, ma_sound* pSound, float pitch) MA_API ma_result ma_engine_sound_set_pitch(ma_engine* pEngine, ma_sound* pSound, float pitch)
{ {
if (pEngine == NULL || pSound == NULL) { if (pEngine == NULL || pSound == NULL) {
...@@ -5992,17 +6023,6 @@ MA_API ma_result ma_engine_sound_set_rotation(ma_engine* pEngine, ma_sound* pSou ...@@ -5992,17 +6023,6 @@ MA_API ma_result ma_engine_sound_set_rotation(ma_engine* pEngine, ma_sound* pSou
return ma_spatializer_set_rotation(&pSound->effect.spatializer, rotation); return ma_spatializer_set_rotation(&pSound->effect.spatializer, rotation);
} }
MA_API ma_result ma_engine_sound_set_effect(ma_engine* pEngine, ma_sound* pSound, ma_effect* pEffect)
{
if (pEngine == NULL || pSound == NULL) {
return MA_INVALID_ARGS;
}
pSound->effect.pPreEffect = pEffect;
return MA_SUCCESS;
}
MA_API ma_result ma_engine_sound_set_looping(ma_engine* pEngine, ma_sound* pSound, ma_bool32 isLooping) MA_API ma_result ma_engine_sound_set_looping(ma_engine* pEngine, ma_sound* pSound, ma_bool32 isLooping)
{ {
if (pEngine == NULL || pSound == NULL) { if (pEngine == NULL || pSound == NULL) {
...@@ -6325,18 +6345,30 @@ MA_API ma_result ma_engine_sound_group_init(ma_engine* pEngine, ma_sound_group* ...@@ -6325,18 +6345,30 @@ MA_API ma_result ma_engine_sound_group_init(ma_engine* pEngine, ma_sound_group*
/* TODO: Look at the possibility of allowing groups to use a different format to the primary data format. Makes mixing and group management much more complicated. */ /* TODO: Look at the possibility of allowing groups to use a different format to the primary data format. Makes mixing and group management much more complicated. */
/* For handling panning, etc. we'll need an engine effect. */
result = ma_engine_effect_init(pEngine, &pGroup->effect);
if (result != MA_SUCCESS) {
return result; /* Failed to initialize the engine effect. */
}
/* The sound group needs a mixer. */ /* The sound group needs a mixer. */
mixerConfig = ma_mixer_config_init(pEngine->format, pEngine->channels, pEngine->periodSizeInFrames, NULL, &pEngine->allocationCallbacks); mixerConfig = ma_mixer_config_init(pEngine->format, pEngine->channels, pEngine->periodSizeInFrames, NULL, &pEngine->allocationCallbacks);
result = ma_mixer_init(&mixerConfig, &pGroup->mixer); result = ma_mixer_init(&mixerConfig, &pGroup->mixer);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
ma_engine_effect_uninit(pEngine, &pGroup->effect);
return result; return result;
} }
/* The mixer's effect is always set to the main engine effect. */
ma_mixer_set_effect(&pGroup->mixer, &pGroup->effect);
/* Attach the sound group to it's parent if it has one (this will only happen if it's the master group). */ /* Attach the sound group to it's parent if it has one (this will only happen if it's the master group). */
if (pParentGroup != NULL) { if (pParentGroup != NULL) {
result = ma_engine_sound_group_attach(pEngine, pGroup, pParentGroup); result = ma_engine_sound_group_attach(pEngine, pGroup, pParentGroup);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
ma_mixer_uninit(&pGroup->mixer); ma_mixer_uninit(&pGroup->mixer);
ma_engine_effect_uninit(pEngine, &pGroup->effect);
return result; return result;
} }
} else { } else {
...@@ -6351,6 +6383,7 @@ MA_API ma_result ma_engine_sound_group_init(ma_engine* pEngine, ma_sound_group* ...@@ -6351,6 +6383,7 @@ MA_API ma_result ma_engine_sound_group_init(ma_engine* pEngine, ma_sound_group*
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
ma_engine_sound_group_detach(pEngine, pGroup); ma_engine_sound_group_detach(pEngine, pGroup);
ma_mixer_uninit(&pGroup->mixer); ma_mixer_uninit(&pGroup->mixer);
ma_engine_effect_uninit(pEngine, &pGroup->effect);
return result; return result;
} }
...@@ -6395,6 +6428,8 @@ MA_API void ma_engine_sound_group_uninit(ma_engine* pEngine, ma_sound_group* pGr ...@@ -6395,6 +6428,8 @@ MA_API void ma_engine_sound_group_uninit(ma_engine* pEngine, ma_sound_group* pGr
ma_mixer_uninit(&pGroup->mixer); ma_mixer_uninit(&pGroup->mixer);
ma_mutex_uninit(&pGroup->lock); ma_mutex_uninit(&pGroup->lock);
ma_engine_effect_uninit(pEngine, &pGroup->effect);
} }
MA_API ma_result ma_engine_sound_group_start(ma_engine* pEngine, ma_sound_group* pGroup) MA_API ma_result ma_engine_sound_group_start(ma_engine* pEngine, ma_sound_group* pGroup)
...@@ -6462,12 +6497,23 @@ MA_API ma_result ma_engine_sound_group_set_effect(ma_engine* pEngine, ma_sound_g ...@@ -6462,12 +6497,23 @@ MA_API ma_result ma_engine_sound_group_set_effect(ma_engine* pEngine, ma_sound_g
pGroup = &pEngine->masterSoundGroup; pGroup = &pEngine->masterSoundGroup;
} }
/* The effect is set on the mixer. */ pGroup->effect.pPreEffect = pEffect;
ma_mixer_set_effect(&pGroup->mixer, pEffect);
return MA_SUCCESS; return MA_SUCCESS;
} }
MA_API ma_result ma_engine_sound_group_set_pan(ma_engine* pEngine, ma_sound_group* pGroup, float pan)
{
if (pEngine == NULL) {
return MA_INVALID_ARGS;
}
if (pGroup == NULL) {
pGroup = &pEngine->masterSoundGroup;
}
return ma_panner_set_pan(&pGroup->effect.panner, pan);
}
MA_API ma_result ma_engine_listener_set_position(ma_engine* pEngine, ma_vec3 position) MA_API ma_result ma_engine_listener_set_position(ma_engine* pEngine, ma_vec3 position)
......
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