mirror of
https://github.com/mackron/miniaudio.git
synced 2026-04-23 08:44:04 +02:00
Add support for configuring automatic resetting of fade points.
This is useful for enabling or disabling fading around loop transitions.
This commit is contained in:
@@ -65,10 +65,12 @@ int main(int argc, char** argv)
|
|||||||
/*ma_sound_set_volume(&sound, 0.25f);*/
|
/*ma_sound_set_volume(&sound, 0.25f);*/
|
||||||
//ma_sound_set_pitch(&sound, 2.0f);
|
//ma_sound_set_pitch(&sound, 2.0f);
|
||||||
ma_sound_set_pan(&sound, 0.0f);
|
ma_sound_set_pan(&sound, 0.0f);
|
||||||
//ma_sound_set_looping(&sound, MA_TRUE);
|
ma_sound_set_looping(&sound, MA_TRUE);
|
||||||
//ma_sound_seek_to_pcm_frame(&sound, 6000000);
|
//ma_sound_seek_to_pcm_frame(&sound, 6000000);
|
||||||
//ma_sound_set_start_delay(&sound, 1110);
|
//ma_sound_set_start_delay(&sound, 1110);
|
||||||
ma_sound_set_fade_point_in_milliseconds(&sound, 0, 0, 1, 0, 2000);
|
ma_sound_set_fade_point_in_milliseconds(&sound, 0, 0, 1, 0, 2000);
|
||||||
|
ma_sound_set_fade_point_auto_reset(&sound, 0, MA_FALSE); /* Enable fading around loop transitions. */
|
||||||
|
ma_sound_set_fade_point_auto_reset(&sound, 1, MA_FALSE);
|
||||||
ma_sound_set_stop_delay(&sound, 1000);
|
ma_sound_set_stop_delay(&sound, 1000);
|
||||||
ma_sound_start(&sound);
|
ma_sound_start(&sound);
|
||||||
|
|
||||||
|
|||||||
+49
-10
@@ -841,6 +841,7 @@ typedef struct
|
|||||||
float volumeEnd;
|
float volumeEnd;
|
||||||
ma_uint64 timeInFramesBeg;
|
ma_uint64 timeInFramesBeg;
|
||||||
ma_uint64 timeInFramesEnd;
|
ma_uint64 timeInFramesEnd;
|
||||||
|
ma_bool32 autoReset; /* Controls whether or not the fade point should automatically reset once the end of the fade point has been reached. */
|
||||||
} state[2];
|
} state[2];
|
||||||
} ma_dual_fader_config;
|
} ma_dual_fader_config;
|
||||||
|
|
||||||
@@ -863,6 +864,7 @@ MA_API ma_bool32 ma_dual_fader_is_time_past_fade(const ma_dual_fader* pFader, ma
|
|||||||
MA_API ma_bool32 ma_dual_fader_is_time_past_both_fades(const ma_dual_fader* pFader);
|
MA_API ma_bool32 ma_dual_fader_is_time_past_both_fades(const ma_dual_fader* pFader);
|
||||||
MA_API ma_bool32 ma_dual_fader_is_in_fade(const ma_dual_fader* pFader, ma_uint32 index);
|
MA_API ma_bool32 ma_dual_fader_is_in_fade(const ma_dual_fader* pFader, ma_uint32 index);
|
||||||
MA_API ma_result ma_dual_fader_reset_fade(ma_dual_fader* pFader, ma_uint32 index); /* Essentially disables fading for one of the sub-fades. To enable again, call ma_dual_fader_set_fade(). */
|
MA_API ma_result ma_dual_fader_reset_fade(ma_dual_fader* pFader, ma_uint32 index); /* Essentially disables fading for one of the sub-fades. To enable again, call ma_dual_fader_set_fade(). */
|
||||||
|
MA_API ma_result ma_dual_fader_set_auto_reset(ma_dual_fader* pFader, ma_uint32 index, ma_bool32 autoReset);
|
||||||
|
|
||||||
|
|
||||||
/* All of the proprties supported by the engine are handled via an effect. */
|
/* All of the proprties supported by the engine are handled via an effect. */
|
||||||
@@ -994,6 +996,7 @@ MA_API ma_result ma_sound_set_rotation(ma_sound* pSound, ma_quat rotation);
|
|||||||
MA_API ma_result ma_sound_set_looping(ma_sound* pSound, ma_bool32 isLooping);
|
MA_API ma_result ma_sound_set_looping(ma_sound* pSound, ma_bool32 isLooping);
|
||||||
MA_API ma_result ma_sound_set_fade_point_in_frames(ma_sound* pSound, ma_uint32 fadePointIndex, float volumeBeg, float volumeEnd, ma_uint64 timeInFramesBeg, ma_uint64 timeInFramesEnd);
|
MA_API ma_result ma_sound_set_fade_point_in_frames(ma_sound* pSound, ma_uint32 fadePointIndex, float volumeBeg, float volumeEnd, ma_uint64 timeInFramesBeg, ma_uint64 timeInFramesEnd);
|
||||||
MA_API ma_result ma_sound_set_fade_point_in_milliseconds(ma_sound* pSound, ma_uint32 fadePointIndex, float volumeBeg, float volumeEnd, ma_uint64 timeInMillisecondsBeg, ma_uint64 timeInMillisecondsEnd);
|
MA_API ma_result ma_sound_set_fade_point_in_milliseconds(ma_sound* pSound, ma_uint32 fadePointIndex, float volumeBeg, float volumeEnd, ma_uint64 timeInMillisecondsBeg, ma_uint64 timeInMillisecondsEnd);
|
||||||
|
MA_API ma_result ma_sound_set_fade_point_auto_reset(ma_sound* pSound, ma_uint32 fadePointIndex, ma_bool32 autoReset);
|
||||||
MA_API ma_result ma_sound_set_start_delay(ma_sound* pSound, ma_uint64 delayInMilliseconds);
|
MA_API ma_result ma_sound_set_start_delay(ma_sound* pSound, ma_uint64 delayInMilliseconds);
|
||||||
MA_API ma_result ma_sound_set_stop_delay(ma_sound* pSound, ma_uint64 delayInMilliseconds);
|
MA_API ma_result ma_sound_set_stop_delay(ma_sound* pSound, ma_uint64 delayInMilliseconds);
|
||||||
MA_API ma_bool32 ma_sound_at_end(const ma_sound* pSound);
|
MA_API ma_bool32 ma_sound_at_end(const ma_sound* pSound);
|
||||||
@@ -1014,6 +1017,7 @@ MA_API ma_result ma_sound_group_set_pan(ma_sound_group* pGroup, float pan);
|
|||||||
MA_API ma_result ma_sound_group_set_pitch(ma_sound_group* pGroup, float pitch);
|
MA_API ma_result ma_sound_group_set_pitch(ma_sound_group* pGroup, float pitch);
|
||||||
MA_API ma_result ma_sound_group_set_fade_point_in_frames(ma_sound_group* pGroup, ma_uint32 fadePointIndex, float volumeBeg, float volumeEnd, ma_uint64 timeInFramesBeg, ma_uint64 timeInFramesEnd);
|
MA_API ma_result ma_sound_group_set_fade_point_in_frames(ma_sound_group* pGroup, ma_uint32 fadePointIndex, float volumeBeg, float volumeEnd, ma_uint64 timeInFramesBeg, ma_uint64 timeInFramesEnd);
|
||||||
MA_API ma_result ma_sound_group_set_fade_point_in_milliseconds(ma_sound_group* pGroup, ma_uint32 fadePointIndex, float volumeBeg, float volumeEnd, ma_uint64 timeInMillisecondsBeg, ma_uint64 timeInMillisecondsEnd);
|
MA_API ma_result ma_sound_group_set_fade_point_in_milliseconds(ma_sound_group* pGroup, ma_uint32 fadePointIndex, float volumeBeg, float volumeEnd, ma_uint64 timeInMillisecondsBeg, ma_uint64 timeInMillisecondsEnd);
|
||||||
|
MA_API ma_result ma_sound_group_set_fade_point_auto_reset(ma_sound_group* pGroup, ma_uint32 fadePointIndex, ma_bool32 autoReset);
|
||||||
MA_API ma_result ma_sound_group_set_start_delay(ma_sound_group* pGroup, ma_uint64 delayInMilliseconds);
|
MA_API ma_result ma_sound_group_set_start_delay(ma_sound_group* pGroup, ma_uint64 delayInMilliseconds);
|
||||||
MA_API ma_result ma_sound_group_set_stop_delay(ma_sound_group* pGroup, ma_uint64 delayInMilliseconds);
|
MA_API ma_result ma_sound_group_set_stop_delay(ma_sound_group* pGroup, ma_uint64 delayInMilliseconds);
|
||||||
MA_API ma_result ma_sound_group_get_time_in_frames(const ma_sound_group* pGroup, ma_uint64* pTimeInFrames);
|
MA_API ma_result ma_sound_group_get_time_in_frames(const ma_sound_group* pGroup, ma_uint64* pTimeInFrames);
|
||||||
@@ -4569,10 +4573,12 @@ MA_API ma_dual_fader_config ma_dual_fader_config_init(ma_format format, ma_uint3
|
|||||||
config.state[0].volumeEnd = 1;
|
config.state[0].volumeEnd = 1;
|
||||||
config.state[0].timeInFramesBeg = 0;
|
config.state[0].timeInFramesBeg = 0;
|
||||||
config.state[0].timeInFramesEnd = 0;
|
config.state[0].timeInFramesEnd = 0;
|
||||||
|
config.state[0].autoReset = MA_TRUE;
|
||||||
config.state[1].volumeBeg = 1;
|
config.state[1].volumeBeg = 1;
|
||||||
config.state[1].volumeEnd = 1;
|
config.state[1].volumeEnd = 1;
|
||||||
config.state[1].timeInFramesBeg = 0;
|
config.state[1].timeInFramesBeg = 0;
|
||||||
config.state[1].timeInFramesEnd = 0;
|
config.state[1].timeInFramesEnd = 0;
|
||||||
|
config.state[1].autoReset = MA_TRUE;
|
||||||
|
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
@@ -4698,6 +4704,10 @@ MA_API ma_result ma_dual_fader_process_pcm_frames_by_index(ma_dual_fader* pFader
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pFader->config.state[index].autoReset && ma_dual_fader_is_time_past_fade(pFader, index)) {
|
||||||
|
ma_dual_fader_reset_fade(pFader, index);
|
||||||
|
}
|
||||||
|
|
||||||
return MA_SUCCESS;
|
return MA_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4835,6 +4845,17 @@ MA_API ma_result ma_dual_fader_reset_fade(ma_dual_fader* pFader, ma_uint32 index
|
|||||||
return MA_SUCCESS;
|
return MA_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MA_API ma_result ma_dual_fader_set_auto_reset(ma_dual_fader* pFader, ma_uint32 index, ma_bool32 autoReset)
|
||||||
|
{
|
||||||
|
if (pFader == NULL) {
|
||||||
|
return MA_INVALID_ARGS;
|
||||||
|
}
|
||||||
|
|
||||||
|
pFader->config.state[index].autoReset = autoReset;
|
||||||
|
|
||||||
|
return MA_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -5300,7 +5321,10 @@ static void ma_engine_mix_sound(ma_engine* pEngine, ma_sound_group* pGroup, ma_s
|
|||||||
/* If the sound is being delayed we don't want to mix anything, nor do we want to advance time forward from the perspective of the data source. */
|
/* If the sound is being delayed we don't want to mix anything, nor do we want to advance time forward from the perspective of the data source. */
|
||||||
if ((pSound->runningTimeInEngineFrames + frameCount) > pSound->startDelayInEngineFrames) {
|
if ((pSound->runningTimeInEngineFrames + frameCount) > pSound->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. */
|
/* 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;
|
ma_uint64 currentTimeInFrames;
|
||||||
|
ma_uint64 offsetInFrames;
|
||||||
|
|
||||||
|
offsetInFrames = 0;
|
||||||
if (pSound->startDelayInEngineFrames > pSound->runningTimeInEngineFrames) {
|
if (pSound->startDelayInEngineFrames > pSound->runningTimeInEngineFrames) {
|
||||||
offsetInFrames = pSound->startDelayInEngineFrames - pSound->runningTimeInEngineFrames;
|
offsetInFrames = pSound->startDelayInEngineFrames - pSound->runningTimeInEngineFrames;
|
||||||
}
|
}
|
||||||
@@ -5314,17 +5338,14 @@ static void ma_engine_mix_sound(ma_engine* pEngine, ma_sound_group* pGroup, ma_s
|
|||||||
*/
|
*/
|
||||||
result = ma_mixer_mix_data_source(&pGroup->mixer, pSound->pDataSource, offsetInFrames, (frameCount - offsetInFrames), &framesProcessed, pSound->volume, &pSound->effect, pSound->isLooping);
|
result = ma_mixer_mix_data_source(&pGroup->mixer, pSound->pDataSource, offsetInFrames, (frameCount - offsetInFrames), &framesProcessed, pSound->volume, &pSound->effect, pSound->isLooping);
|
||||||
|
|
||||||
#if 0
|
/*
|
||||||
/* We're not fading out. For the benefit of looping sounds, we need to make sure the timer is set properly on the fader so that fading works across loop transitions. */
|
For the benefit of the main effect we need to ensure the local time is updated explicitly. This is required for allowing time-based effects to
|
||||||
/* TODO: Add support for controlling fading between loop transitions. Maybe have an auto-reset flag in ma_dual_fader which resets the fade once it's got past the fade time? */
|
support loop transitions properly.
|
||||||
if (pSound->isLooping) {
|
*/
|
||||||
ma_uint64 currentTimeInFrames;
|
result = ma_sound_get_cursor_in_pcm_frames(pSound, ¤tTimeInFrames);
|
||||||
result = ma_sound_get_cursor_in_pcm_frames(pEngine, pSound, ¤tTimeInFrames);
|
|
||||||
if (result == MA_SUCCESS) {
|
if (result == MA_SUCCESS) {
|
||||||
ma_engine_effect_set_time(&pSound->effect, currentTimeInFrames);
|
ma_engine_effect_set_time(&pSound->effect, currentTimeInFrames);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* If we reached the end of the sound we'll want to mark it as at the end and stop it. This should never be returned for looping sounds. */
|
/* If we reached the end of the sound we'll want to mark it as at the end and stop it. This should never be returned for looping sounds. */
|
||||||
if (result == MA_AT_END) {
|
if (result == MA_AT_END) {
|
||||||
@@ -5532,7 +5553,7 @@ static ma_result ma_engine_listener_init(ma_engine* pEngine, const ma_device_id*
|
|||||||
deviceConfig.periodSizeInFrames = pEngine->periodSizeInFrames;
|
deviceConfig.periodSizeInFrames = pEngine->periodSizeInFrames;
|
||||||
deviceConfig.periodSizeInMilliseconds = pEngine->periodSizeInMilliseconds;
|
deviceConfig.periodSizeInMilliseconds = pEngine->periodSizeInMilliseconds;
|
||||||
deviceConfig.noPreZeroedOutputBuffer = MA_TRUE; /* We'll always be outputting to every frame in the callback so there's no need for a pre-silenced buffer. */
|
deviceConfig.noPreZeroedOutputBuffer = MA_TRUE; /* We'll always be outputting to every frame in the callback so there's no need for a pre-silenced buffer. */
|
||||||
deviceConfig.noClip = MA_TRUE; /* The mixing engine here will do clipping for us. */
|
deviceConfig.noClip = MA_TRUE; /* The mixing engine will do clipping itself. */
|
||||||
|
|
||||||
result = ma_device_init(&pEngine->context, &deviceConfig, &pListener->device);
|
result = ma_device_init(&pEngine->context, &deviceConfig, &pListener->device);
|
||||||
if (result != MA_SUCCESS) {
|
if (result != MA_SUCCESS) {
|
||||||
@@ -6261,6 +6282,15 @@ MA_API ma_result ma_sound_set_fade_point_in_milliseconds(ma_sound* pSound, ma_ui
|
|||||||
return ma_sound_set_fade_point_in_frames(pSound, fadePointIndex, volumeBeg, volumeEnd, timeInFramesBeg, timeInFramesEnd);
|
return ma_sound_set_fade_point_in_frames(pSound, fadePointIndex, volumeBeg, volumeEnd, timeInFramesBeg, timeInFramesEnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MA_API ma_result ma_sound_set_fade_point_auto_reset(ma_sound* pSound, ma_uint32 fadePointIndex, ma_bool32 autoReset)
|
||||||
|
{
|
||||||
|
if (pSound == NULL) {
|
||||||
|
return MA_INVALID_ARGS;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ma_dual_fader_set_auto_reset(&pSound->effect.fader, fadePointIndex, autoReset);
|
||||||
|
}
|
||||||
|
|
||||||
MA_API ma_result ma_sound_set_start_delay(ma_sound* pSound, ma_uint64 delayInMilliseconds)
|
MA_API ma_result ma_sound_set_start_delay(ma_sound* pSound, ma_uint64 delayInMilliseconds)
|
||||||
{
|
{
|
||||||
if (pSound == NULL) {
|
if (pSound == NULL) {
|
||||||
@@ -6666,6 +6696,15 @@ MA_API ma_result ma_sound_group_set_fade_point_in_milliseconds(ma_sound_group* p
|
|||||||
return ma_sound_group_set_fade_point_in_frames(pGroup, fadePointIndex, volumeBeg, volumeEnd, timeInFramesBeg, timeInFramesEnd);
|
return ma_sound_group_set_fade_point_in_frames(pGroup, fadePointIndex, volumeBeg, volumeEnd, timeInFramesBeg, timeInFramesEnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MA_API ma_result ma_sound_group_set_fade_point_auto_reset(ma_sound_group* pGroup, ma_uint32 fadePointIndex, ma_bool32 autoReset)
|
||||||
|
{
|
||||||
|
if (pGroup == NULL) {
|
||||||
|
return MA_INVALID_ARGS;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ma_dual_fader_set_auto_reset(&pGroup->effect.fader, fadePointIndex, autoReset);
|
||||||
|
}
|
||||||
|
|
||||||
MA_API ma_result ma_sound_group_set_start_delay(ma_sound_group* pGroup, ma_uint64 delayInMilliseconds)
|
MA_API ma_result ma_sound_group_set_start_delay(ma_sound_group* pGroup, ma_uint64 delayInMilliseconds)
|
||||||
{
|
{
|
||||||
if (pGroup == NULL) {
|
if (pGroup == NULL) {
|
||||||
|
|||||||
Reference in New Issue
Block a user