- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我正在尝试实现生成正弦波的 Python 方法,该正弦波在两个频率之间呈指数上升。[this question] 中解决了线性变化使用以下 Python 代码:
from math import pi, sin
def sweep(f_start, f_end, interval, n_steps):
for i in range(n_steps):
delta = i / float(n_steps)
t = interval * delta
phase = 2 * pi * t * (f_start + (f_end - f_start) * delta / 2)
print t, phase * 180 / pi, 3 * sin(phase)
sweep(1, 10, 5, 1000)
如何将这种线性累积相位/增量方法更改为指数频率扫描并使人耳平滑。
最佳答案
这类问题的诀窍是理解 frequency modulation 之间的关系和 phase modulation ,这两者是密切相关的。具有恒定频率 f
和幅度 A
的正弦可以描述为(公式,不是 python 代码):
x(t) = A sin(2 * pi * f * t)
但是另一种写法是首先定义一个阶段 phi
作为时间的函数:
phi(t) = 2 * pi * f * t
x(t) = A sin(phi(t))
这里需要注意的是,频率f
是相位的导数,除以2*pi:f = d/dt(phi(t))/(2* pi)
.
对于频率随时间变化的信号,您可以类似地定义一个瞬时频率 f_inst
:
x(t) = A sin(phi(t))
f_inst = d/dt(phi(t)) / (2*pi)
你想要做的与此相反,你有一个给定的瞬时频率(你的对数扫描),你需要将其转换为相位。由于推导的对立面是积分,因此您可以像这样计算适当的相位(仍然是公式):
phi(t) = 2 * pi * Integral_0_to_t {f_inst(t) dt}
x(t) = A sin(phi(t))
您在这里所做的是对信号(频率为零)进行某种相位调制以获得所需的瞬时频率。这在 numpy 中很容易做到:
from pylab import *
n = 1000 # number of points
f1, f2 = 10, 30 # frequency sweep range in Hertz
t = linspace(0,1,1000)
dt = t[1] - t[0] # needed for integration
# define desired logarithmic frequency sweep
f_inst = logspace(log10(f1), log10(f2), n)
phi = 2 * pi * cumsum(f_inst) * dt # integrate to get phase
# make plot
plot(t, sin(phi))
xlabel('Time (s)')
ylim([-1.2, 1.2])
grid()
show()
结果图像:
但是(正如 Dave 提到的 dupe 中也提到的),您可能不需要对数扫描,而是指数扫描。您的耳朵对频率具有对数感知,因此平滑/线性音阶(想想钢琴上的琴键)因此呈指数间隔。这可以通过简单地重新定义您的瞬时频率 f_inst(t) = f1 * exp(k * t)
来实现,其中选择 k
使得 f_inst(t2 ) = f2
。
如果你想使用amplitude modulation同时,您可以简单地将公式中的 A
更改为时间相关的 A(t)
。
关于python - 在给定时间/样本量下,频率 f1 和 f2 之间呈指数变化的正弦波,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19771328/
我是一名优秀的程序员,十分优秀!