audioop.rms () - почему он отличается от обычного RMS? - PullRequest
6 голосов
/ 19 марта 2012

Я пишу функцию Python, которая возвращает громкость WAV-файла. RMS, кажется, является лучшим показателем для этого, Обнаружение и запись звука с python . audioop.rms() делает свое дело, но я хотел бы избежать аудиоопиции как зависимости, и я уже импортирую numpy. но я не получаю те же среднеквадратичные значения и был бы признателен за помощь в понимании происходящего.

На странице audioop говорится, что среднеквадратичное вычисление - это то, что вы ожидаете, а именно 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)

но я получаю очень разные среднеквадратичные значения, даже не близко к шарам:

>>> 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

Мой код NMS NUMPY дает такой же результат, как и здесь: Сглаживание среднеквадратичного значения (RMS) сигнала

Я не вижу, где я иду не так, но что-то не так. Любая помощь высоко ценится.


РЕДАКТИРОВАНИЕ / ОБНОВЛЕНИЕ:

В случае, если это полезно, вот код, которым я закончил. Это не так быстро, как Audioop, но все еще достаточно быстро, достаточно хорошо для моих целей. Следует отметить, что использование np.mean () делает его НАМНОГО быстрее (~ 100x), чем моя версия с использованием python sum ().

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 ]

9 голосов
/ 19 марта 2012

Выполните вычисления, используя double, как в audioop.rms() код :

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
0 голосов
/ 19 марта 2012

От 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))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...