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_routinshist.c
     13  *
     14  * This C file contains arithmetic encoding and decoding.
     15  *
     16  */
     17 
     18 #include "arith_routins.h"
     19 
     20 
     21 /****************************************************************************
     22  * WebRtcIsacfix_EncHistMulti(...)
     23  *
     24  * Encode the histogram interval
     25  *
     26  * Input:
     27  *      - streamData        : in-/output struct containing bitstream
     28  *      - data              : data vector
     29  *      - cdf               : array of cdf arrays
     30  *      - lenData           : data vector length
     31  *
     32  * Return value             : 0 if ok
     33  *                            <0 if error detected
     34  */
     35 int WebRtcIsacfix_EncHistMulti(Bitstr_enc *streamData,
     36                                const int16_t *data,
     37                                const uint16_t **cdf,
     38                                const int16_t lenData)
     39 {
     40   uint32_t W_lower;
     41   uint32_t W_upper;
     42   uint32_t W_upper_LSB;
     43   uint32_t W_upper_MSB;
     44   uint16_t *streamPtr;
     45   uint16_t negCarry;
     46   uint16_t *maxStreamPtr;
     47   uint16_t *streamPtrCarry;
     48   uint32_t cdfLo;
     49   uint32_t cdfHi;
     50   int k;
     51 
     52 
     53   /* point to beginning of stream buffer
     54    * and set maximum streamPtr value */
     55   streamPtr = streamData->stream + streamData->stream_index;
     56   maxStreamPtr = streamData->stream + STREAM_MAXW16_60MS - 1;
     57 
     58   W_upper = streamData->W_upper;
     59 
     60   for (k = lenData; k > 0; k--)
     61   {
     62     /* fetch cdf_lower and cdf_upper from cdf tables */
     63     cdfLo = (uint32_t) *(*cdf + (uint32_t)*data);
     64     cdfHi = (uint32_t) *(*cdf++ + (uint32_t)*data++ + 1);
     65 
     66     /* update interval */
     67     W_upper_LSB = W_upper & 0x0000FFFF;
     68     W_upper_MSB = WEBRTC_SPL_RSHIFT_W32(W_upper, 16);
     69     W_lower = WEBRTC_SPL_UMUL(W_upper_MSB, cdfLo);
     70     W_lower += ((W_upper_LSB * cdfLo) >> 16);
     71     W_upper = WEBRTC_SPL_UMUL(W_upper_MSB, cdfHi);
     72     W_upper += ((W_upper_LSB * cdfHi) >> 16);
     73 
     74     /* shift interval such that it begins at zero */
     75     W_upper -= ++W_lower;
     76 
     77     /* add integer to bitstream */
     78     streamData->streamval += W_lower;
     79 
     80     /* handle carry */
     81     if (streamData->streamval < W_lower)
     82     {
     83       /* propagate carry */
     84       streamPtrCarry = streamPtr;
     85       if (streamData->full == 0) {
     86         negCarry = *streamPtrCarry;
     87         negCarry += 0x0100;
     88         *streamPtrCarry = negCarry;
     89         while (!(negCarry))
     90         {
     91           negCarry = *--streamPtrCarry;
     92           negCarry++;
     93           *streamPtrCarry = negCarry;
     94         }
     95       } else {
     96         while ( !(++(*--streamPtrCarry)) );
     97       }
     98     }
     99 
    100     /* renormalize interval, store most significant byte of streamval and update streamval
    101      * W_upper < 2^24 */
    102     while ( !(W_upper & 0xFF000000) )
    103     {
    104       W_upper = WEBRTC_SPL_LSHIFT_W32(W_upper, 8);
    105       if (streamData->full == 0) {
    106         *streamPtr++ += (uint16_t) WEBRTC_SPL_RSHIFT_W32(streamData->streamval, 24);
    107         streamData->full = 1;
    108       } else {
    109         *streamPtr = (uint16_t) WEBRTC_SPL_LSHIFT_W32(
    110             WEBRTC_SPL_RSHIFT_W32(streamData->streamval, 24), 8);
    111         streamData->full = 0;
    112       }
    113 
    114       if( streamPtr > maxStreamPtr ) {
    115         return -ISAC_DISALLOWED_BITSTREAM_LENGTH;
    116       }
    117       streamData->streamval = WEBRTC_SPL_LSHIFT_W32(streamData->streamval, 8);
    118     }
    119   }
    120 
    121   /* calculate new stream_index */
    122   streamData->stream_index = streamPtr - streamData->stream;
    123   streamData->W_upper = W_upper;
    124 
    125   return 0;
    126 }
    127 
    128 
    129 /****************************************************************************
    130  * WebRtcIsacfix_DecHistBisectMulti(...)
    131  *
    132  * Function to decode more symbols from the arithmetic bytestream, using
    133  * method of bisection cdf tables should be of size 2^k-1 (which corresponds
    134  * to an alphabet size of 2^k-2)
    135  *
    136  * Input:
    137  *      - streamData        : in-/output struct containing bitstream
    138  *      - cdf               : array of cdf arrays
    139  *      - cdfSize           : array of cdf table sizes+1 (power of two: 2^k)
    140  *      - lenData           : data vector length
    141  *
    142  * Output:
    143  *      - data              : data vector
    144  *
    145  * Return value             : number of bytes in the stream
    146  *                            <0 if error detected
    147  */
    148 int16_t WebRtcIsacfix_DecHistBisectMulti(int16_t *data,
    149                                          Bitstr_dec *streamData,
    150                                          const uint16_t **cdf,
    151                                          const uint16_t *cdfSize,
    152                                          const int16_t lenData)
    153 {
    154   uint32_t    W_lower = 0;
    155   uint32_t    W_upper;
    156   uint32_t    W_tmp;
    157   uint32_t    W_upper_LSB;
    158   uint32_t    W_upper_MSB;
    159   uint32_t    streamval;
    160   const uint16_t *streamPtr;
    161   const uint16_t *cdfPtr;
    162   int16_t     sizeTmp;
    163   int             k;
    164 
    165 
    166   streamPtr = streamData->stream + streamData->stream_index;
    167   W_upper = streamData->W_upper;
    168 
    169   /* Error check: should not be possible in normal operation */
    170   if (W_upper == 0) {
    171     return -2;
    172   }
    173 
    174   /* first time decoder is called for this stream */
    175   if (streamData->stream_index == 0)
    176   {
    177     /* read first word from bytestream */
    178     streamval = WEBRTC_SPL_LSHIFT_W32((uint32_t)*streamPtr++, 16);
    179     streamval |= *streamPtr++;
    180   } else {
    181     streamval = streamData->streamval;
    182   }
    183 
    184   for (k = lenData; k > 0; k--)
    185   {
    186     /* find the integer *data for which streamval lies in [W_lower+1, W_upper] */
    187     W_upper_LSB = W_upper & 0x0000FFFF;
    188     W_upper_MSB = WEBRTC_SPL_RSHIFT_W32(W_upper, 16);
    189 
    190     /* start halfway the cdf range */
    191     sizeTmp = WEBRTC_SPL_RSHIFT_W16(*cdfSize++, 1);
    192     cdfPtr = *cdf + (sizeTmp - 1);
    193 
    194     /* method of bisection */
    195     for ( ;; )
    196     {
    197       W_tmp = WEBRTC_SPL_UMUL_32_16(W_upper_MSB, *cdfPtr);
    198       W_tmp += (W_upper_LSB * (*cdfPtr)) >> 16;
    199       sizeTmp = WEBRTC_SPL_RSHIFT_W16(sizeTmp, 1);
    200       if (sizeTmp == 0) {
    201         break;
    202       }
    203 
    204       if (streamval > W_tmp)
    205       {
    206         W_lower = W_tmp;
    207         cdfPtr += sizeTmp;
    208       } else {
    209         W_upper = W_tmp;
    210         cdfPtr -= sizeTmp;
    211       }
    212     }
    213     if (streamval > W_tmp)
    214     {
    215       W_lower = W_tmp;
    216       *data++ = cdfPtr - *cdf++;
    217     } else {
    218       W_upper = W_tmp;
    219       *data++ = cdfPtr - *cdf++ - 1;
    220     }
    221 
    222     /* shift interval to start at zero */
    223     W_upper -= ++W_lower;
    224 
    225     /* add integer to bitstream */
    226     streamval -= W_lower;
    227 
    228     /* renormalize interval and update streamval */
    229     /* W_upper < 2^24 */
    230     while ( !(W_upper & 0xFF000000) )
    231     {
    232       /* read next byte from stream */
    233       if (streamData->full == 0) {
    234         streamval = WEBRTC_SPL_LSHIFT_W32(streamval, 8) |
    235             (*streamPtr++ & 0x00FF);
    236         streamData->full = 1;
    237       } else {
    238         streamval = WEBRTC_SPL_LSHIFT_W32(streamval, 8) |
    239             WEBRTC_SPL_RSHIFT_W16(*streamPtr, 8);
    240         streamData->full = 0;
    241       }
    242       W_upper = WEBRTC_SPL_LSHIFT_W32(W_upper, 8);
    243     }
    244 
    245 
    246     /* Error check: should not be possible in normal operation */
    247     if (W_upper == 0) {
    248       return -2;
    249     }
    250 
    251   }
    252 
    253   streamData->stream_index = streamPtr - streamData->stream;
    254   streamData->W_upper = W_upper;
    255   streamData->streamval = streamval;
    256 
    257   if ( W_upper > 0x01FFFFFF ) {
    258     return (streamData->stream_index*2 - 3 + !streamData->full);
    259   } else {
    260     return (streamData->stream_index*2 - 2 + !streamData->full);
    261   }
    262 }
    263 
    264 
    265 /****************************************************************************
    266  * WebRtcIsacfix_DecHistOneStepMulti(...)
    267  *
    268  * Function to decode more symbols from the arithmetic bytestream, taking
    269  * single step up or down at a time.
    270  * cdf tables can be of arbitrary size, but large tables may take a lot of
    271  * iterations.
    272  *
    273  * Input:
    274  *      - streamData        : in-/output struct containing bitstream
    275  *      - cdf               : array of cdf arrays
    276  *      - initIndex         : vector of initial cdf table search entries
    277  *      - lenData           : data vector length
    278  *
    279  * Output:
    280  *      - data              : data vector
    281  *
    282  * Return value             : number of bytes in original stream
    283  *                            <0 if error detected
    284  */
    285 int16_t WebRtcIsacfix_DecHistOneStepMulti(int16_t *data,
    286                                           Bitstr_dec *streamData,
    287                                           const uint16_t **cdf,
    288                                           const uint16_t *initIndex,
    289                                           const int16_t lenData)
    290 {
    291   uint32_t    W_lower;
    292   uint32_t    W_upper;
    293   uint32_t    W_tmp;
    294   uint32_t    W_upper_LSB;
    295   uint32_t    W_upper_MSB;
    296   uint32_t    streamval;
    297   const uint16_t *streamPtr;
    298   const uint16_t *cdfPtr;
    299   int             k;
    300 
    301 
    302   streamPtr = streamData->stream + streamData->stream_index;
    303   W_upper = streamData->W_upper;
    304   /* Error check: Should not be possible in normal operation */
    305   if (W_upper == 0) {
    306     return -2;
    307   }
    308 
    309   /* Check if it is the first time decoder is called for this stream */
    310   if (streamData->stream_index == 0)
    311   {
    312     /* read first word from bytestream */
    313     streamval = WEBRTC_SPL_LSHIFT_U32(*streamPtr++, 16);
    314     streamval |= *streamPtr++;
    315   } else {
    316     streamval = streamData->streamval;
    317   }
    318 
    319   for (k = lenData; k > 0; k--)
    320   {
    321     /* find the integer *data for which streamval lies in [W_lower+1, W_upper] */
    322     W_upper_LSB = W_upper & 0x0000FFFF;
    323     W_upper_MSB = WEBRTC_SPL_RSHIFT_U32(W_upper, 16);
    324 
    325     /* start at the specified table entry */
    326     cdfPtr = *cdf + (*initIndex++);
    327     W_tmp = WEBRTC_SPL_UMUL_32_16(W_upper_MSB, *cdfPtr);
    328     W_tmp += (W_upper_LSB * (*cdfPtr)) >> 16;
    329 
    330     if (streamval > W_tmp)
    331     {
    332       for ( ;; )
    333       {
    334         W_lower = W_tmp;
    335 
    336         /* range check */
    337         if (cdfPtr[0] == 65535) {
    338           return -3;
    339         }
    340 
    341         W_tmp = WEBRTC_SPL_UMUL_32_16(W_upper_MSB, *++cdfPtr);
    342         W_tmp += (W_upper_LSB * (*cdfPtr)) >> 16;
    343 
    344         if (streamval <= W_tmp) {
    345           break;
    346         }
    347       }
    348       W_upper = W_tmp;
    349       *data++ = cdfPtr - *cdf++ - 1;
    350     } else {
    351       for ( ;; )
    352       {
    353         W_upper = W_tmp;
    354         --cdfPtr;
    355 
    356         /* range check */
    357         if (cdfPtr < *cdf) {
    358           return -3;
    359         }
    360 
    361         W_tmp = WEBRTC_SPL_UMUL_32_16(W_upper_MSB, *cdfPtr);
    362         W_tmp += (W_upper_LSB * (*cdfPtr)) >> 16;
    363 
    364         if (streamval > W_tmp) {
    365           break;
    366         }
    367       }
    368       W_lower = W_tmp;
    369       *data++ = cdfPtr - *cdf++;
    370     }
    371 
    372     /* shift interval to start at zero */
    373     W_upper -= ++W_lower;
    374 
    375     /* add integer to bitstream */
    376     streamval -= W_lower;
    377 
    378     /* renormalize interval and update streamval */
    379     /* W_upper < 2^24 */
    380     while ( !(W_upper & 0xFF000000) )
    381     {
    382       /* read next byte from stream */
    383       if (streamData->full == 0) {
    384         streamval = WEBRTC_SPL_LSHIFT_W32(streamval, 8) | (*streamPtr++ & 0x00FF);
    385         streamData->full = 1;
    386       } else {
    387         streamval = WEBRTC_SPL_LSHIFT_W32(streamval, 8) | (*streamPtr >> 8);
    388         streamData->full = 0;
    389       }
    390       W_upper = WEBRTC_SPL_LSHIFT_W32(W_upper, 8);
    391     }
    392   }
    393 
    394   streamData->stream_index = streamPtr - streamData->stream;
    395   streamData->W_upper = W_upper;
    396   streamData->streamval = streamval;
    397 
    398   /* find number of bytes in original stream (determined by current interval width) */
    399   if ( W_upper > 0x01FFFFFF ) {
    400     return (streamData->stream_index*2 - 3 + !streamData->full);
    401   } else {
    402     return (streamData->stream_index*2 - 2 + !streamData->full);
    403   }
    404 }
    405