Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

atan2 for two sinusoids of arbitrary phase shift?

I'm trying to implement an atan2-like function to map two input sinusoidal signals of arbitrary relative phase shift to a single output signal that linearly goes from 0 to . atan2 normally assumes two signals with a 90 deg phase shift.

Given y0(x) = sin(x) and y1 = sin(x + phase), where phase is a fixed non-zero value, how can I implement a way to return x modulo ?

like image 438
tarabyte Avatar asked Dec 23 '22 23:12

tarabyte


1 Answers

atan2 returns the angle of a 2d vector. Your code does not handle such scaling properly. But no worries, it's actually very easy to reduce your problem to an atan2 that would handle everything nicely.

Notice that calculating sin(x) and sin(x + phase) is the same as projecting a point (cos(x), sin(x)) onto the axes (0, 1) and (sin(phase), cos(phase)). This is the same as taking dot products with those axes, or transforming the coordinate system from the standard orthogonal basis into the skewed one. This suggests a simple solution: inverse the transformation to get the coordinates in the orthogonal basis and then use atan2.

Here's a code that does that:

double super_atan2(double x0, double x1, double a0, double a1) {
    double det = sin(a0 - a1);
    double u = (x1*sin(a0) - x0*sin(a1))/det;
    double v = (x0*cos(a1) - x1*cos(a0))/det;
    return atan2(v, u);
}

double duper_atan2(double y0, double y1, double phase) {
    const double tau = 6.28318530717958647692; // https://tauday.com/
    return super_atan2(y0, y1, tau/4, tau/4 - phase);
}

super_atan2 gets the angles of the two projection axes, duper_atan2 solves the problem exactly as you stated.

Also notice that the calculation of det is not strictly necessary. It is possible to replace it by fmod and copysign (we still need the correct sign of u and v).

like image 137
Yakov Galka Avatar answered Dec 28 '22 10:12

Yakov Galka