How to "sample" 2D cubic bezier for 1D "animation"

I'm working on audio for a game, and I'm trying to get frequency (and other parameters) interpolation for playing notes in a simple "tracker". I have several interpolation types, and one of them is to draw a curve in the editor that will drive the interpolation.

A way to do it is just to say that we pass the "time value" (normalized between 0 and 1) to the bezier curve, and use the resulting value as the output.

/*
p0 is the start value;
p1 is the end value;
cp0 is the first control point;
cp1 is the second control point;
All are single f32.
*/
f32 frequency_lerp_factor = bezier_cubic(p0, cp0, cp1, p1, t);

I can graph the curve by using t for x, and frequency_lerp_factor for y. This is (what I call) 1D. I can also graph the points and control points, but it gets confusing because their value would only be the y component, there isn't really a x here (except that p0 is at t = 0 and p1 is at t = 1. The control points, if I graph them, can be at any x in the graph, it doesn't matter where because their x value doesn't affect the curve.

Am I correct about it so far ?

But I'd like more control over the curve, so I want to "draw" a 2d curve using tangents (with some constraints to make sure the curve doesn't go backward). I've used 2d curves with tangents in the past while working on 3D/2D animations, so that was what I wanted when I started to work on the curve for interpolation.

In this case, the curve is controlled by 2D points, that I can graph normally, and I can get the curve by using bezier_cubic on x and y. But now, I think that to get the frequency lerp factor, I need to "sample" the resulting curve.

If I want to get the lerp factor (y) at x on the graph, I need to figure out which t will give me x, and use that t in bezier_cubic to get the y.

/* I don't know how to do bezier_cubic_inverse. */
f32 t = bezier_cubic_inverse( p0.x, cp0.x, cp1.x, p1.x, x );
f32 frequency_lerp_factor = bezier_cubic( p0.y, cp0.y, cp1.y, p1.y, t );

I tried to do the math and got to a point where it looks like I need to solve a cubic polynomial, which I looked a bit how to do, but it doesn't look like there is an easy way to do that on a computer.

This might be wrong. Only using x components of the points.
t³(-3p0+p1+3cp0-3cp1) + t²(3p0-6cp0+3cp1) + t(-3p0+3cp0) + p0 = x
Since p0, p1, cp0, cp1, x are known, we could compute the inside of the parenthesis
and it becomes:
t³a + t²b + tc + p0 = x
And we need to solve for t.

If all that is correct, is solving the equation the way to do this or is there another way ? Or have I misunderstood something ?


Edited by Simon Anciaux on