blob: 9ca6ca48e9e3525edb5bfd918ce3c48809a75d3b [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
2 * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11/******************************************************************
12
13 iLBC Speech Coder ANSI-C Source Code
14
15 WebRtcIlbcfix_DoThePlc.c
16
17******************************************************************/
18
Timothy Gu31117832020-12-18 22:25:57 -080019#include "modules/audio_coding/codecs/ilbc/do_plc.h"
20
Mirko Bonadei06c2aa92018-02-01 15:11:41 +010021#include "modules/audio_coding/codecs/ilbc/bw_expand.h"
Timothy Gu31117832020-12-18 22:25:57 -080022#include "modules/audio_coding/codecs/ilbc/comp_corr.h"
23#include "modules/audio_coding/codecs/ilbc/constants.h"
24#include "modules/audio_coding/codecs/ilbc/defines.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000025
26/*----------------------------------------------------------------*
27 * Packet loss concealment routine. Conceals a residual signal
28 * and LP parameters. If no packet loss, update state.
29 *---------------------------------------------------------------*/
30
31void WebRtcIlbcfix_DoThePlc(
pbos@webrtc.org0946a562013-04-09 00:28:06 +000032 int16_t *PLCresidual, /* (o) concealed residual */
33 int16_t *PLClpc, /* (o) concealed LP parameters */
34 int16_t PLI, /* (i) packet loss indicator
niklase@google.com470e71d2011-07-07 08:21:25 +000035 0 - no PL, 1 = PL */
pbos@webrtc.org0946a562013-04-09 00:28:06 +000036 int16_t *decresidual, /* (i) decoded residual */
37 int16_t *lpc, /* (i) decoded LPC (only used for no PL) */
Peter Kastingdce40cf2015-08-24 14:52:23 -070038 size_t inlag, /* (i) pitch lag */
pbos@webrtc.orgeb544462014-12-17 15:23:29 +000039 IlbcDecoder *iLBCdec_inst
niklase@google.com470e71d2011-07-07 08:21:25 +000040 /* (i/o) decoder instance */
41 ){
Peter Kastingdce40cf2015-08-24 14:52:23 -070042 size_t i;
pbos@webrtc.org0946a562013-04-09 00:28:06 +000043 int32_t cross, ener, cross_comp, ener_comp = 0;
44 int32_t measure, maxMeasure, energy;
Sam Zackrissonae93f042018-05-15 13:41:45 +020045 int32_t noise_energy_threshold_30dB;
pbos@webrtc.org0946a562013-04-09 00:28:06 +000046 int16_t max, crossSquareMax, crossSquare;
Peter Kastingdce40cf2015-08-24 14:52:23 -070047 size_t j, lag, randlag;
48 int16_t tmp1, tmp2;
pbos@webrtc.org0946a562013-04-09 00:28:06 +000049 int16_t shift1, shift2, shift3, shiftMax;
50 int16_t scale3;
Peter Kastingdce40cf2015-08-24 14:52:23 -070051 size_t corrLen;
pbos@webrtc.org0946a562013-04-09 00:28:06 +000052 int32_t tmpW32, tmp2W32;
53 int16_t use_gain;
54 int16_t tot_gain;
55 int16_t max_perSquare;
56 int16_t scale1, scale2;
57 int16_t totscale;
58 int32_t nom;
59 int16_t denom;
60 int16_t pitchfact;
Peter Kastingdce40cf2015-08-24 14:52:23 -070061 size_t use_lag;
niklase@google.com470e71d2011-07-07 08:21:25 +000062 int ind;
pbos@webrtc.org0946a562013-04-09 00:28:06 +000063 int16_t randvec[BLOCKL_MAX];
niklase@google.com470e71d2011-07-07 08:21:25 +000064
65 /* Packet Loss */
66 if (PLI == 1) {
67
68 (*iLBCdec_inst).consPLICount += 1;
69
70 /* if previous frame not lost,
71 determine pitch pred. gain */
72
73 if (iLBCdec_inst->prevPLI != 1) {
74
75 /* Maximum 60 samples are correlated, preserve as high accuracy
76 as possible without getting overflow */
pkastingb297c5a2015-07-22 15:17:22 -070077 max = WebRtcSpl_MaxAbsValueW16((*iLBCdec_inst).prevResidual,
Peter Kastingdce40cf2015-08-24 14:52:23 -070078 iLBCdec_inst->blockl);
niklase@google.com470e71d2011-07-07 08:21:25 +000079 scale3 = (WebRtcSpl_GetSizeInBits(max)<<1) - 25;
80 if (scale3 < 0) {
81 scale3 = 0;
82 }
83
84 /* Store scale for use when interpolating between the
85 * concealment and the received packet */
86 iLBCdec_inst->prevScale = scale3;
87
88 /* Search around the previous lag +/-3 to find the
89 best pitch period */
90 lag = inlag - 3;
91
92 /* Guard against getting outside the frame */
Peter Kastingdce40cf2015-08-24 14:52:23 -070093 corrLen = (size_t)WEBRTC_SPL_MIN(60, iLBCdec_inst->blockl-(inlag+3));
niklase@google.com470e71d2011-07-07 08:21:25 +000094
95 WebRtcIlbcfix_CompCorr( &cross, &ener,
96 iLBCdec_inst->prevResidual, lag, iLBCdec_inst->blockl, corrLen, scale3);
97
98 /* Normalize and store cross^2 and the number of shifts */
99 shiftMax = WebRtcSpl_GetSizeInBits(WEBRTC_SPL_ABS_W32(cross))-15;
bjornv@webrtc.org2f6ae0d2015-03-01 19:50:41 +0000100 crossSquareMax = (int16_t)((
101 (int16_t)WEBRTC_SPL_SHIFT_W32(cross, -shiftMax) *
102 (int16_t)WEBRTC_SPL_SHIFT_W32(cross, -shiftMax)) >> 15);
niklase@google.com470e71d2011-07-07 08:21:25 +0000103
104 for (j=inlag-2;j<=inlag+3;j++) {
105 WebRtcIlbcfix_CompCorr( &cross_comp, &ener_comp,
106 iLBCdec_inst->prevResidual, j, iLBCdec_inst->blockl, corrLen, scale3);
107
108 /* Use the criteria (corr*corr)/energy to compare if
109 this lag is better or not. To avoid the division,
110 do a cross multiplication */
111 shift1 = WebRtcSpl_GetSizeInBits(WEBRTC_SPL_ABS_W32(cross_comp))-15;
bjornv@webrtc.org2f6ae0d2015-03-01 19:50:41 +0000112 crossSquare = (int16_t)((
113 (int16_t)WEBRTC_SPL_SHIFT_W32(cross_comp, -shift1) *
114 (int16_t)WEBRTC_SPL_SHIFT_W32(cross_comp, -shift1)) >> 15);
niklase@google.com470e71d2011-07-07 08:21:25 +0000115
116 shift2 = WebRtcSpl_GetSizeInBits(ener)-15;
bjornv@webrtc.orgba97ea62015-02-13 09:51:40 +0000117 measure = (int16_t)WEBRTC_SPL_SHIFT_W32(ener, -shift2) * crossSquare;
niklase@google.com470e71d2011-07-07 08:21:25 +0000118
119 shift3 = WebRtcSpl_GetSizeInBits(ener_comp)-15;
bjornv@webrtc.orgba97ea62015-02-13 09:51:40 +0000120 maxMeasure = (int16_t)WEBRTC_SPL_SHIFT_W32(ener_comp, -shift3) *
121 crossSquareMax;
niklase@google.com470e71d2011-07-07 08:21:25 +0000122
123 /* Calculate shift value, so that the two measures can
124 be put in the same Q domain */
kwiberg3fc8e8d2016-05-20 04:40:29 -0700125 if(2 * shiftMax + shift3 > 2 * shift1 + shift2) {
126 tmp1 =
127 WEBRTC_SPL_MIN(31, 2 * shiftMax + shift3 - 2 * shift1 - shift2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000128 tmp2 = 0;
129 } else {
130 tmp1 = 0;
kwiberg3fc8e8d2016-05-20 04:40:29 -0700131 tmp2 =
132 WEBRTC_SPL_MIN(31, 2 * shift1 + shift2 - 2 * shiftMax - shift3);
niklase@google.com470e71d2011-07-07 08:21:25 +0000133 }
134
135 if ((measure>>tmp1) > (maxMeasure>>tmp2)) {
136 /* New lag is better => record lag, measure and domain */
137 lag = j;
138 crossSquareMax = crossSquare;
139 cross = cross_comp;
140 shiftMax = shift1;
141 ener = ener_comp;
142 }
143 }
144
145 /* Calculate the periodicity for the lag with the maximum correlation.
146
147 Definition of the periodicity:
148 abs(corr(vec1, vec2))/(sqrt(energy(vec1))*sqrt(energy(vec2)))
149
150 Work in the Square domain to simplify the calculations
151 max_perSquare is less than 1 (in Q15)
152 */
153 tmp2W32=WebRtcSpl_DotProductWithScale(&iLBCdec_inst->prevResidual[iLBCdec_inst->blockl-corrLen],
154 &iLBCdec_inst->prevResidual[iLBCdec_inst->blockl-corrLen],
155 corrLen, scale3);
156
157 if ((tmp2W32>0)&&(ener_comp>0)) {
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000158 /* norm energies to int16_t, compute the product of the energies and
159 use the upper int16_t as the denominator */
niklase@google.com470e71d2011-07-07 08:21:25 +0000160
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000161 scale1=(int16_t)WebRtcSpl_NormW32(tmp2W32)-16;
162 tmp1=(int16_t)WEBRTC_SPL_SHIFT_W32(tmp2W32, scale1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000163
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000164 scale2=(int16_t)WebRtcSpl_NormW32(ener)-16;
165 tmp2=(int16_t)WEBRTC_SPL_SHIFT_W32(ener, scale2);
bjornv@webrtc.org2f6ae0d2015-03-01 19:50:41 +0000166 denom = (int16_t)((tmp1 * tmp2) >> 16); /* in Q(scale1+scale2-16) */
niklase@google.com470e71d2011-07-07 08:21:25 +0000167
168 /* Square the cross correlation and norm it such that max_perSquare
169 will be in Q15 after the division */
170
171 totscale = scale1+scale2-1;
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000172 tmp1 = (int16_t)WEBRTC_SPL_SHIFT_W32(cross, (totscale>>1));
173 tmp2 = (int16_t)WEBRTC_SPL_SHIFT_W32(cross, totscale-(totscale>>1));
niklase@google.com470e71d2011-07-07 08:21:25 +0000174
bjornv@webrtc.orgba97ea62015-02-13 09:51:40 +0000175 nom = tmp1 * tmp2;
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000176 max_perSquare = (int16_t)WebRtcSpl_DivW32W16(nom, denom);
niklase@google.com470e71d2011-07-07 08:21:25 +0000177
178 } else {
179 max_perSquare = 0;
180 }
181 }
182
183 /* previous frame lost, use recorded lag and gain */
184
185 else {
186 lag = iLBCdec_inst->prevLag;
187 max_perSquare = iLBCdec_inst->perSquare;
188 }
189
190 /* Attenuate signal and scale down pitch pred gain if
191 several frames lost consecutively */
192
193 use_gain = 32767; /* 1.0 in Q15 */
194
195 if (iLBCdec_inst->consPLICount*iLBCdec_inst->blockl>320) {
196 use_gain = 29491; /* 0.9 in Q15 */
197 } else if (iLBCdec_inst->consPLICount*iLBCdec_inst->blockl>640) {
198 use_gain = 22938; /* 0.7 in Q15 */
199 } else if (iLBCdec_inst->consPLICount*iLBCdec_inst->blockl>960) {
200 use_gain = 16384; /* 0.5 in Q15 */
201 } else if (iLBCdec_inst->consPLICount*iLBCdec_inst->blockl>1280) {
202 use_gain = 0; /* 0.0 in Q15 */
203 }
204
205 /* Compute mixing factor of picth repeatition and noise:
206 for max_per>0.7 set periodicity to 1.0
207 0.4<max_per<0.7 set periodicity to (maxper-0.4)/0.7-0.4)
208 max_per<0.4 set periodicity to 0.0
209 */
210
211 if (max_perSquare>7868) { /* periodicity > 0.7 (0.7^4=0.2401 in Q15) */
212 pitchfact = 32767;
213 } else if (max_perSquare>839) { /* 0.4 < periodicity < 0.7 (0.4^4=0.0256 in Q15) */
214 /* find best index and interpolate from that */
215 ind = 5;
216 while ((max_perSquare<WebRtcIlbcfix_kPlcPerSqr[ind])&&(ind>0)) {
217 ind--;
218 }
219 /* pitch fact is approximated by first order */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000220 tmpW32 = (int32_t)WebRtcIlbcfix_kPlcPitchFact[ind] +
bjornv@webrtc.org2f6ae0d2015-03-01 19:50:41 +0000221 ((WebRtcIlbcfix_kPlcPfSlope[ind] *
222 (max_perSquare - WebRtcIlbcfix_kPlcPerSqr[ind])) >> 11);
niklase@google.com470e71d2011-07-07 08:21:25 +0000223
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000224 pitchfact = (int16_t)WEBRTC_SPL_MIN(tmpW32, 32767); /* guard against overflow */
niklase@google.com470e71d2011-07-07 08:21:25 +0000225
226 } else { /* periodicity < 0.4 */
227 pitchfact = 0;
228 }
229
230 /* avoid repetition of same pitch cycle (buzzyness) */
231 use_lag = lag;
232 if (lag<80) {
233 use_lag = 2*lag;
234 }
235
236 /* compute concealed residual */
Sam Zackrissonae93f042018-05-15 13:41:45 +0200237 noise_energy_threshold_30dB = (int32_t)iLBCdec_inst->blockl * 900;
niklase@google.com470e71d2011-07-07 08:21:25 +0000238 energy = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000239 for (i=0; i<iLBCdec_inst->blockl; i++) {
240
241 /* noise component - 52 < randlagFIX < 117 */
bjornv@webrtc.orgba97ea62015-02-13 09:51:40 +0000242 iLBCdec_inst->seed = (int16_t)(iLBCdec_inst->seed * 31821 + 13849);
Peter Kastingdce40cf2015-08-24 14:52:23 -0700243 randlag = 53 + (iLBCdec_inst->seed & 63);
Peter Kastingf045e4d2015-06-10 21:15:38 -0700244 if (randlag > i) {
245 randvec[i] =
246 iLBCdec_inst->prevResidual[iLBCdec_inst->blockl + i - randlag];
niklase@google.com470e71d2011-07-07 08:21:25 +0000247 } else {
Peter Kastingf045e4d2015-06-10 21:15:38 -0700248 randvec[i] = iLBCdec_inst->prevResidual[i - randlag];
niklase@google.com470e71d2011-07-07 08:21:25 +0000249 }
250
251 /* pitch repeatition component */
Peter Kastingf045e4d2015-06-10 21:15:38 -0700252 if (use_lag > i) {
253 PLCresidual[i] =
254 iLBCdec_inst->prevResidual[iLBCdec_inst->blockl + i - use_lag];
niklase@google.com470e71d2011-07-07 08:21:25 +0000255 } else {
Peter Kastingf045e4d2015-06-10 21:15:38 -0700256 PLCresidual[i] = PLCresidual[i - use_lag];
niklase@google.com470e71d2011-07-07 08:21:25 +0000257 }
258
259 /* Attinuate total gain for each 10 ms */
260 if (i<80) {
261 tot_gain=use_gain;
262 } else if (i<160) {
bjornv@webrtc.org2f6ae0d2015-03-01 19:50:41 +0000263 tot_gain = (int16_t)((31130 * use_gain) >> 15); /* 0.95*use_gain */
niklase@google.com470e71d2011-07-07 08:21:25 +0000264 } else {
bjornv@webrtc.org2f6ae0d2015-03-01 19:50:41 +0000265 tot_gain = (int16_t)((29491 * use_gain) >> 15); /* 0.9*use_gain */
niklase@google.com470e71d2011-07-07 08:21:25 +0000266 }
267
268
269 /* mix noise and pitch repeatition */
bjornv@webrtc.org2f6ae0d2015-03-01 19:50:41 +0000270 PLCresidual[i] = (int16_t)((tot_gain *
271 ((pitchfact * PLCresidual[i] + (32767 - pitchfact) * randvec[i] +
272 16384) >> 15)) >> 15);
niklase@google.com470e71d2011-07-07 08:21:25 +0000273
Sam Zackrissonae93f042018-05-15 13:41:45 +0200274 /* Compute energy until threshold for noise energy is reached */
275 if (energy < noise_energy_threshold_30dB) {
276 energy += PLCresidual[i] * PLCresidual[i];
277 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000278 }
279
280 /* less than 30 dB, use only noise */
Sam Zackrissonae93f042018-05-15 13:41:45 +0200281 if (energy < noise_energy_threshold_30dB) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000282 for (i=0; i<iLBCdec_inst->blockl; i++) {
283 PLCresidual[i] = randvec[i];
284 }
285 }
286
287 /* use the old LPC */
288 WEBRTC_SPL_MEMCPY_W16(PLClpc, (*iLBCdec_inst).prevLpc, LPC_FILTERORDER+1);
289
290 /* Update state in case there are multiple frame losses */
291 iLBCdec_inst->prevLag = lag;
292 iLBCdec_inst->perSquare = max_perSquare;
293 }
294
295 /* no packet loss, copy input */
296
297 else {
298 WEBRTC_SPL_MEMCPY_W16(PLCresidual, decresidual, iLBCdec_inst->blockl);
299 WEBRTC_SPL_MEMCPY_W16(PLClpc, lpc, (LPC_FILTERORDER+1));
300 iLBCdec_inst->consPLICount = 0;
301 }
302
303 /* update state */
304 iLBCdec_inst->prevPLI = PLI;
305 WEBRTC_SPL_MEMCPY_W16(iLBCdec_inst->prevLpc, PLClpc, (LPC_FILTERORDER+1));
306 WEBRTC_SPL_MEMCPY_W16(iLBCdec_inst->prevResidual, PLCresidual, iLBCdec_inst->blockl);
307
308 return;
309}