⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 melp_syn.c

📁 It is source code for Melp2.4kps vocoder using dsp tms320vc55x of ti
💻 C
📖 第 1 页 / 共 2 页
字号:
/*

*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 + -