Home | History | Annotate | Download | only in source
      1 /*
      2  *  Copyright (c) 2011 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  * arith_routinslogist.c
     13  *
     14  * This C file contains arithmetic encode and decode logistic
     15  *
     16  */
     17 
     18 #include "arith_routins.h"
     19 
     20 
     21 /* Tables for piecewise linear cdf functions: y = k*x */
     22 
     23 /* x Points for function piecewise() in Q15 */
     24 static const WebRtc_Word32 kHistEdges[51] = {
     25   -327680, -314573, -301466, -288359, -275252, -262144, -249037, -235930, -222823, -209716,
     26   -196608, -183501, -170394, -157287, -144180, -131072, -117965, -104858,  -91751,  -78644,
     27   -65536,  -52429,  -39322,  -26215,  -13108,       0,   13107,   26214,   39321,   52428,
     28   65536,   78643,   91750,  104857,  117964,  131072,  144179,  157286,  170393,  183500,
     29   196608,  209715,  222822,  235929,  249036,  262144,  275251,  288358,  301465,  314572,
     30   327680
     31 };
     32 
     33 
     34 /* k Points for function piecewise() in Q0 */
     35 static const WebRtc_UWord16 kCdfSlope[51] = {
     36   5,    5,     5,     5,     5,     5,     5,     5,    5,    5,
     37   5,    5,    13,    23,    47,    87,   154,   315,  700, 1088,
     38   2471, 6064, 14221, 21463, 36634, 36924, 19750, 13270, 5806, 2312,
     39   1095,  660,   316,   145,    86,    41,    32,     5,    5,    5,
     40   5,    5,     5,     5,     5,     5,     5,     5,    5,    2,
     41   0
     42 };
     43 
     44 /* y Points for function piecewise() in Q0 */
     45 static const WebRtc_UWord16 kCdfLogistic[51] = {
     46   0,     2,     4,     6,     8,    10,    12,    14,    16,    18,
     47   20,    22,    24,    29,    38,    57,    92,   153,   279,   559,
     48   994,  1983,  4408, 10097, 18682, 33336, 48105, 56005, 61313, 63636,
     49   64560, 64998, 65262, 65389, 65447, 65481, 65497, 65510, 65512, 65514,
     50   65516, 65518, 65520, 65522, 65524, 65526, 65528, 65530, 65532, 65534,
     51   65535
     52 };
     53 
     54 
     55 /****************************************************************************
     56  * WebRtcIsacfix_Piecewise(...)
     57  *
     58  * Piecewise linear function
     59  *
     60  * Input:
     61  *      - xinQ15           : input value x in Q15
     62  *
     63  * Return value            : korresponding y-value in Q0
     64  */
     65 
     66 
     67 static __inline WebRtc_UWord16 WebRtcIsacfix_Piecewise(WebRtc_Word32 xinQ15) {
     68   WebRtc_Word32 ind;
     69   WebRtc_Word32 qtmp1;
     70   WebRtc_UWord16 qtmp2;
     71 
     72   /* Find index for x-value */
     73   qtmp1 = WEBRTC_SPL_SAT(kHistEdges[50],xinQ15,kHistEdges[0]);
     74   ind = WEBRTC_SPL_MUL(5, qtmp1 - kHistEdges[0]);
     75   ind =  WEBRTC_SPL_RSHIFT_W32(ind, 16);
     76 
     77   /* Calculate corresponding y-value ans return*/
     78   qtmp1 = qtmp1 - kHistEdges[ind];
     79   qtmp2 = (WebRtc_UWord16)WEBRTC_SPL_RSHIFT_U32(
     80       WEBRTC_SPL_UMUL_32_16(qtmp1,kCdfSlope[ind]), 15);
     81   return (kCdfLogistic[ind] + qtmp2);
     82 }
     83 
     84 /****************************************************************************
     85  * WebRtcIsacfix_EncLogisticMulti2(...)
     86  *
     87  * Arithmetic coding of spectrum.
     88  *
     89  * Input:
     90  *      - streamData        : in-/output struct containing bitstream
     91  *      - dataQ7            : data vector in Q7
     92  *      - envQ8             : side info vector defining the width of the pdf
     93  *                            in Q8
     94  *      - lenData           : data vector length
     95  *
     96  * Return value             :  0 if ok,
     97  *                            <0 otherwise.
     98  */
     99 int WebRtcIsacfix_EncLogisticMulti2(Bitstr_enc *streamData,
    100                                    WebRtc_Word16 *dataQ7,
    101                                    const WebRtc_UWord16 *envQ8,
    102                                    const WebRtc_Word16 lenData)
    103 {
    104   WebRtc_UWord32 W_lower;
    105   WebRtc_UWord32 W_upper;
    106   WebRtc_UWord16 W_upper_LSB;
    107   WebRtc_UWord16 W_upper_MSB;
    108   WebRtc_UWord16 *streamPtr;
    109   WebRtc_UWord16 *maxStreamPtr;
    110   WebRtc_UWord16 *streamPtrCarry;
    111   WebRtc_UWord16 negcarry;
    112   WebRtc_UWord32 cdfLo;
    113   WebRtc_UWord32 cdfHi;
    114   int k;
    115 
    116   /* point to beginning of stream buffer
    117    * and set maximum streamPtr value */
    118   streamPtr = streamData->stream + streamData->stream_index;
    119   maxStreamPtr = streamData->stream + STREAM_MAXW16_60MS - 1;
    120   W_upper = streamData->W_upper;
    121 
    122   for (k = 0; k < lenData; k++)
    123   {
    124     /* compute cdf_lower and cdf_upper by evaluating the
    125      * WebRtcIsacfix_Piecewise linear cdf */
    126     cdfLo = WebRtcIsacfix_Piecewise(WEBRTC_SPL_MUL_16_U16(*dataQ7 - 64, *envQ8));
    127     cdfHi = WebRtcIsacfix_Piecewise(WEBRTC_SPL_MUL_16_U16(*dataQ7 + 64, *envQ8));
    128 
    129     /* test and clip if probability gets too small */
    130     while ((cdfLo + 1) >= cdfHi) {
    131       /* clip */
    132       if (*dataQ7 > 0) {
    133         *dataQ7 -= 128;
    134         cdfHi = cdfLo;
    135         cdfLo = WebRtcIsacfix_Piecewise(
    136             WEBRTC_SPL_MUL_16_U16(*dataQ7 - 64, *envQ8));
    137       } else {
    138         *dataQ7 += 128;
    139         cdfLo = cdfHi;
    140         cdfHi = WebRtcIsacfix_Piecewise(
    141             WEBRTC_SPL_MUL_16_U16(*dataQ7 + 64, *envQ8));
    142       }
    143     }
    144 
    145     dataQ7++;
    146     /* increment only once per 4 iterations */
    147     envQ8 += (k & 1) & (k >> 1);
    148 
    149 
    150     /* update interval */
    151     W_upper_LSB = (WebRtc_UWord16)W_upper;
    152     W_upper_MSB = (WebRtc_UWord16)WEBRTC_SPL_RSHIFT_U32(W_upper, 16);
    153     W_lower = WEBRTC_SPL_UMUL_32_16(cdfLo, W_upper_MSB);
    154     W_lower += WEBRTC_SPL_UMUL_32_16_RSFT16(cdfLo, W_upper_LSB);
    155     W_upper = WEBRTC_SPL_UMUL_32_16(cdfHi, W_upper_MSB);
    156     W_upper += WEBRTC_SPL_UMUL_32_16_RSFT16(cdfHi, W_upper_LSB);
    157 
    158     /* shift interval such that it begins at zero */
    159     W_upper -= ++W_lower;
    160 
    161     /* add integer to bitstream */
    162     streamData->streamval += W_lower;
    163 
    164     /* handle carry */
    165     if (streamData->streamval < W_lower)
    166     {
    167       /* propagate carry */
    168       streamPtrCarry = streamPtr;
    169       if (streamData->full == 0) {
    170         negcarry = *streamPtrCarry;
    171         negcarry += 0x0100;
    172         *streamPtrCarry = negcarry;
    173         while (!(negcarry))
    174         {
    175           negcarry = *--streamPtrCarry;
    176           negcarry++;
    177           *streamPtrCarry = negcarry;
    178         }
    179       } else {
    180         while (!(++(*--streamPtrCarry)));
    181       }
    182     }
    183 
    184     /* renormalize interval, store most significant byte of streamval and update streamval
    185      * W_upper < 2^24 */
    186     while ( !(W_upper & 0xFF000000) )
    187     {
    188       W_upper = WEBRTC_SPL_LSHIFT_U32(W_upper, 8);
    189       if (streamData->full == 0) {
    190         *streamPtr++ += (WebRtc_UWord16) WEBRTC_SPL_RSHIFT_U32(
    191             streamData->streamval, 24);
    192         streamData->full = 1;
    193       } else {
    194         *streamPtr = (WebRtc_UWord16) WEBRTC_SPL_LSHIFT_U32(
    195             WEBRTC_SPL_RSHIFT_U32(streamData->streamval, 24), 8);
    196         streamData->full = 0;
    197       }
    198 
    199       if( streamPtr > maxStreamPtr )
    200         return -ISAC_DISALLOWED_BITSTREAM_LENGTH;
    201 
    202       streamData->streamval = WEBRTC_SPL_LSHIFT_U32(streamData->streamval, 8);
    203     }
    204   }
    205 
    206   /* calculate new stream_index */
    207   streamData->stream_index = streamPtr - streamData->stream;
    208   streamData->W_upper = W_upper;
    209 
    210   return 0;
    211 }
    212 
    213 
    214 /****************************************************************************
    215  * WebRtcIsacfix_DecLogisticMulti2(...)
    216  *
    217  * Arithmetic decoding of spectrum.
    218  *
    219  * Input:
    220  *      - streamData        : in-/output struct containing bitstream
    221  *      - envQ8             : side info vector defining the width of the pdf
    222  *                            in Q8
    223  *      - lenData           : data vector length
    224  *
    225  * Input/Output:
    226  *      - dataQ7            : input: dither vector, output: data vector
    227  *
    228  * Return value             : number of bytes in the stream so far
    229  *                            -1 if error detected
    230  */
    231 WebRtc_Word16 WebRtcIsacfix_DecLogisticMulti2(WebRtc_Word16 *dataQ7,
    232                                              Bitstr_dec *streamData,
    233                                              const WebRtc_Word32 *envQ8,
    234                                              const WebRtc_Word16 lenData)
    235 {
    236   WebRtc_UWord32    W_lower;
    237   WebRtc_UWord32    W_upper;
    238   WebRtc_UWord32    W_tmp;
    239   WebRtc_UWord16    W_upper_LSB;
    240   WebRtc_UWord16    W_upper_MSB;
    241   WebRtc_UWord32    streamVal;
    242   WebRtc_UWord16    cdfTmp;
    243   WebRtc_Word32     res;
    244   WebRtc_Word32     inSqrt;
    245   WebRtc_Word32     newRes;
    246   const WebRtc_UWord16 *streamPtr;
    247   WebRtc_Word16     candQ7;
    248   WebRtc_Word16     envCount;
    249   WebRtc_UWord16    tmpARSpecQ8 = 0;
    250   int             k, i;
    251 
    252 
    253   /* point to beginning of stream buffer */
    254   streamPtr = streamData->stream + streamData->stream_index;
    255   W_upper = streamData->W_upper;
    256 
    257   /* Check if it is first time decoder is called for this stream */
    258   if (streamData->stream_index == 0)
    259   {
    260     /* read first word from bytestream */
    261     streamVal = WEBRTC_SPL_LSHIFT_U32(*streamPtr++, 16);
    262     streamVal |= *streamPtr++;
    263 
    264   } else {
    265     streamVal = streamData->streamval;
    266   }
    267 
    268 
    269   res = WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)1,
    270                                WEBRTC_SPL_RSHIFT_W16(WebRtcSpl_GetSizeInBits(envQ8[0]), 1));
    271   envCount = 0;
    272 
    273   /* code assumes lenData%4 == 0 */
    274   for (k = 0; k < lenData; k += 4)
    275   {
    276     int k4;
    277 
    278     /* convert to magnitude spectrum, by doing square-roots (modified from SPLIB) */
    279     inSqrt = envQ8[envCount];
    280     i = 10;
    281 
    282     /* For safty reasons */
    283     if (inSqrt < 0)
    284       inSqrt=-inSqrt;
    285 
    286     newRes = WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_DIV(inSqrt, res) + res, 1);
    287     do
    288     {
    289       res = newRes;
    290       newRes = WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_DIV(inSqrt, res) + res, 1);
    291     } while (newRes != res && i-- > 0);
    292 
    293     tmpARSpecQ8 = (WebRtc_UWord16)newRes;
    294 
    295     for(k4 = 0; k4 < 4; k4++)
    296     {
    297       /* find the integer *data for which streamVal lies in [W_lower+1, W_upper] */
    298       W_upper_LSB = (WebRtc_UWord16) (W_upper & 0x0000FFFF);
    299       W_upper_MSB = (WebRtc_UWord16) WEBRTC_SPL_RSHIFT_U32(W_upper, 16);
    300 
    301       /* find first candidate by inverting the logistic cdf
    302        * Input dither value collected from io-stream */
    303       candQ7 = - *dataQ7 + 64;
    304       cdfTmp = WebRtcIsacfix_Piecewise(WEBRTC_SPL_MUL_16_U16(candQ7, tmpARSpecQ8));
    305 
    306       W_tmp = WEBRTC_SPL_UMUL_16_16(cdfTmp, W_upper_MSB);
    307       W_tmp += WEBRTC_SPL_UMUL_16_16_RSFT16(cdfTmp, W_upper_LSB);
    308 
    309       if (streamVal > W_tmp)
    310       {
    311         W_lower = W_tmp;
    312         candQ7 += 128;
    313         cdfTmp = WebRtcIsacfix_Piecewise(WEBRTC_SPL_MUL_16_U16(candQ7, tmpARSpecQ8));
    314 
    315         W_tmp = WEBRTC_SPL_UMUL_16_16(cdfTmp, W_upper_MSB);
    316         W_tmp += WEBRTC_SPL_UMUL_16_16_RSFT16(cdfTmp, W_upper_LSB);
    317 
    318         while (streamVal > W_tmp)
    319         {
    320           W_lower = W_tmp;
    321           candQ7 += 128;
    322           cdfTmp = WebRtcIsacfix_Piecewise(
    323               WEBRTC_SPL_MUL_16_U16(candQ7, tmpARSpecQ8));
    324 
    325           W_tmp = WEBRTC_SPL_UMUL_16_16(cdfTmp, W_upper_MSB);
    326           W_tmp += WEBRTC_SPL_UMUL_16_16_RSFT16(cdfTmp, W_upper_LSB);
    327 
    328           /* error check */
    329           if (W_lower == W_tmp) {
    330             return -1;
    331           }
    332         }
    333         W_upper = W_tmp;
    334 
    335         /* Output value put in dataQ7: another sample decoded */
    336         *dataQ7 = candQ7 - 64;
    337       }
    338       else
    339       {
    340         W_upper = W_tmp;
    341         candQ7 -= 128;
    342         cdfTmp = WebRtcIsacfix_Piecewise(WEBRTC_SPL_MUL_16_U16(candQ7, tmpARSpecQ8));
    343 
    344         W_tmp = WEBRTC_SPL_UMUL_16_16(cdfTmp, W_upper_MSB);
    345         W_tmp += WEBRTC_SPL_UMUL_16_16_RSFT16(cdfTmp, W_upper_LSB);
    346 
    347         while ( !(streamVal > W_tmp) )
    348         {
    349           W_upper = W_tmp;
    350           candQ7 -= 128;
    351           cdfTmp = WebRtcIsacfix_Piecewise(
    352               WEBRTC_SPL_MUL_16_U16(candQ7, tmpARSpecQ8));
    353 
    354           W_tmp = WEBRTC_SPL_UMUL_16_16(cdfTmp, W_upper_MSB);
    355           W_tmp += WEBRTC_SPL_UMUL_16_16_RSFT16(cdfTmp, W_upper_LSB);
    356 
    357           /* error check */
    358           if (W_upper == W_tmp){
    359             return -1;
    360           }
    361         }
    362         W_lower = W_tmp;
    363 
    364         /* Output value put in dataQ7: another sample decoded */
    365         *dataQ7 = candQ7 + 64;
    366       }
    367 
    368       dataQ7++;
    369 
    370       /* shift interval to start at zero */
    371       W_upper -= ++W_lower;
    372 
    373       /* add integer to bitstream */
    374       streamVal -= W_lower;
    375 
    376       /* renormalize interval and update streamVal
    377        * W_upper < 2^24 */
    378       while ( !(W_upper & 0xFF000000) )
    379       {
    380         /* read next byte from stream */
    381         if (streamData->full == 0) {
    382           streamVal = WEBRTC_SPL_LSHIFT_W32(streamVal, 8) | (*streamPtr++ & 0x00FF);
    383           streamData->full = 1;
    384         } else {
    385           streamVal = WEBRTC_SPL_LSHIFT_W32(streamVal, 8) |
    386               WEBRTC_SPL_RSHIFT_U16(*streamPtr, 8);
    387           streamData->full = 0;
    388         }
    389         W_upper = WEBRTC_SPL_LSHIFT_W32(W_upper, 8);
    390       }
    391     }
    392     envCount++;
    393   }
    394 
    395   streamData->stream_index = streamPtr - streamData->stream;
    396   streamData->W_upper = W_upper;
    397   streamData->streamval = streamVal;
    398 
    399   /* find number of bytes in original stream (determined by current interval width) */
    400   if ( W_upper > 0x01FFFFFF )
    401     return (streamData->stream_index*2 - 3 + !streamData->full);
    402   else
    403     return (streamData->stream_index*2 - 2 + !streamData->full);
    404 }
    405