Question

I'm trying to create a simple function that will decrease audio volume in a buffer (like a fade out) each iteration through the buffer. Here's my simple function.

double iterationSum = 1.0;

double iteration(double sample)
{
 iterationSum *= 0.9;

 //and then multiply that sum with the current sample.
 sample *= iterationSum;
 return sample;
}

This works fine when set to a 44100 kHz samplerate but the problem I'm having is that if the samplerate is for an example changed to 88200 kHz it should only reduce the volume half that step each time because the samplerate is twice as much and will otherwise end the "fade out" in halftime, and I've tried to use a factor like 44100 / 88200 = 0.5 but this will not make it half the step in any way.

I'm stuck with this simple problem and need a guide to lead me through, what can I do to make it half step in each iteration as this function is called if the samplerate is changed during programtime?

Regards, Morgan

Was it helpful?

Solution

The most robust way to fade out independent of sample rate is to keep track of the time since the fadeout started, and use an explicit fadeout(time) function.

If for some reason you can't do that, you can set your exponential decay rate based on the sample rate, as follows:

double decay_time = 0.01; // time to fall to ~37% of original amplitude
double sample_time = 1.0 / sampleRate;
double natural_decay_factor = exp(- sample_time / decay_time);
...
double iteration(double sample) {
    iterationSum *= natural_decay_factor;
    ...
}

The reason for the ~37% is because exp(x) = e^x, where e is the "natural log" base, and 1/e ~ 0.3678.... If you want a different decay factor for your decay time, you need to scale it by a constant:

// for decay to 50% amplitude (~ -6dB) over the given decay_time:
double halflife_decay_factor = exp(- log(2) * sample_time / decay_time);

// for decay to 10% amplitude (-20dB) over the given decay_time:
double db20_decay_factor = exp(- log(10) * sample_time / decay_time);

OTHER TIPS

im not sure if i understood, but what about something like this:

public void fadeOut(double sampleRate)
{
    //run 1 iteration per sec?
    int defaultIterations=10;

    double decrement = calculateIteration(sampleRate, defaultIterations);

    for(int i=0; i < defaultIterations; i++)
    {

        //maybe run each one of these loops every x ms?
        sampleRate = processIteration(sampleRate, decrement);
    }
}


public double calculateIteration(double sampleRate, int numIterations)
{
    return sampleRate/numIterations;
}


private double processIteration(double sampleRate, double decrement)
{
    return sampleRate -= decrement;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top