arith_routines_hist.c revision f71785cd3b282ad7d584d746ba5b19833a11692b
1470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com/*
2470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
3470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *
4470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *  Use of this source code is governed by a BSD-style license
5470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *  that can be found in the LICENSE file in the root of the source
6470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *  tree. An additional intellectual property rights grant can be found
7470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *  in the file PATENTS.  All contributing project authors may
8470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *  be found in the AUTHORS file in the root of the source tree.
9470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com */
10470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
11470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com/*
12470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * arith_routinshist.c
13470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *
14470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * This C file contains arithmetic encoding and decoding.
15470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *
16470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com */
17470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
18470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#include "arith_routins.h"
19470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
20470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
21470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com/****************************************************************************
22470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * WebRtcIsacfix_EncHistMulti(...)
23470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *
24470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * Encode the histogram interval
25470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *
26470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * Input:
27470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *      - streamData        : in-/output struct containing bitstream
28470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *      - data              : data vector
29470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *      - cdf               : array of cdf arrays
30470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *      - lenData           : data vector length
31470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *
32470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * Return value             : 0 if ok
33470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *                            <0 if error detected
34470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com */
35470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint WebRtcIsacfix_EncHistMulti(Bitstr_enc *streamData,
360946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org                               const int16_t *data,
370946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org                               const uint16_t **cdf,
380946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org                               const int16_t lenData)
39470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
400946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  uint32_t W_lower;
410946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  uint32_t W_upper;
420946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  uint32_t W_upper_LSB;
430946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  uint32_t W_upper_MSB;
440946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  uint16_t *streamPtr;
450946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  uint16_t negCarry;
460946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  uint16_t *maxStreamPtr;
470946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  uint16_t *streamPtrCarry;
480946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  uint32_t cdfLo;
490946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  uint32_t cdfHi;
50470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  int k;
51470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
52470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
53470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* point to beginning of stream buffer
54470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com   * and set maximum streamPtr value */
55470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  streamPtr = streamData->stream + streamData->stream_index;
56470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  maxStreamPtr = streamData->stream + STREAM_MAXW16_60MS - 1;
57470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
58470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  W_upper = streamData->W_upper;
59470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
60470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  for (k = lenData; k > 0; k--)
61470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  {
62470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    /* fetch cdf_lower and cdf_upper from cdf tables */
630946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org    cdfLo = (uint32_t) *(*cdf + (uint32_t)*data);
640946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org    cdfHi = (uint32_t) *(*cdf++ + (uint32_t)*data++ + 1);
65470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
66470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    /* update interval */
67470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    W_upper_LSB = W_upper & 0x0000FFFF;
68470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    W_upper_MSB = WEBRTC_SPL_RSHIFT_W32(W_upper, 16);
69470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    W_lower = WEBRTC_SPL_UMUL(W_upper_MSB, cdfLo);
70a3b5673879284f16a2f9f56bc14429eec4f20a0cbjornv@webrtc.org    W_lower += ((W_upper_LSB * cdfLo) >> 16);
71470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    W_upper = WEBRTC_SPL_UMUL(W_upper_MSB, cdfHi);
72a3b5673879284f16a2f9f56bc14429eec4f20a0cbjornv@webrtc.org    W_upper += ((W_upper_LSB * cdfHi) >> 16);
73470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
74470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    /* shift interval such that it begins at zero */
75470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    W_upper -= ++W_lower;
76470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
77470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    /* add integer to bitstream */
78470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    streamData->streamval += W_lower;
79470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
80470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    /* handle carry */
81470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (streamData->streamval < W_lower)
82470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
83470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      /* propagate carry */
84470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      streamPtrCarry = streamPtr;
85470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      if (streamData->full == 0) {
86470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        negCarry = *streamPtrCarry;
87470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        negCarry += 0x0100;
88470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        *streamPtrCarry = negCarry;
89470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        while (!(negCarry))
90470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
91470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com          negCarry = *--streamPtrCarry;
92470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com          negCarry++;
93470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com          *streamPtrCarry = negCarry;
94470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
95470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      } else {
96470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        while ( !(++(*--streamPtrCarry)) );
97470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      }
98470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
99470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
100470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    /* renormalize interval, store most significant byte of streamval and update streamval
101470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com     * W_upper < 2^24 */
102470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    while ( !(W_upper & 0xFF000000) )
103470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
104470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      W_upper = WEBRTC_SPL_LSHIFT_W32(W_upper, 8);
105470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      if (streamData->full == 0) {
1060946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org        *streamPtr++ += (uint16_t) WEBRTC_SPL_RSHIFT_W32(streamData->streamval, 24);
107470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        streamData->full = 1;
108470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      } else {
1090946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org        *streamPtr = (uint16_t) WEBRTC_SPL_LSHIFT_W32(
110470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            WEBRTC_SPL_RSHIFT_W32(streamData->streamval, 24), 8);
111470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        streamData->full = 0;
112470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      }
113470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
114470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      if( streamPtr > maxStreamPtr ) {
115470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -ISAC_DISALLOWED_BITSTREAM_LENGTH;
116470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      }
117470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      streamData->streamval = WEBRTC_SPL_LSHIFT_W32(streamData->streamval, 8);
118470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
119470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
120470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
121470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* calculate new stream_index */
122470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  streamData->stream_index = streamPtr - streamData->stream;
123470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  streamData->W_upper = W_upper;
124470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
125470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  return 0;
126470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
127470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
128470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
129470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com/****************************************************************************
130470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * WebRtcIsacfix_DecHistBisectMulti(...)
131470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *
132470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * Function to decode more symbols from the arithmetic bytestream, using
133470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * method of bisection cdf tables should be of size 2^k-1 (which corresponds
134470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * to an alphabet size of 2^k-2)
135470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *
136470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * Input:
137470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *      - streamData        : in-/output struct containing bitstream
138470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *      - cdf               : array of cdf arrays
139470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *      - cdfSize           : array of cdf table sizes+1 (power of two: 2^k)
140470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *      - lenData           : data vector length
141470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *
142470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * Output:
143470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *      - data              : data vector
144470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *
145470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * Return value             : number of bytes in the stream
146470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *                            <0 if error detected
147470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com */
1480946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.orgint16_t WebRtcIsacfix_DecHistBisectMulti(int16_t *data,
1490946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org                                         Bitstr_dec *streamData,
1500946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org                                         const uint16_t **cdf,
1510946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org                                         const uint16_t *cdfSize,
1520946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org                                         const int16_t lenData)
153470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
1540946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  uint32_t    W_lower = 0;
1550946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  uint32_t    W_upper;
1560946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  uint32_t    W_tmp;
1570946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  uint32_t    W_upper_LSB;
1580946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  uint32_t    W_upper_MSB;
1590946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  uint32_t    streamval;
1600946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  const uint16_t *streamPtr;
1610946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  const uint16_t *cdfPtr;
1620946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int16_t     sizeTmp;
163470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  int             k;
164470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
165470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
166470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  streamPtr = streamData->stream + streamData->stream_index;
167470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  W_upper = streamData->W_upper;
168470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
169470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* Error check: should not be possible in normal operation */
170470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  if (W_upper == 0) {
171470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return -2;
172470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
173470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
174470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* first time decoder is called for this stream */
175470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  if (streamData->stream_index == 0)
176470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  {
177470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    /* read first word from bytestream */
1780946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org    streamval = WEBRTC_SPL_LSHIFT_W32((uint32_t)*streamPtr++, 16);
179470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    streamval |= *streamPtr++;
180470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  } else {
181470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    streamval = streamData->streamval;
182470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
183470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
184470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  for (k = lenData; k > 0; k--)
185470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  {
186470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    /* find the integer *data for which streamval lies in [W_lower+1, W_upper] */
187470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    W_upper_LSB = W_upper & 0x0000FFFF;
188470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    W_upper_MSB = WEBRTC_SPL_RSHIFT_W32(W_upper, 16);
189470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
190470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    /* start halfway the cdf range */
191f71785cd3b282ad7d584d746ba5b19833a11692bbjornv@webrtc.org    sizeTmp = *cdfSize++ / 2;
192470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    cdfPtr = *cdf + (sizeTmp - 1);
193470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
194470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    /* method of bisection */
195470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    for ( ;; )
196470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
197470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      W_tmp = WEBRTC_SPL_UMUL_32_16(W_upper_MSB, *cdfPtr);
1981e3ef4b999ada52fc4e421d1d06b73068e855413bjornv@webrtc.org      W_tmp += (W_upper_LSB * (*cdfPtr)) >> 16;
199f71785cd3b282ad7d584d746ba5b19833a11692bbjornv@webrtc.org      sizeTmp /= 2;
200470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      if (sizeTmp == 0) {
201470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        break;
202470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      }
203470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
204470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      if (streamval > W_tmp)
205470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      {
206470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        W_lower = W_tmp;
207470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        cdfPtr += sizeTmp;
208470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      } else {
209470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        W_upper = W_tmp;
210470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        cdfPtr -= sizeTmp;
211470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      }
212470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
213470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (streamval > W_tmp)
214470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
215470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      W_lower = W_tmp;
216470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      *data++ = cdfPtr - *cdf++;
217470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    } else {
218470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      W_upper = W_tmp;
219470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      *data++ = cdfPtr - *cdf++ - 1;
220470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
221470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
222470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    /* shift interval to start at zero */
223470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    W_upper -= ++W_lower;
224470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
225470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    /* add integer to bitstream */
226470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    streamval -= W_lower;
227470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
228470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    /* renormalize interval and update streamval */
229470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    /* W_upper < 2^24 */
230470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    while ( !(W_upper & 0xFF000000) )
231470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
232470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      /* read next byte from stream */
233470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      if (streamData->full == 0) {
234470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        streamval = WEBRTC_SPL_LSHIFT_W32(streamval, 8) |
235470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            (*streamPtr++ & 0x00FF);
236470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        streamData->full = 1;
237470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      } else {
238f71785cd3b282ad7d584d746ba5b19833a11692bbjornv@webrtc.org        streamval = (streamval << 8) | (*streamPtr >> 8);
239470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        streamData->full = 0;
240470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      }
241470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      W_upper = WEBRTC_SPL_LSHIFT_W32(W_upper, 8);
242470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
243470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
244470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
245470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    /* Error check: should not be possible in normal operation */
246470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (W_upper == 0) {
247470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      return -2;
248470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
249470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
250470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
251470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
252470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  streamData->stream_index = streamPtr - streamData->stream;
253470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  streamData->W_upper = W_upper;
254470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  streamData->streamval = streamval;
255470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
256470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  if ( W_upper > 0x01FFFFFF ) {
257470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return (streamData->stream_index*2 - 3 + !streamData->full);
258470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  } else {
259470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return (streamData->stream_index*2 - 2 + !streamData->full);
260470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
261470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
262470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
263470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
264470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com/****************************************************************************
265470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * WebRtcIsacfix_DecHistOneStepMulti(...)
266470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *
267470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * Function to decode more symbols from the arithmetic bytestream, taking
268470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * single step up or down at a time.
269470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * cdf tables can be of arbitrary size, but large tables may take a lot of
270470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * iterations.
271470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *
272470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * Input:
273470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *      - streamData        : in-/output struct containing bitstream
274470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *      - cdf               : array of cdf arrays
275470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *      - initIndex         : vector of initial cdf table search entries
276470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *      - lenData           : data vector length
277470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *
278470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * Output:
279470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *      - data              : data vector
280470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *
281470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * Return value             : number of bytes in original stream
282470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *                            <0 if error detected
283470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com */
2840946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.orgint16_t WebRtcIsacfix_DecHistOneStepMulti(int16_t *data,
2850946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org                                          Bitstr_dec *streamData,
2860946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org                                          const uint16_t **cdf,
2870946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org                                          const uint16_t *initIndex,
2880946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org                                          const int16_t lenData)
289470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
2900946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  uint32_t    W_lower;
2910946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  uint32_t    W_upper;
2920946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  uint32_t    W_tmp;
2930946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  uint32_t    W_upper_LSB;
2940946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  uint32_t    W_upper_MSB;
2950946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  uint32_t    streamval;
2960946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  const uint16_t *streamPtr;
2970946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  const uint16_t *cdfPtr;
298470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  int             k;
299470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
300470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
301470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  streamPtr = streamData->stream + streamData->stream_index;
302470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  W_upper = streamData->W_upper;
303470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* Error check: Should not be possible in normal operation */
304470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  if (W_upper == 0) {
305470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return -2;
306470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
307470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
308470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* Check if it is the first time decoder is called for this stream */
309470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  if (streamData->stream_index == 0)
310470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  {
311470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    /* read first word from bytestream */
3127c15510f389b00fea03e8512cf1a09d0a344b8e9bjornv@webrtc.org    streamval = (uint32_t)(*streamPtr++) << 16;
313470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    streamval |= *streamPtr++;
314470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  } else {
315470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    streamval = streamData->streamval;
316470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
317470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
318470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  for (k = lenData; k > 0; k--)
319470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  {
320470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    /* find the integer *data for which streamval lies in [W_lower+1, W_upper] */
321470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    W_upper_LSB = W_upper & 0x0000FFFF;
322470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    W_upper_MSB = WEBRTC_SPL_RSHIFT_U32(W_upper, 16);
323470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
324470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    /* start at the specified table entry */
325470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    cdfPtr = *cdf + (*initIndex++);
326470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    W_tmp = WEBRTC_SPL_UMUL_32_16(W_upper_MSB, *cdfPtr);
3271e3ef4b999ada52fc4e421d1d06b73068e855413bjornv@webrtc.org    W_tmp += (W_upper_LSB * (*cdfPtr)) >> 16;
328470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
329470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (streamval > W_tmp)
330470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
331470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      for ( ;; )
332470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      {
333470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        W_lower = W_tmp;
334470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
335470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        /* range check */
336470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (cdfPtr[0] == 65535) {
337470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com          return -3;
338470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
339470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
340470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        W_tmp = WEBRTC_SPL_UMUL_32_16(W_upper_MSB, *++cdfPtr);
3411e3ef4b999ada52fc4e421d1d06b73068e855413bjornv@webrtc.org        W_tmp += (W_upper_LSB * (*cdfPtr)) >> 16;
342470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
343470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (streamval <= W_tmp) {
344470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com          break;
345470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
346470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      }
347470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      W_upper = W_tmp;
348470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      *data++ = cdfPtr - *cdf++ - 1;
349470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    } else {
350470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      for ( ;; )
351470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      {
352470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        W_upper = W_tmp;
353470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        --cdfPtr;
354470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
355470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        /* range check */
356470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (cdfPtr < *cdf) {
357470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com          return -3;
358470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
359470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
360470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        W_tmp = WEBRTC_SPL_UMUL_32_16(W_upper_MSB, *cdfPtr);
3611e3ef4b999ada52fc4e421d1d06b73068e855413bjornv@webrtc.org        W_tmp += (W_upper_LSB * (*cdfPtr)) >> 16;
362470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
363470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (streamval > W_tmp) {
364470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com          break;
365470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
366470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      }
367470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      W_lower = W_tmp;
368470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      *data++ = cdfPtr - *cdf++;
369470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
370470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
371470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    /* shift interval to start at zero */
372470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    W_upper -= ++W_lower;
373470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
374470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    /* add integer to bitstream */
375470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    streamval -= W_lower;
376470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
377470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    /* renormalize interval and update streamval */
378470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    /* W_upper < 2^24 */
379470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    while ( !(W_upper & 0xFF000000) )
380470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
381470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      /* read next byte from stream */
382470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      if (streamData->full == 0) {
383470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        streamval = WEBRTC_SPL_LSHIFT_W32(streamval, 8) | (*streamPtr++ & 0x00FF);
384470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        streamData->full = 1;
385470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      } else {
386470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        streamval = WEBRTC_SPL_LSHIFT_W32(streamval, 8) | (*streamPtr >> 8);
387470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        streamData->full = 0;
388470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      }
389470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      W_upper = WEBRTC_SPL_LSHIFT_W32(W_upper, 8);
390470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
391470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
392470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
393470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  streamData->stream_index = streamPtr - streamData->stream;
394470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  streamData->W_upper = W_upper;
395470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  streamData->streamval = streamval;
396470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
397470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* find number of bytes in original stream (determined by current interval width) */
398470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  if ( W_upper > 0x01FFFFFF ) {
399470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return (streamData->stream_index*2 - 3 + !streamData->full);
400470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  } else {
401470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return (streamData->stream_index*2 - 2 + !streamData->full);
402470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
403470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
404