- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我想为 Iphone 构建一个吉他调音器应用程序。我的目标是找到吉他弦产生的声音的基频。我使用了 Apple 提供的 aurioTouch 示例中的一些代码来计算频谱,并找到了幅度最高的频率。它对于纯声音(只有一种频率的声音)效果很好,但对于来自吉他弦的声音,它会产生错误的结果。我读到这是因为吉他弦产生的泛音可能具有比基音更高的振幅。如何找到适用于吉他弦的基频? C/C++/Obj-C 中是否有用于声音分析(或信号处理)的开源库?
最佳答案
您可以使用信号的自相关,它是 DFT 幅度平方的逆变换。如果您以 44100 个样本/秒的速率进行采样,则 82.4 Hz 基波大约有 535 个样本,而 1479.98 Hz 大约有 30 个样本。查找该范围内的峰值正滞后(例如从 28 到 560)。确保您的窗口至少是最长基本面的两个周期,此处为 1070 个样本。 2 的下一个幂就是 2048 个样本缓冲区。为了获得更好的频率分辨率和更少偏差的估计,请使用更长的缓冲区,但不要太长,以免信号不再近似静止。下面是一个 Python 示例:
from pylab import *
import wave
fs = 44100.0 # sample rate
K = 3 # number of windows
L = 8192 # 1st pass window overlap, 50%
M = 16384 # 1st pass window length
N = 32768 # 1st pass DFT lenth: acyclic correlation
# load a sample of guitar playing an open string 6
# with a fundamental frequency of 82.4 Hz (in theory),
# but this sample is actually at about 81.97 Hz
g = fromstring(wave.open('dist_gtr_6.wav').readframes(-1),
dtype='int16')
g = g / float64(max(abs(g))) # normalize to +/- 1.0
mi = len(g) / 4 # start index
def welch(x, w, L, N):
# Welch's method
M = len(w)
K = (len(x) - L) / (M - L)
Xsq = zeros(N/2+1) # len(N-point rfft) = N/2+1
for k in range(K):
m = k * ( M - L)
xt = w * x[m:m+M]
# use rfft for efficiency (assumes x is real-valued)
Xsq = Xsq + abs(rfft(xt, N)) ** 2
Xsq = Xsq / K
Wsq = abs(rfft(w, N)) ** 2
bias = irfft(Wsq) # for unbiasing Rxx and Sxx
p = dot(x,x) / len(x) # avg power, used as a check
return Xsq, bias, p
# first pass: acyclic autocorrelation
x = g[mi:mi + K*M - (K-1)*L] # len(x) = 32768
w = hamming(M) # hamming[m] = 0.54 - 0.46*cos(2*pi*m/M)
# reduces the side lobes in DFT
Xsq, bias, p = welch(x, w, L, N)
Rxx = irfft(Xsq) # acyclic autocorrelation
Rxx = Rxx / bias # unbias (bias is tapered)
mp = argmax(Rxx[28:561]) + 28 # index of 1st peak in 28 to 560
# 2nd pass: cyclic autocorrelation
N = M = L - (L % mp) # window an integer number of periods
# shortened to ~8192 for stationarity
x = g[mi:mi+K*M] # data for K windows
w = ones(M); L = 0 # rectangular, non-overlaping
Xsq, bias, p = welch(x, w, L, N)
Rxx = irfft(Xsq) # cyclic autocorrelation
Rxx = Rxx / bias # unbias (bias is constant)
mp = argmax(Rxx[28:561]) + 28 # index of 1st peak in 28 to 560
Sxx = Xsq / bias[0]
Sxx[1:-1] = 2 * Sxx[1:-1] # fold the freq axis
Sxx = Sxx / N # normalize S for avg power
n0 = N / mp
np = argmax(Sxx[n0-2:n0+3]) + n0-2 # bin of the nearest peak power
# check
print "\nAverage Power"
print " p:", p
print "Rxx:", Rxx[0] # should equal dot product, p
print "Sxx:", sum(Sxx), '\n' # should equal Rxx[0]
figure().subplots_adjust(hspace=0.5)
subplot2grid((2,1), (0,0))
title('Autocorrelation, R$_{xx}$'); xlabel('Lags')
mr = r_[:3 * mp]
plot(Rxx[mr]); plot(mp, Rxx[mp], 'ro')
xticks(mp/2 * r_[1:6])
grid(); axis('tight'); ylim(1.25*min(Rxx), 1.25*max(Rxx))
subplot2grid((2,1), (1,0))
title('Power Spectral Density, S$_{xx}$'); xlabel('Frequency (Hz)')
fr = r_[:5 * np]; f = fs * fr / N;
vlines(f, 0, Sxx[fr], colors='b', linewidth=2)
xticks((fs * np/N * r_[1:5]).round(3))
grid(); axis('tight'); ylim(0,1.25*max(Sxx[fr]))
show()
输出:
Average Power
p: 0.0410611012542
Rxx: 0.0410611012542
Sxx: 0.0410611012542
峰值滞后为 538,即 44100/538 = 81.97 Hz。首轮非循环 DFT 显示 bin 61 处的基波,即 82.10 +/- 0.67 Hz。第二遍使用 538*15 = 8070 的窗口长度,因此 DFT 频率包括弦的基波周期和谐波。这可以实现泛化循环自相关,从而以更少的谐波扩展来改进 PSD 估计(即相关性可以周期性地环绕窗口)。
编辑:更新为使用韦尔奇方法来估计自相关。重叠窗口可以补偿汉明窗。我还计算了汉明窗的锥形偏差以消除自相关的偏差。
编辑:添加了具有循环相关性的第二遍以清理功率谱密度。此过程使用 3 个不重叠的矩形窗口,长度为 538*15 = 8070(足够短以几乎静止)。循环相关的偏差是一个常数,而不是汉明窗的锥形偏差。
关于audio - 如何找到吉他弦声音的基频?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5044289/
这是我的代码的链接:http://jsbin.com/ebadic/9/edit 它来 self 在这里找到的演示(此链接解释了它是如何工作的,我正在使用的部分位于底部): http://www.ht
关闭。这个问题不满足Stack Overflow guidelines .它目前不接受答案。 想改善这个问题吗?更新问题,使其成为 on-topic对于堆栈溢出。 2年前关闭。 Improve thi
我是一名优秀的程序员,十分优秀!