| /* |
| ** Copyright 2003-2010, VisualOn, Inc. |
| ** |
| ** Licensed under the Apache License, Version 2.0 (the "License"); |
| ** you may not use this file except in compliance with the License. |
| ** You may obtain a copy of the License at |
| ** |
| ** http://www.apache.org/licenses/LICENSE-2.0 |
| ** |
| ** Unless required by applicable law or agreed to in writing, software |
| ** distributed under the License is distributed on an "AS IS" BASIS, |
| ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| ** See the License for the specific language governing permissions and |
| ** limitations under the License. |
| */ |
| |
| /*********************************************************************** |
| * File: p_med_ol.c * |
| * * |
| * Description: Compute the open loop pitch lag * |
| * output: open loop pitch lag * |
| ************************************************************************/ |
| |
| #include "typedef.h" |
| #include "basic_op.h" |
| #include "acelp.h" |
| #include "oper_32b.h" |
| #include "math_op.h" |
| #include "p_med_ol.tab" |
| |
| Word16 Pitch_med_ol( |
| Word16 wsp[], /* i: signal used to compute the open loop pitch*/ |
| /* wsp[-pit_max] to wsp[-1] should be known */ |
| Coder_State *st, /* i/o: codec global structure */ |
| Word16 L_frame /* i: length of frame to compute pitch */ |
| ) |
| { |
| Word16 Tm; |
| Word16 hi, lo; |
| Word16 *ww, *we, *hp_wsp; |
| Word16 exp_R0, exp_R1, exp_R2; |
| Word32 i, j, max, R0, R1, R2; |
| Word16 *p1, *p2; |
| Word16 L_min = 17; /* minimum pitch lag: PIT_MIN / OPL_DECIM */ |
| Word16 L_max = 115; /* maximum pitch lag: PIT_MAX / OPL_DECIM */ |
| Word16 L_0 = st->old_T0_med; /* old open-loop pitch */ |
| Word16 *gain = &(st->ol_gain); /* normalize correlation of hp_wsp for the lag */ |
| Word16 *hp_wsp_mem = st->hp_wsp_mem; /* memory of the hypass filter for hp_wsp[] (lg = 9)*/ |
| Word16 *old_hp_wsp = st->old_hp_wsp; /* hypass wsp[] */ |
| Word16 wght_flg = st->ol_wght_flg; /* is weighting function used */ |
| |
| ww = &corrweight[198]; |
| we = &corrweight[98 + L_max - L_0]; |
| |
| max = MIN_32; |
| Tm = 0; |
| for (i = L_max; i > L_min; i--) |
| { |
| /* Compute the correlation */ |
| R0 = 0; |
| p1 = wsp; |
| p2 = &wsp[-i]; |
| for (j = 0; j < L_frame; j+=4) |
| { |
| R0 += vo_L_mult((*p1++), (*p2++)); |
| R0 += vo_L_mult((*p1++), (*p2++)); |
| R0 += vo_L_mult((*p1++), (*p2++)); |
| R0 += vo_L_mult((*p1++), (*p2++)); |
| } |
| /* Weighting of the correlation function. */ |
| hi = R0>>16; |
| lo = (R0 & 0xffff)>>1; |
| |
| R0 = Mpy_32_16(hi, lo, *ww); |
| ww--; |
| |
| if ((L_0 > 0) && (wght_flg > 0)) |
| { |
| /* Weight the neighbourhood of the old lag. */ |
| hi = R0>>16; |
| lo = (R0 & 0xffff)>>1; |
| R0 = Mpy_32_16(hi, lo, *we); |
| we--; |
| } |
| if(R0 >= max) |
| { |
| max = R0; |
| Tm = i; |
| } |
| } |
| |
| /* Hypass the wsp[] vector */ |
| hp_wsp = old_hp_wsp + L_max; |
| Hp_wsp(wsp, hp_wsp, L_frame, hp_wsp_mem); |
| |
| /* Compute normalize correlation at delay Tm */ |
| R0 = 0; |
| R1 = 0; |
| R2 = 0; |
| p1 = hp_wsp; |
| p2 = hp_wsp - Tm; |
| for (j = 0; j < L_frame; j+=4) |
| { |
| R2 += vo_mult32(*p1, *p1); |
| R1 += vo_mult32(*p2, *p2); |
| R0 += vo_mult32(*p1++, *p2++); |
| R2 += vo_mult32(*p1, *p1); |
| R1 += vo_mult32(*p2, *p2); |
| R0 += vo_mult32(*p1++, *p2++); |
| R2 += vo_mult32(*p1, *p1); |
| R1 += vo_mult32(*p2, *p2); |
| R0 += vo_mult32(*p1++, *p2++); |
| R2 += vo_mult32(*p1, *p1); |
| R1 += vo_mult32(*p2, *p2); |
| R0 += vo_mult32(*p1++, *p2++); |
| } |
| R0 = R0 <<1; |
| R1 = (R1 <<1) + 1L; |
| R2 = (R2 <<1) + 1L; |
| /* gain = R0/ sqrt(R1*R2) */ |
| |
| exp_R0 = norm_l(R0); |
| R0 = (R0 << exp_R0); |
| |
| exp_R1 = norm_l(R1); |
| R1 = (R1 << exp_R1); |
| |
| exp_R2 = norm_l(R2); |
| R2 = (R2 << exp_R2); |
| |
| |
| R1 = vo_L_mult(vo_round(R1), vo_round(R2)); |
| |
| i = norm_l(R1); |
| R1 = (R1 << i); |
| |
| exp_R1 += exp_R2; |
| exp_R1 += i; |
| exp_R1 = 62 - exp_R1; |
| |
| Isqrt_n(&R1, &exp_R1); |
| |
| R0 = vo_L_mult(voround(R0), voround(R1)); |
| exp_R0 = 31 - exp_R0; |
| exp_R0 += exp_R1; |
| |
| *gain = vo_round(L_shl(R0, exp_R0)); |
| |
| /* Shitf hp_wsp[] for next frame */ |
| |
| for (i = 0; i < L_max; i++) |
| { |
| old_hp_wsp[i] = old_hp_wsp[i + L_frame]; |
| } |
| |
| return (Tm); |
| } |
| |
| /************************************************************************ |
| * Function: median5 * |
| * * |
| * Returns the median of the set {X[-2], X[-1],..., X[2]}, * |
| * whose elements are 16-bit integers. * |
| * * |
| * Input: * |
| * X[-2:2] 16-bit integers. * |
| * * |
| * Return: * |
| * The median of {X[-2], X[-1],..., X[2]}. * |
| ************************************************************************/ |
| |
| Word16 median5(Word16 x[]) |
| { |
| Word16 x1, x2, x3, x4, x5; |
| Word16 tmp; |
| |
| x1 = x[-2]; |
| x2 = x[-1]; |
| x3 = x[0]; |
| x4 = x[1]; |
| x5 = x[2]; |
| |
| if (x2 < x1) |
| { |
| tmp = x1; |
| x1 = x2; |
| x2 = tmp; |
| } |
| if (x3 < x1) |
| { |
| tmp = x1; |
| x1 = x3; |
| x3 = tmp; |
| } |
| if (x4 < x1) |
| { |
| tmp = x1; |
| x1 = x4; |
| x4 = tmp; |
| } |
| if (x5 < x1) |
| { |
| x5 = x1; |
| } |
| if (x3 < x2) |
| { |
| tmp = x2; |
| x2 = x3; |
| x3 = tmp; |
| } |
| if (x4 < x2) |
| { |
| tmp = x2; |
| x2 = x4; |
| x4 = tmp; |
| } |
| if (x5 < x2) |
| { |
| x5 = x2; |
| } |
| if (x4 < x3) |
| { |
| x3 = x4; |
| } |
| if (x5 < x3) |
| { |
| x3 = x5; |
| } |
| return (x3); |
| } |
| |
| |
| Word16 Med_olag( /* output : median of 5 previous open-loop lags */ |
| Word16 prev_ol_lag, /* input : previous open-loop lag */ |
| Word16 old_ol_lag[5] |
| ) |
| { |
| Word32 i; |
| |
| /* Use median of 5 previous open-loop lags as old lag */ |
| |
| for (i = 4; i > 0; i--) |
| { |
| old_ol_lag[i] = old_ol_lag[i - 1]; |
| } |
| |
| old_ol_lag[0] = prev_ol_lag; |
| |
| i = median5(&old_ol_lag[2]); |
| |
| return i; |
| |
| } |
| |
| |
| |