FreeCalypso > hg > gsm-codec-lib
comparison libgsmefr/dtx_common.c @ 119:c1d53064b410
libgsmefr: split dtx.c into dtx_{common,dec,enc}.c
| author | Mychaela Falconia <falcon@freecalypso.org> |
|---|---|
| date | Sat, 10 Dec 2022 02:25:20 +0000 |
| parents | libgsmefr/dtx.c@58b64224d4ac |
| children | 7bc011aceb7f |
comparison
equal
deleted
inserted
replaced
| 118:cc08498ed21b | 119:c1d53064b410 |
|---|---|
| 1 /* | |
| 2 * This file is a product of splitting ETSI EFR dtx.c into parts; | |
| 3 * the present module is the common part for both the encoder and | |
| 4 * the decoder. | |
| 5 */ | |
| 6 | |
| 7 #include "gsm_efr.h" | |
| 8 #include "typedef.h" | |
| 9 #include "namespace.h" | |
| 10 #include "basic_op.h" | |
| 11 #include "cnst.h" | |
| 12 #include "sig_proc.h" | |
| 13 #include "memops.h" | |
| 14 #include "no_count.h" | |
| 15 #include "dtx.h" | |
| 16 #include "dtx_defs.h" | |
| 17 | |
| 18 /************************************************************************* | |
| 19 * | |
| 20 * FUNCTION NAME: update_lsf_history | |
| 21 * | |
| 22 * PURPOSE: Update the LSF parameter history. The LSF parameters kept | |
| 23 * in the buffer are used later for computing the reference | |
| 24 * LSF parameter vector and the averaged LSF parameter vector. | |
| 25 * | |
| 26 * INPUTS: lsf1[0..9] LSF vector of the 1st half of the frame | |
| 27 * lsf2[0..9] LSF vector of the 2nd half of the frame | |
| 28 * lsf_old[0..DTX_HANGOVER-1][0..M-1] | |
| 29 * Old LSF history | |
| 30 * | |
| 31 * OUTPUTS: lsf_old[0..DTX_HANGOVER-1][0..M-1] | |
| 32 * Updated LSF history | |
| 33 * | |
| 34 * RETURN VALUE: none | |
| 35 * | |
| 36 *************************************************************************/ | |
| 37 | |
| 38 void update_lsf_history ( | |
| 39 Word16 lsf1[M], | |
| 40 Word16 lsf2[M], | |
| 41 Word16 lsf_old[DTX_HANGOVER][M] | |
| 42 ) | |
| 43 { | |
| 44 Word16 i, j, temp; | |
| 45 | |
| 46 /* shift LSF data to make room for LSFs from current frame */ | |
| 47 /* This can also be implemented by using circular buffering */ | |
| 48 | |
| 49 for (i = DTX_HANGOVER - 1; i > 0; i--) | |
| 50 { | |
| 51 for (j = 0; j < M; j++) | |
| 52 { | |
| 53 lsf_old[i][j] = lsf_old[i - 1][j]; move16 (); | |
| 54 } | |
| 55 } | |
| 56 | |
| 57 /* Store new LSF data to lsf_old buffer */ | |
| 58 | |
| 59 for (i = 0; i < M; i++) | |
| 60 { | |
| 61 temp = add (shr (lsf1[i], 1), shr (lsf2[i], 1)); | |
| 62 lsf_old[0][i] = temp; move16 (); | |
| 63 } | |
| 64 | |
| 65 return; | |
| 66 } | |
| 67 | |
| 68 /************************************************************************* | |
| 69 * | |
| 70 * FUNCTION NAME: update_lsf_p_CN | |
| 71 * | |
| 72 * PURPOSE: Update the reference LSF parameter vector. The reference | |
| 73 * vector is computed by averaging the quantized LSF parameter | |
| 74 * vectors which exist in the LSF parameter history. | |
| 75 * | |
| 76 * INPUTS: lsf_old[0..DTX_HANGOVER-1][0..M-1] | |
| 77 * LSF parameter history | |
| 78 * | |
| 79 * OUTPUTS: lsf_p_CN[0..9] Computed reference LSF parameter vector | |
| 80 * | |
| 81 * RETURN VALUE: none | |
| 82 * | |
| 83 *************************************************************************/ | |
| 84 | |
| 85 void update_lsf_p_CN ( | |
| 86 Word16 lsf_old[DTX_HANGOVER][M], | |
| 87 Word16 lsf_p_CN[M] | |
| 88 ) | |
| 89 { | |
| 90 Word16 i, j; | |
| 91 Word32 L_temp; | |
| 92 | |
| 93 for (j = 0; j < M; j++) | |
| 94 { | |
| 95 L_temp = L_mult (INV_DTX_HANGOVER, lsf_old[0][j]); | |
| 96 for (i = 1; i < DTX_HANGOVER; i++) | |
| 97 { | |
| 98 L_temp = L_mac (L_temp, INV_DTX_HANGOVER, lsf_old[i][j]); | |
| 99 } | |
| 100 lsf_p_CN[j] = round (L_temp); move16 (); | |
| 101 } | |
| 102 | |
| 103 return; | |
| 104 } | |
| 105 | |
| 106 /************************************************************************* | |
| 107 * | |
| 108 * FUNCTION NAME: update_gcode0_CN | |
| 109 * | |
| 110 * PURPOSE: Update the reference fixed codebook gain parameter value. | |
| 111 * The reference value is computed by averaging the quantized | |
| 112 * fixed codebook gain parameter values which exist in the | |
| 113 * fixed codebook gain parameter history. | |
| 114 * | |
| 115 * INPUTS: gain_code_old[0..4*DTX_HANGOVER-1] | |
| 116 * fixed codebook gain parameter history | |
| 117 * | |
| 118 * OUTPUTS: none | |
| 119 * | |
| 120 * RETURN VALUE: Computed reference fixed codebook gain | |
| 121 * | |
| 122 *************************************************************************/ | |
| 123 | |
| 124 Word16 update_gcode0_CN ( | |
| 125 Word16 gain_code_old[4 * DTX_HANGOVER] | |
| 126 ) | |
| 127 { | |
| 128 Word16 i, j; | |
| 129 Word32 L_temp, L_ret; | |
| 130 | |
| 131 L_ret = 0L; move32 (); | |
| 132 for (i = 0; i < DTX_HANGOVER; i++) | |
| 133 { | |
| 134 L_temp = L_mult (0x1fff, gain_code_old[4 * i]); | |
| 135 for (j = 1; j < 4; j++) | |
| 136 { | |
| 137 L_temp = L_mac (L_temp, 0x1fff, gain_code_old[4 * i + j]); | |
| 138 } | |
| 139 L_ret = L_mac (L_ret, INV_DTX_HANGOVER, extract_h (L_temp)); | |
| 140 } | |
| 141 | |
| 142 return extract_h (L_ret); | |
| 143 } | |
| 144 | |
| 145 /************************************************************************* | |
| 146 * | |
| 147 * FUNCTION NAME: build_CN_code | |
| 148 * | |
| 149 * PURPOSE: Compute the comfort noise fixed codebook excitation. The | |
| 150 * gains of the pulses are always +/-1. | |
| 151 * | |
| 152 * INPUTS: *seed Old CN generator shift register state | |
| 153 * | |
| 154 * OUTPUTS: cod[0..39] Generated comfort noise fixed codebook vector | |
| 155 * *seed Updated CN generator shift register state | |
| 156 * | |
| 157 * RETURN VALUE: none | |
| 158 * | |
| 159 *************************************************************************/ | |
| 160 | |
| 161 void build_CN_code ( | |
| 162 Word16 cod[], | |
| 163 Word32 *seed | |
| 164 ) | |
| 165 { | |
| 166 Word16 i, j, k; | |
| 167 | |
| 168 for (i = 0; i < L_SUBFR; i++) | |
| 169 { | |
| 170 cod[i] = 0; move16 (); | |
| 171 } | |
| 172 | |
| 173 for (k = 0; k < NB_PULSE; k++) | |
| 174 { | |
| 175 i = pseudonoise (seed, 2); /* generate pulse position */ | |
| 176 i = shr (extract_l (L_mult (i, 10)), 1); | |
| 177 i = add (i, k); | |
| 178 | |
| 179 j = pseudonoise (seed, 1); /* generate sign */ | |
| 180 | |
| 181 test (); | |
| 182 if (j > 0) | |
| 183 { | |
| 184 cod[i] = 4096; move16 (); | |
| 185 } | |
| 186 else | |
| 187 { | |
| 188 cod[i] = -4096; move16 (); | |
| 189 } | |
| 190 } | |
| 191 | |
| 192 return; | |
| 193 } | |
| 194 | |
| 195 /************************************************************************* | |
| 196 * | |
| 197 * FUNCTION NAME: pseudonoise | |
| 198 * | |
| 199 * PURPOSE: Generate a random integer value to use in comfort noise | |
| 200 * generation. The algorithm uses polynomial x^31 + x^3 + 1 | |
| 201 * (length of PN sequence is 2^31 - 1). | |
| 202 * | |
| 203 * INPUTS: *shift_reg Old CN generator shift register state | |
| 204 * | |
| 205 * | |
| 206 * OUTPUTS: *shift_reg Updated CN generator shift register state | |
| 207 * | |
| 208 * RETURN VALUE: Generated random integer value | |
| 209 * | |
| 210 *************************************************************************/ | |
| 211 | |
| 212 Word16 pseudonoise ( | |
| 213 Word32 *shift_reg, | |
| 214 Word16 no_bits | |
| 215 ) | |
| 216 { | |
| 217 Word16 noise_bits, Sn, i; | |
| 218 | |
| 219 noise_bits = 0; move16 (); | |
| 220 for (i = 0; i < no_bits; i++) | |
| 221 { | |
| 222 /* State n == 31 */ | |
| 223 test (); logic32 (); | |
| 224 if ((*shift_reg & 0x00000001L) != 0) | |
| 225 { | |
| 226 Sn = 1; move16 (); | |
| 227 } | |
| 228 else | |
| 229 { | |
| 230 Sn = 0; move16 (); | |
| 231 } | |
| 232 | |
| 233 /* State n == 3 */ | |
| 234 test (); logic32 (); | |
| 235 if ((*shift_reg & 0x10000000L) != 0) | |
| 236 { | |
| 237 Sn = Sn ^ 1; logic16 (); | |
| 238 } | |
| 239 else | |
| 240 { | |
| 241 Sn = Sn ^ 0; logic16 (); | |
| 242 } | |
| 243 | |
| 244 noise_bits = shl (noise_bits, 1); | |
| 245 noise_bits = noise_bits | (extract_l (*shift_reg) & 1); | |
| 246 logic16 (); logic16 (); | |
| 247 | |
| 248 *shift_reg = L_shr (*shift_reg, 1); move32 (); | |
| 249 test (); logic16 (); | |
| 250 if (Sn & 1) | |
| 251 { | |
| 252 *shift_reg = *shift_reg | 0x40000000L; move32 (); logic32 (); | |
| 253 } | |
| 254 } | |
| 255 | |
| 256 return noise_bits; | |
| 257 } |
