niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 1 | /* |
| 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_EnhancerInterface.c |
| 16 | |
| 17 | ******************************************************************/ |
| 18 | |
Timothy Gu | 3111783 | 2020-12-18 22:25:57 -0800 | [diff] [blame] | 19 | #include "modules/audio_coding/codecs/ilbc/enhancer_interface.h" |
| 20 | |
Ivo Creusen | 812c73c | 2021-01-18 16:25:22 +0100 | [diff] [blame^] | 21 | #include <stdlib.h> |
bjornv@webrtc.org | 5227534 | 2014-08-20 10:09:34 +0000 | [diff] [blame] | 22 | #include <string.h> |
| 23 | |
Mirko Bonadei | 06c2aa9 | 2018-02-01 15:11:41 +0100 | [diff] [blame] | 24 | #include "modules/audio_coding/codecs/ilbc/constants.h" |
Timothy Gu | 3111783 | 2020-12-18 22:25:57 -0800 | [diff] [blame] | 25 | #include "modules/audio_coding/codecs/ilbc/defines.h" |
Mirko Bonadei | 06c2aa9 | 2018-02-01 15:11:41 +0100 | [diff] [blame] | 26 | #include "modules/audio_coding/codecs/ilbc/enhancer.h" |
| 27 | #include "modules/audio_coding/codecs/ilbc/hp_output.h" |
Timothy Gu | 3111783 | 2020-12-18 22:25:57 -0800 | [diff] [blame] | 28 | #include "modules/audio_coding/codecs/ilbc/xcorr_coef.h" |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 29 | |
| 30 | |
| 31 | |
| 32 | /*----------------------------------------------------------------* |
| 33 | * interface for enhancer |
| 34 | *---------------------------------------------------------------*/ |
| 35 | |
kwiberg | affcac4 | 2016-09-01 12:47:17 -0700 | [diff] [blame] | 36 | size_t // (o) Estimated lag in end of in[] |
| 37 | WebRtcIlbcfix_EnhancerInterface( |
| 38 | int16_t* out, // (o) enhanced signal |
| 39 | const int16_t* in, // (i) unenhanced signal |
| 40 | IlbcDecoder* iLBCdec_inst) { // (i) buffers etc |
Peter Kasting | 1380e26 | 2015-08-28 17:31:03 -0700 | [diff] [blame] | 41 | size_t iblock; |
Peter Kasting | dce40cf | 2015-08-24 14:52:23 -0700 | [diff] [blame] | 42 | size_t lag=20, tlag=20; |
| 43 | size_t inLen=iLBCdec_inst->blockl+120; |
| 44 | int16_t scale, scale1; |
| 45 | size_t plc_blockl; |
Peter Kasting | 1380e26 | 2015-08-28 17:31:03 -0700 | [diff] [blame] | 46 | int16_t *enh_buf; |
| 47 | size_t *enh_period; |
| 48 | int32_t tmp1, tmp2, max; |
| 49 | size_t new_blocks; |
pbos@webrtc.org | 0946a56 | 2013-04-09 00:28:06 +0000 | [diff] [blame] | 50 | int16_t *enh_bufPtr1; |
Peter Kasting | dce40cf | 2015-08-24 14:52:23 -0700 | [diff] [blame] | 51 | size_t i; |
Peter Kasting | 1380e26 | 2015-08-28 17:31:03 -0700 | [diff] [blame] | 52 | size_t k; |
pbos@webrtc.org | 0946a56 | 2013-04-09 00:28:06 +0000 | [diff] [blame] | 53 | int16_t EnChange; |
| 54 | int16_t SqrtEnChange; |
| 55 | int16_t inc; |
| 56 | int16_t win; |
| 57 | int16_t *tmpW16ptr; |
Peter Kasting | 1380e26 | 2015-08-28 17:31:03 -0700 | [diff] [blame] | 58 | size_t startPos; |
pbos@webrtc.org | 0946a56 | 2013-04-09 00:28:06 +0000 | [diff] [blame] | 59 | int16_t *plc_pred; |
kwiberg | affcac4 | 2016-09-01 12:47:17 -0700 | [diff] [blame] | 60 | const int16_t *target, *regressor; |
pbos@webrtc.org | 0946a56 | 2013-04-09 00:28:06 +0000 | [diff] [blame] | 61 | int16_t max16; |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 62 | int shifts; |
pbos@webrtc.org | 0946a56 | 2013-04-09 00:28:06 +0000 | [diff] [blame] | 63 | int32_t ener; |
| 64 | int16_t enerSh; |
| 65 | int16_t corrSh; |
Peter Kasting | dce40cf | 2015-08-24 14:52:23 -0700 | [diff] [blame] | 66 | size_t ind; |
| 67 | int16_t sh; |
Peter Kasting | 1380e26 | 2015-08-28 17:31:03 -0700 | [diff] [blame] | 68 | size_t start, stop; |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 69 | /* Stack based */ |
pbos@webrtc.org | 0946a56 | 2013-04-09 00:28:06 +0000 | [diff] [blame] | 70 | int16_t totsh[3]; |
| 71 | int16_t downsampled[(BLOCKL_MAX+120)>>1]; /* length 180 */ |
| 72 | int32_t corr32[50]; |
| 73 | int32_t corrmax[3]; |
| 74 | int16_t corr16[3]; |
| 75 | int16_t en16[3]; |
Peter Kasting | 1380e26 | 2015-08-28 17:31:03 -0700 | [diff] [blame] | 76 | size_t lagmax[3]; |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 77 | |
tina.legrand@webrtc.org | a41b4ce | 2011-08-29 08:19:30 +0000 | [diff] [blame] | 78 | plc_pred = downsampled; /* Reuse memory since plc_pred[ENH_BLOCKL] and |
| 79 | downsampled are non overlapping */ |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 80 | enh_buf=iLBCdec_inst->enh_buf; |
| 81 | enh_period=iLBCdec_inst->enh_period; |
| 82 | |
| 83 | /* Copy in the new data into the enhancer buffer */ |
bjornv@webrtc.org | 5227534 | 2014-08-20 10:09:34 +0000 | [diff] [blame] | 84 | memmove(enh_buf, &enh_buf[iLBCdec_inst->blockl], |
| 85 | (ENH_BUFL - iLBCdec_inst->blockl) * sizeof(*enh_buf)); |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 86 | |
| 87 | WEBRTC_SPL_MEMCPY_W16(&enh_buf[ENH_BUFL-iLBCdec_inst->blockl], in, |
| 88 | iLBCdec_inst->blockl); |
| 89 | |
| 90 | /* Set variables that are dependent on frame size */ |
| 91 | if (iLBCdec_inst->mode==30) { |
| 92 | plc_blockl=ENH_BLOCKL; |
| 93 | new_blocks=3; |
tina.legrand@webrtc.org | a41b4ce | 2011-08-29 08:19:30 +0000 | [diff] [blame] | 94 | startPos=320; /* Start position for enhancement |
| 95 | (640-new_blocks*ENH_BLOCKL-80) */ |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 96 | } else { |
| 97 | plc_blockl=40; |
| 98 | new_blocks=2; |
tina.legrand@webrtc.org | a41b4ce | 2011-08-29 08:19:30 +0000 | [diff] [blame] | 99 | startPos=440; /* Start position for enhancement |
| 100 | (640-new_blocks*ENH_BLOCKL-40) */ |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 101 | } |
| 102 | |
| 103 | /* Update the pitch prediction for each enhancer block, move the old ones */ |
bjornv@webrtc.org | 5227534 | 2014-08-20 10:09:34 +0000 | [diff] [blame] | 104 | memmove(enh_period, &enh_period[new_blocks], |
| 105 | (ENH_NBLOCKS_TOT - new_blocks) * sizeof(*enh_period)); |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 106 | |
Peter Kasting | 1380e26 | 2015-08-28 17:31:03 -0700 | [diff] [blame] | 107 | WebRtcSpl_DownsampleFast( |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 108 | enh_buf+ENH_BUFL-inLen, /* Input samples */ |
Peter Kasting | b7e5054 | 2015-06-11 12:55:50 -0700 | [diff] [blame] | 109 | inLen + ENH_BUFL_FILTEROVERHEAD, |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 110 | downsampled, |
Peter Kasting | b7e5054 | 2015-06-11 12:55:50 -0700 | [diff] [blame] | 111 | inLen / 2, |
pbos@webrtc.org | 0946a56 | 2013-04-09 00:28:06 +0000 | [diff] [blame] | 112 | (int16_t*)WebRtcIlbcfix_kLpFiltCoefs, /* Coefficients in Q12 */ |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 113 | FILTERORDER_DS_PLUS1, /* Length of filter (order-1) */ |
| 114 | FACTOR_DS, |
| 115 | DELAY_DS); |
| 116 | |
| 117 | /* Estimate the pitch in the down sampled domain. */ |
| 118 | for(iblock = 0; iblock<new_blocks; iblock++){ |
| 119 | |
| 120 | /* references */ |
Peter Kasting | f045e4d | 2015-06-10 21:15:38 -0700 | [diff] [blame] | 121 | target = downsampled + 60 + iblock * ENH_BLOCKL_HALF; |
| 122 | regressor = target - 10; |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 123 | |
| 124 | /* scaling */ |
Peter Kasting | b7e5054 | 2015-06-11 12:55:50 -0700 | [diff] [blame] | 125 | max16 = WebRtcSpl_MaxAbsValueW16(®ressor[-50], ENH_BLOCKL_HALF + 50 - 1); |
bjornv@webrtc.org | ba97ea6 | 2015-02-13 09:51:40 +0000 | [diff] [blame] | 126 | shifts = WebRtcSpl_GetSizeInBits((uint32_t)(max16 * max16)) - 25; |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 127 | shifts = WEBRTC_SPL_MAX(0, shifts); |
| 128 | |
| 129 | /* compute cross correlation */ |
Peter Kasting | a8b335c | 2015-06-11 18:51:20 -0700 | [diff] [blame] | 130 | WebRtcSpl_CrossCorrelation(corr32, target, regressor, ENH_BLOCKL_HALF, 50, |
| 131 | shifts, -1); |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 132 | |
| 133 | /* Find 3 highest correlations that should be compared for the |
| 134 | highest (corr*corr)/ener */ |
| 135 | |
| 136 | for (i=0;i<2;i++) { |
| 137 | lagmax[i] = WebRtcSpl_MaxIndexW32(corr32, 50); |
| 138 | corrmax[i] = corr32[lagmax[i]]; |
Peter Kasting | 1380e26 | 2015-08-28 17:31:03 -0700 | [diff] [blame] | 139 | start = WEBRTC_SPL_MAX(2, lagmax[i]) - 2; |
| 140 | stop = WEBRTC_SPL_MIN(47, lagmax[i]) + 2; |
| 141 | for (k = start; k <= stop; k++) { |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 142 | corr32[k] = 0; |
| 143 | } |
| 144 | } |
| 145 | lagmax[2] = WebRtcSpl_MaxIndexW32(corr32, 50); |
| 146 | corrmax[2] = corr32[lagmax[2]]; |
| 147 | |
| 148 | /* Calculate normalized corr^2 and ener */ |
| 149 | for (i=0;i<3;i++) { |
| 150 | corrSh = 15-WebRtcSpl_GetSizeInBits(corrmax[i]); |
Peter Kasting | 1380e26 | 2015-08-28 17:31:03 -0700 | [diff] [blame] | 151 | ener = WebRtcSpl_DotProductWithScale(regressor - lagmax[i], |
| 152 | regressor - lagmax[i], |
tina.legrand@webrtc.org | a41b4ce | 2011-08-29 08:19:30 +0000 | [diff] [blame] | 153 | ENH_BLOCKL_HALF, shifts); |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 154 | enerSh = 15-WebRtcSpl_GetSizeInBits(ener); |
pbos@webrtc.org | 0946a56 | 2013-04-09 00:28:06 +0000 | [diff] [blame] | 155 | corr16[i] = (int16_t)WEBRTC_SPL_SHIFT_W32(corrmax[i], corrSh); |
bjornv@webrtc.org | 2f6ae0d | 2015-03-01 19:50:41 +0000 | [diff] [blame] | 156 | corr16[i] = (int16_t)((corr16[i] * corr16[i]) >> 16); |
pbos@webrtc.org | 0946a56 | 2013-04-09 00:28:06 +0000 | [diff] [blame] | 157 | en16[i] = (int16_t)WEBRTC_SPL_SHIFT_W32(ener, enerSh); |
kwiberg | 4f6c2b6 | 2016-05-26 03:40:51 -0700 | [diff] [blame] | 158 | totsh[i] = enerSh - 2 * corrSh; |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 159 | } |
| 160 | |
| 161 | /* Compare lagmax[0..3] for the (corr^2)/ener criteria */ |
| 162 | ind = 0; |
| 163 | for (i=1; i<3; i++) { |
| 164 | if (totsh[ind] > totsh[i]) { |
| 165 | sh = WEBRTC_SPL_MIN(31, totsh[ind]-totsh[i]); |
bjornv@webrtc.org | 2f6ae0d | 2015-03-01 19:50:41 +0000 | [diff] [blame] | 166 | if (corr16[ind] * en16[i] < (corr16[i] * en16[ind]) >> sh) { |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 167 | ind = i; |
| 168 | } |
| 169 | } else { |
| 170 | sh = WEBRTC_SPL_MIN(31, totsh[i]-totsh[ind]); |
bjornv@webrtc.org | 2f6ae0d | 2015-03-01 19:50:41 +0000 | [diff] [blame] | 171 | if ((corr16[ind] * en16[i]) >> sh < corr16[i] * en16[ind]) { |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 172 | ind = i; |
| 173 | } |
| 174 | } |
| 175 | } |
| 176 | |
Peter Kasting | 1380e26 | 2015-08-28 17:31:03 -0700 | [diff] [blame] | 177 | lag = lagmax[ind] + 10; |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 178 | |
| 179 | /* Store the estimated lag in the non-downsampled domain */ |
Peter Kasting | 1380e26 | 2015-08-28 17:31:03 -0700 | [diff] [blame] | 180 | enh_period[ENH_NBLOCKS_TOT - new_blocks + iblock] = lag * 8; |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 181 | |
| 182 | /* Store the estimated lag for backward PLC */ |
| 183 | if (iLBCdec_inst->prev_enh_pl==1) { |
| 184 | if (!iblock) { |
bjornv@webrtc.org | ba97ea6 | 2015-02-13 09:51:40 +0000 | [diff] [blame] | 185 | tlag = lag * 2; |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 186 | } |
| 187 | } else { |
| 188 | if (iblock==1) { |
bjornv@webrtc.org | ba97ea6 | 2015-02-13 09:51:40 +0000 | [diff] [blame] | 189 | tlag = lag * 2; |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 190 | } |
| 191 | } |
| 192 | |
bjornv@webrtc.org | ba97ea6 | 2015-02-13 09:51:40 +0000 | [diff] [blame] | 193 | lag *= 2; |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 194 | } |
| 195 | |
| 196 | if ((iLBCdec_inst->prev_enh_pl==1)||(iLBCdec_inst->prev_enh_pl==2)) { |
| 197 | |
| 198 | /* Calculate the best lag of the new frame |
| 199 | This is used to interpolate backwards and mix with the PLC'd data |
| 200 | */ |
| 201 | |
| 202 | /* references */ |
| 203 | target=in; |
| 204 | regressor=in+tlag-1; |
| 205 | |
| 206 | /* scaling */ |
Ivo Creusen | 812c73c | 2021-01-18 16:25:22 +0100 | [diff] [blame^] | 207 | // Note that this is not abs-max, so we will take the absolute value below. |
Ivo Creusen | fe06dbd | 2021-01-12 16:01:30 +0100 | [diff] [blame] | 208 | max16 = regressor[WebRtcSpl_MaxAbsIndexW16(regressor, plc_blockl + 3 - 1)]; |
Ivo Creusen | 812c73c | 2021-01-18 16:25:22 +0100 | [diff] [blame^] | 209 | const int16_t max_target = |
| 210 | target[WebRtcSpl_MaxAbsIndexW16(target, plc_blockl + 3 - 1)]; |
| 211 | const int64_t max_val = plc_blockl * abs(max16 * max_target); |
Ivo Creusen | 0ff2b4c | 2020-12-16 17:37:58 +0100 | [diff] [blame] | 212 | const int32_t factor = max_val >> 31; |
| 213 | shifts = factor == 0 ? 0 : 31 - WebRtcSpl_NormW32(factor); |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 214 | |
| 215 | /* compute cross correlation */ |
Peter Kasting | a8b335c | 2015-06-11 18:51:20 -0700 | [diff] [blame] | 216 | WebRtcSpl_CrossCorrelation(corr32, target, regressor, plc_blockl, 3, shifts, |
| 217 | 1); |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 218 | |
| 219 | /* find lag */ |
| 220 | lag=WebRtcSpl_MaxIndexW32(corr32, 3); |
| 221 | lag+=tlag-1; |
| 222 | |
| 223 | /* Copy the backward PLC to plc_pred */ |
| 224 | |
| 225 | if (iLBCdec_inst->prev_enh_pl==1) { |
| 226 | if (lag>plc_blockl) { |
| 227 | WEBRTC_SPL_MEMCPY_W16(plc_pred, &in[lag-plc_blockl], plc_blockl); |
| 228 | } else { |
| 229 | WEBRTC_SPL_MEMCPY_W16(&plc_pred[plc_blockl-lag], in, lag); |
tina.legrand@webrtc.org | a41b4ce | 2011-08-29 08:19:30 +0000 | [diff] [blame] | 230 | WEBRTC_SPL_MEMCPY_W16( |
| 231 | plc_pred, &enh_buf[ENH_BUFL-iLBCdec_inst->blockl-plc_blockl+lag], |
| 232 | (plc_blockl-lag)); |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 233 | } |
| 234 | } else { |
Peter Kasting | dce40cf | 2015-08-24 14:52:23 -0700 | [diff] [blame] | 235 | size_t pos; |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 236 | |
| 237 | pos = plc_blockl; |
| 238 | |
| 239 | while (lag<pos) { |
| 240 | WEBRTC_SPL_MEMCPY_W16(&plc_pred[pos-lag], in, lag); |
| 241 | pos = pos - lag; |
| 242 | } |
| 243 | WEBRTC_SPL_MEMCPY_W16(plc_pred, &in[lag-pos], pos); |
| 244 | |
| 245 | } |
| 246 | |
| 247 | if (iLBCdec_inst->prev_enh_pl==1) { |
| 248 | /* limit energy change |
tina.legrand@webrtc.org | a41b4ce | 2011-08-29 08:19:30 +0000 | [diff] [blame] | 249 | if energy in backward PLC is more than 4 times higher than the forward |
| 250 | PLC, then reduce the energy in the backward PLC vector: |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 251 | sample 1...len-16 set energy of the to 4 times forward PLC |
| 252 | sample len-15..len interpolate between 4 times fw PLC and bw PLC energy |
| 253 | |
| 254 | Note: Compared to floating point code there is a slight change, |
tina.legrand@webrtc.org | a41b4ce | 2011-08-29 08:19:30 +0000 | [diff] [blame] | 255 | the window is 16 samples long instead of 10 samples to simplify the |
| 256 | calculations |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 257 | */ |
| 258 | |
tina.legrand@webrtc.org | a41b4ce | 2011-08-29 08:19:30 +0000 | [diff] [blame] | 259 | max=WebRtcSpl_MaxAbsValueW16( |
| 260 | &enh_buf[ENH_BUFL-iLBCdec_inst->blockl-plc_blockl], plc_blockl); |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 261 | max16=WebRtcSpl_MaxAbsValueW16(plc_pred, plc_blockl); |
| 262 | max = WEBRTC_SPL_MAX(max, max16); |
pbos@webrtc.org | 0946a56 | 2013-04-09 00:28:06 +0000 | [diff] [blame] | 263 | scale=22-(int16_t)WebRtcSpl_NormW32(max); |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 264 | scale=WEBRTC_SPL_MAX(scale,0); |
| 265 | |
tina.legrand@webrtc.org | a41b4ce | 2011-08-29 08:19:30 +0000 | [diff] [blame] | 266 | tmp2 = WebRtcSpl_DotProductWithScale( |
| 267 | &enh_buf[ENH_BUFL-iLBCdec_inst->blockl-plc_blockl], |
| 268 | &enh_buf[ENH_BUFL-iLBCdec_inst->blockl-plc_blockl], |
| 269 | plc_blockl, scale); |
| 270 | tmp1 = WebRtcSpl_DotProductWithScale(plc_pred, plc_pred, |
| 271 | plc_blockl, scale); |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 272 | |
| 273 | /* Check the energy difference */ |
| 274 | if ((tmp1>0)&&((tmp1>>2)>tmp2)) { |
| 275 | /* EnChange is now guaranteed to be <0.5 |
| 276 | Calculate EnChange=tmp2/tmp1 in Q16 |
| 277 | */ |
| 278 | |
pbos@webrtc.org | 0946a56 | 2013-04-09 00:28:06 +0000 | [diff] [blame] | 279 | scale1=(int16_t)WebRtcSpl_NormW32(tmp1); |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 280 | tmp1=WEBRTC_SPL_SHIFT_W32(tmp1, (scale1-16)); /* using 15 bits */ |
| 281 | |
| 282 | tmp2=WEBRTC_SPL_SHIFT_W32(tmp2, (scale1)); |
pbos@webrtc.org | 0946a56 | 2013-04-09 00:28:06 +0000 | [diff] [blame] | 283 | EnChange = (int16_t)WebRtcSpl_DivW32W16(tmp2, |
| 284 | (int16_t)tmp1); |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 285 | |
| 286 | /* Calculate the Sqrt of the energy in Q15 ((14+16)/2) */ |
bjornv@webrtc.org | 4ab23d0 | 2015-03-20 06:01:06 +0000 | [diff] [blame] | 287 | SqrtEnChange = (int16_t)WebRtcSpl_SqrtFloor(EnChange << 14); |
tina.legrand@webrtc.org | a41b4ce | 2011-08-29 08:19:30 +0000 | [diff] [blame] | 288 | |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 289 | |
| 290 | /* Multiply first part of vector with 2*SqrtEnChange */ |
Peter Kasting | dce40cf | 2015-08-24 14:52:23 -0700 | [diff] [blame] | 291 | WebRtcSpl_ScaleVector(plc_pred, plc_pred, SqrtEnChange, plc_blockl-16, |
| 292 | 14); |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 293 | |
| 294 | /* Calculate increase parameter for window part (16 last samples) */ |
tina.legrand@webrtc.org | a41b4ce | 2011-08-29 08:19:30 +0000 | [diff] [blame] | 295 | /* (1-2*SqrtEnChange)/16 in Q15 */ |
bjornv@webrtc.org | f71785c | 2014-10-08 15:36:30 +0000 | [diff] [blame] | 296 | inc = 2048 - (SqrtEnChange >> 3); |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 297 | |
| 298 | win=0; |
| 299 | tmpW16ptr=&plc_pred[plc_blockl-16]; |
| 300 | |
| 301 | for (i=16;i>0;i--) { |
bjornv@webrtc.org | 2f6ae0d | 2015-03-01 19:50:41 +0000 | [diff] [blame] | 302 | *tmpW16ptr = (int16_t)( |
| 303 | (*tmpW16ptr * (SqrtEnChange + (win >> 1))) >> 14); |
tina.legrand@webrtc.org | a41b4ce | 2011-08-29 08:19:30 +0000 | [diff] [blame] | 304 | /* multiply by (2.0*SqrtEnChange+win) */ |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 305 | |
| 306 | win += inc; |
| 307 | tmpW16ptr++; |
| 308 | } |
| 309 | } |
| 310 | |
| 311 | /* Make the linear interpolation between the forward PLC'd data |
| 312 | and the backward PLC'd data (from the new frame) |
| 313 | */ |
| 314 | |
| 315 | if (plc_blockl==40) { |
| 316 | inc=400; /* 1/41 in Q14 */ |
| 317 | } else { /* plc_blockl==80 */ |
| 318 | inc=202; /* 1/81 in Q14 */ |
| 319 | } |
| 320 | win=0; |
| 321 | enh_bufPtr1=&enh_buf[ENH_BUFL-1-iLBCdec_inst->blockl]; |
| 322 | for (i=0; i<plc_blockl; i++) { |
| 323 | win+=inc; |
bjornv@webrtc.org | 2f6ae0d | 2015-03-01 19:50:41 +0000 | [diff] [blame] | 324 | *enh_bufPtr1 = (int16_t)((*enh_bufPtr1 * win) >> 14); |
| 325 | *enh_bufPtr1 += (int16_t)( |
| 326 | ((16384 - win) * plc_pred[plc_blockl - 1 - i]) >> 14); |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 327 | enh_bufPtr1--; |
| 328 | } |
| 329 | } else { |
pbos@webrtc.org | 0946a56 | 2013-04-09 00:28:06 +0000 | [diff] [blame] | 330 | int16_t *synt = &downsampled[LPC_FILTERORDER]; |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 331 | |
| 332 | enh_bufPtr1=&enh_buf[ENH_BUFL-iLBCdec_inst->blockl-plc_blockl]; |
| 333 | WEBRTC_SPL_MEMCPY_W16(enh_bufPtr1, plc_pred, plc_blockl); |
| 334 | |
| 335 | /* Clear fileter memory */ |
| 336 | WebRtcSpl_MemSetW16(iLBCdec_inst->syntMem, 0, LPC_FILTERORDER); |
| 337 | WebRtcSpl_MemSetW16(iLBCdec_inst->hpimemy, 0, 4); |
| 338 | WebRtcSpl_MemSetW16(iLBCdec_inst->hpimemx, 0, 2); |
| 339 | |
| 340 | /* Initialize filter memory by filtering through 2 lags */ |
tina.legrand@webrtc.org | a41b4ce | 2011-08-29 08:19:30 +0000 | [diff] [blame] | 341 | WEBRTC_SPL_MEMCPY_W16(&synt[-LPC_FILTERORDER], iLBCdec_inst->syntMem, |
| 342 | LPC_FILTERORDER); |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 343 | WebRtcSpl_FilterARFastQ12( |
tina.legrand@webrtc.org | a41b4ce | 2011-08-29 08:19:30 +0000 | [diff] [blame] | 344 | enh_bufPtr1, |
| 345 | synt, |
| 346 | &iLBCdec_inst->old_syntdenum[ |
Peter Kasting | 728d903 | 2015-06-11 14:31:38 -0700 | [diff] [blame] | 347 | (iLBCdec_inst->nsub-1)*(LPC_FILTERORDER+1)], |
| 348 | LPC_FILTERORDER+1, lag); |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 349 | |
tina.legrand@webrtc.org | a41b4ce | 2011-08-29 08:19:30 +0000 | [diff] [blame] | 350 | WEBRTC_SPL_MEMCPY_W16(&synt[-LPC_FILTERORDER], &synt[lag-LPC_FILTERORDER], |
| 351 | LPC_FILTERORDER); |
pbos@webrtc.org | 0946a56 | 2013-04-09 00:28:06 +0000 | [diff] [blame] | 352 | WebRtcIlbcfix_HpOutput(synt, (int16_t*)WebRtcIlbcfix_kHpOutCoefs, |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 353 | iLBCdec_inst->hpimemy, iLBCdec_inst->hpimemx, |
Peter Kasting | dce40cf | 2015-08-24 14:52:23 -0700 | [diff] [blame] | 354 | lag); |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 355 | WebRtcSpl_FilterARFastQ12( |
| 356 | enh_bufPtr1, synt, |
tina.legrand@webrtc.org | a41b4ce | 2011-08-29 08:19:30 +0000 | [diff] [blame] | 357 | &iLBCdec_inst->old_syntdenum[ |
Peter Kasting | 728d903 | 2015-06-11 14:31:38 -0700 | [diff] [blame] | 358 | (iLBCdec_inst->nsub-1)*(LPC_FILTERORDER+1)], |
| 359 | LPC_FILTERORDER+1, lag); |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 360 | |
tina.legrand@webrtc.org | a41b4ce | 2011-08-29 08:19:30 +0000 | [diff] [blame] | 361 | WEBRTC_SPL_MEMCPY_W16(iLBCdec_inst->syntMem, &synt[lag-LPC_FILTERORDER], |
| 362 | LPC_FILTERORDER); |
pbos@webrtc.org | 0946a56 | 2013-04-09 00:28:06 +0000 | [diff] [blame] | 363 | WebRtcIlbcfix_HpOutput(synt, (int16_t*)WebRtcIlbcfix_kHpOutCoefs, |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 364 | iLBCdec_inst->hpimemy, iLBCdec_inst->hpimemx, |
Peter Kasting | dce40cf | 2015-08-24 14:52:23 -0700 | [diff] [blame] | 365 | lag); |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 366 | } |
| 367 | } |
| 368 | |
| 369 | |
| 370 | /* Perform enhancement block by block */ |
| 371 | |
| 372 | for (iblock = 0; iblock<new_blocks; iblock++) { |
bjornv@webrtc.org | ba97ea6 | 2015-02-13 09:51:40 +0000 | [diff] [blame] | 373 | WebRtcIlbcfix_Enhancer(out + iblock * ENH_BLOCKL, |
tina.legrand@webrtc.org | a41b4ce | 2011-08-29 08:19:30 +0000 | [diff] [blame] | 374 | enh_buf, |
| 375 | ENH_BUFL, |
Peter Kasting | 1380e26 | 2015-08-28 17:31:03 -0700 | [diff] [blame] | 376 | iblock * ENH_BLOCKL + startPos, |
tina.legrand@webrtc.org | a41b4ce | 2011-08-29 08:19:30 +0000 | [diff] [blame] | 377 | enh_period, |
Peter Kasting | 1380e26 | 2015-08-28 17:31:03 -0700 | [diff] [blame] | 378 | WebRtcIlbcfix_kEnhPlocs, ENH_NBLOCKS_TOT); |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 379 | } |
| 380 | |
| 381 | return (lag); |
| 382 | } |