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