-
Notifications
You must be signed in to change notification settings - Fork 18
/
共振峰估计函数.py
99 lines (91 loc) · 2.64 KB
/
共振峰估计函数.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# 共振峰估计函数
import numpy as np
from chapter3_分析实验.timefeature import *
from chapter3_分析实验.lpc import lpc_coeff
def local_maxium(x):
"""
求序列的极大值
:param x:
:return:
"""
d = np.diff(x)
l_d = len(d)
maxium = []
loc = []
for i in range(l_d - 1):
if d[i] > 0 and d[i + 1] <= 0:
maxium.append(x[i + 1])
loc.append(i + 1)
return maxium, loc
def Formant_Cepst(u, cepstL):
"""
倒谱法共振峰估计函数
:param u:输入信号
:param cepstL:🔪频率上窗函数的宽度
:return: val共振峰幅值 loc共振峰位置 spec包络线
"""
wlen2 = len(u) // 2
u_fft=np.fft.fft(u) #按式(2-1)计算
U = np.log(np.abs( u_fft[:wlen2]))
Cepst = np.fft.ifft(U) #按式(2-2)计算
cepst = np.zeros(wlen2, dtype=np.complex)
cepst[:cepstL] = Cepst[:cepstL] #按式(2-3)计算
cepst[-cepstL + 1:] = Cepst[-cepstL + 1:] #取第二个式子的相反
spec = np.real(np.fft.fft(cepst))
val, loc = local_maxium(spec) #在包络线上寻找极大值
return val, loc, spec
def Formant_Interpolation(u, p, fs):
"""
插值法估计共振峰函数
:param u:
:param p:
:param fs:
:return:
"""
ar, _ = lpc_coeff(u, p)
U = np.power(np.abs(np.fft.rfft(ar, 2 * 255)), -2)
df = fs / 512
val, loc = local_maxium(U)
ll = len(loc)
pp = np.zeros(ll)
F = np.zeros(ll)
Bw = np.zeros(ll)
for k in range(ll):
m = loc[k]
m1, m2 = m - 1, m + 1
p = val[k]
p1, p2 = U[m1], U[m2]
aa = (p1 + p2) / 2 - p
bb = (p2 - p1) / 2
cc = p
dm = -bb / 2 / aa
pp[k] = -bb * bb / 4 / aa + cc
m_new = m + dm
bf = -np.sqrt(bb * bb - 4 * aa * (cc - pp[k] / 2)) / aa
F[k] = (m_new - 1) * df
Bw[k] = bf * df
return F, Bw, pp, U, loc
def Formant_Root(u, p, fs, n_frmnt):
"""
LPC求根法的共振峰估计函数
:param u:
:param p:
:param fs:
:param n_frmnt:
:return:
"""
ar, _ = lpc_coeff(u, p)
U = np.power(np.abs(np.fft.rfft(ar, 2 * 255)), -2)
const = fs / (2 * np.pi)
rts = np.roots(ar)
yf = []
Bw = []
for i in range(len(ar) - 1):
re = np.real(rts[i])
im = np.imag(rts[i])
fromn = const * np.arctan2(im, re)
bw = -2 * const * np.log(np.abs(rts[i]))
if fromn > 150 and bw < 700 and fromn < fs / 2:
yf.append(fromn)
Bw.append(bw)
return yf[:min(len(yf), n_frmnt)], Bw[:min(len(Bw), n_frmnt)], U