Adding a floating point interface to encode and decode

This commit is contained in:
Gregory Maxwell 2008-08-11 23:50:07 -04:00 committed by Jean-Marc Valin
parent 8e30e75fcc
commit 5f2a74b38b
3 changed files with 119 additions and 23 deletions

View file

@ -97,6 +97,8 @@ typedef celt_word32_t celt_mask_t;
#define Q15_ONE ((celt_word16_t)32767) #define Q15_ONE ((celt_word16_t)32767)
#define Q15_ONE_1 (1.f/32768.f) #define Q15_ONE_1 (1.f/32768.f)
#define SCALEIN(a) (a)
#define SCALEOUT(a) (a)
#ifdef FIXED_DEBUG #ifdef FIXED_DEBUG
#include "fixed_debug.h" #include "fixed_debug.h"
@ -213,6 +215,8 @@ typedef float celt_mask_t;
#define DIV32(a,b) (((celt_word32_t)(a))/(celt_word32_t)(b)) #define DIV32(a,b) (((celt_word32_t)(a))/(celt_word32_t)(b))
#define PDIV32(a,b) (((celt_word32_t)(a))/(celt_word32_t)(b)) #define PDIV32(a,b) (((celt_word32_t)(a))/(celt_word32_t)(b))
#define SCALEIN(a) ((a)*32768.)
#define SCALEOUT(a) ((a)*(1/32768.))
#endif /* !FIXED_POINT */ #endif /* !FIXED_POINT */

View file

@ -114,8 +114,8 @@ CELTEncoder *celt_encoder_create(const CELTMode *mode)
st->oldBandE = (celt_word16_t*)celt_alloc(C*mode->nbEBands*sizeof(celt_word16_t)); st->oldBandE = (celt_word16_t*)celt_alloc(C*mode->nbEBands*sizeof(celt_word16_t));
st->preemph_memE = (celt_word16_t*)celt_alloc(C*sizeof(celt_word16_t));; st->preemph_memE = (celt_word16_t*)celt_alloc(C*sizeof(celt_word16_t));
st->preemph_memD = (celt_sig_t*)celt_alloc(C*sizeof(celt_sig_t));; st->preemph_memD = (celt_sig_t*)celt_alloc(C*sizeof(celt_sig_t));
#ifdef EXP_PSY #ifdef EXP_PSY
st->psy_mem = celt_alloc(MAX_PERIOD*sizeof(celt_word16_t)); st->psy_mem = celt_alloc(MAX_PERIOD*sizeof(celt_word16_t));
@ -153,15 +153,23 @@ void celt_encoder_destroy(CELTEncoder *st)
celt_free(st); celt_free(st);
} }
static inline celt_int16_t SIG2INT16(celt_sig_t x) static inline celt_int16_t FLOAT2INT16(float x)
{ {
x = x*32768.;
x = MAX32(x, -32768);
x = MIN32(x, 32767);
return (celt_int16_t)floor(.5+x);
}
static inline celt_word16_t SIG2WORD16(celt_sig_t x)
{
#ifdef FIXED_POINT
x = PSHR32(x, SIG_SHIFT); x = PSHR32(x, SIG_SHIFT);
x = MAX32(x, -32768); x = MAX32(x, -32768);
x = MIN32(x, 32767); x = MIN32(x, 32767);
#ifdef FIXED_POINT
return EXTRACT16(x); return EXTRACT16(x);
#else #else
return (celt_int16_t)floor(.5+x); return (celt_word16_t)x;
#endif #endif
} }
@ -356,8 +364,13 @@ static void compute_inv_mdcts(const CELTMode *mode, int shortBlocks, celt_sig_t
} }
} }
#ifdef FIXED_POINT
int celt_encode(CELTEncoder * restrict st, celt_int16_t * restrict pcm, unsigned char *compressed, int nbCompressedBytes) int celt_encode(CELTEncoder * restrict st, celt_int16_t * restrict pcm, unsigned char *compressed, int nbCompressedBytes)
{ {
#else
int celt_encode_float(CELTEncoder * restrict st, celt_sig_t * restrict pcm, unsigned char *compressed, int nbCompressedBytes)
{
#endif
int i, c, N, N4; int i, c, N, N4;
int has_pitch; int has_pitch;
int pitch_index; int pitch_index;
@ -393,14 +406,14 @@ int celt_encode(CELTEncoder * restrict st, celt_int16_t * restrict pcm, unsigned
CELT_COPY(in, st->in_mem, C*st->overlap); CELT_COPY(in, st->in_mem, C*st->overlap);
for (c=0;c<C;c++) for (c=0;c<C;c++)
{ {
const celt_int16_t * restrict pcmp = pcm+c; const celt_word16_t * restrict pcmp = pcm+c;
celt_sig_t * restrict inp = in+C*st->overlap+c; celt_sig_t * restrict inp = in+C*st->overlap+c;
for (i=0;i<N;i++) for (i=0;i<N;i++)
{ {
/* Apply pre-emphasis */ /* Apply pre-emphasis */
celt_sig_t tmp = SHL32(EXTEND32(*pcmp), SIG_SHIFT); celt_sig_t tmp = SCALEIN(SHL32(EXTEND32(*pcmp), SIG_SHIFT));
*inp = SUB32(tmp, SHR32(MULT16_16(preemph,st->preemph_memE[c]),1)); *inp = SUB32(tmp, SHR32(MULT16_16(preemph,st->preemph_memE[c]),1));
st->preemph_memE[c] = *pcmp; st->preemph_memE[c] = SCALEIN(*pcmp);
inp += C; inp += C;
pcmp += C; pcmp += C;
} }
@ -576,15 +589,12 @@ int celt_encode(CELTEncoder * restrict st, celt_int16_t * restrict pcm, unsigned
for (c=0;c<C;c++) for (c=0;c<C;c++)
{ {
int j; int j;
celt_sig_t * restrict outp=st->out_mem+C*(MAX_PERIOD-N)+c;
celt_int16_t * restrict pcmp = pcm+c;
for (j=0;j<N;j++) for (j=0;j<N;j++)
{ {
celt_sig_t tmp = ADD32(*outp, MULT16_32_Q15(preemph,st->preemph_memD[c])); celt_sig_t tmp = ADD32(st->out_mem[C*(MAX_PERIOD-N)+C*j+c],
MULT16_32_Q15(preemph,st->preemph_memD[c]));
st->preemph_memD[c] = tmp; st->preemph_memD[c] = tmp;
*pcmp = SIG2INT16(tmp); pcm[C*j+c] = SCALEOUT(SIG2WORD16(tmp));
pcmp += C;
outp += C;
} }
} }
#endif #endif
@ -625,6 +635,49 @@ int celt_encode(CELTEncoder * restrict st, celt_int16_t * restrict pcm, unsigned
return nbCompressedBytes; return nbCompressedBytes;
} }
#ifdef FIXED_POINT
#ifndef DISABLE_FLOAT_API
int celt_encode_float(CELTEncoder * restrict st, float * restrict pcm, unsigned char *compressed, int nbCompressedBytes)
{
int j, ret;
const int C = CHANNELS(st->mode);
const int N = st->block_size;
ALLOC(in, C*N, celt_int16_t);
for (j=0;j<C*N;j++)
in[j] = FLOAT2INT16(pcm[j]);
ret=celt_encode(st,in,compressed,nbCompressedBytes);
#ifndef SHORTCUTS
/*Converts backwards for inplace operation*/
for (j=0;j=C*N;j++)
pcm[j]=in[j]*(1/32768.);
#endif
return ret;
}
#endif /*DISABLE_FLOAT_API*/
#else
int celt_encode(CELTEncoder * restrict st, celt_int16_t * restrict pcm, unsigned char *compressed, int nbCompressedBytes)
{
int j, ret;
VARDECL(celt_sig_t, in);
const int C = CHANNELS(st->mode);
const int N = st->block_size;
ALLOC(in, C*N, celt_sig_t);
for (j=0;j<C*N;j++) {
in[j] = SCALEOUT(pcm[j]);
}
ret = celt_encode_float(st,in,compressed,nbCompressedBytes);
#ifndef SHORTCUTS
for (j=0;j<C*N;j++)
pcm[j] = FLOAT2INT16(in[j]);
#endif
return ret;
}
#endif
/****************************************************************************/ /****************************************************************************/
/* */ /* */
@ -675,7 +728,7 @@ CELTDecoder *celt_decoder_create(const CELTMode *mode)
st->oldBandE = (celt_word16_t*)celt_alloc(C*mode->nbEBands*sizeof(celt_word16_t)); st->oldBandE = (celt_word16_t*)celt_alloc(C*mode->nbEBands*sizeof(celt_word16_t));
st->preemph_memD = (celt_sig_t*)celt_alloc(C*sizeof(celt_sig_t));; st->preemph_memD = (celt_sig_t*)celt_alloc(C*sizeof(celt_sig_t));
st->last_pitch_index = 0; st->last_pitch_index = 0;
return st; return st;
@ -703,7 +756,7 @@ void celt_decoder_destroy(CELTDecoder *st)
/** Handles lost packets by just copying past data with the same offset as the last /** Handles lost packets by just copying past data with the same offset as the last
pitch period */ pitch period */
static void celt_decode_lost(CELTDecoder * restrict st, short * restrict pcm) static void celt_decode_lost(CELTDecoder * restrict st, celt_word16_t * restrict pcm)
{ {
int c, N; int c, N;
int pitch_index; int pitch_index;
@ -747,14 +800,19 @@ static void celt_decode_lost(CELTDecoder * restrict st, short * restrict pcm)
celt_sig_t tmp = ADD32(st->out_mem[C*(MAX_PERIOD-N)+C*j+c], celt_sig_t tmp = ADD32(st->out_mem[C*(MAX_PERIOD-N)+C*j+c],
MULT16_32_Q15(preemph,st->preemph_memD[c])); MULT16_32_Q15(preemph,st->preemph_memD[c]));
st->preemph_memD[c] = tmp; st->preemph_memD[c] = tmp;
pcm[C*j+c] = SIG2INT16(tmp); pcm[C*j+c] = SCALEOUT(SIG2WORD16(tmp));
} }
} }
RESTORE_STACK; RESTORE_STACK;
} }
#ifdef FIXED_POINT
int celt_decode(CELTDecoder * restrict st, unsigned char *data, int len, celt_int16_t * restrict pcm) int celt_decode(CELTDecoder * restrict st, unsigned char *data, int len, celt_int16_t * restrict pcm)
{ {
#else
int celt_decode_float(CELTDecoder * restrict st, unsigned char *data, int len, celt_sig_t * restrict pcm)
{
#endif
int i, c, N, N4; int i, c, N, N4;
int has_pitch; int has_pitch;
int pitch_index; int pitch_index;
@ -886,15 +944,12 @@ int celt_decode(CELTDecoder * restrict st, unsigned char *data, int len, celt_in
for (c=0;c<C;c++) for (c=0;c<C;c++)
{ {
int j; int j;
const celt_sig_t * restrict outp=st->out_mem+C*(MAX_PERIOD-N)+c;
celt_int16_t * restrict pcmp = pcm+c;
for (j=0;j<N;j++) for (j=0;j<N;j++)
{ {
celt_sig_t tmp = ADD32(*outp, MULT16_32_Q15(preemph,st->preemph_memD[c])); celt_sig_t tmp = ADD32(st->out_mem[C*(MAX_PERIOD-N)+C*j+c],
MULT16_32_Q15(preemph,st->preemph_memD[c]));
st->preemph_memD[c] = tmp; st->preemph_memD[c] = tmp;
*pcmp = SIG2INT16(tmp); pcm[C*j+c] = SCALEOUT(SIG2WORD16(tmp));
pcmp += C;
outp += C;
} }
} }
@ -917,3 +972,38 @@ int celt_decode(CELTDecoder * restrict st, unsigned char *data, int len, celt_in
/*printf ("\n");*/ /*printf ("\n");*/
} }
#ifdef FIXED_POINT
#ifndef DISABLE_FLOAT_API
int celt_decode_float(CELTDecoder * restrict st, unsigned char *data, int len, float * restrict pcm)
{
int j, ret;
const int C = CHANNELS(st->mode);
const int N = st->block_size;
ALLOC(out, C*N, celt_int16_t);
ret=celt_decode(st, data, len, out);
for (j=0;j<C*N;j++)
pcm[j]=out[j]*(1/32768.);
return ret;
}
#endif /*DISABLE_FLOAT_API*/
#else
int celt_decode(CELTDecoder * restrict st, unsigned char *data, int len, celt_int16_t * restrict pcm)
{
int j, ret;
VARDECL(celt_sig_t, out);
const int C = CHANNELS(st->mode);
const int N = st->block_size;
ALLOC(out, C*N, celt_sig_t);
ret=celt_decode_float(st, data, len, out);
for (j=0;j<C*N;j++)
pcm[j] = FLOAT2INT16 (out[j]);
return ret;
}
#endif

View file

@ -149,6 +149,7 @@ EXPORT void celt_encoder_destroy(CELTEncoder *st);
has occured (see error codes). It is IMPORTANT that the length returned has occured (see error codes). It is IMPORTANT that the length returned
be somehow transmitted to the decoder. Otherwise, no decoding is possible. be somehow transmitted to the decoder. Otherwise, no decoding is possible.
*/ */
EXPORT int celt_encode_float(CELTEncoder *st, float *pcm, unsigned char *compressed, int nbCompressedBytes);
EXPORT int celt_encode(CELTEncoder *st, celt_int16_t *pcm, unsigned char *compressed, int nbCompressedBytes); EXPORT int celt_encode(CELTEncoder *st, celt_int16_t *pcm, unsigned char *compressed, int nbCompressedBytes);
/* Decoder stuff */ /* Decoder stuff */
@ -176,6 +177,7 @@ EXPORT void celt_decoder_destroy(CELTDecoder *st);
returned here. returned here.
@return Error code. @return Error code.
*/ */
EXPORT int celt_decode_float(CELTDecoder *st, unsigned char *data, int len, float *pcm);
EXPORT int celt_decode(CELTDecoder *st, unsigned char *data, int len, celt_int16_t *pcm); EXPORT int celt_decode(CELTDecoder *st, unsigned char *data, int len, celt_int16_t *pcm);
/* @} */ /* @} */