10-21:声音的STFT分析

再次将学习到的知识整理下来,来源有网络和课件。

1.平稳信号和非平稳信号

  • 自然界中几乎所有信号都是非平稳信号,比如我们的语音信号就是典型的非平稳信号。
  • 平稳信号在不同时间得到的采样值的统计特性(比如期望、方差等)是相同的,非平稳信号则与之相反,其特性会随时间变化。在信号处理中,这个特性通常指频率。
  • 通常傅里叶变换只适合处理平稳信号,对于非平稳信号,由于频率特性会随时间变化,为了捕获这一时变特性,我们需要对信号进行时频分析,就包括短时傅里叶变换、小波变换、希尔伯特变换、希尔伯特黄变换这几种变换。

2.FT的局限

  • 频谱分析,发现一些时域中看不到的信息,比如信号的频率分量组成、信号能量在频域上的分布等。
  • 傅里叶变换是一种全局的变换,时域信号经过傅里叶变换后,就变成了频域信号,从频域无法看到时域信息,反变换同理。
  • 【FT对非平稳信号和在分辨率上的局限性】无限长时间可以获得准确的频率定位(频率分辨率);反之无限长的频率可以获得准确的时间定位(时间分辨力);但是我们无法同时获得准确的时间定位和频率定位!
  • 如果信号的频率特性在任何时间都不发生改变(即该信号是平稳信号)的话,使用傅里叶变换是没有问题的,然而如果该信号是非平稳信号,这时候时域信息就相当重要了。会出现不同频率变化但幅度谱一样的情况,我们希望能知道频率是怎么随时间变化的。

3.STFT

定义:
X(n,w)=\sum^{ \infty}_{m = -\infty}x(m)g(n-m)e^{-jwn}
其中,x(m)为输入信号,g(m)为窗函数,X(n,w)是时间n和频率w的二维函数,它将信号的时域和频域联系起来,我们可以据此对信号进行时频分析。其中,S(n,w)=|X(n,w)|^2就是语音信号所谓的语谱图(Spectrogram)。通过STFT,我们可以很容易地得出非平稳信号的时变特性。
计算语谱时采用不同窗长度,可以得到两种语谱图:

  • 窄带语谱图。长时窗(至少两个基音周期)常被用于计算窄带语谱图。窄带语谱图具有较高的频率分辨率和较低的时间分辨率,良好的频率分辨率可以让语音的每个谐波分量更容易被辨别,在语谱图上显示为水平条纹。
  • 宽带语谱图。短窗用于计算宽带语谱图。宽带语谱图具有较高的时间分辨率和较低的频率分辨率,低频率分辨率只能得到谱包络,良好的时间分辨率适合用于分析和检验语音的发音。

接下来开始利用上节学到的知识(时域分析和STFT)对声音进行分析。

4.代码实践

def load_data(name):
    '''
    name:文件路劲,字符串类型
    '''
    mat_contents = sio.loadmat(name)
    sig = mat_contents['sig']   # 
    fs = mat_contents['fs']     # 48000
    sig = sig[:,0]              # 选择第一个通道
    # https://www.osgeo.cn/numpy/reference/generated/numpy.asscalar.html
    fs = np.asscalar(fs)        # 将大小为1的数组转换为其标量等效值
    sigLen = sig.size           # 信号点数48000
    t = np.arange(0,sigLen)/fs  # 采样的时刻
    return sig,fs,sigLen,t

def FenDuanloc_pow(segL,overlap,sig):
    #信号分段
    #计算需要多少段 
    N = len(sig)
    delta = segL-overlap
    
    # 这里算需要多少段,(N-overlap)/(M-overlap ),M表示段长
    segNum = np.int32(np.ceil((N-overlap)/delta));
    
    #扩展信号:看最后有没有多出来一点,补0处理
    padNum = segNum*delta+overlap-N
    if padNum==0:
        sigEx = sig
    elif padNum>0:
        sigEx = np.hstack((sig,np.zeros(padNum)))    
    
    #分段标签:其实就是找每一段的起始位置
    segIdx = np.arange(0,segNum)*delta
    #生成分段矩阵
    segMat = as_strided(sigEx,shape=(segNum,segL),strides=(sigEx.strides[0]*delta,sigEx.strides[0]))
    loc_pow = np.sum(segMat**2,axis=1)/segL
    loc_max = np.max(segMat,axis=1)
    
    return segIdx,segMat,loc_pow,loc_max

sig,fs,sigLen,t = load_data('sound6')
plt.figure(figsize=(12,4))
plt.plot(t,sig)
原始信号.png

1.分析有哪些音

sig,fs,sigLen,t = load_data('sound6')
ff,P,nfft = Myfft(sig,fs,48000)
# 画出0-1000Hz的FFT结果
pIdx = findPink(P[:1000],-70)
plt.figure(figsize=(12,4))
plt.scatter(ff[pIdx],P[:1000][pIdx],c='r')
plt.plot(ff[:1000],P[:1000])
plt.title('1s信号FFT在0-1000Hz的值')
plt.xlabel('Hz')
plt.ylabel('dB')
plt.show()
print('峰值的频率为:',ff[pIdx])
找峰值.png
峰值的频率为: [348. 389.]

从结果来看,有F4音和G4音。

2.分析这些音在什么时刻出现(STFT分析)

sig,fs,sigLen,t = load_data('sound6')

NFFT = 4096              # 每一段信号的长度
overlapSize = NFFT/3     # 每一段可以重叠的长度
plt.figure(figsize=(12,4))
spectrum,freqs,ts,fig = plt.specgram(sig,NFFT = NFFT,Fs =fs,window=np.hanning(M = NFFT),noverlap=overlapSize,mode='default',scale_by_freq=True,sides='default',scale='dB',xextent=None)#绘制频谱图
plt.show()
时频图.png
plt.figure(figsize=(12,4))
plt.contourf(ts, freqs[30:45], spectrum[30:45,:],200)
plt.xlabel('时间/s')
plt.ylabel('频率/Hz')
plt.show()
时频图.png

可以看到大约在1.1s出现了440Hz的音(A4)和在4.4s左右有一个392Hz的音(G4)。但是上面找到了F4音,扩大氛围查看:

plt.figure(figsize=(12,4))
plt.contourf(ts, freqs[25:45], spectrum[25:45,:],200)
时频图.png

可以看到,在刚开始左右有一个349.23Hz的音(F4)。

3.用自己写的STFT进行时频分析

sig,fs,sigLen,t = load_data('sound6')

segL = 1024
overlap = int(segL/3)
segIdx,segMat,loc_pow,loc_max = FenDuanloc_pow(segL,overlap,sig)

ts = t[segIdx]

ff = np.linspace(0,sigLen,segL)*(fs/sigLen)

plt.figure(figsize=(12,4))
pMat = np.fft.fft(segMat)
pMat = np.abs(pMat)**2
plt.contourf(ts, ff[5:15], pMat[:,5:15].T,50)
plt.xlabel('时间/s')
plt.ylabel('频率/Hz')
plt.show()
时频图.png

可以看到,得到基本一致的结果。区别在于我取的每一段长度更短,频率分辨率没那么高。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342