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