平滑地连接来自输入的正弦波
Smoothly concatenating sine waves from input
上个月,我发布了 关于如何在生成正弦波时连接正弦波,但现在我遇到了不同的情况,我将生成一个正弦波并使其从末尾继续另一个我没有生成的正弦波。
我的解决方案基于我上一个问题的第二个答案,计算希尔伯特变换,然后用 numpy.angle 计算角度并通过添加 90 对其进行归一化,并从那里生成下一个正弦。它有效,但只有当我的频率值的单位是 0 或 5 时,否则,波不匹配,我不知道为什么。
from scipy.signal import hilbert
import numpy as np
from matplotlib import pyplot as plt
N = 1024
t = np.linspace(0, 1, N)
freq = 5.0
c = np.sin(2 * np.pi * freq * t + 0.0)
c2 = np.angle(hilbert(c), True) # in degrees
plt.subplot(2, 1, 1)
plt.grid()
plt.plot(c)
plt.subplot(2, 1, 2)
phase = c2[-1] + 90
c3 = np.sin(2.0 * np.pi * freq * t + np.deg2rad(phase))
plt.grid()
plt.plot(c3)
plt.show()
频率:5.0
频率:5.8
当时间间隔开始和结束的值不一致时,就会出现边界效应,从而扭曲希尔伯特变换。 (回想一下,傅里叶变换对不连续性的反应很差。)这可以通过绘制 c2
的末端看出: plt.plot(c2[-200:] + 90)
:注意末端的失真,曲线应该以恒定斜率上升。
从时间边缘后退一段会得到更好的结果window:
phase = c2[-1 - int(N//freq)] + 90
我尝试使用频率 5.8:第二条曲线的开头与第一条曲线的结尾相匹配。
不清楚您的确切问题范围是什么。在上一个问题中,在引发此后续问题的评论中,您说:
If I don't have the generation equation ( say, I've got a chunk from mic ) what would be the approach?
这是否意味着数据不一定是正弦波?吵吗?它的大小不同吗?你提到 DSP:你是在实时进行处理,还是可以根据需要进行分析?
如果它是已知幅度的干净正弦波,则相对容易从信号末尾提取相位,以实现平滑延续。
阶段是sin⁻¹(y/mag)
。 sin(angle)
有两个输入,其结果为 y/mag
,一个用于 sin(angle)
随着 angle
的增加而增加,一个用于减少。通过查看上一点,我们可以确定我们需要哪一个。
def ending_phase(c, mag):
angle = math.asin(c[-1] / mag)
if c[-2] > c[-1]:
angle = np.pi - angle
return angle
从最后一个点的相位和倒数第二个点的相位,我们可以推断出下一个点的相位。
def next_phase(c, mag):
ph1 = ending_phase(c[:-1], mag)
ph2 = ending_phase(c, mag)
return 2 * ph2 - ph1
将前一个块传递给 next_phase()
计算平滑地继续块所需的相位参数。
N = 1024
t = np.linspace(0, 1, N)
mag = 1.2
freq = 5.2
phase = 2.2
c1 = mag * np.sin(2 * np.pi * freq * t + phase)
plt.subplot(2,2,1)
plt.grid()
plt.plot(c1)
freq = 3.8
phase = next_phase(c1, mag)
c2 = mag * np.sin(2 * np.pi * freq * t + phase)
plt.subplot(2,2,2)
plt.grid()
plt.plot(c2)
c3 = np.concatenate((c1, c2))
plt.subplot(2,1,2)
plt.grid()
plt.plot(c3)
plt.show()
上个月,我发布了
我的解决方案基于我上一个问题的第二个答案,计算希尔伯特变换,然后用 numpy.angle 计算角度并通过添加 90 对其进行归一化,并从那里生成下一个正弦。它有效,但只有当我的频率值的单位是 0 或 5 时,否则,波不匹配,我不知道为什么。
from scipy.signal import hilbert
import numpy as np
from matplotlib import pyplot as plt
N = 1024
t = np.linspace(0, 1, N)
freq = 5.0
c = np.sin(2 * np.pi * freq * t + 0.0)
c2 = np.angle(hilbert(c), True) # in degrees
plt.subplot(2, 1, 1)
plt.grid()
plt.plot(c)
plt.subplot(2, 1, 2)
phase = c2[-1] + 90
c3 = np.sin(2.0 * np.pi * freq * t + np.deg2rad(phase))
plt.grid()
plt.plot(c3)
plt.show()
频率:5.0
频率:5.8
当时间间隔开始和结束的值不一致时,就会出现边界效应,从而扭曲希尔伯特变换。 (回想一下,傅里叶变换对不连续性的反应很差。)这可以通过绘制 c2
的末端看出: plt.plot(c2[-200:] + 90)
:注意末端的失真,曲线应该以恒定斜率上升。
从时间边缘后退一段会得到更好的结果window:
phase = c2[-1 - int(N//freq)] + 90
我尝试使用频率 5.8:第二条曲线的开头与第一条曲线的结尾相匹配。
不清楚您的确切问题范围是什么。在上一个问题中,在引发此后续问题的评论中,您说:
If I don't have the generation equation ( say, I've got a chunk from mic ) what would be the approach?
这是否意味着数据不一定是正弦波?吵吗?它的大小不同吗?你提到 DSP:你是在实时进行处理,还是可以根据需要进行分析?
如果它是已知幅度的干净正弦波,则相对容易从信号末尾提取相位,以实现平滑延续。
阶段是sin⁻¹(y/mag)
。 sin(angle)
有两个输入,其结果为 y/mag
,一个用于 sin(angle)
随着 angle
的增加而增加,一个用于减少。通过查看上一点,我们可以确定我们需要哪一个。
def ending_phase(c, mag):
angle = math.asin(c[-1] / mag)
if c[-2] > c[-1]:
angle = np.pi - angle
return angle
从最后一个点的相位和倒数第二个点的相位,我们可以推断出下一个点的相位。
def next_phase(c, mag):
ph1 = ending_phase(c[:-1], mag)
ph2 = ending_phase(c, mag)
return 2 * ph2 - ph1
将前一个块传递给 next_phase()
计算平滑地继续块所需的相位参数。
N = 1024
t = np.linspace(0, 1, N)
mag = 1.2
freq = 5.2
phase = 2.2
c1 = mag * np.sin(2 * np.pi * freq * t + phase)
plt.subplot(2,2,1)
plt.grid()
plt.plot(c1)
freq = 3.8
phase = next_phase(c1, mag)
c2 = mag * np.sin(2 * np.pi * freq * t + phase)
plt.subplot(2,2,2)
plt.grid()
plt.plot(c2)
c3 = np.concatenate((c1, c2))
plt.subplot(2,1,2)
plt.grid()
plt.plot(c3)
plt.show()