diff options
author | erdgeist@erdgeist.org <erdgeist@bauklotz.fritz.box> | 2019-07-04 23:26:09 +0200 |
---|---|---|
committer | erdgeist@erdgeist.org <erdgeist@bauklotz.fritz.box> | 2019-07-04 23:26:09 +0200 |
commit | f02dfce6e6c34b3d8a7b8a0e784b506178e331fa (patch) | |
tree | 45556e6104242d4702689760433d7321ae74ec17 /interp.c |
stripdown of version 0.9
Diffstat (limited to 'interp.c')
-rw-r--r-- | interp.c | 331 |
1 files changed, 331 insertions, 0 deletions
diff --git a/interp.c b/interp.c new file mode 100644 index 0000000..2109acb --- /dev/null +++ b/interp.c | |||
@@ -0,0 +1,331 @@ | |||
1 | /*---------------------------------------------------------------------------*\ | ||
2 | |||
3 | FILE........: interp.c | ||
4 | AUTHOR......: David Rowe | ||
5 | DATE CREATED: 9/10/09 | ||
6 | |||
7 | Interpolation of 20ms frames to 10ms frames. | ||
8 | |||
9 | \*---------------------------------------------------------------------------*/ | ||
10 | |||
11 | /* | ||
12 | Copyright (C) 2009 David Rowe | ||
13 | |||
14 | All rights reserved. | ||
15 | |||
16 | This program is free software; you can redistribute it and/or modify | ||
17 | it under the terms of the GNU Lesser General Public License version 2.1, as | ||
18 | published by the Free Software Foundation. This program is | ||
19 | distributed in the hope that it will be useful, but WITHOUT ANY | ||
20 | WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
21 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public | ||
22 | License for more details. | ||
23 | |||
24 | You should have received a copy of the GNU Lesser General Public License | ||
25 | along with this program; if not, see <http://www.gnu.org/licenses/>. | ||
26 | */ | ||
27 | |||
28 | #include <assert.h> | ||
29 | #include <math.h> | ||
30 | #include <string.h> | ||
31 | #include <stdio.h> | ||
32 | |||
33 | #include "defines.h" | ||
34 | #include "interp.h" | ||
35 | #include "lsp.h" | ||
36 | #include "quantise.h" | ||
37 | |||
38 | float sample_log_amp(MODEL *model, float w); | ||
39 | |||
40 | #if 0 | ||
41 | /*---------------------------------------------------------------------------*\ | ||
42 | |||
43 | FUNCTION....: interp() | ||
44 | AUTHOR......: David Rowe | ||
45 | DATE CREATED: 22/8/10 | ||
46 | |||
47 | Given two frames decribed by model parameters 20ms apart, determines | ||
48 | the model parameters of the 10ms frame between them. Assumes | ||
49 | voicing is available for middle (interpolated) frame. Outputs are | ||
50 | amplitudes and Wo for the interpolated frame. | ||
51 | |||
52 | This version can interpolate the amplitudes between two frames of | ||
53 | different Wo and L. | ||
54 | |||
55 | This version works by log linear interpolation, but listening tests | ||
56 | showed it creates problems in background noise, e.g. hts2a and mmt1. | ||
57 | When this function is used (--dec mode) bg noise appears to be | ||
58 | amplitude modulated, and gets louder. The interp_lsp() function | ||
59 | below seems to do a better job. | ||
60 | |||
61 | \*---------------------------------------------------------------------------*/ | ||
62 | |||
63 | void interpolate( | ||
64 | MODEL *interp, /* interpolated model params */ | ||
65 | MODEL *prev, /* previous frames model params */ | ||
66 | MODEL *next, /* next frames model params */ | ||
67 | float Wo_min | ||
68 | ) | ||
69 | { | ||
70 | int l; | ||
71 | float w,log_amp; | ||
72 | |||
73 | /* Wo depends on voicing of this and adjacent frames */ | ||
74 | |||
75 | if (interp->voiced) { | ||
76 | if (prev->voiced && next->voiced) | ||
77 | interp->Wo = (prev->Wo + next->Wo)/2.0; | ||
78 | if (!prev->voiced && next->voiced) | ||
79 | interp->Wo = next->Wo; | ||
80 | if (prev->voiced && !next->voiced) | ||
81 | interp->Wo = prev->Wo; | ||
82 | } | ||
83 | else { | ||
84 | interp->Wo = Wo_min; | ||
85 | } | ||
86 | interp->L = PI/interp->Wo; | ||
87 | |||
88 | /* Interpolate amplitudes using linear interpolation in log domain */ | ||
89 | |||
90 | for(l=1; l<=interp->L; l++) { | ||
91 | w = l*interp->Wo; | ||
92 | log_amp = (sample_log_amp(prev, w) + sample_log_amp(next, w))/2.0; | ||
93 | interp->A[l] = powf(10.0, log_amp); | ||
94 | } | ||
95 | } | ||
96 | #endif | ||
97 | |||
98 | /*---------------------------------------------------------------------------*\ | ||
99 | |||
100 | FUNCTION....: sample_log_amp() | ||
101 | AUTHOR......: David Rowe | ||
102 | DATE CREATED: 22/8/10 | ||
103 | |||
104 | Samples the amplitude envelope at an arbitrary frequency w. Uses | ||
105 | linear interpolation in the log domain to sample between harmonic | ||
106 | amplitudes. | ||
107 | |||
108 | \*---------------------------------------------------------------------------*/ | ||
109 | |||
110 | float sample_log_amp(MODEL *model, float w) | ||
111 | { | ||
112 | int m; | ||
113 | float f, log_amp; | ||
114 | |||
115 | assert(w > 0.0); assert (w <= PI); | ||
116 | |||
117 | m = floorf(w/model->Wo + 0.5); | ||
118 | f = (w - m*model->Wo)/w; | ||
119 | assert(f <= 1.0); | ||
120 | |||
121 | if (m < 1) { | ||
122 | log_amp = f*log10f(model->A[1] + 1E-6); | ||
123 | } | ||
124 | else if ((m+1) > model->L) { | ||
125 | log_amp = (1.0-f)*log10f(model->A[model->L] + 1E-6); | ||
126 | } | ||
127 | else { | ||
128 | log_amp = (1.0-f)*log10f(model->A[m] + 1E-6) + | ||
129 | f*log10f(model->A[m+1] + 1E-6); | ||
130 | } | ||
131 | |||
132 | return log_amp; | ||
133 | } | ||
134 | |||
135 | #ifdef NOT_NEEDED | ||
136 | |||
137 | /*---------------------------------------------------------------------------*\ | ||
138 | |||
139 | FUNCTION....: interp_lsp() | ||
140 | AUTHOR......: David Rowe | ||
141 | DATE CREATED: 10 Nov 2010 | ||
142 | |||
143 | Given two frames decribed by model parameters 20ms apart, determines | ||
144 | the model parameters of the 10ms frame between them. Assumes | ||
145 | voicing is available for middle (interpolated) frame. Outputs are | ||
146 | amplitudes and Wo for the interpolated frame. | ||
147 | |||
148 | This version uses interpolation of LSPs, seems to do a better job | ||
149 | with bg noise. | ||
150 | |||
151 | \*---------------------------------------------------------------------------*/ | ||
152 | |||
153 | void interpolate_lsp( | ||
154 | codec2_fft_cfg fft_fwd_cfg, | ||
155 | MODEL *interp, /* interpolated model params */ | ||
156 | MODEL *prev, /* previous frames model params */ | ||
157 | MODEL *next, /* next frames model params */ | ||
158 | float *prev_lsps, /* previous frames LSPs */ | ||
159 | float prev_e, /* previous frames LPC energy */ | ||
160 | float *next_lsps, /* next frames LSPs */ | ||
161 | float next_e, /* next frames LPC energy */ | ||
162 | float *ak_interp, /* interpolated aks for this frame */ | ||
163 | float *lsps_interp, /* interpolated lsps for this frame */ | ||
164 | float Wo_min | ||
165 | ) | ||
166 | { | ||
167 | int i; | ||
168 | float e; | ||
169 | float snr; | ||
170 | |||
171 | /* trap corner case where V est is probably wrong */ | ||
172 | |||
173 | if (interp->voiced && !prev->voiced && !next->voiced) { | ||
174 | interp->voiced = 0; | ||
175 | } | ||
176 | |||
177 | /* Wo depends on voicing of this and adjacent frames */ | ||
178 | |||
179 | if (interp->voiced) { | ||
180 | if (prev->voiced && next->voiced) | ||
181 | interp->Wo = (prev->Wo + next->Wo)/2.0; | ||
182 | if (!prev->voiced && next->voiced) | ||
183 | interp->Wo = next->Wo; | ||
184 | if (prev->voiced && !next->voiced) | ||
185 | interp->Wo = prev->Wo; | ||
186 | } | ||
187 | else { | ||
188 | interp->Wo = Wo_min; | ||
189 | } | ||
190 | interp->L = PI/interp->Wo; | ||
191 | |||
192 | //printf(" interp: prev_v: %d next_v: %d prev_Wo: %f next_Wo: %f\n", | ||
193 | // prev->voiced, next->voiced, prev->Wo, next->Wo); | ||
194 | //printf(" interp: Wo: %1.5f L: %d\n", interp->Wo, interp->L); | ||
195 | |||
196 | /* interpolate LSPs */ | ||
197 | |||
198 | for(i=0; i<LPC_ORD; i++) { | ||
199 | lsps_interp[i] = (prev_lsps[i] + next_lsps[i])/2.0; | ||
200 | } | ||
201 | |||
202 | /* Interpolate LPC energy in log domain */ | ||
203 | |||
204 | e = powf(10.0, (log10f(prev_e) + log10f(next_e))/2.0); | ||
205 | //printf(" interp: e: %f\n", e); | ||
206 | |||
207 | /* convert back to amplitudes */ | ||
208 | |||
209 | lsp_to_lpc(lsps_interp, ak_interp, LPC_ORD); | ||
210 | aks_to_M2(fft_fwd_cfg, ak_interp, LPC_ORD, interp, e, &snr, 0, 0, 1, 1, LPCPF_BETA, LPCPF_GAMMA); | ||
211 | //printf(" interp: ak[1]: %f A[1] %f\n", ak_interp[1], interp->A[1]); | ||
212 | } | ||
213 | #endif | ||
214 | |||
215 | /*---------------------------------------------------------------------------*\ | ||
216 | |||
217 | FUNCTION....: interp_Wo() | ||
218 | AUTHOR......: David Rowe | ||
219 | DATE CREATED: 22 May 2012 | ||
220 | |||
221 | Interpolates centre 10ms sample of Wo and L samples given two | ||
222 | samples 20ms apart. Assumes voicing is available for centre | ||
223 | (interpolated) frame. | ||
224 | |||
225 | \*---------------------------------------------------------------------------*/ | ||
226 | |||
227 | void interp_Wo( | ||
228 | MODEL *interp, /* interpolated model params */ | ||
229 | MODEL *prev, /* previous frames model params */ | ||
230 | MODEL *next, /* next frames model params */ | ||
231 | float Wo_min | ||
232 | ) | ||
233 | { | ||
234 | interp_Wo2(interp, prev, next, 0.5, Wo_min); | ||
235 | } | ||
236 | |||
237 | /*---------------------------------------------------------------------------*\ | ||
238 | |||
239 | FUNCTION....: interp_Wo2() | ||
240 | AUTHOR......: David Rowe | ||
241 | DATE CREATED: 22 May 2012 | ||
242 | |||
243 | Weighted interpolation of two Wo samples. | ||
244 | |||
245 | \*---------------------------------------------------------------------------*/ | ||
246 | |||
247 | void interp_Wo2( | ||
248 | MODEL *interp, /* interpolated model params */ | ||
249 | MODEL *prev, /* previous frames model params */ | ||
250 | MODEL *next, /* next frames model params */ | ||
251 | float weight, | ||
252 | float Wo_min | ||
253 | ) | ||
254 | { | ||
255 | /* trap corner case where voicing est is probably wrong */ | ||
256 | |||
257 | if (interp->voiced && !prev->voiced && !next->voiced) { | ||
258 | interp->voiced = 0; | ||
259 | } | ||
260 | |||
261 | /* Wo depends on voicing of this and adjacent frames */ | ||
262 | |||
263 | if (interp->voiced) { | ||
264 | if (prev->voiced && next->voiced) | ||
265 | interp->Wo = (1.0 - weight)*prev->Wo + weight*next->Wo; | ||
266 | if (!prev->voiced && next->voiced) | ||
267 | interp->Wo = next->Wo; | ||
268 | if (prev->voiced && !next->voiced) | ||
269 | interp->Wo = prev->Wo; | ||
270 | } | ||
271 | else { | ||
272 | interp->Wo = Wo_min; | ||
273 | } | ||
274 | interp->L = PI/interp->Wo; | ||
275 | } | ||
276 | |||
277 | |||
278 | /*---------------------------------------------------------------------------*\ | ||
279 | |||
280 | FUNCTION....: interp_energy() | ||
281 | AUTHOR......: David Rowe | ||
282 | DATE CREATED: 22 May 2012 | ||
283 | |||
284 | Interpolates centre 10ms sample of energy given two samples 20ms | ||
285 | apart. | ||
286 | |||
287 | \*---------------------------------------------------------------------------*/ | ||
288 | |||
289 | float interp_energy(float prev_e, float next_e) | ||
290 | { | ||
291 | //return powf(10.0, (log10f(prev_e) + log10f(next_e))/2.0); | ||
292 | return sqrtf(prev_e * next_e); //looks better is math. identical and faster math | ||
293 | } | ||
294 | |||
295 | |||
296 | /*---------------------------------------------------------------------------*\ | ||
297 | |||
298 | FUNCTION....: interp_energy2() | ||
299 | AUTHOR......: David Rowe | ||
300 | DATE CREATED: 22 May 2012 | ||
301 | |||
302 | Interpolates centre 10ms sample of energy given two samples 20ms | ||
303 | apart. | ||
304 | |||
305 | \*---------------------------------------------------------------------------*/ | ||
306 | |||
307 | float interp_energy2(float prev_e, float next_e, float weight) | ||
308 | { | ||
309 | return POW10F((1.0 - weight)*log10f(prev_e) + weight*log10f(next_e)); | ||
310 | |||
311 | } | ||
312 | |||
313 | |||
314 | /*---------------------------------------------------------------------------*\ | ||
315 | |||
316 | FUNCTION....: interpolate_lsp_ver2() | ||
317 | AUTHOR......: David Rowe | ||
318 | DATE CREATED: 22 May 2012 | ||
319 | |||
320 | Weighted interpolation of LSPs. | ||
321 | |||
322 | \*---------------------------------------------------------------------------*/ | ||
323 | |||
324 | void interpolate_lsp_ver2(float interp[], float prev[], float next[], float weight, int order) | ||
325 | { | ||
326 | int i; | ||
327 | |||
328 | for(i=0; i<order; i++) | ||
329 | interp[i] = (1.0 - weight)*prev[i] + weight*next[i]; | ||
330 | } | ||
331 | |||