[Speex-dev] Speex on TI C6x, Problem with TI C5x Patch

Stuart Cording smcording at hotmail.com
Wed May 25 08:42:41 PDT 2005


Hi Jean-Marc, Hi Jim,

I have also seen some problems with the 1.1.8 release on the C55x. So far I 
have boiled down the issues to the following:

1) We need our own "fixed_xx.h" header file. I don't know why, and haven't 
had time to investigate, but there is a definite improvement when I use the 
attached fixed_c55x.h file which has turned all the maths into inline 
functions. Some optimisation or something is probably possible here to 
reduce code size and inline the functions, as by default the C55x compiler 
does not seem to inline them (perhaps due to debugging mode). This can be 
enabled with a C55X_ASM definition following the ARM fixed point math 
definition convention, and some it could be converted to assembler in the 
future.

2) Proper definitions for the speex types are required in the speex_types.h 
file - I did this and you can enable it via a __C55X__ definition. File 
attached. My definition follows the convention of other defines in this 
file. It could be covered by the C55X_ASM define above, but the content of 
this file is not going to have assembler in it. I leave it up to you if 
think this is wrong or right - just tell me and I'll follow!

3) There seem to be further int/long on a C55X issues in nb_celp.c for the 
nb_encoder_ctl and nb_decoder_ctl functions. I think that all the 
(*(int*)ptr) or *((int*)ptr) should be (*(long*)ptr) for a C55X. I don't 
know why. What I presume was happening was that the data passed to the 
function in void *ptr was being lost in the upper or lower half of a 32-bit 
word. So it didn't matter what you passed as a setting for SPEEX_SET_QUALITY 
and SPEEX_SET_COMPLEXITY, the (*(int*)ptr) always = 0. For quality this 
doesn't matter I don't think due to the default settings, but the 
st->complexity always ended up as zero, and the decoded bit-stream ends up 
sounding very ropy. I think this the issue Jim alluded to in his question 2 
regarding 'artifacts'. I don't think it was artifacts but perhaps this issue 
I have described. In nb_celp.c I changed all those effected (*(int*)ptr) to 
long, but perhaps it would be better to have a more platform independant 
resolution? Does ptr need to be a void *? Can't we use an int * or, better 
still, one of the nice Speex types so we know what we are expecting to 
arrive at the function? I can make the changes and submit, I just want to 
know how best to do a platform independant change. (I attach my nb_celp.c 
for Jim and just so you can see what I did). Jim: Note that this will push 
your MIPS up again as now the encode is actually doing a decent job on the 
decoding - I think this was the reason for the huge performance increase.

4) Jamie's CONFIG_TI_C55X definition doesn't seem to work for me. Whenever I 
compile using this option, I get a "Buffer too small to apck bits" and then 
"Could not resize input buffer: not packing" messages. I haven't had time to 
figure out what that means or what causes it, but will if I get time.

5) Re: stack memory allocations, yes, a compile-time option would be great 
to reduce the stack sizes. Ideally what is needed is the minimum stack usage 
so that us embedded developers can support streaming audio, for either 
compression or decompression. For nb mode, for example, this would mean 
receiving a 160 byte raw data frame, compressing and storing or sending, 
then dealing with the next frame. This is my opinion anyway, and I think 
this usage model is a good target model to keep in mind during development. 
For an embedded system it is likely that developers would do only 
compression, or only decompression in their application, so splitting the 
encoder and decoder into seperate files would also be a good idea in the 
future.

6)Jim - there is a known issue with the fwrite and fread functions on the 
C55X. There should be a CCS download to fix this, although I haven't 
installed it myself.

That is about all for now. Any comments or feedback are welcome as always. 
My personal goal at the moment is to get a fixed_point stable version for 
C55x so that I can then use that to develop an XDAIS algorithm, or some 
other TI DSP specific version which includes compiler specific settings so 
we get the best code size/MIPS ratio. Whether you'll want all that stuff put 
back into the main Speex release I don't know, but if you do that is fine 
with me too.

Look forward to hearing from you soon,

Stuart

-------------- next part --------------
/* Copyright (C) 2003 Jean-Marc Valin */
/**
   @file arch.h
   @brief Various architecture definitions Speex
*/
/*
   Redistribution and use in source and binary forms, with or without
   modification, are permitted provided that the following conditions
   are met:

   - Redistributions of source code must retain the above copyright
   notice, this list of conditions and the following disclaimer.

   - Redistributions in binary form must reproduce the above copyright
   notice, this list of conditions and the following disclaimer in the
   documentation and/or other materials provided with the distribution.

   - Neither the name of the Xiph.org Foundation nor the names of its
   contributors may be used to endorse or promote products derived from
   this software without specific prior written permission.

   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#ifndef ARCH_H
#define ARCH_H

#include "speex/speex_types.h"

#define ABS(x) ((x) < 0 ? (-(x)) : (x))

#ifdef FIXED_POINT

typedef spx_int16_t spx_word16_t;
typedef spx_int32_t   spx_word32_t;
#ifdef _MSC_VER
typedef __int64      spx_word64_t;
#else
typedef long long    spx_word64_t;
#endif
typedef spx_word32_t spx_mem_t;
typedef spx_word16_t spx_coef_t;
typedef spx_word16_t spx_lsp_t;
typedef spx_word32_t spx_sig_t;

#define LPC_SCALING  8192
#define SIG_SCALING  16384
#define LSP_SCALING  8192.
#define GAMMA_SCALING 32768.
#define GAIN_SCALING 64
#define GAIN_SCALING_1 0.015625

#define LPC_SHIFT    13
#define SIG_SHIFT    14

#define VERY_SMALL 0


#ifdef ARM5E_ASM
#include "fixed_arm5e.h"
#elif defined (ARM4_ASM)
#include "fixed_arm4.h"
#elif defined (FIXED_DEBUG)
#include "fixed_debug.h"
#elif defined (C55X_ASM)
#include "fixed_c55x.h"
#else
#include "fixed_generic.h"
#endif



#else

typedef float spx_mem_t;
typedef float spx_coef_t;
typedef float spx_lsp_t;
typedef float spx_sig_t;
typedef float spx_word16_t;
typedef float spx_word32_t;
typedef float spx_word64_t;

#define LPC_SCALING  1.
#define SIG_SCALING  1.
#define LSP_SCALING  1.
#define GAMMA_SCALING 1.
#define GAIN_SCALING 1.
#define GAIN_SCALING_1 1.

#define LPC_SHIFT    0
#define SIG_SHIFT    0

#define VERY_SMALL 1e-15

#define NEG16(x) (-(x))
#define NEG32(x) (-(x))
#define EXTRACT16(x) (x)
#define EXTEND32(x) (x)
#define SHR16(a,shift) (a)
#define SHL16(a,shift) (a)
#define SHR32(a,shift) (a)
#define SHL32(a,shift) (a)
#define PSHR16(a,shift) (a)
#define PSHR32(a,shift) (a)
#define SATURATE16(x,a) (x)
#define SATURATE32(x,a) (x)

#define PSHR(a,shift)       (a)
#define SHR(a,shift)       (a)
#define SHL(a,shift)       (a)
#define SATURATE(x,a) (x)

#define ADD16(a,b) ((a)+(b))
#define SUB16(a,b) ((a)-(b))
#define ADD32(a,b) ((a)+(b))
#define SUB32(a,b) ((a)-(b))
#define ADD64(a,b) ((a)+(b))
#define MULT16_16_16(a,b)     ((a)*(b))
#define MULT16_16(a,b)     ((spx_word32_t)(a)*(spx_word32_t)(b))
#define MAC16_16(c,a,b)     ((c)+(spx_word32_t)(a)*(spx_word32_t)(b))

#define MULT16_32_Q11(a,b)     ((a)*(b))
#define MULT16_32_Q13(a,b)     ((a)*(b))
#define MULT16_32_Q14(a,b)     ((a)*(b))
#define MULT16_32_Q15(a,b)     ((a)*(b))

#define MAC16_32_Q11(c,a,b)     ((c)+(a)*(b))
#define MAC16_32_Q15(c,a,b)     ((c)+(a)*(b))

#define MAC16_16_Q11(c,a,b)     ((c)+(a)*(b))
#define MAC16_16_Q13(c,a,b)     ((c)+(a)*(b))
#define MULT16_16_Q11_32(a,b)     ((a)*(b))
#define MULT16_16_Q13(a,b)     ((a)*(b))
#define MULT16_16_Q14(a,b)     ((a)*(b))
#define MULT16_16_Q15(a,b)     ((a)*(b))
#define MULT16_16_P15(a,b)     ((a)*(b))

#define DIV32_16(a,b)     ((a)/(b))
#define DIV32(a,b)     ((a)/(b))


#endif


#ifdef CONFIG_TI_C55X

/* 2 on TI C5x DSP */
#define BYTES_PER_CHAR 2
#define BITS_PER_CHAR 16
#define LOG2_BITS_PER_CHAR 4

#else

#define BYTES_PER_CHAR 1
#define BITS_PER_CHAR 8
#define LOG2_BITS_PER_CHAR 3

#endif

#endif

-------------- next part --------------
/* Copyright (C) 2004 Jean-Marc Valin */
/**
   @file fixed_c55x.h
   @brief C55x fixed-point operations
*/
/*
   Redistribution and use in source and binary forms, with or without
   modification, are permitted provided that the following conditions
   are met:

   - Redistributions of source code must retain the above copyright
   notice, this list of conditions and the following disclaimer.

   - Redistributions in binary form must reproduce the above copyright
   notice, this list of conditions and the following disclaimer in the
   documentation and/or other materials provided with the distribution.

   - Neither the name of the Xiph.org Foundation nor the names of its
   contributors may be used to endorse or promote products derived from
   this software without specific prior written permission.

   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#ifndef FIXED_C55X_H
#define FIXED_C55X_H

//#define NEG16(x) (-(x))
static inline spx_word16_t NEG16(spx_word16_t a)
{
	return -a;
}
//#define NEG32(x) (-(x))
static inline spx_word32_t NEG32(spx_word32_t a)
{
	return -a;
}
//#define EXTRACT16(x) ((spx_word16_t)x)
static inline spx_word16_t EXTRACT16(spx_word32_t a)
{
	return (spx_word16_t) a;
}
//#define EXTEND32(x) ((spx_word32_t)x)
static inline spx_word32_t EXTEND32(spx_word16_t a)
{
	return (spx_word32_t) a;
}
//#define SHR16(a,shift) ((a) >> (shift))
static inline spx_word16_t SHR16(spx_word16_t a, spx_word16_t b)
{
	spx_word16_t res;

	res = a >> b;

	return res;
}
//#define SHL16(a,shift) ((a) << (shift))
static inline spx_word16_t SHL16(spx_word16_t a, spx_word16_t b)
{
	spx_word16_t res;

	res = a << b;

	return res;
}
//#define SHR32(a,shift) ((a) >> (shift))
static inline spx_word32_t SHR32(spx_word32_t a, spx_word16_t b)
{
	spx_word32_t res;

	res = a >> b;

	return res;
}
//#define SHL32(a,shift) ((a) << (shift))
static inline spx_word32_t SHL32(spx_word32_t a, spx_word16_t b)
{
	spx_word32_t res;

	res = a << b;

	return res;
}
//#define PSHR16(a,shift) (SHR16((a)+(1<<((shift)-1)),shift))
static inline spx_word16_t PSHR16(spx_word16_t a, spx_word16_t shift)
{
//	spx_word32_t res;

//	res = ((a)+(1<<(b-1))) >> b;

//	return res;

	return (SHR16((a)+(1<<((shift)-1)),shift));
}
//#define PSHR32(a,shift) (SHR32((a)+(1<<((shift)-1)),shift))
static inline spx_word32_t PSHR32(spx_word32_t a, spx_word16_t shift)
{
//	spx_word32_t res;

//	res = ((a)+(1<<(b-1))) >> b;

//	return res;

	return (SHR32((a)+(1<<((shift)-1)),shift));
}

//#define SHR(a,shift) ((a) >> (shift))
static inline spx_word32_t SHR(spx_word32_t a, spx_word32_t b)
{
	spx_word32_t res;

	res = ((long) a) >> ((long) b);

	return res;
}

//#define SHL(a,shift) ((a) << (shift))
static inline spx_word32_t SHL(spx_word32_t a, spx_word32_t b)
{
	spx_word32_t res;

	res = ((long) a) << ((long) b);

	return res;
}


//#define SATURATE(x,a) ((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x))
static inline spx_word32_t SATURATE(spx_word32_t x, spx_word32_t a)
{
	spx_word32_t res;

	res = (x)>(a) ? (a) : (x)<-(a) ? -(a) : (x);

	return res;
}

//#define ADD16(a,b) ((a)+(b))
static inline spx_word32_t ADD16(spx_word16_t a, spx_word16_t b)
{
//	spx_word32_t res;

//	res = ((long) a) + ((long) b);

//	return res;

	return ((long) a) + ((long) b);
}

//#define SUB16(a,b) ((a)-(b))
static inline spx_word16_t SUB16(spx_word16_t a, spx_word16_t b)
{
//	spx_word32_t res;

//	res = ((long) a) - ((long) b);

//	return res;

	return (int) (a - b);
}

//#define ADD32(a,b) ((a)+(b))
static inline long long ADD32(spx_word32_t a, spx_word32_t b)
{
	long long res;

	res = ((long long) a) + ((long long) b);

	return res;
}

//#define SUB32(a,b) ((a)-(b))
static inline spx_word32_t SUB32(spx_word32_t a, spx_word32_t b)
{
	spx_word32_t res;

	res = (a) - (b);

	return res;
}

//#define ADD64(a,b) ((a)+(b))
static inline long long ADD64(long long a, long long b)
{
	long long res, tmp;

	res = (a) + (b);

	tmp = (a / 2) + (b / 2);

	if ((res / 2) != tmp)
		res = -1;

	return res;
}

//#define PSHR(a,shift) (SHR((a)+(1<<((shift)-1)),shift))
static inline spx_word32_t PSHR(spx_word32_t a, spx_word32_t shift)
{
//	spx_word32_t res;

//	res = ((a)+(1<<(b-1))) >> b;

//	return res;

	return ((SHR((a)+(1<<((shift)-1)),shift)));
}

/* result fits in 16 bits */
//#define MULT16_16_16(a,b)     ((a)*(b))
static inline spx_word16_t MULT16_16_16(spx_word16_t x, spx_word16_t y)
{
  int res;

  res = (int)((long) x * (long) y);

  return(res);
}

//#define MULT16_16(a,b)     ((a)*(b))
static inline spx_word32_t MULT16_16(spx_word16_t x, spx_word16_t y)
{
  long res;

  res = ((long) x * (long) y);

  return(res);
}

//#define MAC16_16(c,a,b)     (ADD32((c),MULT16_16((a),(b))))
static inline spx_word32_t MAC16_16(spx_word32_t w, spx_word16_t x, 
spx_word16_t y)
{
  long res;

  res = w + ((long) x * (long) y);

  return(res);
}
//#define MULT16_32_Q12(a,b) ADD32(MULT16_16((a),SHR((b),12)), 
SHR(MULT16_16((a),((b)&0x00000fff)),12))
static inline spx_word32_t MULT16_32_Q12(spx_word16_t a, spx_word32_t b)
{
//  long res, tmp, tmp2;

//  tmp  = ((long) x) * (y >> 12);
//  tmp2 = ((long) x * (y & 0x00000fff)) >> 12;
//  res = tmp + tmp2;

//  return(res);
  return(ADD32(MULT16_16((a),SHR((b),12)), 
SHR(MULT16_16((a),((b)&0x00000fff)),12)));
}
//#define MULT16_32_Q13(a,b) ADD32(MULT16_16((a),SHR((b),13)), 
SHR(MULT16_16((a),((b)&0x00001fff)),13))
static inline spx_word32_t MULT16_32_Q13(spx_word16_t a, spx_word32_t b)
{
//  long res, tmp, tmp2;

//  tmp  = ((long) x) * (y >> 13);
//  tmp2 = ((long) x * (y & 0x00001fff)) >> 13;
//  res = tmp + tmp2;

//  return(res);
  return(ADD32(MULT16_16((a),SHR((b),13)), 
SHR(MULT16_16((a),((b)&0x00001fff)),13)));
}
//#define MULT16_32_Q14(a,b) ADD32(MULT16_16((a),SHR((b),14)), 
SHR(MULT16_16((a),((b)&0x00003fff)),14))
static inline spx_word32_t MULT16_32_Q14(spx_word16_t a, spx_word32_t b)
{
//  long res, tmp, tmp2;

//  tmp  = ((long) x) * (y >> 14);
//  tmp2 = ((long) x * (y & 0x00003fff)) >> 14;
//  res = tmp + tmp2;

//  return(res);
  return(ADD32(MULT16_16((a),SHR((b),14)), 
SHR(MULT16_16((a),((b)&0x00003fff)),14)));
}

//#define MAC16_32_Q11(c,a,b) ADD32(c,ADD32(MULT16_16((a),SHR((b),11)), 
SHR(MULT16_16((a),((b)&0x000007ff)),11)))
static inline spx_word32_t MAC16_32_Q11(spx_word32_t c, spx_word16_t a, 
spx_word32_t b)
{
//  long res, tmp, tmp2;

//  tmp  = ((long) a) * (b >> 11);

//  tmp2 = (((long) a) * (b & 0x000007ff)) >> 11;

//  res = c + tmp + tmp2;

//  return(res);
  return(ADD32(c,ADD32(MULT16_16((a),SHR((b),11)), 
SHR(MULT16_16((a),((b)&0x000007ff)),11))));
}

//#define MULT16_32_Q11(a,b) ADD32(MULT16_16((a),SHR((b),11)), 
SHR(MULT16_16((a),((b)&0x000007ff)),11))
static inline spx_word32_t MULT16_32_Q11(spx_word16_t a, spx_word32_t b)
{
//  long res, tmp, tmp2;

//  tmp  = ((long) x) * (y >> 11);
//  tmp2 = (((long) x * (y & 0x000007ff))) >> 11;
//  res = tmp + tmp2;

//  return(res);
  return(ADD32(MULT16_16((a),SHR((b),11)), 
SHR(MULT16_16((a),((b)&0x000007ff)),11)));
}

//#define MULT16_32_Q15(a,b) ADD32(MULT16_16((a),SHR((b),15)), 
SHR(MULT16_16((a),((b)&0x00007fff)),15))
//ADD32()
//MULT16_16((a),SHR((b),15)),
//SHR(MULT16_16((a),((b)&0x00007fff)),15)
static inline spx_word32_t MULT16_32_Q15(spx_word16_t a, spx_word32_t b)
{
//  long res, tmp, tmp2, tmp3, tmp4;

//  tmp  = (b >> 15);
//  tmp2 = a * tmp;
//  tmp  = b & 0x00007fff;
//  tmp3 = a * tmp;
//  tmp4 = tmp3 >> 15;
//  tmp2 = (((long) a * (b & 0x00007fff))) >> 15;
//  res = tmp2 + tmp4;

//  return(res);

  return(ADD32(MULT16_16((a),SHR((b),15)), 
SHR(MULT16_16((a),((b)&0x00007fff)),15)));
}

//#define MAC16_32_Q15(c,a,b) ADD32(c,ADD32(MULT16_16((a),SHR((b),15)), 
SHR(MULT16_16((a),((b)&0x00007fff)),15)))
static inline spx_word32_t MAC16_32_Q15(spx_word32_t c, spx_word16_t a, 
spx_word32_t b)
{
//  long res, tmp, tmp2;

//  tmp  = ((long) x) * ( y >> 15);

//  tmp2 = (((long) x) * (((long) y) & 0x00007fff)) >> 15;

//  res = w + tmp + tmp2;

//  return(res);
  return(ADD32(c,ADD32(MULT16_16((a),SHR((b),15)), 
SHR(MULT16_16((a),((b)&0x00007fff)),15))));
}

//#define MAC16_16_Q11(c,a,b)     (ADD32((c),SHR(MULT16_16((a),(b)),11)))
static inline spx_word16_t MAC16_16_Q11(spx_word16_t c, spx_word16_t a, 
spx_word32_t b)
{
  spx_word16_t res;

  res  = (spx_word16_t) (((long) c) + ((((long) a) * (b)) >> 11));

  return(res);
}

//#define MULT16_16_Q11(a,b) (SHR(MULT16_16((a),(b)),11))
static inline spx_word16_t MULT16_16_Q11(spx_word16_t x, spx_word16_t y)
{
  spx_word16_t res;

  res = (spx_word16_t) ((((long) x) * ((long) y)) >> 11);

  return(res);
}

//#define MULT16_16_Q13(a,b) (SHR(MULT16_16((a),(b)),13))
static inline spx_word16_t MULT16_16_Q13(spx_word16_t x, spx_word16_t y)
{
  spx_word16_t res;

  res = (spx_word16_t) ((((long) x) * ((long) y)) >> 13);

  return(res);
}

//#define MULT16_16_Q14(a,b) (SHR(MULT16_16((a),(b)),14))
static inline spx_word16_t MULT16_16_Q14(spx_word16_t x, spx_word16_t y)
{
  spx_word16_t res;

  res = (spx_word16_t) ((((long) x) * ((long) y)) >> 14);

  return(res);
}

//#define MULT16_16_Q15(a,b) (SHR(MULT16_16((a),(b)),15))
static inline spx_word16_t MULT16_16_Q15(spx_word16_t x, spx_word16_t y)
{
  spx_word16_t res;

  res = (spx_word16_t) ((((long) x) * ((long) y)) >> 15);

  return(res);
}

//#define MULT16_16_P13(a,b) (SHR(ADD32(4096,MULT16_16((a),(b))),13))
static inline spx_word16_t MULT16_16_P13(spx_word16_t x, spx_word16_t y)
{
  spx_word16_t res;

  res = (spx_word16_t) (((((long) x) * ((long) y)) + 4096) >> 13);

  return(res);
}

//#define MULT16_16_P14(a,b) (SHR(ADD32(8192,MULT16_16((a),(b))),14))
static inline spx_word16_t MULT16_16_P14(spx_word16_t x, spx_word16_t y)
{
  spx_word16_t res;

  res = (spx_word16_t) (((((long) x) * ((long) y)) + 8192) >> 14);

  return(res);
}

//#define MULT16_16_P15(a,b) (SHR(ADD32(16384,MULT16_16((a),(b))),15))
static inline spx_word16_t MULT16_16_P15(spx_word16_t x, spx_word16_t y)
{
  spx_word16_t res;

  res = (spx_word16_t) (((((long) x) * ((long) y)) + 16384) >> 15);

  return(res);
}

//#define MUL_16_32_R15(a,bh,bl) ADD32(MULT16_16((a),(bh)), 
SHR(MULT16_16((a),(bl)),15))
static inline spx_word32_t MULT16_16_R15(spx_word16_t a, spx_word16_t bh, 
spx_word16_t bl)
{
  spx_word32_t res;

  res = (((long)a) * ((long) bh)) + ((((long) a) * ((long) bl)) >> 15);

  return(res);
}

//#define DIV32_16(a,b) (((signed long)(a))/((signed long)(b)))
static inline spx_word16_t DIV32_16(spx_word32_t a, spx_word32_t b)
{
	spx_word16_t res;

	res = (spx_word16_t) (a / b);

	return res;
}


//#define DIV32(a,b) (((signed long)(a))/((signed long)(b)))
static inline spx_word32_t DIV32(spx_word32_t a, spx_word32_t b)
{
	spx_word32_t res;

	res = (a / b);

	return res;
}

//#define MAC16_16_Q13(c,a,b)     (ADD32((c),SHR(MULT16_16((a),(b)),13)))
static inline spx_word16_t MAC16_16_Q13(spx_word16_t c, spx_word16_t a, 
spx_word16_t b)
{
//  spx_word16_t res;

//  res  = (spx_word16_t) (((long) c) + ((((long) a) * (b)) >> 13));

//  return(res);

  return (spx_word16_t) ADD32((c),SHR32(MULT16_16((a),(b)),13));
}

//#define MULT16_16_Q11_32(a,b) (SHR(MULT16_16((a),(b)),11))
static inline spx_word32_t MULT16_16_Q11_32(spx_word16_t a, spx_word16_t b)
{
//  spx_word32_t res;

//  res = (spx_word32_t) ((((long) x) * ((long) y)) >> 11);

//  return(res);

  return (spx_word32_t) SHR32(MULT16_16(((long) a),((long) b)),11);
}

#endif

-------------- next part --------------
/* Copyright (C) 2002 Jean-Marc Valin
   File: nb_celp.c

   Redistribution and use in source and binary forms, with or without
   modification, are permitted provided that the following conditions
   are met:

   - Redistributions of source code must retain the above copyright
   notice, this list of conditions and the following disclaimer.

   - Redistributions in binary form must reproduce the above copyright
   notice, this list of conditions and the following disclaimer in the
   documentation and/or other materials provided with the distribution.

   - Neither the name of the Xiph.org Foundation nor the names of its
   contributors may be used to endorse or promote products derived from
   this software without specific prior written permission.

   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <math.h>
#include "nb_celp.h"
#include "lpc.h"
#include "lsp.h"
#include "ltp.h"
#include "quant_lsp.h"
#include "cb_search.h"
#include "filters.h"
#include "stack_alloc.h"
#include "vq.h"
#include <speex/speex_bits.h>
#include "vbr.h"
#include "misc.h"
#include <speex/speex_callbacks.h>

#ifndef M_PI
#define M_PI           3.14159265358979323846  /* pi */
#endif

#ifndef NULL
#define NULL 0
#endif

#define SUBMODE(x) st->submodes[st->submodeID]->x


#ifdef FIXED_POINT
const spx_word32_t ol_gain_table[32]={18900, 25150, 33468, 44536, 59265, 
78865, 104946, 139653, 185838, 247297, 329081, 437913, 582736, 775454, 
1031906, 1373169, 1827293, 2431601, 3235761, 4305867, 5729870, 7624808, 
10146425, 13501971, 17967238, 23909222, 31816294, 42338330, 56340132, 
74972501, 99766822, 132760927};
const spx_word16_t exc_gain_quant_scal3_bound[7]={1841, 3883, 6051, 8062, 
10444, 13580, 18560};
const spx_word16_t exc_gain_quant_scal3[8]={1002, 2680, 5086, 7016, 9108, 
11781, 15380, 21740};
const spx_word16_t exc_gain_quant_scal1_bound[1]={14385};
const spx_word16_t exc_gain_quant_scal1[2]={11546, 17224};

#define LSP_MARGIN 16
#define LSP_DELTA1 6553
#define LSP_DELTA2 1638

#else

const float exc_gain_quant_scal3_bound[7]={0.112338, 0.236980, 0.369316, 
0.492054, 0.637471, 0.828874, 1.132784};
const float exc_gain_quant_scal3[8]={0.061130, 0.163546, 0.310413, 0.428220, 
0.555887, 0.719055, 0.938694, 1.326874};
const float exc_gain_quant_scal1_bound[1]={0.87798};
const float exc_gain_quant_scal1[2]={0.70469, 1.05127};

#define LSP_MARGIN .002
#define LSP_DELTA1 .2
#define LSP_DELTA2 .05

#endif




#define sqr(x) ((x)*(x))

void *nb_encoder_init(const SpeexMode *m)
{
   EncState *st;
   const SpeexNBMode *mode;
   int i;

   mode=(const SpeexNBMode *)m->mode;
#if defined(VAR_ARRAYS) || defined (USE_ALLOCA)
   st = (EncState*)speex_alloc(sizeof(EncState));
   st->stack = NULL;
#else
   st = (EncState*)speex_alloc(sizeof(EncState)+8000*sizeof(spx_sig_t));
   st->stack = ((char*)st) + sizeof(EncState);
#endif
   if (!st)
      return NULL;

   st->mode=m;

   st->frameSize = mode->frameSize;
   st->windowSize = st->frameSize*3/2;
   st->nbSubframes=mode->frameSize/mode->subframeSize;
   st->subframeSize=mode->subframeSize;
   st->lpcSize = mode->lpcSize;
   st->gamma1=mode->gamma1;
   st->gamma2=mode->gamma2;
   st->min_pitch=mode->pitchStart;
   st->max_pitch=mode->pitchEnd;
   st->lag_factor=mode->lag_factor;
   st->lpc_floor = mode->lpc_floor;

   st->submodes=mode->submodes;
   st->submodeID=st->submodeSelect=mode->defaultSubmode;
   st->bounded_pitch = 1;

   st->encode_submode = 1;
#ifdef EPIC_48K
   st->lbr_48k=mode->lbr48k;
#endif

   /* Allocating input buffer */
   st->inBuf = speex_alloc((st->windowSize)*sizeof(spx_sig_t));
   st->frame = st->inBuf;
   /* Allocating excitation buffer */
   st->excBuf = 
speex_alloc((mode->frameSize+mode->pitchEnd+1)*sizeof(spx_sig_t));
   st->exc = st->excBuf + mode->pitchEnd + 1;
   st->swBuf = 
speex_alloc((mode->frameSize+mode->pitchEnd+1)*sizeof(spx_sig_t));
   st->sw = st->swBuf + mode->pitchEnd + 1;

   st->innov = speex_alloc((st->frameSize)*sizeof(spx_sig_t));

   /* Asymmetric "pseudo-Hamming" window */
   {
      int part1, part2;
      part1=st->frameSize - (st->subframeSize>>1);
      part2=(st->frameSize>>1) + (st->subframeSize>>1);
      st->window = speex_alloc((st->windowSize)*sizeof(spx_word16_t));
      for (i=0;i<part1;i++)
         
st->window[i]=(spx_word16_t)(SIG_SCALING*(.54-.46*cos(M_PI*i/part1)));
      for (i=0;i<part2;i++)
         
st->window[part1+i]=(spx_word16_t)(SIG_SCALING*(.54+.46*cos(M_PI*i/part2)));
   }
   /* Create the window for autocorrelation (lag-windowing) */
   st->lagWindow = speex_alloc((st->lpcSize+1)*sizeof(spx_word16_t));
   for (i=0;i<st->lpcSize+1;i++)
      st->lagWindow[i]=16384*exp(-.5*sqr(2*M_PI*st->lag_factor*i));

   st->autocorr = speex_alloc((st->lpcSize+1)*sizeof(spx_word16_t));

   st->lpc = speex_alloc((st->lpcSize+1)*sizeof(spx_coef_t));
   st->interp_lpc = speex_alloc((st->lpcSize+1)*sizeof(spx_coef_t));
   st->interp_qlpc = speex_alloc((st->lpcSize+1)*sizeof(spx_coef_t));
   st->bw_lpc1 = speex_alloc((st->lpcSize+1)*sizeof(spx_coef_t));
   st->bw_lpc2 = speex_alloc((st->lpcSize+1)*sizeof(spx_coef_t));

   st->lsp = speex_alloc((st->lpcSize)*sizeof(spx_lsp_t));
   st->qlsp = speex_alloc((st->lpcSize)*sizeof(spx_lsp_t));
   st->old_lsp = speex_alloc((st->lpcSize)*sizeof(spx_lsp_t));
   st->old_qlsp = speex_alloc((st->lpcSize)*sizeof(spx_lsp_t));
   st->interp_lsp = speex_alloc((st->lpcSize)*sizeof(spx_lsp_t));
   st->interp_qlsp = speex_alloc((st->lpcSize)*sizeof(spx_lsp_t));

   st->first = 1;
   for (i=0;i<st->lpcSize;i++)
   {
      st->lsp[i]=LSP_SCALING*(M_PI*((float)(i+1)))/(st->lpcSize+1);
   }

   st->mem_sp = speex_alloc((st->lpcSize)*sizeof(spx_mem_t));
   st->mem_sw = speex_alloc((st->lpcSize)*sizeof(spx_mem_t));
   st->mem_sw_whole = speex_alloc((st->lpcSize)*sizeof(spx_mem_t));
   st->mem_exc = speex_alloc((st->lpcSize)*sizeof(spx_mem_t));

   st->pi_gain = speex_alloc((st->nbSubframes)*sizeof(spx_word32_t));

   st->pitch = speex_alloc((st->nbSubframes)*sizeof(int));

   st->vbr = speex_alloc(sizeof(VBRState));
   vbr_init(st->vbr);
   st->vbr_quality = 8;
   st->vbr_enabled = 0;
   st->vad_enabled = 0;
   st->dtx_enabled = 0;
   st->abr_enabled = 0;
   st->abr_drift = 0;

   st->plc_tuning = 2;
   st->complexity=2;
   st->sampling_rate=8000;
   st->dtx_count=0;

#ifdef ENABLE_VALGRIND
   VALGRIND_MAKE_READABLE(st, (st->stack-(char*)st));
#endif
   return st;
}

void nb_encoder_destroy(void *state)
{
   EncState *st=(EncState *)state;
   /* Free all allocated memory */

   vbr_destroy(st->vbr);

   /*Free state memory... should be last*/
   speex_free(st);
}

int nb_encode(void *state, void *vin, SpeexBits *bits)
{
   EncState *st;
   int i, sub, roots;
   int ol_pitch;
   spx_word16_t ol_pitch_coef;
   spx_word32_t ol_gain;
   VARDECL(spx_sig_t *res);
   VARDECL(spx_sig_t *target);
   VARDECL(spx_mem_t *mem);
   char *stack;
   VARDECL(spx_word16_t *syn_resp);
   VARDECL(spx_sig_t *real_exc);
#ifdef EPIC_48K
   int pitch_half[2];
   int ol_pitch_id=0;
#endif
   spx_word16_t *in = vin;

   st=(EncState *)state;
   stack=st->stack;

   /* Copy new data in input buffer */
   speex_move(st->inBuf, st->inBuf+st->frameSize, 
(st->windowSize-st->frameSize)*sizeof(spx_sig_t));
   for (i=0;i<st->frameSize;i++)
      st->inBuf[st->windowSize-st->frameSize+i] = SHL32(EXTEND32(in[i]), 
SIG_SHIFT);

   /* Move signals 1 frame towards the past */
   speex_move(st->excBuf, st->excBuf+st->frameSize, 
(st->max_pitch+1)*sizeof(spx_sig_t));
   speex_move(st->swBuf, st->swBuf+st->frameSize, 
(st->max_pitch+1)*sizeof(spx_sig_t));

   {
      VARDECL(spx_word16_t *w_sig);
      ALLOC(w_sig, st->windowSize, spx_word16_t);
      /* Window for analysis */
      for (i=0;i<st->windowSize;i++)
         w_sig[i] = 
EXTRACT16(SHR32(MULT16_16(EXTRACT16(SHR32(st->frame[i],SIG_SHIFT)),st->window[i]),SIG_SHIFT));

      /* Compute auto-correlation */
      _spx_autocorr(w_sig, st->autocorr, st->lpcSize+1, st->windowSize);
   }
   st->autocorr[0] = (spx_word16_t) (st->autocorr[0]*st->lpc_floor); /* 
Noise floor in auto-correlation domain */

   /* Lag windowing: equivalent to filtering in the power-spectrum domain */
   for (i=0;i<st->lpcSize+1;i++)
      st->autocorr[i] = MULT16_16_Q14(st->autocorr[i],st->lagWindow[i]);

   /* Levinson-Durbin */
   _spx_lpc(st->lpc+1, st->autocorr, st->lpcSize);
   st->lpc[0]=(spx_coef_t)LPC_SCALING;

   /* LPC to LSPs (x-domain) transform */
   roots=lpc_to_lsp (st->lpc, st->lpcSize, st->lsp, 15, LSP_DELTA1, stack);
   /* Check if we found all the roots */
   if (roots!=st->lpcSize)
   {
      /* Search again if we can afford it */
      if (st->complexity>1)
         roots = lpc_to_lsp (st->lpc, st->lpcSize, st->lsp, 11, LSP_DELTA2, 
stack);
      if (roots!=st->lpcSize)
      {
         /*If we can't find all LSP's, do some damage control and use 
previous filter*/
         for (i=0;i<st->lpcSize;i++)
         {
            st->lsp[i]=st->old_lsp[i];
         }
      }
   }



   /* Whole frame analysis (open-loop estimation of pitch and excitation 
gain) */
   {
      if (st->first)
         for (i=0;i<st->lpcSize;i++)
            st->interp_lsp[i] = st->lsp[i];
      else
         lsp_interpolate(st->old_lsp, st->lsp, st->interp_lsp, st->lpcSize, 
st->nbSubframes, st->nbSubframes<<1);

      lsp_enforce_margin(st->interp_lsp, st->lpcSize, LSP_MARGIN);

      /* Compute interpolated LPCs (unquantized) for whole frame*/
      lsp_to_lpc(st->interp_lsp, st->interp_lpc, st->lpcSize,stack);


      /*Open-loop pitch*/
      if (!st->submodes[st->submodeID] || st->vbr_enabled || st->vad_enabled 
|| SUBMODE(forced_pitch_gain) ||
          SUBMODE(lbr_pitch) != -1)
      {
         int nol_pitch[6];
         spx_word16_t nol_pitch_coef[6];

         bw_lpc(st->gamma1, st->interp_lpc, st->bw_lpc1, st->lpcSize);
         bw_lpc(st->gamma2, st->interp_lpc, st->bw_lpc2, st->lpcSize);

         filter_mem2(st->frame, st->bw_lpc1, st->bw_lpc2, st->sw, 
st->frameSize, st->lpcSize, st->mem_sw_whole);

         open_loop_nbest_pitch(st->sw, st->min_pitch, st->max_pitch, 
st->frameSize,
                               nol_pitch, nol_pitch_coef, 6, stack);
         ol_pitch=nol_pitch[0];
         ol_pitch_coef = nol_pitch_coef[0];
         /*Try to remove pitch multiples*/
         for (i=1;i<6;i++)
         {
#ifdef FIXED_POINT
            if ((nol_pitch_coef[i]>MULT16_16_Q15(nol_pitch_coef[0],27853)) 
&&
#else
            if ((nol_pitch_coef[i]>.85*nol_pitch_coef[0]) &&
#endif
                (ABS(2*nol_pitch[i]-ol_pitch)<=2 || 
ABS(3*nol_pitch[i]-ol_pitch)<=3 ||
                 ABS(4*nol_pitch[i]-ol_pitch)<=4 || 
ABS(5*nol_pitch[i]-ol_pitch)<=5))
            {
               /*ol_pitch_coef=nol_pitch_coef[i];*/
               ol_pitch = nol_pitch[i];
            }
         }
         /*if (ol_pitch>50)
           ol_pitch/=2;*/
         /*ol_pitch_coef = sqrt(ol_pitch_coef);*/

#ifdef EPIC_48K
         if (st->lbr_48k)
         {
            if (ol_pitch < st->min_pitch+2)
               ol_pitch = st->min_pitch+2;
            if (ol_pitch > st->max_pitch-2)
               ol_pitch = st->max_pitch-2;
            open_loop_nbest_pitch(st->sw, ol_pitch-2, ol_pitch+2, 
st->frameSize>>1,
                                  &pitch_half[0], nol_pitch_coef, 1, stack);
            open_loop_nbest_pitch(st->sw+(st->frameSize>>1), 
pitch_half[0]-1, pitch_half[0]+2, st->frameSize>>1,
                                  &pitch_half[1], nol_pitch_coef, 1, stack);
         }
#endif
      } else {
         ol_pitch=0;
         ol_pitch_coef=0;
      }
      /*Compute "real" excitation*/
      fir_mem2(st->frame, st->interp_lpc, st->exc, st->frameSize, 
st->lpcSize, st->mem_exc);

      /* Compute open-loop excitation gain */
#ifdef EPIC_48K
      if (st->lbr_48k)
      {
         float ol1=0,ol2=0;
         float ol_gain2;
         ol1 = compute_rms(st->exc, st->frameSize>>1);
         ol2 = compute_rms(st->exc+(st->frameSize>>1), st->frameSize>>1);
         ol1 *= ol1*(st->frameSize>>1);
         ol2 *= ol2*(st->frameSize>>1);

         ol_gain2=ol1;
         if (ol2>ol1)
            ol_gain2=ol2;
         ol_gain2 = 
sqrt(2*ol_gain2*(ol1+ol2))*1.3*(1-.5*GAIN_SCALING_1*GAIN_SCALING_1*ol_pitch_coef*ol_pitch_coef);

         ol_gain=SHR(sqrt(1+ol_gain2/st->frameSize),SIG_SHIFT);

      } else {
#endif
         ol_gain = SHL32(EXTEND32(compute_rms(st->exc, 
st->frameSize)),SIG_SHIFT);
#ifdef EPIC_48K
      }
#endif
   }

   /*VBR stuff*/
   if (st->vbr && (st->vbr_enabled||st->vad_enabled))
   {
      float lsp_dist=0;
      for (i=0;i<st->lpcSize;i++)
         lsp_dist += (st->old_lsp[i] - st->lsp[i])*(st->old_lsp[i] - 
st->lsp[i]);
      lsp_dist /= LSP_SCALING*LSP_SCALING;

      if (st->abr_enabled)
      {
         float qual_change=0;
         if (st->abr_drift2 * st->abr_drift > 0)
         {
            /* Only adapt if long-term and short-term drift are the same 
sign */
            qual_change = -.00001*st->abr_drift/(1+st->abr_count);
            if (qual_change>.05)
               qual_change=.05;
            if (qual_change<-.05)
               qual_change=-.05;
         }
         st->vbr_quality += qual_change;
         if (st->vbr_quality>10)
            st->vbr_quality=10;
         if (st->vbr_quality<0)
            st->vbr_quality=0;
      }

      st->relative_quality = vbr_analysis(st->vbr, in, st->frameSize, 
ol_pitch, GAIN_SCALING_1*ol_pitch_coef);
      /*if (delta_qual<0)*/
      /*  delta_qual*=.1*(3+st->vbr_quality);*/
      if (st->vbr_enabled)
      {
         int mode;
         int choice=0;
         float min_diff=100;
         mode = 8;
         while (mode)
         {
            int v1;
            float thresh;
            v1=(int)floor(st->vbr_quality);
            if (v1==10)
               thresh = vbr_nb_thresh[mode][v1];
            else
               thresh = (st->vbr_quality-v1)*vbr_nb_thresh[mode][v1+1] + 
(1+v1-st->vbr_quality)*vbr_nb_thresh[mode][v1];
            if (st->relative_quality > thresh &&
                st->relative_quality-thresh<min_diff)
            {
               choice = mode;
               min_diff = st->relative_quality-thresh;
            }
            mode--;
         }
         mode=choice;
         if (mode==0)
         {
            if (st->dtx_count==0 || lsp_dist>.05 || !st->dtx_enabled || 
st->dtx_count>20)
            {
               mode=1;
               st->dtx_count=1;
            } else {
               mode=0;
               st->dtx_count++;
            }
         } else {
            st->dtx_count=0;
         }

         speex_encoder_ctl(state, SPEEX_SET_MODE, &mode);

         if (st->abr_enabled)
         {
            int bitrate;
            speex_encoder_ctl(state, SPEEX_GET_BITRATE, &bitrate);
            st->abr_drift+=(bitrate-st->abr_enabled);
            st->abr_drift2 = .95*st->abr_drift2 + 
.05*(bitrate-st->abr_enabled);
            st->abr_count += 1.0;
         }

      } else {
         /*VAD only case*/
         int mode;
         if (st->relative_quality<2)
         {
            if (st->dtx_count==0 || lsp_dist>.05 || !st->dtx_enabled || 
st->dtx_count>20)
            {
               st->dtx_count=1;
               mode=1;
            } else {
               mode=0;
               st->dtx_count++;
            }
         } else {
            st->dtx_count = 0;
            mode=st->submodeSelect;
         }
         /*speex_encoder_ctl(state, SPEEX_SET_MODE, &mode);*/
         st->submodeID=mode;
      }
   } else {
      st->relative_quality = -1;
   }

   if (st->encode_submode)
   {
#ifdef EPIC_48K
   if (!st->lbr_48k) {
#endif

   /* First, transmit a zero for narrowband */
   speex_bits_pack(bits, 0, 1);

   /* Transmit the sub-mode we use for this frame */
   speex_bits_pack(bits, st->submodeID, NB_SUBMODE_BITS);

#ifdef EPIC_48K
   }
#endif
   }

   /* If null mode (no transmission), just set a couple things to zero*/
   if (st->submodes[st->submodeID] == NULL)
   {
      for (i=0;i<st->frameSize;i++)
         st->exc[i]=st->sw[i]=VERY_SMALL;

      for (i=0;i<st->lpcSize;i++)
         st->mem_sw[i]=0;
      st->first=1;
      st->bounded_pitch = 1;

      /* Final signal synthesis from excitation */
      iir_mem2(st->exc, st->interp_qlpc, st->frame, st->frameSize, 
st->lpcSize, st->mem_sp);

#ifdef RESYNTH
      for (i=0;i<st->frameSize;i++)
         in[i]=st->frame[i];
#endif
      return 0;

   }

   /* LSP Quantization */
   if (st->first)
   {
      for (i=0;i<st->lpcSize;i++)
         st->old_lsp[i] = st->lsp[i];
   }


   /*Quantize LSPs*/
#if 1 /*0 for unquantized*/
   SUBMODE(lsp_quant)(st->lsp, st->qlsp, st->lpcSize, bits);
#else
   for (i=0;i<st->lpcSize;i++)
     st->qlsp[i]=st->lsp[i];
#endif

#ifdef EPIC_48K
   if (st->lbr_48k) {
      speex_bits_pack(bits, pitch_half[0]-st->min_pitch, 7);
      speex_bits_pack(bits, pitch_half[1]-pitch_half[0]+1, 2);

      {
         int quant = (int)floor(.5+7.4*GAIN_SCALING_1*ol_pitch_coef);
         if (quant>7)
            quant=7;
         if (quant<0)
            quant=0;
         ol_pitch_id=quant;
         speex_bits_pack(bits, quant, 3);
         ol_pitch_coef=GAIN_SCALING*0.13514*quant;

      }
      {
         int qe = (int)(floor(.5+2.1*log(ol_gain*1.0/SIG_SCALING)))-2;
         if (qe<0)
            qe=0;
         if (qe>15)
            qe=15;
         ol_gain = exp((qe+2)/2.1)*SIG_SCALING;
         speex_bits_pack(bits, qe, 4);
      }

   } else {
#endif

   /*If we use low bit-rate pitch mode, transmit open-loop pitch*/
   if (SUBMODE(lbr_pitch)!=-1)
   {
      speex_bits_pack(bits, ol_pitch-st->min_pitch, 7);
   }

   if (SUBMODE(forced_pitch_gain))
   {
      int quant;
      quant = (int)floor(.5+15*ol_pitch_coef*GAIN_SCALING_1);
      if (quant>15)
         quant=15;
      if (quant<0)
         quant=0;
      speex_bits_pack(bits, quant, 4);
      ol_pitch_coef=GAIN_SCALING*0.066667*quant;
   }


   /*Quantize and transmit open-loop excitation gain*/
#ifdef FIXED_POINT
   {
      int qe = scal_quant32(ol_gain, ol_gain_table, 32);
      /*ol_gain = exp(qe/3.5)*SIG_SCALING;*/
      ol_gain = MULT16_32_Q15(28406,ol_gain_table[qe]);
      speex_bits_pack(bits, qe, 5);
   }
#else
   {
      int qe = (int)(floor(.5+3.5*log(ol_gain*1.0/SIG_SCALING)));
      if (qe<0)
         qe=0;
      if (qe>31)
         qe=31;
      ol_gain = exp(qe/3.5)*SIG_SCALING;
      speex_bits_pack(bits, qe, 5);
   }
#endif


#ifdef EPIC_48K
   }
#endif


   /* Special case for first frame */
   if (st->first)
   {
      for (i=0;i<st->lpcSize;i++)
         st->old_qlsp[i] = st->qlsp[i];
   }

   /* Filter response */
   ALLOC(res, st->subframeSize, spx_sig_t);
   /* Target signal */
   ALLOC(target, st->subframeSize, spx_sig_t);
   ALLOC(syn_resp, st->subframeSize, spx_word16_t);
   ALLOC(real_exc, st->subframeSize, spx_sig_t);
   ALLOC(mem, st->lpcSize, spx_mem_t);

   /* Loop on sub-frames */
   for (sub=0;sub<st->nbSubframes;sub++)
   {
      int   offset;
      spx_sig_t *sp, *sw, *exc;
      int pitch;
      int response_bound = st->subframeSize;
#ifdef EPIC_48K
      if (st->lbr_48k)
      {
         if (sub*2 < st->nbSubframes)
            ol_pitch = pitch_half[0];
         else
            ol_pitch = pitch_half[1];
      }
#endif

      /* Offset relative to start of frame */
      offset = st->subframeSize*sub;
      /* Original signal */
      sp=st->frame+offset;
      /* Excitation */
      exc=st->exc+offset;
      /* Weighted signal */
      sw=st->sw+offset;

      /* LSP interpolation (quantized and unquantized) */
      lsp_interpolate(st->old_lsp, st->lsp, st->interp_lsp, st->lpcSize, 
sub, st->nbSubframes);
      lsp_interpolate(st->old_qlsp, st->qlsp, st->interp_qlsp, st->lpcSize, 
sub, st->nbSubframes);

      /* Make sure the filters are stable */
      lsp_enforce_margin(st->interp_lsp, st->lpcSize, LSP_MARGIN);
      lsp_enforce_margin(st->interp_qlsp, st->lpcSize, LSP_MARGIN);

      /* Compute interpolated LPCs (quantized and unquantized) */
      lsp_to_lpc(st->interp_lsp, st->interp_lpc, st->lpcSize,stack);

      lsp_to_lpc(st->interp_qlsp, st->interp_qlpc, st->lpcSize, stack);

      /* Compute analysis filter gain at w=pi (for use in SB-CELP) */
      {
         spx_word32_t pi_g=st->interp_qlpc[0];
         for (i=1;i<=st->lpcSize;i+=2)
         {
            /*pi_g += -st->interp_qlpc[i] +  st->interp_qlpc[i+1];*/
            pi_g = ADD32(pi_g, 
SUB32(st->interp_qlpc[i+1],st->interp_qlpc[i]));
         }
         st->pi_gain[sub] = pi_g;
      }


      /* Compute bandwidth-expanded (unquantized) LPCs for perceptual 
weighting */
      bw_lpc(st->gamma1, st->interp_lpc, st->bw_lpc1, st->lpcSize);
      if (st->gamma2>=0)
         bw_lpc(st->gamma2, st->interp_lpc, st->bw_lpc2, st->lpcSize);
      else
      {
         st->bw_lpc2[0]=1;
         for (i=1;i<=st->lpcSize;i++)
            st->bw_lpc2[i]=0;
      }

      for (i=0;i<st->subframeSize;i++)
         real_exc[i] = exc[i];

      if (st->complexity==0)
         response_bound >>= 1;
      compute_impulse_response(st->interp_qlpc, st->bw_lpc1, st->bw_lpc2, 
syn_resp, response_bound, st->lpcSize, stack);
      for (i=response_bound;i<st->subframeSize;i++)
         syn_resp[i]=VERY_SMALL;

      /* Reset excitation */
      for (i=0;i<st->subframeSize;i++)
         exc[i]=VERY_SMALL;

      /* Compute zero response of A(z/g1) / ( A(z/g2) * A(z) ) */
      for (i=0;i<st->lpcSize;i++)
         mem[i]=st->mem_sp[i];
#ifdef SHORTCUTS2
      iir_mem2(exc, st->interp_qlpc, exc, response_bound, st->lpcSize, mem);
      for (i=0;i<st->lpcSize;i++)
         mem[i]=st->mem_sw[i];
      filter_mem2(exc, st->bw_lpc1, st->bw_lpc2, res, response_bound, 
st->lpcSize, mem);
      for (i=response_bound;i<st->subframeSize;i++)
         res[i]=0;
#else
      iir_mem2(exc, st->interp_qlpc, exc, st->subframeSize, st->lpcSize, 
mem);
      for (i=0;i<st->lpcSize;i++)
         mem[i]=st->mem_sw[i];
      filter_mem2(exc, st->bw_lpc1, st->bw_lpc2, res, st->subframeSize, 
st->lpcSize, mem);
#endif

      /* Compute weighted signal */
      for (i=0;i<st->lpcSize;i++)
         mem[i]=st->mem_sw[i];
      filter_mem2(sp, st->bw_lpc1, st->bw_lpc2, sw, st->subframeSize, 
st->lpcSize, mem);

      if (st->complexity==0)
         for (i=0;i<st->lpcSize;i++)
            st->mem_sw[i]=mem[i];

      /* Compute target signal */
      for (i=0;i<st->subframeSize;i++)
         target[i]=sw[i]-res[i];

      for (i=0;i<st->subframeSize;i++)
         exc[i]=0;

      /* If we have a long-term predictor (otherwise, something's wrong) */
      if (SUBMODE(ltp_quant))
      {
         int pit_min, pit_max;
         /* Long-term prediction */
         if (SUBMODE(lbr_pitch) != -1)
         {
            /* Low bit-rate pitch handling */
            int margin;
            margin = SUBMODE(lbr_pitch);
            if (margin)
            {
               if (ol_pitch < st->min_pitch+margin-1)
                  ol_pitch=st->min_pitch+margin-1;
               if (ol_pitch > st->max_pitch-margin)
                  ol_pitch=st->max_pitch-margin;
               pit_min = ol_pitch-margin+1;
               pit_max = ol_pitch+margin;
            } else {
               pit_min=pit_max=ol_pitch;
            }
         } else {
            pit_min = st->min_pitch;
            pit_max = st->max_pitch;
         }

         /* Force pitch to use only the current frame if needed */
         if (st->bounded_pitch && pit_max>offset)
            pit_max=offset;

#ifdef EPIC_48K
         if (st->lbr_48k)
         {
            pitch = SUBMODE(ltp_quant)(target, sw, st->interp_qlpc, 
st->bw_lpc1, st->bw_lpc2,
                                       exc, SUBMODE(ltp_params), pit_min, 
pit_max, ol_pitch_coef,
                                       st->lpcSize, st->subframeSize, bits, 
stack,
                                       exc, syn_resp, st->complexity, 
ol_pitch_id, st->plc_tuning);
         } else {
#endif

         /* Perform pitch search */
         pitch = SUBMODE(ltp_quant)(target, sw, st->interp_qlpc, 
st->bw_lpc1, st->bw_lpc2,
                                    exc, SUBMODE(ltp_params), pit_min, 
pit_max, ol_pitch_coef,
                                    st->lpcSize, st->subframeSize, bits, 
stack,
                                    exc, syn_resp, st->complexity, 0, 
st->plc_tuning);
#ifdef EPIC_48K
         }
#endif

         st->pitch[sub]=pitch;
      } else {
         speex_error ("No pitch prediction, what's wrong");
      }

      /* Quantization of innovation */
      {
         spx_sig_t *innov;
         spx_word32_t ener=0;
         spx_word16_t fine_gain;

         innov = st->innov+sub*st->subframeSize;
         for (i=0;i<st->subframeSize;i++)
            innov[i]=0;

         for (i=0;i<st->subframeSize;i++)
            real_exc[i] = SUB32(real_exc[i], exc[i]);

         ener = SHL32(EXTEND32(compute_rms(real_exc, 
st->subframeSize)),SIG_SHIFT);

         /*FIXME: Should use DIV32_16 and make sure result fits in 16 bits 
*/
#ifdef FIXED_POINT
         {
            spx_word32_t f = DIV32(ener,PSHR32(ol_gain,SIG_SHIFT));
            if (f<32768)
               fine_gain = f;
            else
               fine_gain = 32767;
         }
#else
         fine_gain = DIV32_16(ener,PSHR32(ol_gain,SIG_SHIFT));
#endif
         /* Calculate gain correction for the sub-frame (if any) */
         if (SUBMODE(have_subframe_gain))
         {
            int qe;
            if (SUBMODE(have_subframe_gain)==3)
            {
               qe = scal_quant(fine_gain, exc_gain_quant_scal3_bound, 8);
               speex_bits_pack(bits, qe, 3);
               ener=MULT16_32_Q14(exc_gain_quant_scal3[qe],ol_gain);
            } else {
               qe = scal_quant(fine_gain, exc_gain_quant_scal1_bound, 2);
               speex_bits_pack(bits, qe, 1);
               ener=MULT16_32_Q14(exc_gain_quant_scal1[qe],ol_gain);
            }
         } else {
            ener=ol_gain;
         }

         /*printf ("%f %f\n", ener, ol_gain);*/

         /* Normalize innovation */
         signal_div(target, target, ener, st->subframeSize);

         /* Quantize innovation */
         if (SUBMODE(innovation_quant))
         {
            /* Codebook search */
            SUBMODE(innovation_quant)(target, st->interp_qlpc, st->bw_lpc1, 
st->bw_lpc2,
                                      SUBMODE(innovation_params), 
st->lpcSize, st->subframeSize,
                                      innov, syn_resp, bits, stack, 
st->complexity, SUBMODE(double_codebook));

            /* De-normalize innovation and update excitation */
            signal_mul(innov, innov, ener, st->subframeSize);

            for (i=0;i<st->subframeSize;i++)
               exc[i] = ADD32(exc[i],innov[i]);
         } else {
            speex_error("No fixed codebook");
         }

         /* In some (rare) modes, we do a second search (more bits) to 
reduce noise even more */
         if (SUBMODE(double_codebook)) {
            char *tmp_stack=stack;
            VARDECL(spx_sig_t *innov2);
            ALLOC(innov2, st->subframeSize, spx_sig_t);
            for (i=0;i<st->subframeSize;i++)
               innov2[i]=0;
            for (i=0;i<st->subframeSize;i++)
               target[i]*=2.2;
            SUBMODE(innovation_quant)(target, st->interp_qlpc, st->bw_lpc1, 
st->bw_lpc2,
                                      SUBMODE(innovation_params), 
st->lpcSize, st->subframeSize,
                                      innov2, syn_resp, bits, stack, 
st->complexity, 0);
            signal_mul(innov2, innov2, (spx_word32_t) (ener*(1/2.2)), 
st->subframeSize);
            for (i=0;i<st->subframeSize;i++)
               exc[i] = ADD32(exc[i],innov2[i]);
            stack = tmp_stack;
         }

      }

      /* Final signal synthesis from excitation */
      iir_mem2(exc, st->interp_qlpc, sp, st->subframeSize, st->lpcSize, 
st->mem_sp);

      /* Compute weighted signal again, from synthesized speech (not sure 
it's the right thing) */
      if (st->complexity!=0)
         filter_mem2(sp, st->bw_lpc1, st->bw_lpc2, sw, st->subframeSize, 
st->lpcSize, st->mem_sw);

   }

   /* Store the LSPs for interpolation in the next frame */
   if (st->submodeID>=1)
   {
      for (i=0;i<st->lpcSize;i++)
         st->old_lsp[i] = st->lsp[i];
      for (i=0;i<st->lpcSize;i++)
         st->old_qlsp[i] = st->qlsp[i];
   }

   if (st->submodeID==1)
   {
      if (st->dtx_count)
         speex_bits_pack(bits, 15, 4);
      else
         speex_bits_pack(bits, 0, 4);
   }

   /* The next frame will not be the first (Duh!) */
   st->first = 0;

#ifdef RESYNTH
   /* Replace input by synthesized speech */
   for (i=0;i<st->frameSize;i++)
   {
      spx_word32_t sig = PSHR32(st->frame[i],SIG_SHIFT);
      if (sig>32767)
         sig = 32767;
      if (sig<-32767)
         sig = -32767;
     in[i]=sig;
   }
#endif

   if (SUBMODE(innovation_quant) == noise_codebook_quant || 
st->submodeID==0)
      st->bounded_pitch = 1;
   else
      st->bounded_pitch = 0;

   return 1;
}


void *nb_decoder_init(const SpeexMode *m)
{
   DecState *st;
   const SpeexNBMode *mode;
   int i;

   mode=(const SpeexNBMode*)m->mode;
#if defined(VAR_ARRAYS) || defined (USE_ALLOCA)
   st = (DecState *)speex_alloc(sizeof(DecState));
   st->stack = NULL;
#else
   st = (DecState *)speex_alloc(sizeof(DecState)+4000*sizeof(spx_sig_t));
   st->stack = ((char*)st) + sizeof(DecState);
#endif
   if (!st)
      return NULL;

   st->mode=m;


   st->encode_submode = 1;
#ifdef EPIC_48K
   st->lbr_48k=mode->lbr48k;
#endif

   st->first=1;
   /* Codec parameters, should eventually have several "modes"*/
   st->frameSize = mode->frameSize;
   st->nbSubframes=mode->frameSize/mode->subframeSize;
   st->subframeSize=mode->subframeSize;
   st->lpcSize = mode->lpcSize;
   st->min_pitch=mode->pitchStart;
   st->max_pitch=mode->pitchEnd;

   st->submodes=mode->submodes;
   st->submodeID=mode->defaultSubmode;

   st->lpc_enh_enabled=0;


   st->inBuf = speex_alloc((st->frameSize)*sizeof(spx_sig_t));
   st->frame = st->inBuf;
   st->excBuf = speex_alloc((st->frameSize + st->max_pitch + 
1)*sizeof(spx_sig_t));
   st->exc = st->excBuf + st->max_pitch + 1;
   for (i=0;i<st->frameSize;i++)
      st->inBuf[i]=0;
   for (i=0;i<st->frameSize + st->max_pitch + 1;i++)
      st->excBuf[i]=0;
   st->innov = speex_alloc((st->frameSize)*sizeof(spx_sig_t));

   st->interp_qlpc = speex_alloc((st->lpcSize+1)*sizeof(spx_coef_t));
   st->qlsp = speex_alloc((st->lpcSize)*sizeof(spx_lsp_t));
   st->old_qlsp = speex_alloc((st->lpcSize)*sizeof(spx_lsp_t));
   st->interp_qlsp = speex_alloc((st->lpcSize)*sizeof(spx_lsp_t));
   st->mem_sp = speex_alloc((5*st->lpcSize)*sizeof(spx_mem_t));
   st->comb_mem = speex_alloc(sizeof(CombFilterMem));
   comb_filter_mem_init (st->comb_mem);

   st->pi_gain = speex_alloc((st->nbSubframes)*sizeof(spx_word32_t));
   st->last_pitch = 40;
   st->count_lost=0;
   st->pitch_gain_buf[0] = st->pitch_gain_buf[1] = st->pitch_gain_buf[2] = 
0;
   st->pitch_gain_buf_idx = 0;

   st->sampling_rate=8000;
   st->last_ol_gain = 0;

   st->user_callback.func = &speex_default_user_handler;
   st->user_callback.data = NULL;
   for (i=0;i<16;i++)
      st->speex_callbacks[i].func = NULL;

   st->voc_m1=st->voc_m2=st->voc_mean=0;
   st->voc_offset=0;
   st->dtx_enabled=0;
#ifdef ENABLE_VALGRIND
   VALGRIND_MAKE_READABLE(st, (st->stack-(char*)st));
#endif
   return st;
}

void nb_decoder_destroy(void *state)
{
   DecState *st;
   st=(DecState*)state;

   speex_free(state);
}

#define median3(a, b, c)	((a) < (b) ? ((b) < (c) ? (b) : ((a) < (c) ? (c) : 
(a))) : ((c) < (b) ? (b) : ((c) < (a) ? (c) : (a))))

static void nb_decode_lost(DecState *st, spx_word16_t *out, char *stack)
{
   int i, sub;
   VARDECL(spx_coef_t *awk1);
   VARDECL(spx_coef_t *awk2);
   VARDECL(spx_coef_t *awk3);
   float pitch_gain, fact;
   spx_word16_t gain_med;

   fact = exp(-.04*st->count_lost*st->count_lost);
   gain_med = median3(st->pitch_gain_buf[0], st->pitch_gain_buf[1], 
st->pitch_gain_buf[2]);
   if (gain_med < st->last_pitch_gain)
      st->last_pitch_gain = gain_med;

   pitch_gain = GAIN_SCALING_1*st->last_pitch_gain;
   if (pitch_gain>.95)
      pitch_gain=.95;

   pitch_gain = fact*pitch_gain + VERY_SMALL;

   /* Shift all buffers by one frame */
   /*speex_move(st->inBuf, st->inBuf+st->frameSize, 
(st->bufSize-st->frameSize)*sizeof(spx_sig_t));*/
   speex_move(st->excBuf, st->excBuf+st->frameSize, (st->max_pitch + 
1)*sizeof(spx_sig_t));

   ALLOC(awk1, (st->lpcSize+1), spx_coef_t);
   ALLOC(awk2, (st->lpcSize+1), spx_coef_t);
   ALLOC(awk3, (st->lpcSize+1), spx_coef_t);

   for (sub=0;sub<st->nbSubframes;sub++)
   {
      int offset;
      spx_sig_t *sp, *exc;
      /* Offset relative to start of frame */
      offset = st->subframeSize*sub;
      /* Original signal */
      sp=st->frame+offset;
      /* Excitation */
      exc=st->exc+offset;
      /* Excitation after post-filter*/

      /* Calculate perceptually enhanced LPC filter */
      if (st->lpc_enh_enabled)
      {
         spx_word16_t k1,k2,k3;
         if (st->submodes[st->submodeID] != NULL)
         {
            k1=SUBMODE(lpc_enh_k1);
            k2=SUBMODE(lpc_enh_k2);
            k3=SUBMODE(lpc_enh_k3);
         } else {
            k1=k2=.7*GAMMA_SCALING;
            k3=.0;
         }
         bw_lpc(k1, st->interp_qlpc, awk1, st->lpcSize);
         bw_lpc(k2, st->interp_qlpc, awk2, st->lpcSize);
         bw_lpc(k3, st->interp_qlpc, awk3, st->lpcSize);
      }

      /* Make up a plausible excitation */
      /* FIXME: THIS CAN BE IMPROVED */
      /*if (pitch_gain>.95)
        pitch_gain=.95;*/
      {
      float innov_gain=0;
      innov_gain = compute_rms(st->innov, st->frameSize);
      for (i=0;i<st->subframeSize;i++)
      {
#if 0
         exc[i] = pitch_gain * exc[i - st->last_pitch] + 
fact*sqrt(1-pitch_gain)*st->innov[i+offset];
         /*Just so it give the same lost packets as with if 0*/
         /*rand();*/
#else
         /*exc[i]=pitch_gain*exc[i-st->last_pitch] +  
fact*st->innov[i+offset];*/
         exc[i]=pitch_gain*(exc[i-st->last_pitch]+VERY_SMALL) +
         fact*sqrt(1-pitch_gain)*speex_rand(innov_gain);
#endif
      }
      }
      for (i=0;i<st->subframeSize;i++)
         sp[i]=exc[i];

      /* Signal synthesis */
      if (st->lpc_enh_enabled)
      {
         filter_mem2(sp, awk2, awk1, sp, st->subframeSize, st->lpcSize,
                     st->mem_sp+st->lpcSize);
         filter_mem2(sp, awk3, st->interp_qlpc, sp, st->subframeSize, 
st->lpcSize,
                     st->mem_sp);
      } else {
         for (i=0;i<st->lpcSize;i++)
            st->mem_sp[st->lpcSize+i] = 0;
         iir_mem2(sp, st->interp_qlpc, sp, st->subframeSize, st->lpcSize,
                     st->mem_sp);
      }
   }

   for (i=0;i<st->frameSize;i++)
   {
      spx_word32_t sig = PSHR32(st->frame[i],SIG_SHIFT);
      if (sig>32767)
         sig = 32767;
      if (sig<-32767)
         sig = -32767;
     out[i]=sig;
   }

   st->first = 0;
   st->count_lost++;
   st->pitch_gain_buf[st->pitch_gain_buf_idx++] = GAIN_SCALING*pitch_gain;
   if (st->pitch_gain_buf_idx > 2) /* rollover */
      st->pitch_gain_buf_idx = 0;
}

int nb_decode(void *state, SpeexBits *bits, void *vout)
{
   DecState *st;
   int i, sub;
   int pitch;
   spx_word16_t pitch_gain[3];
   spx_word32_t ol_gain=0;
   int ol_pitch=0;
   spx_word16_t ol_pitch_coef=0;
   int best_pitch=40;
   spx_word16_t best_pitch_gain=0;
   int wideband;
   int m;
   char *stack;
   VARDECL(spx_coef_t *awk1);
   VARDECL(spx_coef_t *awk2);
   VARDECL(spx_coef_t *awk3);
   spx_word16_t pitch_average=0;
#ifdef EPIC_48K
   int pitch_half[2];
   int ol_pitch_id=0;
#endif
   spx_word16_t *out = vout;

   st=(DecState*)state;
   stack=st->stack;

   if (st->encode_submode)
   {
#ifdef EPIC_48K
   if (!st->lbr_48k) {
#endif

   /* Check if we're in DTX mode*/
   if (!bits && st->dtx_enabled)
   {
      st->submodeID=0;
   } else
   {
      /* If bits is NULL, consider the packet to be lost (what could we do 
anyway) */
      if (!bits)
      {
         nb_decode_lost(st, out, stack);
         return 0;
      }

      /* Search for next narrowband block (handle requests, skip wideband 
blocks) */
      do {
         if (speex_bits_remaining(bits)<5)
            return -1;
         wideband = speex_bits_unpack_unsigned(bits, 1);
         if (wideband) /* Skip wideband block (for compatibility) */
         {
            int submode;
            int advance;
            advance = submode = speex_bits_unpack_unsigned(bits, 
SB_SUBMODE_BITS);
            speex_mode_query(&speex_wb_mode, SPEEX_SUBMODE_BITS_PER_FRAME, 
&advance);
            if (advance < 0)
            {
               speex_warning ("Invalid wideband mode encountered. Corrupted 
stream?");
               return -2;
            }
            advance -= (SB_SUBMODE_BITS+1);
            speex_bits_advance(bits, advance);

            if (speex_bits_remaining(bits)<5)
               return -1;
            wideband = speex_bits_unpack_unsigned(bits, 1);
            if (wideband)
            {
               advance = submode = speex_bits_unpack_unsigned(bits, 
SB_SUBMODE_BITS);
               speex_mode_query(&speex_wb_mode, 
SPEEX_SUBMODE_BITS_PER_FRAME, &advance);
               if (advance < 0)
               {
                  speex_warning ("Invalid wideband mode encountered: 
corrupted stream?");
                  return -2;
               }
               advance -= (SB_SUBMODE_BITS+1);
               speex_bits_advance(bits, advance);
               wideband = speex_bits_unpack_unsigned(bits, 1);
               if (wideband)
               {
                  speex_warning ("More than two wideband layers found: 
corrupted stream?");
                  return -2;
               }

            }
         }
         if (speex_bits_remaining(bits)<4)
            return -1;
         /* FIXME: Check for overflow */
         m = speex_bits_unpack_unsigned(bits, 4);
         if (m==15) /* We found a terminator */
         {
            return -1;
         } else if (m==14) /* Speex in-band request */
         {
            int ret = speex_inband_handler(bits, st->speex_callbacks, 
state);
            if (ret)
               return ret;
         } else if (m==13) /* User in-band request */
         {
            int ret = st->user_callback.func(bits, state, 
st->user_callback.data);
            if (ret)
               return ret;
         } else if (m>8) /* Invalid mode */
         {
            speex_warning("Invalid mode encountered: corrupted stream?");
            return -2;
         }

      } while (m>8);

      /* Get the sub-mode that was used */
      st->submodeID = m;

   }
#ifdef EPIC_48K
   }
#endif
   }

   /* Shift all buffers by one frame */
   speex_move(st->excBuf, st->excBuf+st->frameSize, (st->max_pitch + 
1)*sizeof(spx_sig_t));

   /* If null mode (no transmission), just set a couple things to zero*/
   if (st->submodes[st->submodeID] == NULL)
   {
      VARDECL(spx_coef_t *lpc);
      ALLOC(lpc, 11, spx_coef_t);
      bw_lpc(GAMMA_SCALING*.93, st->interp_qlpc, lpc, 10);
      {
         float innov_gain=0;
         float pgain=GAIN_SCALING_1*st->last_pitch_gain;
         if (pgain>.6)
            pgain=.6;
	 innov_gain = compute_rms(st->innov, st->frameSize);
         for (i=0;i<st->frameSize;i++)
            st->exc[i]=VERY_SMALL;
         speex_rand_vec(innov_gain, st->exc, st->frameSize);
      }


      st->first=1;

      /* Final signal synthesis from excitation */
      iir_mem2(st->exc, lpc, st->frame, st->frameSize, st->lpcSize, 
st->mem_sp);

      for (i=0;i<st->frameSize;i++)
      {
         spx_word32_t sig = PSHR32(st->frame[i],SIG_SHIFT);
         if (sig>32767)
            sig = 32767;
         if (sig<-32767)
            sig = -32767;
         out[i]=sig;
      }

      st->count_lost=0;
      return 0;
   }

   /* Unquantize LSPs */
   SUBMODE(lsp_unquant)(st->qlsp, st->lpcSize, bits);

   /*Damp memory if a frame was lost and the LSP changed too much*/
   if (st->count_lost)
   {
      float lsp_dist=0, fact;
      for (i=0;i<st->lpcSize;i++)
         lsp_dist += fabs(st->old_qlsp[i] - st->qlsp[i]);
      lsp_dist /= LSP_SCALING;
      fact = .6*exp(-.2*lsp_dist);
      for (i=0;i<2*st->lpcSize;i++)
         st->mem_sp[i] = (spx_mem_t)(st->mem_sp[i]*fact);
   }


   /* Handle first frame and lost-packet case */
   if (st->first || st->count_lost)
   {
      for (i=0;i<st->lpcSize;i++)
         st->old_qlsp[i] = st->qlsp[i];
   }

#ifdef EPIC_48K
   if (st->lbr_48k) {
      pitch_half[0] = st->min_pitch+speex_bits_unpack_unsigned(bits, 7);
      pitch_half[1] = pitch_half[0]+speex_bits_unpack_unsigned(bits, 2)-1;

      ol_pitch_id = speex_bits_unpack_unsigned(bits, 3);
      ol_pitch_coef=GAIN_SCALING*0.13514*ol_pitch_id;

      {
         int qe;
         qe = speex_bits_unpack_unsigned(bits, 4);
         ol_gain = SIG_SCALING*exp((qe+2)/2.1),SIG_SHIFT;
      }

   } else {
#endif

   /* Get open-loop pitch estimation for low bit-rate pitch coding */
   if (SUBMODE(lbr_pitch)!=-1)
   {
      ol_pitch = st->min_pitch+speex_bits_unpack_unsigned(bits, 7);
   }

   if (SUBMODE(forced_pitch_gain))
   {
      int quant;
      quant = speex_bits_unpack_unsigned(bits, 4);
      ol_pitch_coef=GAIN_SCALING*0.066667*quant;
   }

   /* Get global excitation gain */
   {
      int qe;
      qe = speex_bits_unpack_unsigned(bits, 5);
#ifdef FIXED_POINT
      ol_gain = MULT16_32_Q15(28406,ol_gain_table[qe]);
#else
      ol_gain = SIG_SCALING*exp(qe/3.5);
#endif
   }
#ifdef EPIC_48K
   }
#endif

   ALLOC(awk1, st->lpcSize+1, spx_coef_t);
   ALLOC(awk2, st->lpcSize+1, spx_coef_t);
   ALLOC(awk3, st->lpcSize+1, spx_coef_t);

   if (st->submodeID==1)
   {
      int extra;
      extra = speex_bits_unpack_unsigned(bits, 4);

      if (extra==15)
         st->dtx_enabled=1;
      else
         st->dtx_enabled=0;
   }
   if (st->submodeID>1)
      st->dtx_enabled=0;

   /*Loop on subframes */
   for (sub=0;sub<st->nbSubframes;sub++)
   {
      int offset;
      spx_sig_t *sp, *exc;
      spx_word16_t tmp;

#ifdef EPIC_48K
      if (st->lbr_48k)
      {
         if (sub*2 < st->nbSubframes)
            ol_pitch = pitch_half[0];
         else
            ol_pitch = pitch_half[1];
      }
#endif

      /* Offset relative to start of frame */
      offset = st->subframeSize*sub;
      /* Original signal */
      sp=st->frame+offset;
      /* Excitation */
      exc=st->exc+offset;
      /* Excitation after post-filter*/

      /* LSP interpolation (quantized and unquantized) */
      lsp_interpolate(st->old_qlsp, st->qlsp, st->interp_qlsp, st->lpcSize, 
sub, st->nbSubframes);

      /* Make sure the LSP's are stable */
      lsp_enforce_margin(st->interp_qlsp, st->lpcSize, LSP_MARGIN);


      /* Compute interpolated LPCs (unquantized) */
      lsp_to_lpc(st->interp_qlsp, st->interp_qlpc, st->lpcSize, stack);

      /* Compute enhanced synthesis filter */
      if (st->lpc_enh_enabled)
      {
         bw_lpc(SUBMODE(lpc_enh_k1), st->interp_qlpc, awk1, st->lpcSize);
         bw_lpc(SUBMODE(lpc_enh_k2), st->interp_qlpc, awk2, st->lpcSize);
         bw_lpc(SUBMODE(lpc_enh_k3), st->interp_qlpc, awk3, st->lpcSize);
      }

      /* Compute analysis filter at w=pi */
      {
         spx_word32_t pi_g=st->interp_qlpc[0];
         for (i=1;i<=st->lpcSize;i+=2)
         {
            /*pi_g += -st->interp_qlpc[i] +  st->interp_qlpc[i+1];*/
            pi_g = ADD32(pi_g, 
SUB32(st->interp_qlpc[i+1],st->interp_qlpc[i]));
         }
         st->pi_gain[sub] = pi_g;
      }

      /* Reset excitation */
      for (i=0;i<st->subframeSize;i++)
         exc[i]=0;

      /*Adaptive codebook contribution*/
      if (SUBMODE(ltp_unquant))
      {
         int pit_min, pit_max;
         /* Handle pitch constraints if any */
         if (SUBMODE(lbr_pitch) != -1)
         {
            int margin;
            margin = SUBMODE(lbr_pitch);
            if (margin)
            {
/* GT - need optimization?
               if (ol_pitch < st->min_pitch+margin-1)
                  ol_pitch=st->min_pitch+margin-1;
               if (ol_pitch > st->max_pitch-margin)
                  ol_pitch=st->max_pitch-margin;
               pit_min = ol_pitch-margin+1;
               pit_max = ol_pitch+margin;
*/
               pit_min = ol_pitch-margin+1;
               if (pit_min < st->min_pitch)
		  pit_min = st->min_pitch;
               pit_max = ol_pitch+margin;
               if (pit_max > st->max_pitch)
		  pit_max = st->max_pitch;
            } else {
               pit_min = pit_max = ol_pitch;
            }
         } else {
            pit_min = st->min_pitch;
            pit_max = st->max_pitch;
         }


#ifdef EPIC_48K
         if (st->lbr_48k)
         {
             SUBMODE(ltp_unquant)(exc, pit_min, pit_max, ol_pitch_coef, 
SUBMODE(ltp_params),
                                  st->subframeSize, &pitch, &pitch_gain[0], 
bits, stack,
                                  st->count_lost, offset, 
st->last_pitch_gain, ol_pitch_id);
         } else {
#endif

             SUBMODE(ltp_unquant)(exc, pit_min, pit_max, ol_pitch_coef, 
SUBMODE(ltp_params),
                                  st->subframeSize, &pitch, &pitch_gain[0], 
bits, stack,
                                  st->count_lost, offset, 
st->last_pitch_gain, 0);

#ifdef EPIC_48K
         }
#endif


         /* If we had lost frames, check energy of last received frame */
         if (st->count_lost && ol_gain < st->last_ol_gain)
         {
            float fact = (float)ol_gain/(st->last_ol_gain+1);
            for (i=0;i<st->subframeSize;i++)
               exc[i]*=fact;
         }

         tmp = gain_3tap_to_1tap(pitch_gain);

         pitch_average += tmp;
         if (tmp>best_pitch_gain)
         {
            best_pitch = pitch;
	    best_pitch_gain = tmp;
         }
      } else {
         speex_error("No pitch prediction, what's wrong");
      }

      /* Unquantize the innovation */
      {
         int q_energy;
         spx_word32_t ener;
         spx_sig_t *innov;

         innov = st->innov+sub*st->subframeSize;
         for (i=0;i<st->subframeSize;i++)
            innov[i]=0;

         /* Decode sub-frame gain correction */
         if (SUBMODE(have_subframe_gain)==3)
         {
            q_energy = speex_bits_unpack_unsigned(bits, 3);
            ener = MULT16_32_Q14(exc_gain_quant_scal3[q_energy],ol_gain);
         } else if (SUBMODE(have_subframe_gain)==1)
         {
            q_energy = speex_bits_unpack_unsigned(bits, 1);
            ener = MULT16_32_Q14(exc_gain_quant_scal1[q_energy],ol_gain);
         } else {
            ener = ol_gain;
         }

         if (SUBMODE(innovation_unquant))
         {
            /*Fixed codebook contribution*/
            SUBMODE(innovation_unquant)(innov, SUBMODE(innovation_params), 
st->subframeSize, bits, stack);
         } else {
            speex_error("No fixed codebook");
         }

         /* De-normalize innovation and update excitation */
#ifdef FIXED_POINT
         signal_mul(innov, innov, ener, st->subframeSize);
#else
         signal_mul(innov, innov, ener, st->subframeSize);
#endif
         /*Vocoder mode*/
         if (st->submodeID==1)
         {
            float g=ol_pitch_coef*GAIN_SCALING_1;


            for (i=0;i<st->subframeSize;i++)
               exc[i]=0;
            while (st->voc_offset<st->subframeSize)
            {
               if (st->voc_offset>=0)
                  exc[st->voc_offset]=SIG_SCALING*sqrt(1.0*ol_pitch);
               st->voc_offset+=ol_pitch;
            }
            st->voc_offset -= st->subframeSize;

            g=.5+2*(g-.6);
            if (g<0)
               g=0;
            if (g>1)
               g=1;
            for (i=0;i<st->subframeSize;i++)
            {
               float exci=exc[i];
               exc[i]=.8*g*exc[i]*ol_gain/SIG_SCALING + 
.6*g*st->voc_m1*ol_gain/SIG_SCALING + .5*g*innov[i] - .5*g*st->voc_m2 + 
(1-g)*innov[i];
               st->voc_m1 = exci;
               st->voc_m2=innov[i];
               st->voc_mean = .95*st->voc_mean + .05*exc[i];
               exc[i]-=st->voc_mean;
            }
         } else {
            for (i=0;i<st->subframeSize;i++)
               exc[i]=ADD32(exc[i],innov[i]);
            /*print_vec(exc, 40, "innov");*/
         }
         /* Decode second codebook (only for some modes) */
         if (SUBMODE(double_codebook))
         {
            char *tmp_stack=stack;
            VARDECL(spx_sig_t *innov2);
            ALLOC(innov2, st->subframeSize, spx_sig_t);
            for (i=0;i<st->subframeSize;i++)
               innov2[i]=0;
            SUBMODE(innovation_unquant)(innov2, SUBMODE(innovation_params), 
st->subframeSize, bits, stack);
            signal_mul(innov2, innov2, (spx_word32_t) (ener*(1/2.2)), 
st->subframeSize);
            for (i=0;i<st->subframeSize;i++)
               exc[i] = ADD32(exc[i],innov2[i]);
            stack = tmp_stack;
         }

      }

      for (i=0;i<st->subframeSize;i++)
         sp[i]=exc[i];

      /* Signal synthesis */
      if (st->lpc_enh_enabled && SUBMODE(comb_gain)>0)
         comb_filter(exc, sp, st->interp_qlpc, st->lpcSize, 
st->subframeSize,
                              pitch, pitch_gain, SUBMODE(comb_gain), 
st->comb_mem);

      if (st->lpc_enh_enabled)
      {
         /* Use enhanced LPC filter */
         filter_mem2(sp, awk2, awk1, sp, st->subframeSize, st->lpcSize,
                     st->mem_sp+st->lpcSize);
         filter_mem2(sp, awk3, st->interp_qlpc, sp, st->subframeSize, 
st->lpcSize,
                     st->mem_sp);
      } else {
         /* Use regular filter */
         for (i=0;i<st->lpcSize;i++)
            st->mem_sp[st->lpcSize+i] = 0;
         iir_mem2(sp, st->interp_qlpc, sp, st->subframeSize, st->lpcSize,
                     st->mem_sp);
      }
   }

   /*Copy output signal*/
   for (i=0;i<st->frameSize;i++)
   {
      spx_word32_t sig = PSHR32(st->frame[i],SIG_SHIFT);
      if (sig>32767)
         sig = 32767;
      if (sig<-32767)
         sig = -32767;
     out[i]=sig;
   }

   /*for (i=0;i<st->frameSize;i++)
     printf ("%d\n", (int)st->frame[i]);*/

   /* Store the LSPs for interpolation in the next frame */
   for (i=0;i<st->lpcSize;i++)
      st->old_qlsp[i] = st->qlsp[i];

   /* The next frame will not be the first (Duh!) */
   st->first = 0;
   st->count_lost=0;
   st->last_pitch = best_pitch;
#ifdef FIXED_POINT
   st->last_pitch_gain = PSHR16(pitch_average,2);
#else
   st->last_pitch_gain = .25*pitch_average;
#endif
   st->pitch_gain_buf[st->pitch_gain_buf_idx++] = st->last_pitch_gain;
   if (st->pitch_gain_buf_idx > 2) /* rollover */
      st->pitch_gain_buf_idx = 0;

   st->last_ol_gain = ol_gain;

   return 0;
}

int nb_encoder_ctl(void *state, int request, void *ptr)
{
   EncState *st;
   st=(EncState*)state;
   switch(request)
   {
   case SPEEX_GET_FRAME_SIZE:
      (*(long*)ptr) = st->frameSize;
      break;
   case SPEEX_SET_LOW_MODE:
   case SPEEX_SET_MODE:
      st->submodeSelect = st->submodeID = (*(long*)ptr);
      break;
   case SPEEX_GET_LOW_MODE:
   case SPEEX_GET_MODE:
      (*(long*)ptr) = st->submodeID;
      break;
   case SPEEX_SET_VBR:
      st->vbr_enabled = (*(long*)ptr);
      break;
   case SPEEX_GET_VBR:
      (*(long*)ptr) = st->vbr_enabled;
      break;
   case SPEEX_SET_VAD:
      st->vad_enabled = (*(long*)ptr);
      break;
   case SPEEX_GET_VAD:
      (*(long*)ptr) = st->vad_enabled;
      break;
   case SPEEX_SET_DTX:
      st->dtx_enabled = (*(long*)ptr);
      break;
   case SPEEX_GET_DTX:
      (*(long*)ptr) = st->dtx_enabled;
      break;
   case SPEEX_SET_ABR:
      st->abr_enabled = (*(long*)ptr);
      st->vbr_enabled = 1;
      {
         int i=10, rate, target;
         float vbr_qual;
         target = (*(long*)ptr);
         while (i>=0)
         {
            speex_encoder_ctl(st, SPEEX_SET_QUALITY, &i);
            speex_encoder_ctl(st, SPEEX_GET_BITRATE, &rate);
            if (rate <= target)
               break;
            i--;
         }
         vbr_qual=i;
         if (vbr_qual<0)
            vbr_qual=0;
         speex_encoder_ctl(st, SPEEX_SET_VBR_QUALITY, &vbr_qual);
         st->abr_count=0;
         st->abr_drift=0;
         st->abr_drift2=0;
      }

      break;
   case SPEEX_GET_ABR:
      (*(long*)ptr) = st->abr_enabled;
      break;
   case SPEEX_SET_VBR_QUALITY:
      st->vbr_quality = (*(float*)ptr);
      break;
   case SPEEX_GET_VBR_QUALITY:
      (*(float*)ptr) = st->vbr_quality;
      break;
   case SPEEX_SET_QUALITY:
      {
         int quality = (*(long*)ptr);
         if (quality < 0)
            quality = 0;
         if (quality > 10)
            quality = 10;
         st->submodeSelect = st->submodeID = ((const 
SpeexNBMode*)(st->mode->mode))->quality_map[quality];
      }
      break;
   case SPEEX_SET_COMPLEXITY:
      st->complexity = (*(long*)ptr);
      if (st->complexity<0)
         st->complexity=0;
      break;
   case SPEEX_GET_COMPLEXITY:
      (*(long*)ptr) = st->complexity;
      break;
   case SPEEX_SET_BITRATE:
      {
         int i=10, rate, target;
         target = (*(long*)ptr);
         while (i>=0)
         {
            speex_encoder_ctl(st, SPEEX_SET_QUALITY, &i);
            speex_encoder_ctl(st, SPEEX_GET_BITRATE, &rate);
            if (rate <= target)
               break;
            i--;
         }
      }
      break;
   case SPEEX_GET_BITRATE:
      if (st->submodes[st->submodeID])
         (*(long*)ptr) = 
st->sampling_rate*SUBMODE(bits_per_frame)/st->frameSize;
      else
         (*(long*)ptr) = 
st->sampling_rate*(NB_SUBMODE_BITS+1)/st->frameSize;
      break;
   case SPEEX_SET_SAMPLING_RATE:
      st->sampling_rate = (*(long*)ptr);
      break;
   case SPEEX_GET_SAMPLING_RATE:
      (*(long*)ptr)=st->sampling_rate;
      break;
   case SPEEX_RESET_STATE:
      {
         int i;
         st->bounded_pitch = 1;
         st->first = 1;
         for (i=0;i<st->lpcSize;i++)
            st->lsp[i]=(M_PI*((float)(i+1)))/(st->lpcSize+1);
         for (i=0;i<st->lpcSize;i++)
            
st->mem_sw[i]=st->mem_sw_whole[i]=st->mem_sp[i]=st->mem_exc[i]=0;
         for (i=0;i<st->frameSize+st->max_pitch+1;i++)
            st->excBuf[i]=st->swBuf[i]=0;
         for (i=0;i<st->windowSize;i++)
            st->inBuf[i]=0;
      }
      break;
   case SPEEX_SET_SUBMODE_ENCODING:
      st->encode_submode = (*(long*)ptr);
      break;
   case SPEEX_GET_SUBMODE_ENCODING:
      (*(long*)ptr) = st->encode_submode;
      break;
   case SPEEX_GET_LOOKAHEAD:
      (*(long*)ptr)=(st->windowSize-st->frameSize);
      break;
   case SPEEX_SET_PLC_TUNING:
      st->plc_tuning = (*(long*)ptr);
      if (st->plc_tuning>100)
         st->plc_tuning=100;
      break;
   case SPEEX_GET_PLC_TUNING:
      (*(long*)ptr)=(st->plc_tuning);
      break;
   case SPEEX_GET_PI_GAIN:
      {
         int i;
         spx_word32_t *g = (spx_word32_t*)ptr;
         for (i=0;i<st->nbSubframes;i++)
            g[i]=st->pi_gain[i];
      }
      break;
   case SPEEX_GET_EXC:
      {
         int i;
         spx_sig_t *e = (spx_sig_t*)ptr;
         for (i=0;i<st->frameSize;i++)
            e[i]=st->exc[i];
      }
      break;
   case SPEEX_GET_INNOV:
      {
         int i;
         spx_sig_t *e = (spx_sig_t*)ptr;
         for (i=0;i<st->frameSize;i++)
            e[i]=st->innov[i];
      }
      break;
   case SPEEX_GET_RELATIVE_QUALITY:
      (*(float*)ptr)=st->relative_quality;
      break;
   default:
      speex_warning_int("Unknown nb_ctl request: ", request);
      return -1;
   }
   return 0;
}

int nb_decoder_ctl(void *state, int request, void *ptr)
{
   DecState *st;
   st=(DecState*)state;
   switch(request)
   {
   case SPEEX_SET_LOW_MODE:
   case SPEEX_SET_MODE:
      st->submodeID = (*(long*)ptr);
      break;
   case SPEEX_GET_LOW_MODE:
   case SPEEX_GET_MODE:
      (*(long*)ptr) = st->submodeID;
      break;
   case SPEEX_SET_ENH:
      st->lpc_enh_enabled = *((long*)ptr);
      break;
   case SPEEX_GET_ENH:
      *((long*)ptr) = st->lpc_enh_enabled;
      break;
   case SPEEX_GET_FRAME_SIZE:
      (*(long*)ptr) = st->frameSize;
      break;
   case SPEEX_GET_BITRATE:
      if (st->submodes[st->submodeID])
         (*(long*)ptr) = 
st->sampling_rate*SUBMODE(bits_per_frame)/st->frameSize;
      else
         (*(long*)ptr) = 
st->sampling_rate*(NB_SUBMODE_BITS+1)/st->frameSize;
      break;
   case SPEEX_SET_SAMPLING_RATE:
      st->sampling_rate = (*(long*)ptr);
      break;
   case SPEEX_GET_SAMPLING_RATE:
      (*(long*)ptr)=st->sampling_rate;
      break;
   case SPEEX_SET_HANDLER:
      {
         SpeexCallback *c = (SpeexCallback*)ptr;
         st->speex_callbacks[c->callback_id].func=c->func;
         st->speex_callbacks[c->callback_id].data=c->data;
         st->speex_callbacks[c->callback_id].callback_id=c->callback_id;
      }
      break;
   case SPEEX_SET_USER_HANDLER:
      {
         SpeexCallback *c = (SpeexCallback*)ptr;
         st->user_callback.func=c->func;
         st->user_callback.data=c->data;
         st->user_callback.callback_id=c->callback_id;
      }
      break;
   case SPEEX_RESET_STATE:
      {
         int i;
         for (i=0;i<2*st->lpcSize;i++)
            st->mem_sp[i]=0;
         for (i=0;i<st->frameSize + st->max_pitch + 1;i++)
            st->excBuf[i]=0;
         for (i=0;i<st->frameSize;i++)
            st->inBuf[i] = 0;
      }
      break;
   case SPEEX_SET_SUBMODE_ENCODING:
      st->encode_submode = (*(long*)ptr);
      break;
   case SPEEX_GET_SUBMODE_ENCODING:
      (*(long*)ptr) = st->encode_submode;
      break;
   case SPEEX_GET_PI_GAIN:
      {
         int i;
         spx_word32_t *g = (spx_word32_t*)ptr;
         for (i=0;i<st->nbSubframes;i++)
            g[i]=st->pi_gain[i];
      }
      break;
   case SPEEX_GET_EXC:
      {
         int i;
         spx_sig_t *e = (spx_sig_t*)ptr;
         for (i=0;i<st->frameSize;i++)
            e[i]=st->exc[i];
      }
      break;
   case SPEEX_GET_INNOV:
      {
         int i;
         spx_sig_t *e = (spx_sig_t*)ptr;
         for (i=0;i<st->frameSize;i++)
            e[i]=st->innov[i];
      }
      break;
   case SPEEX_GET_DTX_STATUS:
      *((long*)ptr) = st->dtx_enabled;
      break;
   default:
      speex_warning_int("Unknown nb_ctl request: ", request);
      return -1;
   }
   return 0;
}

-------------- next part --------------
/* speex_types.h taken from libogg */
/********************************************************************
*                                                                  *
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE.   *
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
*                                                                  *
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2002             *
* by the Xiph.Org Foundation http://www.xiph.org/                  *
*                                                                  *
********************************************************************

function: #ifdef jail to whip a few platforms into the UNIX ideal.
last mod: $Id: os_types.h 7524 2004-08-11 04:20:36Z conrad $

********************************************************************/
#ifndef _SPEEX_TYPES_H
#define _SPEEX_TYPES_H

#if defined(_WIN32)

#  if defined(__CYGWIN__)
#    include <_G_config.h>
     typedef _G_int64_t spx_int64_t;
     typedef _G_int32_t spx_int32_t;
     typedef _G_uint32_t spx_uint32_t;
     typedef _G_int16_t spx_int16_t;
     typedef _G_uint16_t spx_uint16_t;
#  elif defined(__MINGW32__)
     typedef short spx_int16_t;
     typedef unsigned short spx_uint16_t;
     typedef int spx_int32_t;
     typedef unsigned int spx_uint32_t;
     typedef long long spx_int64_t;
     typedef unsigned long long spx_uint64_t;
#  elif defined(__MWERKS__)
     typedef long long spx_int64_t;
     typedef int spx_int32_t;
     typedef unsigned int spx_uint32_t;
     typedef short spx_int16_t;
     typedef unsigned short spx_uint16_t;
#  else
     /* MSVC/Borland */
     typedef __int64 spx_int64_t;
     typedef __int32 spx_int32_t;
     typedef unsigned __int32 spx_uint32_t;
     typedef __int16 spx_int16_t;
     typedef unsigned __int16 spx_uint16_t;
#  endif

#elif defined(__MACOS__)

#  include <sys/types.h>
   typedef SInt16 spx_int16_t;
   typedef UInt16 spx_uint16_t;
   typedef SInt32 spx_int32_t;
   typedef UInt32 spx_uint32_t;
   typedef SInt64 spx_int64_t;

#elif defined(__MACOSX__) /* MacOS X Framework build */

#  include <sys/types.h>
   typedef int16_t spx_int16_t;
   typedef u_int16_t spx_uint16_t;
   typedef int32_t spx_int32_t;
   typedef u_int32_t spx_uint32_t;
   typedef int64_t spx_int64_t;

#elif defined(__BEOS__)

   /* Be */
#  include <inttypes.h>
   typedef int16_t spx_int16_t;
   typedef u_int16_t spx_uint16_t;
   typedef int32_t spx_int32_t;
   typedef u_int32_t spx_uint32_t;
   typedef int64_t spx_int64_t;

#elif defined (__EMX__)

   /* OS/2 GCC */
   typedef short spx_int16_t;
   typedef unsigned short spx_uint16_t;
   typedef int spx_int32_t;
   typedef unsigned int spx_uint32_t;
   typedef long long spx_int64_t;

#elif defined (DJGPP)

   /* DJGPP */
   typedef short spx_int16_t;
   typedef int spx_int32_t;
   typedef unsigned int spx_uint32_t;
   typedef long long spx_int64_t;

#elif defined(R5900)

   /* PS2 EE */
   typedef long spx_int64_t;
   typedef int spx_int32_t;
   typedef unsigned spx_uint32_t;
   typedef short spx_int16_t;

#elif defined(__SYMBIAN32__)

   /* Symbian GCC */
   typedef signed short spx_int16_t;
   typedef unsigned short spx_uint16_t;
   typedef signed int spx_int32_t;
   typedef unsigned int spx_uint32_t;
   typedef long long int spx_int64_t;

#elif defined(__C55X__)

   /* Symbian GCC */
   typedef signed short spx_int16_t;
   typedef unsigned short spx_uint16_t;
   typedef signed long spx_int32_t;			// We use long as int is 16-bits on 
this processor
   typedef unsigned long spx_uint32_t;
   typedef long long int spx_int64_t;		// Note: only 40-bits on this 
platform!!!

#else

#include <speex/speex_config_types.h>

#endif

#endif  /* _SPEEX_TYPES_H */



More information about the Speex-dev mailing list