【问题标题】:Smoothly concatenating sine waves from input从输入平滑连接正弦波
【发布时间】:2018-07-10 05:44:52
【问题描述】:

上个月,我在this question 上发布了关于在生成正弦波时如何连接它们的帖子,但现在我遇到了不同的情况,我将生成一个正弦波并使其从我所做的另一个正弦波的末尾继续不生成。

我的解决方案基于我上一个问题的第二个答案,计算希尔伯特变换,然后用 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

【问题讨论】:

    标签: python numpy scipy signal-processing


    【解决方案1】:

    当时间间隔开始和结束的值不一致时,会出现边界效应,从而扭曲希尔伯特变换。 (回想一下,傅里叶变换对不连续性的反应很差。)这可以通过绘制c2 的末端看到:plt.plot(c2[-200:] + 90):注意接近末端的失真,曲线应该以恒定斜率上升。

    从时间窗口的边缘后退一个周期会得到更好的结果:

    phase = c2[-1 - int(N//freq)] + 90
    

    我尝试使用频率 5.8:第二条曲线的起点与第一条曲线的终点相匹配。

    【讨论】:

    • 假设我没有第一波的确切频率(我的问题就是这种情况)这种方法行不通,对吧?
    • 并假设我没有获得确切频率的可靠方法(可能是这种情况)。
    • 另外,我用你非常受欢迎的解决方案做了一些测试,而且奇怪的是,当我用频率 = 18.0 进行测试时,图表略有损坏。
    • np.angle(hilbert(c)) 中的跳跃很好地处理了频率(它们每个周期发生一次)。对于高频,也许后退一个周期不足以避免边界效应......另外,也许这是一个愚蠢的建议,但为什么不匹配两个波的结束/开始值呢?找到适合第一波结束的第二个值,然后从那里开始。还要检查增加的方向。
    • 这不是一个愚蠢的建议,我只是想解决这个问题,所以我可以学习并为我的客户制作一个好的产品,这就是我想出的解决方案,也是我我是 DSP 新手,如果您知道更好的方法,请随时为我指明方向。
    【解决方案2】:

    尚不清楚您的确切问题范围是什么。在上一个问题中,在引发此后续问题的评论中,您说:

    如果我没有生成方程(比如说,我从 mic 中得到了一个块),那么方法是什么?

    这是否意味着数据不一定是正弦波?吵吗?它的大小不同吗?您提到了 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()
    

    【讨论】:

    • 感谢 AJ(再次),我怕我把事情简单化的意图让我听起来含糊不清,我会尽量不要再这样做了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多