1551ccae044b0ff658fe629dd67edd5ffe75d10e8Reid Spencer/*
263b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
36c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke *
46c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke *  Use of this source code is governed by a BSD-style license
57ed47a13356daed2a34cd2209a31f92552e3bdd8Chris Lattner *  that can be found in the LICENSE file in the root of the source
67ed47a13356daed2a34cd2209a31f92552e3bdd8Chris Lattner *  tree. An additional intellectual property rights grant can be found
763b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman *  in the file PATENTS.  All contributing project authors may
86c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke *  be found in the AUTHORS file in the root of the source tree.
96c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke */
106c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke
116c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke#include "settings.h"
1263b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman#include "arith_routines.h"
139a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson
149a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson
159a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson/*
169a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson * code symbols into arithmetic bytestream
176c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke */
186c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaekevoid WebRtcIsac_EncHistMulti(Bitstr *streamdata, /* in-/output struct containing bitstream */
196c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke                             const int *data,  /* input: data vector */
20551ccae044b0ff658fe629dd67edd5ffe75d10e8Reid Spencer                             const WebRtc_UWord16 **cdf, /* input: array of cdf arrays */
21551ccae044b0ff658fe629dd67edd5ffe75d10e8Reid Spencer                             const int N)   /* input: data vector length */
22551ccae044b0ff658fe629dd67edd5ffe75d10e8Reid Spencer{
235e4d8a5eca03c977ba01e061078a2d740ee6130aZonr Chang  WebRtc_UWord32 W_lower, W_upper;
241f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer  WebRtc_UWord32 W_upper_LSB, W_upper_MSB;
256c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  WebRtc_UWord8 *stream_ptr;
266c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  WebRtc_UWord8 *stream_ptr_carry;
276c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  WebRtc_UWord32 cdf_lo, cdf_hi;
286c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  int k;
296c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke
306c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke
316c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  /* point to beginning of stream buffer */
326c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  stream_ptr = streamdata->stream + streamdata->stream_index;
33c8f6c44af46554036084cba21a118266f5e26c0eMichael J. Spencer  W_upper = streamdata->W_upper;
346c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke
35c8f6c44af46554036084cba21a118266f5e26c0eMichael J. Spencer  for (k=N; k>0; k--)
366c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  {
37620ee02353d8b65959dc01a66b073adfcdef9eacBrian Gaeke    /* fetch cdf_lower and cdf_upper from cdf tables */
38620ee02353d8b65959dc01a66b073adfcdef9eacBrian Gaeke    cdf_lo = (WebRtc_UWord32) *(*cdf + *data);
39c8f6c44af46554036084cba21a118266f5e26c0eMichael J. Spencer    cdf_hi = (WebRtc_UWord32) *(*cdf++ + *data++ + 1);
40620ee02353d8b65959dc01a66b073adfcdef9eacBrian Gaeke
41c8f6c44af46554036084cba21a118266f5e26c0eMichael J. Spencer    /* update interval */
42620ee02353d8b65959dc01a66b073adfcdef9eacBrian Gaeke    W_upper_LSB = W_upper & 0x0000FFFF;
43c8f6c44af46554036084cba21a118266f5e26c0eMichael J. Spencer    W_upper_MSB = W_upper >> 16;
44620ee02353d8b65959dc01a66b073adfcdef9eacBrian Gaeke    W_lower = W_upper_MSB * cdf_lo;
456c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke    W_lower += (W_upper_LSB * cdf_lo) >> 16;
46757c1f9d87b516a1e3bc4cd678245b207ae9c559Brian Gaeke    W_upper = W_upper_MSB * cdf_hi;
476c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke    W_upper += (W_upper_LSB * cdf_hi) >> 16;
489a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson
499a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson    /* shift interval such that it begins at zero */
509a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson    W_upper -= ++W_lower;
519a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson
529a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson    /* add integer to bitstream */
539a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson    streamdata->streamval += W_lower;
549a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson
559a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson    /* handle carry */
569a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson    if (streamdata->streamval < W_lower)
579a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson    {
589a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson      /* propagate carry */
599a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson      stream_ptr_carry = stream_ptr;
609a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson      while (!(++(*--stream_ptr_carry)));
619a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson    }
629a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson
636c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke    /* renormalize interval, store most significant byte of streamval and update streamval */
649a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson    while ( !(W_upper & 0xFF000000) )      /* W_upper < 2^24 */
656c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke    {
666c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke      W_upper <<= 8;
676c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke      *stream_ptr++ = (WebRtc_UWord8) (streamdata->streamval >> 24);
686c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke      streamdata->streamval <<= 8;
696c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke    }
706c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  }
716c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke
726c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  /* calculate new stream_index */
736c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  streamdata->stream_index = (int)(stream_ptr - streamdata->stream);
746c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  streamdata->W_upper = W_upper;
756c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke
766c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  return;
776c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke}
78fe4591bfc2b147c10d6a7b1a5af56454fb78daceStephen Wilson
79314451326ad1ef89241b240a704e104897e4ee81Stephen Wilson
806c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke
819a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson/*
829a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson * function to decode more symbols from the arithmetic bytestream, using method of bisection
836c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke * cdf tables should be of size 2^k-1 (which corresponds to an alphabet size of 2^k-2)
846c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke */
85620ee02353d8b65959dc01a66b073adfcdef9eacBrian Gaekeint WebRtcIsac_DecHistBisectMulti(int *data,     /* output: data vector */
86620ee02353d8b65959dc01a66b073adfcdef9eacBrian Gaeke                                  Bitstr *streamdata,   /* in-/output struct containing bitstream */
87e9f6f2c0492af8097166f1b7d62f131f20ca5714Brian Gaeke                                  const WebRtc_UWord16 **cdf,  /* input: array of cdf arrays */
889a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson                                  const WebRtc_UWord16 *cdf_size, /* input: array of cdf table sizes+1 (power of two: 2^k) */
89c8f6c44af46554036084cba21a118266f5e26c0eMichael J. Spencer                                  const int N)    /* input: data vector length */
90c8f6c44af46554036084cba21a118266f5e26c0eMichael J. Spencer{
91c8f6c44af46554036084cba21a118266f5e26c0eMichael J. Spencer  WebRtc_UWord32    W_lower, W_upper;
92620ee02353d8b65959dc01a66b073adfcdef9eacBrian Gaeke  WebRtc_UWord32    W_tmp;
93620ee02353d8b65959dc01a66b073adfcdef9eacBrian Gaeke  WebRtc_UWord32    W_upper_LSB, W_upper_MSB;
94620ee02353d8b65959dc01a66b073adfcdef9eacBrian Gaeke  WebRtc_UWord32    streamval;
95c8f6c44af46554036084cba21a118266f5e26c0eMichael J. Spencer  const   WebRtc_UWord8 *stream_ptr;
96c8f6c44af46554036084cba21a118266f5e26c0eMichael J. Spencer  const   WebRtc_UWord16 *cdf_ptr;
97c8f6c44af46554036084cba21a118266f5e26c0eMichael J. Spencer  int     size_tmp;
98c8f6c44af46554036084cba21a118266f5e26c0eMichael J. Spencer  int     k;
99c8f6c44af46554036084cba21a118266f5e26c0eMichael J. Spencer
100c8f6c44af46554036084cba21a118266f5e26c0eMichael J. Spencer  W_lower = 0; //to remove warning -DH
101c8f6c44af46554036084cba21a118266f5e26c0eMichael J. Spencer  stream_ptr = streamdata->stream + streamdata->stream_index;
1029a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson  W_upper = streamdata->W_upper;
1039a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson  if (W_upper == 0)
1049a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson    /* Should not be possible in normal operation */
1059a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson    return -2;
1069a9ad77847c1be4ffc5ba6304e33ccecbf72e43fStephen Wilson
107e9f6f2c0492af8097166f1b7d62f131f20ca5714Brian Gaeke  if (streamdata->stream_index == 0)   /* first time decoder is called for this stream */
108620ee02353d8b65959dc01a66b073adfcdef9eacBrian Gaeke  {
1096c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke    /* read first word from bytestream */
1106c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke    streamval = *stream_ptr << 24;
1116c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke    streamval |= *++stream_ptr << 16;
1126c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke    streamval |= *++stream_ptr << 8;
1136c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke    streamval |= *++stream_ptr;
1146c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  } else {
1156c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke    streamval = streamdata->streamval;
1166c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  }
1176c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke
1186c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  for (k=N; k>0; k--)
1196c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke  {
1205af8f421b6412e52530608097e39d2602195629fDan Gohman    /* find the integer *data for which streamval lies in [W_lower+1, W_upper] */
1215af8f421b6412e52530608097e39d2602195629fDan Gohman    W_upper_LSB = W_upper & 0x0000FFFF;
1225af8f421b6412e52530608097e39d2602195629fDan Gohman    W_upper_MSB = W_upper >> 16;
1235af8f421b6412e52530608097e39d2602195629fDan Gohman
1245af8f421b6412e52530608097e39d2602195629fDan Gohman    /* start halfway the cdf range */
1255af8f421b6412e52530608097e39d2602195629fDan Gohman    size_tmp = *cdf_size++ >> 1;
1266c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke    cdf_ptr = *cdf + (size_tmp - 1);
1276c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke
128fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer    /* method of bisection */
129fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer    for ( ;; )
130fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer    {
131fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer      W_tmp = W_upper_MSB * *cdf_ptr;
132fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer      W_tmp += (W_upper_LSB * *cdf_ptr) >> 16;
133fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer      size_tmp >>= 1;
134fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer      if (size_tmp == 0) break;
135fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer      if (streamval > W_tmp)
136fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer      {
137fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer        W_lower = W_tmp;
138fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer        cdf_ptr += size_tmp;
139fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer      } else {
140fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer        W_upper = W_tmp;
141fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer        cdf_ptr -= size_tmp;
142fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer      }
143fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer    }
144fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer    if (streamval > W_tmp)
145fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer    {
146fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer      W_lower = W_tmp;
147fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer      *data++ = (int)(cdf_ptr - *cdf++);
148fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer    } else {
149fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer      W_upper = W_tmp;
150fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer      *data++ = (int)(cdf_ptr - *cdf++ - 1);
151fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer    }
152fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer
153fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer    /* shift interval to start at zero */
154fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer    W_upper -= ++W_lower;
155fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer
156fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer    /* add integer to bitstream */
157fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer    streamval -= W_lower;
158fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer
159fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer    /* renormalize interval and update streamval */
160fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer    while ( !(W_upper & 0xFF000000) )    /* W_upper < 2^24 */
161fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer    {
162fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer      /* read next byte from stream */
163fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer      streamval = (streamval << 8) | *++stream_ptr;
164fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer      W_upper <<= 8;
165fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer    }
166fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer
167fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer    if (W_upper == 0)
168fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer      /* Should not be possible in normal operation */
169fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer      return -2;
170fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer
171fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer
172fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer  }
173fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer
174fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer  streamdata->stream_index = (int)(stream_ptr - streamdata->stream);
175fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer  streamdata->W_upper = W_upper;
176fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer  streamdata->streamval = streamval;
177fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer
178fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer
179fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer  /* find number of bytes in original stream (determined by current interval width) */
180fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer  if ( W_upper > 0x01FFFFFF )
181fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer    return streamdata->stream_index - 2;
182fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer  else
183fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer    return streamdata->stream_index - 1;
184fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer}
185fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer
186fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer
187fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer
188fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer/*
189fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer * function to decode more symbols from the arithmetic bytestream, taking single step up or
190fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer * down at a time
191fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer * cdf tables can be of arbitrary size, but large tables may take a lot of iterations
192fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer */
193fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencerint WebRtcIsac_DecHistOneStepMulti(int *data,        /* output: data vector */
194fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer                                   Bitstr *streamdata,      /* in-/output struct containing bitstream */
195fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer                                   const WebRtc_UWord16 **cdf,   /* input: array of cdf arrays */
196fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer                                   const WebRtc_UWord16 *init_index, /* input: vector of initial cdf table search entries */
197fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer                                   const int N)     /* input: data vector length */
198fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer{
199fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer  WebRtc_UWord32    W_lower, W_upper;
200fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer  WebRtc_UWord32    W_tmp;
201fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer  WebRtc_UWord32    W_upper_LSB, W_upper_MSB;
202fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer  WebRtc_UWord32    streamval;
203fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer  const   WebRtc_UWord8 *stream_ptr;
204fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer  const   WebRtc_UWord16 *cdf_ptr;
205fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer  int     k;
206fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer
207fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer
208fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer  stream_ptr = streamdata->stream + streamdata->stream_index;
209fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer  W_upper = streamdata->W_upper;
210fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer  if (W_upper == 0)
211fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer    /* Should not be possible in normal operation */
212fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer    return -2;
213fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer
214fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer  if (streamdata->stream_index == 0)   /* first time decoder is called for this stream */
215fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer  {
216fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer    /* read first word from bytestream */
217fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer    streamval = *stream_ptr << 24;
218fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer    streamval |= *++stream_ptr << 16;
219fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer    streamval |= *++stream_ptr << 8;
220fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer    streamval |= *++stream_ptr;
221fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer  } else {
222fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer    streamval = streamdata->streamval;
223fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer  }
224fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer
225fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer
226fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer  for (k=N; k>0; k--)
227fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer  {
228fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer    /* find the integer *data for which streamval lies in [W_lower+1, W_upper] */
229fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer    W_upper_LSB = W_upper & 0x0000FFFF;
230fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer    W_upper_MSB = W_upper >> 16;
231fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer
232fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer    /* start at the specified table entry */
233fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer    cdf_ptr = *cdf + (*init_index++);
234fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer    W_tmp = W_upper_MSB * *cdf_ptr;
235fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer    W_tmp += (W_upper_LSB * *cdf_ptr) >> 16;
236fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer    if (streamval > W_tmp)
237fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer    {
238fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer      for ( ;; )
239fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer      {
240fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer        W_lower = W_tmp;
241fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer        if (cdf_ptr[0]==65535)
242fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer          /* range check */
243fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer          return -3;
244fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer        W_tmp = W_upper_MSB * *++cdf_ptr;
245fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer        W_tmp += (W_upper_LSB * *cdf_ptr) >> 16;
246fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer        if (streamval <= W_tmp) break;
247fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer      }
248fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer      W_upper = W_tmp;
249fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer      *data++ = (int)(cdf_ptr - *cdf++ - 1);
250fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer    } else {
251fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer      for ( ;; )
25268ef0382e4efe4a4c06e47a53a275b873ba0cff4Evandro Menezes      {
253fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer        W_upper = W_tmp;
254fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer        --cdf_ptr;
255fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer        if (cdf_ptr<*cdf) {
256fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer          /* range check */
257fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer          return -3;
258fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer        }
259fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer        W_tmp = W_upper_MSB * *cdf_ptr;
260fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer        W_tmp += (W_upper_LSB * *cdf_ptr) >> 16;
261fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer        if (streamval > W_tmp) break;
262fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer      }
263fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer      W_lower = W_tmp;
264fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer      *data++ = (int)(cdf_ptr - *cdf++);
265fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer    }
266fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer
267fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer    /* shift interval to start at zero */
268fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer    W_upper -= ++W_lower;
269fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer    /* add integer to bitstream */
270fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer    streamval -= W_lower;
271fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer
272fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer    /* renormalize interval and update streamval */
273fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer    while ( !(W_upper & 0xFF000000) )    /* W_upper < 2^24 */
274fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer    {
27572062f5744557e270a38192554c3126ea5f97434Tim Northover      /* read next byte from stream */
276fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer      streamval = (streamval << 8) | *++stream_ptr;
277fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer      W_upper <<= 8;
278fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer    }
279fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer  }
280fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer
281fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer  streamdata->stream_index = (int)(stream_ptr - streamdata->stream);
282fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer  streamdata->W_upper = W_upper;
283fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer  streamdata->streamval = streamval;
284fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer
285fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer
286fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer  /* find number of bytes in original stream (determined by current interval width) */
287fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer  if ( W_upper > 0x01FFFFFF )
288fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer    return streamdata->stream_index - 2;
289fc61a23506fdad8f38e3437d741a4108339abcfeMichael J. Spencer  else
2906fccaafd8be0eb7619b5a210387b0d1254ef4174Rafael Espindola    return streamdata->stream_index - 1;
2916c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke}
2926c39a42b5c93b6d0af008dbafed6134d1deaa848Brian Gaeke