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
13470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com iLBC Speech Coder ANSI-C Source Code
14470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
15470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WebRtcIlbcfix_StateSearch.c
16470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
17470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com******************************************************************/
18470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
19470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#include "defines.h"
20470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#include "constants.h"
21470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#include "abs_quant.h"
22470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
23470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com/*----------------------------------------------------------------*
24470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *  encoding of start state
25470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *---------------------------------------------------------------*/
26470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
27470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comvoid WebRtcIlbcfix_StateSearch(
28eb544460e47140d494dddf1217a698a1dcf4dee0pbos@webrtc.org    IlbcEncoder *iLBCenc_inst,
29470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    /* (i) Encoder instance */
30470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    iLBC_bits *iLBC_encbits,/* (i/o) Encoded bits (output idxForMax
31470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                               and idxVec, input state_first) */
320946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org    int16_t *residual,   /* (i) target residual vector */
330946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org    int16_t *syntDenum,  /* (i) lpc synthesis filter */
340946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org    int16_t *weightDenum  /* (i) weighting filter denuminator */
35470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                               ) {
36dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  size_t k, index;
370946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int16_t maxVal;
380946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int16_t scale, shift;
390946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int32_t maxValsq;
400946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int16_t scaleRes;
410946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int16_t max;
42470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  int i;
43470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* Stack based */
440946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int16_t numerator[1+LPC_FILTERORDER];
450946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int16_t residualLongVec[2*STATE_SHORT_LEN_30MS+LPC_FILTERORDER];
460946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int16_t sampleMa[2*STATE_SHORT_LEN_30MS];
470946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int16_t *residualLong = &residualLongVec[LPC_FILTERORDER];
480946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int16_t *sampleAr = residualLong;
49470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
50470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* Scale to maximum 12 bits to avoid saturation in circular convolution filter */
51470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  max = WebRtcSpl_MaxAbsValueW16(residual, iLBCenc_inst->state_short_len);
52470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  scaleRes = WebRtcSpl_GetSizeInBits(max)-12;
53470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  scaleRes = WEBRTC_SPL_MAX(0, scaleRes);
54470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* Set up the filter coefficients for the circular convolution */
55470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  for (i=0; i<LPC_FILTERORDER+1; i++) {
56470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    numerator[i] = (syntDenum[LPC_FILTERORDER-i]>>scaleRes);
57470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
58470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
59470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* Copy the residual to a temporary buffer that we can filter
60470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com   * and set the remaining samples to zero.
61470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com   */
62470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  WEBRTC_SPL_MEMCPY_W16(residualLong, residual, iLBCenc_inst->state_short_len);
63470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  WebRtcSpl_MemSetW16(residualLong + iLBCenc_inst->state_short_len, 0, iLBCenc_inst->state_short_len);
64470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
65470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* Run the Zero-Pole filter (Ciurcular convolution) */
66470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  WebRtcSpl_MemSetW16(residualLongVec, 0, LPC_FILTERORDER);
67dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  WebRtcSpl_FilterMAFastQ12(residualLong, sampleMa, numerator,
68dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting                            LPC_FILTERORDER + 1,
69dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting                            iLBCenc_inst->state_short_len + LPC_FILTERORDER);
70470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  WebRtcSpl_MemSetW16(&sampleMa[iLBCenc_inst->state_short_len + LPC_FILTERORDER], 0, iLBCenc_inst->state_short_len - LPC_FILTERORDER);
71470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
72470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  WebRtcSpl_FilterARFastQ12(
73470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      sampleMa, sampleAr,
74b7e5054414ff524f9db81dab7917729b8c4c8bcbPeter Kasting      syntDenum, LPC_FILTERORDER+1, 2 * iLBCenc_inst->state_short_len);
75470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
76470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  for(k=0;k<iLBCenc_inst->state_short_len;k++){
77470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    sampleAr[k] += sampleAr[k+iLBCenc_inst->state_short_len];
78470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
79470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
80470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* Find maximum absolute value in the vector */
81470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  maxVal=WebRtcSpl_MaxAbsValueW16(sampleAr, iLBCenc_inst->state_short_len);
82470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
83470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* Find the best index */
84470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
850946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  if ((((int32_t)maxVal)<<scaleRes)<23170) {
860946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org    maxValsq=((int32_t)maxVal*maxVal)<<(2+2*scaleRes);
87470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  } else {
880946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org    maxValsq=(int32_t)WEBRTC_SPL_WORD32_MAX;
89470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
90470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
91470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  index=0;
92470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  for (i=0;i<63;i++) {
93470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
94470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (maxValsq>=WebRtcIlbcfix_kChooseFrgQuant[i]) {
95470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      index=i+1;
96470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    } else {
97470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      i=63;
98470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
99470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
100470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  iLBC_encbits->idxForMax=index;
101470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
102470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* Rescale the vector before quantization */
103470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  scale=WebRtcIlbcfix_kScale[index];
104470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
105470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  if (index<27) { /* scale table is in Q16, fout[] is in Q(-1) and we want the result to be in Q11 */
106470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    shift=4;
107470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  } else { /* scale table is in Q21, fout[] is in Q(-1) and we want the result to be in Q11 */
108470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    shift=9;
109470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
110470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
111470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* Set up vectors for AbsQuant and rescale it with the scale factor */
112470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  WebRtcSpl_ScaleVectorWithSat(sampleAr, sampleAr, scale,
1130946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org                              iLBCenc_inst->state_short_len, (int16_t)(shift-scaleRes));
114470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
115470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* Quantize the values in fout[] */
116470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  WebRtcIlbcfix_AbsQuant(iLBCenc_inst, iLBC_encbits, sampleAr, weightDenum);
117470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
118470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  return;
119470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
120