📄 melp_syn.c
字号:
/* ================================================================== */
/* */
/* Microsoft Speech coder ANSI-C Source Code */
/* SC1200 1200 bps speech coder */
/* Fixed Point Implementation Version 7.0 */
/* Copyright (C) 2000, Microsoft Corp. */
/* All rights reserved. */
/* */
/* ================================================================== */
/*
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.
*/
#include "sc1200.h"
#include "mathhalf.h"
#include "macro.h"
#include "lpc_lib.h"
#include "mat_lib.h"
#include "vq_lib.h"
#include "fs_lib.h"
#include "math_lib.h"
#include "constant.h"
#include "global.h"
#include "harm.h"
#include "fsvq_cb.h"
#include "dsp_sub.h"
#include "melp_sub.h"
#include "coeff.h"
#if POSTFILTER
#include "postfilt.h"
#endif
#define INV_LPC_ORD 2979
/* ((1.0/(LPC_ORD + 1))*(1<<15) + 0.5) for Q15 */
#define X005_Q19 26214 /* 0.05 * (1 << 19) */
#define X025_Q15 8192 /* 0.25 * (1 << 15) */
#define X1_732_Q14 28377 /* 1.732 * (1 << 14) */
#define X12_Q8 3072 /* 12.0 * (1 << 8) */
#define X30_Q8 7680 /* 30.0 * (1 << 8) */
#define TIME_DOMAIN_SYN FALSE
#define TILT_ORD 1
#define SCALEOVER 10
#define INV_SCALEOVER_Q18 26214 /* ((1.0/SCALEOVER)*(1 << 18)) */
#define PDEL SCALEOVER
#if (MIX_ORD > DISP_ORD)
#define BEGIN MIX_ORD
#else
#define BEGIN DISP_ORD
#endif
#define ORIGINAL_SYNTH_GAIN FALSE
#if ORIGINAL_SYNTH_GAIN
#define SYN_GAIN_Q4 16000 /* (1000.0*(1 << 4)) */
#else
#define SYN_GAIN_Q4 32000
#endif
static struct melp_param prev_par;
static Shortword sigsave[PITCHMAX];
static Shortword syn_begin;
static BOOLEAN erase;
/* Prototype */
static void melp_syn(struct melp_param *par, Shortword sp_out[]);
/****************************************************************************
**
** Function: synthesis
**
** Description: The synthesis routine for the sc1200 coder
**
** Arguments:
**
** melp_param *par ---- output encoded melp parameters
** Shortword sp_in[] ---- input speech data buffer
**
** Return value: None
**
*****************************************************************************/
void synthesis(struct melp_param *par, Shortword sp_out[])
{
register Shortword i;
/* Copy previous period of processed speech to output array */
if (syn_begin > 0){
if (syn_begin > frameSize){ /* impossible */
v_equ(sp_out, sigsave, frameSize);
/* past end: save remainder in sigsave[0] */
v_equ(sigsave, &sigsave[frameSize], (Shortword) (syn_begin - frameSize));
} else
v_equ(sp_out, sigsave, syn_begin);
}
erase = FALSE; /* no erasures yet */
/* Read and decode channel input buffer. */
if (rate == RATE2400)
erase = melp_chn_read(&quant_par, par, &prev_par, chbuf);
#if !SKIP_CHANNEL
else
erase = (BOOLEAN) low_rate_chn_read(&quant_par, par, &prev_par);
#endif
if (rate == RATE2400){
par->uv_flag = quant_par.uv_flag[0];
melp_syn(par, sp_out);
} else {
for (i = 0; i < NF; i++){
melp_syn(&par[i], &sp_out[i*FRAME]);
if ((syn_begin > 0) && (i < NF - 1))
v_equ(&sp_out[(i + 1)*FRAME], sigsave, syn_begin);
}
}
}
/* 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 */
static void melp_syn(struct melp_param *par, Shortword sp_out[])
{
register Shortword i;
static BOOLEAN firstTime = TRUE;
static Shortword noise_gain = MIN_NOISE_Q8;
static Shortword prev_lpc_gain = ONE_Q15;
static Shortword lpc_del[LPC_ORD]; /* Q0 */
static Shortword prev_tilt;
static Shortword prev_pcof[MIX_ORD + 1], prev_ncof[MIX_ORD + 1];
static Shortword disp_del[DISP_ORD];
static Shortword ase_del[LPC_ORD], tilt_del[TILT_ORD];
static Shortword pulse_del[MIX_ORD], noise_del[MIX_ORD];
Shortword fs_real[PITCHMAX];
Shortword sig2[BEGIN + PITCHMAX];
Shortword sigbuf[BEGIN + PITCHMAX];
Shortword gaincnt, 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];
Shortword lpc[LPC_ORD + 1];
Shortword ase_num[LPC_ORD + 1], ase_den[LPC_ORD];
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;
Shortword fc_prev, fc_curr, fc;
/* Update adaptive noise level estimate based on last gain */
if (firstTime){
noise_gain = par->gain[NUM_GAINFR - 1]; /* noise_gain in Q8 */
prev_tilt = 0;
v_zap(prev_pcof, MIX_ORD + 1);
v_zap(prev_ncof, MIX_ORD + 1);
prev_ncof[MIX_ORD/2] = ONE_Q15;
v_zap(disp_del, DISP_ORD);
v_zap(ase_del, LPC_ORD);
v_zap(tilt_del, TILT_ORD);
v_zap(pulse_del, MIX_ORD);
v_zap(noise_del, MIX_ORD);
firstTime = FALSE;
} else if (!erase){
for (i = 0; i < NUM_GAINFR; i++){
noise_est(par->gain[i], &noise_gain, UPCONST_Q19, DOWNCONST_Q17,
MIN_NOISE_Q8, MAX_NOISE_Q8);
/* Adjust gain based on noise level (noise suppression) */
noise_sup(&par->gain[i], noise_gain, MAX_NS_SUP_Q8, MAX_NS_ATT_Q8,
NFACT_Q8);
}
}
if (par->uv_flag && (rate == RATE1200)){
fill(par->fs_mag, ONE_Q13, NUM_HARM);
par->pitch = UV_PITCH_Q7;
par->jitter = X025_Q15;
}
/* Un-weight Fourier magnitudes */
if (!par->uv_flag && !erase)
window_Q(par->fs_mag, w_fs_inv, par->fs_mag, NUM_HARM, 14);
/* 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[1]), LPC_ORD);
/* Use LPC prediction gain for adaptive scaling */
/* lpc_gain = sqrt(lpc_pred2refl(lpc, sig2, LPC_ORD)); */
/* Here we only make use of sig2[0] from the returned value instead of */
/* using the whole array sig2[]. */
lpc_gain = lpc_pred2refl(&(lpc[1]), sig2, LPC_ORD);
lpc_gain = sqrt_fxp(lpc_gain, 15); /* lpc_gain in Q15 */
if (sig2[0] < 0)
curr_tilt = shr(sig2[0], 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 = add(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], MIX_ORD + 1); /* bp_cof in Q14 */
else
v_add(curr_ncof, bp_cof[i], MIX_ORD + 1);
}
/* Process each pitch period */
while (syn_begin < FRAME){
/* interpolate previous and current parameters */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -