blob: c9f48c2b59d9eb334ccf43863fc341766f4fa2c1 [file] [log] [blame]
/*
** 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: voicefac.c *
* *
* Description: Find the voicing factors (1 = voice to -1 = unvoiced) *
* *
************************************************************************/
#include "typedef.h"
#include "basic_op.h"
#include "math_op.h"
Word16 voice_factor( /* (o) Q15 : factor (-1=unvoiced to 1=voiced) */
Word16 exc[], /* (i) Q_exc : pitch excitation */
Word16 Q_exc, /* (i) : exc format */
Word16 gain_pit, /* (i) Q14 : gain of pitch */
Word16 code[], /* (i) Q9 : Fixed codebook excitation */
Word16 gain_code, /* (i) Q0 : gain of code */
Word16 L_subfr /* (i) : subframe length */
)
{
Word16 tmp, exp, ener1, exp1, ener2, exp2;
Word32 i, L_tmp;
#ifdef ASM_OPT /* asm optimization branch */
ener1 = extract_h(Dot_product12_asm(exc, exc, L_subfr, &exp1));
#else
ener1 = extract_h(Dot_product12(exc, exc, L_subfr, &exp1));
#endif
exp1 = exp1 - (Q_exc + Q_exc);
L_tmp = vo_L_mult(gain_pit, gain_pit);
exp = norm_l(L_tmp);
tmp = extract_h(L_tmp << exp);
ener1 = vo_mult(ener1, tmp);
exp1 = exp1 - exp - 10; /* 10 -> gain_pit Q14 to Q9 */
#ifdef ASM_OPT /* asm optimization branch */
ener2 = extract_h(Dot_product12_asm(code, code, L_subfr, &exp2));
#else
ener2 = extract_h(Dot_product12(code, code, L_subfr, &exp2));
#endif
exp = norm_s(gain_code);
tmp = gain_code << exp;
tmp = vo_mult(tmp, tmp);
ener2 = vo_mult(ener2, tmp);
exp2 = exp2 - (exp + exp);
i = exp1 - exp2;
if (i >= 0)
{
ener1 = ener1 >> 1;
ener2 = ener2 >> (i + 1);
} else
{
ener1 = ener1 >> (1 - i);
ener2 = ener2 >> 1;
}
tmp = vo_sub(ener1, ener2);
ener1 = add1(add1(ener1, ener2), 1);
if (tmp >= 0)
{
tmp = div_s(tmp, ener1);
} else
{
tmp = vo_negate(div_s(vo_negate(tmp), ener1));
}
return (tmp);
}