Commit d8aa6192 authored by David Reid's avatar David Reid

Add some experimental fading APIs to the engine API.

This is a simplified and somewhat more intuitive way of handling fades.
With these APIs, fades are applied immediately, whereas with the old
fading APIs the fades were scheduled. The old APIs still exist, but may
be removed.

The ma_sound_set_fade_in_frames/milliseconds() API sets the fade which
will be applied immediately. If the starting volume is negative, the
fade will start from the current fade volume. This will also overwrite
any existing fade that is already happening.

The ma_sound_get_current_fade_volume() API allows you to retrieve the
current volume of the fade.

The fade is layered on top of the normal volume parameter. I.e. they
are configured and applied to the signal interdependently.

Currently, all fades are applied linearly.
parent f6beb799
...@@ -103,14 +103,17 @@ int main(int argc, char** argv) ...@@ -103,14 +103,17 @@ int main(int argc, char** argv)
//ma_sound_group_set_pan(ma_engine_get_master_sound_group(&engine), -1); //ma_sound_group_set_pan(ma_engine_get_master_sound_group(&engine), -1);
//ma_sound_group_set_pitch(ma_engine_get_master_sound_group(&engine), 1.0f); //ma_sound_group_set_pitch(ma_engine_get_master_sound_group(&engine), 1.0f);
//ma_sound_group_set_start_delay(ma_engine_get_master_sound_group(&engine), 2000); //ma_sound_group_set_start_delay(ma_engine_get_master_sound_group(&engine), 2000);
ma_sound_group_set_fade_in_milliseconds(&group, 0, 1, 5000);
//ma_sound_set_fade_in_milliseconds(&sound, 0, 1, 5000);
/*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_volume(&sound, 0.5f); //ma_sound_set_volume(&sound, 0.5f);
//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, 0, MA_FALSE); /* Enable fading around loop transitions. */
//ma_sound_set_fade_point_auto_reset(&sound, 1, MA_FALSE); //ma_sound_set_fade_point_auto_reset(&sound, 1, MA_FALSE);
......
...@@ -1482,6 +1482,33 @@ MA_API ma_result ma_spatializer_set_position(ma_spatializer* pSpatializer, ma_ve ...@@ -1482,6 +1482,33 @@ MA_API ma_result ma_spatializer_set_position(ma_spatializer* pSpatializer, ma_ve
MA_API ma_result ma_spatializer_set_rotation(ma_spatializer* pSpatializer, ma_quat rotation); MA_API ma_result ma_spatializer_set_rotation(ma_spatializer* pSpatializer, ma_quat rotation);
/* Fader. */
typedef struct
{
ma_format format;
ma_uint32 channels;
ma_uint32 sampleRate;
} ma_fader_config;
MA_API ma_fader_config ma_fader_config_init(ma_format format, ma_uint32 channels, ma_uint32 sampleRate);
typedef struct
{
ma_effect_base effect;
ma_fader_config config;
float volumeBeg; /* If volumeBeg and volumeEnd is equal to 1, no fading happens (ma_fader_process_pcm_frames() will run as a passthrough). */
float volumeEnd;
ma_uint64 lengthInFrames; /* The total length of the fade. */
ma_uint64 cursorInFrames; /* The current time in frames. Incremented by ma_fader_process_pcm_frames(). */
} ma_fader;
MA_API ma_result ma_fader_init(const ma_fader_config* pConfig, ma_fader* pFader);
MA_API ma_result ma_fader_process_pcm_frames(ma_fader* pFader, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount);
MA_API ma_result ma_fader_get_data_format(const ma_fader* pFader, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate);
MA_API ma_result ma_fader_set_fade(ma_fader* pFader, float volumeBeg, float volumeEnd, ma_uint64 lengthInFrames);
MA_API ma_result ma_fader_get_current_volume(ma_fader* pFader, float* pVolume);
/* Dual Fader. Used for separating fading in and fading out. */ /* Dual Fader. Used for separating fading in and fading out. */
typedef struct typedef struct
...@@ -1529,7 +1556,8 @@ typedef struct ...@@ -1529,7 +1556,8 @@ typedef struct
ma_effect* pPreEffect; /* The application-defined effect that will be applied before spationalization, etc. */ ma_effect* pPreEffect; /* The application-defined effect that will be applied before spationalization, etc. */
ma_panner panner; ma_panner panner;
ma_spatializer spatializer; ma_spatializer spatializer;
ma_dual_fader fader; /* For fading in and out when starting and stopping. */ ma_fader fader;
ma_dual_fader dualFader; /* For fading in and out when starting and stopping. */
float pitch; float pitch;
float oldPitch; /* For determining whether or not the resampler needs to be updated to reflect the new pitch. The resampler will be updated on the mixing thread. */ float oldPitch; /* For determining whether or not the resampler needs to be updated to reflect the new pitch. The resampler will be updated on the mixing thread. */
ma_data_converter converter; /* For pitch shift. May change this to ma_linear_resampler later. */ ma_data_converter converter; /* For pitch shift. May change this to ma_linear_resampler later. */
...@@ -1653,9 +1681,15 @@ MA_API ma_result ma_sound_set_pitch(ma_sound* pSound, float pitch); ...@@ -1653,9 +1681,15 @@ MA_API ma_result ma_sound_set_pitch(ma_sound* pSound, float pitch);
MA_API ma_result ma_sound_set_position(ma_sound* pSound, ma_vec3 position); MA_API ma_result ma_sound_set_position(ma_sound* pSound, ma_vec3 position);
MA_API ma_result ma_sound_set_rotation(ma_sound* pSound, ma_quat rotation); 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_in_frames(ma_sound* pSound, float volumeBeg, float volumeEnd, ma_uint64 fadeLengthInFrames);
MA_API ma_result ma_sound_set_fade_in_milliseconds(ma_sound* pSound, float volumeBeg, float volumeEnd, ma_uint64 fadeLengthInMilliseconds);
MA_API ma_result ma_sound_get_current_fade_volume(ma_sound* pSound, float* pVolume);
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_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_is_playing(const ma_sound* pSound); MA_API ma_bool32 ma_sound_is_playing(const ma_sound* pSound);
...@@ -1675,9 +1709,15 @@ MA_API ma_result ma_sound_group_set_gain_db(ma_sound_group* pGroup, float gainDB ...@@ -1675,9 +1709,15 @@ MA_API ma_result ma_sound_group_set_gain_db(ma_sound_group* pGroup, float gainDB
MA_API ma_result ma_sound_group_set_effect(ma_sound_group* pGroup, ma_effect* pEffect); MA_API ma_result ma_sound_group_set_effect(ma_sound_group* pGroup, ma_effect* pEffect);
MA_API ma_result ma_sound_group_set_pan(ma_sound_group* pGroup, float pan); 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_in_frames(ma_sound_group* pGroup, float volumeBeg, float volumeEnd, ma_uint64 fadeLengthInFrames);
MA_API ma_result ma_sound_group_set_fade_in_milliseconds(ma_sound_group* pGroup, float volumeBeg, float volumeEnd, ma_uint64 fadeLengthInMilliseconds);
MA_API ma_result ma_sound_group_get_current_fade_volume(ma_sound_group* pGroup, float* pVolume);
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_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_bool32 ma_sound_group_is_playing(const ma_sound_group* pGroup); MA_API ma_bool32 ma_sound_group_is_playing(const ma_sound_group* pGroup);
...@@ -7659,6 +7699,184 @@ MA_API ma_result ma_spatializer_set_rotation(ma_spatializer* pSpatializer, ma_qu ...@@ -7659,6 +7699,184 @@ MA_API ma_result ma_spatializer_set_rotation(ma_spatializer* pSpatializer, ma_qu
MA_API ma_fader_config ma_fader_config_init(ma_format format, ma_uint32 channels, ma_uint32 sampleRate)
{
ma_fader_config config;
MA_ZERO_OBJECT(&config);
config.format = format;
config.channels = channels;
config.sampleRate = sampleRate;
return config;
}
static ma_result ma_fader_effect__on_process_pcm_frames(ma_effect* pEffect, const void* pFramesIn, ma_uint64* pFrameCountIn, void* pFramesOut, ma_uint64* pFrameCountOut)
{
ma_fader* pFader = (ma_fader*)pEffect;
ma_result result;
ma_uint64 frameCount;
/* The fader has a 1:1 relationship between input and output frame counts. */
frameCount = ma_min(*pFrameCountIn, *pFrameCountOut);
result = ma_fader_process_pcm_frames(pFader, pFramesOut, pFramesIn, frameCount);
*pFrameCountIn = frameCount;
*pFrameCountOut = frameCount;
return result;
}
static ma_result ma_fader_effect__on_get_data_format(ma_effect* pEffect, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate)
{
return ma_fader_get_data_format((ma_fader*)pEffect, pFormat, pChannels, pSampleRate);
}
MA_API ma_result ma_fader_init(const ma_fader_config* pConfig, ma_fader* pFader)
{
if (pFader == NULL) {
return MA_INVALID_ARGS;
}
MA_ZERO_OBJECT(pFader);
if (pConfig == NULL) {
return MA_INVALID_ARGS;
}
/* Only f32 is supported for now. */
if (pConfig->format != ma_format_f32) {
return MA_INVALID_ARGS;
}
pFader->effect.onProcessPCMFrames = ma_fader_effect__on_process_pcm_frames;
pFader->effect.onGetRequiredInputFrameCount = NULL;
pFader->effect.onGetExpectedOutputFrameCount = NULL;
pFader->effect.onGetInputDataFormat = ma_fader_effect__on_get_data_format;
pFader->effect.onGetOutputDataFormat = ma_fader_effect__on_get_data_format;
pFader->config = *pConfig;
pFader->volumeBeg = 1;
pFader->volumeEnd = 1;
pFader->lengthInFrames = 0;
pFader->cursorInFrames = 0;
return MA_SUCCESS;
}
MA_API ma_result ma_fader_process_pcm_frames(ma_fader* pFader, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount)
{
if (pFader == NULL) {
return MA_INVALID_ARGS;
}
/* Optimized path if volumeBeg and volumeEnd are equal. */
if (pFader->volumeBeg == pFader->volumeEnd) {
if (pFader->volumeBeg == 1) {
/* Straight copy. */
ma_copy_pcm_frames(pFramesOut, pFramesIn, frameCount, pFader->config.format, pFader->config.channels);
} else {
/* Copy with volume. */
ma_volume_and_clip_pcm_frames(pFramesOut, pFramesIn, frameCount, pFader->config.format, pFader->config.channels, pFader->volumeEnd);
}
} else {
/* Slower path. Volumes are different, so may need to do an interpolation. */
if (pFader->cursorInFrames >= pFader->lengthInFrames) {
/* Fast path. We've gone past the end of the fade period so just apply the end volume to all samples. */
ma_volume_and_clip_pcm_frames(pFramesOut, pFramesIn, frameCount, pFader->config.format, pFader->config.channels, pFader->volumeEnd);
} else {
/* Slow path. This is where we do the actual fading. */
ma_uint64 iFrame;
ma_uint32 iChannel;
/* For now we only support f32. Support for other formats will be added later. */
if (pFader->config.format == ma_format_f32) {
const float* pFramesInF32 = (const float*)pFramesIn;
/* */ float* pFramesOutF32 = ( float*)pFramesOut;
for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
float a = ma_min(pFader->cursorInFrames + iFrame, pFader->lengthInFrames) / (float)pFader->lengthInFrames;
float volume = ma_mix_f32_fast(pFader->volumeBeg, pFader->volumeEnd, a);
for (iChannel = 0; iChannel < pFader->config.channels; iChannel += 1) {
pFramesOutF32[iFrame*pFader->config.channels + iChannel] = pFramesInF32[iFrame*pFader->config.channels + iChannel] * volume;
}
}
} else {
return MA_NOT_IMPLEMENTED;
}
}
}
pFader->cursorInFrames += frameCount;
return MA_SUCCESS;
}
MA_API ma_result ma_fader_get_data_format(const ma_fader* pFader, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate)
{
if (pFader == NULL) {
return MA_INVALID_ARGS;
}
if (pFormat != NULL) {
*pFormat = pFader->config.format;
}
if (pChannels != NULL) {
*pChannels = pFader->config.channels;
}
if (pSampleRate != NULL) {
*pSampleRate = pFader->config.sampleRate;
}
return MA_SUCCESS;
}
MA_API ma_result ma_fader_set_fade(ma_fader* pFader, float volumeBeg, float volumeEnd, ma_uint64 lengthInFrames)
{
if (pFader == NULL) {
return MA_INVALID_ARGS;
}
/* If the volume is negative, use current volume. */
if (volumeBeg < 0) {
ma_fader_get_current_volume(pFader, &volumeBeg);
}
pFader->volumeBeg = volumeBeg;
pFader->volumeEnd = volumeEnd;
pFader->lengthInFrames = lengthInFrames;
pFader->cursorInFrames = 0; /* Reset cursor. */
return MA_SUCCESS;
}
MA_API ma_result ma_fader_get_current_volume(ma_fader* pFader, float* pVolume)
{
if (pFader == NULL) {
return MA_INVALID_ARGS;
}
/* The current volume depends on the position of the cursor. */
if (pFader->cursorInFrames <= 0) {
*pVolume = pFader->volumeBeg;
} else if (pFader->cursorInFrames >= pFader->lengthInFrames) {
*pVolume = pFader->volumeEnd;
} else {
/* The cursor is somewhere inside the fading period. We can figure this out with a simple linear interpoluation between volumeBeg and volumeEnd based on our cursor position. */
*pVolume = ma_mix_f32_fast(pFader->volumeBeg, pFader->volumeEnd, pFader->cursorInFrames / (float)pFader->lengthInFrames);
}
return MA_SUCCESS;
}
MA_API ma_dual_fader_config ma_dual_fader_config_init(ma_format format, ma_uint32 channels, ma_uint32 sampleRate) MA_API ma_dual_fader_config ma_dual_fader_config_init(ma_format format, ma_uint32 channels, ma_uint32 sampleRate)
{ {
...@@ -8013,8 +8231,16 @@ static ma_result ma_engine_effect__on_process_pcm_frames__no_pre_effect_no_pitch ...@@ -8013,8 +8231,16 @@ static ma_result ma_engine_effect__on_process_pcm_frames__no_pre_effect_no_pitch
pSubEffect[subEffectCount++] = &pEngineEffect->spatializer; pSubEffect[subEffectCount++] = &pEngineEffect->spatializer;
} }
/* Fader. Always required because timing information must always be updated. */ /* Fader. Don't need to bother running this is the fade volumes are both 1. */
if (pEngineEffect->fader.volumeBeg == 1 && pEngineEffect->fader.volumeEnd == 1) {
/* Fast path. No fading. */
} else {
/* Slow path. Fading required. */
pSubEffect[subEffectCount++] = &pEngineEffect->fader; pSubEffect[subEffectCount++] = &pEngineEffect->fader;
}
/* Dual Fader. Always required because timing information must always be updated. */
pSubEffect[subEffectCount++] = &pEngineEffect->dualFader;
/* We've built our list of effects, now we just need to execute them. */ /* We've built our list of effects, now we just need to execute them. */
...@@ -8259,7 +8485,8 @@ static ma_result ma_engine_effect_init(ma_engine* pEngine, ma_engine_effect* pEf ...@@ -8259,7 +8485,8 @@ static ma_result ma_engine_effect_init(ma_engine* pEngine, ma_engine_effect* pEf
ma_result result; ma_result result;
ma_panner_config pannerConfig; ma_panner_config pannerConfig;
ma_spatializer_config spatializerConfig; ma_spatializer_config spatializerConfig;
ma_dual_fader_config faderConfig; ma_fader_config faderConfig;
ma_dual_fader_config dualFaderConfig;
ma_data_converter_config converterConfig; ma_data_converter_config converterConfig;
MA_ASSERT(pEngine != NULL); MA_ASSERT(pEngine != NULL);
...@@ -8290,12 +8517,18 @@ static ma_result ma_engine_effect_init(ma_engine* pEngine, ma_engine_effect* pEf ...@@ -8290,12 +8517,18 @@ static ma_result ma_engine_effect_init(ma_engine* pEngine, ma_engine_effect* pEf
return result; /* Failed to create the spatializer. */ return result; /* Failed to create the spatializer. */
} }
faderConfig = ma_dual_fader_config_init(pEngine->format, pEngine->channels, pEngine->sampleRate); faderConfig = ma_fader_config_init(pEngine->format, pEngine->channels, pEngine->sampleRate);
result = ma_dual_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. */
} }
dualFaderConfig = ma_dual_fader_config_init(pEngine->format, pEngine->channels, pEngine->sampleRate);
result = ma_dual_fader_init(&dualFaderConfig, &pEffect->dualFader);
if (result != MA_SUCCESS) {
return result; /* Failed to create the dual fader. */
}
/* Our effect processor requires f32 for now, but I may implement an s16 optimized pipeline. */ /* Our effect processor requires f32 for now, but I may implement an s16 optimized pipeline. */
...@@ -8357,7 +8590,7 @@ static ma_bool32 ma_engine_effect_is_passthrough(ma_engine_effect* pEffect) ...@@ -8357,7 +8590,7 @@ static ma_bool32 ma_engine_effect_is_passthrough(ma_engine_effect* pEffect)
} }
/* If we're fading we need to make sure we do processing. */ /* If we're fading we need to make sure we do processing. */
if (ma_dual_fader_is_time_past_both_fades(&pEffect->fader) == MA_FALSE) { if (ma_dual_fader_is_time_past_both_fades(&pEffect->dualFader) == MA_FALSE) {
return MA_FALSE; return MA_FALSE;
} }
...@@ -8369,7 +8602,7 @@ static ma_result ma_engine_effect_set_time(ma_engine_effect* pEffect, ma_uint64 ...@@ -8369,7 +8602,7 @@ static ma_result ma_engine_effect_set_time(ma_engine_effect* pEffect, ma_uint64
MA_ASSERT(pEffect != NULL); MA_ASSERT(pEffect != NULL);
pEffect->timeInFrames = timeInFrames; pEffect->timeInFrames = timeInFrames;
ma_dual_fader_set_time(&pEffect->fader, timeInFrames); ma_dual_fader_set_time(&pEffect->dualFader, timeInFrames);
return MA_SUCCESS; return MA_SUCCESS;
} }
...@@ -9375,13 +9608,42 @@ MA_API ma_result ma_sound_set_looping(ma_sound* pSound, ma_bool32 isLooping) ...@@ -9375,13 +9608,42 @@ MA_API ma_result ma_sound_set_looping(ma_sound* pSound, ma_bool32 isLooping)
return MA_SUCCESS; return MA_SUCCESS;
} }
MA_API ma_result ma_sound_set_fade_in_frames(ma_sound* pSound, float volumeBeg, float volumeEnd, ma_uint64 fadeLengthInFrames)
{
if (pSound == NULL) {
return MA_INVALID_ARGS;
}
return ma_fader_set_fade(&pSound->effect.fader, volumeBeg, volumeEnd, fadeLengthInFrames);
}
MA_API ma_result ma_sound_set_fade_in_milliseconds(ma_sound* pSound, float volumeBeg, float volumeEnd, ma_uint64 fadeLengthInMilliseconds)
{
if (pSound == NULL) {
return MA_INVALID_ARGS;
}
return ma_sound_set_fade_in_frames(pSound, volumeBeg, volumeEnd, (fadeLengthInMilliseconds * pSound->effect.fader.config.sampleRate) / 1000);
}
MA_API ma_result ma_sound_get_current_fade_volume(ma_sound* pSound, float* pVolume)
{
if (pSound == NULL) {
return MA_INVALID_ARGS;
}
return ma_fader_get_current_volume(&pSound->effect.fader, pVolume);
}
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)
{ {
if (pSound == NULL) { if (pSound == NULL) {
return MA_INVALID_ARGS; return MA_INVALID_ARGS;
} }
return ma_dual_fader_set_fade(&pSound->effect.fader, fadePointIndex, volumeBeg, volumeEnd, timeInFramesBeg, timeInFramesEnd); return ma_dual_fader_set_fade(&pSound->effect.dualFader, fadePointIndex, volumeBeg, volumeEnd, timeInFramesBeg, 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)
...@@ -9393,8 +9655,8 @@ MA_API ma_result ma_sound_set_fade_point_in_milliseconds(ma_sound* pSound, ma_ui ...@@ -9393,8 +9655,8 @@ MA_API ma_result ma_sound_set_fade_point_in_milliseconds(ma_sound* pSound, ma_ui
return MA_INVALID_ARGS; return MA_INVALID_ARGS;
} }
timeInFramesBeg = (timeInMillisecondsBeg * pSound->effect.fader.config.sampleRate) / 1000; timeInFramesBeg = (timeInMillisecondsBeg * pSound->effect.dualFader.config.sampleRate) / 1000;
timeInFramesEnd = (timeInMillisecondsEnd * pSound->effect.fader.config.sampleRate) / 1000; timeInFramesEnd = (timeInMillisecondsEnd * pSound->effect.dualFader.config.sampleRate) / 1000;
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);
} }
...@@ -9405,7 +9667,7 @@ MA_API ma_result ma_sound_set_fade_point_auto_reset(ma_sound* pSound, ma_uint32 ...@@ -9405,7 +9667,7 @@ MA_API ma_result ma_sound_set_fade_point_auto_reset(ma_sound* pSound, ma_uint32
return MA_INVALID_ARGS; return MA_INVALID_ARGS;
} }
return ma_dual_fader_set_auto_reset(&pSound->effect.fader, fadePointIndex, autoReset); return ma_dual_fader_set_auto_reset(&pSound->effect.dualFader, 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)
...@@ -9798,13 +10060,42 @@ MA_API ma_result ma_sound_group_set_pitch(ma_sound_group* pGroup, float pitch) ...@@ -9798,13 +10060,42 @@ MA_API ma_result ma_sound_group_set_pitch(ma_sound_group* pGroup, float pitch)
return MA_SUCCESS; return MA_SUCCESS;
} }
MA_API ma_result ma_sound_group_set_fade_in_frames(ma_sound_group* pGroup, float volumeBeg, float volumeEnd, ma_uint64 fadeLengthInFrames)
{
if (pGroup == NULL) {
return MA_INVALID_ARGS;
}
return ma_fader_set_fade(&pGroup->effect.fader, volumeBeg, volumeEnd, fadeLengthInFrames);
}
MA_API ma_result ma_sound_group_set_fade_in_milliseconds(ma_sound_group* pGroup, float volumeBeg, float volumeEnd, ma_uint64 fadeLengthInMilliseconds)
{
if (pGroup == NULL) {
return MA_INVALID_ARGS;
}
return ma_sound_group_set_fade_in_frames(pGroup, volumeBeg, volumeEnd, (fadeLengthInMilliseconds * pGroup->effect.fader.config.sampleRate) / 1000);
}
MA_API ma_result ma_sound_group_get_current_fade_volume(ma_sound_group* pGroup, float* pVolume)
{
if (pGroup == NULL) {
return MA_INVALID_ARGS;
}
return ma_fader_get_current_volume(&pGroup->effect.fader, pVolume);
}
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)
{ {
if (pGroup == NULL) { if (pGroup == NULL) {
return MA_INVALID_ARGS; return MA_INVALID_ARGS;
} }
return ma_dual_fader_set_fade(&pGroup->effect.fader, fadePointIndex, volumeBeg, volumeEnd, timeInFramesBeg, timeInFramesEnd); return ma_dual_fader_set_fade(&pGroup->effect.dualFader, fadePointIndex, volumeBeg, volumeEnd, timeInFramesBeg, 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)
...@@ -9816,8 +10107,8 @@ MA_API ma_result ma_sound_group_set_fade_point_in_milliseconds(ma_sound_group* p ...@@ -9816,8 +10107,8 @@ MA_API ma_result ma_sound_group_set_fade_point_in_milliseconds(ma_sound_group* p
return MA_INVALID_ARGS; return MA_INVALID_ARGS;
} }
timeInFramesBeg = (timeInMillisecondsBeg * pGroup->effect.fader.config.sampleRate) / 1000; timeInFramesBeg = (timeInMillisecondsBeg * pGroup->effect.dualFader.config.sampleRate) / 1000;
timeInFramesEnd = (timeInMillisecondsEnd * pGroup->effect.fader.config.sampleRate) / 1000; timeInFramesEnd = (timeInMillisecondsEnd * pGroup->effect.dualFader.config.sampleRate) / 1000;
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);
} }
...@@ -9828,7 +10119,7 @@ MA_API ma_result ma_sound_group_set_fade_point_auto_reset(ma_sound_group* pGroup ...@@ -9828,7 +10119,7 @@ MA_API ma_result ma_sound_group_set_fade_point_auto_reset(ma_sound_group* pGroup
return MA_INVALID_ARGS; return MA_INVALID_ARGS;
} }
return ma_dual_fader_set_auto_reset(&pGroup->effect.fader, fadePointIndex, autoReset); return ma_dual_fader_set_auto_reset(&pGroup->effect.dualFader, 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)
......
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