Calculate logarithmic fade out?

DSP, Plugin and Host development discussion.
Post Reply New Topic
RELATED
PRODUCTS

Post

I'm looking for a way (function) I can periodically call (via a timer) that sets a variable from say 100 (full volume) to 0 silence in given amount of time.
I have it working linear but rather would like to do it logarithmic (since the device I'm controlling has linear volume adjustment, a log fade would then be perceived as linear.)

Since I'm not sure it's clear what I want, another use case of this is a play position indicator in an audio player, goes from 0 (left / song start) to 100 (right / song end) continously in given amount of time (song duration), I practically want this reversed and logarithmic.

Image

Post

So essentially, you want to translate a volume change of current volume level down to 0 from a linear descend into a logarithmic descend?

Post

set a threshold, you'll never get to zero

reference RT60 calcs, where teh thresh is .001
you come and go, you come and go. amitabha neither a follower nor a leader be tagore "where roads are made i lose my way" where there is certainty, consideration is absent.

Post

Are you looking to emulate an audio taper pot? You don't need to use logs to get that, as it's based on the math for putting a fixed value resistor in parallel with a variable resistor.

If:
v = current volume level
k = a constant value used to tweak the non-linear response
a = % of attenuation where 1.0 = maximum volume and 0.0 = zero volume

instantaneous value of volume (v) = a / (1 + (1 - a) * k)

If the response is not what you expect, then you can vary k until it works for you. Maybe start with a value around 0.25 or so.
Last edited by Forgotten on Sat Jul 27, 2019 1:51 am, edited 1 time in total.

Post

If you want it to be linear in decibels, start with 1 and exponentially decay toward zero. Or use a power function like x^alpha from x=1 to 0 to approximate exponential decay with the benefit of having a finite support.
VCV Rack, the Eurorack simulator

Post

No_Use wrote: Fri Jul 26, 2019 1:06 am I'm looking for a way (function) I can periodically call (via a timer) that sets a variable from say 100 (full volume) to 0 silence in given amount of time.
I have it working linear but rather would like to do it logarithmic (since the device I'm controlling has linear volume adjustment, a log fade would then be perceived as linear.)

Since I'm not sure it's clear what I want, another use case of this is a play position indicator in an audio player, goes from 0 (left / song start) to 100 (right / song end) continously in given amount of time (song duration), I practically want this reversed and logarithmic.
OK, you want an exponential fade, right? That would be the equivalent of a linear fade on a log (dB) scale. For an exponential fade, simply start with 1.0 and multiply it by a rate value less than 1 every update period (every sample, for instance). For example, if the multiplier is 0.5, you'd get 1.0, 0.5, 0.25, 0.125, 0.625...corresponding to (approximately) 0 dB, -6 dB, -12 dB, -18 dB, -24 dB...

It will never get to zero, but you choose a target value (after which you can set it to zero). The math is not so obvious, but you can calculate the rate multiplier exactly (within floating point limits). Check out my article series with code for the details, including sample-accurate fade time (discussed in part 2 and the code):

https://www.earlevel.com/main/category/ ... enerators/
My audio DSP blog: earlevel.com

Post

Oh, either reply notification didn't work or I forgot to turn it on err..., sorry for the late reply.
vortico wrote: Sat Jul 27, 2019 1:11 am If you want it to be linear in decibels, start with 1 and exponentially decay toward zero.
earlevel wrote: Wed Jul 31, 2019 5:26 pm OK, you want an exponential fade, right? That would be the equivalent of a linear fade on a log (dB) scale.
Yep that's it, it's a good starting point to realize that I want an exponential fade. :D
Fade time needn't be sample accurate at all (it's not for an audio application / plugin, just for a sleep timer app with volume fade function), so rough approximation will do.

Will check out the linked articles.
Thanks for the answers.

edit:
To give further details, the doc for the device in question says:
Specifying Volume in the Level Scale
The level scale specifies volume in a linear scale. It ranges from 0 to 100, where 0 represents silence and 100 represents the highest volume. The mapping for producing a linear multiplicative value is implementation dependent.
So essentailly what I'd like to achieve is an exponential (linear in dB) fade out from [current level] to (approx.) 0 over (roughly) a given amount of time. Any advice how to do that with the simplest math possible? :oops:

Post

Simple, just start with a variable at 1.0. It’s the gain value that you use to multiply your audio by, so your audio is played at its full level. When it’s time to fade, go into a new state where you multiply the gain by a rate factor, at each sample period. A rate factor slightly less than 1 would be a very slow fade. Smaller values are faster. More details in my envelope generator article, but that’s the gist of it.

A good idea to set a limit, so once the gain is below a certain level, you set it to zero, or at least stop updating it. Otherwise you hit denormals. Every decimal point is another 20 dB, so 0.1 is -20 dB, 0.00001 is -100 dB.
My audio DSP blog: earlevel.com

Post

Thanks.
I get it this far. What I'm stumbling on is how to calculate the gain factor so it reaches the limit in a given amount of time.
This is what I have currently in my app as the crude linear 'fade' (periodically reducing volume in steps of 5 over roughly a minute) via a timer (Java):

Code: Select all

private void startVolumeFade() {
	int vol = vc.getLevel();
	int steps = vol / 5; // reduce vol. in steps of 5
	int oneStepDurationMillisec = 60 / steps * 1000;
	vc.setFadeLevel(vc.getLevel()); // start fading at current volume
	fadeOutTimer = new Timer();
	
	TimerTask task = new TimerTask() {
		public void run() {
			vc.setFadeLevel(vc.getFadeLevel() - 5);
		}
	};
	fadeOutTimer.schedule(task, 0, oneStepDurationMillisec);
}
I then check periodically if volume has reached <= 0 to trigger a shutdown.
It works sufficently ok for my purpose.

Post

OK, you said roughly—I thought that meant you would plug in some numbers and see what you get.

As I said, the math is explained in my article series, and is in the code. The idea is that for a linear fade, and wanting to set a given number of steps to get there, you'd divide the distance you need to move by the number of steps to get the increment, right? For an exponential move, you essentially need to warp the move to linear (by taking the log), doing the same thing you did for a linear move, then warping it back (exp).

Grab calcCoef from my code. targetRatio is a number like 0.0001 (-80 dB), rate is the number of steps to get there. Note that if you set targetRatio too low, it will sound like the fade finishes earlier, because the tail gets too quiet.

Code: Select all

float ADSR::calcCoef(float rate, float targetRatio) {
    return (rate <= 0) ? 0.0 : exp(-log((1.0 + targetRatio) / targetRatio) / rate);
}
You can grab the iterative code from the release.

Code: Select all

        case env_release:
            output = releaseBase + output * releaseCoef;
            if (output <= 0.0) {
                output = 0.0;
                state = env_idle;
            }
Note that I set a target below zero and stop when it gets to zero. That means the base needs to be below zero, and that's what releaseBase is about. You can grab its calculation from my code too. Or, you can omit it as many people do (because it's not as hard to figure out), and just kill it or let it continue to run (but watch out for denormals).
My audio DSP blog: earlevel.com

Post

No_Use wrote: Mon Aug 12, 2019 11:36 am I get it this far. What I'm stumbling on is how to calculate the gain factor so it reaches the limit in a given amount of time.
This is rather trivial if you take the problem into log-domain and think about it in terms of decibels, since we're just adding numbers.

Let's say we want -100dB = 10^(100/20) fade over 5 seconds and we're updating 30 times a second. So we have 5*20=150 updates, each of which should reduce the gain by -100dB/150 = -0.75dB. That's it.

The coefficient formula then becomes:

10^(dBtotal/(20*timeSec*updatesPerSec))
= exp(log(10)/20 * dBtotal/(timeSec*updatesPerSec))

Post

Another way of saying what mystran said:

Code: Select all

// outside of your audio loop initialize these variables
int N = timeSec*updatesPerSec;
int i = 0;
float k = 10^(dBtotal/(20*N)); // calculate this just once
gain = 1; // max gain

// inside your audio loop, every updatesPerSec call this code to calculate gain
gain = (++i > N ? 0 : gain*k) // fast way to update gain; no powers


Post

from the xoxos dsp enema freely offered:
DECAY
The gain of a recursive system at recursion n is derivable using the pow function:
gain_at_n_recursions = pow(gain, n);
Eg. a variable multiplied by 0.5 on every sample is obviously 0.0625 of its original value on the 4th iteration:
0.0625 = pow(0.5, 4);
If we intend to have a specific gain at a specific number of recursions, we can calculate a gain coefficient:
sought coefficient = pow(intended_gain_at_n_recursions, inverse_of_n);
eg: 0.5 = pow(0.0625, 1/4);
Given any two of these variables we can derive the third using the identities:
x = pow(b, y);
b = pow(x, 1 / y);
y = log(x) / log(b);
eg. 4 = log(0.0625) / log(0.5);
you come and go, you come and go. amitabha neither a follower nor a leader be tagore "where roads are made i lose my way" where there is certainty, consideration is absent.

Post

No_Use wrote: Fri Jul 26, 2019 1:06 am I'm looking for a way (function) I can periodically call (via a timer) that sets a variable from say 100 (full volume) to 0 silence in given amount of time.
Try this formula: https://www.desmos.com/calculator/p7jao8ae2i

Post

Just wanted to say thanks for all the replies, I'm still following. :)
Though it will be a bit until getting back to this project, that's why I haven't reported back in more detail yet..

Post Reply

Return to “DSP and Plugin Development”