python 频率数组的音调扫描

Tone sweep from array of frequencies with python

我有一个包含频率值的数组,我想生成带有在给定值之间扫过的音调的 wav 文件。说

freqs = [100, 100, 200, 400, 1000, 100, 50]
duration = 7

我想要时长为 7 秒的 WAV。所以从 T=0 到 T=1s 音调应该是 100Hz,从 T=1 到 T=2 扫频从 100Hz 到 200Hz 等等。

如何生成要传递给 scipy.io.wavfile.write 的波形?

以下是如何针对两个任意频率执行此操作:

import numpy as np
from scipy.signal import chirp
from scipy.io.wavfile import write

interval_length = 1 # in seconds
fs = 16000 # sampling of your signal
f0 = 100   # frequency 1
f1 = 200   # frequency 2
t = np.linspace(0, interval_length, int(fs * interval_length))
w = chirp(t, f0=f0, f1=f0, t1=interval_length, method='linear') # check also other methods
write('test.wav', fs, w)

我留给你做一个练习,让你在你拥有的一组频率的循环中做这个。

作为 this can be done with np.chirp():

import numpy as np
from scipy.signal import chirp
from scipy.io.wavfile import write

duration = 30 
Fs = 16000
freqs = [100, 100, 300, 300, 600, 100, 100]

segment = int(Fs * duration /  (len(freqs)-1))
f = np.array(freqs) / Fs
wav = np.array(1)
for f0, f1 in zip(f[:-1], f[1:]):
    wav = np.append(wav, chirp(np.arange(segment), f0=f0, t1=segment, f1=f1))

write('test.wav', Fs, wav)

这给出了很好的频谱图: 在这里收听:https://soundcloud.com/dcoder_mm/npchip/s-Kx8L2vN0nfv

它有效,但您会注意到(在频谱上和聆听时)一些咔嗒声。

让我们尝试降低频率:

freqs = [100, 100, 300, 300, 600, 100, 100]

在这里收听:https://soundcloud.com/dcoder_mm/dj-npchirp-feat-low-frequencies/s-fNsA61bJ0Wk

事情变得更糟了。为什么?

由于两个线性调频信号合并点的相位误差:

为了摆脱这个,我们需要计算相位校正。根据最后一点的 wiki 阶段(对于 线性 线性调频!)将是:

phi = T*(f1+f0)/2

所以这将完成工作:

import numpy as np
from scipy.signal import chirp
from scipy.io.wavfile import write

duration = 30 
Fs = 16000
freqs = [100, 100.5, 99, 99.3, 100.1, 100]

segment = int(Fs * duration / (len(freqs)-1))
f = np.array(freqs) / Fs
wav = np.array(1)

phase = 0
for f0, f1 in zip(f[:-1], f[1:]):
    wav = np.append(wav, chirp(np.arange(segment), f0=f0, t1=segment, f1=f1, phi=phase))
    phase = phase + 360*(segment*(f0+f1)/2)

write('test3.wav', Fs, wav)

听:https://soundcloud.com/dcoder_mm/dj-npchirp-feat-low-frequencies-phase-c/s-XneSWRlojLD

注意phi = T*(f1+f0)/2只适用于线性调频。对于其他方法,您需要不同的相位公式。 另请参阅 this question