简体   繁体   English

Python 音频文件RMS幅度直方图

[英]Python histogram of RMS amplitude of audio file

I would like to make a histogram that bins RMS amplitude for an audio file.我想制作一个直方图,将音频文件的RMS 幅度分档。 The goal is to show, for the full duration of the file, how much of the signal is at each amplitude level.目标是在文件的整个持续时间内显示每个幅度级别的信号量。 Is there a Python package with a function for this?是否有 Python package 和 function 用于此? If not, how can it be coded?如果不是,如何编码?

I would also like to set the frequency range over which the analysis will be computed, eg between 1 and 6 kHz.我还想设置计算分析的频率范围,例如在 1 到 6 kHz 之间。

I have the following as a crude start, though I don't yet understand what it represents, and it certainly does not use RMS:我有以下粗略的开始,虽然我还不明白它代表什么,而且它当然不使用 RMS:

import numpy as np
import matplotlib.pyplot as plt
   
Fs, data = wavfile.read('file') 
print('data =',data)
print('number of samples in data =',len(data))

subset = data[0:44100] 
subset = abs(subset)
print('number of samples in subset =',len(subset))

plt.hist(subset, bins='auto')  
plt.show()

As far as I know, there is no special function in numpy for RMS, but you can do it like this据我所知,在 numpy 中没有专门的numpy用于 RMS,但你可以这样做

RMS = np.sqrt(np.mean(x**2))

And the question is, for which data (for which x ) do you want to calculate the RMS.问题是,您要针对哪些数据(针对哪些x )计算 RMS。 For example, you can apply RMS for each sample, than assuming you only have one channel in your wav-file:例如,您可以为每个样本应用 RMS,而不是假设您的 wav 文件中只有一个通道:

length = data.shape[0] / Fs
print(f"length = {length}s")

RMS = lambda x: np.sqrt(np.mean(x**2))

sample = np.arange(int(length))
RMS_of_sample = np.zeros(sample.shape)
for ns in sample:
    # here you can apply the frequency window for the sample 
    RMS_of_sample[ns] = RMS(data[ns*Fs:(ns+1)*Fs])

plt.hist(RMS_of_sample, label="Left channel")
plt.show()

here you can also apply some signal windows .在这里你也可以应用一些信号 windows This code gives you something like this这段代码给你这样的东西

在此处输入图像描述

for incoming signal:对于输入信号:

在此处输入图像描述


ADDITION to the question in the comment regarding full/partial frequency range关于全/部分频率范围的评论中的问题的补充

If you want to analyze a complete signal in a certain frequency domain, you can apply, for example, simple filter (rectangular frequency window) for the frequency range [filter_freq_min, filter_freq_max] like this:如果要分析某个频域中的完整信号,例如,可以对频率范围[filter_freq_min, filter_freq_max]应用简单滤波器(矩形频率窗口),如下所示:

from scipy.fft import fft, ifft, fftfreq

filter_freq_min = 1000 # Hz
filter_freq_max = 2000 # Hz

freq = fftfreq(len(data), 1 / Fs)
data_fft = fft(data)

condition = np.logical_or(abs(freq) <= filter_freq_min, abs(freq) >= filter_freq_max)
filtered_data_fft = np.copy(data_fft)
filtered_data_fft [condition] = 0
filtered_data = np.real(ifft(filtered_data_fft ))

# show fft for incoming signal (blue) and filtered signal (orange) 
plt.plot(freq, np.abs(data_fft),'.')
plt.plot(freq, np.abs(filtered_data_fft ),'.')
plt.xlim( [10, Fs/2] )
plt.xlabel( 'Frequency (Hz)' )
plt.show()

# check RMS for filtered and unfiltered signal
print(RMS(filtered_data),RMS(data))

在此处输入图像描述

In this way, you can cycle through the required frequency ranges.这样,您可以在所需的频率范围内循环。

To play sound directly in Python, you can use要直接在 Python 中播放声音,可以使用

import sounddevice as sd # For playing/recording audio
sd.play(data, Fs)
sd.play(filtered_data, Fs)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM