📄 pit_lib.c
字号:
/*
2.4 kbps MELP Proposed Federal Standard speech coder
Fixed-point C code, version 1.0
Copyright (c) 1998, Texas Instruments, Inc.
Texas Instruments has intellectual property rights on the MELP
algorithm. The Texas Instruments contact for licensing issues for
commercial and non-government use is William Gordon, Director,
Government Contracts, Texas Instruments Incorporated, Semiconductor
Group (phone 972 480 7442).
The fixed-point version of the voice codec Mixed Excitation Linear
Prediction (MELP) is based on specifications on the C-language software
simulation contained in GSM 06.06 which is protected by copyright and
is the property of the European Telecommunications Standards Institute
(ETSI). This standard is available from the ETSI publication office
tel. +33 (0)4 92 94 42 58. ETSI has granted a license to United States
Department of Defense to use the C-language software simulation contained
in GSM 06.06 for the purposes of the development of a fixed-point
version of the voice codec Mixed Excitation Linear Prediction (MELP).
Requests for authorization to make other use of the GSM 06.06 or
otherwise distribute or modify them need to be addressed to the ETSI
Secretariat fax: +33 493 65 47 16.
*/
/*
pit_lib.c: pitch analysis subroutines
*/
#include <stdio.h>
#include <math.h>
#include "spbstd.h"
#include "mathhalf.h"
#include "mathdp31.h"
#include "wmops.h"
#include "mat.h"
#include "math_lib.h"
#include "dsp_sub.h"
#include "pit.h"
#include "constant.h"
extern int saturation; /* saturation flag */
/* */
/* double_chk.c: check for pitch doubling */
/* and also verify pitch multiple for short pitches. */
/* */
/* Q values
--------
sig_in - Q0
pcorr - Q14
pitch - Q7
pdouble - Q7
*/
#define NUM_MULT 8
Shortword double_chk(Shortword sig_in[],Shortword *pcorr,Shortword pitch,
Shortword pdouble,Shortword pmin,Shortword pmax,
Shortword pmin_q7,Shortword pmax_q7,
Shortword lmin)
{
Shortword mult;
Shortword corr,thresh;
Shortword temp_pit;
Shortword temp1,temp2;
Longword L_temp;
pitch = frac_pch(sig_in,pcorr,pitch,0,pmin,pmax,pmin_q7,pmax_q7,lmin);
/* compute threshold Q14*Q7>>8 */
/* extra right shift to compensate left shift of L_mult */
L_temp = L_mult(*pcorr,pdouble);
L_temp = L_shr(L_temp,8);
thresh = extract_l(L_temp); /* Q14 */
/* Check pitch submultiples from shortest to longest */
for (mult = NUM_MULT; mult >= 2; mult--) {
/* temp_pit = pitch / mult */
temp1 = 0; data_move();
temp2 = shl(mult,11); /* Q11 */ data_move();
temp_pit = pitch; data_move();
while (temp_pit > temp2) {
/* increment complexity for while statement */
compare_nonzero();
temp_pit = shr(temp_pit,1); data_move();
temp1 = add(temp1,1); data_move();
}
/* Q7*Q15/Q11 -> Q11 */
temp2 = divide_s(temp_pit,temp2); data_move();
temp1 = sub(4,temp1); data_move();
/* temp_pit=pitch/mult in Q7 */
temp_pit = shr(temp2,temp1); data_move();
/* increment complexity for if statement */
compare_nonzero();
if (temp_pit >= pmin_q7) {
temp_pit = frac_pch(sig_in,&corr,temp_pit,0,pmin,pmax,pmin_q7,
pmax_q7,lmin);
double_ver(sig_in,&corr,temp_pit,pmin,pmax,pmin_q7,
pmax_q7,lmin);
/* stop if submultiple greater than threshold */
/* increment complexity for if statement */
compare_nonzero();
if (corr > thresh) {
/* refine estimate one more time since previous window */
/* may be off center slightly and temp_pit has moved */
pitch = frac_pch(sig_in,pcorr,temp_pit,0,pmin,pmax,pmin_q7,
pmax_q7,lmin);
break;
}
}
}
/* Verify pitch multiples for short pitches */
double_ver(sig_in,pcorr,pitch,pmin,pmax,pmin_q7,pmax_q7,lmin);
/* Return full floating point pitch value and correlation*/
return(pitch);
}
#undef NUM_MULT
/* */
/* double_ver.c: verify pitch multiple for short pitches. */
/* */
/* Q values
--------
pitch - Q7
pcorr - Q14
*/
#define SHORT_PITCH 3840 /* (30*(1<<7)) */ /* Q7 */
void double_ver(Shortword sig_in[],Shortword *pcorr,Shortword pitch,
Shortword pmin,Shortword pmax,Shortword pmin_q7,
Shortword pmax_q7,Shortword lmin)
{
Shortword multiple;
Shortword corr,temp_pit;
/* Verify pitch multiples for short pitches */
multiple = 1; data_move();
while (extract_l(L_shr(L_mult(pitch,multiple),1)) < SHORT_PITCH) {
/* increment complexity for while statement */
compare_nonzero();
multiple=add(multiple,1); data_move();
}
/* increment complexity for if statement */
compare_nonzero();
if (multiple > 1) {
temp_pit = extract_l(L_shr(L_mult(pitch,multiple),1));
temp_pit = frac_pch(sig_in,&corr,temp_pit,0,pmin,pmax,
pmin_q7,pmax_q7,lmin);
/* use smaller of two correlation values */
/* increment complexity for if statement */
compare_nonzero();
if (corr < *pcorr) {
*pcorr = corr; data_move();
}
}
}
#undef SHORT_PITCH
/* */
/* f_pitch_scale.c: Scale pitch signal buffer for best precision */
/* */
Shortword f_pitch_scale(Shortword sig_out[],Shortword sig_in[],
Shortword length)
{
int sat_save;
Shortword scale;
Shortword *temp_buf;
Longword corr;
/* allocate scratch buffer */
MEM_ALLOC(MALLOC,temp_buf,length,Shortword);
/* Compute signal buffer scale factor */
sat_save = saturation;
scale = 0;
corr = L_v_magsq(sig_in, length, 0, 1);
if (saturation > sat_save) {
/* saturation: right shift input signal and try again */
scale = 5;
v_equ_shr(temp_buf,sig_in,scale,length);
corr = L_v_magsq(temp_buf, length, 0, 1);
/* could add delta to compensate possible truncation error */
/* reset saturation counter */
saturation = sat_save;
}
scale = sub(scale,shr(norm_l(corr),1));
/* Scale signal buffer */
v_equ_shr(sig_out,sig_in,scale,length);
/* free scratch buffer */
MEM_FREE(FREE,temp_buf);
/* return scale factor */
return(scale);
}
/* */
/* find_pitch.c: Determine pitch value. */
/* */
/* Q values:
sig_in - Q0
ipitch - Q0
*pcorr - Q14 */
/*
WARNING: this function assumes the input buffer has been normalized
by f_pitch_scale.
*/
Shortword find_pitch(Shortword sig_in[],Shortword *pcorr,Shortword lower,
Shortword upper,Shortword length)
{
Shortword i,cbegin,ipitch,even_flag;
Shortword s_corr;
Shortword shift1a,shift1b,shift2,shift;
Longword c0_0,cT_T,corr;
Longword denom,max_denom,num,max_num;
/* Find beginning of correlation window centered on signal */
ipitch = lower; data_move();
max_num = 0; data_move();
max_denom = 1; data_move();
even_flag = 1; data_move();
/* cbegin = -((length+upper)/2) */
cbegin = negate(shr(add(length,upper),1)); data_move();
c0_0 = L_v_magsq(&sig_in[cbegin],length, 0, 1); L_data_move();
cT_T = L_v_magsq(&sig_in[cbegin+upper],length, 0, 1); L_data_move();
for (i = upper; i >= lower; i--) {
/* calculate normalized crosscorrelation */
corr= L_v_inner(&sig_in[cbegin],&sig_in[cbegin+i],length,0,0,1);
/* calculate normalization for numerator and denominator */
shift1a = norm_s(extract_h(c0_0));
shift1b = norm_s(extract_h(cT_T));
shift = add(shift1a,shift1b);
shift2 = shr(shift,1); /* shift2 = half of total shift */
if (shl(shift2,1) != shift)
shift1a = sub(shift1a,1);
/* check if current maximum value */
if (corr > 0) {
s_corr = extract_h(L_shl(corr,shift2));
num = extract_h(L_mult(s_corr,s_corr));
}
else
num = 0;
denom = extract_h(L_mult(extract_h(L_shl(c0_0,shift1a)),
extract_h(L_shl(cT_T,shift1b))));
if (denom < 1)
denom = 1;
L_compare_nonzero();
if (L_mult((Shortword)num,(Shortword)max_denom) > L_mult((Shortword)max_num,(Shortword)denom)) {
max_denom = denom; data_move();
max_num = num; data_move();
ipitch = i; data_move();
}
/* update for next iteration */
/* increment complexity for if statement */
compare_zero();
if (even_flag) {
even_flag = 0; data_move();
c0_0 = L_msu(c0_0,sig_in[cbegin],sig_in[cbegin]); L_data_move();
c0_0 = L_mac(c0_0,sig_in[cbegin+length],
sig_in[cbegin+length]); L_data_move();
cbegin = add(cbegin,1); data_move();
}
else {
even_flag = 1; data_move();
cT_T = L_msu(cT_T, sig_in[cbegin+i-1+length],
sig_in[cbegin+i-1+length]); L_data_move();
cT_T = L_mac(cT_T, sig_in[cbegin+i-1], sig_in[cbegin+i-1]);
L_data_move();
}
}
/* Return pitch value and correlation*/
*pcorr = shr(sqrt_fxp(divide_s((Shortword)max_num,(Shortword)max_denom),15),1);
data_move();
return(ipitch);
}
/*
Name: frac_pch.c
Description: Determine fractional pitch.
Inputs:
sig_in - input signal
fpitch - initial floating point pitch estimate
range - range for local integer pitch search (0=none)
pmin - minimum allowed pitch value
pmax - maximum allowed pitch value
lmin - minimum correlation length
Outputs:
pcorr - correlation at fractional pitch value
Returns: fpitch - fractional pitch value
Copyright (c) 1995 by Texas Instruments, Inc. All rights reserved.
*/
/* Q values
--------
ipitch - Q0
fpitch - Q7
sig_in - Q0
*pcorr - Q14
*/
/*
WARNING: this function assumes the input buffer has been normalized
by f_pitch_scale.
*/
#define MAXFRAC 16384 /* (2.0*(1<<13)) */ /* Q13 */
#define MINFRAC -8192 /* (-1.0*(1<<13)) */ /* Q13 */
Shortword frac_pch(Shortword sig_in[],Shortword *pcorr,Shortword fpitch,
Shortword range,Shortword pmin,Shortword pmax,
Shortword pmin_q7,Shortword pmax_q7,Shortword lmin)
{
Shortword length,cbegin,lower,upper,ipitch;
Shortword c0_0,c0_T,c0_T1,cT_T,cT_T1,cT1_T1,c0_Tm1;
Shortword shift1a,shift1b,shift2,shift;
Shortword frac,frac1,corr;
Shortword temp;
Longword denom,denom1,denom2,denom3,numer;
Longword mag_sq;
Longword L_temp1;
/* Perform local integer pitch search for better fpitch estimate */
/* increment complexity for if statement */
compare_zero();
if (range > 0) {
ipitch = shift_r(fpitch, -7); data_move();
lower = sub(ipitch,range); data_move();
upper = add(ipitch,range); data_move();
/* increment complexity for if statement */
compare_nonzero();
if (upper > pmax) {
upper = pmax; data_move();
}
/* increment complexity for if statement */
compare_nonzero();
if (lower < pmin) {
lower = pmin; data_move();
}
/* increment complexity for if statement */
compare_nonzero();
if (lower < add(shr(ipitch,1),shr(ipitch,2))) {
lower = add(shr(ipitch,1),shr(ipitch,2)); data_move();
}
length = ipitch; data_move();
/* increment complexity for if statement */
compare_nonzero();
if (length < lmin) {
length = lmin; data_move();
}
fpitch = shl(find_pitch(sig_in,&corr,lower,upper,length),7);
data_move();
}
/* Estimate needed crosscorrelations */
ipitch = shift_r(fpitch,-7); data_move();
/* increment complexity for if statement */
compare_nonzero();
if (ipitch >= pmax) {
ipitch = sub(pmax,1); data_move();
}
length = ipitch; data_move();
/* increment complexity for if statement */
compare_nonzero();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -