ref: 222494f3ea66da5abb218508abf53dc40d13b99e
parent: 8a23fe977f1f273c84865a9bb5eef012fcdb7d3f
author: Jean-Marc Valin <[email protected]>
date: Wed Aug 17 11:53:37 EDT 2011
Adds a floating-point API to Opus The high-level Opus encoder and decoder can now be compiled as either fixed or float. Also, we now use the stack_alloc.h macros in the top-level Opus code.
--- a/libcelt/celt.c
+++ b/libcelt/celt.c
@@ -283,14 +283,6 @@
celt_free(st);
}
-static inline opus_int16 FLOAT2INT16(float x)
-{
- x = x*CELT_SIG_SCALE;
- x = MAX32(x, -32768);
- x = MIN32(x, 32767);
- return (opus_int16)float2int(x);
-}
-
static inline opus_val16 SIG2WORD16(celt_sig x)
{
#ifdef FIXED_POINT
@@ -891,15 +883,9 @@
> MULT16_32_Q15(m->eBands[13]<<(LM+1), sumLR);
}
-#ifdef FIXED_POINT
CELT_STATIC
-int celt_encode_with_ec(CELTEncoder * restrict st, const opus_int16 * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes, ec_enc *enc)
+int celt_encode_with_ec(CELTEncoder * restrict st, const opus_val16 * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes, ec_enc *enc)
{
-#else
-CELT_STATIC
-int celt_encode_with_ec_float(CELTEncoder * restrict st, const celt_sig * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes, ec_enc *enc)
-{
-#endif
int i, c, N;
opus_int32 bits;
ec_enc _enc;
@@ -1675,10 +1661,16 @@
return nbCompressedBytes;
}
+
+
#ifdef FIXED_POINT
+int celt_encode(CELTEncoder * restrict st, const opus_int16 * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes)
+{
+ return celt_encode_with_ec(st, pcm, frame_size, compressed, nbCompressedBytes, NULL);
+}
+
#ifndef DISABLE_FLOAT_API
-CELT_STATIC
-int celt_encode_with_ec_float(CELTEncoder * restrict st, const float * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes, ec_enc *enc)
+int celt_encode_float(CELTEncoder * restrict st, const float * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes)
{
int j, ret, C, N;
VARDECL(opus_int16, in);
@@ -1694,7 +1686,7 @@
for (j=0;j<C*N;j++)
in[j] = FLOAT2INT16(pcm[j]);
- ret=celt_encode_with_ec(st,in,frame_size,compressed,nbCompressedBytes, enc);
+ ret=celt_encode_with_ec(st,in,frame_size,compressed,nbCompressedBytes, NULL);
#ifdef RESYNTH
for (j=0;j<C*N;j++)
((float*)pcm)[j]=in[j]*(1.f/32768.f);
@@ -1701,12 +1693,11 @@
#endif
RESTORE_STACK;
return ret;
-
}
-#endif /*DISABLE_FLOAT_API*/
+#endif /* DISABLE_FLOAT_API */
#else
-CELT_STATIC
-int celt_encode_with_ec(CELTEncoder * restrict st, const opus_int16 * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes, ec_enc *enc)
+
+int celt_encode(CELTEncoder * restrict st, const opus_int16 * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes)
{
int j, ret, C, N;
VARDECL(celt_sig, in);
@@ -1722,7 +1713,7 @@
in[j] = SCALEOUT(pcm[j]);
}
- ret = celt_encode_with_ec_float(st,in,frame_size,compressed,nbCompressedBytes, enc);
+ ret = celt_encode_with_ec(st,in,frame_size,compressed,nbCompressedBytes, NULL);
#ifdef RESYNTH
for (j=0;j<C*N;j++)
((opus_int16*)pcm)[j] = FLOAT2INT16(in[j]);
@@ -1730,20 +1721,14 @@
RESTORE_STACK;
return ret;
}
-#endif
-int celt_encode(CELTEncoder * restrict st, const opus_int16 * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes)
+int celt_encode_float(CELTEncoder * restrict st, const float * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes)
{
return celt_encode_with_ec(st, pcm, frame_size, compressed, nbCompressedBytes, NULL);
}
-#ifndef DISABLE_FLOAT_API
-int celt_encode_float(CELTEncoder * restrict st, const float * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes)
-{
- return celt_encode_with_ec_float(st, pcm, frame_size, compressed, nbCompressedBytes, NULL);
-}
-#endif /* DISABLE_FLOAT_API */
+#endif
int celt_encoder_ctl(CELTEncoder * restrict st, int request, ...)
{
va_list ap;
@@ -2252,15 +2237,9 @@
RESTORE_STACK;
}
-#ifdef FIXED_POINT
CELT_STATIC
-int celt_decode_with_ec(CELTDecoder * restrict st, const unsigned char *data, int len, opus_int16 * restrict pcm, int frame_size, ec_dec *dec)
+int celt_decode_with_ec(CELTDecoder * restrict st, const unsigned char *data, int len, opus_val16 * restrict pcm, int frame_size, ec_dec *dec)
{
-#else
-CELT_STATIC
-int celt_decode_with_ec_float(CELTDecoder * restrict st, const unsigned char *data, int len, celt_sig * restrict pcm, int frame_size, ec_dec *dec)
-{
-#endif
int c, i, N;
int spread_decision;
opus_int32 bits;
@@ -2627,10 +2606,16 @@
return frame_size/st->downsample;
}
+
+
#ifdef FIXED_POINT
+int celt_decode(CELTDecoder * restrict st, const unsigned char *data, int len, opus_int16 * restrict pcm, int frame_size)
+{
+ return celt_decode_with_ec(st, data, len, pcm, frame_size, NULL);
+}
+
#ifndef DISABLE_FLOAT_API
-CELT_STATIC
-int celt_decode_with_ec_float(CELTDecoder * restrict st, const unsigned char *data, int len, float * restrict pcm, int frame_size, ec_dec *dec)
+int celt_decode_float(CELTDecoder * restrict st, const unsigned char *data, int len, float * restrict pcm, int frame_size)
{
int j, ret, C, N;
VARDECL(opus_int16, out);
@@ -2643,7 +2628,7 @@
N = frame_size;
ALLOC(out, C*N, opus_int16);
- ret=celt_decode_with_ec(st, data, len, out, frame_size, dec);
+ ret=celt_decode_with_ec(st, data, len, out, frame_size, NULL);
if (ret>0)
for (j=0;j<C*ret;j++)
pcm[j]=out[j]*(1.f/32768.f);
@@ -2651,11 +2636,17 @@
RESTORE_STACK;
return ret;
}
-#endif /*DISABLE_FLOAT_API*/
+#endif /* DISABLE_FLOAT_API */
+
#else
-CELT_STATIC
-int celt_decode_with_ec(CELTDecoder * restrict st, const unsigned char *data, int len, opus_int16 * restrict pcm, int frame_size, ec_dec *dec)
+
+int celt_decode_float(CELTDecoder * restrict st, const unsigned char *data, int len, float * restrict pcm, int frame_size)
{
+ return celt_decode_with_ec(st, data, len, pcm, frame_size, NULL);
+}
+
+int celt_decode(CELTDecoder * restrict st, const unsigned char *data, int len, opus_int16 * restrict pcm, int frame_size)
+{
int j, ret, C, N;
VARDECL(celt_sig, out);
ALLOC_STACK;
@@ -2667,7 +2658,7 @@
N = frame_size;
ALLOC(out, C*N, celt_sig);
- ret=celt_decode_with_ec_float(st, data, len, out, frame_size, dec);
+ ret=celt_decode_with_ec(st, data, len, out, frame_size, NULL);
if (ret>0)
for (j=0;j<C*ret;j++)
@@ -2676,19 +2667,9 @@
RESTORE_STACK;
return ret;
}
+
#endif
-int celt_decode(CELTDecoder * restrict st, const unsigned char *data, int len, opus_int16 * restrict pcm, int frame_size)
-{
- return celt_decode_with_ec(st, data, len, pcm, frame_size, NULL);
-}
-
-#ifndef DISABLE_FLOAT_API
-int celt_decode_float(CELTDecoder * restrict st, const unsigned char *data, int len, float * restrict pcm, int frame_size)
-{
- return celt_decode_with_ec_float(st, data, len, pcm, frame_size, NULL);
-}
-#endif /* DISABLE_FLOAT_API */
int celt_decoder_ctl(CELTDecoder * restrict st, int request, ...)
{
--- a/libcelt/float_cast.h
+++ b/libcelt/float_cast.h
@@ -123,4 +123,12 @@
#define float2int(flt) ((int)(floor(.5+flt)))
#endif
+static inline opus_int16 FLOAT2INT16(float x)
+{
+ x = x*CELT_SIG_SCALE;
+ x = MAX32(x, -32768);
+ x = MIN32(x, 32767);
+ return (opus_int16)float2int(x);
+}
+
#endif /* FLOAT_CAST_H */
--- a/libcelt/modes.h
+++ b/libcelt/modes.h
@@ -102,10 +102,8 @@
#define CELT_GET_MODE(x) CELT_GET_MODE_REQUEST, _celt_check_mode_ptr_ptr(x)
/* Prototypes for _ec versions of the encoder/decoder calls (not public) */
-int celt_encode_with_ec(CELTEncoder * restrict st, const opus_int16 * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes, ec_enc *enc);
-int celt_encode_with_ec_float(CELTEncoder * restrict st, const float * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes, ec_enc *enc);
-int celt_decode_with_ec(CELTDecoder * restrict st, const unsigned char *data, int len, opus_int16 * restrict pcm, int frame_size, ec_dec *dec);
-int celt_decode_with_ec_float(CELTDecoder * restrict st, const unsigned char *data, int len, float * restrict pcm, int frame_size, ec_dec *dec);
+int celt_encode_with_ec(CELTEncoder * restrict st, const opus_val16 * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes, ec_enc *enc);
+int celt_decode_with_ec(CELTDecoder * restrict st, const unsigned char *data, int len, opus_val16 * restrict pcm, int frame_size, ec_dec *dec);
#endif /* OPUS_BUILD */
#endif
--- a/src/opus_decoder.c
+++ b/src/opus_decoder.c
@@ -38,7 +38,15 @@
#include "entdec.h"
#include "modes.h"
#include "silk_API.h"
+#include "stack_alloc.h"
+#include "float_cast.h"
+#ifdef FIXED_POINT
+#define celt_decode_native celt_decode
+#else
+#define celt_decode_native celt_decode_float
+#endif
+
/* Make sure everything's aligned to 4 bytes (this may need to be increased
on really weird architectures) */
static inline int align(int i)
@@ -109,7 +117,7 @@
return opus_decoder_init((OpusDecoder*)raw_state, Fs, channels);
}
-static void smooth_fade(const opus_int16 *in1, const opus_int16 *in2, opus_int16 *out,
+static void smooth_fade(const opus_val16 *in1, const opus_val16 *in2, opus_val16 *out,
int overlap, int channels, const opus_val16 *window, int Fs)
{
int i, c;
@@ -142,7 +150,7 @@
}
static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
- int len, opus_int16 *pcm, int frame_size, int decode_fec)
+ int len, opus_val16 *pcm, int frame_size, int decode_fec)
{
void *silk_dec;
CELTDecoder *celt_dec;
@@ -150,8 +158,8 @@
ec_dec dec;
silk_DecControlStruct DecControl;
opus_int32 silk_frame_size;
- opus_int16 pcm_celt[960*2];
- opus_int16 pcm_transition[480*2];
+ VARDECL(opus_int16, pcm_silk);
+ VARDECL(opus_val16, pcm_transition);
int audiosize;
int mode;
@@ -160,10 +168,10 @@
int redundancy=0;
int redundancy_bytes = 0;
int celt_to_silk=0;
- opus_int16 redundant_audio[240*2];
int c;
int F2_5, F5, F10, F20;
const opus_val16 *window;
+ ALLOC_STACK;
silk_dec = (char*)st+st->silk_dec_offset;
celt_dec = (CELTDecoder*)((char*)st+st->celt_dec_offset);
@@ -176,6 +184,7 @@
{
data = NULL;
/* In that case, don't conceal more than what the ToC says */
+ /* FIXME: What if st->frame_size has never been set? */
frame_size = IMIN(frame_size, st->frame_size);
}
if (data != NULL)
@@ -190,6 +199,7 @@
/* If we haven't got any packet yet, all we can do is return zeros */
for (i=0;i<audiosize;i++)
pcm[i] = 0;
+ RESTORE_STACK;
return audiosize;
} else {
mode = st->prev_mode;
@@ -196,6 +206,8 @@
}
}
+ ALLOC(pcm_transition, F5*st->channels, opus_val16);
+
if (data!=NULL && !st->prev_redundancy && mode != st->prev_mode && st->prev_mode > 0
&& !(mode == MODE_SILK_ONLY && st->prev_mode == MODE_HYBRID)
&& !(mode == MODE_HYBRID && st->prev_mode == MODE_SILK_ONLY))
@@ -202,21 +214,25 @@
{
transition = 1;
if (mode == MODE_CELT_ONLY)
- opus_decode_frame(st, NULL, 0, pcm_transition, IMIN(F10, audiosize), 0);
+ opus_decode_frame(st, NULL, 0, pcm_transition, IMIN(F5, audiosize), 0);
}
if (audiosize > frame_size)
{
fprintf(stderr, "PCM buffer too small: %d vs %d (mode = %d)\n", audiosize, frame_size, mode);
+ RESTORE_STACK;
return OPUS_BAD_ARG;
} else {
frame_size = audiosize;
}
+ ALLOC(pcm_silk, frame_size*st->channels, opus_int16);
+ ALLOC(redundant_audio, F5*st->channels, opus_val16);
+
/* SILK processing */
if (mode != MODE_CELT_ONLY)
{
int lost_flag, decoded_samples;
- opus_int16 *pcm_ptr = pcm;
+ opus_int16 *pcm_ptr = pcm_silk;
if (st->prev_mode==MODE_CELT_ONLY)
silk_InitDecoder( silk_dec );
@@ -254,15 +270,14 @@
silk_frame_size = frame_size;
for (i=0;i<frame_size*st->channels;i++)
pcm_ptr[i] = 0;
- } else
- return OPUS_CORRUPTED_DATA;
+ } else {
+ RESTORE_STACK;
+ return OPUS_CORRUPTED_DATA;
+ }
}
pcm_ptr += silk_frame_size * st->channels;
decoded_samples += silk_frame_size;
} while( decoded_samples < frame_size );
- } else {
- for (i=0;i<frame_size*st->channels;i++)
- pcm[i] = 0;
}
start_band = 0;
@@ -285,8 +300,10 @@
}
}
len -= redundancy_bytes;
- if (len<0)
- return OPUS_CORRUPTED_DATA;
+ if (len<0) {
+ RESTORE_STACK;
+ return OPUS_CORRUPTED_DATA;
+ }
/* Shrink decoder because of raw bits */
dec.storage -= redundancy_bytes;
}
@@ -321,13 +338,13 @@
transition = 0;
if (transition && mode != MODE_CELT_ONLY)
- opus_decode_frame(st, NULL, 0, pcm_transition, IMIN(F10, audiosize), 0);
+ opus_decode_frame(st, NULL, 0, pcm_transition, IMIN(F5, audiosize), 0);
/* 5 ms redundant frame for CELT->SILK*/
if (redundancy && celt_to_silk)
{
celt_decoder_ctl(celt_dec, CELT_SET_START_BAND(0));
- celt_decode(celt_dec, data+len, redundancy_bytes, redundant_audio, F5);
+ celt_decode_native(celt_dec, data+len, redundancy_bytes, redundant_audio, F5);
celt_decoder_ctl(celt_dec, CELT_RESET_STATE);
}
@@ -341,12 +358,24 @@
{
int celt_frame_size = IMIN(F20, frame_size);
/* Decode CELT */
- celt_ret = celt_decode_with_ec(celt_dec, decode_fec?NULL:data, len, pcm_celt, celt_frame_size, &dec);
- for (i=0;i<celt_frame_size*st->channels;i++)
- pcm[i] = SAT16(pcm[i] + (int)pcm_celt[i]);
+ celt_ret = celt_decode_with_ec(celt_dec, decode_fec?NULL:data, len, pcm, celt_frame_size, &dec);
+ } else {
+ for (i=0;i<frame_size*st->channels;i++)
+ pcm[i] = 0;
}
+ if (mode != MODE_CELT_ONLY)
{
+#ifdef FIXED_POINT
+ for (i=0;i<frame_size*st->channels;i++)
+ pcm[i] = SAT16(pcm[i] + pcm_silk[i]);
+#else
+ for (i=0;i<frame_size*st->channels;i++)
+ pcm[i] = pcm[i] + (1./32768.)*pcm_silk[i];
+#endif
+ }
+
+ {
const CELTMode *celt_mode;
celt_decoder_ctl(celt_dec, CELT_GET_MODE(&celt_mode));
window = celt_mode->window;
@@ -358,7 +387,7 @@
celt_decoder_ctl(celt_dec, CELT_RESET_STATE);
celt_decoder_ctl(celt_dec, CELT_SET_START_BAND(0));
- celt_decode(celt_dec, data+len, redundancy_bytes, redundant_audio, F5);
+ celt_decode_native(celt_dec, data+len, redundancy_bytes, redundant_audio, F5);
smooth_fade(pcm+st->channels*(frame_size-F2_5), redundant_audio+st->channels*F2_5,
pcm+st->channels*(frame_size-F2_5), F2_5, st->channels, window, st->Fs);
}
@@ -386,6 +415,7 @@
st->prev_mode = mode;
st->prev_redundancy = redundancy;
+ RESTORE_STACK;
return celt_ret<0 ? celt_ret : audiosize;
}
@@ -528,9 +558,13 @@
return count;
}
-
+#ifdef FIXED_POINT
int opus_decode(OpusDecoder *st, const unsigned char *data,
- int len, opus_int16 *pcm, int frame_size, int decode_fec)
+ int len, opus_val16 *pcm, int frame_size, int decode_fec)
+#else
+int opus_decode_float(OpusDecoder *st, const unsigned char *data,
+ int len, opus_val16 *pcm, int frame_size, int decode_fec)
+#endif
{
int i, nb_samples;
int count;
@@ -566,6 +600,49 @@
return nb_samples;
}
+#ifdef FIXED_POINT
+
+#ifndef DISABLE_FLOAT_API
+int opus_decode_float(OpusDecoder *st, const unsigned char *data,
+ int len, float *pcm, int frame_size, int decode_fec)
+{
+ VARDECL(opus_int16, out);
+ int ret, i;
+ ALLOC_STACK;
+
+ ALLOC(out, frame_size*st->channels, opus_int16);
+
+ ret = opus_decode(st, data, len, out, frame_size, decode_fec);
+ if (ret > 0)
+ {
+ for (i=0;i<ret*st->channels;i++)
+ pcm[i] = (1./32768.)*(out[i]);
+ }
+ RESTORE_STACK;
+ return ret;
+}
+#endif
+
+#else
+int opus_decode(OpusDecoder *st, const unsigned char *data,
+ int len, opus_int16 *pcm, int frame_size, int decode_fec)
+{
+ VARDECL(float, out);
+ int ret, i;
+ ALLOC_STACK;
+
+ ALLOC(out, frame_size*st->channels, float);
+
+ ret = opus_decode_float(st, data, len, out, frame_size, decode_fec);
+ if (ret > 0)
+ {
+ for (i=0;i<ret*st->channels;i++)
+ pcm[i] = FLOAT2INT16(out[i]);
+ }
+ RESTORE_STACK;
+ return ret;
+}
+#endif
int opus_decoder_ctl(OpusDecoder *st, int request, ...)
{
--- a/src/opus_encoder.c
+++ b/src/opus_encoder.c
@@ -38,7 +38,15 @@
#include "entenc.h"
#include "modes.h"
#include "silk_API.h"
+#include "stack_alloc.h"
+#include "float_cast.h"
+#ifdef FIXED_POINT
+#define celt_encode_native celt_encode
+#else
+#define celt_encode_native celt_encode_float
+#endif
+
/* Transition tables for the voice and audio modes. First column is the
middle (memoriless) threshold. The second column is the hysteresis
(difference with the middle) */
@@ -161,9 +169,13 @@
return NULL;
return opus_encoder_init((OpusEncoder*)raw_state, Fs, channels, mode);
}
-
-int opus_encode(OpusEncoder *st, const opus_int16 *pcm, int frame_size,
+#ifdef FIXED_POINT
+int opus_encode(OpusEncoder *st, const opus_val16 *pcm, int frame_size,
unsigned char *data, int max_data_bytes)
+#else
+int opus_encode_float(OpusEncoder *st, const opus_val16 *pcm, int frame_size,
+ unsigned char *data, int max_data_bytes)
+#endif
{
void *silk_enc;
CELTEncoder *celt_enc;
@@ -179,12 +191,11 @@
int redundancy = 0;
int redundancy_bytes = 0;
int celt_to_silk = 0;
- /* TODO: This is 60 only so we can handle 60ms speech/audio switching
- it shouldn't be too hard to reduce to 20 ms if needed */
- opus_int16 pcm_buf[60*48*2];
+ VARDECL(opus_val16, pcm_buf);
int nb_compr_bytes;
int to_celt = 0;
opus_int32 mono_rate;
+ ALLOC_STACK;
if (400*frame_size != st->Fs && 200*frame_size != st->Fs && 100*frame_size != st->Fs &&
50*frame_size != st->Fs && 25*frame_size != st->Fs && 50*frame_size != 3*st->Fs)
@@ -378,6 +389,12 @@
/* SILK processing */
if (st->mode != MODE_CELT_ONLY)
{
+#ifdef FIXED_POINT
+ const opus_int16 *pcm_silk;
+#else
+ VARDECL(opus_int16, pcm_silk);
+ ALLOC(pcm_silk, st->channels*frame_size, opus_int16);
+#endif
st->silk_mode.bitRate = st->bitrate_bps - 8*st->Fs/frame_size;
if( st->mode == MODE_HYBRID ) {
st->silk_mode.bitRate /= st->stream_channels;
@@ -429,10 +446,22 @@
if (prefill)
{
int zero=0;
- silk_Encode( silk_enc, &st->silk_mode, st->delay_buffer, st->encoder_buffer, NULL, &zero, 1 );
+#ifdef FIXED_POINT
+ pcm_silk = st->delay_buffer;
+#else
+ for (i=0;i<st->encoder_buffer*st->channels;i++)
+ pcm_silk[i] = FLOAT2INT16(st->delay_buffer[i]);
+#endif
+ silk_Encode( silk_enc, &st->silk_mode, pcm_silk, st->encoder_buffer, NULL, &zero, 1 );
}
- ret = silk_Encode( silk_enc, &st->silk_mode, pcm, frame_size, &enc, &nBytes, 0 );
+#ifdef FIXED_POINT
+ pcm_silk = pcm;
+#else
+ for (i=0;i<frame_size*st->channels;i++)
+ pcm_silk[i] = FLOAT2INT16(pcm[i]);
+#endif
+ ret = silk_Encode( silk_enc, &st->silk_mode, pcm_silk, frame_size, &enc, &nBytes, 0 );
if( ret ) {
fprintf (stderr, "SILK encode error: %d\n", ret);
/* Handle error */
@@ -487,7 +516,7 @@
celt_encoder_ctl(celt_enc, CELT_SET_START_BAND(0));
celt_encoder_ctl(celt_enc, CELT_SET_PREDICTION(0));
/* TODO: This wastes CPU a bit compared to just prefilling the buffer */
- celt_encode(celt_enc, &st->delay_buffer[(st->encoder_buffer-st->delay_compensation-st->Fs/400)*st->channels], st->Fs/400, dummy, 10);
+ celt_encode_native(celt_enc, &st->delay_buffer[(st->encoder_buffer-st->delay_compensation-st->Fs/400)*st->channels], st->Fs/400, dummy, 10);
} else {
celt_encoder_ctl(celt_enc, CELT_SET_PREDICTION(2));
}
@@ -519,6 +548,7 @@
nb_compr_bytes = 0;
}
+ ALLOC(pcm_buf, IMAX(frame_size, st->Fs/200)*st->channels, opus_val16);
for (i=0;i<IMIN(frame_size, st->delay_compensation)*st->channels;i++)
pcm_buf[i] = st->delay_buffer[(st->encoder_buffer-st->delay_compensation)*st->channels+i];
for (;i<frame_size*st->channels;i++)
@@ -588,7 +618,7 @@
{
celt_encoder_ctl(celt_enc, CELT_SET_START_BAND(0));
celt_encoder_ctl(celt_enc, CELT_SET_VBR(0));
- celt_encode(celt_enc, pcm_buf, st->Fs/200, data+nb_compr_bytes, redundancy_bytes);
+ celt_encode_native(celt_enc, pcm_buf, st->Fs/200, data+nb_compr_bytes, redundancy_bytes);
celt_encoder_ctl(celt_enc, CELT_RESET_STATE);
}
@@ -611,9 +641,9 @@
celt_encoder_ctl(celt_enc, CELT_SET_PREDICTION(0));
/* TODO: We could speed up prefilling here */
- celt_encode(celt_enc, pcm_buf+st->channels*(frame_size-N2-N4), N4, data+nb_compr_bytes, redundancy_bytes);
+ celt_encode_native(celt_enc, pcm_buf+st->channels*(frame_size-N2-N4), N4, data+nb_compr_bytes, redundancy_bytes);
- celt_encode(celt_enc, pcm_buf+st->channels*(frame_size-N2), N2, data+nb_compr_bytes, redundancy_bytes);
+ celt_encode_native(celt_enc, pcm_buf+st->channels*(frame_size-N2), N2, data+nb_compr_bytes, redundancy_bytes);
}
@@ -668,6 +698,45 @@
st->first = 0;
return ret+1+redundancy_bytes;
}
+
+#ifdef FIXED_POINT
+
+#ifndef DISABLE_FLOAT_API
+int opus_encode_float(OpusEncoder *st, const float *pcm, int frame_size,
+ unsigned char *data, int max_data_bytes)
+{
+ int i, ret;
+ VARDECL(opus_int16, in);
+ ALLOC_STACK;
+
+ ALLOC(in, frame_size*st->channels, opus_int16);
+
+ for (i=0;i<frame_size*st->channels;i++)
+ in[i] = FLOAT2INT16(pcm[i]);
+ ret = opus_encode(st, in, frame_size, data, max_data_bytes);
+ RESTORE_STACK;
+ return ret;
+}
+#endif
+
+#else
+int opus_encode(OpusEncoder *st, const opus_int16 *pcm, int frame_size,
+ unsigned char *data, int max_data_bytes)
+{
+ int i, ret;
+ VARDECL(float, in);
+ ALLOC_STACK;
+
+ ALLOC(in, frame_size*st->channels, float);
+
+ for (i=0;i<frame_size*st->channels;i++)
+ in[i] = (1./32768)*pcm[i];
+ ret = opus_encode_float(st, in, frame_size, data, max_data_bytes);
+ RESTORE_STACK;
+ return ret;
+}
+#endif
+
int opus_encoder_ctl(OpusEncoder *st, int request, ...)
{
--- a/src/opus_encoder.h
+++ b/src/opus_encoder.h
@@ -31,8 +31,8 @@
#include "celt.h"
#include "opus.h"
#include "silk_API.h"
+#include "arch.h"
-/* FIXME: This is only valid for 48 kHz */
#define MAX_ENCODER_BUFFER 480
struct OpusEncoder {
@@ -60,7 +60,7 @@
int encoder_buffer;
int delay_compensation;
int first;
- short delay_buffer[MAX_ENCODER_BUFFER*2];
+ opus_val16 delay_buffer[MAX_ENCODER_BUFFER*2];
int rangeFinal;
};
--- a/src/test_opus.c
+++ b/src/test_opus.c
@@ -380,6 +380,8 @@
{
fwrite(out+skip, sizeof(short)*channels, output_samples-skip, fout);
skip = 0;
+ } else {
+ fprintf(stderr, "error decoding frame: %s\n", opus_strerror(output_samples));
}
}
}