Commit 3de7f5ca authored by David Reid's avatar David Reid

Add support for start delays to sound groups.

parent 56dbcb52
...@@ -38,6 +38,7 @@ int main(int argc, char** argv) ...@@ -38,6 +38,7 @@ int main(int argc, char** argv)
//ma_engine_sound_group_set_pan(&engine, NULL, -1); //ma_engine_sound_group_set_pan(&engine, NULL, -1);
ma_engine_sound_group_set_pitch(&engine, NULL, 1.0f); ma_engine_sound_group_set_pitch(&engine, NULL, 1.0f);
ma_engine_sound_group_set_fade_in(&engine, NULL, 4000); ma_engine_sound_group_set_fade_in(&engine, NULL, 4000);
ma_engine_sound_group_set_start_delay(&engine, NULL, 2000);
/*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, 2.0f); //ma_engine_sound_set_pitch(&engine, &sound, 2.0f);
......
...@@ -913,6 +913,8 @@ struct ma_sound_group ...@@ -913,6 +913,8 @@ struct ma_sound_group
ma_engine_effect effect; /* The main effect for panning, etc. This is set on the mixer at initialisation time. */ 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_uint64 runningTimeInEngineFrames; /* The amount of time the sound has been running in engine frames, including start delays. */
ma_uint64 startDelayInEngineFrames;
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. */
}; };
...@@ -998,6 +1000,7 @@ MA_API ma_result ma_engine_sound_group_set_effect(ma_engine* pEngine, ma_sound_g ...@@ -998,6 +1000,7 @@ MA_API ma_result ma_engine_sound_group_set_effect(ma_engine* pEngine, ma_sound_g
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_sound_group_set_pan(ma_engine* pEngine, ma_sound_group* pGroup, float pan);
MA_API ma_result ma_engine_sound_group_set_pitch(ma_engine* pEngine, ma_sound_group* pGroup, float pitch); MA_API ma_result ma_engine_sound_group_set_pitch(ma_engine* pEngine, ma_sound_group* pGroup, float pitch);
MA_API ma_result ma_engine_sound_group_set_fade_in(ma_engine* pEngine, ma_sound_group* pGroup, ma_uint64 fadeTimeInMilliseconds); MA_API ma_result ma_engine_sound_group_set_fade_in(ma_engine* pEngine, ma_sound_group* pGroup, ma_uint64 fadeTimeInMilliseconds);
MA_API ma_result ma_engine_sound_group_set_start_delay(ma_engine* pEngine, ma_sound_group* pGroup, ma_uint64 delayInMilliseconds);
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);
...@@ -5336,7 +5339,7 @@ static void ma_engine_mix_sound(ma_engine* pEngine, ma_sound_group* pGroup, ma_s ...@@ -5336,7 +5339,7 @@ static void ma_engine_mix_sound(ma_engine* pEngine, ma_sound_group* pGroup, ma_s
c89atomic_exchange_32(&pSound->atEnd, MA_TRUE); /* This will be set to false in ma_engine_sound_start(). */ c89atomic_exchange_32(&pSound->atEnd, MA_TRUE); /* This will be set to false in ma_engine_sound_start(). */
} }
pSound->runningTimeInEngineFrames += framesProcessed; pSound->runningTimeInEngineFrames += offsetInFrames + framesProcessed;
} else { } else {
/* The sound hasn't started yet. Just keep advancing time forward, but leave the data source alone. */ /* The sound hasn't started yet. Just keep advancing time forward, but leave the data source alone. */
pSound->runningTimeInEngineFrames += frameCount; pSound->runningTimeInEngineFrames += frameCount;
...@@ -5372,16 +5375,26 @@ static void ma_engine_mix_sound_group(ma_engine* pEngine, ma_sound_group* pGroup ...@@ -5372,16 +5375,26 @@ static void ma_engine_mix_sound_group(ma_engine* pEngine, ma_sound_group* pGroup
frameCountOut = frameCount; frameCountOut = frameCount;
frameCountIn = frameCount; frameCountIn = frameCount;
/* If the group is being delayed we don't want to mix anything. */
if ((pGroup->runningTimeInEngineFrames + frameCount) > pGroup->startDelayInEngineFrames) {
/* We're not delayed so we can mix or seek. In order to get frame-exact playback timing we need to start mixing from an offset. */
ma_uint64 offsetInFrames = 0;
if (pGroup->startDelayInEngineFrames > pGroup->runningTimeInEngineFrames) {
offsetInFrames = pGroup->startDelayInEngineFrames - pGroup->runningTimeInEngineFrames;
}
MA_ASSERT(offsetInFrames < frameCount);
/* We need to loop here to ensure we fill every frame. This won't necessarily be able to be done in one iteration due to resampling within the effect. */ /* We need to loop here to ensure we fill every frame. This won't necessarily be able to be done in one iteration due to resampling within the effect. */
totalFramesProcessed = 0; totalFramesProcessed = 0;
while (totalFramesProcessed < frameCount) { while (totalFramesProcessed < (frameCount - offsetInFrames)) {
frameCountOut = frameCount - totalFramesProcessed; frameCountOut = frameCount - offsetInFrames - totalFramesProcessed;
frameCountIn = frameCount - totalFramesProcessed; frameCountIn = frameCount - offsetInFrames - totalFramesProcessed;
/* Before can mix the group we need to mix it's children. */ /* Before can mix the group we need to mix it's children. */
result = ma_mixer_begin(&pGroup->mixer, pParentMixer, &frameCountOut, &frameCountIn); result = ma_mixer_begin(&pGroup->mixer, pParentMixer, &frameCountOut, &frameCountIn);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
return; break;
} }
MA_ASSERT(frameCountIn < 0xFFFFFFFF); MA_ASSERT(frameCountIn < 0xFFFFFFFF);
...@@ -5397,13 +5410,19 @@ static void ma_engine_mix_sound_group(ma_engine* pEngine, ma_sound_group* pGroup ...@@ -5397,13 +5410,19 @@ static void ma_engine_mix_sound_group(ma_engine* pEngine, ma_sound_group* pGroup
} }
/* Now mix into the parent. */ /* Now mix into the parent. */
result = ma_mixer_end(&pGroup->mixer, pParentMixer, pFramesOut, totalFramesProcessed); result = ma_mixer_end(&pGroup->mixer, pParentMixer, pFramesOut, offsetInFrames + totalFramesProcessed);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
return; break;
} }
totalFramesProcessed += frameCountOut; totalFramesProcessed += frameCountOut;
} }
pGroup->runningTimeInEngineFrames += offsetInFrames + totalFramesProcessed;
} else {
/* The group hasn't started yet. Just keep advancing time forward, but leave the data source alone. */
pGroup->runningTimeInEngineFrames += frameCount;
}
} }
static void ma_engine_listener__data_callback_fixed(ma_engine* pEngine, void* pFramesOut, ma_uint32 frameCount) static void ma_engine_listener__data_callback_fixed(ma_engine* pEngine, void* pFramesOut, ma_uint32 frameCount)
...@@ -6568,6 +6587,21 @@ MA_API ma_result ma_engine_sound_group_set_fade_in(ma_engine* pEngine, ma_sound_ ...@@ -6568,6 +6587,21 @@ MA_API ma_result ma_engine_sound_group_set_fade_in(ma_engine* pEngine, ma_sound_
return ma_dual_fader_set_fade(&pGroup->effect.fader, 0, 0, 1, pGroup->effect.fader.timeInFramesCur, pGroup->effect.fader.timeInFramesCur + (fadeTimeInMilliseconds * pGroup->effect.fader.config.sampleRate) / 1000); return ma_dual_fader_set_fade(&pGroup->effect.fader, 0, 0, 1, pGroup->effect.fader.timeInFramesCur, pGroup->effect.fader.timeInFramesCur + (fadeTimeInMilliseconds * pGroup->effect.fader.config.sampleRate) / 1000);
} }
MA_API ma_result ma_engine_sound_group_set_start_delay(ma_engine* pEngine, ma_sound_group* pGroup, ma_uint64 delayInMilliseconds)
{
if (pEngine == NULL) {
return MA_INVALID_ARGS;
}
if (pGroup == NULL) {
pGroup = &pEngine->masterSoundGroup;
}
pGroup->startDelayInEngineFrames = (pEngine->sampleRate * delayInMilliseconds) / 1000;
return MA_SUCCESS;
}
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