Commit bda27d49 authored by jmvalin's avatar jmvalin
Browse files

Added low bit-rate (8 kbps) narrowband mode. It is still sub-optimal but

at least it seems to work...


git-svn-id: http://svn.xiph.org/trunk/speex@3373 0101bb08-14d6-0310-b084-bc0e0c8e3800
parent a9dbf50c
## Process this file with automake to produce Makefile.in. -*-Makefile-*-
# $Id: Makefile.am,v 1.30 2002/06/05 06:07:18 jmvalin Exp $
# $Id: Makefile.am,v 1.31 2002/06/11 06:08:31 jmvalin Exp $
# Disable automatic dependency tracking if using other tools than gcc and gmake
#AUTOMAKE_OPTIONS = no-dependencies
......@@ -27,6 +27,7 @@ libspeex_la_SOURCES = nb_celp.c \
hexc_table.c \
exc_5_256_table.c \
exc_5_64_table.c \
exc_10_32_table.c \
post_filter.c
......
float exc_10_32_table[32][10]={{-0.0650833,-0.0127175,0.15243,0.412487,0.70276,0.648247,0.239389,-0.481389,-0.971266,-0.782175},
{0.823255,-1.38751,1.46535,-0.74324,-0.0729989,0.310202,-0.346112,0.364435,-0.304743,0.208398},
{0.925485,-1.02196,0.269,0.67272,-0.984351,0.76207,-0.315047,-0.121744,0.192334,-0.135836},
{-0.629032,0.849876,-0.951448,0.75439,-0.0329939,-0.700964,0.876844,-0.690453,0.564513,-0.394044},
{-0.0417819,0.0446498,-0.0210186,-0.0319054,0.0492155,0.1814,-0.984497,1.96363,-1.62843,0.480187},
{0.159291,-0.155808,0.0397108,-0.287783,1.25157,-1.71232,0.555061,0.704883,-0.61184,0.117399},
{-1.01205,1.80694,-1.64157,0.683777,-0.2295,0.290442,-0.276946,0.204107,-0.201362,0.218884},
{0.112654,-0.132651,0.129492,-0.152157,0.204945,-0.22453,0.357274,-1.04578,1.98288,-1.84874},
{0.184115,0.246724,0.0753163,-0.120653,-0.487387,-0.594183,-0.528711,0.138581,0.767295,1.22995},
{1.29268,0.594388,-0.236972,-0.532,-0.266004,-0.106981,0.0568159,-0.0222551,-0.0831287,-0.190151},
{-0.805679,0.964487,-1.1675,1.3281,-1.24135,0.999758,-0.941164,0.922136,-0.852255,0.737061},
{0.842752,-1.21308,1.49299,-1.42549,1.18894,-0.959532,0.85528,-0.747771,0.658172,-0.60694},
{-0.0532811,0.0787138,-0.122763,0.0329663,0.0427411,0.62878,-1.74116,1.22109,0.365764,-0.678148},
{-0.750448,0.1252,1.27873,-0.747464,-0.640997,0.404841,0.321208,-0.277069,0.00380886,0.0361227},
{-0.13398,0.245071,-0.162342,0.107937,-0.156469,0.127712,-0.155854,0.195145,-0.279554,0.167991},
{-0.685915,-0.434041,0.461219,0.814491,0.437365,-0.364736,-0.672887,-0.323771,0.129575,0.252148},
{-0.0659221,-0.517433,0.366341,0.833583,-0.913421,-0.695998,0.86603,0.531177,-0.508925,-0.271964},
{1.82897,-1.59782,0.343249,-0.138259,0.449941,-0.40065,0.239173,-0.244677,0.276439,-0.223304},
{0.694612,0.0273125,-1.50751,1.27622,0.0148847,-0.186515,-0.237778,0.238604,-0.105283,0.086892},
{0.120101,-0.100098,0.0237457,0.117561,-0.298729,0.0549176,1.04098,-2.00316,1.27185,-0.112897},
{-0.0732836,0.0706076,-0.115325,0.116897,-0.150037,0.2285,-0.2878,0.602568,-1.58479,2.02217},
{-0.624569,0.9511,-0.225748,-1.10234,1.34359,-0.63785,0.280883,-0.271444,0.297317,-0.208585},
{-1.78726,1.12847,-0.0442747,0.113599,-0.219116,0.180292,-0.164597,0.294796,-0.309492,0.168715},
{-0.0954666,0.0746028,-0.0196098,0.0594211,-0.132036,0.0351186,-0.063248,0.438139,0.525251,-1.87477},
{0.101718,-0.0828372,0.0866638,-0.183715,0.168252,-0.419872,1.08406,-0.856321,-0.747,1.31035},
{0.351146,-0.394581,0.404593,-0.339666,0.374607,-0.414098,0.334761,-0.347885,0.425438,-0.3967},
{-0.313345,0.482818,-0.688464,1.27194,-1.67114,1.07701,-0.103382,-0.330088,0.33062,-0.195219},
{0.0849411,-0.132119,0.249548,-0.495836,1.01882,-1.67923,1.85051,-1.34076,0.829642,-0.600037},
{0.0469392,-0.046845,-0.00332371,0.376391,-1.20727,1.81952,-1.56888,0.962301,-0.75061,0.623107},
{0.0976541,-0.35783,1.01755,-1.62301,1.29225,-0.187937,-0.467274,0.421445,-0.350532,0.296101},
{0.0348442,0.380331,-0.245299,-0.615952,0.252616,1.18765,-0.809042,-0.743674,0.575318,0.253249},
{-0.592265,-0.797179,-0.715578,-0.374579,0.0758649,0.412432,0.568196,0.618405,0.448291,0.250063}};
......@@ -28,7 +28,7 @@
#define abs(x) ((x)<0 ? -(x) : (x))
static void open_loop_nbest_pitch(float *sw, int start, int end, int len, int *pitch, int N, float *stack)
void open_loop_nbest_pitch(float *sw, int start, int end, int len, int *pitch, int N, float *stack)
{
int i,j,k;
float corr;
......
......@@ -27,6 +27,8 @@ typedef struct ltp_params {
} ltp_params;
void open_loop_nbest_pitch(float *sw, int start, int end, int len, int *pitch, int N, float *stack);
/** Finds the best quantized 3-tap pitch predictor by analysis by synthesis */
int pitch_search_3tap(
......
......@@ -33,6 +33,7 @@ extern float gain_cdbk_nb[];
extern float hexc_table[];
extern float exc_5_256_table[];
extern float exc_5_64_table[];
extern float exc_10_32_table[];
/* Post-filter parameters for narrowband */
pf_params pf_params_nb = {
......@@ -55,7 +56,23 @@ ltp_params ltp_params_nb = {
7
};
/* Split-VQ innovation parameters */
/* Parameters for Long-Term Prediction (LTP)*/
ltp_params ltp_params_lbr = {
gain_cdbk_nb,
5,
4
};
/* Split-VQ innovation parameters for low bit-rate narrowband */
split_cb_params split_cb_nb_lbr = {
10, /*subvect_size*/
4, /*nb_subvect*/
exc_10_32_table, /*shape_cb*/
5, /*shape_bits*/
};
/* Split-VQ innovation parameters narrowband */
split_cb_params split_cb_nb = {
5, /*subvect_size*/
8, /*nb_subvect*/
......@@ -63,6 +80,7 @@ split_cb_params split_cb_nb = {
6, /*shape_bits*/
};
/* Split-VQ innovation for low-band wideband */
split_cb_params split_cb_sb = {
5, /*subvect_size*/
8, /*nb_subvect*/
......@@ -70,6 +88,7 @@ split_cb_params split_cb_sb = {
8, /*shape_bits*/
};
/* Split-VQ innovation for high-band wideband */
static split_cb_params split_cb_high = {
8, /*subvect_size*/
5, /*nb_subvect*/
......@@ -86,6 +105,7 @@ SpeexNBMode nb_mode = {
640, /*bufSize*/
17, /*pitchStart*/
144, /*pitchEnd*/
0, /*lbr_pitch*/
0.9, /*gamma1*/
0.6, /*gamma2*/
.005, /*lag_factor*/
......@@ -106,6 +126,39 @@ SpeexNBMode nb_mode = {
&pf_params_nb
};
/* Default mode for narrowband */
SpeexNBMode nb_lbr_mode = {
160, /*frameSize*/
40, /*subframeSize*/
320, /*windowSize*/
10, /*lpcSize*/
640, /*bufSize*/
17, /*pitchStart*/
144, /*pitchEnd*/
1, /*lbr_pitch*/
0.9, /*gamma1*/
0.6, /*gamma2*/
.005, /*lag_factor*/
1.0001, /*lpc_floor*/
0.0, /*preemph*/
/*LSP quantization*/
lsp_quant_lbr,
lsp_unquant_lbr,
/*Pitch quantization*/
pitch_search_3tap,
pitch_unquant_3tap,
&ltp_params_lbr,
/*Innovation quantization*/
split_cb_search_nogain2,
split_cb_nogain_unquant,
&split_cb_nb_lbr,
nb_post_filter,
&pf_params_nb
};
/* Narrowband mode used for split-band wideband CELP*/
static SpeexNBMode low_sb_mode = {
160, /*frameSize*/
......@@ -115,6 +168,7 @@ static SpeexNBMode low_sb_mode = {
640, /*bufSize*/
17, /*pitchStart*/
144, /*pitchEnd*/
0, /*lbr_pitch*/
.9, /*gamma1*/
0.6, /*gamma2*/
.002, /*lag_factor*/
......@@ -159,6 +213,18 @@ SpeexMode speex_nb_mode = {
&nb_decoder_ctl,
};
SpeexMode speex_nb_lbr_mode = {
&nb_lbr_mode,
&nb_encoder_init,
&nb_encoder_destroy,
&nb_encode,
&nb_decoder_init,
&nb_decoder_destroy,
&nb_decode,
&nb_encoder_ctl,
&nb_decoder_ctl,
};
/* Split-band wideband CELP mode*/
static SpeexSBMode sb_wb_mode = {
&low_wb_mode,
......
......@@ -58,6 +58,7 @@ typedef struct SpeexNBMode {
int bufSize;
int pitchStart;
int pitchEnd;
int lbr_pitch;
float gamma1;
float gamma2;
float lag_factor;
......
......@@ -36,6 +36,11 @@
#define M_PI 3.14159265358979323846 /* pi */
#endif
/*float exc_gain_quant_scal[8]={-1.24094, -0.439969, -0.66471, 0.371277, -1.90821, -0.213486, -0.908305, 0.0211083};*/
float exc_gain_quant_scal[8]={-2.794750, -1.810660, -1.169850, -0.848119, -0.587190, -0.329818, -0.063266, 0.282826};
float exc_gain_quant_scal16[16]={-2.941970, -2.375000, -1.918470, -1.546230, -1.266590, -1.073730, -0.916557, -0.777102, -0.648242, -0.521670, -0.394253, -0.265417, -0.127491, 0.015092, 0.198158, 0.470588};
#define sqr(x) ((x)*(x))
#define min(a,b) ((a) < (b) ? (a) : (b))
......@@ -60,6 +65,7 @@ void *nb_encoder_init(SpeexMode *m)
st->gamma2=mode->gamma2;
st->min_pitch=mode->pitchStart;
st->max_pitch=mode->pitchEnd;
st->lbr_pitch=mode->lbr_pitch;
st->lag_factor=mode->lag_factor;
st->lpc_floor = mode->lpc_floor;
st->preemph = mode->preemph;
......@@ -167,7 +173,9 @@ void nb_encode(void *state, float *in, SpeexBits *bits)
EncState *st;
int i, sub, roots;
float error;
int ol_pitch;
float ol_gain;
st=state;
/* Copy new data in input buffer */
memmove(st->inBuf, st->inBuf+st->frameSize, (st->bufSize-st->frameSize)*sizeof(float));
......@@ -233,6 +241,51 @@ void nb_encode(void *state, float *in, SpeexBits *bits)
st->old_qlsp[i] = st->qlsp[i];
}
/* Whole frame analysis */
{
for (i=0;i<st->lpcSize;i++)
st->interp_lsp[i] = .5*st->old_lsp[i] + .5*st->lsp[i];
lsp_enforce_margin(st->interp_lsp, st->lpcSize, .002);
/* Compute interpolated LPCs (unquantized) */
for (i=0;i<st->lpcSize;i++)
st->interp_lsp[i] = cos(st->interp_lsp[i]);
lsp_to_lpc(st->interp_lsp, st->interp_lpc, st->lpcSize,st->stack);
bw_lpc(st->gamma1, st->interp_lpc, st->bw_lpc1, st->lpcSize);
bw_lpc(st->gamma2, st->interp_lpc, st->bw_lpc2, st->lpcSize);
residue(st->frame, st->bw_lpc1, st->exc, st->frameSize, st->lpcSize);
syn_filt(st->exc, st->bw_lpc2, st->sw, st->frameSize, st->lpcSize);
open_loop_nbest_pitch(st->sw, st->min_pitch, st->max_pitch, st->frameSize, &ol_pitch, 1, st->stack);
printf ("ol_pitch: %d\n", ol_pitch);
if (st->lbr_pitch)
speex_bits_pack(bits, ol_pitch-st->min_pitch, 7);
residue(st->frame, st->interp_lpc, st->exc, st->frameSize, st->lpcSize);
ol_gain=0;
for (i=0;i<st->frameSize;i++)
ol_gain += st->exc[i]*st->exc[i];
ol_gain=sqrt(1+ol_gain/st->frameSize);
printf ("ol_gain: %f\n", ol_gain);
if (1) {
int qe = (int)(floor(3.5*log(ol_gain)));
if (qe<0)
qe=0;
if (qe>31)
qe=31;
ol_gain = exp(qe/3.5);
speex_bits_pack(bits, qe, 5);
}
}
/* Loop on sub-frames */
for (sub=0;sub<st->nbSubframes;sub++)
{
......@@ -359,9 +412,21 @@ void nb_encode(void *state, float *in, SpeexBits *bits)
exc[i]=0;
/* Long-term prediction */
pitch = st->ltp_quant(target, sw, st->interp_qlpc, st->bw_lpc1, st->bw_lpc2,
exc, st->ltp_params, st->min_pitch, st->max_pitch,
st->lpcSize, st->subframeSize, bits, st->stack, exc2);
if (st->lbr_pitch)
{
int pit_min, pit_max;
if (ol_pitch < st->min_pitch+7)
ol_pitch=st->min_pitch+7;
pit_min = ol_pitch-7;
pit_max = ol_pitch+8;
pitch = st->ltp_quant(target, sw, st->interp_qlpc, st->bw_lpc1, st->bw_lpc2,
exc, st->ltp_params, pit_min, pit_max,
st->lpcSize, st->subframeSize, bits, st->stack, exc2);
} else
pitch = st->ltp_quant(target, sw, st->interp_qlpc, st->bw_lpc1, st->bw_lpc2,
exc, st->ltp_params, st->min_pitch, st->max_pitch,
st->lpcSize, st->subframeSize, bits, st->stack, exc2);
printf ("cl_pitch: %d\n", pitch);
st->pitch[sub]=pitch;
/* Update target for adaptive codebook contribution */
......@@ -443,7 +508,21 @@ void nb_encode(void *state, float *in, SpeexBits *bits)
ener+=st->buf2[i]*st->buf2[i];
ener=sqrt(.1+ener/st->subframeSize);
printf ("cl_ener: %f %f\n", ener, ol_gain);
if (0){
static float old_ener=1;
if (sub)
printf ("ener: %f %f\n", old_ener, ener);
old_ener=ener;
}
ener /= ol_gain;
{
float ratio = log(ener);
if (ratio<-3)
ratio=-3;
printf ("ener_ratio: %f\n", ratio);
}
if (0) {
int qe = (int)(floor(7*log(ener)));
if (qe<0)
qe=0;
......@@ -451,7 +530,17 @@ void nb_encode(void *state, float *in, SpeexBits *bits)
qe=63;
ener = exp(qe/7.0);
speex_bits_pack(bits, qe, 6);
} else {
int qe;
ener=log(ener);
qe = vq_index(&ener, exc_gain_quant_scal, 1, 8);
speex_bits_pack(bits, qe, 3);
ener=exc_gain_quant_scal[qe];
ener=exp(ener);
printf ("encode gain: %d %f\n", qe, ener);
}
ener*=ol_gain;
printf ("transmit gain: %f\n", ener);
ener_1 = 1/ener;
for (i=0;i<st->subframeSize;i++)
......@@ -556,6 +645,7 @@ void *nb_decoder_init(SpeexMode *m)
st->gamma2=mode->gamma2;
st->min_pitch=mode->pitchStart;
st->max_pitch=mode->pitchEnd;
st->lbr_pitch=mode->lbr_pitch;
st->preemph = mode->preemph;
st->pre_mem=0;
......@@ -624,7 +714,8 @@ void nb_decode(void *state, SpeexBits *bits, float *out, int lost)
int i, sub;
int pitch;
float pitch_gain[3];
float ol_gain;
int ol_pitch;
st=state;
memmove(st->inBuf, st->inBuf+st->frameSize, (st->bufSize-st->frameSize)*sizeof(float));
......@@ -639,6 +730,16 @@ void nb_decode(void *state, SpeexBits *bits, float *out, int lost)
st->old_qlsp[i] = st->qlsp[i];
}
if (st->lbr_pitch)
ol_pitch = st->min_pitch+speex_bits_unpack_unsigned(bits, 7);
{
int qe;
qe = speex_bits_unpack_unsigned(bits, 5);
ol_gain = exp(qe/3.5);
printf ("decode_ol_gain: %f\n", ol_gain);
}
/*Loop on subframes */
for (sub=0;sub<st->nbSubframes;sub++)
{
......@@ -680,7 +781,16 @@ void nb_decode(void *state, SpeexBits *bits, float *out, int lost)
exc[i]=0;
/*Adaptive codebook contribution*/
st->ltp_unquant(exc, st->min_pitch, st->max_pitch, st->ltp_params, st->subframeSize, &pitch, &pitch_gain[0], bits, st->stack, lost);
if (st->lbr_pitch)
{
int pit_min, pit_max;
if (ol_pitch < st->min_pitch+7)
ol_pitch=st->min_pitch+7;
pit_min = ol_pitch-7;
pit_max = ol_pitch+8;
st->ltp_unquant(exc, pit_min, pit_max, st->ltp_params, st->subframeSize, &pitch, &pitch_gain[0], bits, st->stack, lost);
} else
st->ltp_unquant(exc, st->min_pitch, st->max_pitch, st->ltp_params, st->subframeSize, &pitch, &pitch_gain[0], bits, st->stack, lost);
{
......@@ -692,8 +802,12 @@ void nb_decode(void *state, SpeexBits *bits, float *out, int lost)
for (i=0;i<st->subframeSize;i++)
innov[i]=0;
q_energy = speex_bits_unpack_unsigned(bits, 6);
ener = exp(q_energy/7.0);
q_energy = speex_bits_unpack_unsigned(bits, 3);
/*ener = exp(q_energy/7.0);*/
ener = ol_gain*exp(exc_gain_quant_scal[q_energy]);
printf ("decode_cl_gain: %f\n", ener);
/*printf ("unquant_energy: %d %f\n", q_energy, ener);*/
/*Fixed codebook contribution*/
......
......@@ -35,6 +35,7 @@ typedef struct EncState {
int bufSize; /* Buffer size */
int min_pitch; /* Minimum pitch value allowed */
int max_pitch; /* Maximum pitch value allowed */
int lbr_pitch; /* Forces pitch to be within +-7 samples of open-loop pitch*/
int ol_pitch; /* Open-loop pitch */
int ol_voiced; /* Open-loop voiced/non-voiced decision */
int *pitch;
......@@ -93,6 +94,7 @@ typedef struct DecState {
int bufSize; /* Buffer size */
int min_pitch; /* Minimum pitch value allowed */
int max_pitch; /* Maximum pitch value allowed */
int lbr_pitch; /* Forces pitch to be within +-7 samples of open-loop pitch*/
float gamma1; /* Perceptual filter: A(z/gamma1) */
float gamma2; /* Perceptual filter: A(z/gamma2) */
float preemph; /* Pre-emphasis: P(z) = 1 - a*z^-1*/
......
......@@ -152,6 +152,64 @@ void lsp_unquant_nb(float *lsp, int order, SpeexBits *bits)
}
void lsp_quant_lbr(float *lsp, float *qlsp, int order, SpeexBits *bits)
{
int i;
float tmp1, tmp2;
int id;
for (i=0;i<order;i++)
qlsp[i]=lsp[i];
quant_weight[0] = 1/(qlsp[1]-qlsp[0]);
quant_weight[order-1] = 1/(qlsp[order-1]-qlsp[order-2]);
for (i=1;i<order-1;i++)
{
#if 1
tmp1 = 1/((.15+qlsp[i]-qlsp[i-1])*(.15+qlsp[i]-qlsp[i-1]));
tmp2 = 1/((.15+qlsp[i+1]-qlsp[i])*(.15+qlsp[i+1]-qlsp[i]));
#else
tmp1 = 1/(qlsp[i]-qlsp[i-1]);
tmp2 = 1/(qlsp[i+1]-qlsp[i]);
#endif
quant_weight[i] = tmp1 > tmp2 ? tmp1 : tmp2;
}
id = lsp_quant(qlsp, cdbk_nb, NB_CDBK_SIZE, order);
speex_bits_pack(bits, id, 6);
id = lsp_weight_quant(qlsp, quant_weight, cdbk_nb_low1, NB_CDBK_SIZE_LOW1, 5);
speex_bits_pack(bits, id, 6);
id = lsp_weight_quant(qlsp+5, quant_weight+5, cdbk_nb_high1, NB_CDBK_SIZE_HIGH1, 5);
speex_bits_pack(bits, id, 6);
for (i=0;i<order;i++)
qlsp[i]=lsp[i]-qlsp[i];
}
void lsp_unquant_lbr(float *lsp, int order, SpeexBits *bits)
{
int i, id;
for (i=0;i<order;i++)
lsp[i]=0;
id=speex_bits_unpack_unsigned(bits, 6);
for (i=0;i<10;i++)
lsp[i] += cdbk_nb[id*10+i];
id=speex_bits_unpack_unsigned(bits, 6);
for (i=0;i<5;i++)
lsp[i] += cdbk_nb_low1[id*5+i];
id=speex_bits_unpack_unsigned(bits, 6);
for (i=0;i<5;i++)
lsp[i+5] += cdbk_nb_high1[id*5+i];
}
extern float lsp_cdbk_wb[];
extern float lsp_cdbk_wb11[];
extern float lsp_cdbk_wb12[];
......
......@@ -43,6 +43,12 @@ void lsp_quant_nb(float *lsp, float *qlsp, int order, SpeexBits *bits);
/* Decodes quantized narrowband LSPs */
void lsp_unquant_nb(float *lsp, int order, SpeexBits *bits);
/* Quantizes low bit-rate narrowband LSPs with 18 bits */
void lsp_quant_lbr(float *lsp, float *qlsp, int order, SpeexBits *bits);
/* Decodes quantized low bit-rate narrowband LSPs */
void lsp_unquant_lbr(float *lsp, int order, SpeexBits *bits);
/* Quantizes wideband LSPs with 50 bits */
void lsp_quant_wb(float *lsp, float *qlsp, int order, SpeexBits *bits);
......
......@@ -111,6 +111,9 @@ void speex_decoder_ctl(void *state, int request, void *ptr);
/** Default narrowband mode */
extern SpeexMode speex_nb_mode;
/** Low bit-rate narrowband mode */
extern SpeexMode speex_nb_lbr_mode;
/** Default wideband mode */
extern SpeexMode speex_wb_mode;
......
......@@ -24,9 +24,17 @@
#define SPEEX_HEADER_H
typedef struct SpeexHeader {
char speex_version[20];
int speex_header_version;
int rate;
int mode;
int nb_channels;
int byte_rate;
int frame_size;
} SpeexHeader;
char *speex_header_to_packet(SpeexHeader *header, int *size);
SpeexHeader *speex_packet_to_header(char *packet, int size);
#endif
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment