/*
LPC-10 voice codec, part of the HawkVoice Direct Interface (HVDI)
cross platform network voice library
Copyright (C) 2001-2004 Phil Frisbie, Jr. (phil@hawksoft.com)
The VBR algorithm was contributed by
Ben Appleton <appleton@bigpond.net.au>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
Or go to http://www.gnu.org/copyleft/lgpl.html
*/
#if !defined( MACOSX ) && !defined (__APPLE__)
#include <malloc.h>
#endif
#include <stdlib.h>
#ifdef __MWERKS__
#include <string.h>
#else
#include <memory.h>
#endif
#ifdef _MSC_VER
#pragma warning (disable:4711) /* to disable automatic inline warning */
#endif
#include <math.h>
#include "ftol.h"
#include "lpc10.h"
#if __GNUC__ == 2
#define lrintf(d) ((int) (d))
#endif
#define LPC10_BITS_IN_COMPRESSED_FRAME 54
#ifndef TRUE
#define TRUE (1)
#define FALSE (0)
#endif
#ifndef min
#define min(a,b) ((a) <= (b) ? (a) : (b))
#define max(a,b) ((a) >= (b) ? (a) : (b))
#endif
typedef struct lpc10_d_state {
/* State used by function decode */
long iptold; /* initial value 60 */
/* State used by function synths */
float buf[360];
long buflen; /* initial value 180 */
/* State used by function pitsyn */
long ivoico; /* no initial value necessary as long as first_pitsyn is initially TRUE_ */
long ipito; /* no initial value necessary as long as first_pitsyn is initially TRUE_ */
float rmso; /* initial value 1.f */
float rco[10]; /* no initial value necessary as long as first_pitsyn is initially TRUE_ */
long jsamp; /* no initial value necessary as long as first_pitsyn is initially TRUE_ */
int first_pitsyn; /* initial value TRUE_ */
/* State used by function bsynz */
long ipo;
float exc[166];
float exc2[166];
float lpi1;
float lpi2;
float lpi3;
float hpi1;
float hpi2;
float hpi3;
float rmso_bsynz;
/* State used by function deemp */
float dei1;
float dei2;
float deo1;
float deo2;
float deo3;
} lpc10_d_state_t;
extern long lpcbits[10];
/* Table of constant values */
static long detau[128] = { 0,0,0,3,0,3,3,31,0,3,3,21,3,3,29,30,0,3,3,
20,3,25,27,26,3,23,58,22,3,24,28,3,0,3,3,3,3,39,33,32,3,37,35,36,
3,38,34,3,3,42,46,44,50,40,48,3,54,3,56,3,52,3,3,1,0,3,3,108,3,78,
100,104,3,84,92,88,156,80,96,3,3,74,70,72,66,76,68,3,62,3,60,3,64,
3,3,1,3,116,132,112,148,152,3,3,140,3,136,3,144,3,3,1,124,120,128,
3,3,3,3,1,3,3,3,1,3,1,1,1 };
static long rmst[64] = { 1024,936,856,784,718,656,600,550,502,460,420,
384,352,328,294,270,246,226,206,188,172,158,144,132,120,110,102,
92,84,78,70,64,60,54,50,46,42,38,34,32,30,26,24,22,20,18,17,16,15,
14,13,12,11,10,9,8,7,6,5,4,3,2,1,0 };
static long detab7[32] = { 4,11,18,25,32,39,46,53,60,66,72,77,82,87,92,
96,101,104,108,111,114,115,117,119,121,122,123,124,125,126,127,127 };
static float descl[8] = { .6953f,.625f,.5781f,.5469f,.5312f,.5391f,.4688f,.3828f };
static long deadd[8] = { 1152,-2816,-1536,-3584,-1280,-2432,768,-1920 };
static long qb[8] = { 511,511,1023,1023,1023,1023,2047,4095 };
static long nbit[10] = { 8,8,5,5,4,4,4,4,3,2 };
static long kexc[25] = { 8,-16,26,-48,86,-162,294,-502,718,-728,184,
672,-610,-672,184,728,718,502,294,162,86,48,26,16,8 };
static void pitsyn(long *voice, long *pitch, float *rms, float *rc,
long *ivuv, long *ipiti, float *rmsi, float *rci, long *nout,
float *ratio, lpc10_decoder_state *st)
{
/* Initialized data */
float *rmso;
/* Local variables */
float alrn, alro, yarc[10], prop;
long i, j, vflag, jused, lsamp;
long *jsamp;
float slope;
long *ipito;
float uvpit;
long ip, nl, ivoice;
long *ivoico;
long istart;
float *rco;
float xxy;
/* Function Body */
ivoico = &(st->ivoico);
ipito = &(st->ipito);
rmso = &(st->rmso);
rco = &(st->rco[0]);
jsamp = &(st->jsamp);
if (*rms < 1.f) {
*rms = 1.f;
}
if (*rmso < 1.f) {
*rmso = 1.f;
}
uvpit = 0.f;
*ratio = *rms / (*rmso + 8.f);
if (st->first_pitsyn) {
lsamp = 0;
ivoice = voice[1];
if (ivoice == 0) {
*pitch = LPC10_SAMPLES_PER_FRAME / 4;
}
*nout = LPC10_SAMPLES_PER_FRAME / *pitch;
*jsamp = LPC10_SAMPLES_PER_FRAME - *nout * *pitch;
for (i = 0; i < *nout; ++i) {
for (j = 0; j < 10; ++j) {
rci[j + i * 10] = rc[j];
}
ivuv[i] = ivoice;
ipiti[i] = *pitch;
rmsi[i] = *rms;
}
st->first_pitsyn = FALSE;
} else {
vflag = 0;
lsamp = LPC10_SAMPLES_PER_FRAME + *jsamp;
slope = (*pitch - *ipito) / (float) lsamp;
*nout = 0;
jused = 0;
istart = 1;
if (voice[0] == *ivoico && voice[1] == voice[0]) {
if (voice[1] == 0) {
/* SSUV - - 0 , 0 , 0 */
*pitch = LPC10_SAMPLES_PER_FRAME / 4;
*ipito = *pitch;
if (*ratio > 8.f) {
*rmso = *rms;
}
}
/* SSVC - - 1 , 1 , 1 */
slope = (*pitch - *ipito) / (float) lsamp;
ivoice = voice[1];
} else {
if (*ivoico != 1) {
if (*ivoico == voice[0]) {
/* UV2VC2 - - 0 , 0 , 1 */
nl = lsamp - LPC10_SAMPLES_PER_FRAME / 4;
} else {
/* UV2VC1 - - 0 , 1 , 1 */
nl = lsamp - LPC10_SAMPLES_PER_FRAME * 3 / 4;
}
ipiti[0] = nl / 2;
ipiti[1] = nl - ipiti[0];
ivuv[0] = 0;
ivuv[1] = 0;
rmsi[0] = *rmso;
rmsi[1] = *rmso;
for (i = 0; i < 10; ++i) {
rci[i] = rco[i];
rci[i + 10] = rco[i];
rco[i] = rc[i];
}
slope = 0.f;
*nout = 2;
*ipito = *pitch;
jused = nl;
istart = nl + 1;
ivoice = 1;
} else {
if (*ivoico != voice[0]) {
lsamp = LPC10_SAMPLES_PER_FRAME / 4 + *jsamp;
} else {
lsamp = LPC10_SAMPLES_PER_FRAME * 3 / 4 + *jsamp;
}
for (i = 0; i < 10; ++i) {
yarc[i] = rc[i];
rc[i] = rco[i];
}
ivoice = 1;
slope = 0.f;
vflag = 1;
}
}
for(;;) {
for (i = istart; i <= lsamp; ++i) {
if (uvpit != 0.f) {
ip = lrintf(uvpit);
}
else {
ip = lrintf(*ipito + slope * i + .5f);
}
if (ip <= i - jused) {
ipiti[*nout] = ip;
*pitch = ip;
ivuv[*nout] = ivoice;
jused += ip;
prop = (jused - ip / 2) / (float) lsamp;
for (j = 0; j < 10; ++j) {
alro = (float)log((rco[j] + 1) / (1 - rco[j]));
alrn = (float)log((rc[j] + 1) / (1 - rc[j]));
xxy = alro + prop * (alrn - alro);
xxy = (float)exp(xxy);
rci[j + *nout * 10] = (xxy - 1) / (xxy + 1);
}
rmsi[*nout] = (float)(log(*rmso) + prop * (log(*rms) - log(*rmso)));
rmsi[*nout] = (float)exp(rmsi[*nout]);
++(*nout);
}
}
if (vflag != 1) {
break;
}
vflag = 0;
istart = jused + 1;
lsamp = LPC10_SAMPLES_PER_FRAME + *jsamp;
slope = 0.f;
ivoice = 0;
uvpit = (float) ((lsamp - istart) / 2);
if (uvpit > 90.f) {
uvpit /= 2;
}
*rmso = *rms;
for (i = 1; i <= 10; ++i) {
rco[i - 1] = rc[i - 1] = yarc[i - 1];
}
}
*jsamp = lsamp - jused;
}
if (*nout != 0) {
*ivoico = voice[1];
*ipito = *pitch;
*rmso = *rms;
for (i = 0; i < 10; ++i) {
rco[i] = rc[i];
}
}
} /* pitsyn_ */
#define MIDTAP 1
#define MAXTAP 4
static short y[MAXTAP+1]={-21161, -8478, 30892,-10216, 16950};
static int j=MIDTAP, k=MAXTAP;
static int random16 (void)
{
int the_random;
/* The following is a 16 bit 2's complement addition,
* with overflow checking disabled */
y[k] = (short)(y[k] + y[j]);
the_random = y[k];
k--;
if (k < 0) k = MAXTAP;
j--;
if (j < 0) j = MAXTAP;
return(the_random);
}
static void bsynz(float *coef, long ip, long *iv,
float *sout, float *rms, float *ratio, float *g2pass,
lpc10_decoder_state *st)
{
/* Initialized data */
long *ipo;
float *rmso;
float *exc;
float *exc2;
float lpi1;
float lpi2;
float hpi1;
float hpi2;
/* Local variables */
float gain, xssq;
long i, j, k;
float pulse;
long px;
float sscale;
float xy, sum, ssq;
float lpi0, hpi0;
/* Parameter adjustments */
if (coef) {
--coef;
}
/* Function Body */
ipo = &(st->ipo);
exc = &(st->exc[0]);
exc2 = &(st->exc2[0]);
lpi1 = st->lpi1;
lpi2 = st->lpi2;
hpi1 = st->hpi1;
hpi2 = st->hpi2;
rmso = &(st->rmso_bsynz);
/* MAXPIT+MAXORD=166 */
/* Calculate history scale factor XY and scale filter state */
/* Computing MIN */
xy = min((*rmso / (*rms + 1e-6f)),8.f);
*rmso = *rms;
for (i = 0; i < 10; ++i) {
exc2[i] = exc2[*ipo + i] * xy;
}
*ipo = ip;
if (*iv == 0) {
/* Generate white noise for unvoiced */
for (i = 0; i < ip; ++i) {
exc[10 + i] = (float) (random16() >> 6);
}
px = ((random16() + 32768) * (ip - 1) >> 16) + 10 + 1;
pulse = *ratio * 85.5f;
if (pulse > 2e3f) {
pulse = 2e3f;
}
exc[px - 1] += pulse;
exc[px] -= pulse;
/* Load voiced excitation */
} else {
sscale = (float)sqrt((float) (ip)) * 0.144341801f;
for (i = 0; i < ip; ++i) {
float temp;
if (i > 27) {
temp = 0.f;
}
else if (i < 25) {
lpi0 = temp = sscale * kexc[i];
temp = lpi0 * .125f + lpi1 * .75f + lpi2 * .125f;
lpi2 = lpi1;
lpi1 = lpi0;
}
else{
lpi0 = temp = 0.f;
temp = lpi1 * .75f + lpi2 * .125f;
lpi2 = lpi1;
lpi1 = lpi0;
}
hpi0 = (float)(random16() >> 6);
exc[10 + i] = temp + hpi0 * -.125f + hpi1 * .25f + hpi2 * -.125f;
hpi2 = hpi1;
hpi1 = hpi0;
}
}
/* Synthesis filters: */
/* Modify the excitation with all-zero filter 1 + G*SUM */
xssq = 0.f;
for (i = 0; i < ip; ++i) {
k = 10 + i;
sum = 0.f;
for (j = 1; j <= 10; ++j) {
sum += coef[j] * exc[k - j];
}
sum *= *g2pass;
exc2[k] = sum + exc[k];
}
/* Synthesize using the all pole filter 1 / (1 - SUM) */
for (i = 0; i < ip; ++i) {
k = 10 + i;
sum = 0.f;
for (j = 1; j <= 10; ++j) {
sum += coef[j] * exc2[k - j];
}
exc2[k] += sum;
xssq += exc2[k] * exc2[k];
}
/* Save filter history for next epoch */
for (i = 0; i < 10; ++i) {
exc[i] = exc[ip + i];
exc2[i] = exc2[ip + i];
}
/* Apply gain to match RMS */
ssq = *rms * *rms * ip;
gain = (float)sqrt(ssq / xssq);
for (i = 0; i < ip; ++i) {
sout[i] = gain * exc2[10 + i];
}
st->lpi1 = lpi1;
st->lpi2 = lpi2;
st->hpi1 = hpi1;
st->hpi2 = hpi2;
} /* bsynz_ */
static void irc2pc(float *rc, float *pc, float gprime, float *g2pass)
{
/* System generated locals */
long i2;
/* Local variables */
float temp[10];
long i, j;
/* Parameter adjustments */
--pc;
--rc;
/* Function Body */
*g2pass = 1.f;
for (i = 1; i <= 10; ++i) {
*g2pass *= 1.f - rc[i] * rc[i];
}
*g2pass = gprime * (float)sqrt(*g2pass);
pc[1] = rc[1];
for (i = 2; i <= 10; ++i) {
i2 = i - 1;
for (j = 1; j <= i2; ++j) {
temp[j - 1] = pc[j] - rc[i] * pc[i - j];
}
i2 = i - 1;
for (j = 1; j <= i2; ++j) {
pc[j] = temp[j - 1];
}
pc[i] = rc[i];
}
} /* irc2pc_ */
static void deemp(float *x, long n, lpc10_decoder_state *st)
{
/* Initialized data */
float dei1;
float dei2;
float deo1;
float deo2;
float deo3;
/* Local variables */
long k;
float dei0;
/* Function Body */
dei1 = st->dei1;
dei2 = st->dei2;
deo1 = st->deo1;
deo2 = st->deo2;
deo3 = st->deo3;
for (k = 0; k < n; ++k) {
dei0 = x[k];
x[k] = dei0 - dei1 * 1.9998f + dei2 + deo1 * 2.5f - deo2 * 2.0925f + deo3 * .585f;
dei2 = dei1;
dei1 = dei0;
deo3 = deo2;
deo2 = deo1;
deo1 = x[k];
}
st->dei1 = dei1;
st->dei2 = dei2;
st->deo1 = deo1;
st->deo2 = deo2;
st->deo3 = deo3;
} /* deemp_ */
static void synths(long *voice, long pitch, float rms, float *rc, short *speech, lpc10_decoder_state *st)
{
/* Initialized data */
float *buf;
long *buflen;
/* Local variables */
float rmsi[16];
long nout, ivuv[16], i, j;
float ratio;
long ipiti[16];
float g2pass;
float pc[10];
float rci[160] /* was [10][16] */;
/* Function Body */
buf = &(st->buf[0]);
buflen = &(st->buflen);
pitch = max(min(pitch,156), 20);
for (i = 0; i < 10; ++i) {
rc[i] = max(min(rc[i],.99f), -.99f);
}
pitsyn(voice, &pitch, &rms, rc, ivuv, ipiti, rmsi, rci, &nout, &ratio, st);
if (nout > 0) {
for (j = 0; j < nout; ++j) {
irc2pc(&rci[j * 10], pc, 0.7f, &g2pass);
bsynz(pc, ipiti[j], &ivuv[j], &buf[*buflen], &rmsi[j], &ratio, &g2pass, st);
deemp(&buf[*buflen], ipiti[j], st);
*buflen += ipiti[j];
}
for (i = 0; i < LPC10_SAMPLES_PER_FRAME; ++i) {
speech[i] = (short) max(-32768, min(lrintf(8.0f * buf[i]), 32767));
}
*buflen -= LPC10_SAMPLES_PER_FRAME;
for (i = 0; i < *buflen; ++i) {
buf[i] = buf[i + LPC10_SAMPLES_PER_FRAME];
}
}
} /* synths_ */
static void decode(long ipitv, long irms, long *irc, long *voice, long *pitch,
float *rms, float *rc, lpc10_decoder_state *st)
{
/* Local variables */
long i, i1, i2, i4;
long ishift;
/* Function Body */
i4 = detau[ipitv];
voice[0] = 1;
voice[1] = 1;
if (ipitv <= 1) {
voice[0] = 0;
}
if (ipitv == 0 || ipitv == 2) {
voice[1] = 0;
}
*pitch = i4;
if (*pitch <= 4) {
*pitch = st->iptold;
}
if (voice[0] == 1 && voice[1] == 1) {
st->iptold = *pitch;
}
if (voice[0] != voice[1]) {
*pitch = st->iptold;
}
/* Decode RMS */
irms = rmst[(31 - irms) * 2];
/* Decode RC(1) and RC(2) from log-area-ratios */
/* Protect from illegal coded value (-16) caused by bit errors */
for (i = 0; i < 2; ++i) {
i2 = irc[i];
i1 = 0;
if (i2 < 0) {
i1 = 1;
i2 = -i2;
if (i2 > 15) {
i2 = 0;
}
}
i2 = detab7[i2 * 2];
if (i1 == 1) {
i2 = -i2;
}
ishift = 15 - nbit[i];
irc[i] = i2 * (2 << (ishift-1));
}
/* Decode RC(3)-RC(10) to sign plus 14 bits */
for (i = 2; i < 10; ++i) {
i2 = irc[i];
ishift = 15 - nbit[i];
i2 *= (2 << (ishift-1));
i2 += qb[i - 2];
irc[i] = (int)(i2 * descl[i - 2] + deadd[i - 2]);
}
/* Scale RMS and RC's to floats */
*rms = (float) (irms);
for (i = 0; i < 10; ++i) {
rc[i] = irc[i] / 16384.f;
}
} /* decode_ */
static void unpack(long *array, long bits, long *value, long *pointer)
{
int i;
for (i = 0, *value = 0; i < bits; i++, (*pointer)++)
*value |= array[*pointer] << i;
}
static void chanrd(long *ipitv, long *irms, long *irc, long *ibits, int *p, int vbr)
{
static long bit[] = {0, 1, 2, 4, 8, 16, 32, 64, 128};
long pointer, i;
pointer = 0;
unpack(ibits, 7, ipitv, &pointer);
if(vbr == TRUE)
{
/* check for silence packet */
if (*ipitv == 127) {
*ipitv = 0;
*irms = 0;
*p = 1;
return;
}
}
unpack(ibits, 5, irms, &pointer);
*p = 4;
for (i = 0; i < 4; ++i) {
unpack(ibits, lpcbits[i], &irc[i], &pointer);
}
if ((*ipitv != 0 && *ipitv != 126) || vbr == FALSE) {
*p = 7;
for (i = 4; i < 10; ++i) {
unpack(ibits, lpcbits[i], &irc[i], &pointer);
}
}
/* Sign extend RC's */
for (i = 0; i < 10; ++i) {
if ((irc[i] & bit[lpcbits[i]]) != 0) {
irc[i] -= bit[lpcbits[i]] << 1;
}
}
}
static int lpc10_decode_int(unsigned char *in, int inLenMax, short *speech,
lpc10_decoder_state *st, int *p, int vbr)
{
long bits[LPC10_BITS_IN_COMPRESSED_FRAME];
int i;
long irms, voice[2], pitch, ipitv;
float rc[10];
long irc[10];
float rms;
/* unpack bits into array */
int maxBits = inLenMax << 3;
if(maxBits > LPC10_BITS_IN_COMPRESSED_FRAME)
maxBits = LPC10_BITS_IN_COMPRESSED_FRAME;
for (i = 0; i < maxBits; i++)
{
bits[i] = (in[i >> 3] & (1 << (i & 7))) != 0 ? 1 : 0;
}
for (; i < LPC10_BITS_IN_COMPRESSED_FRAME; i++)
bits[i] = 0;
/* decode speech */
memset(irc, 0, sizeof(irc));
chanrd(&ipitv, &irms, irc, bits, p, vbr);
decode(ipitv, irms, irc, voice, &pitch, &rms, rc, st);
synths(voice, pitch, rms, rc, speech, st);
return LPC10_SAMPLES_PER_FRAME;
}
int lpc10_decode(unsigned char *in, int inLenMax, short *speech, lpc10_decoder_state *st)
{
int p = 0;
return lpc10_decode_int(in, inLenMax, speech, st, &p, FALSE);
}
int vbr_lpc10_decode(unsigned char *in, int inLenMax, short *speech, lpc10_decoder_state *st, int *p)
{
return lpc10_decode_int(in, inLenMax, speech, st, p, TRUE);
}
/* Allocate memory for, and initialize, the state that needs to be
kept from decoding one frame to the next for a single
LPC-10-compressed audio stream. Return 0 if malloc fails,
otherwise return pointer to new structure. */
lpc10_decoder_state *create_lpc10_decoder_state(void)
{
lpc10_decoder_state *st;
st = (lpc10_decoder_state *)malloc((unsigned) sizeof (lpc10_decoder_state));
return (st);
}
void init_lpc10_decoder_state(lpc10_decoder_state *st)
{
int i;
/* State used by function decode */
st->iptold = 60;
/* State used by function synths */
for (i = 0; i < 360; i++) {
st->buf[i] = 0.0f;
}
st->buflen = 180;
/* State used by function pitsyn */
st->rmso = 1.0f;
st->first_pitsyn = TRUE;
/* State used by function bsynz */
st->ipo = 0;
for (i = 0; i < 166; i++) {
st->exc[i] = 0.0f;
st->exc2[i] = 0.0f;
}
st->lpi1 = 0.0f;
st->lpi2 = 0.0f;
st->lpi3 = 0.0f;
st->hpi1 = 0.0f;
st->hpi2 = 0.0f;
st->hpi3 = 0.0f;
st->rmso_bsynz = 0.0f;
/* State used by function deemp */
st->dei1 = 0.0f;
st->dei2 = 0.0f;
st->deo1 = 0.0f;
st->deo2 = 0.0f;
st->deo3 = 0.0f;
}
void destroy_lpc10_decoder_state (lpc10_decoder_state *st)
{
if(st != NULL)
{
free(st);
st = NULL;
}
}
syntax highlighted by Code2HTML, v. 0.9.1