📄 melp_ana.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.
*/
/* compiler include files */
#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 "fft_lib.h"
#include "pit_lib.h"
#include "math_lib.h"
#include "constant.h"
#include "cprv.h"
#include "global.h"
#include "pitch.h"
#include "qnt12_cb.h"
#include "qnt12.h"
#include "msvq_cb.h"
#include "fsvq_cb.h"
#include "melp_sub.h"
#include "dsp_sub.h"
#include "coeff.h"
/* compiler constants */
#define BWFACT_Q15 32571
#define HF_CORR_Q15 4 /* 0.0001220703125 in Q15 */
#define PEAK_THRESH_Q12 5488 /* 1.34 * (1 << 12) */
#define PEAK_THR2_Q12 6553 /* 1.6 * (1 << 12) */
#define SILENCE_DB_Q8 7680 /* 30.0 * (1 << 8) */
#define SIG_LENGTH (LPF_ORD + PITCH_FR) /* 327 */
#define X01_Q15 3277 /* 0.1 * (1 << 15) */
#define X03_Q11 614 /* 0.3 * (1 << 11) */
#define X04_Q14 6554 /* 0.4 * (1 << 14) */
#define X045_Q14 7273 /* 0.45 * (1 << 14) */
#define X05_Q11 1024 /* 0.5 * (1 << 11) */
#define X07_Q14 11469 /* 0.7 * (1 << 11) */
#define X08_Q11 1638 /* 0.8 * (1 << 11) */
#define X12_Q11 2458 /* 1.2 * (1 << 11) */
#define X28_Q11 5734 /* 2.8 * (1 << 11) */
#define MX01_Q15 -3277 /* -0.1 * (1 << 15) */
#define MX02_Q15 -6554 /* -0.2 * (1 << 15) */
/* memory definitions */
static Shortword sigbuf[SIG_LENGTH];
static classParam classStat[TRACK_NUM]; /* class of subframes */
static pitTrackParam pitTrack[TRACK_NUM]; /* pitch of subframes */
Shortword top_lpc[LPC_ORD];
/* Prototype */
static void melp_ana(Shortword sp_in[], struct melp_param *par,
Shortword subnum);
void sc_ana(struct melp_param *par);
static BOOLEAN subenergyRelation1(classParam classStat[], Shortword curTrack);
static BOOLEAN subenergyRelation2(classParam classStat[], Shortword curTrack);
/****************************************************************************
**
** Function: analysis
**
** Description: The analysis routine for the sc1200 coder
**
** Arguments:
**
** Shortword sp_in[] ---- input speech data buffer (Q0)
** melp_param *par ---- output encoded melp parameters
**
** Return value: None
**
*****************************************************************************/
void analysis(Shortword sp_in[], struct melp_param *par)
{
register Shortword i;
Shortword lpc[LPC_ORD + 1], weights[LPC_ORD];
Shortword num_frames;
num_frames = (Shortword) ((rate == RATE2400) ? 1 : NF);
/* ======== Compute melp parameters ======== */
for (i = 0; i < num_frames; i++){
/* Remove DC from input speech */
/* Previously the floating point version of dc_rmv() for RATE1200 */
/* uses the following filter: */
/* */
/* H(z) = N(z)/D(z), with */
/* N(z) = 0.92692416 - 3.70563834 z^{-1} + 5.55742893 z^{-2} - */
/* 3.70563834 z^{-3} + 0.92642416 z^{-4}, */
/* D(z) = 1 - 3.84610723 z^{-1} + 5.5520976 z^{-2} - */
/* 3.56516069 z^{-3} + 0.85918839 z^{-4}. */
/* It can be shown that this is equivalent to the fixed point filter */
/* (Q13) we use for RATE 2400. */
if (rate == RATE2400)
dc_rmv(&sp_in[i*FRAME], &hpspeech[OLD_IN_BEG], dcdelin,
dcdelout_hi, dcdelout_lo, FRAME);
else
dc_rmv(&sp_in[i*FRAME], &hpspeech[IN_BEG + i*FRAME], dcdelin,
dcdelout_hi, dcdelout_lo, FRAME);
melp_ana(&hpspeech[i*FRAME], &par[i], i);
}
/* ---- New routine to refine the parameters for block ---- */
if (rate == RATE1200)
sc_ana(par);
/* ======== Quantization ======== */
lpc[0] = ONE_Q12;
if (rate == RATE2400){
/* -- Quantize MELP parameters to 2400 bps and generate bitstream -- */
/* Quantize LSF's with MSVQ */
v_equ(&(lpc[1]), top_lpc, LPC_ORD);
vq_lspw(weights, par->lsf, &(lpc[1]), LPC_ORD);
/* msvq_enc(par->lsf, weights, par->lsf, vq_par); */
vq_ms4(msvq_cb, par->lsf, msvq_cb_mean, msvq_levels, MSVQ_M, 4,
LPC_ORD, weights, par->lsf, quant_par.msvq_index, MSVQ_MAXCNT);
/* Force minimum LSF bandwidth (separation) */
lpc_clamp(par->lsf, BWMIN_Q15, LPC_ORD);
} else
lsf_vq(par);
if (rate == RATE2400){
/* 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, &(quant_par.pitch_index), PIT_QLO_Q12,
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);
} else
pitch_vq(par);
if (rate == RATE2400){
/* Quantize gain terms with uniform log quantizer */
q_gain(par->gain, quant_par.gain_index, GN_QLO_Q8, GN_QUP_Q8,
GN_QLEV_M1, GN_QLEV_M1_Q10, 0, 5);
} else
gain_vq(par);
if (rate == RATE2400){ /* Quantize jitter */
/* quant_u(&par->jitter, &par->jit_index, 0, MAX_JITTER_Q15, 2); */
if (par->jitter < shr(MAX_JITTER_Q15, 1)){
par->jitter = 0;
quant_par.jit_index[0] = 0;
} else {
par->jitter = MAX_JITTER_Q15;
quant_par.jit_index[0] = 1;
}
} else {
for (i = 0; i < NF; i++)
quant_u(&par[i].jitter, &(quant_par.jit_index[i]), 0,
MAX_JITTER_Q15, 2, ONE_Q15, 1, 7);
}
/* Quantize bandpass voicing */
if (rate == RATE2400)
par[0].uv_flag = q_bpvc(par[0].bpvc, &(quant_par.bpvc_index[0]),
NUM_BANDS);
else
quant_bp(par, num_frames);
if (rate == RATE1200)
quant_jitter(par);
/* Calculate Fourier coeffs of residual from quantized LPC */
for (i = 0; i < num_frames; i++){
/* The following fill() action is believed to be unnecessary. */
fill(par[i].fs_mag, ONE_Q13, NUM_HARM);
if (!par[i].uv_flag){
lpc_lsp2pred(par[i].lsf, &(lpc[1]), LPC_ORD);
zerflt(&hpspeech[(i*FRAME + FRAME_END - (LPC_FRAME/2))], lpc,
sigbuf, LPC_ORD, LPC_FRAME);
window(sigbuf, win_cof, sigbuf, LPC_FRAME);
find_harm(sigbuf, par[i].fs_mag, par[i].pitch, NUM_HARM,
LPC_FRAME);
}
}
if (rate == RATE2400){
/* quantize Fourier coefficients */
/* pre-weight vector, then use Euclidean distance */
window_Q(par->fs_mag, w_fs, par->fs_mag, NUM_HARM, 14);
/* fsvq_enc(par->fs_mag, par->fs_mag, fs_vq_par); */
/* Later it is found that we do not need the structured variable */
/* fs_vq_par at all. References to its individual fields can be */
/* replaced directly with constants or other variables. */
vq_enc(fsvq_cb, par->fs_mag, FS_LEVELS, NUM_HARM, par->fs_mag,
&(quant_par.fsvq_index));
} else
quant_fsmag(par);
for (i = 0; i < num_frames; i++)
quant_par.uv_flag[i] = par[i].uv_flag;
/* Write channel bitstream */
if (rate == RATE2400)
melp_chn_write(&quant_par, chbuf);
#if !SKIP_CHANNEL
else
low_rate_chn_write(&quant_par);
#endif
/* Update delay buffers for next block */
v_equ(hpspeech, &(hpspeech[num_frames*FRAME]), IN_BEG);
}
/* ========================================================================== */
/* Name: melp_ana.c */
/* Description: MELP analysis */
/* Inputs: */
/* speech[] - input speech signal */
/* subnum - subframe index */
/* Outputs: */
/* *par - MELP parameter structure */
/* Returns: void */
/* ========================================================================== */
static void melp_ana(Shortword speech[], struct melp_param *par,
Shortword subnum)
{
register Shortword i;
static BOOLEAN firstTime = TRUE;
static Shortword lpfsp_delin[LPF_ORD];
static Shortword lpfsp_delout[LPF_ORD];
static Shortword pitch_avg;
static Shortword fpitch[NUM_PITCHES];
Shortword cur_track, begin;
Shortword sub_pitch;
Shortword temp, dontcare, pcorr;
Shortword auto_corr[EN_FILTER_ORDER], lpc[LPC_ORD + 1];
Shortword section;
Shortword temp_delin[LPF_ORD];
Shortword temp_delout[LPF_ORD];
if (firstTime){
v_zap(lpfsp_delin, LPF_ORD); /* Release V2 only use "lpfsp_del". */
v_zap(lpfsp_delout, LPF_ORD);
pitch_avg = DEFAULT_PITCH_Q7;
fill(fpitch, DEFAULT_PITCH_Q7, 2);
firstTime = FALSE;
}
/* Copy input speech to pitch window and lowpass filter */
/* The following filter block was in use in the fixed point implementa- */
/* tion of RATE2400. As a comparision, the floating point version of */
/* RATE1200 uses the following filter: */
/* */
/* H(z) = N(z)/D(z), with */
/* N(z) = 0.00105165 + 0.00630988 z^{-1} + 0.01577470 z^{-2} + */
/* 0.02103294 z^{-3} + 0.01577470 z^{-4} + */
/* 0.00630988 z^{-5} + 0.00105165 z^{-6}, */
/* D(z) = 1 - 2.97852993 z^{-1} + 4.136081 z^{-2} - */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -