Creative Communities of the World Forums

The peer to peer support community for media production professionals.

Activity Forums Adobe After Effects Expressions Getting a variable to decay over time if it’s below a slider’s level

  • Getting a variable to decay over time if it’s below a slider’s level

    Posted by Stephen OConnor on February 23, 2024 at 10:27 pm

    Hi, all! Google has led me to this helpful community many times, but this is my first time posting. I’ve searched high and low for an answer to this and keep coming up with nothing. Please be kind if I’ve overlooked it somewhere!

    I am trying to build an expression for an audio visualizer for podcast social media cards I’m building (I work for a university). Most traditional visualizers typically jump up to whatever peak level is detected, then decay slowly back down to zero over a set window of time until the signal level surpasses the meter’s current value again. What I’ve been doing so far is trying to build this behavior into a variable. This way, I can use the variable to modulate a Math.Sin function on the y-position or the y-scale property of the layer of interest.

    If the variable is below the slider’s value then setting it to equal the slider is a simple if/then statement. The tricky bit is getting the variable to decay, linearly or logarithmically, when it’s above the slider’s value. I can’t seem to figure out how to store the variable for reference in the next frame, nor incrementally subtract a set amount until it hits 0 or crosses the slider’s value again. For instance, if the level was 10 and the slider value was 2 on the current frame, then on the next frame I’d like to divide the current frame’s variable’s value (10) by 2 to make it 5, then 2.5 on the following frame, and so on until it falls below the slider’s value. Once it falls below the slider value, I want it to jump up to match the slider again, until the slider’s value drops below and the process repeats. Bonus points if I can set a lower threshold where low audio levels will simply return a “0,” just to keep the animation tidy.

    The only thing I’ve managed to get working is for the variable to either match the slider’s value for the entire span of values or fall to 0 on the next frame, meaning the animation “works” but has no gentle fall to 0 like I want. I have read some discouraging things that variables (not properties, but variables) cannot be retrieved from past frames, but I’ve seen some complex audio visualizer presets on various stock sites that emulate this behavior, so I feel like it must be possible somehow.

    I’ve provided the existing expression below so folks can see what I have working. I should also note that I am not an expert in Javascript or expressions and am teaching myself so I can do this for my department, so apologies if I am missing something obvious!

    Thanks all!

    var frequency = 7;
    var a = 1;
    if (thisComp.layer("Audio Amplitude").effect("Both Channels")("Slider") > a) {
        a = thisComp.layer("Audio Amplitude").effect("Both Channels")("Slider");
    }
    else {

    a = a * 0.5;

    }

    if (a < 1){

    a=0

    }

    sinWave = Math.sin(2*Math.PI*frequency*time)*a*10;
    [transform.position[0],transform.position[1]+sinWave];
    Brie Clayton replied 2 years, 4 months ago 3 Members · 3 Replies
  • 3 Replies
  • Dan Ebberts

    February 23, 2024 at 10:53 pm

    >I can’t seem to figure out how to store the variable for reference in the next frame

    You can’t. Expressions have no memory. There’s no way for a variable to survive from frame to frame. What an expression can do, is examine previous pre-expression values, using .valueAtTime() to re-create previous calculations. This is a an expression I have in the archive that implements a vu meter with a 300 ms decay, which you may find useful:

    decay = .3; // 300 ms
    a = thisComp.layer("Audio Amplitude").effect("Both Channels")("Slider");
    maxVal = a.value;
    t = thisComp.frameDuration;
    while (t < decay){
    temp = a.valueAtTime(time - t);
    maxVal = Math.max(maxVal, easeOut(t,0,decay,temp,0));
    t += thisComp.frameDuration;
    }
    maxVal

  • Stephen OConnor

    February 26, 2024 at 6:32 pm

    Hi, Dan! This is super clever and works a treat. Thank you so much!

    I recognize your name from ECAbrams’ YT channel, who has sung your praises on multiple occasions. Appreciate getting the help from the legend, himself. 😄

  • Brie Clayton

    February 26, 2024 at 8:11 pm

    Thank you for solving this issue, Dan!

We use anonymous cookies to give you the best experience we can.
Our Privacy policy | GDPR Policy