我正在编写一个python函数来返回.wav文件的响度。 RMS似乎是最佳指标,Detect and record a sound with python。
audioop.rms()
可以解决这个问题,但是我想避免将audioop作为依赖项,而且我已经导入了numpy。但是我没有得到相同的RMS值,并且非常感谢帮助理解正在发生的事情。
从audioop page开始,它说rms计算正是您所期望的,即sqrt(sum(S_i^2)/n)
,其中,S_i
是i
的样本声音。似乎它不是火箭科学。
要使用numpy,我首先将声音转换为numpy数组,并始终看到相同的min / max和相同的数据长度(因此转换似乎很好)。
>>> 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 Root-Mean-Squared (RMS) smoothing of a signal
我不知道我哪里出错了,但有些事情已经过去了。任何帮助非常感谢。
已编辑/更新:
如果它有用,这是我最终得到的代码。它不像audioop那么快,但仍然足够快,足够我的目的。值得注意的是,使用np.mean()比使用python sum()的版本快得多(~100x)。
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 )
答案 0 :(得分:8)
使用audioop.rms()
code中的double
执行计算:
d = np.frombuffer(data, np.int16).astype(np.float)
>>> import audioop, numpy as np
>>> data = 'abcdefgh'
>>> audioop.rms(data, 2)
25962
>>> d = np.frombuffer(data, np.int16)
>>> np.sqrt((d*d).sum()/(1.*len(d)))
80.131142510262507
>>> d = np.frombuffer(data, np.int16).astype(np.float)
>>> np.sqrt((d*d).sum()/len(d))
25962.360851817772
答案 1 :(得分:0)
来自matplotlib.mlab:
def rms_flat(a):
"""
Return the root mean square of all the elements of *a*, flattened out.
"""
return np.sqrt(np.mean(np.absolute(a)**2))