python - 使用 librosa 计算光谱质心
问题描述
我发现了以下两种计算光谱质心的方法,但它们不会返回相同的值。
哪个是正确的版本,两者有何不同?
1.
def spectral_centroid(x, samplerate=44100):
magnitudes = np.abs(np.fft.rfft(x)) # magnitudes of positive frequencies
length = len(x)
freqs = np.abs(np.fft.fftfreq(length, 1.0/samplerate)[:length//2+1]) # positive frequencies
return np.sum(magnitudes*freqs) / np.sum(magnitudes)
2.
cent = librosa.feature.spectral_centroid(y=y, sr=sr)
print(np.mean(cent.T, axis=0))
解决方案
如果您遵循正确的公式,那么两者都应该是正确的。不过我会选择librosa实现,因为我相信它背后的开发团队。显然,如果它在您的用例中提供优势,您也可以使用您的方法。
现在让我们解决为什么结果不同?这是因为您的方法使用了numpy.fft.rfft中实现的离散傅里叶变换 (DFT),而librosa.feature.spectral_centroid方法使用的是短时傅里叶变换 (STFT)。您可以通过查看以下 librosa 链接来验证这一点:spectral-centroid & spectrum。
STFT 和 DFT 具有不同的优势,因此由于 STFT 是时间相关的,并且不会丢失时间变化的信息,因此它比 DFT 计算量更大且速度更慢。
推荐阅读
- reactjs - 如何使用函数为 React-Router 制作地图?
- ios - 如何在 SwiftUI 中将项目与 VStack 内的顶部对齐?
- node.js - 使用 sequelize 在 nodejs 和 Postgres 中插入错误
- android - 在android studio中运行我的第一个flutter应用程序时出现问题
- python - Python 是否有 Parquet 等价物?
- android - 如何在不复制和粘贴其父 onMeasure 实现的情况下修改自定义 TextView WRAP_CONTENT 高度?
- javascript - 如何在 React js 中读取和更新 csv 文件
- flutter - 向 Flutter 中的默认 User 类添加新属性
- python - 蟒龟在移动时留下点
- jenkins - 如何在 jenkins 文件中获取 hg 分支名称