Я пишу функцию 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 )