2 * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
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.
14 * This C file contains arithmetic encoding and decoding.
18 #include "arith_routins.h"
21 /****************************************************************************
22 * WebRtcIsacfix_EncHistMulti(...)
24 * Encode the histogram interval
27 * - streamData : in-/output struct containing bitstream
28 * - data : data vector
29 * - cdf : array of cdf arrays
30 * - lenData : data vector length
32 * Return value : 0 if ok
33 * <0 if error detected
35 int WebRtcIsacfix_EncHistMulti(Bitstr_enc *streamData,
38 const int16_t lenData)
46 uint16_t *maxStreamPtr;
47 uint16_t *streamPtrCarry;
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;
58 W_upper = streamData->W_upper;
60 for (k = lenData; k > 0; k--)
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);
67 W_upper_LSB = W_upper & 0x0000FFFF;
68 W_upper_MSB = 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);
74 /* shift interval such that it begins at zero */
77 /* add integer to bitstream */
78 streamData->streamval += W_lower;
81 if (streamData->streamval < W_lower)
84 streamPtrCarry = streamPtr;
85 if (streamData->full == 0) {
86 negCarry = *streamPtrCarry;
88 *streamPtrCarry = negCarry;
91 negCarry = *--streamPtrCarry;
93 *streamPtrCarry = negCarry;
96 while ( !(++(*--streamPtrCarry)) );
100 /* renormalize interval, store most significant byte of streamval and update streamval
102 while ( !(W_upper & 0xFF000000) )
104 W_upper = WEBRTC_SPL_LSHIFT_W32(W_upper, 8);
105 if (streamData->full == 0) {
106 *streamPtr++ += (uint16_t)(streamData->streamval >> 24);
107 streamData->full = 1;
109 *streamPtr = (uint16_t)((streamData->streamval >> 24) << 8);
110 streamData->full = 0;
113 if( streamPtr > maxStreamPtr ) {
114 return -ISAC_DISALLOWED_BITSTREAM_LENGTH;
116 streamData->streamval = WEBRTC_SPL_LSHIFT_W32(streamData->streamval, 8);
120 /* calculate new stream_index */
121 streamData->stream_index = streamPtr - streamData->stream;
122 streamData->W_upper = W_upper;
128 /****************************************************************************
129 * WebRtcIsacfix_DecHistBisectMulti(...)
131 * Function to decode more symbols from the arithmetic bytestream, using
132 * method of bisection cdf tables should be of size 2^k-1 (which corresponds
133 * to an alphabet size of 2^k-2)
136 * - streamData : in-/output struct containing bitstream
137 * - cdf : array of cdf arrays
138 * - cdfSize : array of cdf table sizes+1 (power of two: 2^k)
139 * - lenData : data vector length
142 * - data : data vector
144 * Return value : number of bytes in the stream
145 * <0 if error detected
147 int16_t WebRtcIsacfix_DecHistBisectMulti(int16_t *data,
148 Bitstr_dec *streamData,
149 const uint16_t **cdf,
150 const uint16_t *cdfSize,
151 const int16_t lenData)
153 uint32_t W_lower = 0;
156 uint32_t W_upper_LSB;
157 uint32_t W_upper_MSB;
159 const uint16_t *streamPtr;
160 const uint16_t *cdfPtr;
165 streamPtr = streamData->stream + streamData->stream_index;
166 W_upper = streamData->W_upper;
168 /* Error check: should not be possible in normal operation */
173 /* first time decoder is called for this stream */
174 if (streamData->stream_index == 0)
176 /* read first word from bytestream */
177 streamval = WEBRTC_SPL_LSHIFT_W32((uint32_t)*streamPtr++, 16);
178 streamval |= *streamPtr++;
180 streamval = streamData->streamval;
183 for (k = lenData; k > 0; k--)
185 /* find the integer *data for which streamval lies in [W_lower+1, W_upper] */
186 W_upper_LSB = W_upper & 0x0000FFFF;
187 W_upper_MSB = W_upper >> 16;
189 /* start halfway the cdf range */
190 sizeTmp = *cdfSize++ / 2;
191 cdfPtr = *cdf + (sizeTmp - 1);
193 /* method of bisection */
196 W_tmp = WEBRTC_SPL_UMUL_32_16(W_upper_MSB, *cdfPtr);
197 W_tmp += (W_upper_LSB * (*cdfPtr)) >> 16;
203 if (streamval > W_tmp)
212 if (streamval > W_tmp)
215 *data++ = cdfPtr - *cdf++;
218 *data++ = cdfPtr - *cdf++ - 1;
221 /* shift interval to start at zero */
222 W_upper -= ++W_lower;
224 /* add integer to bitstream */
225 streamval -= W_lower;
227 /* renormalize interval and update streamval */
229 while ( !(W_upper & 0xFF000000) )
231 /* read next byte from stream */
232 if (streamData->full == 0) {
233 streamval = WEBRTC_SPL_LSHIFT_W32(streamval, 8) |
234 (*streamPtr++ & 0x00FF);
235 streamData->full = 1;
237 streamval = (streamval << 8) | (*streamPtr >> 8);
238 streamData->full = 0;
240 W_upper = WEBRTC_SPL_LSHIFT_W32(W_upper, 8);
244 /* Error check: should not be possible in normal operation */
251 streamData->stream_index = streamPtr - streamData->stream;
252 streamData->W_upper = W_upper;
253 streamData->streamval = streamval;
255 if ( W_upper > 0x01FFFFFF ) {
256 return (streamData->stream_index*2 - 3 + !streamData->full);
258 return (streamData->stream_index*2 - 2 + !streamData->full);
263 /****************************************************************************
264 * WebRtcIsacfix_DecHistOneStepMulti(...)
266 * Function to decode more symbols from the arithmetic bytestream, taking
267 * single step up or down at a time.
268 * cdf tables can be of arbitrary size, but large tables may take a lot of
272 * - streamData : in-/output struct containing bitstream
273 * - cdf : array of cdf arrays
274 * - initIndex : vector of initial cdf table search entries
275 * - lenData : data vector length
278 * - data : data vector
280 * Return value : number of bytes in original stream
281 * <0 if error detected
283 int16_t WebRtcIsacfix_DecHistOneStepMulti(int16_t *data,
284 Bitstr_dec *streamData,
285 const uint16_t **cdf,
286 const uint16_t *initIndex,
287 const int16_t lenData)
292 uint32_t W_upper_LSB;
293 uint32_t W_upper_MSB;
295 const uint16_t *streamPtr;
296 const uint16_t *cdfPtr;
300 streamPtr = streamData->stream + streamData->stream_index;
301 W_upper = streamData->W_upper;
302 /* Error check: Should not be possible in normal operation */
307 /* Check if it is the first time decoder is called for this stream */
308 if (streamData->stream_index == 0)
310 /* read first word from bytestream */
311 streamval = (uint32_t)(*streamPtr++) << 16;
312 streamval |= *streamPtr++;
314 streamval = streamData->streamval;
317 for (k = lenData; k > 0; k--)
319 /* find the integer *data for which streamval lies in [W_lower+1, W_upper] */
320 W_upper_LSB = W_upper & 0x0000FFFF;
321 W_upper_MSB = WEBRTC_SPL_RSHIFT_U32(W_upper, 16);
323 /* start at the specified table entry */
324 cdfPtr = *cdf + (*initIndex++);
325 W_tmp = WEBRTC_SPL_UMUL_32_16(W_upper_MSB, *cdfPtr);
326 W_tmp += (W_upper_LSB * (*cdfPtr)) >> 16;
328 if (streamval > W_tmp)
335 if (cdfPtr[0] == 65535) {
339 W_tmp = WEBRTC_SPL_UMUL_32_16(W_upper_MSB, *++cdfPtr);
340 W_tmp += (W_upper_LSB * (*cdfPtr)) >> 16;
342 if (streamval <= W_tmp) {
347 *data++ = cdfPtr - *cdf++ - 1;
359 W_tmp = WEBRTC_SPL_UMUL_32_16(W_upper_MSB, *cdfPtr);
360 W_tmp += (W_upper_LSB * (*cdfPtr)) >> 16;
362 if (streamval > W_tmp) {
367 *data++ = cdfPtr - *cdf++;
370 /* shift interval to start at zero */
371 W_upper -= ++W_lower;
373 /* add integer to bitstream */
374 streamval -= W_lower;
376 /* renormalize interval and update streamval */
378 while ( !(W_upper & 0xFF000000) )
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;
385 streamval = WEBRTC_SPL_LSHIFT_W32(streamval, 8) | (*streamPtr >> 8);
386 streamData->full = 0;
388 W_upper = WEBRTC_SPL_LSHIFT_W32(W_upper, 8);
392 streamData->stream_index = streamPtr - streamData->stream;
393 streamData->W_upper = W_upper;
394 streamData->streamval = streamval;
396 /* find number of bytes in original stream (determined by current interval width) */
397 if ( W_upper > 0x01FFFFFF ) {
398 return (streamData->stream_index*2 - 3 + !streamData->full);
400 return (streamData->stream_index*2 - 2 + !streamData->full);