atan2 用于任意相移的两个正弦波?
atan2 for two sinusoids of arbitrary phase shift?
我正在尝试实现一个类似 atan2 的函数,以将任意相对相移的两个输入正弦信号映射到从 0
到 2π
线性变化的单个输出信号。 atan2
通常假定两个信号具有 90 度相移。
给定 y0(x) = sin(x)
和 y1 = sin(x + phase)
,其中 phase
是固定的非零值,我如何实现 return x
模的方法2π
?
atan2
returns 二维向量的角度。您的代码无法正确处理此类缩放。但不用担心,实际上很容易将您的问题减少到可以很好地处理所有问题的 atan2
。
请注意,计算 sin(x)
和 sin(x + phase)
与将点 (cos(x), sin(x))
投影到轴 (0, 1)
和 (sin(phase), cos(phase))
相同。这与使用这些轴进行点积,或将坐标系从标准正交基转换为倾斜基相同。这提出了一个简单的解决方案:反转变换以获得正交基中的坐标,然后使用 atan2
.
这是执行此操作的代码:
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
得到两个投影轴的角度,duper_atan2
完全按照你说的解决问题。
另请注意,det
的计算并非绝对必要。可以用fmod
和copysign
代替(我们还需要u
和v
的正确符号)。
推导:
代码中:
// assume phase != k * pi, for any integer k
double f (double y0, double y1, double phase)
{
double u = (- y0 * cos(phase) + y1) / sin(phase);
double v = y0;
double x = atan2 (v, u);
return (x < 0) ? (x + 2 * M_PI) : x;
}
我正在尝试实现一个类似 atan2 的函数,以将任意相对相移的两个输入正弦信号映射到从 0
到 2π
线性变化的单个输出信号。 atan2
通常假定两个信号具有 90 度相移。
给定 y0(x) = sin(x)
和 y1 = sin(x + phase)
,其中 phase
是固定的非零值,我如何实现 return x
模的方法2π
?
atan2
returns 二维向量的角度。您的代码无法正确处理此类缩放。但不用担心,实际上很容易将您的问题减少到可以很好地处理所有问题的 atan2
。
请注意,计算 sin(x)
和 sin(x + phase)
与将点 (cos(x), sin(x))
投影到轴 (0, 1)
和 (sin(phase), cos(phase))
相同。这与使用这些轴进行点积,或将坐标系从标准正交基转换为倾斜基相同。这提出了一个简单的解决方案:反转变换以获得正交基中的坐标,然后使用 atan2
.
这是执行此操作的代码:
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
得到两个投影轴的角度,duper_atan2
完全按照你说的解决问题。
另请注意,det
的计算并非绝对必要。可以用fmod
和copysign
代替(我们还需要u
和v
的正确符号)。
推导:
代码中:
// assume phase != k * pi, for any integer k
double f (double y0, double y1, double phase)
{
double u = (- y0 * cos(phase) + y1) / sin(phase);
double v = y0;
double x = atan2 (v, u);
return (x < 0) ? (x + 2 * M_PI) : x;
}