仅作为操作记录,大佬请跳过
关于手机录一段声音,用python分析——加载和显示
可参考博主文章 传送门
关于手机录一段声音,用python分析——分帧显示
可参考博主文章传送门
关键点
求各帧对应的time
思路
所谓短时能量,即将对时域信号,分成若干小段(小段信号的长度<<信号总长度)——将各小段的各点平方后,小段内加和,得出一个值,这一个值,代表这一小段的所有的点(作为能量);其他小段能量也是这样。
本例,信号总长256000个点,分成了1997段信号——最终得出1997个点——1997个点plot成图——横轴time(0~5.333秒)想办法对应这1997个点。即得出短时能量。
程序小注
在获取每帧信号组成的几行的矩阵后(含重叠),加入了如下代码即可求出原信号的短时能量
(即矩阵一行代表一段信号,一行代表一段信号;有几行代表分成了几段;博主有1997行,也就是把原信号分成了1997段)
关于矩阵的各行统一求和:
np.sum(矩阵,axis=1) # axis=1表示每行每行求和
直接上代码
import wave
import numpy as np
from matplotlib.pyplot import *
f=wave.open(r'E:\document\clear.wav','rb')
params=f.getparams()
nchannels, sampwidth, framerate, nframes = params[:4]
str_data=f.readframes(nframes)
wave_data=np.fromstring(str_data,dtype=np.short) # 归一化
wave_data=wave_data/max(abs(wave_data))
wave_data.shape=-1,2
wave_data=wave_data.T
wave_data=wave_data[0]
wlen=512
inc=128
signal_length=len(wave_data) #信号总长度
if signal_length<=wlen: #若信号长度小于一个帧的长度,则帧数定义为1
nf=1
else: #否则,计算帧的总长度
nf=int(np.ceil((1.0*signal_length-wlen+inc)/inc))
pad_length=int((nf-1)*inc+wlen) #所有帧加起来总的铺平后的长度
zeros=np.zeros((pad_length-signal_length,)) #不够的长度使用0填补,类似于FFT中的扩充数组操作
pad_signal=np.concatenate((wave_data,zeros)) #填补后的信号记为pad_signal
indices=np.tile(np.arange(0,wlen),(nf,1))+np.tile(np.arange(0,nf*inc,inc),(wlen,1)).T
indices=np.array(indices,dtype=np.int32) #将indices转化为矩阵
frames=pad_signal[indices] #得到帧信号
u2=np.square(frames)
en=np.sum(u2,axis=1)
# a=frames[168]
#
#
# time=np.arange(0,a.size)*(1/framerate)
#
#
# window=np.hanning(wlen)
# b=a*window
#
#
#
# c=np.square(b)
# plot(time,c,c="g");show()
# time0=np.arange(0,nframes)*(1/framerate)
# time=np.arange(0,len(en))*(1/(48000*1997/256000))
time=np.arange(0,len(en))*(1/(framerate*len(en)/nframes))
plot(time,en);show()
print('ok')
显示短时能量
语音中录的5个字是 “我 到 北 京 去”