📄 melp_sub.c
字号:
/*2.4 kbps MELP Proposed Federal Standard speech coderversion 1.2Copyright (c) 1996, Texas Instruments, Inc. Texas Instruments has intellectual property rights on the MELPalgorithm. The Texas Instruments contact for licensing issues forcommercial and non-government use is William Gordon, Director,Government Contracts, Texas Instruments Incorporated, SemiconductorGroup (phone 972 480 7442).*//* melp_sub.c: MELP-specific subroutines*/#include <stdio.h>#include <math.h>#include "spbstd.h"#include "mat.h"#include "melp_sub.h"#include "dsp_sub.h"#include "pit.h"/* Name: bpvc_ana.c Description: Bandpass voicing analysis Inputs: speech[] - input speech signal fpitch[] - initial (floating point) pitch estimates Outputs: bpvc[] - bandpass voicing decisions pitch[] - frame pitch estimates Returns: void Copyright (c) 1995 by Texas Instruments, Inc. All rights reserved.*//* Filter orders */#define ENV_ORD 2#define BPF_ORD 6/* Constants */static int PITCHMAX;static int PITCHMIN;static int FRAME;static int NUM_BANDS;static int PIT_BEG;static int PIT_P_FR;static int PIT_FR_BEG;static int FIRST_CNTR;static int BPF_BEG;static int NUM_PITCHES;static int LMIN;/* Static memory */static float **bpfdel;static float **envdel;static float *envdel2;static float *sigbuf;/* External variables */extern float bpf_num[], bpf_den[];void bpvc_ana(float speech[], float fpitch[], float bpvc[], float pitch[]){ float pcorr, temp; int j; /* Filter lowest band and estimate pitch */ v_equ(&sigbuf[PIT_BEG-BPF_ORD],&bpfdel[0][0],BPF_ORD); polflt(&speech[PIT_FR_BEG],&bpf_den[0],&sigbuf[PIT_BEG], BPF_ORD,PIT_P_FR); v_equ(&bpfdel[0][0],&sigbuf[PIT_BEG+FRAME-BPF_ORD],BPF_ORD); zerflt(&sigbuf[PIT_BEG],&bpf_num[0],&sigbuf[PIT_BEG], BPF_ORD,PIT_P_FR); *pitch = frac_pch(&sigbuf[FIRST_CNTR], &bpvc[0],fpitch[0],5,PITCHMIN,PITCHMAX,LMIN); for (j = 1; j < NUM_PITCHES; j++) { temp = frac_pch(&sigbuf[FIRST_CNTR], &pcorr,fpitch[j],5,PITCHMIN,PITCHMAX,LMIN); /* choose largest correlation value */ if (pcorr > bpvc[0]) { *pitch = temp; bpvc[0] = pcorr; } } /* Calculate bandpass voicing for frames */ for (j = 1; j < NUM_BANDS; j++) { /* Bandpass filter input speech */ v_equ(&sigbuf[PIT_BEG-BPF_ORD],&bpfdel[j][0],BPF_ORD); polflt(&speech[PIT_FR_BEG],&bpf_den[j*(BPF_ORD+1)],&sigbuf[PIT_BEG], BPF_ORD,PIT_P_FR); v_equ(&bpfdel[j][0],&sigbuf[PIT_BEG+FRAME-BPF_ORD],BPF_ORD); zerflt(&sigbuf[PIT_BEG],&bpf_num[j*(BPF_ORD+1)],&sigbuf[PIT_BEG], BPF_ORD,PIT_P_FR); /* Check correlations for each frame */ temp = frac_pch(&sigbuf[FIRST_CNTR], &bpvc[j],*pitch,0,PITCHMIN,PITCHMAX,LMIN); /* Calculate envelope of bandpass filtered input speech */ temp = envdel2[j]; envdel2[j] = sigbuf[PIT_BEG+FRAME-1]; v_equ(&sigbuf[PIT_BEG-ENV_ORD],&envdel[j][0],ENV_ORD); envelope(&sigbuf[PIT_BEG],temp,&sigbuf[PIT_BEG],PIT_P_FR); v_equ(&envdel[j][0],&sigbuf[PIT_BEG+FRAME-ENV_ORD],ENV_ORD); /* Check correlations for each frame */ temp = frac_pch(&sigbuf[FIRST_CNTR],&pcorr, *pitch,0,PITCHMIN,PITCHMAX,LMIN); /* reduce envelope correlation */ pcorr -= 0.1; if (pcorr > bpvc[j]) bpvc[j] = pcorr; }}void bpvc_ana_init(int fr, int pmin, int pmax, int nbands, int num_p, int lmin){ /* Initialize constants */ FRAME = fr; PITCHMIN = pmin; PITCHMAX = pmax; NUM_BANDS = nbands; NUM_PITCHES = num_p; LMIN = lmin; PIT_BEG = BPF_ORD; PIT_P_FR = ((2*PITCHMAX)+1); PIT_FR_BEG = (-PITCHMAX); FIRST_CNTR = (PIT_BEG+PITCHMAX); BPF_BEG = (PIT_BEG+PIT_P_FR-FRAME); /* Allocate memory */ MEM_2ALLOC(malloc,bpfdel,NUM_BANDS,BPF_ORD,float); v_zap(&bpfdel[0][0],NUM_BANDS*BPF_ORD); MEM_2ALLOC(malloc,envdel,NUM_BANDS,ENV_ORD,float); v_zap(&envdel[0][0],NUM_BANDS*ENV_ORD); MEM_ALLOC(malloc,envdel2,NUM_BANDS,float); v_zap(envdel2,NUM_BANDS); /* Allocate scratch buffer */ MEM_ALLOC(malloc,sigbuf,PIT_BEG+PIT_P_FR,float);}/* Name: dc_rmv.c Description: remove DC from input signal Inputs: sigin[] - input signal dcdel[] - filter delay history (size DC_ORD) frame - number of samples to filter Outputs: sigout[] - output signal dcdel[] - updated filter delay history Returns: void See_Also: Copyright (c) 1995 by Texas Instruments, Inc. All rights reserved.*//* Filter order */#define DC_ORD 4/* DC removal filter *//* 4th order Chebychev Type II 60 Hz removal filter *//* cutoff=60 Hz, stop=-30 dB */static float dc_num[DC_ORD+1] = { 0.92692416, -3.70563834, 5.55742893, -3.70563834, 0.92692416};static float dc_den[DC_ORD+1] = { 1.00000000, -3.84610723, 5.55209760, -3.56516069, 0.85918839};void dc_rmv(float sigin[], float sigout[], float dcdel[], int frame){ float *sigbuf; /* Allocate scratch buffer */ MEM_ALLOC(malloc,sigbuf,frame+DC_ORD,float); /* Remove DC from input speech */ v_equ(sigbuf,dcdel,DC_ORD); polflt(sigin,dc_den,&sigbuf[DC_ORD],DC_ORD,frame); v_equ(dcdel,&sigbuf[frame],DC_ORD); zerflt(&sigbuf[DC_ORD],dc_num,sigout,DC_ORD,frame); /* Free scratch buffer */ MEM_FREE(free,sigbuf);}/* Name: gain_ana.c Description: analyze gain level for input signal Inputs: sigin[] - input signal pitch - pitch value (for pitch synchronous window) minlength - minimum window length maxlength - maximum window length Outputs: Returns: log gain in dB See_Also: Copyright (c) 1995 by Texas Instruments, Inc. All rights reserved.*/#define MINGAIN 0.0float gain_ana(float sigin[], float pitch, int minlength, int maxlength){ int length; float flength, gain; /* Find shortest pitch multiple window length (floating point) */ flength = pitch; while (flength < minlength) flength += pitch; /* Convert window length to integer and check against maximum */ length = flength + 0.5; if (length > maxlength) length = (length/2); /* Calculate RMS gain in dB */ gain = 10.0*log10(0.01 + (v_magsq(&sigin[-(length/2)],length) / length)); if (gain < MINGAIN) gain = MINGAIN; return(gain);}/* Name: lin_int_bnd.c Description: Linear interpolation within bounds Inputs: x - input X value xmin - minimum X value xmax - maximum X value ymin - minimum Y value ymax - maximum Y value Returns: y - interpolated and bounded y value Copyright (c) 1995 by Texas Instruments, Inc. All rights reserved.*/float lin_int_bnd(float x,float xmin,float xmax,float ymin,float ymax){ float y; if (x <= xmin) y = ymin; else if (x >= xmax) y = ymax; else y = ymin + (x-xmin)*(ymax-ymin)/(xmax-xmin); return(y);}/* Name: noise_est.c Description: Estimate long-term noise floor Inputs: gain - input gain (in dB) noise_gain - current noise gain estimate up - maximum up stepsize down - maximum down stepsize min - minimum allowed gain max - maximum allowed gain Outputs: noise_gain - updated noise gain estimate Returns: void Copyright (c) 1995 by Texas Instruments, Inc. All rights reserved.*/void noise_est(float gain,float *noise_gain,float up,float down,float min,float max){ /* Update noise_gain */ if (gain > *noise_gain+up) *noise_gain = *noise_gain+up; else if (gain < *noise_gain+down) *noise_gain = *noise_gain+down; else *noise_gain = gain; /* Constrain total range of noise_gain */ if (*noise_gain < min) *noise_gain = min; if (*noise_gain > max) *noise_gain = max; }/* Name: noise_sup.c Description: Perform noise suppression on speech gain Inputs: (all in dB) gain - input gain (in dB) noise_gain - current noise gain estimate (in dB) max_noise - maximum allowed noise gain max_atten - maximum allowed attenuation nfact - noise floor boost Outputs: gain - updated gain Returns: void Copyright (c) 1995 by Texas Instruments, Inc. All rights reserved.*/void noise_sup(float *gain,float noise_gain,float max_noise,float max_atten,float nfact){ float gain_lev,suppress; /* Reduce effect for louder background noise */ if (noise_gain > max_noise) noise_gain = max_noise; /* Calculate suppression factor */ gain_lev = *gain - (noise_gain + nfact); if (gain_lev > 0.001) { suppress = -10.0*log10(1.0 - pow(10.0,-0.1*gain_lev)); if (suppress > max_atten) suppress = max_atten; } else suppress = max_atten; /* Apply suppression to input gain */ *gain -= suppress;}/* Name: q_bpvc.c, q_bpvc_dec.c Description: Quantize/decode bandpass voicing Inputs: bpvc, bpvc_index bpthresh - threshold NUM_BANDS - number of bands Outputs: bpvc, bpvc_index Returns: uv_flag - flag if unvoiced Copyright (c) 1995 by Texas Instruments, Inc. All rights reserved.*//* Compile constants */#define INVALID_BPVC 0001int q_bpvc(float *bpvc,int *bpvc_index,float bpthresh,int NUM_BANDS){ int j, uv_flag; uv_flag = 1; if (bpvc[0] > bpthresh) { /* Voiced: pack bandpass voicing */ uv_flag = 0; *bpvc_index = 0; bpvc[0] = 1.0; for (j = 1; j < NUM_BANDS; j++) { *bpvc_index <<= 1; /* left shift */ if (bpvc[j] > bpthresh) { bpvc[j] = 1.0; *bpvc_index |= 1; } else { bpvc[j] = 0.0; *bpvc_index |= 0; } } /* Don't use invalid code (only top band voiced) */ if (*bpvc_index == INVALID_BPVC) { bpvc[(NUM_BANDS-1)] = 0.0; *bpvc_index = 0; } } else { /* Unvoiced: force all bands unvoiced */ *bpvc_index = 0; for (j = 0; j < NUM_BANDS; j++) bpvc[j] = 0.0; } return(uv_flag);}void q_bpvc_dec(float *bpvc,int *bpvc_index,int uv_flag,int NUM_BANDS){ int j; if (uv_flag) { /* Unvoiced: set all bpvc to 0 */ *bpvc_index = 0; bpvc[0] = 0.0; } else { /* Voiced: set bpvc[0] to 1.0 */ bpvc[0] = 1.0; } if (*bpvc_index == INVALID_BPVC) { /* Invalid code received: set higher band voicing to zero */ *bpvc_index = 0; } /* Decode remaining bands */ for (j = NUM_BANDS-1; j > 0; j--) { if ((*bpvc_index & 1) == 1) bpvc[j] = 1.0; else bpvc[j] = 0.0; *bpvc_index >>= 1; }}/* Name: q_gain.c, q_gain_dec.c Description: Quantize/decode two gain terms using quasi-differential coding Inputs: gain[2],gain_index[2] GN_QLO,GN_QUP,GN_QLEV for second gain term Outputs: gain[2],gain_index[2] Returns: void Copyright (c) 1995 by Texas Instruments, Inc. All rights reserved.*//* Compile constants */#define GAIN_INT_DB 5.0void q_gain(float *gain,int *gain_index,float GN_QLO,float GN_QUP,float GN_QLEV){ static float prev_gain = 0.0; float temp,temp2; /* Quantize second gain term with uniform quantizer */ quant_u(&gain[1],&gain_index[1],GN_QLO,GN_QUP,GN_QLEV); /* Check for intermediate gain interpolation */ if (gain[0] < GN_QLO) gain[0] = GN_QLO; if (gain[0] > GN_QUP) gain[0] = GN_QUP; if (fabs(gain[1] - prev_gain) < GAIN_INT_DB && fabs(gain[0] - 0.5*(gain[1]+prev_gain)) < 3.0) { /* interpolate and set special code */ gain[0] = 0.5*(gain[1]+prev_gain); gain_index[0] = 0; } else { /* Code intermediate gain with 7-levels */ if (prev_gain < gain[1]) { temp = prev_gain; temp2 = gain[1]; } else { temp = gain[1]; temp2 = prev_gain; } temp -= 6.0; temp2 += 6.0; if (temp < GN_QLO) temp = GN_QLO; if (temp2 > GN_QUP) temp2 = GN_QUP; quant_u(&gain[0],&gain_index[0],temp,temp2,7); /* Skip all-zero code */ gain_index[0]++; } /* Update previous gain for next time */ prev_gain = gain[1]; }void q_gain_dec(float *gain,int *gain_index,float GN_QLO,float GN_QUP,float GN_QLEV){ static float prev_gain = 0.0; static int prev_gain_err = 0; float temp,temp2; /* Decode second gain term */ quant_u_dec(gain_index[1],&gain[1],GN_QLO,GN_QUP,GN_QLEV); if (gain_index[0] == 0) { /* interpolation bit code for intermediate gain */ if (fabs(gain[1] - prev_gain) > GAIN_INT_DB) { /* Invalid received data (bit error) */ if (prev_gain_err == 0) { /* First time: don't allow gain excursion */ gain[1] = prev_gain; } prev_gain_err = 1; } else prev_gain_err = 0; /* Use interpolated gain value */ gain[0] = 0.5*(gain[1]+prev_gain); } else { /* Decode 7-bit quantizer for first gain term */ prev_gain_err = 0; gain_index[0]--; if (prev_gain < gain[1]) { temp = prev_gain; temp2 = gain[1]; } else { temp = gain[1]; temp2 = prev_gain; } temp -= 6.0; temp2 += 6.0; if (temp < GN_QLO) temp = GN_QLO; if (temp2 > GN_QUP) temp2 = GN_QUP; quant_u_dec(gain_index[0],&gain[0],temp,temp2,7); } /* Update previous gain for next time */ prev_gain = gain[1]; }/* Name: scale_adj.c Description: Adjust scaling of output speech signal. Inputs: speech - speech signal gain - desired RMS gain prev_scale - previous scale factor length - number of samples in signal SCALEOVER - number of points to interpolate scale factor Warning: SCALEOVER is assumed to be less than length. Outputs: speech - scaled speech signal prev_scale - updated previous scale factor Returns: void Copyright (c) 1995 by Texas Instruments, Inc. All rights reserved.*/void scale_adj(float *speech, float gain, float *prev_scale, int length, int SCALEOVER){ int i; float scale; /* Calculate desired scaling factor to match gain level */ scale = gain / (sqrt(v_magsq(&speech[0],length) / length) + .01); /* interpolate scale factors for first SCALEOVER points */ for (i = 1; i < SCALEOVER; i++) { speech[i-1] *= ((scale*i + *prev_scale*(SCALEOVER-i)) * (1.0/SCALEOVER) ); } /* Scale rest of signal */ v_scale(&speech[SCALEOVER-1],scale,length-SCALEOVER+1); /* Update previous scale factor for next call */ *prev_scale = scale; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -