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 | * This file contains the function for handling "normal" speech operation. |
| 13 | */ |
| 14 | #include "dsp.h" |
| 15 | |
| 16 | #include "signal_processing_library.h" |
| 17 | |
| 18 | #include "dsp_helpfunctions.h" |
| 19 | |
| 20 | /* Scratch usage: |
| 21 | |
| 22 | Type Name size startpos endpos |
pbos@webrtc.org | 0946a56 | 2013-04-09 00:28:06 +0000 | [diff] [blame] | 23 | int16_t pw16_expanded 125*fs/8000 0 125*fs/8000-1 |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 24 | |
| 25 | func WebRtcNetEQ_Expand 40+370*fs/8000 125*fs/8000 39+495*fs/8000 |
| 26 | |
| 27 | Total: 40+495*fs/8000 |
| 28 | */ |
| 29 | |
| 30 | #define SCRATCH_PW16_EXPANDED 0 |
| 31 | #if (defined(NETEQ_48KHZ_WIDEBAND)) |
| 32 | #define SCRATCH_NETEQ_EXPAND 756 |
| 33 | #elif (defined(NETEQ_32KHZ_WIDEBAND)) |
| 34 | #define SCRATCH_NETEQ_EXPAND 504 |
| 35 | #elif (defined(NETEQ_WIDEBAND)) |
| 36 | #define SCRATCH_NETEQ_EXPAND 252 |
| 37 | #else /* NB */ |
| 38 | #define SCRATCH_NETEQ_EXPAND 126 |
| 39 | #endif |
| 40 | |
| 41 | /**************************************************************************** |
| 42 | * WebRtcNetEQ_Normal(...) |
| 43 | * |
| 44 | * This function has the possibility to modify data that is played out in Normal |
| 45 | * mode, for example adjust the gain of the signal. The length of the signal |
| 46 | * can not be changed. |
| 47 | * |
| 48 | * Input: |
| 49 | * - inst : NetEq instance, i.e. the user that requests more |
| 50 | * speech/audio data |
| 51 | * - scratchPtr : Pointer to scratch vector |
| 52 | * - decoded : Pointer to vector of new data from decoder |
| 53 | * (Vector contents may be altered by the function) |
| 54 | * - len : Number of input samples |
| 55 | * |
| 56 | * Output: |
| 57 | * - inst : Updated user information |
| 58 | * - outData : Pointer to a memory space where the output data |
| 59 | * should be stored |
| 60 | * - pw16_len : Pointer to variable where the number of samples |
| 61 | * produced will be written |
| 62 | * |
| 63 | * Return value : >=0 - Number of samples written to outData |
| 64 | * -1 - Error |
| 65 | */ |
| 66 | |
| 67 | int WebRtcNetEQ_Normal(DSPInst_t *inst, |
| 68 | #ifdef SCRATCH |
pbos@webrtc.org | 0946a56 | 2013-04-09 00:28:06 +0000 | [diff] [blame] | 69 | int16_t *pw16_scratchPtr, |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 70 | #endif |
pbos@webrtc.org | 0946a56 | 2013-04-09 00:28:06 +0000 | [diff] [blame] | 71 | int16_t *pw16_decoded, int16_t len, |
| 72 | int16_t *pw16_outData, int16_t *pw16_len) |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 73 | { |
| 74 | |
| 75 | int i; |
pbos@webrtc.org | 0946a56 | 2013-04-09 00:28:06 +0000 | [diff] [blame] | 76 | int16_t fs_mult; |
| 77 | int16_t fs_shift; |
| 78 | int32_t w32_En_speech; |
| 79 | int16_t enLen; |
| 80 | int16_t w16_muted; |
| 81 | int16_t w16_inc, w16_frac; |
| 82 | int16_t w16_tmp; |
| 83 | int32_t w32_tmp; |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 84 | |
| 85 | /* Sanity check */ |
| 86 | if (len < 0) |
| 87 | { |
| 88 | /* Cannot have negative length of input vector */ |
| 89 | return (-1); |
| 90 | } |
| 91 | |
| 92 | if (len == 0) |
| 93 | { |
| 94 | /* Still got some data to play => continue with the same mode */ |
| 95 | *pw16_len = len; |
| 96 | return (len); |
| 97 | } |
| 98 | |
| 99 | fs_mult = WebRtcSpl_DivW32W16ResW16(inst->fs, 8000); |
| 100 | fs_shift = 30 - WebRtcSpl_NormW32(fs_mult); /* Note that this is not "exact" for 48kHz */ |
| 101 | |
| 102 | /* |
| 103 | * Check if last RecOut call resulted in an Expand or a FadeToBGN. If so, we have to take |
| 104 | * care of some cross-fading and unmuting. |
| 105 | */ |
| 106 | if (inst->w16_mode == MODE_EXPAND || inst->w16_mode == MODE_FADE_TO_BGN) |
| 107 | { |
| 108 | |
| 109 | /* Define memory where temporary result from Expand algorithm can be stored. */ |
| 110 | #ifdef SCRATCH |
pbos@webrtc.org | 0946a56 | 2013-04-09 00:28:06 +0000 | [diff] [blame] | 111 | int16_t *pw16_expanded = pw16_scratchPtr + SCRATCH_PW16_EXPANDED; |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 112 | #else |
pbos@webrtc.org | 0946a56 | 2013-04-09 00:28:06 +0000 | [diff] [blame] | 113 | int16_t pw16_expanded[FSMULT * 125]; |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 114 | #endif |
pbos@webrtc.org | 0946a56 | 2013-04-09 00:28:06 +0000 | [diff] [blame] | 115 | int16_t expandedLen = 0; |
| 116 | int16_t w16_decodedMax; |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 117 | |
| 118 | /* Find largest value in new data */ |
pbos@webrtc.org | 0946a56 | 2013-04-09 00:28:06 +0000 | [diff] [blame] | 119 | w16_decodedMax = WebRtcSpl_MaxAbsValueW16(pw16_decoded, (int16_t) len); |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 120 | |
| 121 | /* Generate interpolation data using Expand */ |
| 122 | /* First, set Expand parameters to appropriate values. */ |
| 123 | inst->ExpandInst.w16_lagsPosition = 0; |
| 124 | inst->ExpandInst.w16_lagsDirection = 0; |
| 125 | inst->ExpandInst.w16_stopMuting = 1; /* Do not mute signal any more */ |
| 126 | |
| 127 | /* Call Expand */ |
| 128 | WebRtcNetEQ_Expand(inst, |
| 129 | #ifdef SCRATCH |
| 130 | pw16_scratchPtr + SCRATCH_NETEQ_EXPAND, |
| 131 | #endif |
pbos@webrtc.org | 0946a56 | 2013-04-09 00:28:06 +0000 | [diff] [blame] | 132 | pw16_expanded, &expandedLen, (int16_t) (inst->w16_mode == MODE_FADE_TO_BGN)); |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 133 | |
| 134 | inst->ExpandInst.w16_stopMuting = 0; /* Restore value */ |
| 135 | inst->ExpandInst.w16_consecExp = 0; /* Last was not Expand any more */ |
| 136 | |
| 137 | /* Adjust muting factor (main muting factor times expand muting factor) */ |
| 138 | if (inst->w16_mode == MODE_FADE_TO_BGN) |
| 139 | { |
| 140 | /* If last mode was FadeToBGN, the mute factor should be zero. */ |
| 141 | inst->w16_muteFactor = 0; |
| 142 | } |
| 143 | else |
| 144 | { |
| 145 | /* w16_muteFactor * w16_expandMuteFactor */ |
| 146 | inst->w16_muteFactor |
pbos@webrtc.org | 0946a56 | 2013-04-09 00:28:06 +0000 | [diff] [blame] | 147 | = (int16_t) WEBRTC_SPL_MUL_16_16_RSFT(inst->w16_muteFactor, |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 148 | inst->ExpandInst.w16_expandMuteFactor, 14); |
| 149 | } |
| 150 | |
| 151 | /* Adjust muting factor if needed (to BGN level) */ |
| 152 | enLen = WEBRTC_SPL_MIN(fs_mult<<6, len); /* min( fs_mult * 64, len ) */ |
| 153 | w16_tmp = 6 + fs_shift - WebRtcSpl_NormW32( |
| 154 | WEBRTC_SPL_MUL_16_16(w16_decodedMax, w16_decodedMax)); |
| 155 | w16_tmp = WEBRTC_SPL_MAX(w16_tmp, 0); |
| 156 | w32_En_speech = WebRtcNetEQ_DotW16W16(pw16_decoded, pw16_decoded, enLen, w16_tmp); |
pbos@webrtc.org | 0946a56 | 2013-04-09 00:28:06 +0000 | [diff] [blame] | 157 | w32_En_speech = WebRtcSpl_DivW32W16(w32_En_speech, (int16_t) (enLen >> w16_tmp)); |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 158 | |
| 159 | if ((w32_En_speech != 0) && (w32_En_speech > inst->BGNInst.w32_energy)) |
| 160 | { |
| 161 | /* Normalize new frame energy to 15 bits */ |
| 162 | w16_tmp = WebRtcSpl_NormW32(w32_En_speech) - 16; |
| 163 | /* we want inst->BGNInst.energy/En_speech in Q14 */ |
| 164 | w32_tmp = WEBRTC_SPL_SHIFT_W32(inst->BGNInst.w32_energy, (w16_tmp+14)); |
pbos@webrtc.org | 0946a56 | 2013-04-09 00:28:06 +0000 | [diff] [blame] | 165 | w16_tmp = (int16_t) WEBRTC_SPL_SHIFT_W32(w32_En_speech, w16_tmp); |
| 166 | w16_tmp = (int16_t) WebRtcSpl_DivW32W16(w32_tmp, w16_tmp); |
| 167 | w16_muted = (int16_t) WebRtcSpl_SqrtFloor( |
| 168 | WEBRTC_SPL_LSHIFT_W32((int32_t) w16_tmp, |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 169 | 14)); /* w16_muted in Q14 (sqrt(Q28)) */ |
| 170 | } |
| 171 | else |
| 172 | { |
| 173 | w16_muted = 16384; /* 1.0 in Q14 */ |
| 174 | } |
| 175 | if (w16_muted > inst->w16_muteFactor) |
| 176 | { |
| 177 | inst->w16_muteFactor = WEBRTC_SPL_MIN(w16_muted, 16384); |
| 178 | } |
| 179 | |
| 180 | /* If muted increase by 0.64 for every 20 ms (NB/WB 0.0040/0.0020 in Q14) */ |
| 181 | w16_inc = WebRtcSpl_DivW32W16ResW16(64, fs_mult); |
| 182 | for (i = 0; i < len; i++) |
| 183 | { |
| 184 | /* scale with mute factor */ |
| 185 | w32_tmp = WEBRTC_SPL_MUL_16_16(pw16_decoded[i], inst->w16_muteFactor); |
| 186 | /* shift 14 with proper rounding */ |
pbos@webrtc.org | 0946a56 | 2013-04-09 00:28:06 +0000 | [diff] [blame] | 187 | pw16_decoded[i] = (int16_t) WEBRTC_SPL_RSHIFT_W32((w32_tmp + 8192), 14); |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 188 | /* increase mute_factor towards 16384 */ |
| 189 | inst->w16_muteFactor = WEBRTC_SPL_MIN(16384, (inst->w16_muteFactor+w16_inc)); |
| 190 | } |
| 191 | |
| 192 | /* |
| 193 | * Interpolate the expanded data into the new vector |
| 194 | * (NB/WB/SWB32/SWB40 8/16/32/32 samples) |
| 195 | */ |
| 196 | fs_shift = WEBRTC_SPL_MIN(3, fs_shift); /* Set to 3 for >32kHz */ |
| 197 | w16_inc = 4 >> fs_shift; |
| 198 | w16_frac = w16_inc; |
| 199 | for (i = 0; i < 8 * fs_mult; i++) |
| 200 | { |
pbos@webrtc.org | 0946a56 | 2013-04-09 00:28:06 +0000 | [diff] [blame] | 201 | pw16_decoded[i] = (int16_t) WEBRTC_SPL_RSHIFT_W32( |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 202 | (WEBRTC_SPL_MUL_16_16(w16_frac, pw16_decoded[i]) + |
| 203 | WEBRTC_SPL_MUL_16_16((32 - w16_frac), pw16_expanded[i]) + 8), |
| 204 | 5); |
| 205 | w16_frac += w16_inc; |
| 206 | } |
| 207 | |
| 208 | #ifdef NETEQ_CNG_CODEC |
| 209 | } |
| 210 | else if (inst->w16_mode==MODE_RFC3389CNG) |
| 211 | { /* previous was RFC 3389 CNG...*/ |
pbos@webrtc.org | 0946a56 | 2013-04-09 00:28:06 +0000 | [diff] [blame] | 212 | int16_t pw16_CngInterp[32]; |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 213 | /* Reset mute factor and start up fresh */ |
| 214 | inst->w16_muteFactor = 16384; |
| 215 | if (inst->CNG_Codec_inst != NULL) |
| 216 | { |
| 217 | /* Generate long enough for 32kHz */ |
| 218 | if(WebRtcCng_Generate(inst->CNG_Codec_inst,pw16_CngInterp, 32, 0)<0) |
| 219 | { |
| 220 | /* error returned; set return vector to all zeros */ |
| 221 | WebRtcSpl_MemSetW16(pw16_CngInterp, 0, 32); |
| 222 | } |
| 223 | } |
| 224 | else |
| 225 | { |
| 226 | /* |
| 227 | * If no CNG instance is defined, just copy from the decoded data. |
| 228 | * (This will result in interpolating the decoded with itself.) |
| 229 | */ |
| 230 | WEBRTC_SPL_MEMCPY_W16(pw16_CngInterp, pw16_decoded, fs_mult * 8); |
| 231 | } |
| 232 | /* |
| 233 | * Interpolate the CNG into the new vector |
| 234 | * (NB/WB/SWB32kHz/SWB48kHz 8/16/32/32 samples) |
| 235 | */ |
| 236 | fs_shift = WEBRTC_SPL_MIN(3, fs_shift); /* Set to 3 for >32kHz */ |
| 237 | w16_inc = 4>>fs_shift; |
| 238 | w16_frac = w16_inc; |
| 239 | for (i = 0; i < 8 * fs_mult; i++) |
| 240 | { |
pbos@webrtc.org | 0946a56 | 2013-04-09 00:28:06 +0000 | [diff] [blame] | 241 | pw16_decoded[i] = (int16_t) WEBRTC_SPL_RSHIFT_W32( |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 242 | (WEBRTC_SPL_MUL_16_16(w16_frac, pw16_decoded[i]) + |
| 243 | WEBRTC_SPL_MUL_16_16((32-w16_frac), pw16_CngInterp[i]) + 8), |
| 244 | 5); |
| 245 | w16_frac += w16_inc; |
| 246 | } |
| 247 | #endif |
| 248 | |
| 249 | } |
| 250 | else if (inst->w16_muteFactor < 16384) |
| 251 | { |
| 252 | /* |
| 253 | * Previous was neither of Expand, FadeToBGN or RFC3389_CNG, but we are still |
| 254 | * ramping up from previous muting. |
| 255 | * If muted increase by 0.64 for every 20 ms (NB/WB 0.0040/0.0020 in Q14) |
| 256 | */ |
| 257 | w16_inc = WebRtcSpl_DivW32W16ResW16(64, fs_mult); |
| 258 | for (i = 0; i < len; i++) |
| 259 | { |
| 260 | /* scale with mute factor */ |
| 261 | w32_tmp = WEBRTC_SPL_MUL_16_16(pw16_decoded[i], inst->w16_muteFactor); |
| 262 | /* shift 14 with proper rounding */ |
pbos@webrtc.org | 0946a56 | 2013-04-09 00:28:06 +0000 | [diff] [blame] | 263 | pw16_decoded[i] = (int16_t) WEBRTC_SPL_RSHIFT_W32((w32_tmp + 8192), 14); |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 264 | /* increase mute_factor towards 16384 */ |
| 265 | inst->w16_muteFactor = WEBRTC_SPL_MIN(16384, (inst->w16_muteFactor+w16_inc)); |
| 266 | } |
| 267 | } |
| 268 | |
| 269 | /* Copy data to other buffer */WEBRTC_SPL_MEMMOVE_W16(pw16_outData, pw16_decoded, len); |
| 270 | |
| 271 | inst->w16_mode = MODE_NORMAL; |
| 272 | *pw16_len = len; |
| 273 | return (len); |
| 274 | |
| 275 | } |
| 276 | |
| 277 | #undef SCRATCH_PW16_EXPANDED |
| 278 | #undef SCRATCH_NETEQ_EXPAND |
| 279 | |