ref: 60d213d2a215dc1c764507b51a065d81b6a2a8d7
dir: /src/mixer/ft2_silence_mix.c/
#include <assert.h>
#include <stdint.h>
#include "../ft2_audio.h"
// used for the audio channel mixer when voice volume is zero
void silenceMixRoutine(voice_t *v, int32_t numSamples)
{
const uint64_t samplesToMix = (uint64_t)v->delta * (uint32_t)numSamples; // fixed-point
const uint32_t samples = (uint32_t)(samplesToMix >> MIXER_FRAC_BITS);
const uint64_t samplesFrac = (samplesToMix & MIXER_FRAC_MASK) + v->positionFrac;
uint32_t position = v->position + samples + (uint32_t)(samplesFrac >> MIXER_FRAC_BITS);
uint64_t positionFrac = samplesFrac & MIXER_FRAC_MASK;
if (position < (uint32_t)v->sampleEnd) // we haven't reached the sample's end yet
{
v->positionFrac = positionFrac;
v->position = position;
return;
}
// end of sample (or loop) reached
if (v->loopType == LOOP_DISABLED)
{
v->active = false; // shut down voice
return;
}
if (v->loopType == LOOP_FORWARD)
{
if (v->loopLength >= 2)
position = v->loopStart + ((position - v->sampleEnd) % v->loopLength);
else
position = v->loopStart;
}
else // pingpong loop
{
if (v->loopLength >= 2)
{
// wrap as forward loop (position is inverted if sampling backwards, when needed)
const uint32_t overflow = position - v->sampleEnd;
const uint32_t cycles = overflow / v->loopLength;
const uint32_t phase = overflow % v->loopLength;
position = v->loopStart + phase;
v->samplingBackwards ^= !(cycles & 1);
}
else
{
position = v->loopStart;
}
}
v->hasLooped = true;
v->positionFrac = positionFrac;
v->position = position;
}