Musical Keyboard

Welcome to my CPE 474 final project: the Animated Keyboard!

Press these buttons to make different sounds:






Timing Functions

Each of the cube-instruments use a different timing function to achieve their motion. For each movement, I pass in a start transform, an ending transform and a duration. Without the timing function, each animation would simply linearly go from the starting transform to the ending transform.

This would be super boring. Instead, I modify each animation with a timing function. First, I normalize the time elapsed for each animation. That is, instead of going from (starting milliseconds) to (ending milliseconds), each animation goes from 0 to 1. Then, I pass in the normalized time parameter into my timing function.

Javascript lets you treat functions like variables and argument parameters, so the entire function to animate a cube looks like:
animate_cube( cube, start_transform, end_transform, duration, timing_function );


Timing Function Examples

Shimmy

Without the timing function, it looks like this:
It simply goes from big -> small, and makes one quarter-turn. We apply its timing function:
function shimmy(u) {
    return Math.random() * (1 - u) + u;
}
When u == 0, the result is random between 0 and 1.
At u == 0.5, the result is random between 0.5 and 1.
At u == 1, the result is always 1.

As u goes from 0 to 1, it restricts the space that the function can land on, eventually landing on exactly 1. So the end result is a sort of "jitter" as it bounces around different angles, until it finally settles on the end transform, at u == 1.


Clap

Without the timing function, it looks like this:

It rotates and moves in a random direction. Here's the timing function(s):
function easeIn(u) {
    return u*u*u;
}

function clap(u) {
    return easeIn(1 - u);
}
As you can see, we can easily chain timing functions by calling one from another. In this case, clap() simply runs the easeIn function backwards, so it runs from the end transform to the start transform. I could've achieved the same effect just by switching the transforms in the animation function call, but this was cooler.

Remember that cubing a value below 1 makes it smaller, in a curvy shape that passes through (1, 1):
As you can see from the "clapping" cube, it starts moving quickly (at u == 1) and eases slowly back towards 0. I use the "ease" effect for the bass drum cube as well.

Double-tap

Finally, the double-tap:
This is an interesting one. Without a timing function, it looks like this:
Here's what the timing function looks like:
function instant(u) {
    if (u < 0.5) {
        return 0;
    }
    else {
        return 1;
    }
}
If u is less than 1/2, it returns 0. Otherwise, it returns 1. This makes the animation abruptly jump from the starting transform to the ending transform, then back again, giving a quick "click" animation.

Final Remarks

As you can see, timing functions are pretty powerful. I used similar timing functions to control the bouncy cubes and the particles that shrink and disappear. You can check out the timing code I wrote right here. It's well-documented and contains some stuff you might recognize from a graphics class, like lerpVectors and slerp. Check it out!