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