Creative Communities of the World Forums

The peer to peer support community for media production professionals.

Activity Forums Adobe After Effects Expressions Trigger effect every third event

  • Trigger effect every third event

    Posted by Isaac Someah-kwaw on April 24, 2016 at 1:04 am

    Hi all,

    I’m working with Trapcode soundkeys, and I have three (or more) layers, that I want to react to a soundkeys output in alternating fashion.

    More specifically, I want to get the glow intensity of the three layers to react to the output (a kick drum rhythm), but to varying degrees. So if layer one’s glow reaches 100%, I want layer two to simultaneously reach a max of 75%, and layer three a max of 50%. And For every kick hit, I want those three values to continuously cycle between those three elements so that all three at no point share the same value.

    I was thinking I could try to make some kind of three-phase circuit expression for each element, but so far I haven’t had any luck figuring out a way to do that. AE accepts the code I came up with, but the element doesn’t react the way I’m expecting. I’m thinking there’s a far simpler and more elegant way to do this, but if not, how could I fix what I have below?

    hit = thisComp.layer("Sound Keys").effect("Sound Keys")("Output 1");
    a = 1

    if (a = 1) {
    hit;
    // links element glow intensity to Soundkeys output. In this example
    //I only want the glow to activate on the 1st kick drum occurrence,
    //and for nothing to happen every 2nd and 3rd occurence.
    };

    if (a = 1 && hit > 50) {
    b = 1;

    //if "a = 1" condition is active AND the soundkeys output value
    //is greater than 50, activate "b=1" switch. I'm using a value
    //greater than 50 to signify a kick hit.

    };

    if (a = 1 && b = 1 && hit < 20) {
    a = 2;
    //if "a=1" condition is active AND "b=1" switch is active
    //AND the Soundkeys output is below 20, I wanted this
    //to disable the "a=1" condition and activate the "a=2" conditon,
    //thus disabling the glow intensity stored in "a=1",
    //and activating the next effect stored in "a=2".
    //Ideally I wanted "hit = 0" here as well, but given that the
    //kick drum is playing simultaneously with other audio elements
    //in the same frequency range, the output rarely reaches 0.
    //This is also problematic because, once the output falls
    //below 20, the effect abruptly cuts off. I would prefer
    //it to be a smooth transition.
    };

    if (a = 2) {
    // repeat process with 2nd effect.

    };

    if (a = 2 && hit > 50) {
    b = 2;

    };

    if (a = 2 && b = 2 && hit < 20) {
    a = 3 ;
    };

    if (a = 3) {
    // repeat process with 3rd effect.
    };

    if (a = 3 && hit > 50) {
    b = 3;
    };

    if (a = 3 && b = 3 && hit < 20) {
    a = 1;
    b = 0;
    //supposed to trigger a cycle by making "a=1" happen again,
    //but this does not seem to happen. What I'm noticing instead
    //is that the glow only seems to occur when the output is
    //below one of the values I set above. I'm unsure if the value
    //is the 50 or 20. I can tell as much because I have one of
    //the other three elements pickwhipped directly to the output,
    //so that It always reacts to the kick. The element with the above
    //expression only reacts as the glow for the other element is
    //dying out. But Once the output exceeds a certain value, the glow
    //for this element abruptly cuts off, while the directly linked
    //element proceeds to reach full glow intensity.
    };

    Isaac Someah-kwaw replied 10 years, 3 months ago 2 Members · 5 Replies
  • 5 Replies
  • Dan Ebberts

    April 24, 2016 at 1:33 am

    I notice a couple of things. One is that for logical comparison, you need to use == (or ===), not = .

    So instead of

    if (a = 1)…

    it would be

    if (a == 1)…

    The second is that it’s not clear to me if you understand (my apologies if you do) that expressions have no memory, so variables you set are gone when the expression evaluates at the next frame. To find out if some event has happened in the past, you generally have to loop back in time, frame by frame until you find when the event occurred, or you reach time zero.

    Dan

  • Isaac Someah-kwaw

    April 24, 2016 at 1:40 am

    Thanks for the reply Dan,

    Oops, I forgot I had to use ==. And yeah, It dawned on me right after I posted this that each conditional expression would only recognize globally set variables, and not ones set within the other conditional statements. Is there a reasonable way to do as you described?

  • Dan Ebberts

    April 24, 2016 at 2:23 am

    The basic idea of finding a triggering event is described here:

    https://motionscript.com/design-guide/audio-trigger.html

    Your situation (multiple conditions to meet) complicates things, but I think it’s probably still do-able.

    Dan

  • Isaac Someah-kwaw

    April 24, 2016 at 10:24 am

    I spent a while tweaking that code, but can’t get beyond making it work with the glow intensity property instead of the position property.

    I read your posts here. The codes are similar, and I’m thinking I could integrate a looping array into the code you linked me to, but I’m not sure how to go about that. Would it be possible to use “thisProperty” to continuously multiply the glow intensity value by decimal numbers stored in the array in order to achieve the “100%, 75%, 50%” cycle I’m looking for?

    Also, I’m splitting hairs, but would there be a way to have the glow still decay at the same speed as the audio output? I notice that with this code, the decay rate of the glow is a fixed value instead of decaying as fast/slow as the sound does.

    threshold = 38;

    audioLev = thisComp.layer("Sound Keys").effect("Sound Keys")("Output 1");

    above = false;
    frame = Math.round(time / thisComp.frameDuration);
    while (true){
    t = frame * thisComp.frameDuration;
    if (above){
    if (audioLev.valueAtTime(t) < threshold){
    frame++;
    break;
    }
    }else if (audioLev.valueAtTime(t) >= threshold){
    above = true;
    }
    if (frame == 0){
    break;
    }
    frame--
    }
    if (! above){
    t = 0;
    }else{
    t = time - frame * thisComp.frameDuration;
    }

    amp = 100;
    freq = 2;
    decay = 2.0;

    angle = freq * 2 * Math.PI * t;
    glow = 1 + amp * Math.sin(angle) / Math.exp(decay * t) / 100;

    thisProperty * glow;

  • Isaac Someah-kwaw

    April 25, 2016 at 6:20 am

    Wooo! After enough poking and prodding, I’ve figured out a solution that suits my needs.

    The key was in creating an incremental loop that gets triggered by passing the threshold, and resets itself once its value is greater than 3. Each increment sets a different x value that gets multiplied by the audio output level. And the linear expression keeps the glow from completely disappearing when the output falls below the threshold.

    Thanks Dan!

    threshold = 38;
    x = 0;
    n = 0;
    audioLev = thisComp.layer("Sound Keys").effect("Sound Keys")("Output 1");
    frame = Math.round(time / thisComp.frameDuration);

    above = false;
    while (frame >= 0){
    t = frame * thisComp.frameDuration;
    if (above){
    if (audioLev.valueAtTime(t) < threshold){
    above = false;
    };
    }else if (audioLev.valueAtTime(t) >= threshold){
    above = true;
    n++;
    if (n==1) {x = 1;
    };
    else if (n==2) {x = .75;
    };
    else if (n==3) {x = .5;
    };
    else if (n > 3) {n = 1; x = 1;
    };
    };
    frame--
    };

    glow = audioLev*x
    linear(glow,0,500,60,500);

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