diff options
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 | |||
