diff --git a/libcelt/celt.c b/libcelt/celt.c index 8a721ea51889bdc7905a9b659677a1821c3e0fb7..dfa72e14ebd2b610a7c40c8697d217be9e8650f4 100644 --- a/libcelt/celt.c +++ b/libcelt/celt.c @@ -283,14 +283,6 @@ void celt_encoder_destroy(CELTEncoder *st) 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 @@ static int stereo_analysis(const CELTMode *m, const celt_norm *X, > 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) -{ -#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) +int celt_encode_with_ec(CELTEncoder * restrict st, const opus_val16 * 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 @@ int celt_encode_with_ec_float(CELTEncoder * restrict st, const celt_sig * pcm, i 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,19 +1686,18 @@ int celt_encode_with_ec_float(CELTEncoder * restrict st, const float * pcm, int 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); #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 @@ int celt_encode_with_ec(CELTEncoder * restrict st, const opus_int16 * pcm, int f 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 @@ int celt_encode_with_ec(CELTEncoder * restrict st, const opus_int16 * pcm, int f 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 @@ static void celt_decode_lost(CELTDecoder * restrict st, opus_val16 * restrict pc 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 @@ int celt_decode_with_ec_float(CELTDecoder * restrict st, const unsigned char *da 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 @@ int celt_decode_with_ec_float(CELTDecoder * restrict st, const unsigned char *da 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,10 +2636,16 @@ int celt_decode_with_ec_float(CELTDecoder * restrict st, const unsigned char *da 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); @@ -2667,7 +2658,7 @@ int celt_decode_with_ec(CELTDecoder * restrict st, const unsigned char *data, in 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 @@ int celt_decode_with_ec(CELTDecoder * restrict st, const unsigned char *data, in 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); -} +#endif -#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, ...) { diff --git a/libcelt/float_cast.h b/libcelt/float_cast.h index b130b88051d3fcacfe6eb81f6c2df79e97e9f12f..b3670f0b8cfdc207e314d44edfe9e421c5d679e9 100644 --- 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 */ diff --git a/libcelt/modes.h b/libcelt/modes.h index 33cd038506249f6b874a4d459e69d4a417011225..89836e3040718d258dc76560e70b6a14242f1012 100644 --- a/libcelt/modes.h +++ b/libcelt/modes.h @@ -102,10 +102,8 @@ struct CELTMode { #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 diff --git a/src/opus_decoder.c b/src/opus_decoder.c index d8f4af4b9b36c03051ce81f835df8af81168e52d..df7df509bc5210d61d9368061b85227028f6fbd2 100644 --- a/src/opus_decoder.c +++ b/src/opus_decoder.c @@ -38,6 +38,14 @@ #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) */ @@ -109,7 +117,7 @@ OpusDecoder *opus_decoder_create(int Fs, int channels) 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_packet_get_mode(const unsigned char *data) } 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 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data, 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 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data, 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 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data, { 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,33 +199,40 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data, /* 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; } } + 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)) { 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 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data, 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 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data, } } 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 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data, 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,9 +358,21 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data, { 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 } { @@ -358,7 +387,7 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data, 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 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data, st->prev_mode = mode; st->prev_redundancy = redundancy; + RESTORE_STACK; return celt_ret<0 ? celt_ret : audiosize; } @@ -528,9 +558,13 @@ int opus_packet_parse(const unsigned char *data, int len, 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 @@ int opus_decode(OpusDecoder *st, const unsigned char *data, 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, ...) { diff --git a/src/opus_encoder.c b/src/opus_encoder.c index 3e86c63104fc49d87d3ba3f681e3ca19abf4b3f4..fbf857cba6a38b4cbc57ea72589d3e2f32fb4962 100644 --- a/src/opus_encoder.c +++ b/src/opus_encoder.c @@ -38,6 +38,14 @@ #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 @@ -161,9 +169,13 @@ OpusEncoder *opus_encoder_create(int Fs, int channels, int mode) 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 opus_encode(OpusEncoder *st, const opus_int16 *pcm, int frame_size, 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 @@ int opus_encode(OpusEncoder *st, const opus_int16 *pcm, int frame_size, /* 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 @@ int opus_encode(OpusEncoder *st, const opus_int16 *pcm, int frame_size, 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 @@ int opus_encode(OpusEncoder *st, const opus_int16 *pcm, int frame_size, 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 @@ int opus_encode(OpusEncoder *st, const opus_int16 *pcm, int frame_size, 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 @@ int opus_encode(OpusEncoder *st, const opus_int16 *pcm, int frame_size, { 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 @@ int opus_encode(OpusEncoder *st, const opus_int16 *pcm, int frame_size, 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); } @@ -669,6 +699,45 @@ int opus_encode(OpusEncoder *st, const opus_int16 *pcm, int frame_size, 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, ...) { CELTEncoder *celt_enc; diff --git a/src/opus_encoder.h b/src/opus_encoder.h index 73e862e11d947bcf9ae7772d2403de1157087c0a..7b1aaccee7ca975fff9797221a2340edf35abdbd 100644 --- 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 @@ struct OpusEncoder { 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; }; diff --git a/src/test_opus.c b/src/test_opus.c index 274fbcb74067bf9b5c010e2eb6f6fc9d23349f7f..664539a754e589fc360ab2eb3170c0a4dc453f56 100644 --- a/src/test_opus.c +++ b/src/test_opus.c @@ -380,6 +380,8 @@ int main(int argc, char *argv[]) { fwrite(out+skip, sizeof(short)*channels, output_samples-skip, fout); skip = 0; + } else { + fprintf(stderr, "error decoding frame: %s\n", opus_strerror(output_samples)); } } }