/
utils_lpc.py
64 lines (49 loc) · 1.47 KB
/
utils_lpc.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
import numpy as np
def bac(x, p):
# compute the biased autocorrelation for x up to lag p
L = len(x)
r = np.zeros(p+1)
for m in range(0, p+1):
for n in range(0, L-m):
r[m] += x[n] * x[n+m]
r[m] /= float(L)
return r
def ld(r, p):
# solve the toeplitz system using the Levinson-Durbin algorithm
g = r[1] / r[0]
a = np.array([g])
v = (1. - g * g) * r[0]
for i in range(1, p):
g = (r[i+1] - np.dot(a, r[1:i+1])) / v
a = np.r_[ g, a - g * a[i-1::-1] ]
v *= 1. - g*g
# return the coefficients of the A(z) filter
return np.r_[1, -a[::-1]]
def lpc(x, p):
# compute p LPC coefficients for a speech segment
return ld(bac(x, p), p)
"""
C-"friendly" implementation
"""
def ld_eff(r, order):
# solve the toeplitz system using the Levinson-Durbin algorithm
a = np.ones(order+1)
a_prev = np.ones(order)
a[1] = r[1]/r[0]
for p in range(2, order+1):
for j in range(1, p):
a_prev[j] = a[j]
# TODO: compute `k` from `r` and `a`
k = 1
# TODO: compute new `a` with `a_prev` and `k`
# separate vector is needed so we don't overwrite!
for j in range(1, p):
a[j] = a_prev[j]
a[p] = k
# by convention, have negative of coefficients
for p in range(1, order+1):
a[p] *= -1
return a
def lpc_eff(x, p):
# compute p LPC coefficients for a speech segment
return ld_eff(bac(x, p), p)