我找到了一种算法,它使用自相关和抛物线插值来估计音频信号的频率。
# correct the signal.
auto = scipy.signal.fftconvolve(signal, signal[::-1], mode='full')
auto = auto[len(auto)/2:]
# find the first minimum point in the signal.
difference = numpy.diff(auto)
start = matplotlib.mlab.find(difference > 0)[0]
# find the peak from that position.
peak = numpy.argmax(auto[start:]) + start
# calculate the period using parabolic interpolation.
period = 1/2.0 * (auto[peak-1] - auto[peak+1]) / (auto[peak-1] - 2 * auto[peak] + auto[peak+1]) + peak
frequency = sample_rate / period
我知道人类听觉的范围是 20Hz 到 20kHz 。采样率 44100Hz ,我可以准确地写入和读取 22049Hz 。但是,该算法会误认为某些频率。
给定 840Hz 的信号,它读取 420Hz 。在 20000Hz 时,算法计算 512Hz 。该算法在准确的估计之间振荡并返回不正确的频率。
我对信号处理知之甚少。
答案 0 :(得分:0)
如果您想估算纯模拟信号的频率,傅里叶变换完全符合您的需求。
import numpy as np
SAMPLE_RATE = 48000
FREQUENCY = 840.0
# simulated pure signal
t = np.linspace(0, 1, SAMPLE_RATE)
signal = np.sin(2 * np.pi * FREQUENCY * t)
# compute the magnitude of the Fourier Transform and its corresponding frequency values
freq_magnitudes = np.abs(np.fft.fft(signal))
freq_values = np.fft.fftfreq(SAMPLE_RATE, 1/SAMPLE_RATE)
# find the max. magnitude
max_positive_freq_idx = np.argmax(freq_magnitudes[:SAMPLE_RATE//2 + 1])
print(freq_values[max_positive_freq_idx]) # 840.0
如果您不熟悉傅里叶变换,例如看看史蒂芬史密斯的第8章The Scientist and Engineer's Guide to Digital Signal Processing。