Home | History | Annotate | Download | only in ilbc
      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 
     45 void WebRtcIlbcfix_EncodeImpl(
     46     uint16_t *bytes,     /* (o) encoded data bits iLBC */
     47     const int16_t *block, /* (i) speech vector to encode */
     48     iLBC_Enc_Inst_t *iLBCenc_inst /* (i/o) the general encoder
     49                                      state */
     50                           ){
     51   int n, meml_gotten, Nfor, Nback;
     52   int16_t diff, start_pos;
     53   int index;
     54   int subcount, subframe;
     55   int16_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                          (int16_t) (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(WEBRTC_SPL_MUL_16_16(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, (int16_t)(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, (int16_t)(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, 2);
    321       }
    322       if (iLBCenc_inst->section == 2)
    323       {
    324         start_count = WEBRTC_SPL_MIN (Nfor, 2);
    325         end_count = Nfor;
    326       }
    327     }
    328 #else
    329     start_count = 0;
    330     end_count = (int16_t)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                              (int16_t)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   Nback = iLBCbits_inst->startIdx-1;
    383 
    384   if( Nback > 0 ){
    385 
    386     /* create reverse order vectors
    387        (The decresidual does not need to be copied since it is
    388        contained in the same vector as the residual)
    389     */
    390 
    391     WebRtcSpl_MemCpyReversedOrder(&reverseResidual[Nback*SUBL-1], residual, Nback*SUBL);
    392 
    393     /* setup memory */
    394 
    395     meml_gotten = SUBL*(iLBCenc_inst->nsub+1-iLBCbits_inst->startIdx);
    396     if( meml_gotten > CB_MEML ) {
    397       meml_gotten=CB_MEML;
    398     }
    399 
    400     WebRtcSpl_MemCpyReversedOrder(&mem[CB_MEML-1], &decresidual[Nback*SUBL], meml_gotten);
    401     WebRtcSpl_MemSetW16(mem, 0, (int16_t)(CB_MEML-meml_gotten));
    402 
    403 #ifdef SPLIT_10MS
    404     if (iLBCenc_inst->Nback_flag > 0)
    405     {
    406       for (subframe = 0; subframe < WEBRTC_SPL_MAX (2 - Nfor, 0); subframe++)
    407       {
    408         /* update memory */
    409         WEBRTC_SPL_MEMCPY_W16 (mem, mem + SUBL, (CB_MEML - SUBL));
    410         WEBRTC_SPL_MEMCPY_W16 (mem + CB_MEML - SUBL,
    411                                &reverseDecresidual[subframe * SUBL], SUBL);
    412       }
    413     }
    414 
    415     iLBCenc_inst->Nback_flag++;
    416 
    417 
    418     if (iLBCenc_inst->mode == 20)
    419     {
    420       start_count = 0;
    421       end_count = Nback;
    422     }
    423     if (iLBCenc_inst->mode == 30)
    424     {
    425       if (iLBCenc_inst->section == 1)
    426       {
    427         start_count = 0;
    428         end_count = WEBRTC_SPL_MAX (2 - Nfor, 0);
    429       }
    430       if (iLBCenc_inst->section == 2)
    431       {
    432         start_count = WEBRTC_SPL_MAX (2 - Nfor, 0);
    433         end_count = Nback;
    434       }
    435     }
    436 #else
    437     start_count = 0;
    438     end_count = (int16_t)Nback;
    439 #endif
    440 
    441     /* loop over subframes to encode */
    442 
    443     for (subframe = start_count; subframe < end_count; subframe++){
    444 
    445       /* encode subframe */
    446 
    447       WebRtcIlbcfix_CbSearch(iLBCenc_inst, iLBCbits_inst->cb_index+subcount*CB_NSTAGES,
    448                              iLBCbits_inst->gain_index+subcount*CB_NSTAGES, &reverseResidual[subframe*SUBL],
    449                              mem, MEM_LF_TBL, SUBL,
    450                              &weightdenum[(iLBCbits_inst->startIdx-2-subframe)*(LPC_FILTERORDER+1)],
    451                              (int16_t)subcount);
    452 
    453       /* construct decoded vector */
    454 
    455       WebRtcIlbcfix_CbConstruct(&reverseDecresidual[subframe*SUBL],
    456                                 iLBCbits_inst->cb_index+subcount*CB_NSTAGES,
    457                                 iLBCbits_inst->gain_index+subcount*CB_NSTAGES,
    458                                 mem, MEM_LF_TBL, SUBL
    459                                 );
    460 
    461       /* update memory */
    462       memmove(mem, mem + SUBL, (CB_MEML - SUBL) * sizeof(*mem));
    463       WEBRTC_SPL_MEMCPY_W16(mem+CB_MEML-SUBL,
    464                             &reverseDecresidual[subframe*SUBL], SUBL);
    465 
    466       subcount++;
    467 
    468     }
    469 
    470     /* get decoded residual from reversed vector */
    471 
    472     WebRtcSpl_MemCpyReversedOrder(&decresidual[SUBL*Nback-1], reverseDecresidual, SUBL*Nback);
    473   }
    474   /* end encoding part */
    475 
    476   /* adjust index */
    477 
    478   WebRtcIlbcfix_IndexConvEnc(iLBCbits_inst->cb_index);
    479 
    480   /* Packetize the parameters into the frame */
    481 
    482 #ifdef SPLIT_10MS
    483   if( (iLBCenc_inst->mode==30) && (iLBCenc_inst->section==1) ){
    484     WebRtcIlbcfix_PackBits(iLBCenc_inst->bytes, iLBCbits_inst, iLBCenc_inst->mode);
    485   }
    486   else{
    487     WebRtcIlbcfix_PackBits(bytes, iLBCbits_inst, iLBCenc_inst->mode);
    488   }
    489 #else
    490   WebRtcIlbcfix_PackBits(bytes, iLBCbits_inst, iLBCenc_inst->mode);
    491 #endif
    492 
    493 #ifndef WEBRTC_ARCH_BIG_ENDIAN
    494   /* Swap bytes for LITTLE ENDIAN since the packbits()
    495      function assumes BIG_ENDIAN machine */
    496 #ifdef SPLIT_10MS
    497   if (( (iLBCenc_inst->section == 1) && (iLBCenc_inst->mode == 20) ) ||
    498       ( (iLBCenc_inst->section == 2) && (iLBCenc_inst->mode == 30) )){
    499     WebRtcIlbcfix_SwapBytes(bytes, iLBCenc_inst->no_of_words, bytes);
    500   }
    501 #else
    502   WebRtcIlbcfix_SwapBytes(bytes, iLBCenc_inst->no_of_words, bytes);
    503 #endif
    504 #endif
    505 
    506 #ifdef SPLIT_10MS
    507   if (subcount == (iLBCenc_inst->nsub - 1))
    508   {
    509     iLBCenc_inst->section = 0;
    510   }
    511   else
    512   {
    513     iLBCenc_inst->section++;
    514     WEBRTC_SPL_MEMCPY_W16 (weightdenumbuf, weightdenum,
    515                            SCRATCH_ENCODE_DATAVEC - SCRATCH_ENCODE_WEIGHTDENUM);
    516   }
    517 #endif
    518 
    519 }
    520