rendering

This is the smooth, periodic sine waveform generated by math.sin ()

A smooth frequency ramp is realized by using a linear key frame integrator

Control frequency

In the world of expressions, it’s not uncommon to create looping or oscillating motions by using the built-in JavaScript trigonometric functions math.sin (and math.cos (). They do a good job of producing smooth, periodic sine waves. If you remember that JavaScript trigonometry calls for radians rather than degrees, it’s easy to set the frequency of the wave, because a complete oscillation (360 degrees) is expressed in 2* PI radians. These trigonometric functions produce waveforms with amplitudes varying between -1 and +1. For example, in the first illustration above, this expression oscillates between +100 and -100 with a period time of 1 second (or, in other words, a frequency of 1.0):

freq = 1;
amp = 100;
value + amp*Math.sin(freq*time*Math.PI*2)
Copy the code

Note that the conversion to radians can be easily handled by multiplying the frequency by JavaScript’s built-in constant π (math.pi) by 2. Also note that this expression adds the result of the calculation to the preceding expression value, and it oscillates around the static value of the keyframe or property.

Now it’s time to try to Control the frequency by binding the frequency variable freq directly to the Slider Control. Here’s the code:

freq = effect("Slider Control") ("Slider");
amp = 100;
value + amp*Math.sin(freq*time*Math.PI*2)
Copy the code

The figure below shows the keyframe values for Slider Control: frequency from 0 to 1, then held at 1, then from 1 to 2, then held at 2, then back to 0.

This shows the keyframe value for the Slider Control that controls the frequency.

The next graph shows the horrible result, which is not even what we wanted.

This is the messy result of trying to control math.sin () frequency directly with Slider control.

Once again, the linear keyframe integrator comes into play. Here’s the code:

freq = effect("Slider Control") ("Slider");
amp = 100;
n = freq.numKeys;
if (n > 0 && freq.key(1).time < time){
  accum = freq.key(1).value*(freq.key(1).time - inPoint);
  for (i = 2; i <= n; i++){
    if (freq.key(i).time > time) break;
    k1 = freq.key(i-1);
    k2 = freq.key(i);
    accum += (k1.value + k2.value)*(k2.time - k1.time)/2;
  }
  accum += (freq.value + freq.key(i-1).value)*(time - freq.key(i-1).time)/2;
}else{
  accum = freq.value*(time - inPoint);
}
value + amp*Math.sin(accum*Math.PI*2)
Copy the code

The figure below shows the improved result, which is very accurate. See it in action in the second image above.

The use of linear key frame integrator greatly improves the calculation results.