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