e@0
|
1 # -*- coding: utf-8 -*-
|
e@0
|
2 """
|
e@0
|
3 Created on Mon Mar 7 13:03:01 2016
|
e@0
|
4
|
e@0
|
5 @author: Emmanouil Theofanis Chourdakis
|
e@0
|
6 """
|
e@0
|
7
|
e@0
|
8 from numpy import *
|
e@0
|
9 from scipy.optimize import *
|
e@0
|
10
|
e@0
|
11
|
e@0
|
12 ga = sqrt(2)
|
e@0
|
13 g1_min = 0.136
|
e@0
|
14 g1_max = 0.999
|
e@0
|
15
|
e@0
|
16 d1_min = 0.010
|
e@0
|
17 d1_max = 0.900
|
e@0
|
18
|
e@0
|
19 da_min = 0.006
|
e@0
|
20 da_max = 0.012
|
e@0
|
21
|
e@0
|
22 gc_min = 0.001
|
e@0
|
23 gc_max = 0.999
|
e@0
|
24
|
e@0
|
25 G_min = 0.001
|
e@0
|
26 G_max = 0.999
|
e@0
|
27
|
e@0
|
28 # Limits are defined by the variables minima and maxima
|
e@0
|
29
|
e@0
|
30 T60_min = 0.02
|
e@0
|
31 T60_max = 5
|
e@0
|
32 #
|
e@0
|
33 D_min = 200
|
e@0
|
34 D_max = 10000
|
e@0
|
35 #
|
e@0
|
36 C_min = -20
|
e@0
|
37 C_max = 10
|
e@0
|
38 #
|
e@0
|
39 Tc_min = 0.001
|
e@0
|
40 Tc_max = 5.0
|
e@0
|
41 #
|
e@0
|
42 SC_min = 200
|
e@0
|
43 SC_max = 11025
|
e@0
|
44 def normalize(f,fmin,fmax):
|
e@0
|
45 return (f - fmin)/(fmax - fmin)
|
e@0
|
46
|
e@0
|
47 def normalize_param(p):
|
e@0
|
48 return array([
|
e@0
|
49 normalize(p[0],T60_min,T60_max),
|
e@0
|
50 normalize(p[1],D_min,D_max),
|
e@0
|
51 normalize(p[2],C_min,C_max),
|
e@0
|
52 normalize(p[3],Tc_min,Tc_max)
|
e@0
|
53 ])
|
e@0
|
54
|
e@0
|
55 def get_high_param_norm(x):
|
e@0
|
56 return array([
|
e@0
|
57 normalize(T60(x),T60_min,T60_max),
|
e@0
|
58 normalize(D(x),D_min,D_max),
|
e@0
|
59 normalize(C(x),C_min,C_max),
|
e@0
|
60 normalize(Tc(x),Tc_min,Tc_max)
|
e@0
|
61 ])
|
e@0
|
62 def T601d(d1,g1,gc,G):
|
e@0
|
63 g1 = abs(g1)
|
e@0
|
64 return -d1/log(g1)*(log(G)+log(1-gc)+log(ga)+3*log(10))
|
e@0
|
65
|
e@0
|
66
|
e@0
|
67
|
e@0
|
68 def D1d(d1,da,t=0.1):
|
e@0
|
69 kS = 20.78125
|
e@0
|
70
|
e@0
|
71 return kS*t/d1/da
|
e@0
|
72
|
e@0
|
73
|
e@0
|
74 def C1d(g1,gc, G):
|
e@0
|
75 s_ = 0
|
e@0
|
76 for k in range(1, 7):
|
e@0
|
77 s_ += g1**(2*1.5**(1-k))/(1-g1**(2*1.5**(1-k)))
|
e@0
|
78
|
e@0
|
79 return -10 * log10(G**2*(1-gc)/(1+gc)*s_)
|
e@0
|
80
|
e@0
|
81 def Tc1d(d1,da,g1):
|
e@0
|
82 gk = lambda k: g1**(1.5)**(1-k)
|
e@0
|
83 dk = lambda k: d1*1.5**(1-k)
|
e@0
|
84
|
e@0
|
85 sum1 = 0
|
e@0
|
86 sum2 = 0
|
e@0
|
87
|
e@0
|
88 for k in range(1, 7):
|
e@0
|
89 s1 = gk(k)**2/(1-gk(k)**2)
|
e@0
|
90 sum2 += s1
|
e@0
|
91 sum1 += dk(k)*s1/(1-gk(k)**2)
|
e@0
|
92
|
e@0
|
93 return sum1/sum2 + da
|
e@0
|
94
|
e@0
|
95 def Tc_g1_d1_D(d1,g1,D, t=0.1):
|
e@0
|
96 S1 = sum([1.5**(-k + 1)*d1*g1**(2*1.5**(-k + 1))/(-g1**(2*1.5**(-k + 1)) + 1)**2 for k in range(1, 7)])
|
e@0
|
97 S2 = sum([g1**(2*1.5**(-k + 1))/(-g1**(2*1.5**(-k + 1)) + 1) for k in range(1, 7)])
|
e@0
|
98 Tc = S1/S2 + 20.78125*t/(D*d1)
|
e@0
|
99 return Tc
|
e@0
|
100
|
e@0
|
101 def T60_d1_g1_C(d1,g1,gc,C):
|
e@0
|
102 # S1 = sum([g1**(2*1.5**(-k + 1))/(-g1**(2*1.5**(-k + 1)) + 1) for k in range(1, 7)])
|
e@0
|
103 g1 = abs(g1)
|
e@0
|
104 s_ = 0
|
e@0
|
105 for k in range(1, 7):
|
e@0
|
106 s_ += g1**(2*1.5**(1-k))/(1-g1**(2*1.5**(1-k)))
|
e@0
|
107
|
e@0
|
108 T60 = d1*log(0.001/ga*exp(C*log(10)/20)/(sqrt((gc + 1)/((-gc + 1)*s_))*(-gc + 1)))/log(g1)
|
e@0
|
109
|
e@0
|
110 return T60
|
e@0
|
111
|
e@0
|
112 def d1_g1_T60_C(g1,gc,T60,C):
|
e@0
|
113 g1 = abs(g1)
|
e@0
|
114 s_ = 0
|
e@0
|
115 for k in range(1, 7):
|
e@0
|
116 s_ += g1**(2*1.5**(1-k))/(1-g1**(2*1.5**(1-k)))
|
e@0
|
117 #S1 = sum([g1**(2*1.5**(-k + 1))/(-g1**(2*1.5**(-k + 1)) + 1) for k in range(1, 7)])
|
e@0
|
118
|
e@0
|
119
|
e@0
|
120 d1 = T60*log(g1)/log(0.001/ga*exp(C*log(10)/20)/(sqrt((gc + 1)/((-gc + 1)*s_))*(-gc + 1)))
|
e@0
|
121 return d1
|
e@0
|
122
|
e@0
|
123 def G_g1_C(g1,gc, C):
|
e@0
|
124
|
e@0
|
125 s_ = 0
|
e@0
|
126 for k in range(1, 7):
|
e@0
|
127 s_ += g1**(2*1.5**(1-k))/(1-g1**(2*1.5**(1-k)))
|
e@0
|
128
|
e@0
|
129 G = sqrt(exp(-C/10*log(10))/(1-gc)*(1+gc)/s_)
|
e@0
|
130 return G
|
e@0
|
131
|
e@0
|
132 def da_d1_D(d1,gc, D,t=0.1):
|
e@0
|
133 return 20.78125*t/d1/D
|
e@0
|
134
|
e@0
|
135
|
e@0
|
136 def Tc_g1_T60_D_C(g1,gc, T60, D, C):
|
e@0
|
137 S1 = sum([g1**(2*1.5**(-k + 1))/(-g1**(2*1.5**(-k + 1)) + 1) for k in range(1, 7)])
|
e@0
|
138 L1 = log(0.001*exp(C*log(10)/20)/(ga*sqrt((gc + 1)/((-gc + 1)*S1))*(-gc + 1)))
|
e@0
|
139 S2 = sum([1.5**(-k + 1)*T60*g1**(2*1.5**(-k + 1))*log(g1)/((-g1**(2*1.5**(-k + 1)) + 1)**2*L1) for k in range(1, 7)])
|
e@0
|
140 Tc = S2/S1 + 20.78125*t*log(0.001*exp(C*log(10)/20)/(ga*sqrt((gc + 1)/((-gc + 1)*S1))*(-gc + 1)))/(D*T60*log(g1))
|
e@0
|
141
|
e@0
|
142 return Tc
|
e@0
|
143
|
e@0
|
144 def f_gc(sc,SR=44100):
|
e@0
|
145 T = loadtxt('scmapping.csv')
|
e@0
|
146 SampleRates = T[:,0]
|
e@0
|
147 P = T[:,1:]
|
e@0
|
148 p = P[SampleRates == SR][0]
|
e@0
|
149 return polyval(p, sc)
|
e@0
|
150
|
e@0
|
151 def errorfunc(g1, Target, gc, weights=(1.0, 1.0, 1.0, 1.0)):
|
e@0
|
152
|
e@0
|
153 (kT60, kD, kC, kTc) = Target
|
e@0
|
154 G = G_g1_C(g1, gc, kC)
|
e@0
|
155
|
e@0
|
156
|
e@0
|
157 # Check bounds
|
e@0
|
158
|
e@0
|
159 if G>G_max:
|
e@0
|
160 G = G_max
|
e@0
|
161 if G<G_min:
|
e@0
|
162 G = G_min
|
e@0
|
163
|
e@0
|
164
|
e@0
|
165 d1 = d1_g1_T60_C(g1,gc, kT60, kC)
|
e@0
|
166
|
e@0
|
167 if d1>d1_max:
|
e@0
|
168 d1 = d1_max
|
e@0
|
169 if d1<d1_min:
|
e@0
|
170 d1 = d1_min
|
e@0
|
171
|
e@0
|
172 da = da_d1_D(d1, gc, kD)
|
e@0
|
173
|
e@0
|
174 if da>da_max:
|
e@0
|
175 da = da_max
|
e@0
|
176 if da<da_min:
|
e@0
|
177 da = da_min
|
e@0
|
178
|
e@0
|
179 T_60_est = T601d(d1,g1,gc,G)
|
e@0
|
180 D_est = D1d(d1,da)
|
e@0
|
181 C_est = C1d(g1,gc,G)
|
e@0
|
182 Tc_est = Tc1d(d1,da,g1)
|
e@0
|
183
|
e@0
|
184 est_vect = normalize_param(array([T_60_est, D_est, C_est, Tc_est]))
|
e@0
|
185 orig_vect = normalize_param([kT60, kD, kC, kTc])
|
e@0
|
186
|
e@0
|
187 errvec = abs(est_vect-orig_vect)
|
e@0
|
188 w1 = weights[0]
|
e@0
|
189 w2 = weights[1]
|
e@0
|
190 w3 = weights[2]
|
e@0
|
191 w4 = weights[3]
|
e@0
|
192
|
e@0
|
193 errvec = array([w1*errvec[0],w2*errvec[1],w3*errvec[2],w4*errvec[3]])
|
e@0
|
194
|
e@0
|
195 return mean(errvec**2) + var(errvec**2)**2 #+ skew(abs(est_vect-orig_vect)**2)
|
e@0
|
196
|
e@0
|
197 def SC1d(gc,SR=44100):
|
e@0
|
198
|
e@0
|
199 lut = 1-2*gc*cos(2*pi*arange(0,int(SR/2)+1)/SR)+gc**2
|
e@0
|
200
|
e@0
|
201 fgcn = lambda n: 1/lut[n]
|
e@0
|
202
|
e@0
|
203 sum1 = 0
|
e@0
|
204 sum2 = 0
|
e@0
|
205
|
e@0
|
206 for n in range(0, int(SR/2)):
|
e@0
|
207 fgcn_ = fgcn(n)
|
e@0
|
208 sum1 += n*fgcn_
|
e@0
|
209 sum2 += fgcn_
|
e@0
|
210
|
e@0
|
211 return sum1/sum2
|
e@0
|
212
|
e@0
|
213
|
e@0
|
214 def forward_mapping(d1, da, g1, gc, G):
|
e@0
|
215 SC = SC1d(gc)
|
e@0
|
216 T60 = T601d(d1,g1,gc,G)
|
e@0
|
217 D = D1d(d1,da)
|
e@0
|
218 C = C1d(g1,gc,G)
|
e@0
|
219 Tc = Tc1d(d1,da,g1)
|
e@0
|
220
|
e@0
|
221 return (T60, D, C, Tc, SC)
|
e@0
|
222
|
e@0
|
223 def inverse_mapping(T60, D, C, Tc, SC, SR=44100):
|
e@0
|
224 """ returns a vector (d1, da, g1, gc, G) of filter coefficients """
|
e@0
|
225
|
e@0
|
226 #1. Estimate gc from spectral centroid
|
e@0
|
227 gc = f_gc(SC, SR)
|
e@0
|
228
|
e@0
|
229 #2. Estimate g1
|
e@0
|
230 g1 = minimize_scalar(lambda x: errorfunc(x, (T60,D,C,Tc), gc), bounds=(g1_min,g1_max), method='bounded').x
|
e@0
|
231
|
e@0
|
232 #4. a. Estimate G from G_g1_C
|
e@0
|
233 G = G_g1_C(g1, gc, C)
|
e@0
|
234 if G > G_max:
|
e@0
|
235 G = G_max
|
e@0
|
236 elif G < G_min:
|
e@0
|
237 G = G_min
|
e@0
|
238
|
e@0
|
239 #4. b. Estimate d1 from d1_g1_T60_C
|
e@0
|
240 d1 = d1_g1_T60_C(g1,gc,T60,C)
|
e@0
|
241 if d1 > d1_max:
|
e@0
|
242 d1 = d1_max
|
e@0
|
243 elif d1 < d1_min:
|
e@0
|
244 d1 = d1_min
|
e@0
|
245
|
e@0
|
246 #4. c. Estimate da from da_d1_D
|
e@0
|
247 da = da_d1_D(d1,gc, D)
|
e@0
|
248 if da > da_max:
|
e@0
|
249 da = da_max
|
e@0
|
250 elif da < da_min:
|
e@0
|
251 da = da_min
|
e@0
|
252
|
e@0
|
253 return (d1, da, g1, gc, G)
|
e@0
|
254
|