📄 melp_ana.c
字号:
/*
*2.4 kbps MELP Proposed Federal Standard speech coder
*
*TMS320C5x assembly 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 following code was hand optimized for the Texas Instuments
* TMS320C5x DSP by DSPCon, Inc. For information, please contact DSPCon
* at:
*
* DSPCon, Inc.
* 380 Foothill Road
* Bridgewater, New Jersey 08807
* (908) 722-5656
* info@dspcon.com
* www.dspcon.com
*
*************************************************************************/
/*
Name: melp_ana.c
Description: MELP analysis
Inputs:
speech[] - input speech signal
Outputs:
*par - MELP parameter structure
Returns: void
*/
/* compiler include files */
#include <math.h>
#include "mathhalf.h"
#include "melp.h"
#include "spbstd.h"
#include "lpc.h"
#include "mat.h"
#include "vq.h"
#include "fs.h"
#include "pit.h"
#include "math_lib.h"
/* compiler constants */
#define BEGIN 0
#define END 1
#define HF_CORR_Q15 4 /* 0.0001220703125 in Q15 */
#define LAG_WIN 0.005 /* not used */
#define PDECAY_Q15 (Shortword)((0.95*((Longword)1<<15)))
#define PDECAY_PITCH_Q7 ((0.05*DEFAULT_PITCH)*(1<<7))
#define PEAK_THRESH_Q12 (1.34*(1<<12))
#define PEAK_THR2_Q12 (1.6*(1<<12))
#define SILENCE_DB_Q8 (30.0*(1<<8))
#define MAX_ORD LPF_ORD
#define FRAME_BEG (PITCHMAX-(FRAME/2))
#define FRAME_END (FRAME_BEG+FRAME)
#define PITCH_BEG (FRAME_END-PITCHMAX)
#define PITCH_FR ((2*PITCHMAX)+1)
#define IN_BEG (PITCH_BEG+PITCH_FR-FRAME)
#define SIG_LENGTH (LPF_ORD+PITCH_FR)
#define ONE_Q12 (1<<12)
#define ONE_Q13 (1<<13)
#define X60_Q9 (60*(1<<9))
/* external memory references */
extern Shortword win_cof[];
extern Shortword lpf_num[];
extern Shortword lpf_den[];
extern Shortword msvq_cb[];
extern Shortword msvq_cb_mean[];
extern Shortword fsvq_cb[];
extern Shortword fsvq_weighted;
/* memory definitions */
static Shortword sigbuf[SIG_LENGTH];
static Shortword speech[IN_BEG+FRAME];
static Shortword dcdelin[DC_ORD];
static Shortword dcdelout_hi[DC_ORD];
static Shortword dcdelout_lo[DC_ORD];
static Shortword lpfsp_delin[LPF_ORD];
static Shortword lpfsp_delout[LPF_ORD];
static Shortword pitch_avg;
static Shortword fpitch[2];
static struct msvq_param vq_par; /* MSVQ parameters */
static struct msvq_param fs_vq_par; /* Fourier series VQ parameters */
static Shortword w_fs[NUM_HARM];
/* Used for timing code */
extern volatile unsigned int TCount;
extern volatile unsigned int tArray[]; /* General purpose timer */
void melp_ana(Shortword sp_in[],struct melp_param *par)
{
Shortword i;
Shortword begin;
Shortword sub_pitch;
Shortword temp,pcorr,bpthresh;
Shortword r[LPC_ORD+1],refc[LPC_ORD+1],lpc[LPC_ORD+1];
Shortword weights[LPC_ORD];
Shortword section;
Shortword temp_delin[LPF_ORD];
Shortword temp_delout[LPF_ORD];
/* Remove DC from input speech */
dc_rmv(sp_in,&speech[IN_BEG],dcdelin,dcdelout_hi,dcdelout_lo,FRAME);
/* Copy input speech to pitch window and lowpass filter */
v_equ(&sigbuf[LPF_ORD],&speech[PITCH_BEG],PITCH_FR);
/* do first loop thru with less overhead */
iir_2nd_s(&sigbuf[LPF_ORD],lpf_den,lpf_num,
&sigbuf[LPF_ORD],lpfsp_delin,
lpfsp_delout,FRAME);
/* save delay buffers for the next overlapping frame */
for (i = 0; i < 2; i++) {
temp_delin[i] = lpfsp_delin[i];
temp_delout[i] = lpfsp_delout[i];
}
iir_2nd_s(&sigbuf[LPF_ORD+FRAME], lpf_den,
lpf_num, &sigbuf[LPF_ORD+FRAME],
lpfsp_delin, lpfsp_delout, PITCH_FR-FRAME);
/* restore delay buffers for the next overlapping frame */
for (i = 0; i < 2; i++) {
lpfsp_delin[i] = temp_delin[i];
lpfsp_delout[i] = temp_delout[i];
}
iir_2nd_s(&sigbuf[LPF_ORD],&lpf_den[3],&lpf_num[3],
&sigbuf[LPF_ORD],&lpfsp_delin[2],
&lpfsp_delout[2],FRAME);
/* save delay buffers for the next overlapping frame */
for (i = 2; i < 4; i++) {
temp_delin[i] = lpfsp_delin[i];
temp_delout[i] = lpfsp_delout[i];
}
iir_2nd_s(&sigbuf[LPF_ORD+FRAME],&lpf_den[3],
&lpf_num[3],&sigbuf[LPF_ORD+FRAME],
&lpfsp_delin[2],&lpfsp_delout[2],
PITCH_FR-FRAME);
/* restore delay buffers for the next overlapping frame */
for (i = 2; i < 4; i++) {
lpfsp_delin[i] = temp_delin[i];
lpfsp_delout[i] = temp_delout[i];
}
iir_2nd_s(&sigbuf[LPF_ORD],&lpf_den[6],&lpf_num[6],
&sigbuf[LPF_ORD],&lpfsp_delin[4],
&lpfsp_delout[4],FRAME);
/* save delay buffers for the next overlapping frame */
for (i = 4; i < 6; i++) {
temp_delin[i] = lpfsp_delin[i];
temp_delout[i] = lpfsp_delout[i];
}
iir_2nd_s(&sigbuf[LPF_ORD+FRAME],&lpf_den[6],
&lpf_num[6],&sigbuf[LPF_ORD+FRAME],
&lpfsp_delin[4],&lpfsp_delout[4],
PITCH_FR-FRAME);
/* restore delay buffers for the next overlapping frame */
for (i = 4; i < 6; i++) {
lpfsp_delin[i] = temp_delin[i];
lpfsp_delout[i] = temp_delout[i];
}
/* Perform global pitch search at frame end on lowpass speech signal */
/* Note: avoid short pitches due to formant tracking */
f_pitch_scale(&sigbuf[LPF_ORD],&sigbuf[LPF_ORD],PITCH_FR);
fpitch[END] = find_pitch(&sigbuf[LPF_ORD+(PITCH_FR/2)],&temp,
(2*PITCHMIN),PITCHMAX,PITCHMAX);
fpitch[END] = shl(fpitch[END],7); /* fpitch in Q7 */
/* Perform bandpass voicing analysis for end of frame */
bpvc_ana(&speech[FRAME_END], fpitch, &par->bpvc[0], &sub_pitch);
/* Force jitter if lowest band voicing strength is weak */
if (par->bpvc[0] < VJIT_Q14) /* par->bpvc in Q14 */
par->jitter = (Shortword)MAX_JITTER_Q15; /* par->jitter in Q15 */
else
par->jitter = (Shortword)0;
/* Calculate LPC for end of frame */
lpc_autocorr(&speech[(FRAME_END-(LPC_FRAME/2))],win_cof,r,
HF_CORR_Q15,(Shortword)LAG_WIN,LPC_ORD,LPC_FRAME);
lpc[0] = ONE_Q12; /* 1 in Q12 */
lpc_schur(r,lpc,refc,LPC_ORD); /* lpc in Q12, refc in Q15 */
/* Calculate LPC residual */
zerflt(&speech[PITCH_BEG],lpc,&sigbuf[LPF_ORD],LPC_ORD,PITCH_FR);
/* Check peakiness of residual signal */
begin = (LPF_ORD+(PITCHMAX/2));
temp = peakiness(&sigbuf[begin],PITCHMAX); /* temp in Q12 */
/* Peakiness: force lowest band to be voiced */
if (temp > PEAK_THRESH_Q12) {
par->bpvc[0] = 1<<14;
}
/* Extreme peakiness: force second and third bands to be voiced */
if (temp > PEAK_THR2_Q12) {
par->bpvc[1] = 1<<14;
par->bpvc[2] = 1<<14;
}
/* Calculate overall frame pitch using lowpass filtered residual */
par->pitch = pitch_ana(&speech[FRAME_END], &sigbuf[LPF_ORD+PITCHMAX],
sub_pitch,pitch_avg,&pcorr);
bpthresh = (Shortword)BPTHRESH_Q14;
/* Calculate gain of input speech for each gain subframe */
for (i = 0; i < NUM_GAINFR; i++) {
if (par->bpvc[0] > bpthresh) {
/* voiced mode: pitch synchronous window length */
temp = sub_pitch;
par->gain[i] = gain_ana(&speech[FRAME_BEG+(i+1)*GAINFR],
temp,MIN_GAINFR,PITCHMAX_X2);
}
else {
temp = (Shortword)GAIN_PITCH_Q7;
par->gain[i] = gain_ana(&speech[FRAME_BEG+(i+1)*GAINFR],
temp,0,PITCHMAX_X2);
}
}
/* Update average pitch value */
if (par->gain[NUM_GAINFR-1] > SILENCE_DB_Q8) /* par->gain in Q8 */
temp = pcorr;
else
temp = 0;
/* pcorr in Q14 */
pitch_avg = p_avg_update(par->pitch,temp,(Shortword)VMIN_Q14);
/* Calculate Line Spectral Frequencies */
lpc_pred2lsp(lpc,par->lsf,LPC_ORD);
/* Quantize MELP parameters to 2400 bps and generate bitstream */
/* Quantize LSF's with MSVQ */
vq_lspw(weights, &par->lsf[1], lpc, LPC_ORD);
msvq_enc(&par->lsf[1], weights, &par->lsf[1], vq_par);
par->msvq_index = vq_par.indices;
/* Quantize logarithmic pitch period */
/* Reserve all zero code for completely unvoiced */
par->pitch = log10_fxp(par->pitch,7); /* par->pitch in Q12 */
quant_u(&par->pitch,&par->pitch_index,(Shortword)PIT_QLO_Q12,
(Shortword)PIT_QUP_Q12,PIT_QLEV_M1,PIT_QLEV_M1_Q8,1,7);
/* convert pitch back to linear in Q7 */
par->pitch = pow10_fxp(par->pitch,7);
/* Quantize gain terms with uniform log quantizer */
q_gain(par->gain, par->gain_index,(Shortword)GN_QLO_Q8,
(Shortword)GN_QUP_Q8,GN_QLEV_M1,GN_QLEV_M1_Q10,0,5);
/* Quantize jitter */
/* quant_u(&par->jitter,&par->jit_index,0,MAX_JITTER_Q15,2); */
if (par->jitter < shr((Shortword)MAX_JITTER_Q15,1)) {
par->jitter = 0;
par->jit_index = 0;
}
else {
par->jitter = (Shortword)MAX_JITTER_Q15;
par->jit_index = 1;
}
/* Quantize bandpass voicing */
par->uv_flag = q_bpvc(&par->bpvc[0],&par->bpvc_index,bpthresh,
NUM_BANDS);
/* Calculate Fourier coefficients of residual signal from quantized LPC */
fill(par->fs_mag,ONE_Q13,NUM_HARM);
if (par->bpvc[0] > bpthresh) {
lpc_lsp2pred(par->lsf,lpc,LPC_ORD);
/* write data to file for fixed-point debugging */
zerflt(&speech[(FRAME_END-(LPC_FRAME/2))],lpc,sigbuf,
LPC_ORD,LPC_FRAME);
window(sigbuf,win_cof,sigbuf,LPC_FRAME);
find_harm(sigbuf, par->fs_mag, par->pitch, NUM_HARM, LPC_FRAME);
/* write data to file for fixed-point debugging */
}
/* write data to file for fixed-point debugging */
/* quantize Fourier coefficients */
/* pre-weight vector, then use Euclidean distance */
window_Q(&par->fs_mag[0],w_fs,&par->fs_mag[0],NUM_HARM);
fsvq_enc(&par->fs_mag[0], &par->fs_mag[0], fs_vq_par);
/* Set MELP indeces to point to same array */
par->fsvq_index = fs_vq_par.indices;
/* Update MSVQ information */
par->msvq_stages = vq_par.num_stages;
par->msvq_bits = vq_par.num_bits;
/* Write channel bitstream */
melp_chn_write(par);
/* Update delay buffers for next frame */
v_equ(&speech[0],&speech[FRAME],IN_BEG);
fpitch[BEGIN] = fpitch[END];
} /* melp_ana */
/*
* melp_ana_init: perform initialization
*/
void melp_ana_init()
{
Shortword j;
bpvc_ana_init(FRAME,PITCHMIN,PITCHMAX,NUM_BANDS,2,MINLENGTH);
pitch_ana_init(PITCHMIN,PITCHMAX,FRAME,LPF_ORD,MINLENGTH);
p_avg_init((Shortword)PDECAY_Q15,DEFAULT_PITCH_Q7,
(Shortword)PDECAY_PITCH_Q7,3);
v_zap(speech,IN_BEG+FRAME);
pitch_avg=DEFAULT_PITCH_Q7;
fill(fpitch,DEFAULT_PITCH_Q7,2);
v_zap(lpfsp_delin,LPF_ORD);
v_zap(lpfsp_delout,LPF_ORD);
/* Initialize multi-stage vector quantization (read codebook) */
vq_par.num_best = MSVQ_M;
vq_par.num_stages = 4;
vq_par.dimension = 10;
/*
* Allocate memory for number of levels per stage and indices
* and for number of bits per stage
*/
MEM_ALLOC(MALLOC,vq_par.num_levels,vq_par.num_stages,Shortword);
MEM_ALLOC(MALLOC,vq_par.indices,vq_par.num_stages,Shortword);
MEM_ALLOC(MALLOC,vq_par.num_bits,vq_par.num_stages,Shortword);
vq_par.num_levels[0] = 128;
vq_par.num_levels[1] = 64;
vq_par.num_levels[2] = 64;
vq_par.num_levels[3] = 64;
vq_par.num_bits[0] = 7;
vq_par.num_bits[1] = 6;
vq_par.num_bits[2] = 6;
vq_par.num_bits[3] = 6;
vq_par.cb = msvq_cb;
vq_par.cb_mean = msvq_cb_mean;
/* Initialize Fourier magnitude vector quantization (read codebook) */
fs_vq_par.num_best = 1;
fs_vq_par.num_stages = 1;
fs_vq_par.dimension = NUM_HARM;
/*
* Allocate memory for number of levels per stage and indices
* and for number of bits per stage
*/
MEM_ALLOC(MALLOC,fs_vq_par.num_levels,fs_vq_par.num_stages,Shortword);
MEM_ALLOC(MALLOC,fs_vq_par.indices,fs_vq_par.num_stages,Shortword);
MEM_ALLOC(MALLOC,fs_vq_par.num_bits,fs_vq_par.num_stages,Shortword);
fs_vq_par.num_levels[0] = FS_LEVELS;
fs_vq_par.num_bits[0] = FS_BITS;
fs_vq_par.cb = fsvq_cb;
/* Initialize fixed MSE weighting and inverse of weighting */
vq_fsw(w_fs, NUM_HARM, X60_Q9);
/* Initialize wr_array and wi_array */
fs_init();
/* Initialize LSP cos_tab */
LSP_init();
} /* melp_ana_init */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -