When working with audio, there may be occasions where you want each beat to cause a unique response. For this example, we'll examine a way to cause a new layer to appear on each beat.
In Triggering an Expression With Audio we looked at a way to detect the most recent beat and use that to drive an animation. What we need here is very similar (in fact we'll borrow a lot of the code from the previous topic). In the previous case, our code looped back from the current comp time until it found a "beat" (a transition from below threshold to above threshold). This time though, we'll need to loop from the current comp time all the way back to time zero and count the number of beats along the way.
So the process will be essentially the same as in previous example, except that instead of calculating how long it has been since the most recent transition, we'll be calculating how many total transitions there have been. We'll perform this calculation in an expression for a slider control applied to a null layer. For this example, we'll name the null layer "control". We'll use the slider control expression to "publish" the beat-counting results for use by expressions applied to the opacity property of our other layers.
The opacity expression will examine the current beat count provided by the slider control and use that information in conjunction with the layer's own index in the layer stack to determine whether or not the layer should be visible at the current time. The opacity expression will check to see if the beat count equals or exceeds the number of layers participating (six in this example) minus the layer's own layer index. The result of this will be that the layers will pop into view, one by one, from bottom to top. The opacity expression will look like this:
n = 6;
slider = thisComp.layer("control").effect("Slider Control")("Slider");
if (slider > (n - index)){ 100 }else{ 0 }
Note that this simple opacity expression makes some assumptions about the layers to which it is applied. One assumption is that the layers are in the same comp as the "control" layer. Another assumption is that the layers are at the top of the layer stack (that is, they are layers 1 through n (6 in this example). If you want the layers to be in a different comp, or to be somewhere other than the top of the layer stack, you'll have to modify the expression.
The figure below illustrates how the beat counter increments by one whenever the audio amplitude exceeds the threshold value.
Here's the expression (to be applied to the slider control) that counts the number of transitions:
threshold = 10.0;
audioLev = thisComp.layer("Audio Amplitude").effect("Both Channels")("Slider");
above = false;
frame = Math.round(time / thisComp.frameDuration);
n = 0;
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++;
}
frame--
}
n
This topic relies on concepts from the previous audio topics. Please refer to those if you get a little lost here.
There is, of course, a drawback to this approach of looping from the current time back to time zero. As the comp gets longer, the rendering may begin to bog down because the expression has to do more and more calculation at each frame. However, this technique is useful in many situations and generally, the benefits will outweigh the negatives.