Creative Communities of the World Forums

The peer to peer support community for media production professionals.

Activity Forums Adobe After Effects expression play once on beat

  • expression play once on beat

    Posted by Marcel Ooms on May 16, 2014 at 12:50 pm

    hello cows,

    I’m working on a audio project. We made a cool seperate comp for every sound layer. I now want to automate the sound, so it should play once everytime it hits a certain peak

    I thought just using a time remap, and put an ‘if/else’ expression that would return to frame ‘0’ when it hits the peak would do the trick. I was wrong. It won’t continue playing, or it goes to ‘0’ for 1 frame and when it leaves the peak it is back to normal ‘time’

    I hope it is a little bit clear. Basically I want (in frames)

    frame 1.2.3.4.5 1.2.3.4.5. etc
    ^
    (here is the peak of audio)

    thanks in advance

    Walter Soyka replied 11 years, 12 months ago 2 Members · 12 Replies
  • 12 Replies
  • Marcel Ooms

    May 16, 2014 at 12:57 pm

    in flash language (which doesn’t work with timeremap:D)I would say:

    if (thisComp.layer(“Audio Amplitude”).effect(“Both Channels”)(“Slider”) > 50)
    {
    play(once);
    }

  • Walter Soyka

    May 16, 2014 at 1:01 pm

    If the beat is regular, you could keyframe it once and then use the loopOut expression:

    loopOut("cycle");

    Otherwise, it’s a little more complicated. Expressions are evaluated anew every single frame; they have no memory of what happened during the frame before. Your time remapping logic must control not only when the sound starts, but also its entire continuation and when it ends.

    Can you post the expression you started with and we can take a look?

    Walter Soyka
    Principal & Designer at Keen Live
    Motion Graphics, Widescreen Events, Presentation Design, and Consulting
    RenderBreak Blog – What I’m thinking when my workstation’s thinking
    Creative Cow Forum Host: Live & Stage Events

  • Marcel Ooms

    May 16, 2014 at 2:03 pm

    that’s a start! thanks. But it is an irregular beat.

    so far I have:

    t=value;
    if(thisComp.layer(“Audio Amplitude”).effect(“Both Channels”)(“Slider”) > 55)
    {
    t = 0
    loopOut(“cycle”)
    }

    t

    but now it won’t run the cycle. When the beats hits 55 it return to 0 (as I want it too) but then I want it to play at normal speed, so timeremap should just be 0 en continue.

    instead, because of the t=value, the frame after the beat hits 55 it return to it’s original value. So how do I make a value, which at the beginning just gives the normal framerate, but I can tell “when you hit the beat, value = 0 and start over”

  • Walter Soyka

    May 16, 2014 at 8:18 pm

    As I mentioned above, expressions are evaluated anew every frame — they have no “memory” of what the results were on the frame before.

    How long is the audio sample? You may have to calculate how long it has been from the current frame to the time the amplitude last hit 55 and have your expression control not just the first frame where the audio hits, but also all the frames it’s supposed to play thereafter.

    Or it might be quicker just to cut the samples manually in where they belong. Audition would be better suited for than this Ae.

    Walter Soyka
    Principal & Designer at Keen Live
    Motion Graphics, Widescreen Events, Presentation Design, and Consulting
    RenderBreak Blog – What I’m thinking when my workstation’s thinking
    Creative Cow Forum Host: Live & Stage Events

  • Marcel Ooms

    May 19, 2014 at 8:40 am

    Indeed I was hoping for some kind of memory instead of a everyframe check.

    The animation is about 10 frames long and the beat too. Can you program something like: when hit 55, play 10 frames. I’m not sure how it works with your second paragraph, but indeed it would be a way to say: play frame 0 when hits 55, thereafter 1 thereafter 2 then 3…. etc, in some way hardcoded instead of just (cycle)

    yes it is possible to just set a comp for every beat. But we want o automate it, so with 10 music layers, 2 minutes and at the end even switch the song so we get an totally different animation but with the same elements.

    so audition wouldn’t work, because we want to make it applicable for every songs (of course with a little bit of tweeking in the AE file) without changing the song

  • Walter Soyka

    May 19, 2014 at 1:06 pm

    Gotcha. You’ll need logic that controls the entire duration, somewhat like the following untested snippet of code:

    sampleDurationFrames = 10; // how long is the animation, or how many frames back should I look?
    timeRemapped = -1; // safe value for time remapping in case I'm not supposed to be playing the animation

    // loop from the back of the sampling range to the current time, checking to see where I should be in the animation based on the sound
    for (i = sampleDurationFrames; i > 0; i--) {
    timeBack = time-framesToTime(i);
    if (thisComp.layer("Audio Amplitude").effect("Both Channels")("Slider").valueAtTime(timeBack) > 55) timeRemapped = sampleDurationframes-i;
    }

    Walter Soyka
    Principal & Designer at Keen Live
    Motion Graphics, Widescreen Events, Presentation Design, and Consulting
    RenderBreak Blog – What I’m thinking when my workstation’s thinking
    Creative Cow Forum Host: Live & Stage Events

  • Walter Soyka

    May 19, 2014 at 2:22 pm

    My post above contains at least one error. You’ll have to convert the calculated time remapping values back from frames back to time.

    Walter Soyka
    Principal & Designer at Keen Live
    Motion Graphics, Widescreen Events, Presentation Design, and Consulting
    RenderBreak Blog – What I’m thinking when my workstation’s thinking
    Creative Cow Forum Host: Live & Stage Events

  • Marcel Ooms

    May 19, 2014 at 7:09 pm

    Hey walter,

    Thanks for your help. I figured out that I had to convert them back, but still the value switched back to its original value as soon as it hits the frame after (in this example) 55. But i’ve got the feeling we are getting there.

    I also tried a different way today. Just copying the animated layer and offsetting it start to everytime the layer hits 55, but this asked for a script i guess, which is even harder (if you’re not the programming genius like me). so that plan failed 🙂

    it’s really strange that after effects hasn’t got an expression like ‘nextFrame()’ or something, so you can get the value back to 0 and then say ‘nextFrame(till frame 20)’

  • Marcel Ooms

    May 19, 2014 at 9:17 pm

    A new idea is just add a slider, and add expression:

    numberFrames=60 //frames animation lenght
    l = 60/numberFrames
    numberCycles = Math.floor(time*l)
    i=numberCycles/l;
    f= time-i;
    f

    and find the loop or regular beat and use the slider for all the irregular beats, but the only reason for this solution is because i really can’t get your script to work or have any more ideas

    why doesn’t AE have any kind of expression memory instead of the everyframe check!!!! 🙁

  • Walter Soyka

    May 20, 2014 at 12:38 am

    This is something I could use myself, so I’ve reworked it a bit:

    property = thisComp.layer("Test").transform.opacity; // property to check for threshold crossing
    threshold = 70; // threshold which activates playback
    maxFrames = 10; // the length of the animation in frames

    animationFrame = -1; // the "current frame" of the underlying animation; -1 when not playing

    // we need to go back twice as many frames as the animation is, to catch cases where it's already supposed to be playing
    // this for loop starts 20 frames back on the timeline, then advances to the current time
    // it looks to see if we're playing the animation already; if so, we continue playing
    // if not, we check to see if we should start

    for (i = maxFrames*2; i >=0; i--) {
    // is the animation currently playing? if so, advance its counter
    if (animationFrame >= 0) animationFrame++;

    // if we've reached the end of the animation, reset it
    if (animationFrame >= maxFrames) animationFrame = -1;

    // if we're not playing, check for a value that's crossed the threshold and start playing again
    if ((animationFrame == -1) && (property.valueAtTime(time-framesToTime(i)) > threshold)) animationFrame = 0;

    }

    // if the current frame on the timeline is supposed to be playing the animation, play that frame
    // otherwise, play frame 0 of the underlying animation
    if (animationFrame >= 0) framesToTime(animationFrame) else 0;

    Note that I’m using the opacity of a layer called Test to trigger my playback. You’ll have to tweak the first couple lines for your own animation.

    This also responds to the first value that crosses the threshold to trigger playback, then ignores any other values over the threshold during playback.

    [marcel ooms] “why doesn’t AE have any kind of expression memory instead of the everyframe check!!!! :(“

    Instead of thinking of an expression as a program that executes over a composition, think of it as a program that executes on a given frame.

    While some tasks like this are a little harder this way, frame-based expressions are extremely flexible and generally desirable for non-accumulating tasks.

    Walter Soyka
    Principal & Designer at Keen Live
    Motion Graphics, Widescreen Events, Presentation Design, and Consulting
    RenderBreak Blog – What I’m thinking when my workstation’s thinking
    Creative Cow Forum Host: Live & Stage Events

Page 1 of 2

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