FreeCalypso > hg > gsmhr-codec-ref
comparison sp_enc.c @ 0:9008dbc8ca74
import original C code from GSM 06.06
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Fri, 14 Jun 2024 23:27:16 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:9008dbc8ca74 |
---|---|
1 /*************************************************************************** | |
2 * | |
3 * File Name: sp_enc.c | |
4 * | |
5 * Purpose: Contains speech encoder function. Calls are made to the | |
6 * frame-based encoding functions (see sp_frm.c), and the subframe- | |
7 * based encoding function (see sp_sfrm.c) | |
8 * | |
9 * Functions in this file (only 1) | |
10 * speechEncoder() | |
11 * | |
12 **************************************************************************/ | |
13 /*_________________________________________________________________________ | |
14 | | | |
15 | Include Files | | |
16 |_________________________________________________________________________| | |
17 */ | |
18 | |
19 #include "mathhalf.h" | |
20 #include "mathdp31.h" | |
21 #include "sp_rom.h" | |
22 #include "sp_dec.h" | |
23 #include "sp_frm.h" | |
24 #include "sp_sfrm.h" | |
25 #include "sp_enc.h" | |
26 #include "host.h" | |
27 #include "vad.h" | |
28 | |
29 /*_________________________________________________________________________ | |
30 | | | |
31 | Local Defines | | |
32 |_________________________________________________________________________| | |
33 */ | |
34 | |
35 #define CG_INT_MACS 6 /* Number of Multiply-Accumulates in */ | |
36 /* one interpolation */ | |
37 #define ASCALE 0x0800 | |
38 #define LMAX 142 /* largest lag (integer sense) */ | |
39 #define LSMAX (LMAX+ CG_INT_MACS/2) /* Lag Search Array Length */ | |
40 #define NUM_CLOSED 3 /* Maximum number of lags searched */ | |
41 /* in closed loop. */ | |
42 | |
43 #define LPCSTARTINDEX 25 /* Where the LPC analysis window | |
44 * starts */ | |
45 #define INBUFFSZ LPCSTARTINDEX + A_LEN /* Input buffer size */ | |
46 #define NUMSTARTUPSMP INBUFFSZ - F_LEN /* Number of samples needed */ | |
47 /* at start up */ | |
48 #define NUMSTARTUPSMP_P1 INBUFFSZ - F_LEN + 1 | |
49 #define HPFSHIFT 1 /* no right shifts high pass shifts | |
50 * speech */ | |
51 | |
52 /*_________________________________________________________________________ | |
53 | | | |
54 | State variables (globals) | | |
55 |_________________________________________________________________________| | |
56 */ | |
57 | |
58 Shortword swOldR0; | |
59 Shortword swOldR0Index; | |
60 | |
61 struct NormSw psnsWSfrmEngSpace[2 * N_SUB]; | |
62 | |
63 Shortword pswHPFXState[4]; | |
64 Shortword pswHPFYState[8]; | |
65 Shortword pswOldFrmKs[NP]; | |
66 Shortword pswOldFrmAs[NP]; | |
67 Shortword pswOldFrmSNWCoefs[NP]; | |
68 Shortword pswWgtSpeechSpace[F_LEN + LMAX + CG_INT_MACS / 2]; | |
69 | |
70 Shortword pswSpeech[INBUFFSZ]; /* input speech */ | |
71 | |
72 Shortword swPtch = 1; | |
73 | |
74 /*_________________________________________________________________________ | |
75 | | | |
76 | Global DTX variables | | |
77 |_________________________________________________________________________| | |
78 */ | |
79 | |
80 Shortword swTxGsHistPtr = 0; | |
81 | |
82 Shortword pswCNVSCode1[N_SUB], | |
83 pswCNVSCode2[N_SUB], | |
84 pswCNGsp0Code[N_SUB], | |
85 pswCNLpc[3], | |
86 swCNR0; | |
87 | |
88 | |
89 extern Longword pL_GsHist[]; | |
90 extern LongwordRom ppLr_gsTable[4][32]; | |
91 | |
92 /*************************************************************************** | |
93 * | |
94 * FUNCTION NAME: speechEncoder | |
95 * | |
96 * PURPOSE: | |
97 * | |
98 * Performs GSM half-rate speech encoding on frame basis (160 samples). | |
99 * | |
100 * INPUTS: | |
101 * | |
102 * pswSpeechIn[0:159] - input speech samples, 160 new samples per frame | |
103 * | |
104 * OUTPUTS: | |
105 * | |
106 * pswFrmCodes[0:19] - output parameters, 18 speech parameters plus | |
107 * VAD and SP flags | |
108 * | |
109 * RETURN VALUE: | |
110 * | |
111 * None | |
112 * | |
113 * IMPLEMENTATION: | |
114 * | |
115 * n/a | |
116 * | |
117 * REFERENCES: Sub-clause 4.1 of GSM Recomendation 06.20 | |
118 * | |
119 * KEYWORDS: speechcoder, analysis | |
120 * | |
121 *************************************************************************/ | |
122 | |
123 void speechEncoder(Shortword pswSpeechIn[], Shortword pswFrmCodes[]) | |
124 { | |
125 | |
126 /*_________________________________________________________________________ | |
127 | | | |
128 | Static Variables | | |
129 |_________________________________________________________________________| | |
130 */ | |
131 | |
132 /* 1st point in analysis window */ | |
133 static Shortword *pswLpcStart = &pswSpeech[LPCSTARTINDEX]; | |
134 | |
135 /* 1st point of new frame other than 1st */ | |
136 static Shortword *pswNewSpeech = &pswSpeech[NUMSTARTUPSMP]; | |
137 | |
138 /* sample 0 of weighted speech */ | |
139 static Shortword *pswWgtSpeech = &pswWgtSpeechSpace[LSMAX]; | |
140 | |
141 static struct NormSw *psnsWSfrmEng = &psnsWSfrmEngSpace[N_SUB]; | |
142 | |
143 /*_________________________________________________________________________ | |
144 | | | |
145 | Automatic Variables | | |
146 |_________________________________________________________________________| | |
147 */ | |
148 | |
149 int iVoicing, /* bitAlloc */ | |
150 iR0, /* bitAlloc and aflat */ | |
151 piVq[3], /* bitAlloc */ | |
152 iSi, /* bitAlloc */ | |
153 piLagCode[N_SUB], /* bitAlloc */ | |
154 piVSCode1[N_SUB], /* bitAlloc */ | |
155 piVSCode2[N_SUB], /* bitAlloc */ | |
156 piGsp0Code[N_SUB]; /* bitAlloc */ | |
157 | |
158 short int siUVCode, | |
159 siSi, | |
160 i, | |
161 j; | |
162 | |
163 Shortword swR0, | |
164 pswLagCode[N_SUB], | |
165 pswVSCode1[N_SUB], | |
166 pswVSCode2[N_SUB], | |
167 pswGsp0Code[N_SUB], | |
168 *pswLagListPtr, | |
169 pswFrmKs[NP], | |
170 pswFrmAs[NP], | |
171 pswFrmSNWCoefs[NP], | |
172 pswLagList[N_SUB * NUM_CLOSED], | |
173 pswNumLagList[N_SUB], | |
174 pswPitchBuf[N_SUB], | |
175 pswHNWCoefBuf[N_SUB], | |
176 ppswSNWCoefAs[N_SUB][NP], | |
177 ppswSynthAs[N_SUB][NP]; | |
178 | |
179 Shortword swSP, | |
180 pswVadLags[4], /* VAD Parameters */ | |
181 swVadFlag; /* flag indicating voice activity | |
182 * detector state. 1 = speech or | |
183 * speech/signal present */ | |
184 struct NormSw | |
185 psnsSqrtRs[N_SUB]; | |
186 | |
187 /*_________________________________________________________________________ | |
188 | | | |
189 | Executable Code | | |
190 |_________________________________________________________________________| | |
191 */ | |
192 | |
193 /* Speech frame processing */ | |
194 /* High pass filter the speech */ | |
195 /* ---------------------------- */ | |
196 | |
197 filt4_2nd(psrHPFCoefs, pswSpeechIn, | |
198 pswHPFXState, pswHPFYState, F_LEN, HPFSHIFT); | |
199 | |
200 /* copy high passed filtered speech into encoder's speech buff */ | |
201 /*-------------------------------------------------------------*/ | |
202 | |
203 for (i = 0; i < F_LEN; i++) | |
204 pswNewSpeech[i] = pswSpeechIn[i]; | |
205 | |
206 | |
207 | |
208 | |
209 /* Calculate and quantize LPC coefficients */ | |
210 /* --------------------------------------- */ | |
211 | |
212 aflat(pswLpcStart, &iR0, pswFrmKs, piVq, | |
213 swPtch, &swVadFlag, &swSP); | |
214 | |
215 | |
216 /* Lookup frame energy r0 */ | |
217 /* ---------------------- */ | |
218 | |
219 swR0 = psrR0DecTbl[iR0 * 2]; /* lookupR0 */ | |
220 | |
221 /* Generate the direct form coefs */ | |
222 /* ------------------------------ */ | |
223 | |
224 if (!rcToADp(ASCALE, pswFrmKs, pswFrmAs)) | |
225 { | |
226 | |
227 getNWCoefs(pswFrmAs, pswFrmSNWCoefs); | |
228 } | |
229 else | |
230 { | |
231 | |
232 for (i = 0; i < NP; i++) | |
233 { | |
234 pswFrmKs[i] = pswOldFrmKs[i]; | |
235 pswFrmAs[i] = pswOldFrmAs[i]; | |
236 pswFrmSNWCoefs[i] = pswOldFrmSNWCoefs[i]; | |
237 } | |
238 } | |
239 | |
240 /* Interpolate, or otherwise get sfrm reflection coefs */ | |
241 /* --------------------------------------------------- */ | |
242 | |
243 getSfrmLpcTx(swOldR0, swR0, | |
244 pswOldFrmKs, pswOldFrmAs, | |
245 pswOldFrmSNWCoefs, | |
246 pswFrmKs, pswFrmAs, | |
247 pswFrmSNWCoefs, | |
248 pswSpeech, | |
249 &siSi, | |
250 psnsSqrtRs, | |
251 ppswSynthAs, ppswSNWCoefAs); | |
252 | |
253 /* loose once bitAlloc done */ | |
254 iSi = siSi; | |
255 | |
256 /* Weight the entire speech frame */ | |
257 /* ------------------------------ */ | |
258 | |
259 weightSpeechFrame(pswSpeech, ppswSynthAs[0], ppswSNWCoefAs[0], | |
260 pswWgtSpeechSpace); | |
261 | |
262 /* Perform open-loop lag search, get harmonic-noise-weighting parameters */ | |
263 /* --------------------------------------------------------------------- */ | |
264 | |
265 openLoopLagSearch(&pswWgtSpeechSpace[LSMAX], | |
266 swOldR0Index, | |
267 (Shortword) iR0, | |
268 &siUVCode, | |
269 pswLagList, | |
270 pswNumLagList, | |
271 pswPitchBuf, | |
272 pswHNWCoefBuf, | |
273 &psnsWSfrmEng[0], | |
274 pswVadLags, | |
275 swSP); | |
276 | |
277 iVoicing = siUVCode; | |
278 | |
279 | |
280 /* Using open loop LTP data to calculate swPtch */ /* DTX mode */ | |
281 /* parameter */ /* DTX mode */ | |
282 /* -------------------------------------------- */ /* DTX mode */ | |
283 | |
284 periodicity_update(pswVadLags, &swPtch); /* DTX mode */ | |
285 | |
286 | |
287 /* Subframe processing loop */ | |
288 /* ------------------------ */ | |
289 | |
290 pswLagListPtr = pswLagList; | |
291 | |
292 for (giSfrmCnt = 0; giSfrmCnt < N_SUB; giSfrmCnt++) | |
293 { | |
294 | |
295 if (swSP == 0) /* DTX mode */ | |
296 { /* DTX mode */ | |
297 pswVSCode1[giSfrmCnt] = pswCNVSCode1[giSfrmCnt]; /* DTX mode */ | |
298 pswVSCode2[giSfrmCnt] = pswCNVSCode2[giSfrmCnt]; /* DTX mode */ | |
299 pswGsp0Code[giSfrmCnt] = pswCNGsp0Code[giSfrmCnt]; /* DTX mode */ | |
300 } /* DTX mode */ | |
301 | |
302 sfrmAnalysis(&pswWgtSpeech[giSfrmCnt * S_LEN], | |
303 siUVCode, | |
304 psnsSqrtRs[giSfrmCnt], | |
305 ppswSNWCoefAs[giSfrmCnt], | |
306 pswLagListPtr, | |
307 pswNumLagList[giSfrmCnt], | |
308 pswPitchBuf[giSfrmCnt], | |
309 pswHNWCoefBuf[giSfrmCnt], | |
310 &pswLagCode[giSfrmCnt], &pswVSCode1[giSfrmCnt], | |
311 &pswVSCode2[giSfrmCnt], &pswGsp0Code[giSfrmCnt], | |
312 swSP); | |
313 | |
314 pswLagListPtr = &pswLagListPtr[pswNumLagList[giSfrmCnt]]; | |
315 | |
316 } | |
317 | |
318 | |
319 /* copy comfort noise parameters, */ /* DTX mode */ | |
320 /* update GS history */ /* DTX mode */ | |
321 /* ------------------------------ */ /* DTX mode */ | |
322 | |
323 if (swSP == 0) /* DTX mode */ | |
324 { /* DTX mode */ | |
325 | |
326 /* copy comfort noise frame parameter */ /* DTX mode */ | |
327 /* ---------------------------------- */ /* DTX mode */ | |
328 | |
329 iR0 = swCNR0; /* quantized R0 index */ /* DTX mode */ | |
330 for (i=0; i < 3; i++) /* DTX mode */ | |
331 piVq[i] = pswCNLpc[i]; /* DTX mode */ | |
332 | |
333 } /* DTX mode */ | |
334 else /* DTX mode */ | |
335 { /* DTX mode */ | |
336 | |
337 /* if swSP != 0, then update the GS history */ /* DTX mode */ | |
338 /* -----------------------------------------*/ /* DTX mode */ | |
339 | |
340 for (i=0; i < N_SUB; i++){ /* DTX mode */ | |
341 pL_GsHist[swTxGsHistPtr] = /* DTX mode */ | |
342 ppLr_gsTable[siUVCode][pswGsp0Code[i]]; /* DTX mode */ | |
343 swTxGsHistPtr++; /* DTX mode */ | |
344 if (swTxGsHistPtr > ((OVERHANG-1)*N_SUB)-1) /* DTX mode */ | |
345 swTxGsHistPtr=0; /* DTX mode */ | |
346 } /* DTX mode */ | |
347 | |
348 } /* DTX mode */ | |
349 | |
350 | |
351 /* End of frame processing, update frame based parameters */ | |
352 /* ------------------------------------------------------ */ | |
353 | |
354 for (i = 0; i < N_SUB; i++) | |
355 { | |
356 piLagCode[i] = pswLagCode[i]; | |
357 piVSCode1[i] = pswVSCode1[i]; | |
358 piVSCode2[i] = pswVSCode2[i]; | |
359 piGsp0Code[i] = pswGsp0Code[i]; | |
360 } | |
361 | |
362 swOldR0Index = (Shortword) iR0; | |
363 swOldR0 = swR0; | |
364 | |
365 for (i = 0; i < NP; i++) | |
366 { | |
367 pswOldFrmKs[i] = pswFrmKs[i]; | |
368 pswOldFrmAs[i] = pswFrmAs[i]; | |
369 pswOldFrmSNWCoefs[i] = pswFrmSNWCoefs[i]; | |
370 } | |
371 | |
372 /* Insert SID Codeword */ /* DTX mode */ | |
373 /* ------------------- */ /* DTX mode */ | |
374 | |
375 if (swSP == 0) /* DTX mode */ | |
376 { /* DTX mode */ | |
377 iVoicing = 0x0003; /* 2 bits */ /* DTX mode */ | |
378 iSi = 0x0001; /* 1 bit */ /* DTX mode */ | |
379 for (i=0; i < N_SUB; i++) /* DTX mode */ | |
380 { /* DTX mode */ | |
381 piVSCode1[i] = 0x01ff; /* 9 bits */ /* DTX mode */ | |
382 piGsp0Code[i] = 0x001f; /* 5 bits */ /* DTX mode */ | |
383 } | |
384 piLagCode[0] = 0x00ff; /* 8 bits */ /* DTX mode */ | |
385 piLagCode[1] = 0x000f; /* 4 bits */ /* DTX mode */ | |
386 piLagCode[2] = 0x000f; /* 4 bits */ /* DTX mode */ | |
387 piLagCode[3] = 0x000f; /* 4 bits */ /* DTX mode */ | |
388 } /* DTX mode */ | |
389 | |
390 | |
391 /* Generate encoded parameter array */ | |
392 /* -------------------------------- */ | |
393 | |
394 fillBitAlloc(iVoicing, iR0, piVq, iSi, piLagCode, | |
395 piVSCode1, piVSCode2, | |
396 piGsp0Code, swVadFlag, swSP, pswFrmCodes); | |
397 | |
398 | |
399 /* delay the input speech by 1 frame */ | |
400 /*-----------------------------------*/ | |
401 | |
402 for (i = 0, j = F_LEN; j < INBUFFSZ; i++, j++) | |
403 { | |
404 pswSpeech[i] = pswSpeech[j]; | |
405 } | |
406 } |