xref: /aosp_15_r20/external/webrtc/modules/audio_coding/codecs/ilbc/encode.c (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright (c) 2012 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_Encode.c
16 
17 ******************************************************************/
18 
19 #include "modules/audio_coding/codecs/ilbc/encode.h"
20 
21 #include <string.h>
22 
23 #include "modules/audio_coding/codecs/ilbc/cb_construct.h"
24 #include "modules/audio_coding/codecs/ilbc/cb_search.h"
25 #include "modules/audio_coding/codecs/ilbc/constants.h"
26 #include "modules/audio_coding/codecs/ilbc/defines.h"
27 #include "modules/audio_coding/codecs/ilbc/frame_classify.h"
28 #include "modules/audio_coding/codecs/ilbc/hp_input.h"
29 #include "modules/audio_coding/codecs/ilbc/index_conv_enc.h"
30 #include "modules/audio_coding/codecs/ilbc/lpc_encode.h"
31 #include "modules/audio_coding/codecs/ilbc/pack_bits.h"
32 #include "modules/audio_coding/codecs/ilbc/state_construct.h"
33 #include "modules/audio_coding/codecs/ilbc/state_search.h"
34 #include "rtc_base/checks.h"
35 #include "rtc_base/system/arch.h"
36 
37 #ifdef SPLIT_10MS
38 #include "modules/audio_coding/codecs/ilbc/unpack_bits.h"
39 #include "modules/audio_coding/codecs/ilbc/index_conv_dec.h"
40 #endif
41 
42 #ifndef WEBRTC_ARCH_BIG_ENDIAN
43 #include "modules/audio_coding/codecs/ilbc/swap_bytes.h"
44 #endif
45 
46 /*----------------------------------------------------------------*
47  *  main encoder function
48  *---------------------------------------------------------------*/
49 
WebRtcIlbcfix_EncodeImpl(uint16_t * bytes,const int16_t * block,IlbcEncoder * iLBCenc_inst)50 void WebRtcIlbcfix_EncodeImpl(
51     uint16_t *bytes,     /* (o) encoded data bits iLBC */
52     const int16_t *block, /* (i) speech vector to encode */
53     IlbcEncoder *iLBCenc_inst /* (i/o) the general encoder
54                                      state */
55                           ){
56   size_t n, meml_gotten, Nfor;
57   size_t diff, start_pos;
58   size_t index;
59   size_t subcount, subframe;
60   size_t start_count, end_count;
61   int16_t *residual;
62   int32_t en1, en2;
63   int16_t scale, max;
64   int16_t *syntdenum;
65   int16_t *decresidual;
66   int16_t *reverseResidual;
67   int16_t *reverseDecresidual;
68   /* Stack based */
69   int16_t weightdenum[(LPC_FILTERORDER + 1)*NSUB_MAX];
70   int16_t dataVec[BLOCKL_MAX + LPC_FILTERORDER];
71   int16_t memVec[CB_MEML+CB_FILTERLEN];
72   int16_t bitsMemory[sizeof(iLBC_bits)/sizeof(int16_t)];
73   iLBC_bits *iLBCbits_inst = (iLBC_bits*)bitsMemory;
74 
75 
76 #ifdef SPLIT_10MS
77   int16_t *weightdenumbuf = iLBCenc_inst->weightdenumbuf;
78   int16_t last_bit;
79 #endif
80 
81   int16_t *data = &dataVec[LPC_FILTERORDER];
82   int16_t *mem = &memVec[CB_HALFFILTERLEN];
83 
84   /* Reuse som buffers to save stack memory */
85   residual = &iLBCenc_inst->lpc_buffer[LPC_LOOKBACK+BLOCKL_MAX-iLBCenc_inst->blockl];
86   syntdenum = mem;      /* syntdenum[(LPC_FILTERORDER + 1)*NSUB_MAX] and mem are used non overlapping in the code */
87   decresidual = residual;     /* Already encoded residual is overwritten by the decoded version */
88   reverseResidual = data;     /* data and reverseResidual are used non overlapping in the code */
89   reverseDecresidual = reverseResidual; /* Already encoded residual is overwritten by the decoded version */
90 
91 #ifdef SPLIT_10MS
92 
93   WebRtcSpl_MemSetW16 (  (int16_t *) iLBCbits_inst, 0,
94                          sizeof(iLBC_bits) / sizeof(int16_t)  );
95 
96   start_pos = iLBCenc_inst->start_pos;
97   diff = iLBCenc_inst->diff;
98 
99   if (iLBCenc_inst->section != 0){
100     WEBRTC_SPL_MEMCPY_W16 (weightdenum, weightdenumbuf,
101                            SCRATCH_ENCODE_DATAVEC - SCRATCH_ENCODE_WEIGHTDENUM);
102     /* Un-Packetize the frame into parameters */
103     last_bit = WebRtcIlbcfix_UnpackBits (iLBCenc_inst->bytes, iLBCbits_inst, iLBCenc_inst->mode);
104     if (last_bit)
105       return;
106     /* adjust index */
107     WebRtcIlbcfix_IndexConvDec (iLBCbits_inst->cb_index);
108 
109     if (iLBCenc_inst->section == 1){
110       /* Save first 80 samples of a 160/240 sample frame for 20/30msec */
111       WEBRTC_SPL_MEMCPY_W16 (iLBCenc_inst->past_samples, block, 80);
112     }
113     else{ // iLBCenc_inst->section == 2 AND mode = 30ms
114       /* Save second 80 samples of a 240 sample frame for 30msec */
115       WEBRTC_SPL_MEMCPY_W16 (iLBCenc_inst->past_samples + 80, block, 80);
116     }
117   }
118   else{ // iLBCenc_inst->section == 0
119     /* form a complete frame of 160/240 for 20msec/30msec mode */
120     WEBRTC_SPL_MEMCPY_W16 (data + (iLBCenc_inst->mode * 8) - 80, block, 80);
121     WEBRTC_SPL_MEMCPY_W16 (data, iLBCenc_inst->past_samples,
122                            (iLBCenc_inst->mode * 8) - 80);
123     iLBCenc_inst->Nfor_flag = 0;
124     iLBCenc_inst->Nback_flag = 0;
125 #else
126     /* copy input block to data*/
127     WEBRTC_SPL_MEMCPY_W16(data,block,iLBCenc_inst->blockl);
128 #endif
129 
130     /* high pass filtering of input signal and scale down the residual (*0.5) */
131     WebRtcIlbcfix_HpInput(data, (int16_t*)WebRtcIlbcfix_kHpInCoefs,
132                           iLBCenc_inst->hpimemy, iLBCenc_inst->hpimemx,
133                           iLBCenc_inst->blockl);
134 
135     /* LPC of hp filtered input data */
136     WebRtcIlbcfix_LpcEncode(syntdenum, weightdenum, iLBCbits_inst->lsf, data,
137                             iLBCenc_inst);
138 
139     /* Set up state */
140     WEBRTC_SPL_MEMCPY_W16(dataVec, iLBCenc_inst->anaMem, LPC_FILTERORDER);
141 
142     /* inverse filter to get residual */
143     for (n=0; n<iLBCenc_inst->nsub; n++ ) {
144       WebRtcSpl_FilterMAFastQ12(
145           &data[n*SUBL], &residual[n*SUBL],
146           &syntdenum[n*(LPC_FILTERORDER+1)],
147           LPC_FILTERORDER+1, SUBL);
148     }
149 
150     /* Copy the state for next frame */
151     WEBRTC_SPL_MEMCPY_W16(iLBCenc_inst->anaMem, &data[iLBCenc_inst->blockl-LPC_FILTERORDER], LPC_FILTERORDER);
152 
153     /* find state location */
154 
155     iLBCbits_inst->startIdx = WebRtcIlbcfix_FrameClassify(iLBCenc_inst,residual);
156 
157     /* check if state should be in first or last part of the
158        two subframes */
159 
160     index = (iLBCbits_inst->startIdx-1)*SUBL;
161     max=WebRtcSpl_MaxAbsValueW16(&residual[index], 2*SUBL);
162     scale = WebRtcSpl_GetSizeInBits((uint32_t)(max * max));
163 
164     /* Scale to maximum 25 bits so that the MAC won't cause overflow */
165     scale = scale - 25;
166     if(scale < 0) {
167       scale = 0;
168     }
169 
170     diff = STATE_LEN - iLBCenc_inst->state_short_len;
171     en1=WebRtcSpl_DotProductWithScale(&residual[index], &residual[index],
172                                       iLBCenc_inst->state_short_len, scale);
173     index += diff;
174     en2=WebRtcSpl_DotProductWithScale(&residual[index], &residual[index],
175                                       iLBCenc_inst->state_short_len, scale);
176     if (en1 > en2) {
177       iLBCbits_inst->state_first = 1;
178       start_pos = (iLBCbits_inst->startIdx-1)*SUBL;
179     } else {
180       iLBCbits_inst->state_first = 0;
181       start_pos = (iLBCbits_inst->startIdx-1)*SUBL + diff;
182     }
183 
184     /* scalar quantization of state */
185 
186     WebRtcIlbcfix_StateSearch(iLBCenc_inst, iLBCbits_inst, &residual[start_pos],
187                               &syntdenum[(iLBCbits_inst->startIdx-1)*(LPC_FILTERORDER+1)],
188                               &weightdenum[(iLBCbits_inst->startIdx-1)*(LPC_FILTERORDER+1)]);
189 
190     WebRtcIlbcfix_StateConstruct(iLBCbits_inst->idxForMax, iLBCbits_inst->idxVec,
191                                  &syntdenum[(iLBCbits_inst->startIdx-1)*(LPC_FILTERORDER+1)],
192                                  &decresidual[start_pos], iLBCenc_inst->state_short_len
193                                  );
194 
195     /* predictive quantization in state */
196 
197     if (iLBCbits_inst->state_first) { /* put adaptive part in the end */
198 
199       /* setup memory */
200 
201       WebRtcSpl_MemSetW16(mem, 0, CB_MEML - iLBCenc_inst->state_short_len);
202       WEBRTC_SPL_MEMCPY_W16(mem+CB_MEML-iLBCenc_inst->state_short_len,
203                             decresidual+start_pos, iLBCenc_inst->state_short_len);
204 
205       /* encode subframes */
206 
207       WebRtcIlbcfix_CbSearch(iLBCenc_inst, iLBCbits_inst->cb_index, iLBCbits_inst->gain_index,
208                              &residual[start_pos+iLBCenc_inst->state_short_len],
209                              mem+CB_MEML-ST_MEM_L_TBL, ST_MEM_L_TBL, diff,
210                              &weightdenum[iLBCbits_inst->startIdx*(LPC_FILTERORDER+1)], 0);
211 
212       /* construct decoded vector */
213 
214       RTC_CHECK(WebRtcIlbcfix_CbConstruct(
215           &decresidual[start_pos + iLBCenc_inst->state_short_len],
216           iLBCbits_inst->cb_index, iLBCbits_inst->gain_index,
217           mem + CB_MEML - ST_MEM_L_TBL, ST_MEM_L_TBL, diff));
218 
219     }
220     else { /* put adaptive part in the beginning */
221 
222       /* create reversed vectors for prediction */
223 
224       WebRtcSpl_MemCpyReversedOrder(&reverseResidual[diff-1],
225                                     &residual[(iLBCbits_inst->startIdx+1)*SUBL-STATE_LEN], diff);
226 
227       /* setup memory */
228 
229       meml_gotten = iLBCenc_inst->state_short_len;
230       WebRtcSpl_MemCpyReversedOrder(&mem[CB_MEML-1], &decresidual[start_pos], meml_gotten);
231       WebRtcSpl_MemSetW16(mem, 0, CB_MEML - iLBCenc_inst->state_short_len);
232 
233       /* encode subframes */
234       WebRtcIlbcfix_CbSearch(iLBCenc_inst, iLBCbits_inst->cb_index, iLBCbits_inst->gain_index,
235                              reverseResidual, mem+CB_MEML-ST_MEM_L_TBL, ST_MEM_L_TBL, diff,
236                              &weightdenum[(iLBCbits_inst->startIdx-1)*(LPC_FILTERORDER+1)],
237                              0);
238 
239       /* construct decoded vector */
240       RTC_CHECK(WebRtcIlbcfix_CbConstruct(
241             reverseDecresidual, iLBCbits_inst->cb_index,
242             iLBCbits_inst->gain_index, mem + CB_MEML - ST_MEM_L_TBL,
243             ST_MEM_L_TBL, diff));
244 
245       /* get decoded residual from reversed vector */
246 
247       WebRtcSpl_MemCpyReversedOrder(&decresidual[start_pos-1], reverseDecresidual, diff);
248     }
249 
250 #ifdef SPLIT_10MS
251     iLBCenc_inst->start_pos = start_pos;
252     iLBCenc_inst->diff = diff;
253     iLBCenc_inst->section++;
254     /* adjust index */
255     WebRtcIlbcfix_IndexConvEnc (iLBCbits_inst->cb_index);
256     /* Packetize the parameters into the frame */
257     WebRtcIlbcfix_PackBits (iLBCenc_inst->bytes, iLBCbits_inst, iLBCenc_inst->mode);
258     WEBRTC_SPL_MEMCPY_W16 (weightdenumbuf, weightdenum,
259                            SCRATCH_ENCODE_DATAVEC - SCRATCH_ENCODE_WEIGHTDENUM);
260     return;
261   }
262 #endif
263 
264   /* forward prediction of subframes */
265 
266   Nfor = iLBCenc_inst->nsub-iLBCbits_inst->startIdx-1;
267 
268   /* counter for predicted subframes */
269 #ifdef SPLIT_10MS
270   if (iLBCenc_inst->mode == 20)
271   {
272     subcount = 1;
273   }
274   if (iLBCenc_inst->mode == 30)
275   {
276     if (iLBCenc_inst->section == 1)
277     {
278       subcount = 1;
279     }
280     if (iLBCenc_inst->section == 2)
281     {
282       subcount = 3;
283     }
284   }
285 #else
286   subcount=1;
287 #endif
288 
289   if( Nfor > 0 ){
290 
291     /* setup memory */
292 
293     WebRtcSpl_MemSetW16(mem, 0, CB_MEML-STATE_LEN);
294     WEBRTC_SPL_MEMCPY_W16(mem+CB_MEML-STATE_LEN,
295                           decresidual+(iLBCbits_inst->startIdx-1)*SUBL, STATE_LEN);
296 
297 #ifdef SPLIT_10MS
298     if (iLBCenc_inst->Nfor_flag > 0)
299     {
300       for (subframe = 0; subframe < WEBRTC_SPL_MIN (Nfor, 2); subframe++)
301       {
302         /* update memory */
303         WEBRTC_SPL_MEMCPY_W16 (mem, mem + SUBL, (CB_MEML - SUBL));
304         WEBRTC_SPL_MEMCPY_W16 (mem + CB_MEML - SUBL,
305                                &decresidual[(iLBCbits_inst->startIdx + 1 +
306                                              subframe) * SUBL], SUBL);
307       }
308     }
309 
310     iLBCenc_inst->Nfor_flag++;
311 
312     if (iLBCenc_inst->mode == 20)
313     {
314       start_count = 0;
315       end_count = Nfor;
316     }
317     if (iLBCenc_inst->mode == 30)
318     {
319       if (iLBCenc_inst->section == 1)
320       {
321         start_count = 0;
322         end_count = WEBRTC_SPL_MIN (Nfor, (size_t)2);
323       }
324       if (iLBCenc_inst->section == 2)
325       {
326         start_count = WEBRTC_SPL_MIN (Nfor, (size_t)2);
327         end_count = Nfor;
328       }
329     }
330 #else
331     start_count = 0;
332     end_count = Nfor;
333 #endif
334 
335     /* loop over subframes to encode */
336 
337     for (subframe = start_count; subframe < end_count; subframe++){
338 
339       /* encode subframe */
340 
341       WebRtcIlbcfix_CbSearch(iLBCenc_inst, iLBCbits_inst->cb_index+subcount*CB_NSTAGES,
342                              iLBCbits_inst->gain_index+subcount*CB_NSTAGES,
343                              &residual[(iLBCbits_inst->startIdx+1+subframe)*SUBL],
344                              mem, MEM_LF_TBL, SUBL,
345                              &weightdenum[(iLBCbits_inst->startIdx+1+subframe)*(LPC_FILTERORDER+1)],
346                              subcount);
347 
348       /* construct decoded vector */
349       RTC_CHECK(WebRtcIlbcfix_CbConstruct(
350             &decresidual[(iLBCbits_inst->startIdx + 1 + subframe) * SUBL],
351             iLBCbits_inst->cb_index + subcount * CB_NSTAGES,
352             iLBCbits_inst->gain_index + subcount * CB_NSTAGES, mem, MEM_LF_TBL,
353             SUBL));
354 
355       /* update memory */
356 
357       memmove(mem, mem + SUBL, (CB_MEML - SUBL) * sizeof(*mem));
358       WEBRTC_SPL_MEMCPY_W16(mem+CB_MEML-SUBL,
359                             &decresidual[(iLBCbits_inst->startIdx+1+subframe)*SUBL], SUBL);
360 
361       subcount++;
362     }
363   }
364 
365 #ifdef SPLIT_10MS
366   if ((iLBCenc_inst->section == 1) &&
367       (iLBCenc_inst->mode == 30) && (Nfor > 0) && (end_count == 2))
368   {
369     iLBCenc_inst->section++;
370     /* adjust index */
371     WebRtcIlbcfix_IndexConvEnc (iLBCbits_inst->cb_index);
372     /* Packetize the parameters into the frame */
373     WebRtcIlbcfix_PackBits (iLBCenc_inst->bytes, iLBCbits_inst, iLBCenc_inst->mode);
374     WEBRTC_SPL_MEMCPY_W16 (weightdenumbuf, weightdenum,
375                            SCRATCH_ENCODE_DATAVEC - SCRATCH_ENCODE_WEIGHTDENUM);
376     return;
377   }
378 #endif
379 
380   /* backward prediction of subframes */
381 
382   if (iLBCbits_inst->startIdx > 1) {
383 
384     /* create reverse order vectors
385        (The decresidual does not need to be copied since it is
386        contained in the same vector as the residual)
387     */
388 
389     size_t Nback = iLBCbits_inst->startIdx - 1;
390     WebRtcSpl_MemCpyReversedOrder(&reverseResidual[Nback*SUBL-1], residual, Nback*SUBL);
391 
392     /* setup memory */
393 
394     meml_gotten = SUBL*(iLBCenc_inst->nsub+1-iLBCbits_inst->startIdx);
395     if( meml_gotten > CB_MEML ) {
396       meml_gotten=CB_MEML;
397     }
398 
399     WebRtcSpl_MemCpyReversedOrder(&mem[CB_MEML-1], &decresidual[Nback*SUBL], meml_gotten);
400     WebRtcSpl_MemSetW16(mem, 0, CB_MEML - meml_gotten);
401 
402 #ifdef SPLIT_10MS
403     if (iLBCenc_inst->Nback_flag > 0)
404     {
405       for (subframe = 0; subframe < WEBRTC_SPL_MAX (2 - Nfor, 0); subframe++)
406       {
407         /* update memory */
408         WEBRTC_SPL_MEMCPY_W16 (mem, mem + SUBL, (CB_MEML - SUBL));
409         WEBRTC_SPL_MEMCPY_W16 (mem + CB_MEML - SUBL,
410                                &reverseDecresidual[subframe * SUBL], SUBL);
411       }
412     }
413 
414     iLBCenc_inst->Nback_flag++;
415 
416 
417     if (iLBCenc_inst->mode == 20)
418     {
419       start_count = 0;
420       end_count = Nback;
421     }
422     if (iLBCenc_inst->mode == 30)
423     {
424       if (iLBCenc_inst->section == 1)
425       {
426         start_count = 0;
427         end_count = (Nfor >= 2) ? 0 : (2 - NFor);
428       }
429       if (iLBCenc_inst->section == 2)
430       {
431         start_count = (Nfor >= 2) ? 0 : (2 - NFor);
432         end_count = Nback;
433       }
434     }
435 #else
436     start_count = 0;
437     end_count = Nback;
438 #endif
439 
440     /* loop over subframes to encode */
441 
442     for (subframe = start_count; subframe < end_count; subframe++){
443 
444       /* encode subframe */
445 
446       WebRtcIlbcfix_CbSearch(iLBCenc_inst, iLBCbits_inst->cb_index+subcount*CB_NSTAGES,
447                              iLBCbits_inst->gain_index+subcount*CB_NSTAGES, &reverseResidual[subframe*SUBL],
448                              mem, MEM_LF_TBL, SUBL,
449                              &weightdenum[(iLBCbits_inst->startIdx-2-subframe)*(LPC_FILTERORDER+1)],
450                              subcount);
451 
452       /* construct decoded vector */
453       RTC_CHECK(WebRtcIlbcfix_CbConstruct(
454             &reverseDecresidual[subframe * SUBL],
455             iLBCbits_inst->cb_index + subcount * CB_NSTAGES,
456             iLBCbits_inst->gain_index + subcount * CB_NSTAGES, mem, MEM_LF_TBL,
457             SUBL));
458 
459       /* update memory */
460       memmove(mem, mem + SUBL, (CB_MEML - SUBL) * sizeof(*mem));
461       WEBRTC_SPL_MEMCPY_W16(mem+CB_MEML-SUBL,
462                             &reverseDecresidual[subframe*SUBL], SUBL);
463 
464       subcount++;
465 
466     }
467 
468     /* get decoded residual from reversed vector */
469 
470     WebRtcSpl_MemCpyReversedOrder(&decresidual[SUBL*Nback-1], reverseDecresidual, SUBL*Nback);
471   }
472   /* end encoding part */
473 
474   /* adjust index */
475 
476   WebRtcIlbcfix_IndexConvEnc(iLBCbits_inst->cb_index);
477 
478   /* Packetize the parameters into the frame */
479 
480 #ifdef SPLIT_10MS
481   if( (iLBCenc_inst->mode==30) && (iLBCenc_inst->section==1) ){
482     WebRtcIlbcfix_PackBits(iLBCenc_inst->bytes, iLBCbits_inst, iLBCenc_inst->mode);
483   }
484   else{
485     WebRtcIlbcfix_PackBits(bytes, iLBCbits_inst, iLBCenc_inst->mode);
486   }
487 #else
488   WebRtcIlbcfix_PackBits(bytes, iLBCbits_inst, iLBCenc_inst->mode);
489 #endif
490 
491 #ifndef WEBRTC_ARCH_BIG_ENDIAN
492   /* Swap bytes for LITTLE ENDIAN since the packbits()
493      function assumes BIG_ENDIAN machine */
494 #ifdef SPLIT_10MS
495   if (( (iLBCenc_inst->section == 1) && (iLBCenc_inst->mode == 20) ) ||
496       ( (iLBCenc_inst->section == 2) && (iLBCenc_inst->mode == 30) )){
497     WebRtcIlbcfix_SwapBytes(bytes, iLBCenc_inst->no_of_words, bytes);
498   }
499 #else
500   WebRtcIlbcfix_SwapBytes(bytes, iLBCenc_inst->no_of_words, bytes);
501 #endif
502 #endif
503 
504 #ifdef SPLIT_10MS
505   if (subcount == (iLBCenc_inst->nsub - 1))
506   {
507     iLBCenc_inst->section = 0;
508   }
509   else
510   {
511     iLBCenc_inst->section++;
512     WEBRTC_SPL_MEMCPY_W16 (weightdenumbuf, weightdenum,
513                            SCRATCH_ENCODE_DATAVEC - SCRATCH_ENCODE_WEIGHTDENUM);
514   }
515 #endif
516 
517 }
518