/* * broadvoice - a library for the BroadVoice 16 and 32 codecs * * bv16lspquan.c - LSP quantization based on inter-frame moving-average * prediction and two-stage VQ. * * Adapted by Steve Underwood from code which is * Copyright 2000-2009 Broadcom Corporation * * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 2.1, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /*! \file */ #if defined(HAVE_CONFIG_H) #include "config.h" #endif #include #include "typedef.h" #include "bv16externs.h" #include "bvcommon.h" void vqmse(Float *xq, int16_t *idx, Float *x, const Float *cb, int vdim, int cbsz); void svqwmse(Float *xq, int16_t *idx, Float *x, Float *xa, Float *w, const Float *cb, int vdim, int cbsz); void lspquan(Float *lspq, int16_t *lspidx, Float *lsp, Float *lsppm) { Float d[LPCO]; Float w[LPCO]; Float elsp[LPCO]; Float lspe[LPCO]; Float lspa[LPCO]; Float lspeq1[LPCO]; Float lspeq2[LPCO]; Float a0; Float *fp1; const Float *fp2; const Float *fp3; int i; int k; /* Calculate the weights for weighted mean-square error distortion */ for (i = 0; i < LPCO - 1; i++) d[i] = lsp[i + 1] - lsp[i]; /* LSP difference vector */ w[0] = 1.0F/d[0]; for (i = 1; i < LPCO - 1; i++) { if (d[i] < d[i-1]) w[i] = 1.0F/d[i]; else w[i] = 1.0F/d[i - 1]; } w[LPCO - 1] = 1.0F/d[LPCO - 2]; /* Calculate estimated (ma-predicted) lsp vector */ fp3 = bv16_lspp; fp2 = lsppm; for (i = 0; i < LPCO; i++) { a0 = 0.0F; for (k = 0; k < LSPPORDER; k++) a0 += *fp3++ * *fp2++; elsp[i] = a0; } /* Subtract lsp mean value & estimated lsp to get prediction error */ for (i = 0; i < LPCO; i++) lspe[i] = lsp[i] - bv16_lspmean[i] - elsp[i]; /* Perform first-stage mse vq codebook search */ vqmse(lspeq1, &lspidx[0], lspe, bv16_lspecb1, LPCO, LSPECBSZ1); /* Calculate quantization error vector of first-stage vq */ for (i = 0; i < LPCO; i++) d[i] = lspe[i] - lspeq1[i]; /* Perform second-stage vq codebook search, signed codebook with wmse */ for (i = 0; i < LPCO; i++) lspa[i] = bv16_lspmean[i] + elsp[i] + lspeq1[i]; svqwmse(lspeq2, &lspidx[1], d, lspa, w, bv16_lspecb2, LPCO, LSPECBSZ2); /* Get overall quantizer output vector of the two-stage vq */ for (i = 0; i < LPCO; i++) lspe[i] = lspeq1[i] + lspeq2[i]; /* Update lsp ma predictor memory */ i = LPCO * LSPPORDER - 1; fp1 = &lsppm[i]; fp2 = &lsppm[i - 1]; for (i = LPCO - 1; i >= 0; i--) { for (k = LSPPORDER; k > 1; k--) *fp1-- = *fp2--; *fp1-- = lspe[i]; fp2--; } /* Calculate quantized lsp */ for (i = 0; i < LPCO; i++) lspq[i] = lspa[i] + lspeq2[i]; /* Ensure correct ordering of lsp to guarantee lpc filter stability */ stblz_lsp(lspq, LPCO); } void vqmse(Float *xq, /* VQ output vector (quantized version of input vector) */ int16_t *idx, /* VQ codebook index for the nearest neighbor */ Float *x, /* input vector */ const Float *cb, /* VQ codebook */ int vdim, /* vector dimension */ int cbsz) /* codebook size (number of codevectors) */ { const Float *fp1; Float dmin; Float d; int j; int k; Float e; fp1 = cb; dmin = 1.0e30; for (j = 0; j < cbsz; j++) { d = 0.0F; for (k = 0; k < vdim; k++) { e = x[k] - (*fp1++); d += e*e; } if (d < dmin) { dmin = d; *idx = (int16_t) j; } } j = *idx * vdim; for (k = 0; k < vdim; k++) xq[k] = cb[j + k]; } /* Signed WMSE VQ */ void svqwmse(Float *xq, /* VQ output vector (quantized version of input vector) */ int16_t *idx, /* VQ codebook index for the nearest neighbor */ Float *x, /* input vector */ Float *xa, /* approximation prior to current stage */ Float *w, /* weights for weighted Mean-Square Error */ const Float *cb, /* VQ codebook */ int vdim, /* vector dimension */ int cbsz) /* codebook size (number of codevectors) */ { const Float *fp1; const Float *fp2; Float dmin; Float d; Float xqc[STBLDIM]; int j; int k; int stbl; int sign = 1; Float e; fp1 = cb; dmin = 1e30; *idx = -1; for (j = 0; j < cbsz; j++) { /* Try negative sign */ d = 0.0; fp2 = fp1; for (k = 0; k < vdim; k++) { e = x[k] + *fp1++; d += w[k]*e*e; } /* Check candidate - negative sign */ if (d < dmin) { for (k = 0; k < STBLDIM; k++) xqc[k] = xa[k] - *fp2++; /* Check stability - negative sign */ stbl = stblchck(xqc, STBLDIM); if (stbl > 0) { dmin = d; *idx = (int16_t) j; sign = -1; } } /* Try positive sign */ fp1 -= vdim; d = 0.0; fp2 = fp1; for (k = 0; k < vdim; k++) { e = x[k] - *fp1++; d += w[k]*e*e; } /* Check candidate - positive sign */ if (d < dmin) { for (k = 0; k < STBLDIM; k++) xqc[k] = xa[k] + *fp2++; /* Check stability - positive sign */ stbl = stblchck(xqc, STBLDIM); if (stbl > 0) { dmin = d; *idx = (int16_t) j; sign = +1; } } } if (*idx == -1) { printf("\nWARNING: Encoder-decoder synchronization lost for clean channel!!!\n"); *idx = 0; sign = 1; } fp1 = cb + (*idx)*vdim; for (k = 0; k < vdim; k++) xq[k] = (double) sign*(*fp1++); if (sign < 0) *idx = (2*cbsz - 1) - (*idx); }