audioop.rms() - 为什么它与普通RMS不同?

时间:2012-03-19 00:05:57

标签: python numpy

我正在编写一个python函数来返回.wav文件的响度。 RMS似乎是最佳指标,Detect and record a sound with pythonaudioop.rms()可以解决这个问题,但是我想避免将audioop作为依赖项,而且我已经导入了numpy。但是我没有得到相同的RMS值,并且非常感谢帮助理解正在发生的事情。

audioop page开始,它说rms计算正是您所期望的,即sqrt(sum(S_i^2)/n),其中,S_ii的样本声音。似乎它不是火箭科学。

要使用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 )

2 个答案:

答案 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))