我正在编写一个 python 函数来返回 .wav 文件的响度。 RMS 似乎是最好的衡量标准,用python检测并记录声音 https://stackoverflow.com/questions/2668442/detect-and-record-a-sound-with-python.
audioop.rms()
可以解决问题,但我想避免将 audioop 作为依赖项,并且我已经导入了 numpy.但我没有得到相同的 RMS 值,并且希望能帮助您了解正在发生的情况。
来自音频页面 http://docs.python.org/library/audioop.html,它表示 rms 计算正是您所期望的,即sqrt(sum(S_i^2)/n)
, 在哪里,S_i
is the i
-th 声音样本。看起来这不是火箭科学。
要使用 numpy,我首先将声音转换为 numpy 数组,并且始终看到相同的最小值/最大值以及相同的数据长度(因此转换看起来很好)。
>>> d = np.frombuffer(data, np.int16)
>>> print (min(d), max(d)), audioop.minmax(data,2)
(-2593, 2749) (-2593, 2749)
但我得到的 RMS 值非常不同,甚至没有接近:
>>> numpy_rms = np.sqrt(sum(d*d)/len(d))
>>> print numpy_rms, audioop.rms(data, 2)
41.708703254716383, 120
它们之间的差异是可变的,我看不到明显的模式,例如,我也得到:
63.786714248938772, 402
62.779300661773405, 148
我的 numpy RMS 代码提供与此处相同的输出:信号的 Numpy 均方根 (RMS) 平滑 https://stackoverflow.com/questions/8245687/numpy-root-mean-squared-rms-smoothing-of-a-signal
我不知道哪里出了问题,但有些地方不对劲。非常感谢任何帮助。
编辑/更新:
如果它有用,这是我最终得到的代码。它不像audioop那么快,但仍然足够快,足以满足我的目的。值得注意的是,使用 np.mean() 比我使用 python sum() 的版本快得多(~100 倍)。
def np_audioop_rms(data, width):
"""audioop.rms() using numpy; avoids another dependency for app"""
#_checkParameters(data, width)
if len(data) == 0: return None
fromType = (np.int8, np.int16, np.int32)[width//2]
d = np.frombuffer(data, fromType).astype(np.float)
rms = np.sqrt( np.mean(d**2) )
return int( rms )