183 lines
4.1 KiB
C
183 lines
4.1 KiB
C
#include <math.h>
|
|
#include "nb_celp.h"
|
|
#include "lsp.h"
|
|
#include "ltp.h"
|
|
#include "quant_lsp.h"
|
|
#include "cb_search.h"
|
|
#include "filters.h"
|
|
#include "os_support.h"
|
|
|
|
#ifndef NULL
|
|
#define NULL 0
|
|
#endif
|
|
|
|
#define LSP_MARGIN .002f
|
|
#define SIG_SCALING 1.f
|
|
#define NB_DEC_BUFFER (NB_FRAME_SIZE+2*NB_PITCH_END+NB_SUBFRAME_SIZE+12)
|
|
#define NB_ORDER 10
|
|
#define NB_FRAME_SIZE 160
|
|
#define NB_SUBFRAME_SIZE 40
|
|
#define NB_NB_SUBFRAMES 4
|
|
#define NB_PITCH_START 17
|
|
#define NB_PITCH_END 144
|
|
|
|
|
|
struct speex_decode_state {
|
|
float excBuf[NB_DEC_BUFFER]; /**< Excitation buffer */
|
|
float *exc; /**< Start of excitation frame */
|
|
float old_qlsp[10]; /**< Quantized LSPs for previous frame */
|
|
float interp_qlpc[10]; /**< Interpolated quantized LPCs */
|
|
float mem_sp[10]; /**< Filter memory for synthesis signal */
|
|
int first; /**< Is this the first frame? */
|
|
};
|
|
|
|
|
|
static const float exc_gain_quant_scal1[2] = {0.70469f, 1.05127f};
|
|
|
|
|
|
struct speex_decode_state *nb_decoder_init(void)
|
|
{
|
|
struct speex_decode_state *st;
|
|
|
|
st = malloc(sizeof(*st));
|
|
if (!st)
|
|
return NULL;
|
|
|
|
memset(st, 0, sizeof(*st));
|
|
st->first = 1;
|
|
|
|
return st;
|
|
}
|
|
|
|
|
|
void nb_decoder_destroy(struct speex_decode_state *state)
|
|
{
|
|
if (state)
|
|
free(state);
|
|
}
|
|
|
|
|
|
/* basic decoder using mode3 only */
|
|
int nb_decode(struct speex_decode_state *st, SpeexBits *bits, float *out)
|
|
{
|
|
int i, sub, wideband, mode, qe;
|
|
float ol_gain;
|
|
float innov[NB_SUBFRAME_SIZE];
|
|
float exc32[NB_SUBFRAME_SIZE];
|
|
float qlsp[NB_ORDER], interp_qlsp[NB_ORDER];
|
|
float ak[NB_ORDER];
|
|
|
|
if (!bits)
|
|
return -1;
|
|
|
|
st->exc = st->excBuf + 2*NB_PITCH_END + NB_SUBFRAME_SIZE + 6;
|
|
|
|
/* Decode Sub-modes */
|
|
do {
|
|
if (speex_bits_remaining(bits) < 5)
|
|
return -1;
|
|
|
|
wideband = speex_bits_unpack_unsigned(bits, 1);
|
|
if (wideband) {
|
|
printf("wideband not supported\n");
|
|
return -2;
|
|
}
|
|
|
|
mode = speex_bits_unpack_unsigned(bits, 4);
|
|
if (mode == 15)
|
|
return -1;
|
|
|
|
} while (mode > 8);
|
|
|
|
if (mode != 3) {
|
|
printf("only mode 3 supported\n");
|
|
return -2;
|
|
}
|
|
|
|
/* Shift all buffers by one frame */
|
|
SPEEX_MOVE(st->excBuf, st->excBuf+NB_FRAME_SIZE,
|
|
2*NB_PITCH_END + NB_SUBFRAME_SIZE + 12);
|
|
|
|
/* Unquantize LSPs */
|
|
lsp_unquant_lbr(qlsp, NB_ORDER, bits);
|
|
|
|
/* Handle first frame */
|
|
if (st->first) {
|
|
st->first = 0;
|
|
|
|
for (i=0; i<NB_ORDER; i++)
|
|
st->old_qlsp[i] = qlsp[i];
|
|
}
|
|
|
|
/* Get global excitation gain */
|
|
qe = speex_bits_unpack_unsigned(bits, 5);
|
|
ol_gain = SIG_SCALING*exp(qe/3.5);
|
|
|
|
/* Loop on subframes */
|
|
for (sub=0; sub<4; sub++) {
|
|
int offset, q_energy;
|
|
float *exc, *sp;
|
|
float ener;
|
|
|
|
offset = NB_SUBFRAME_SIZE*sub;
|
|
exc = st->exc + offset;
|
|
sp = out + offset;
|
|
|
|
SPEEX_MEMSET(exc, 0, NB_SUBFRAME_SIZE);
|
|
|
|
/* Adaptive codebook contribution */
|
|
pitch_unquant_3tap(exc, exc32, NB_PITCH_START,
|
|
NB_SUBFRAME_SIZE, bits, 0);
|
|
|
|
sanitize_values32(exc32, -32000, 32000, NB_SUBFRAME_SIZE);
|
|
|
|
/* Unquantize the innovation */
|
|
SPEEX_MEMSET(innov, 0, NB_SUBFRAME_SIZE);
|
|
|
|
/* Decode sub-frame gain correction */
|
|
q_energy = speex_bits_unpack_unsigned(bits, 1);
|
|
ener = exc_gain_quant_scal1[q_energy] * ol_gain;
|
|
|
|
/* Fixed codebook contribution */
|
|
split_cb_shape_sign_unquant(innov, bits);
|
|
|
|
/* De-normalize innovation and update excitation */
|
|
signal_mul(innov, innov, ener, NB_SUBFRAME_SIZE);
|
|
|
|
for (i=0; i<NB_SUBFRAME_SIZE; i++) {
|
|
exc[i] = exc32[i] + innov[i];
|
|
}
|
|
}
|
|
|
|
SPEEX_COPY(out, &st->exc[-NB_SUBFRAME_SIZE], NB_FRAME_SIZE);
|
|
|
|
/* Loop on subframes */
|
|
for (sub=0; sub<4; sub++) {
|
|
const int offset = NB_SUBFRAME_SIZE*sub;
|
|
float *sp, *exc;
|
|
|
|
sp = out + offset;
|
|
exc = st->exc + offset;
|
|
|
|
/* LSP interpolation (quantized and unquantized) */
|
|
lsp_interpolate(st->old_qlsp, qlsp, interp_qlsp, NB_ORDER,
|
|
sub, NB_NB_SUBFRAMES, LSP_MARGIN);
|
|
|
|
/* Compute interpolated LPCs (unquantized) */
|
|
lsp_to_lpc(interp_qlsp, ak, NB_ORDER);
|
|
|
|
iir_mem16(sp, st->interp_qlpc, sp, NB_SUBFRAME_SIZE,
|
|
NB_ORDER, st->mem_sp);
|
|
|
|
/* Save for interpolation in next frame */
|
|
for (i=0; i<NB_ORDER; i++)
|
|
st->interp_qlpc[i] = ak[i];
|
|
}
|
|
|
|
/* Store the LSPs for interpolation in the next frame */
|
|
for (i=0; i<NB_ORDER; i++)
|
|
st->old_qlsp[i] = qlsp[i];
|
|
|
|
return 0;
|
|
}
|