📄 melp_syn.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_syn.c
Description: MELP synthesis
This program takes the new parameters for a speech
frame and synthesizes the output speech. It keeps
an internal record of the previous frame parameters
to use for interpolation.
Inputs:
*par - MELP parameter structure
Outputs:
speech[] - output speech signal
Returns: void
*/
/* compiler include files */
/* Used for timing code */
extern unsigned int TCount;
extern unsigned int tArray[]; /* General purpose timer */
#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 "math_lib.h"
/* compiler constants */
#define ORIGINAL_SYNTH_GAIN 0
#if (MIX_ORD > DISP_ORD)
#define BEGIN MIX_ORD
#else
#define BEGIN DISP_ORD
#endif
#define TILT_ORD 1
#if (ORIGINAL_SYNTH_GAIN)
#define SYN_GAIN_Q4 (1000.0*(1<<4))
#else
#define SYN_GAIN_Q4 (2000.0*(1<<4))
#endif
#define SCALEOVER 10
#define INV_SCALEOVER_Q18 ((1.0/SCALEOVER)*((Longword)1<<18))
#define PDEL SCALEOVER
#define ONE_Q12 (1<<12)
#define ONE_Q13 (1<<13)
#define ONE_Q14 (1<<14)
#define ONE_Q15 (Shortword)(((Longword)1<<15)-1)
#define SIX_Q8 (6.0*(1<<8))
#define X05_Q14 (0.5*(1<<14))
#define X12_Q8 (12.0*(1<<8))
#define X30_Q8 (30.0*(1<<8))
#define X1_732_Q14 (1.732*(1<<14))
#define X60_Q9 (60.0*(1<<9))
#define X005_Q19 (0.05*((Longword)1<<19))
/* external memory references */
extern Shortword bp_cof[NUM_BANDS][MIX_ORD+1];
extern Shortword disp_cof[DISP_ORD+1];
extern Shortword msvq_cb[];
extern Shortword msvq_cb_mean[];
extern Shortword fsvq_cb[];
extern Shortword fsvq_weighted;
/* temporary memory */
static Shortword sigbuf[BEGIN+PITCHMAX];
static Shortword sig2[BEGIN+PITCHMAX];
static Shortword fs_real[PITCHMAX];
static Shortword sp_out[BEGIN+FRAME];
/* permanent memory */
static Shortword firstcall = 1; /* Just used for noise gain init */
static Shortword prev_gain_err;
static Shortword sigsave[PITCHMAX];
static struct melp_param prev_par;
static Shortword syn_begin;
static Shortword prev_scale;
static Shortword noise_gain = (Shortword)MIN_NOISE_Q8;
static Shortword pulse_del[MIX_ORD],noise_del[MIX_ORD];
static Shortword lpc_del[LPC_ORD],ase_del[LPC_ORD],tilt_del[TILT_ORD];
static Shortword disp_del[DISP_ORD];
static Shortword prev_lpc_gain;
static struct msvq_param vq_par; /* MSVQ parameters */
static struct msvq_param fs_vq_par; /* Fourier series VQ parameters */
static Shortword w_fs_inv[NUM_HARM];
/* these can be saved or recomputed */
static Shortword prev_pcof[MIX_ORD+1],prev_ncof[MIX_ORD+1];
static Shortword prev_tilt;
static Shortword prev_gain;
void melp_syn(struct melp_param *par,Shortword speech_out[])
{
Shortword i, gaincnt;
Shortword erase;
Shortword length;
Shortword intfact, intfact1, ifact, ifact_gain;
Shortword gain,pulse_gain,pitch,jitter;
Shortword curr_tilt,tilt_cof[TILT_ORD+1];
Shortword sig_prob,syn_gain,lpc_gain;
Shortword lsf[LPC_ORD+1];
Shortword lpc[LPC_ORD+1];
Shortword ase_num[LPC_ORD+1],ase_den[LPC_ORD+1];
Shortword curr_pcof[MIX_ORD+1],curr_ncof[MIX_ORD+1];
Shortword pulse_cof[MIX_ORD+1],noise_cof[MIX_ORD+1];
Shortword temp1,temp2;
Longword L_temp1,L_temp2;
/* Copy previous period of processed speech to output array */
if (syn_begin > 0) {
if (syn_begin > FRAME) {
v_equ(&sp_out[BEGIN],&sigsave[0],FRAME);
/* past end: save remainder in sigsave[0] */
v_equ(&sigsave[0],&sigsave[FRAME],(Shortword)(syn_begin-FRAME));
}
else
v_equ(&sp_out[BEGIN],&sigsave[0],syn_begin);
}
erase = 0; /* no erasures yet */
/* Update MSVQ information */
par->msvq_stages = vq_par.num_stages;
par->msvq_bits = vq_par.num_bits;
par->msvq_levels = vq_par.num_levels;
par->msvq_index = vq_par.indices;
par->fsvq_index = fs_vq_par.indices;
/* Read and decode channel input buffer */
erase = melp_chn_read(par,&prev_par);
if (par->uv_flag != 1 && !erase) {
/* Un-weight Fourier magnitudes */
window_Q(&par->fs_mag[0],w_fs_inv,&par->fs_mag[0],NUM_HARM);
}
/* Update adaptive noise level estimate based on last gain */
if (firstcall) {
firstcall = 0;
noise_gain = par->gain[NUM_GAINFR-1]; /* noise_gain in Q8 */
}
else if (!erase) {
for (i = 0; i < NUM_GAINFR; i++) {
/* write data to file for fixed-point debugging */
noise_est(par->gain[i],&noise_gain,(Shortword)UPCONST_Q19,
(Shortword)DOWNCONST_Q17,(Shortword)MIN_NOISE_Q8,
(Shortword)MAX_NOISE_Q8);
/* Adjust gain based on noise level (noise suppression) */
/* write data to file for fixed-point debugging */
noise_sup(&par->gain[i],noise_gain,(Shortword)MAX_NS_SUP_Q8,
(Shortword)MAX_NS_ATT_Q8,(Shortword)NFACT_Q8);
}
}
/* Clamp LSP bandwidths to avoid sharp LPC filters */
lpc_clamp(par->lsf,BWMIN_Q15,LPC_ORD);
/* Calculate spectral tilt for current frame for spectral enhancement */
tilt_cof[0] = ONE_Q15; /* tilt_cof in Q15 */
lpc_lsp2pred(par->lsf,lpc,LPC_ORD);
#if (!ORIGINAL_SYNTH_GAIN)
/* Use LPC prediction gain for adaptive scaling */
/* write data to file for fixed-point debugging */
/* lpc_gain = sqrt(lpc_pred2refl(lpc,sig2,LPC_ORD));*/
lpc_gain = lpc_pred2refl(lpc,sig2,LPC_ORD);
lpc_gain = sqrt_fxp(lpc_gain,15); /* lpc_gain in Q15 */
/* write data to file for fixed-point debugging */
#else
/* Original synthesis scaling */
lpc_pred2refl(lpc,sig2,LPC_ORD);
lpc_gain = ONE_Q15;
#endif
if (sig2[1] < 0)
curr_tilt = shr(sig2[1],1); /* curr_tilt in Q15 */
else
curr_tilt = 0;
/* Disable pitch interpolation for high-pitched onsets */
/* if (par->pitch < 0.5*prev_par.pitch &&
par->gain[0] > 6.0 + prev_par.gain[NUM_GAINFR-1]) { */
temp1 = shr(prev_par.pitch,1);
temp2 = (Shortword)SIX_Q8 + prev_par.gain[NUM_GAINFR-1];
if ((par->pitch < temp1) && (par->gain[0] > temp2)) {
/* copy current pitch into previous */
prev_par.pitch = par->pitch;
}
/* Set pulse and noise coefficients based on voicing strengths */
v_zap(curr_pcof,MIX_ORD+1); /* curr_pcof in Q14 */
v_zap(curr_ncof,MIX_ORD+1); /* curr_ncof in Q14 */
for (i = 0; i < NUM_BANDS; i++) {
if (par->bpvc[i] > X05_Q14)
v_add(curr_pcof,&bp_cof[i][0],MIX_ORD+1); /* bp_cof in Q14 */
else
v_add(curr_ncof,&bp_cof[i][0],MIX_ORD+1);
}
/* Process each pitch period */
while (syn_begin < FRAME) {
/* interpolate previous and current parameters */
ifact = divide_s(syn_begin,FRAME); /* ifact in Q15 */
if (syn_begin >= GAINFR) {
gaincnt = 2;
temp1 = syn_begin - GAINFR;
ifact_gain = divide_s(temp1,GAINFR);
}
else {
gaincnt = 1;
ifact_gain = divide_s(syn_begin,GAINFR);
}
/* interpolate gain */
if (gaincnt > 1) {
/* gain = ifact_gain*par->gain[gaincnt-1] +
(1.0-ifact_gain)*par->gain[gaincnt-2]; */
L_temp1 = L_mult(par->gain[gaincnt-1],ifact_gain);
temp1 = ONE_Q15 - ifact_gain;
L_temp2 = L_mult(par->gain[gaincnt-2],temp1);
gain = extract_h(L_add(L_temp1,L_temp2)); /* gain in Q8 */
}
else {
/* gain = ifact_gain*par->gain[gaincnt-1] +
(1.0-ifact_gain)*prev_par.gain[NUM_GAINFR-1]; */
L_temp1 = L_mult(par->gain[gaincnt-1],ifact_gain);
temp1 = ONE_Q15 - ifact_gain;
L_temp2 = L_mult(prev_par.gain[NUM_GAINFR-1],temp1);
gain = extract_h(L_add(L_temp1,L_temp2)); /* gain in Q8 */
}
/* Set overall interpolation path based on gain change */
temp1 = par->gain[NUM_GAINFR-1] - prev_par.gain[NUM_GAINFR-1];
if (abs_s(temp1) > SIX_Q8) {
/* Power surge: use gain adjusted interpolation */
/* intfact = (gain - prev_par.gain[NUM_GAINFR-1]) / temp; */
temp2 = gain - prev_par.gain[NUM_GAINFR-1];
if (((temp2 > 0) && (temp1 < 0)) || ((temp2 < 0) && (temp1 > 0)))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -