build: More build fixes and cleanups
This commit is contained in:
		| @@ -0,0 +1,291 @@ | ||||
| /* | ||||
|  *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. | ||||
|  * | ||||
|  *  Use of this source code is governed by a BSD-style license | ||||
|  *  that can be found in the LICENSE file in the root of the source | ||||
|  *  tree. An additional intellectual property rights grant can be found | ||||
|  *  in the file PATENTS.  All contributing project authors may | ||||
|  *  be found in the AUTHORS file in the root of the source tree. | ||||
|  */ | ||||
|  | ||||
| #include "settings.h" | ||||
| #include "arith_routines.h" | ||||
|  | ||||
|  | ||||
| /* | ||||
|  * code symbols into arithmetic bytestream | ||||
|  */ | ||||
| void WebRtcIsac_EncHistMulti(Bitstr *streamdata, /* in-/output struct containing bitstream */ | ||||
|                              const int *data,  /* input: data vector */ | ||||
|                              const uint16_t **cdf, /* input: array of cdf arrays */ | ||||
|                              const int N)   /* input: data vector length */ | ||||
| { | ||||
|   uint32_t W_lower, W_upper; | ||||
|   uint32_t W_upper_LSB, W_upper_MSB; | ||||
|   uint8_t *stream_ptr; | ||||
|   uint8_t *stream_ptr_carry; | ||||
|   uint32_t cdf_lo, cdf_hi; | ||||
|   int k; | ||||
|  | ||||
|  | ||||
|   /* point to beginning of stream buffer */ | ||||
|   stream_ptr = streamdata->stream + streamdata->stream_index; | ||||
|   W_upper = streamdata->W_upper; | ||||
|  | ||||
|   for (k=N; k>0; k--) | ||||
|   { | ||||
|     /* fetch cdf_lower and cdf_upper from cdf tables */ | ||||
|     cdf_lo = (uint32_t) *(*cdf + *data); | ||||
|     cdf_hi = (uint32_t) *(*cdf++ + *data++ + 1); | ||||
|  | ||||
|     /* update interval */ | ||||
|     W_upper_LSB = W_upper & 0x0000FFFF; | ||||
|     W_upper_MSB = W_upper >> 16; | ||||
|     W_lower = W_upper_MSB * cdf_lo; | ||||
|     W_lower += (W_upper_LSB * cdf_lo) >> 16; | ||||
|     W_upper = W_upper_MSB * cdf_hi; | ||||
|     W_upper += (W_upper_LSB * cdf_hi) >> 16; | ||||
|  | ||||
|     /* shift interval such that it begins at zero */ | ||||
|     W_upper -= ++W_lower; | ||||
|  | ||||
|     /* add integer to bitstream */ | ||||
|     streamdata->streamval += W_lower; | ||||
|  | ||||
|     /* handle carry */ | ||||
|     if (streamdata->streamval < W_lower) | ||||
|     { | ||||
|       /* propagate carry */ | ||||
|       stream_ptr_carry = stream_ptr; | ||||
|       while (!(++(*--stream_ptr_carry))); | ||||
|     } | ||||
|  | ||||
|     /* renormalize interval, store most significant byte of streamval and update streamval */ | ||||
|     while ( !(W_upper & 0xFF000000) )      /* W_upper < 2^24 */ | ||||
|     { | ||||
|       W_upper <<= 8; | ||||
|       *stream_ptr++ = (uint8_t) (streamdata->streamval >> 24); | ||||
|       streamdata->streamval <<= 8; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   /* calculate new stream_index */ | ||||
|   streamdata->stream_index = (int)(stream_ptr - streamdata->stream); | ||||
|   streamdata->W_upper = W_upper; | ||||
|  | ||||
|   return; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| /* | ||||
|  * function to decode more symbols from the arithmetic bytestream, using method of bisection | ||||
|  * cdf tables should be of size 2^k-1 (which corresponds to an alphabet size of 2^k-2) | ||||
|  */ | ||||
| int WebRtcIsac_DecHistBisectMulti(int *data,     /* output: data vector */ | ||||
|                                   Bitstr *streamdata,   /* in-/output struct containing bitstream */ | ||||
|                                   const uint16_t **cdf,  /* input: array of cdf arrays */ | ||||
|                                   const uint16_t *cdf_size, /* input: array of cdf table sizes+1 (power of two: 2^k) */ | ||||
|                                   const int N)    /* input: data vector length */ | ||||
| { | ||||
|   uint32_t    W_lower, W_upper; | ||||
|   uint32_t    W_tmp; | ||||
|   uint32_t    W_upper_LSB, W_upper_MSB; | ||||
|   uint32_t    streamval; | ||||
|   const   uint8_t *stream_ptr; | ||||
|   const   uint16_t *cdf_ptr; | ||||
|   int     size_tmp; | ||||
|   int     k; | ||||
|  | ||||
|   W_lower = 0; //to remove warning -DH | ||||
|   stream_ptr = streamdata->stream + streamdata->stream_index; | ||||
|   W_upper = streamdata->W_upper; | ||||
|   if (W_upper == 0) | ||||
|     /* Should not be possible in normal operation */ | ||||
|     return -2; | ||||
|  | ||||
|   if (streamdata->stream_index == 0)   /* first time decoder is called for this stream */ | ||||
|   { | ||||
|     /* read first word from bytestream */ | ||||
|     streamval = *stream_ptr << 24; | ||||
|     streamval |= *++stream_ptr << 16; | ||||
|     streamval |= *++stream_ptr << 8; | ||||
|     streamval |= *++stream_ptr; | ||||
|   } else { | ||||
|     streamval = streamdata->streamval; | ||||
|   } | ||||
|  | ||||
|   for (k=N; k>0; k--) | ||||
|   { | ||||
|     /* find the integer *data for which streamval lies in [W_lower+1, W_upper] */ | ||||
|     W_upper_LSB = W_upper & 0x0000FFFF; | ||||
|     W_upper_MSB = W_upper >> 16; | ||||
|  | ||||
|     /* start halfway the cdf range */ | ||||
|     size_tmp = *cdf_size++ >> 1; | ||||
|     cdf_ptr = *cdf + (size_tmp - 1); | ||||
|  | ||||
|     /* method of bisection */ | ||||
|     for ( ;; ) | ||||
|     { | ||||
|       W_tmp = W_upper_MSB * *cdf_ptr; | ||||
|       W_tmp += (W_upper_LSB * *cdf_ptr) >> 16; | ||||
|       size_tmp >>= 1; | ||||
|       if (size_tmp == 0) break; | ||||
|       if (streamval > W_tmp) | ||||
|       { | ||||
|         W_lower = W_tmp; | ||||
|         cdf_ptr += size_tmp; | ||||
|       } else { | ||||
|         W_upper = W_tmp; | ||||
|         cdf_ptr -= size_tmp; | ||||
|       } | ||||
|     } | ||||
|     if (streamval > W_tmp) | ||||
|     { | ||||
|       W_lower = W_tmp; | ||||
|       *data++ = (int)(cdf_ptr - *cdf++); | ||||
|     } else { | ||||
|       W_upper = W_tmp; | ||||
|       *data++ = (int)(cdf_ptr - *cdf++ - 1); | ||||
|     } | ||||
|  | ||||
|     /* shift interval to start at zero */ | ||||
|     W_upper -= ++W_lower; | ||||
|  | ||||
|     /* add integer to bitstream */ | ||||
|     streamval -= W_lower; | ||||
|  | ||||
|     /* renormalize interval and update streamval */ | ||||
|     while ( !(W_upper & 0xFF000000) )    /* W_upper < 2^24 */ | ||||
|     { | ||||
|       /* read next byte from stream */ | ||||
|       streamval = (streamval << 8) | *++stream_ptr; | ||||
|       W_upper <<= 8; | ||||
|     } | ||||
|  | ||||
|     if (W_upper == 0) | ||||
|       /* Should not be possible in normal operation */ | ||||
|       return -2; | ||||
|  | ||||
|  | ||||
|   } | ||||
|  | ||||
|   streamdata->stream_index = (int)(stream_ptr - streamdata->stream); | ||||
|   streamdata->W_upper = W_upper; | ||||
|   streamdata->streamval = streamval; | ||||
|  | ||||
|  | ||||
|   /* find number of bytes in original stream (determined by current interval width) */ | ||||
|   if ( W_upper > 0x01FFFFFF ) | ||||
|     return streamdata->stream_index - 2; | ||||
|   else | ||||
|     return streamdata->stream_index - 1; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| /* | ||||
|  * function to decode more symbols from the arithmetic bytestream, taking single step up or | ||||
|  * down at a time | ||||
|  * cdf tables can be of arbitrary size, but large tables may take a lot of iterations | ||||
|  */ | ||||
| int WebRtcIsac_DecHistOneStepMulti(int *data,        /* output: data vector */ | ||||
|                                    Bitstr *streamdata,      /* in-/output struct containing bitstream */ | ||||
|                                    const uint16_t **cdf,   /* input: array of cdf arrays */ | ||||
|                                    const uint16_t *init_index, /* input: vector of initial cdf table search entries */ | ||||
|                                    const int N)     /* input: data vector length */ | ||||
| { | ||||
|   uint32_t    W_lower, W_upper; | ||||
|   uint32_t    W_tmp; | ||||
|   uint32_t    W_upper_LSB, W_upper_MSB; | ||||
|   uint32_t    streamval; | ||||
|   const   uint8_t *stream_ptr; | ||||
|   const   uint16_t *cdf_ptr; | ||||
|   int     k; | ||||
|  | ||||
|  | ||||
|   stream_ptr = streamdata->stream + streamdata->stream_index; | ||||
|   W_upper = streamdata->W_upper; | ||||
|   if (W_upper == 0) | ||||
|     /* Should not be possible in normal operation */ | ||||
|     return -2; | ||||
|  | ||||
|   if (streamdata->stream_index == 0)   /* first time decoder is called for this stream */ | ||||
|   { | ||||
|     /* read first word from bytestream */ | ||||
|     streamval = *stream_ptr << 24; | ||||
|     streamval |= *++stream_ptr << 16; | ||||
|     streamval |= *++stream_ptr << 8; | ||||
|     streamval |= *++stream_ptr; | ||||
|   } else { | ||||
|     streamval = streamdata->streamval; | ||||
|   } | ||||
|  | ||||
|  | ||||
|   for (k=N; k>0; k--) | ||||
|   { | ||||
|     /* find the integer *data for which streamval lies in [W_lower+1, W_upper] */ | ||||
|     W_upper_LSB = W_upper & 0x0000FFFF; | ||||
|     W_upper_MSB = W_upper >> 16; | ||||
|  | ||||
|     /* start at the specified table entry */ | ||||
|     cdf_ptr = *cdf + (*init_index++); | ||||
|     W_tmp = W_upper_MSB * *cdf_ptr; | ||||
|     W_tmp += (W_upper_LSB * *cdf_ptr) >> 16; | ||||
|     if (streamval > W_tmp) | ||||
|     { | ||||
|       for ( ;; ) | ||||
|       { | ||||
|         W_lower = W_tmp; | ||||
|         if (cdf_ptr[0]==65535) | ||||
|           /* range check */ | ||||
|           return -3; | ||||
|         W_tmp = W_upper_MSB * *++cdf_ptr; | ||||
|         W_tmp += (W_upper_LSB * *cdf_ptr) >> 16; | ||||
|         if (streamval <= W_tmp) break; | ||||
|       } | ||||
|       W_upper = W_tmp; | ||||
|       *data++ = (int)(cdf_ptr - *cdf++ - 1); | ||||
|     } else { | ||||
|       for ( ;; ) | ||||
|       { | ||||
|         W_upper = W_tmp; | ||||
|         --cdf_ptr; | ||||
|         if (cdf_ptr<*cdf) { | ||||
|           /* range check */ | ||||
|           return -3; | ||||
|         } | ||||
|         W_tmp = W_upper_MSB * *cdf_ptr; | ||||
|         W_tmp += (W_upper_LSB * *cdf_ptr) >> 16; | ||||
|         if (streamval > W_tmp) break; | ||||
|       } | ||||
|       W_lower = W_tmp; | ||||
|       *data++ = (int)(cdf_ptr - *cdf++); | ||||
|     } | ||||
|  | ||||
|     /* shift interval to start at zero */ | ||||
|     W_upper -= ++W_lower; | ||||
|     /* add integer to bitstream */ | ||||
|     streamval -= W_lower; | ||||
|  | ||||
|     /* renormalize interval and update streamval */ | ||||
|     while ( !(W_upper & 0xFF000000) )    /* W_upper < 2^24 */ | ||||
|     { | ||||
|       /* read next byte from stream */ | ||||
|       streamval = (streamval << 8) | *++stream_ptr; | ||||
|       W_upper <<= 8; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   streamdata->stream_index = (int)(stream_ptr - streamdata->stream); | ||||
|   streamdata->W_upper = W_upper; | ||||
|   streamdata->streamval = streamval; | ||||
|  | ||||
|  | ||||
|   /* find number of bytes in original stream (determined by current interval width) */ | ||||
|   if ( W_upper > 0x01FFFFFF ) | ||||
|     return streamdata->stream_index - 2; | ||||
|   else | ||||
|     return streamdata->stream_index - 1; | ||||
| } | ||||
| @@ -0,0 +1,294 @@ | ||||
| /* | ||||
|  *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. | ||||
|  * | ||||
|  *  Use of this source code is governed by a BSD-style license | ||||
|  *  that can be found in the LICENSE file in the root of the source | ||||
|  *  tree. An additional intellectual property rights grant can be found | ||||
|  *  in the file PATENTS.  All contributing project authors may | ||||
|  *  be found in the AUTHORS file in the root of the source tree. | ||||
|  */ | ||||
|  | ||||
| /* | ||||
|  * arith_routines.h | ||||
|  * | ||||
|  * This file contains functions for arithmatically encoding and | ||||
|  * decoding DFT coefficients. | ||||
|  * | ||||
|  */ | ||||
|  | ||||
|  | ||||
| #include "arith_routines.h" | ||||
|  | ||||
|  | ||||
|  | ||||
| static const int32_t kHistEdgesQ15[51] = { | ||||
|   -327680, -314573, -301466, -288359, -275252, -262144, -249037, -235930, -222823, -209716, | ||||
|   -196608, -183501, -170394, -157287, -144180, -131072, -117965, -104858, -91751, -78644, | ||||
|   -65536, -52429, -39322, -26215, -13108,  0,  13107,  26214,  39321,  52428, | ||||
|   65536,  78643,  91750,  104857,  117964,  131072,  144179,  157286,  170393,  183500, | ||||
|   196608,  209715,  222822,  235929,  249036,  262144,  275251,  288358,  301465,  314572, | ||||
|   327680}; | ||||
|  | ||||
|  | ||||
| static const int kCdfSlopeQ0[51] = {  /* Q0 */ | ||||
|   5,  5,  5,  5,  5,  5,  5,  5,  5,  5, | ||||
|   5,  5,  13,  23,  47,  87,  154,  315,  700,  1088, | ||||
|   2471,  6064,  14221,  21463,  36634,  36924,  19750,  13270,  5806,  2312, | ||||
|   1095,  660,  316,  145,  86,  41,  32,  5,  5,  5, | ||||
|   5,  5,  5,  5,  5,  5,  5,  5,  5,  2, 0}; | ||||
|  | ||||
|  | ||||
| static const int kCdfQ16[51] = {  /* Q16 */ | ||||
|   0,  2,  4,  6,  8,  10,  12,  14,  16,  18, | ||||
|   20,  22,  24,  29,  38,  57,  92,  153,  279,  559, | ||||
|   994,  1983,  4408,  10097,  18682,  33336,  48105,  56005,  61313,  63636, | ||||
|   64560,  64998,  65262,  65389,  65447,  65481,  65497,  65510,  65512,  65514, | ||||
|   65516,  65518,  65520,  65522,  65524,  65526,  65528,  65530,  65532,  65534, | ||||
|   65535}; | ||||
|  | ||||
|  | ||||
|  | ||||
| /* function to be converted to fixed point */ | ||||
| static __inline uint32_t piecewise(int32_t xinQ15) { | ||||
|  | ||||
|   int32_t ind, qtmp1, qtmp2, qtmp3; | ||||
|   uint32_t tmpUW32; | ||||
|  | ||||
|  | ||||
|   qtmp2 = xinQ15; | ||||
|  | ||||
|   if (qtmp2 < kHistEdgesQ15[0]) { | ||||
|     qtmp2 = kHistEdgesQ15[0]; | ||||
|   } | ||||
|   if (qtmp2 > kHistEdgesQ15[50]) { | ||||
|     qtmp2 = kHistEdgesQ15[50]; | ||||
|   } | ||||
|  | ||||
|   qtmp1 = qtmp2 - kHistEdgesQ15[0];       /* Q15 - Q15 = Q15        */ | ||||
|   ind = (qtmp1 * 5) >> 16;              /* 2^16 / 5 = 0.4 in Q15  */ | ||||
|   /* Q15 -> Q0              */ | ||||
|   qtmp1 = qtmp2 - kHistEdgesQ15[ind];     /* Q15 - Q15 = Q15        */ | ||||
|   qtmp2 = kCdfSlopeQ0[ind] * qtmp1;      /* Q0 * Q15 = Q15         */ | ||||
|   qtmp3 = qtmp2>>15;                    /* Q15 -> Q0              */ | ||||
|  | ||||
|   tmpUW32 = kCdfQ16[ind] + qtmp3;    /* Q0 + Q0 = Q0           */ | ||||
|   return tmpUW32; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| int WebRtcIsac_EncLogisticMulti2( | ||||
|     Bitstr *streamdata,      /* in-/output struct containing bitstream */ | ||||
|     int16_t *dataQ7,    /* input: data vector */ | ||||
|     const uint16_t *envQ8, /* input: side info vector defining the width of the pdf */ | ||||
|     const int N,       /* input: data vector length / 2 */ | ||||
|     const int16_t isSWB12kHz) | ||||
| { | ||||
|   uint32_t W_lower, W_upper; | ||||
|   uint32_t W_upper_LSB, W_upper_MSB; | ||||
|   uint8_t *stream_ptr; | ||||
|   uint8_t *maxStreamPtr; | ||||
|   uint8_t *stream_ptr_carry; | ||||
|   uint32_t cdf_lo, cdf_hi; | ||||
|   int k; | ||||
|  | ||||
|   /* point to beginning of stream buffer */ | ||||
|   stream_ptr = streamdata->stream + streamdata->stream_index; | ||||
|   W_upper = streamdata->W_upper; | ||||
|  | ||||
|   maxStreamPtr = streamdata->stream + STREAM_SIZE_MAX_60 - 1; | ||||
|   for (k = 0; k < N; k++) | ||||
|   { | ||||
|     /* compute cdf_lower and cdf_upper by evaluating the piecewise linear cdf */ | ||||
|     cdf_lo = piecewise((*dataQ7 - 64) * *envQ8); | ||||
|     cdf_hi = piecewise((*dataQ7 + 64) * *envQ8); | ||||
|  | ||||
|     /* test and clip if probability gets too small */ | ||||
|     while (cdf_lo+1 >= cdf_hi) { | ||||
|       /* clip */ | ||||
|       if (*dataQ7 > 0) { | ||||
|         *dataQ7 -= 128; | ||||
|         cdf_hi = cdf_lo; | ||||
|         cdf_lo = piecewise((*dataQ7 - 64) * *envQ8); | ||||
|       } else { | ||||
|         *dataQ7 += 128; | ||||
|         cdf_lo = cdf_hi; | ||||
|         cdf_hi = piecewise((*dataQ7 + 64) * *envQ8); | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     dataQ7++; | ||||
|     // increment only once per 4 iterations for SWB-16kHz or WB | ||||
|     // increment only once per 2 iterations for SWB-12kHz | ||||
|     envQ8 += (isSWB12kHz)? (k & 1):((k & 1) & (k >> 1)); | ||||
|  | ||||
|  | ||||
|     /* update interval */ | ||||
|     W_upper_LSB = W_upper & 0x0000FFFF; | ||||
|     W_upper_MSB = W_upper >> 16; | ||||
|     W_lower = W_upper_MSB * cdf_lo; | ||||
|     W_lower += (W_upper_LSB * cdf_lo) >> 16; | ||||
|     W_upper = W_upper_MSB * cdf_hi; | ||||
|     W_upper += (W_upper_LSB * cdf_hi) >> 16; | ||||
|  | ||||
|     /* shift interval such that it begins at zero */ | ||||
|     W_upper -= ++W_lower; | ||||
|  | ||||
|     /* add integer to bitstream */ | ||||
|     streamdata->streamval += W_lower; | ||||
|  | ||||
|     /* handle carry */ | ||||
|     if (streamdata->streamval < W_lower) | ||||
|     { | ||||
|       /* propagate carry */ | ||||
|       stream_ptr_carry = stream_ptr; | ||||
|       while (!(++(*--stream_ptr_carry))); | ||||
|     } | ||||
|  | ||||
|     /* renormalize interval, store most significant byte of streamval and update streamval */ | ||||
|     while ( !(W_upper & 0xFF000000) )      /* W_upper < 2^24 */ | ||||
|     { | ||||
|       W_upper <<= 8; | ||||
|       *stream_ptr++ = (uint8_t) (streamdata->streamval >> 24); | ||||
|  | ||||
|       if(stream_ptr > maxStreamPtr) | ||||
|       { | ||||
|         return -ISAC_DISALLOWED_BITSTREAM_LENGTH; | ||||
|       } | ||||
|       streamdata->streamval <<= 8; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   /* calculate new stream_index */ | ||||
|   streamdata->stream_index = (int)(stream_ptr - streamdata->stream); | ||||
|   streamdata->W_upper = W_upper; | ||||
|  | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| int WebRtcIsac_DecLogisticMulti2( | ||||
|     int16_t *dataQ7,       /* output: data vector */ | ||||
|     Bitstr *streamdata,      /* in-/output struct containing bitstream */ | ||||
|     const uint16_t *envQ8, /* input: side info vector defining the width of the pdf */ | ||||
|     const int16_t *ditherQ7,/* input: dither vector */ | ||||
|     const int N,         /* input: data vector length */ | ||||
|     const int16_t isSWB12kHz) | ||||
| { | ||||
|   uint32_t    W_lower, W_upper; | ||||
|   uint32_t    W_tmp; | ||||
|   uint32_t    W_upper_LSB, W_upper_MSB; | ||||
|   uint32_t    streamval; | ||||
|   const uint8_t *stream_ptr; | ||||
|   uint32_t    cdf_tmp; | ||||
|   int16_t     candQ7; | ||||
|   int             k; | ||||
|  | ||||
|   stream_ptr = streamdata->stream + streamdata->stream_index; | ||||
|   W_upper = streamdata->W_upper; | ||||
|   if (streamdata->stream_index == 0)   /* first time decoder is called for this stream */ | ||||
|   { | ||||
|     /* read first word from bytestream */ | ||||
|     streamval = *stream_ptr << 24; | ||||
|     streamval |= *++stream_ptr << 16; | ||||
|     streamval |= *++stream_ptr << 8; | ||||
|     streamval |= *++stream_ptr; | ||||
|   } else { | ||||
|     streamval = streamdata->streamval; | ||||
|   } | ||||
|  | ||||
|  | ||||
|   for (k = 0; k < N; k++) | ||||
|   { | ||||
|     /* find the integer *data for which streamval lies in [W_lower+1, W_upper] */ | ||||
|     W_upper_LSB = W_upper & 0x0000FFFF; | ||||
|     W_upper_MSB = W_upper >> 16; | ||||
|  | ||||
|     /* find first candidate by inverting the logistic cdf */ | ||||
|     candQ7 = - *ditherQ7 + 64; | ||||
|     cdf_tmp = piecewise(candQ7 * *envQ8); | ||||
|  | ||||
|     W_tmp = W_upper_MSB * cdf_tmp; | ||||
|     W_tmp += (W_upper_LSB * cdf_tmp) >> 16; | ||||
|     if (streamval > W_tmp) | ||||
|     { | ||||
|       W_lower = W_tmp; | ||||
|       candQ7 += 128; | ||||
|       cdf_tmp = piecewise(candQ7 * *envQ8); | ||||
|  | ||||
|       W_tmp = W_upper_MSB * cdf_tmp; | ||||
|       W_tmp += (W_upper_LSB * cdf_tmp) >> 16; | ||||
|       while (streamval > W_tmp) | ||||
|       { | ||||
|         W_lower = W_tmp; | ||||
|         candQ7 += 128; | ||||
|         cdf_tmp = piecewise(candQ7 * *envQ8); | ||||
|  | ||||
|         W_tmp = W_upper_MSB * cdf_tmp; | ||||
|         W_tmp += (W_upper_LSB * cdf_tmp) >> 16; | ||||
|  | ||||
|         /* error check */ | ||||
|         if (W_lower == W_tmp) return -1; | ||||
|       } | ||||
|       W_upper = W_tmp; | ||||
|  | ||||
|       /* another sample decoded */ | ||||
|       *dataQ7 = candQ7 - 64; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|       W_upper = W_tmp; | ||||
|       candQ7 -= 128; | ||||
|       cdf_tmp = piecewise(candQ7 * *envQ8); | ||||
|  | ||||
|       W_tmp = W_upper_MSB * cdf_tmp; | ||||
|       W_tmp += (W_upper_LSB * cdf_tmp) >> 16; | ||||
|       while ( !(streamval > W_tmp) ) | ||||
|       { | ||||
|         W_upper = W_tmp; | ||||
|         candQ7 -= 128; | ||||
|         cdf_tmp = piecewise(candQ7 * *envQ8); | ||||
|  | ||||
|         W_tmp = W_upper_MSB * cdf_tmp; | ||||
|         W_tmp += (W_upper_LSB * cdf_tmp) >> 16; | ||||
|  | ||||
|         /* error check */ | ||||
|         if (W_upper == W_tmp) return -1; | ||||
|       } | ||||
|       W_lower = W_tmp; | ||||
|  | ||||
|       /* another sample decoded */ | ||||
|       *dataQ7 = candQ7 + 64; | ||||
|     } | ||||
|     ditherQ7++; | ||||
|     dataQ7++; | ||||
|     // increment only once per 4 iterations for SWB-16kHz or WB | ||||
|     // increment only once per 2 iterations for SWB-12kHz | ||||
|     envQ8 += (isSWB12kHz)? (k & 1):((k & 1) & (k >> 1)); | ||||
|  | ||||
|     /* shift interval to start at zero */ | ||||
|     W_upper -= ++W_lower; | ||||
|  | ||||
|     /* add integer to bitstream */ | ||||
|     streamval -= W_lower; | ||||
|  | ||||
|     /* renormalize interval and update streamval */ | ||||
|     while ( !(W_upper & 0xFF000000) )    /* W_upper < 2^24 */ | ||||
|     { | ||||
|       /* read next byte from stream */ | ||||
|       streamval = (streamval << 8) | *++stream_ptr; | ||||
|       W_upper <<= 8; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   streamdata->stream_index = (int)(stream_ptr - streamdata->stream); | ||||
|   streamdata->W_upper = W_upper; | ||||
|   streamdata->streamval = streamval; | ||||
|  | ||||
|   /* find number of bytes in original stream (determined by current interval width) */ | ||||
|   if ( W_upper > 0x01FFFFFF ) | ||||
|     return streamdata->stream_index - 2; | ||||
|   else | ||||
|     return streamdata->stream_index - 1; | ||||
| } | ||||
| @@ -0,0 +1,263 @@ | ||||
| /* | ||||
|  *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. | ||||
|  * | ||||
|  *  Use of this source code is governed by a BSD-style license | ||||
|  *  that can be found in the LICENSE file in the root of the source | ||||
|  *  tree. An additional intellectual property rights grant can be found | ||||
|  *  in the file PATENTS.  All contributing project authors may | ||||
|  *  be found in the AUTHORS file in the root of the source tree. | ||||
|  */ | ||||
|  | ||||
| #include <memory.h> | ||||
| #include <string.h> | ||||
| #ifdef WEBRTC_ANDROID | ||||
| #include <stdlib.h> | ||||
| #endif | ||||
| #include "pitch_estimator.h" | ||||
| #include "lpc_analysis.h" | ||||
| #include "codec.h" | ||||
|  | ||||
|  | ||||
|  | ||||
| void WebRtcIsac_AllPoleFilter(double* InOut, | ||||
|                               double* Coef, | ||||
|                               size_t lengthInOut, | ||||
|                               int orderCoef) { | ||||
|   /* the state of filter is assumed to be in InOut[-1] to InOut[-orderCoef] */ | ||||
|   double scal; | ||||
|   double sum; | ||||
|   size_t n; | ||||
|   int k; | ||||
|  | ||||
|   //if (fabs(Coef[0]-1.0)<0.001) { | ||||
|   if ( (Coef[0] > 0.9999) && (Coef[0] < 1.0001) ) | ||||
|   { | ||||
|     for(n = 0; n < lengthInOut; n++) | ||||
|     { | ||||
|       sum = Coef[1] * InOut[-1]; | ||||
|       for(k = 2; k <= orderCoef; k++){ | ||||
|         sum += Coef[k] * InOut[-k]; | ||||
|       } | ||||
|       *InOut++ -= sum; | ||||
|     } | ||||
|   } | ||||
|   else | ||||
|   { | ||||
|     scal = 1.0 / Coef[0]; | ||||
|     for(n=0;n<lengthInOut;n++) | ||||
|     { | ||||
|       *InOut *= scal; | ||||
|       for(k=1;k<=orderCoef;k++){ | ||||
|         *InOut -= scal*Coef[k]*InOut[-k]; | ||||
|       } | ||||
|       InOut++; | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
|  | ||||
| void WebRtcIsac_AllZeroFilter(double* In, | ||||
|                               double* Coef, | ||||
|                               size_t lengthInOut, | ||||
|                               int orderCoef, | ||||
|                               double* Out) { | ||||
|   /* the state of filter is assumed to be in In[-1] to In[-orderCoef] */ | ||||
|  | ||||
|   size_t n; | ||||
|   int k; | ||||
|   double tmp; | ||||
|  | ||||
|   for(n = 0; n < lengthInOut; n++) | ||||
|   { | ||||
|     tmp = In[0] * Coef[0]; | ||||
|  | ||||
|     for(k = 1; k <= orderCoef; k++){ | ||||
|       tmp += Coef[k] * In[-k]; | ||||
|     } | ||||
|  | ||||
|     *Out++ = tmp; | ||||
|     In++; | ||||
|   } | ||||
| } | ||||
|  | ||||
|  | ||||
| void WebRtcIsac_ZeroPoleFilter(double* In, | ||||
|                                double* ZeroCoef, | ||||
|                                double* PoleCoef, | ||||
|                                size_t lengthInOut, | ||||
|                                int orderCoef, | ||||
|                                double* Out) { | ||||
|   /* the state of the zero section is assumed to be in In[-1] to In[-orderCoef] */ | ||||
|   /* the state of the pole section is assumed to be in Out[-1] to Out[-orderCoef] */ | ||||
|  | ||||
|   WebRtcIsac_AllZeroFilter(In,ZeroCoef,lengthInOut,orderCoef,Out); | ||||
|   WebRtcIsac_AllPoleFilter(Out,PoleCoef,lengthInOut,orderCoef); | ||||
| } | ||||
|  | ||||
|  | ||||
| void WebRtcIsac_AutoCorr(double* r, const double* x, size_t N, size_t order) { | ||||
|   size_t  lag, n; | ||||
|   double sum, prod; | ||||
|   const double *x_lag; | ||||
|  | ||||
|   for (lag = 0; lag <= order; lag++) | ||||
|   { | ||||
|     sum = 0.0f; | ||||
|     x_lag = &x[lag]; | ||||
|     prod = x[0] * x_lag[0]; | ||||
|     for (n = 1; n < N - lag; n++) { | ||||
|       sum += prod; | ||||
|       prod = x[n] * x_lag[n]; | ||||
|     } | ||||
|     sum += prod; | ||||
|     r[lag] = sum; | ||||
|   } | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
| void WebRtcIsac_BwExpand(double* out, double* in, double coef, size_t length) { | ||||
|   size_t i; | ||||
|   double  chirp; | ||||
|  | ||||
|   chirp = coef; | ||||
|  | ||||
|   out[0] = in[0]; | ||||
|   for (i = 1; i < length; i++) { | ||||
|     out[i] = chirp * in[i]; | ||||
|     chirp *= coef; | ||||
|   } | ||||
| } | ||||
|  | ||||
| void WebRtcIsac_WeightingFilter(const double* in, | ||||
|                                 double* weiout, | ||||
|                                 double* whiout, | ||||
|                                 WeightFiltstr* wfdata) { | ||||
|   double  tmpbuffer[PITCH_FRAME_LEN + PITCH_WLPCBUFLEN]; | ||||
|   double  corr[PITCH_WLPCORDER+1], rc[PITCH_WLPCORDER+1]; | ||||
|   double apol[PITCH_WLPCORDER+1], apolr[PITCH_WLPCORDER+1]; | ||||
|   double  rho=0.9, *inp, *dp, *dp2; | ||||
|   double  whoutbuf[PITCH_WLPCBUFLEN + PITCH_WLPCORDER]; | ||||
|   double  weoutbuf[PITCH_WLPCBUFLEN + PITCH_WLPCORDER]; | ||||
|   double  *weo, *who, opol[PITCH_WLPCORDER+1], ext[PITCH_WLPCWINLEN]; | ||||
|   int     k, n, endpos, start; | ||||
|  | ||||
|   /* Set up buffer and states */ | ||||
|   memcpy(tmpbuffer, wfdata->buffer, sizeof(double) * PITCH_WLPCBUFLEN); | ||||
|   memcpy(tmpbuffer+PITCH_WLPCBUFLEN, in, sizeof(double) * PITCH_FRAME_LEN); | ||||
|   memcpy(wfdata->buffer, tmpbuffer+PITCH_FRAME_LEN, sizeof(double) * PITCH_WLPCBUFLEN); | ||||
|  | ||||
|   dp=weoutbuf; | ||||
|   dp2=whoutbuf; | ||||
|   for (k=0;k<PITCH_WLPCORDER;k++) { | ||||
|     *dp++ = wfdata->weostate[k]; | ||||
|     *dp2++ = wfdata->whostate[k]; | ||||
|     opol[k]=0.0; | ||||
|   } | ||||
|   opol[0]=1.0; | ||||
|   opol[PITCH_WLPCORDER]=0.0; | ||||
|   weo=dp; | ||||
|   who=dp2; | ||||
|  | ||||
|   endpos=PITCH_WLPCBUFLEN + PITCH_SUBFRAME_LEN; | ||||
|   inp=tmpbuffer + PITCH_WLPCBUFLEN; | ||||
|  | ||||
|   for (n=0; n<PITCH_SUBFRAMES; n++) { | ||||
|     /* Windowing */ | ||||
|     start=endpos-PITCH_WLPCWINLEN; | ||||
|     for (k=0; k<PITCH_WLPCWINLEN; k++) { | ||||
|       ext[k]=wfdata->window[k]*tmpbuffer[start+k]; | ||||
|     } | ||||
|  | ||||
|     /* Get LPC polynomial */ | ||||
|     WebRtcIsac_AutoCorr(corr, ext, PITCH_WLPCWINLEN, PITCH_WLPCORDER); | ||||
|     corr[0]=1.01*corr[0]+1.0; /* White noise correction */ | ||||
|     WebRtcIsac_LevDurb(apol, rc, corr, PITCH_WLPCORDER); | ||||
|     WebRtcIsac_BwExpand(apolr, apol, rho, PITCH_WLPCORDER+1); | ||||
|  | ||||
|     /* Filtering */ | ||||
|     WebRtcIsac_ZeroPoleFilter(inp, apol, apolr, PITCH_SUBFRAME_LEN, PITCH_WLPCORDER, weo); | ||||
|     WebRtcIsac_ZeroPoleFilter(inp, apolr, opol, PITCH_SUBFRAME_LEN, PITCH_WLPCORDER, who); | ||||
|  | ||||
|     inp+=PITCH_SUBFRAME_LEN; | ||||
|     endpos+=PITCH_SUBFRAME_LEN; | ||||
|     weo+=PITCH_SUBFRAME_LEN; | ||||
|     who+=PITCH_SUBFRAME_LEN; | ||||
|   } | ||||
|  | ||||
|   /* Export filter states */ | ||||
|   for (k=0;k<PITCH_WLPCORDER;k++) { | ||||
|     wfdata->weostate[k]=weoutbuf[PITCH_FRAME_LEN+k]; | ||||
|     wfdata->whostate[k]=whoutbuf[PITCH_FRAME_LEN+k]; | ||||
|   } | ||||
|  | ||||
|   /* Export output data */ | ||||
|   memcpy(weiout, weoutbuf+PITCH_WLPCORDER, sizeof(double) * PITCH_FRAME_LEN); | ||||
|   memcpy(whiout, whoutbuf+PITCH_WLPCORDER, sizeof(double) * PITCH_FRAME_LEN); | ||||
| } | ||||
|  | ||||
|  | ||||
| static const double APupper[ALLPASSSECTIONS] = {0.0347, 0.3826}; | ||||
| static const double APlower[ALLPASSSECTIONS] = {0.1544, 0.744}; | ||||
|  | ||||
|  | ||||
| void WebRtcIsac_AllpassFilterForDec(double* InOut, | ||||
|                                     const double* APSectionFactors, | ||||
|                                     size_t lengthInOut, | ||||
|                                     double* FilterState) { | ||||
|   //This performs all-pass filtering--a series of first order all-pass sections are used | ||||
|   //to filter the input in a cascade manner. | ||||
|   size_t n,j; | ||||
|   double temp; | ||||
|   for (j=0; j<ALLPASSSECTIONS; j++){ | ||||
|     for (n=0;n<lengthInOut;n+=2){ | ||||
|       temp = InOut[n]; //store input | ||||
|       InOut[n] = FilterState[j] + APSectionFactors[j]*temp; | ||||
|       FilterState[j] = -APSectionFactors[j]*InOut[n] + temp; | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| void WebRtcIsac_DecimateAllpass(const double* in, | ||||
|                                 double* state_in, | ||||
|                                 size_t N, | ||||
|                                 double* out) { | ||||
|   size_t n; | ||||
|   double data_vec[PITCH_FRAME_LEN]; | ||||
|  | ||||
|   /* copy input */ | ||||
|   memcpy(data_vec+1, in, sizeof(double) * (N-1)); | ||||
|  | ||||
|   data_vec[0] = state_in[2*ALLPASSSECTIONS];   //the z^(-1) state | ||||
|   state_in[2*ALLPASSSECTIONS] = in[N-1]; | ||||
|  | ||||
|   WebRtcIsac_AllpassFilterForDec(data_vec+1, APupper, N, state_in); | ||||
|   WebRtcIsac_AllpassFilterForDec(data_vec, APlower, N, state_in+ALLPASSSECTIONS); | ||||
|  | ||||
|   for (n=0;n<N/2;n++) | ||||
|     out[n] = data_vec[2*n] + data_vec[2*n+1]; | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
| /* create high-pass filter ocefficients | ||||
|  * z = 0.998 * exp(j*2*pi*35/8000); | ||||
|  * p = 0.94 * exp(j*2*pi*140/8000); | ||||
|  * HP_b = [1, -2*real(z), abs(z)^2]; | ||||
|  * HP_a = [1, -2*real(p), abs(p)^2]; */ | ||||
| static const double a_coef[2] = { 1.86864659625574, -0.88360000000000}; | ||||
| static const double b_coef[2] = {-1.99524591718270,  0.99600400000000}; | ||||
|  | ||||
| /* second order high-pass filter */ | ||||
| void WebRtcIsac_Highpass(const double* in, | ||||
|                          double* out, | ||||
|                          double* state, | ||||
|                          size_t N) { | ||||
|   size_t k; | ||||
|  | ||||
|   for (k=0; k<N; k++) { | ||||
|     *out = *in + state[1]; | ||||
|     state[1] = state[0] + b_coef[0] * *in + a_coef[0] * *out; | ||||
|     state[0] = b_coef[1] * *in++ + a_coef[1] * *out++; | ||||
|   } | ||||
| } | ||||
| @@ -0,0 +1,37 @@ | ||||
| /* | ||||
|  *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. | ||||
|  * | ||||
|  *  Use of this source code is governed by a BSD-style license | ||||
|  *  that can be found in the LICENSE file in the root of the source | ||||
|  *  tree. An additional intellectual property rights grant can be found | ||||
|  *  in the file PATENTS.  All contributing project authors may | ||||
|  *  be found in the AUTHORS file in the root of the source tree. | ||||
|  */ | ||||
|  | ||||
| /* filterbank_tables.c*/ | ||||
| /* This file contains variables that are used in filterbanks.c*/ | ||||
|  | ||||
| #include "filterbank_tables.h" | ||||
| #include "settings.h" | ||||
|  | ||||
| /* The composite all-pass filter factors */ | ||||
| const float WebRtcIsac_kCompositeApFactorsFloat[4] = { | ||||
|  0.03470000000000f,  0.15440000000000f,  0.38260000000000f,  0.74400000000000f}; | ||||
|  | ||||
| /* The upper channel all-pass filter factors */ | ||||
| const float WebRtcIsac_kUpperApFactorsFloat[2] = { | ||||
|  0.03470000000000f,  0.38260000000000f}; | ||||
|  | ||||
| /* The lower channel all-pass filter factors */ | ||||
| const float WebRtcIsac_kLowerApFactorsFloat[2] = { | ||||
|  0.15440000000000f,  0.74400000000000f}; | ||||
|  | ||||
| /* The matrix for transforming the backward composite state to upper channel state */ | ||||
| const float WebRtcIsac_kTransform1Float[8] = { | ||||
|   -0.00158678506084f,  0.00127157815343f, -0.00104805672709f,  0.00084837248079f, | ||||
|   0.00134467983258f, -0.00107756549387f,  0.00088814793277f, -0.00071893072525f}; | ||||
|  | ||||
| /* The matrix for transforming the backward composite state to lower channel state */ | ||||
| const float WebRtcIsac_kTransform2Float[8] = { | ||||
|  -0.00170686041697f,  0.00136780109829f, -0.00112736532350f,  0.00091257055385f, | ||||
|   0.00103094281812f, -0.00082615076557f,  0.00068092756088f, -0.00055119165484f}; | ||||
| @@ -0,0 +1,46 @@ | ||||
| /* | ||||
|  *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. | ||||
|  * | ||||
|  *  Use of this source code is governed by a BSD-style license | ||||
|  *  that can be found in the LICENSE file in the root of the source | ||||
|  *  tree. An additional intellectual property rights grant can be found | ||||
|  *  in the file PATENTS.  All contributing project authors may | ||||
|  *  be found in the AUTHORS file in the root of the source tree. | ||||
|  */ | ||||
|  | ||||
| /* | ||||
|  * filterbank_tables.h | ||||
|  * | ||||
|  * Header file for variables that are defined in | ||||
|  * filterbank_tables.c. | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_FILTERBANK_TABLES_H_ | ||||
| #define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_FILTERBANK_TABLES_H_ | ||||
|  | ||||
| #include "structs.h" | ||||
|  | ||||
| /********************* Coefficient Tables ************************/ | ||||
| /* The number of composite all-pass filter factors */ | ||||
| #define NUMBEROFCOMPOSITEAPSECTIONS 4 | ||||
|  | ||||
| /* The number of all-pass filter factors in an upper or lower channel*/ | ||||
| #define NUMBEROFCHANNELAPSECTIONS 2 | ||||
|  | ||||
| /* The composite all-pass filter factors */ | ||||
| extern const float WebRtcIsac_kCompositeApFactorsFloat[4]; | ||||
|  | ||||
| /* The upper channel all-pass filter factors */ | ||||
| extern const float WebRtcIsac_kUpperApFactorsFloat[2]; | ||||
|  | ||||
| /* The lower channel all-pass filter factors */ | ||||
| extern const float WebRtcIsac_kLowerApFactorsFloat[2]; | ||||
|  | ||||
| /* The matrix for transforming the backward composite state to upper channel state */ | ||||
| extern const float WebRtcIsac_kTransform1Float[8]; | ||||
|  | ||||
| /* The matrix for transforming the backward composite state to lower channel state */ | ||||
| extern const float WebRtcIsac_kTransform2Float[8]; | ||||
|  | ||||
| #endif /* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_FILTERBANK_TABLES_H_ */ | ||||
| @@ -0,0 +1,346 @@ | ||||
| /* | ||||
|  *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. | ||||
|  * | ||||
|  *  Use of this source code is governed by a BSD-style license | ||||
|  *  that can be found in the LICENSE file in the root of the source | ||||
|  *  tree. An additional intellectual property rights grant can be found | ||||
|  *  in the file PATENTS.  All contributing project authors may | ||||
|  *  be found in the AUTHORS file in the root of the source tree. | ||||
|  */ | ||||
|  | ||||
| /* | ||||
|  * filterbanks.c | ||||
|  * | ||||
|  * This file contains function WebRtcIsac_AllPassFilter2Float, | ||||
|  * WebRtcIsac_SplitAndFilter, and WebRtcIsac_FilterAndCombine | ||||
|  * which implement filterbanks that produce decimated lowpass and | ||||
|  * highpass versions of a signal, and performs reconstruction. | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #include "settings.h" | ||||
| #include "filterbank_tables.h" | ||||
| #include "codec.h" | ||||
|  | ||||
| /* This function performs all-pass filtering--a series of first order all-pass | ||||
|  * sections are used to filter the input in a cascade manner. | ||||
|  * The input is overwritten!! | ||||
|  */ | ||||
| static void WebRtcIsac_AllPassFilter2Float(float *InOut, const float *APSectionFactors, | ||||
|                                            int lengthInOut, int NumberOfSections, | ||||
|                                            float *FilterState) | ||||
| { | ||||
|   int n, j; | ||||
|   float temp; | ||||
|   for (j=0; j<NumberOfSections; j++){ | ||||
|     for (n=0;n<lengthInOut;n++){ | ||||
|       temp = FilterState[j] + APSectionFactors[j] * InOut[n]; | ||||
|       FilterState[j] = -APSectionFactors[j] * temp + InOut[n]; | ||||
|       InOut[n] = temp; | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| /* HPstcoeff_in = {a1, a2, b1 - b0 * a1, b2 - b0 * a2}; */ | ||||
| static const float kHpStCoefInFloat[4] = | ||||
| {-1.94895953203325f, 0.94984516000000f, -0.05101826139794f, 0.05015484000000f}; | ||||
|  | ||||
| /* Function WebRtcIsac_SplitAndFilter | ||||
|  * This function creates low-pass and high-pass decimated versions of part of | ||||
|  the input signal, and part of the signal in the input 'lookahead buffer'. | ||||
|  | ||||
|  INPUTS: | ||||
|  in: a length FRAMESAMPLES array of input samples | ||||
|  prefiltdata: input data structure containing the filterbank states | ||||
|  and lookahead samples from the previous encoding | ||||
|  iteration. | ||||
|  OUTPUTS: | ||||
|  LP: a FRAMESAMPLES_HALF array of low-pass filtered samples that | ||||
|  have been phase equalized.  The first QLOOKAHEAD samples are | ||||
|  based on the samples in the two prefiltdata->INLABUFx arrays | ||||
|  each of length QLOOKAHEAD. | ||||
|  The remaining FRAMESAMPLES_HALF-QLOOKAHEAD samples are based | ||||
|  on the first FRAMESAMPLES_HALF-QLOOKAHEAD samples of the input | ||||
|  array in[]. | ||||
|  HP: a FRAMESAMPLES_HALF array of high-pass filtered samples that | ||||
|  have been phase equalized.  The first QLOOKAHEAD samples are | ||||
|  based on the samples in the two prefiltdata->INLABUFx arrays | ||||
|  each of length QLOOKAHEAD. | ||||
|  The remaining FRAMESAMPLES_HALF-QLOOKAHEAD samples are based | ||||
|  on the first FRAMESAMPLES_HALF-QLOOKAHEAD samples of the input | ||||
|  array in[]. | ||||
|  | ||||
|  LP_la: a FRAMESAMPLES_HALF array of low-pass filtered samples. | ||||
|  These samples are not phase equalized. They are computed | ||||
|  from the samples in the in[] array. | ||||
|  HP_la: a FRAMESAMPLES_HALF array of high-pass filtered samples | ||||
|  that are not phase equalized. They are computed from | ||||
|  the in[] vector. | ||||
|  prefiltdata: this input data structure's filterbank state and | ||||
|  lookahead sample buffers are updated for the next | ||||
|  encoding iteration. | ||||
| */ | ||||
| void WebRtcIsac_SplitAndFilterFloat(float *pin, float *LP, float *HP, | ||||
|                                     double *LP_la, double *HP_la, | ||||
|                                     PreFiltBankstr *prefiltdata) | ||||
| { | ||||
|   int k,n; | ||||
|   float CompositeAPFilterState[NUMBEROFCOMPOSITEAPSECTIONS]; | ||||
|   float ForTransform_CompositeAPFilterState[NUMBEROFCOMPOSITEAPSECTIONS]; | ||||
|   float ForTransform_CompositeAPFilterState2[NUMBEROFCOMPOSITEAPSECTIONS]; | ||||
|   float tempinoutvec[FRAMESAMPLES+MAX_AR_MODEL_ORDER]; | ||||
|   float tempin_ch1[FRAMESAMPLES+MAX_AR_MODEL_ORDER]; | ||||
|   float tempin_ch2[FRAMESAMPLES+MAX_AR_MODEL_ORDER]; | ||||
|   float in[FRAMESAMPLES]; | ||||
|   float ftmp; | ||||
|  | ||||
|  | ||||
|   /* High pass filter */ | ||||
|  | ||||
|   for (k=0;k<FRAMESAMPLES;k++) { | ||||
|     in[k] = pin[k] + kHpStCoefInFloat[2] * prefiltdata->HPstates_float[0] + | ||||
|         kHpStCoefInFloat[3] * prefiltdata->HPstates_float[1]; | ||||
|     ftmp = pin[k] - kHpStCoefInFloat[0] * prefiltdata->HPstates_float[0] - | ||||
|         kHpStCoefInFloat[1] * prefiltdata->HPstates_float[1]; | ||||
|     prefiltdata->HPstates_float[1] = prefiltdata->HPstates_float[0]; | ||||
|     prefiltdata->HPstates_float[0] = ftmp; | ||||
|   } | ||||
|  | ||||
|   /* | ||||
|     % backwards all-pass filtering to obtain zero-phase | ||||
|     [tmp1(N2+LA:-1:LA+1, 1), state1] = filter(Q.coef, Q.coef(end:-1:1), in(N:-2:2)); | ||||
|     tmp1(LA:-1:1) = filter(Q.coef, Q.coef(end:-1:1), Q.LookAheadBuf1, state1); | ||||
|     Q.LookAheadBuf1 = in(N:-2:N-2*LA+2); | ||||
|   */ | ||||
|   /*Backwards all-pass filter the odd samples of the input (upper channel) | ||||
|     to eventually obtain zero phase.  The composite all-pass filter (comprised of both | ||||
|     the upper and lower channel all-pass filsters in series) is used for the | ||||
|     filtering. */ | ||||
|  | ||||
|   /* First Channel */ | ||||
|  | ||||
|   /*initial state of composite filter is zero */ | ||||
|   for (k=0;k<NUMBEROFCOMPOSITEAPSECTIONS;k++){ | ||||
|     CompositeAPFilterState[k] = 0.0; | ||||
|   } | ||||
|   /* put every other sample of input into a temporary vector in reverse (backward) order*/ | ||||
|   for (k=0;k<FRAMESAMPLES_HALF;k++) { | ||||
|     tempinoutvec[k] = in[FRAMESAMPLES-1-2*k]; | ||||
|   } | ||||
|  | ||||
|   /* now all-pass filter the backwards vector.  Output values overwrite the input vector. */ | ||||
|   WebRtcIsac_AllPassFilter2Float(tempinoutvec, WebRtcIsac_kCompositeApFactorsFloat, | ||||
|                                  FRAMESAMPLES_HALF, NUMBEROFCOMPOSITEAPSECTIONS, CompositeAPFilterState); | ||||
|  | ||||
|   /* save the backwards filtered output for later forward filtering, | ||||
|      but write it in forward order*/ | ||||
|   for (k=0;k<FRAMESAMPLES_HALF;k++) { | ||||
|     tempin_ch1[FRAMESAMPLES_HALF+QLOOKAHEAD-1-k] = tempinoutvec[k]; | ||||
|   } | ||||
|  | ||||
|   /* save the backwards filter state  becaue it will be transformed | ||||
|      later into a forward state */ | ||||
|   for (k=0; k<NUMBEROFCOMPOSITEAPSECTIONS; k++) { | ||||
|     ForTransform_CompositeAPFilterState[k] = CompositeAPFilterState[k]; | ||||
|   } | ||||
|  | ||||
|   /* now backwards filter the samples in the lookahead buffer. The samples were | ||||
|      placed there in the encoding of the previous frame.  The output samples | ||||
|      overwrite the input samples */ | ||||
|   WebRtcIsac_AllPassFilter2Float(prefiltdata->INLABUF1_float, | ||||
|                                  WebRtcIsac_kCompositeApFactorsFloat, QLOOKAHEAD, | ||||
|                                  NUMBEROFCOMPOSITEAPSECTIONS, CompositeAPFilterState); | ||||
|  | ||||
|   /* save the output, but write it in forward order */ | ||||
|   /* write the lookahead samples for the next encoding iteration. Every other | ||||
|      sample at the end of the input frame is written in reverse order for the | ||||
|      lookahead length. Exported in the prefiltdata structure. */ | ||||
|   for (k=0;k<QLOOKAHEAD;k++) { | ||||
|     tempin_ch1[QLOOKAHEAD-1-k]=prefiltdata->INLABUF1_float[k]; | ||||
|     prefiltdata->INLABUF1_float[k]=in[FRAMESAMPLES-1-2*k]; | ||||
|   } | ||||
|  | ||||
|   /* Second Channel.  This is exactly like the first channel, except that the | ||||
|      even samples are now filtered instead (lower channel). */ | ||||
|   for (k=0;k<NUMBEROFCOMPOSITEAPSECTIONS;k++){ | ||||
|     CompositeAPFilterState[k] = 0.0; | ||||
|   } | ||||
|  | ||||
|   for (k=0;k<FRAMESAMPLES_HALF;k++) { | ||||
|     tempinoutvec[k] = in[FRAMESAMPLES-2-2*k]; | ||||
|   } | ||||
|  | ||||
|   WebRtcIsac_AllPassFilter2Float(tempinoutvec, WebRtcIsac_kCompositeApFactorsFloat, | ||||
|                                  FRAMESAMPLES_HALF, NUMBEROFCOMPOSITEAPSECTIONS, CompositeAPFilterState); | ||||
|  | ||||
|   for (k=0;k<FRAMESAMPLES_HALF;k++) { | ||||
|     tempin_ch2[FRAMESAMPLES_HALF+QLOOKAHEAD-1-k] = tempinoutvec[k]; | ||||
|   } | ||||
|  | ||||
|   for (k=0; k<NUMBEROFCOMPOSITEAPSECTIONS; k++) { | ||||
|     ForTransform_CompositeAPFilterState2[k] = CompositeAPFilterState[k]; | ||||
|   } | ||||
|  | ||||
|  | ||||
|   WebRtcIsac_AllPassFilter2Float(prefiltdata->INLABUF2_float, | ||||
|                                  WebRtcIsac_kCompositeApFactorsFloat, QLOOKAHEAD,NUMBEROFCOMPOSITEAPSECTIONS, | ||||
|                                  CompositeAPFilterState); | ||||
|  | ||||
|   for (k=0;k<QLOOKAHEAD;k++) { | ||||
|     tempin_ch2[QLOOKAHEAD-1-k]=prefiltdata->INLABUF2_float[k]; | ||||
|     prefiltdata->INLABUF2_float[k]=in[FRAMESAMPLES-2-2*k]; | ||||
|   } | ||||
|  | ||||
|   /* Transform filter states from backward to forward */ | ||||
|   /*At this point, each of the states of the backwards composite filters for the | ||||
|     two channels are transformed into forward filtering states for the corresponding | ||||
|     forward channel filters.  Each channel's forward filtering state from the previous | ||||
|     encoding iteration is added to the transformed state to get a proper forward state */ | ||||
|  | ||||
|   /* So the existing NUMBEROFCOMPOSITEAPSECTIONS x 1 (4x1) state vector is multiplied by a | ||||
|      NUMBEROFCHANNELAPSECTIONSxNUMBEROFCOMPOSITEAPSECTIONS (2x4) transform matrix to get the | ||||
|      new state that is added to the previous 2x1 input state */ | ||||
|  | ||||
|   for (k=0;k<NUMBEROFCHANNELAPSECTIONS;k++){ /* k is row variable */ | ||||
|     for (n=0; n<NUMBEROFCOMPOSITEAPSECTIONS;n++){/* n is column variable */ | ||||
|       prefiltdata->INSTAT1_float[k] += ForTransform_CompositeAPFilterState[n]* | ||||
|           WebRtcIsac_kTransform1Float[k*NUMBEROFCHANNELAPSECTIONS+n]; | ||||
|       prefiltdata->INSTAT2_float[k] += ForTransform_CompositeAPFilterState2[n]* | ||||
|           WebRtcIsac_kTransform2Float[k*NUMBEROFCHANNELAPSECTIONS+n]; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   /*obtain polyphase components by forward all-pass filtering through each channel */ | ||||
|   /* the backward filtered samples are now forward filtered with the corresponding channel filters */ | ||||
|   /* The all pass filtering automatically updates the filter states which are exported in the | ||||
|      prefiltdata structure */ | ||||
|   WebRtcIsac_AllPassFilter2Float(tempin_ch1,WebRtcIsac_kUpperApFactorsFloat, | ||||
|                                  FRAMESAMPLES_HALF, NUMBEROFCHANNELAPSECTIONS, prefiltdata->INSTAT1_float); | ||||
|   WebRtcIsac_AllPassFilter2Float(tempin_ch2,WebRtcIsac_kLowerApFactorsFloat, | ||||
|                                  FRAMESAMPLES_HALF, NUMBEROFCHANNELAPSECTIONS, prefiltdata->INSTAT2_float); | ||||
|  | ||||
|   /* Now Construct low-pass and high-pass signals as combinations of polyphase components */ | ||||
|   for (k=0; k<FRAMESAMPLES_HALF; k++) { | ||||
|     LP[k] = 0.5f*(tempin_ch1[k] + tempin_ch2[k]);/* low pass signal*/ | ||||
|     HP[k] = 0.5f*(tempin_ch1[k] - tempin_ch2[k]);/* high pass signal*/ | ||||
|   } | ||||
|  | ||||
|   /* Lookahead LP and HP signals */ | ||||
|   /* now create low pass and high pass signals of the input vector.  However, no | ||||
|      backwards filtering is performed, and hence no phase equalization is involved. | ||||
|      Also, the input contains some samples that are lookahead samples.  The high pass | ||||
|      and low pass signals that are created are used outside this function for analysis | ||||
|      (not encoding) purposes */ | ||||
|  | ||||
|   /* set up input */ | ||||
|   for (k=0; k<FRAMESAMPLES_HALF; k++) { | ||||
|     tempin_ch1[k]=in[2*k+1]; | ||||
|     tempin_ch2[k]=in[2*k]; | ||||
|   } | ||||
|  | ||||
|   /* the input filter states are passed in and updated by the all-pass filtering routine and | ||||
|      exported in the prefiltdata structure*/ | ||||
|   WebRtcIsac_AllPassFilter2Float(tempin_ch1,WebRtcIsac_kUpperApFactorsFloat, | ||||
|                                  FRAMESAMPLES_HALF, NUMBEROFCHANNELAPSECTIONS, prefiltdata->INSTATLA1_float); | ||||
|   WebRtcIsac_AllPassFilter2Float(tempin_ch2,WebRtcIsac_kLowerApFactorsFloat, | ||||
|                                  FRAMESAMPLES_HALF, NUMBEROFCHANNELAPSECTIONS, prefiltdata->INSTATLA2_float); | ||||
|  | ||||
|   for (k=0; k<FRAMESAMPLES_HALF; k++) { | ||||
|     LP_la[k] = (float)(0.5f*(tempin_ch1[k] + tempin_ch2[k])); /*low pass */ | ||||
|     HP_la[k] = (double)(0.5f*(tempin_ch1[k] - tempin_ch2[k])); /* high pass */ | ||||
|   } | ||||
|  | ||||
|  | ||||
| }/*end of WebRtcIsac_SplitAndFilter */ | ||||
|  | ||||
|  | ||||
| /* Combining */ | ||||
|  | ||||
| /* HPstcoeff_out_1 = {a1, a2, b1 - b0 * a1, b2 - b0 * a2}; */ | ||||
| static const float kHpStCoefOut1Float[4] = | ||||
| {-1.99701049409000f, 0.99714204490000f, 0.01701049409000f, -0.01704204490000f}; | ||||
|  | ||||
| /* HPstcoeff_out_2 = {a1, a2, b1 - b0 * a1, b2 - b0 * a2}; */ | ||||
| static const float kHpStCoefOut2Float[4] = | ||||
| {-1.98645294509837f, 0.98672435560000f, 0.00645294509837f, -0.00662435560000f}; | ||||
|  | ||||
|  | ||||
| /* Function WebRtcIsac_FilterAndCombine */ | ||||
| /* This is a decoder function that takes the decimated | ||||
|    length FRAMESAMPLES_HALF input low-pass and | ||||
|    high-pass signals and creates a reconstructed fullband | ||||
|    output signal of length FRAMESAMPLES. WebRtcIsac_FilterAndCombine | ||||
|    is the sibling function of WebRtcIsac_SplitAndFilter */ | ||||
| /* INPUTS: | ||||
|    inLP: a length FRAMESAMPLES_HALF array of input low-pass | ||||
|    samples. | ||||
|    inHP: a length FRAMESAMPLES_HALF array of input high-pass | ||||
|    samples. | ||||
|    postfiltdata: input data structure containing the filterbank | ||||
|    states from the previous decoding iteration. | ||||
|    OUTPUTS: | ||||
|    Out: a length FRAMESAMPLES array of output reconstructed | ||||
|    samples (fullband) based on the input low-pass and | ||||
|    high-pass signals. | ||||
|    postfiltdata: the input data structure containing the filterbank | ||||
|    states is updated for the next decoding iteration */ | ||||
| void WebRtcIsac_FilterAndCombineFloat(float *InLP, | ||||
|                                       float *InHP, | ||||
|                                       float *Out, | ||||
|                                       PostFiltBankstr *postfiltdata) | ||||
| { | ||||
|   int k; | ||||
|   float tempin_ch1[FRAMESAMPLES+MAX_AR_MODEL_ORDER]; | ||||
|   float tempin_ch2[FRAMESAMPLES+MAX_AR_MODEL_ORDER]; | ||||
|   float ftmp, ftmp2; | ||||
|  | ||||
|   /* Form the polyphase signals*/ | ||||
|   for (k=0;k<FRAMESAMPLES_HALF;k++) { | ||||
|     tempin_ch1[k]=InLP[k]+InHP[k]; /* Construct a new upper channel signal*/ | ||||
|     tempin_ch2[k]=InLP[k]-InHP[k]; /* Construct a new lower channel signal*/ | ||||
|   } | ||||
|  | ||||
|  | ||||
|   /* all-pass filter the new upper channel signal. HOWEVER, use the all-pass filter factors | ||||
|      that were used as a lower channel at the encoding side.  So at the decoder, the | ||||
|      corresponding all-pass filter factors for each channel are swapped.*/ | ||||
|   WebRtcIsac_AllPassFilter2Float(tempin_ch1, WebRtcIsac_kLowerApFactorsFloat, | ||||
|                                  FRAMESAMPLES_HALF, NUMBEROFCHANNELAPSECTIONS,postfiltdata->STATE_0_UPPER_float); | ||||
|  | ||||
|   /* Now, all-pass filter the new lower channel signal. But since all-pass filter factors | ||||
|      at the decoder are swapped from the ones at the encoder, the 'upper' channel | ||||
|      all-pass filter factors (WebRtcIsac_kUpperApFactorsFloat) are used to filter this new | ||||
|      lower channel signal */ | ||||
|   WebRtcIsac_AllPassFilter2Float(tempin_ch2, WebRtcIsac_kUpperApFactorsFloat, | ||||
|                                  FRAMESAMPLES_HALF, NUMBEROFCHANNELAPSECTIONS,postfiltdata->STATE_0_LOWER_float); | ||||
|  | ||||
|  | ||||
|   /* Merge outputs to form the full length output signal.*/ | ||||
|   for (k=0;k<FRAMESAMPLES_HALF;k++) { | ||||
|     Out[2*k]=tempin_ch2[k]; | ||||
|     Out[2*k+1]=tempin_ch1[k]; | ||||
|   } | ||||
|  | ||||
|  | ||||
|   /* High pass filter */ | ||||
|  | ||||
|   for (k=0;k<FRAMESAMPLES;k++) { | ||||
|     ftmp2 = Out[k] + kHpStCoefOut1Float[2] * postfiltdata->HPstates1_float[0] + | ||||
|         kHpStCoefOut1Float[3] * postfiltdata->HPstates1_float[1]; | ||||
|     ftmp = Out[k] - kHpStCoefOut1Float[0] * postfiltdata->HPstates1_float[0] - | ||||
|         kHpStCoefOut1Float[1] * postfiltdata->HPstates1_float[1]; | ||||
|     postfiltdata->HPstates1_float[1] = postfiltdata->HPstates1_float[0]; | ||||
|     postfiltdata->HPstates1_float[0] = ftmp; | ||||
|     Out[k] = ftmp2; | ||||
|   } | ||||
|  | ||||
|   for (k=0;k<FRAMESAMPLES;k++) { | ||||
|     ftmp2 = Out[k] + kHpStCoefOut2Float[2] * postfiltdata->HPstates2_float[0] + | ||||
|         kHpStCoefOut2Float[3] * postfiltdata->HPstates2_float[1]; | ||||
|     ftmp = Out[k] - kHpStCoefOut2Float[0] * postfiltdata->HPstates2_float[0] - | ||||
|         kHpStCoefOut2Float[1] * postfiltdata->HPstates2_float[1]; | ||||
|     postfiltdata->HPstates2_float[1] = postfiltdata->HPstates2_float[0]; | ||||
|     postfiltdata->HPstates2_float[0] = ftmp; | ||||
|     Out[k] = ftmp2; | ||||
|   } | ||||
| } | ||||
							
								
								
									
										171
									
								
								webrtc/modules/audio_coding/codecs/isac/main/source/intialize.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										171
									
								
								webrtc/modules/audio_coding/codecs/isac/main/source/intialize.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,171 @@ | ||||
| /* | ||||
|  *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. | ||||
|  * | ||||
|  *  Use of this source code is governed by a BSD-style license | ||||
|  *  that can be found in the LICENSE file in the root of the source | ||||
|  *  tree. An additional intellectual property rights grant can be found | ||||
|  *  in the file PATENTS.  All contributing project authors may | ||||
|  *  be found in the AUTHORS file in the root of the source tree. | ||||
|  */ | ||||
|  | ||||
| /* encode.c  - Encoding function for the iSAC coder */ | ||||
|  | ||||
| #include "structs.h" | ||||
| #include "codec.h" | ||||
| #include "pitch_estimator.h" | ||||
|  | ||||
| #include <math.h> | ||||
|  | ||||
| void WebRtcIsac_InitMasking(MaskFiltstr *maskdata) { | ||||
|  | ||||
|   int k; | ||||
|  | ||||
|   for (k = 0; k < WINLEN; k++) { | ||||
|     maskdata->DataBufferLo[k] = 0.0; | ||||
|     maskdata->DataBufferHi[k] = 0.0; | ||||
|   } | ||||
|   for (k = 0; k < ORDERLO+1; k++) { | ||||
|     maskdata->CorrBufLo[k] = 0.0; | ||||
|     maskdata->PreStateLoF[k] = 0.0; | ||||
|     maskdata->PreStateLoG[k] = 0.0; | ||||
|     maskdata->PostStateLoF[k] = 0.0; | ||||
|     maskdata->PostStateLoG[k] = 0.0; | ||||
|   } | ||||
|   for (k = 0; k < ORDERHI+1; k++) { | ||||
|     maskdata->CorrBufHi[k] = 0.0; | ||||
|     maskdata->PreStateHiF[k] = 0.0; | ||||
|     maskdata->PreStateHiG[k] = 0.0; | ||||
|     maskdata->PostStateHiF[k] = 0.0; | ||||
|     maskdata->PostStateHiG[k] = 0.0; | ||||
|   } | ||||
|  | ||||
|   maskdata->OldEnergy = 10.0; | ||||
|   return; | ||||
| } | ||||
|  | ||||
| void WebRtcIsac_InitPreFilterbank(PreFiltBankstr *prefiltdata) | ||||
| { | ||||
|   int k; | ||||
|  | ||||
|   for (k = 0; k < QLOOKAHEAD; k++) { | ||||
|     prefiltdata->INLABUF1[k] = 0; | ||||
|     prefiltdata->INLABUF2[k] = 0; | ||||
|  | ||||
|     prefiltdata->INLABUF1_float[k] = 0; | ||||
|     prefiltdata->INLABUF2_float[k] = 0; | ||||
|   } | ||||
|   for (k = 0; k < 2*(QORDER-1); k++) { | ||||
|     prefiltdata->INSTAT1[k] = 0; | ||||
|     prefiltdata->INSTAT2[k] = 0; | ||||
|     prefiltdata->INSTATLA1[k] = 0; | ||||
|     prefiltdata->INSTATLA2[k] = 0; | ||||
|  | ||||
|     prefiltdata->INSTAT1_float[k] = 0; | ||||
|     prefiltdata->INSTAT2_float[k] = 0; | ||||
|     prefiltdata->INSTATLA1_float[k] = 0; | ||||
|     prefiltdata->INSTATLA2_float[k] = 0; | ||||
|   } | ||||
|  | ||||
|   /* High pass filter states */ | ||||
|   prefiltdata->HPstates[0] = 0.0; | ||||
|   prefiltdata->HPstates[1] = 0.0; | ||||
|  | ||||
|   prefiltdata->HPstates_float[0] = 0.0f; | ||||
|   prefiltdata->HPstates_float[1] = 0.0f; | ||||
|  | ||||
|   return; | ||||
| } | ||||
|  | ||||
| void WebRtcIsac_InitPostFilterbank(PostFiltBankstr *postfiltdata) | ||||
| { | ||||
|   int k; | ||||
|  | ||||
|   for (k = 0; k < 2*POSTQORDER; k++) { | ||||
|     postfiltdata->STATE_0_LOWER[k] = 0; | ||||
|     postfiltdata->STATE_0_UPPER[k] = 0; | ||||
|  | ||||
|     postfiltdata->STATE_0_LOWER_float[k] = 0; | ||||
|     postfiltdata->STATE_0_UPPER_float[k] = 0; | ||||
|   } | ||||
|  | ||||
|   /* High pass filter states */ | ||||
|   postfiltdata->HPstates1[0] = 0.0; | ||||
|   postfiltdata->HPstates1[1] = 0.0; | ||||
|  | ||||
|   postfiltdata->HPstates2[0] = 0.0; | ||||
|   postfiltdata->HPstates2[1] = 0.0; | ||||
|  | ||||
|   postfiltdata->HPstates1_float[0] = 0.0f; | ||||
|   postfiltdata->HPstates1_float[1] = 0.0f; | ||||
|  | ||||
|   postfiltdata->HPstates2_float[0] = 0.0f; | ||||
|   postfiltdata->HPstates2_float[1] = 0.0f; | ||||
|  | ||||
|   return; | ||||
| } | ||||
|  | ||||
|  | ||||
| void WebRtcIsac_InitPitchFilter(PitchFiltstr *pitchfiltdata) | ||||
| { | ||||
|   int k; | ||||
|  | ||||
|   for (k = 0; k < PITCH_BUFFSIZE; k++) { | ||||
|     pitchfiltdata->ubuf[k] = 0.0; | ||||
|   } | ||||
|   pitchfiltdata->ystate[0] = 0.0; | ||||
|   for (k = 1; k < (PITCH_DAMPORDER); k++) { | ||||
|     pitchfiltdata->ystate[k] = 0.0; | ||||
|   } | ||||
|   pitchfiltdata->oldlagp[0] = 50.0; | ||||
|   pitchfiltdata->oldgainp[0] = 0.0; | ||||
| } | ||||
|  | ||||
| void WebRtcIsac_InitWeightingFilter(WeightFiltstr *wfdata) | ||||
| { | ||||
|   int k; | ||||
|   double t, dtmp, dtmp2, denum, denum2; | ||||
|  | ||||
|   for (k=0;k<PITCH_WLPCBUFLEN;k++) | ||||
|     wfdata->buffer[k]=0.0; | ||||
|  | ||||
|   for (k=0;k<PITCH_WLPCORDER;k++) { | ||||
|     wfdata->istate[k]=0.0; | ||||
|     wfdata->weostate[k]=0.0; | ||||
|     wfdata->whostate[k]=0.0; | ||||
|   } | ||||
|  | ||||
|   /* next part should be in Matlab, writing to a global table */ | ||||
|   t = 0.5; | ||||
|   denum = 1.0 / ((double) PITCH_WLPCWINLEN); | ||||
|   denum2 = denum * denum; | ||||
|   for (k=0;k<PITCH_WLPCWINLEN;k++) { | ||||
|     dtmp = PITCH_WLPCASYM * t * denum + (1-PITCH_WLPCASYM) * t * t * denum2; | ||||
|     dtmp *= 3.14159265; | ||||
|     dtmp2 = sin(dtmp); | ||||
|     wfdata->window[k] = dtmp2 * dtmp2; | ||||
|     t++; | ||||
|   } | ||||
| } | ||||
|  | ||||
| /* clear all buffers */ | ||||
| void WebRtcIsac_InitPitchAnalysis(PitchAnalysisStruct *State) | ||||
| { | ||||
|   int k; | ||||
|  | ||||
|   for (k = 0; k < PITCH_CORR_LEN2+PITCH_CORR_STEP2+PITCH_MAX_LAG/2-PITCH_FRAME_LEN/2+2; k++) | ||||
|     State->dec_buffer[k] = 0.0; | ||||
|   for (k = 0; k < 2*ALLPASSSECTIONS+1; k++) | ||||
|     State->decimator_state[k] = 0.0; | ||||
|   for (k = 0; k < 2; k++) | ||||
|     State->hp_state[k] = 0.0; | ||||
|   for (k = 0; k < QLOOKAHEAD; k++) | ||||
|     State->whitened_buf[k] = 0.0; | ||||
|   for (k = 0; k < QLOOKAHEAD; k++) | ||||
|     State->inbuf[k] = 0.0; | ||||
|  | ||||
|   WebRtcIsac_InitPitchFilter(&(State->PFstr_wght)); | ||||
|  | ||||
|   WebRtcIsac_InitPitchFilter(&(State->PFstr)); | ||||
|  | ||||
|   WebRtcIsac_InitWeightingFilter(&(State->Wghtstr)); | ||||
| } | ||||
| @@ -0,0 +1,383 @@ | ||||
| /* | ||||
|  *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | ||||
|  * | ||||
|  *  Use of this source code is governed by a BSD-style license | ||||
|  *  that can be found in the LICENSE file in the root of the source | ||||
|  *  tree. An additional intellectual property rights grant can be found | ||||
|  *  in the file PATENTS.  All contributing project authors may | ||||
|  *  be found in the AUTHORS file in the root of the source tree. | ||||
|  */ | ||||
|  | ||||
| #include "pitch_estimator.h" | ||||
|  | ||||
| #include <math.h> | ||||
| #include <memory.h> | ||||
| #include <stdlib.h> | ||||
|  | ||||
| #include "os_specific_inline.h" | ||||
|  | ||||
| /* | ||||
|  * We are implementing the following filters; | ||||
|  * | ||||
|  * Pre-filtering: | ||||
|  *   y(z) = x(z) + damper(z) * gain * (x(z) + y(z)) * z ^ (-lag); | ||||
|  * | ||||
|  * Post-filtering: | ||||
|  *   y(z) = x(z) - damper(z) * gain * (x(z) + y(z)) * z ^ (-lag); | ||||
|  * | ||||
|  * Note that |lag| is a floating number so we perform an interpolation to | ||||
|  * obtain the correct |lag|. | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| static const double kDampFilter[PITCH_DAMPORDER] = {-0.07, 0.25, 0.64, 0.25, | ||||
|     -0.07}; | ||||
|  | ||||
| /* interpolation coefficients; generated by design_pitch_filter.m */ | ||||
| static const double kIntrpCoef[PITCH_FRACS][PITCH_FRACORDER] = { | ||||
|     {-0.02239172458614,  0.06653315052934, -0.16515880017569,  0.60701333734125, | ||||
|      0.64671399919202, -0.20249000396417,  0.09926548334755, -0.04765933793109, | ||||
|      0.01754159521746}, | ||||
|     {-0.01985640750434,  0.05816126837866, -0.13991265473714,  0.44560418147643, | ||||
|      0.79117042386876, -0.20266133815188,  0.09585268418555, -0.04533310458084, | ||||
|      0.01654127246314}, | ||||
|     {-0.01463300534216,  0.04229888475060, -0.09897034715253,  0.28284326017787, | ||||
|      0.90385267956632, -0.16976950138649,  0.07704272393639, -0.03584218578311, | ||||
|      0.01295781500709}, | ||||
|     {-0.00764851320885,  0.02184035544377, -0.04985561057281,  0.13083306574393, | ||||
|      0.97545011664662, -0.10177807997561,  0.04400901776474, -0.02010737175166, | ||||
|      0.00719783432422}, | ||||
|     {-0.00000000000000,  0.00000000000000, -0.00000000000001,  0.00000000000001, | ||||
|      0.99999999999999,  0.00000000000001, -0.00000000000001,  0.00000000000000, | ||||
|      -0.00000000000000}, | ||||
|     {0.00719783432422, -0.02010737175166,  0.04400901776474, -0.10177807997562, | ||||
|      0.97545011664663,  0.13083306574393, -0.04985561057280,  0.02184035544377, | ||||
|      -0.00764851320885}, | ||||
|     {0.01295781500710, -0.03584218578312,  0.07704272393640, -0.16976950138650, | ||||
|      0.90385267956634,  0.28284326017785, -0.09897034715252,  0.04229888475059, | ||||
|      -0.01463300534216}, | ||||
|     {0.01654127246315, -0.04533310458085,  0.09585268418557, -0.20266133815190, | ||||
|      0.79117042386878,  0.44560418147640, -0.13991265473712,  0.05816126837865, | ||||
|      -0.01985640750433} | ||||
| }; | ||||
|  | ||||
| /* | ||||
|  * Enumerating the operation of the filter. | ||||
|  * iSAC has 4 different pitch-filter which are very similar in their structure. | ||||
|  * | ||||
|  * kPitchFilterPre     : In this mode the filter is operating as pitch | ||||
|  *                       pre-filter. This is used at the encoder. | ||||
|  * kPitchFilterPost    : In this mode the filter is operating as pitch | ||||
|  *                       post-filter. This is the inverse of pre-filter and used | ||||
|  *                       in the decoder. | ||||
|  * kPitchFilterPreLa   : This is, in structure, similar to pre-filtering but | ||||
|  *                       utilizing 3 millisecond lookahead. It is used to | ||||
|  *                       obtain the signal for LPC analysis. | ||||
|  * kPitchFilterPreGain : This is, in structure, similar to pre-filtering but | ||||
|  *                       differential changes in gain is considered. This is | ||||
|  *                       used to find the optimal gain. | ||||
|  */ | ||||
| typedef enum { | ||||
|   kPitchFilterPre, kPitchFilterPost, kPitchFilterPreLa, kPitchFilterPreGain | ||||
| } PitchFilterOperation; | ||||
|  | ||||
| /* | ||||
|  * Structure with parameters used for pitch-filtering. | ||||
|  * buffer           : a buffer where the sum of previous inputs and outputs | ||||
|  *                    are stored. | ||||
|  * damper_state     : the state of the damping filter. The filter is defined by | ||||
|  *                    |kDampFilter|. | ||||
|  * interpol_coeff   : pointer to a set of coefficient which are used to utilize | ||||
|  *                    fractional pitch by interpolation. | ||||
|  * gain             : pitch-gain to be applied to the current segment of input. | ||||
|  * lag              : pitch-lag for the current segment of input. | ||||
|  * lag_offset       : the offset of lag w.r.t. current sample. | ||||
|  * sub_frame        : sub-frame index, there are 4 pitch sub-frames in an iSAC | ||||
|  *                    frame. | ||||
|  *                    This specifies the usage of the filter. See | ||||
|  *                    'PitchFilterOperation' for operational modes. | ||||
|  * num_samples      : number of samples to be processed in each segment. | ||||
|  * index            : index of the input and output sample. | ||||
|  * damper_state_dg  : state of damping filter for different trial gains. | ||||
|  * gain_mult        : differential changes to gain. | ||||
|  */ | ||||
| typedef struct { | ||||
|   double buffer[PITCH_INTBUFFSIZE + QLOOKAHEAD]; | ||||
|   double damper_state[PITCH_DAMPORDER]; | ||||
|   const double *interpol_coeff; | ||||
|   double gain; | ||||
|   double lag; | ||||
|   int lag_offset; | ||||
|  | ||||
|   int sub_frame; | ||||
|   PitchFilterOperation mode; | ||||
|   int num_samples; | ||||
|   int index; | ||||
|  | ||||
|   double damper_state_dg[4][PITCH_DAMPORDER]; | ||||
|   double gain_mult[4]; | ||||
| } PitchFilterParam; | ||||
|  | ||||
| /********************************************************************** | ||||
|  * FilterSegment() | ||||
|  * Filter one segment, a quarter of a frame. | ||||
|  * | ||||
|  * Inputs | ||||
|  *   in_data      : pointer to the input signal of 30 ms at 8 kHz sample-rate. | ||||
|  *   filter_param : pitch filter parameters. | ||||
|  * | ||||
|  * Outputs | ||||
|  *   out_data     : pointer to a buffer where the filtered signal is written to. | ||||
|  *   out_dg       : [only used in kPitchFilterPreGain] pointer to a buffer | ||||
|  *                  where the output of different gain values (differential | ||||
|  *                  change to gain) is written. | ||||
|  */ | ||||
| static void FilterSegment(const double* in_data, PitchFilterParam* parameters, | ||||
|                           double* out_data, | ||||
|                           double out_dg[][PITCH_FRAME_LEN + QLOOKAHEAD]) { | ||||
|   int n; | ||||
|   int m; | ||||
|   int j; | ||||
|   double sum; | ||||
|   double sum2; | ||||
|   /* Index of |parameters->buffer| where the output is written to. */ | ||||
|   int pos = parameters->index + PITCH_BUFFSIZE; | ||||
|   /* Index of |parameters->buffer| where samples are read for fractional-lag | ||||
|    * computation. */ | ||||
|   int pos_lag = pos - parameters->lag_offset; | ||||
|  | ||||
|   for (n = 0; n < parameters->num_samples; ++n) { | ||||
|     /* Shift low pass filter states. */ | ||||
|     for (m = PITCH_DAMPORDER - 1; m > 0; --m) { | ||||
|       parameters->damper_state[m] = parameters->damper_state[m - 1]; | ||||
|     } | ||||
|     /* Filter to get fractional pitch. */ | ||||
|     sum = 0.0; | ||||
|     for (m = 0; m < PITCH_FRACORDER; ++m) { | ||||
|       sum += parameters->buffer[pos_lag + m] * parameters->interpol_coeff[m]; | ||||
|     } | ||||
|     /* Multiply with gain. */ | ||||
|     parameters->damper_state[0] = parameters->gain * sum; | ||||
|  | ||||
|     if (parameters->mode == kPitchFilterPreGain) { | ||||
|       int lag_index = parameters->index - parameters->lag_offset; | ||||
|       int m_tmp = (lag_index < 0) ? -lag_index : 0; | ||||
|       /* Update the damper state for the new sample. */ | ||||
|       for (m = PITCH_DAMPORDER - 1; m > 0; --m) { | ||||
|         for (j = 0; j < 4; ++j) { | ||||
|           parameters->damper_state_dg[j][m] = | ||||
|               parameters->damper_state_dg[j][m - 1]; | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       for (j = 0; j < parameters->sub_frame + 1; ++j) { | ||||
|         /* Filter for fractional pitch. */ | ||||
|         sum2 = 0.0; | ||||
|         for (m = PITCH_FRACORDER-1; m >= m_tmp; --m) { | ||||
|           /* |lag_index + m| is always larger than or equal to zero, see how | ||||
|            * m_tmp is computed. This is equivalent to assume samples outside | ||||
|            * |out_dg[j]| are zero. */ | ||||
|           sum2 += out_dg[j][lag_index + m] * parameters->interpol_coeff[m]; | ||||
|         } | ||||
|         /* Add the contribution of differential gain change. */ | ||||
|         parameters->damper_state_dg[j][0] = parameters->gain_mult[j] * sum + | ||||
|             parameters->gain * sum2; | ||||
|       } | ||||
|  | ||||
|       /* Filter with damping filter, and store the results. */ | ||||
|       for (j = 0; j < parameters->sub_frame + 1; ++j) { | ||||
|         sum = 0.0; | ||||
|         for (m = 0; m < PITCH_DAMPORDER; ++m) { | ||||
|           sum -= parameters->damper_state_dg[j][m] * kDampFilter[m]; | ||||
|         } | ||||
|         out_dg[j][parameters->index] = sum; | ||||
|       } | ||||
|     } | ||||
|     /* Filter with damping filter. */ | ||||
|     sum = 0.0; | ||||
|     for (m = 0; m < PITCH_DAMPORDER; ++m) { | ||||
|       sum += parameters->damper_state[m] * kDampFilter[m]; | ||||
|     } | ||||
|  | ||||
|     /* Subtract from input and update buffer. */ | ||||
|     out_data[parameters->index] = in_data[parameters->index] - sum; | ||||
|     parameters->buffer[pos] = in_data[parameters->index] + | ||||
|         out_data[parameters->index]; | ||||
|  | ||||
|     ++parameters->index; | ||||
|     ++pos; | ||||
|     ++pos_lag; | ||||
|   } | ||||
|   return; | ||||
| } | ||||
|  | ||||
| /* Update filter parameters based on the pitch-gains and pitch-lags. */ | ||||
| static void Update(PitchFilterParam* parameters) { | ||||
|   double fraction; | ||||
|   int fraction_index; | ||||
|   /* Compute integer lag-offset. */ | ||||
|   parameters->lag_offset = WebRtcIsac_lrint(parameters->lag + PITCH_FILTDELAY + | ||||
|                                             0.5); | ||||
|   /* Find correct set of coefficients for computing fractional pitch. */ | ||||
|   fraction = parameters->lag_offset - (parameters->lag + PITCH_FILTDELAY); | ||||
|   fraction_index = WebRtcIsac_lrint(PITCH_FRACS * fraction - 0.5); | ||||
|   parameters->interpol_coeff = kIntrpCoef[fraction_index]; | ||||
|  | ||||
|   if (parameters->mode == kPitchFilterPreGain) { | ||||
|     /* If in this mode make a differential change to pitch gain. */ | ||||
|     parameters->gain_mult[parameters->sub_frame] += 0.2; | ||||
|     if (parameters->gain_mult[parameters->sub_frame] > 1.0) { | ||||
|       parameters->gain_mult[parameters->sub_frame] = 1.0; | ||||
|     } | ||||
|     if (parameters->sub_frame > 0) { | ||||
|       parameters->gain_mult[parameters->sub_frame - 1] -= 0.2; | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| /****************************************************************************** | ||||
|  * FilterFrame() | ||||
|  * Filter a frame of 30 millisecond, given pitch-lags and pitch-gains. | ||||
|  * | ||||
|  * Inputs | ||||
|  *   in_data     : pointer to the input signal of 30 ms at 8 kHz sample-rate. | ||||
|  *   lags        : pointer to pitch-lags, 4 lags per frame. | ||||
|  *   gains       : pointer to pitch-gians, 4 gains per frame. | ||||
|  *   mode        : defining the functionality of the filter. It takes the | ||||
|  *                 following values. | ||||
|  *                 kPitchFilterPre:     Pitch pre-filter, used at encoder. | ||||
|  *                 kPitchFilterPost:    Pitch post-filter, used at decoder. | ||||
|  *                 kPitchFilterPreLa:   Pitch pre-filter with lookahead. | ||||
|  *                 kPitchFilterPreGain: Pitch pre-filter used to otain optimal | ||||
|  *                                      pitch-gains. | ||||
|  * | ||||
|  * Outputs | ||||
|  *   out_data    : pointer to a buffer where the filtered signal is written to. | ||||
|  *   out_dg      : [only used in kPitchFilterPreGain] pointer to a buffer | ||||
|  *                 where the output of different gain values (differential | ||||
|  *                 change to gain) is written. | ||||
|  */ | ||||
| static void FilterFrame(const double* in_data, PitchFiltstr* filter_state, | ||||
|                         double* lags, double* gains, PitchFilterOperation mode, | ||||
|                         double* out_data, | ||||
|                         double out_dg[][PITCH_FRAME_LEN + QLOOKAHEAD]) { | ||||
|   PitchFilterParam filter_parameters; | ||||
|   double gain_delta, lag_delta; | ||||
|   double old_lag, old_gain; | ||||
|   int n; | ||||
|   int m; | ||||
|   const double kEnhancer = 1.3; | ||||
|  | ||||
|   /* Set up buffer and states. */ | ||||
|   filter_parameters.index = 0; | ||||
|   filter_parameters.lag_offset = 0; | ||||
|   filter_parameters.mode = mode; | ||||
|   /* Copy states to local variables. */ | ||||
|   memcpy(filter_parameters.buffer, filter_state->ubuf, | ||||
|          sizeof(filter_state->ubuf)); | ||||
|   memcpy(filter_parameters.damper_state, filter_state->ystate, | ||||
|          sizeof(filter_state->ystate)); | ||||
|  | ||||
|   if (mode == kPitchFilterPreGain) { | ||||
|     /* Clear buffers. */ | ||||
|     memset(filter_parameters.gain_mult, 0, sizeof(filter_parameters.gain_mult)); | ||||
|     memset(filter_parameters.damper_state_dg, 0, | ||||
|            sizeof(filter_parameters.damper_state_dg)); | ||||
|     for (n = 0; n < PITCH_SUBFRAMES; ++n) { | ||||
|       //memset(out_dg[n], 0, sizeof(double) * (PITCH_FRAME_LEN + QLOOKAHEAD)); | ||||
|       memset(out_dg[n], 0, sizeof(out_dg[n])); | ||||
|     } | ||||
|   } else if (mode == kPitchFilterPost) { | ||||
|     /* Make output more periodic. Negative sign is to change the structure | ||||
|      * of the filter. */ | ||||
|     for (n = 0; n < PITCH_SUBFRAMES; ++n) { | ||||
|       gains[n] *= -kEnhancer; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   old_lag = *filter_state->oldlagp; | ||||
|   old_gain = *filter_state->oldgainp; | ||||
|  | ||||
|   /* No interpolation if pitch lag step is big. */ | ||||
|   if ((lags[0] > (PITCH_UPSTEP * old_lag)) || | ||||
|       (lags[0] < (PITCH_DOWNSTEP * old_lag))) { | ||||
|     old_lag = lags[0]; | ||||
|     old_gain = gains[0]; | ||||
|  | ||||
|     if (mode == kPitchFilterPreGain) { | ||||
|       filter_parameters.gain_mult[0] = 1.0; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   filter_parameters.num_samples = PITCH_UPDATE; | ||||
|   for (m = 0; m < PITCH_SUBFRAMES; ++m) { | ||||
|     /* Set the sub-frame value. */ | ||||
|     filter_parameters.sub_frame = m; | ||||
|     /* Calculate interpolation steps for pitch-lag and pitch-gain. */ | ||||
|     lag_delta = (lags[m] - old_lag) / PITCH_GRAN_PER_SUBFRAME; | ||||
|     filter_parameters.lag = old_lag; | ||||
|     gain_delta = (gains[m] - old_gain) / PITCH_GRAN_PER_SUBFRAME; | ||||
|     filter_parameters.gain = old_gain; | ||||
|     /* Store for the next sub-frame. */ | ||||
|     old_lag = lags[m]; | ||||
|     old_gain = gains[m]; | ||||
|  | ||||
|     for (n = 0; n < PITCH_GRAN_PER_SUBFRAME; ++n) { | ||||
|       /* Step-wise interpolation of pitch gains and lags. As pitch-lag changes, | ||||
|        * some parameters of filter need to be update. */ | ||||
|       filter_parameters.gain += gain_delta; | ||||
|       filter_parameters.lag += lag_delta; | ||||
|       /* Update parameters according to new lag value. */ | ||||
|       Update(&filter_parameters); | ||||
|       /* Filter a segment of input. */ | ||||
|       FilterSegment(in_data, &filter_parameters, out_data, out_dg); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   if (mode != kPitchFilterPreGain) { | ||||
|     /* Export buffer and states. */ | ||||
|     memcpy(filter_state->ubuf, &filter_parameters.buffer[PITCH_FRAME_LEN], | ||||
|            sizeof(filter_state->ubuf)); | ||||
|     memcpy(filter_state->ystate, filter_parameters.damper_state, | ||||
|            sizeof(filter_state->ystate)); | ||||
|  | ||||
|     /* Store for the next frame. */ | ||||
|     *filter_state->oldlagp = old_lag; | ||||
|     *filter_state->oldgainp = old_gain; | ||||
|   } | ||||
|  | ||||
|   if ((mode == kPitchFilterPreGain) || (mode == kPitchFilterPreLa)) { | ||||
|     /* Filter the lookahead segment, this is treated as the last sub-frame. So | ||||
|      * set |pf_param| to last sub-frame. */ | ||||
|     filter_parameters.sub_frame = PITCH_SUBFRAMES - 1; | ||||
|     filter_parameters.num_samples = QLOOKAHEAD; | ||||
|     FilterSegment(in_data, &filter_parameters, out_data, out_dg); | ||||
|   } | ||||
| } | ||||
|  | ||||
| void WebRtcIsac_PitchfilterPre(double* in_data, double* out_data, | ||||
|                                PitchFiltstr* pf_state, double* lags, | ||||
|                                double* gains) { | ||||
|   FilterFrame(in_data, pf_state, lags, gains, kPitchFilterPre, out_data, NULL); | ||||
| } | ||||
|  | ||||
| void WebRtcIsac_PitchfilterPre_la(double* in_data, double* out_data, | ||||
|                                   PitchFiltstr* pf_state, double* lags, | ||||
|                                   double* gains) { | ||||
|   FilterFrame(in_data, pf_state, lags, gains, kPitchFilterPreLa, out_data, | ||||
|               NULL); | ||||
| } | ||||
|  | ||||
| void WebRtcIsac_PitchfilterPre_gains( | ||||
|     double* in_data, double* out_data, | ||||
|     double out_dg[][PITCH_FRAME_LEN + QLOOKAHEAD], PitchFiltstr *pf_state, | ||||
|     double* lags, double* gains) { | ||||
|   FilterFrame(in_data, pf_state, lags, gains, kPitchFilterPreGain, out_data, | ||||
|               out_dg); | ||||
| } | ||||
|  | ||||
| void WebRtcIsac_PitchfilterPost(double* in_data, double* out_data, | ||||
|                                 PitchFiltstr* pf_state, double* lags, | ||||
|                                 double* gains) { | ||||
|   FilterFrame(in_data, pf_state, lags, gains, kPitchFilterPost, out_data, NULL); | ||||
| } | ||||
		Reference in New Issue
	
	Block a user