Index: src/opus_encoder.c |
diff --git a/src/opus_encoder.c b/src/opus_encoder.c |
index fbd3de6392159ab5e4e75b41154b93a8764c3bd4..d94163f44eceb31906025307f96abbd66d99cf5e 100644 |
--- a/src/opus_encoder.c |
+++ b/src/opus_encoder.c |
@@ -38,6 +38,7 @@ |
#include "float_cast.h" |
#include "opus.h" |
#include "arch.h" |
+#include "pitch.h" |
#include "opus_private.h" |
#include "os_support.h" |
#include "cpu_support.h" |
@@ -231,7 +232,7 @@ int opus_encoder_init(OpusEncoder* st, opus_int32 Fs, int channels, int applicat |
st->lsb_depth = 24; |
st->variable_duration = OPUS_FRAMESIZE_ARG; |
- /* Delay compensation of 4 ms (2.5 ms for SILK's extra look-ahead |
+ /* Delay compensation of 4 ms (2.5 ms for SILK's extra look-ahead |
+ 1.5 ms for SILK resamplers and stereo prediction) */ |
st->delay_compensation = st->Fs/250; |
@@ -648,7 +649,7 @@ static int transient_viterbi(const float *E, const float *E_1, int N, int frame_ |
return best_state; |
} |
-int optimize_framesize(const opus_val16 *x, int len, int C, opus_int32 Fs, |
+static int optimize_framesize(const void *x, int len, int C, opus_int32 Fs, |
int bitrate, opus_val16 tonality, float *mem, int buffering, |
downmix_func downmix) |
{ |
@@ -660,6 +661,7 @@ int optimize_framesize(const opus_val16 *x, int len, int C, opus_int32 Fs, |
int bestLM=0; |
int subframe; |
int pos; |
+ int offset; |
VARDECL(opus_val32, sub); |
subframe = Fs/400; |
@@ -670,9 +672,8 @@ int optimize_framesize(const opus_val16 *x, int len, int C, opus_int32 Fs, |
{ |
/* Consider the CELT delay when not in restricted-lowdelay */ |
/* We assume the buffering is between 2.5 and 5 ms */ |
- int offset = 2*subframe - buffering; |
+ offset = 2*subframe - buffering; |
celt_assert(offset>=0 && offset <= subframe); |
- x += C*offset; |
len -= offset; |
e[1]=mem[1]; |
e_1[1]=1.f/(EPSILON+mem[1]); |
@@ -681,6 +682,7 @@ int optimize_framesize(const opus_val16 *x, int len, int C, opus_int32 Fs, |
pos = 3; |
} else { |
pos=1; |
+ offset=0; |
} |
N=IMIN(len/subframe, MAX_DYNAMIC_FRAMESIZE); |
/* Just silencing a warning, it's really initialized later */ |
@@ -692,7 +694,7 @@ int optimize_framesize(const opus_val16 *x, int len, int C, opus_int32 Fs, |
int j; |
tmp=EPSILON; |
- downmix(x, sub, subframe, i*subframe, 0, -2, C); |
+ downmix(x, sub, subframe, i*subframe+offset, 0, -2, C); |
if (i==0) |
memx = sub[0]; |
for (j=0;j<subframe;j++) |
@@ -836,6 +838,12 @@ opus_int32 compute_frame_size(const void *analysis_pcm, int frame_size, |
LM--; |
frame_size = (Fs/400<<LM); |
} else |
+#else |
+ (void)analysis_pcm; |
+ (void)C; |
+ (void)bitrate_bps; |
+ (void)delay_compensation; |
+ (void)downmix; |
#endif |
{ |
frame_size = frame_size_select(frame_size, variable_duration, Fs); |
@@ -924,7 +932,8 @@ opus_val16 compute_stereo_width(const opus_val16 *pcm, int frame_size, opus_int3 |
opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_size, |
unsigned char *data, opus_int32 out_data_bytes, int lsb_depth, |
- const void *analysis_pcm, opus_int32 analysis_size, int c1, int c2, int analysis_channels, downmix_func downmix) |
+ const void *analysis_pcm, opus_int32 analysis_size, int c1, int c2, |
+ int analysis_channels, downmix_func downmix, int float_api) |
{ |
void *silk_enc; |
CELTEncoder *celt_enc; |
@@ -954,9 +963,11 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_ |
int total_buffer; |
opus_val16 stereo_width; |
const CELTMode *celt_mode; |
+#ifndef DISABLE_FLOAT_API |
AnalysisInfo analysis_info; |
int analysis_read_pos_bak=-1; |
int analysis_read_subframe_bak=-1; |
+#endif |
VARDECL(opus_val16, tmp_prefill); |
ALLOC_STACK; |
@@ -982,9 +993,9 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_ |
lsb_depth = IMIN(lsb_depth, st->lsb_depth); |
- analysis_info.valid = 0; |
celt_encoder_ctl(celt_enc, CELT_GET_MODE(&celt_mode)); |
#ifndef DISABLE_FLOAT_API |
+ analysis_info.valid = 0; |
#ifdef FIXED_POINT |
if (st->silk_mode.complexity >= 10 && st->Fs==48000) |
#else |
@@ -997,6 +1008,9 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_ |
c1, c2, analysis_channels, st->Fs, |
lsb_depth, downmix, &analysis_info); |
} |
+#else |
+ (void)analysis_pcm; |
+ (void)analysis_size; |
#endif |
st->voice_ratio = -1; |
@@ -1377,7 +1391,7 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_ |
st->user_forced_mode = MODE_CELT_ONLY; |
tmp_len = opus_encode_native(st, pcm+i*(st->channels*st->Fs/50), st->Fs/50, |
tmp_data+i*bytes_per_frame, bytes_per_frame, lsb_depth, |
- NULL, 0, c1, c2, analysis_channels, downmix); |
+ NULL, 0, c1, c2, analysis_channels, downmix, float_api); |
if (tmp_len<0) |
{ |
RESTORE_STACK; |
@@ -1424,8 +1438,7 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_ |
ec_enc_init(&enc, data, max_data_bytes-1); |
ALLOC(pcm_buf, (total_buffer+frame_size)*st->channels, opus_val16); |
- for (i=0;i<total_buffer*st->channels;i++) |
- pcm_buf[i] = st->delay_buffer[(st->encoder_buffer-total_buffer)*st->channels+i]; |
+ OPUS_COPY(pcm_buf, &st->delay_buffer[(st->encoder_buffer-total_buffer)*st->channels], total_buffer*st->channels); |
if (st->mode == MODE_CELT_ONLY) |
hp_freq_smth1 = silk_LSHIFT( silk_lin2log( VARIABLE_HP_MIN_CUTOFF_HZ ), 8 ); |
@@ -1444,7 +1457,17 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_ |
} else { |
dc_reject(pcm, 3, &pcm_buf[total_buffer*st->channels], st->hp_mem, frame_size, st->channels, st->Fs); |
} |
- |
+#ifndef FIXED_POINT |
+ if (float_api) |
+ { |
+ opus_val32 sum; |
+ sum = celt_inner_prod(&pcm_buf[total_buffer*st->channels], &pcm_buf[total_buffer*st->channels], frame_size*st->channels, st->arch); |
+ /* This should filter out both NaNs and ridiculous signals that could |
+ cause NaNs further down. */ |
+ if (!(sum < 1e9f) || celt_isnan(sum)) |
+ OPUS_CLEAR(&pcm_buf[total_buffer*st->channels], frame_size*st->channels); |
+ } |
+#endif |
/* SILK processing */ |
@@ -1599,8 +1622,7 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_ |
prefill_offset = st->channels*(st->encoder_buffer-st->delay_compensation-st->Fs/400); |
gain_fade(st->delay_buffer+prefill_offset, st->delay_buffer+prefill_offset, |
0, Q15ONE, celt_mode->overlap, st->Fs/400, st->channels, celt_mode->window, st->Fs); |
- for(i=0;i<prefill_offset;i++) |
- st->delay_buffer[i]=0; |
+ OPUS_CLEAR(st->delay_buffer, prefill_offset); |
#ifdef FIXED_POINT |
pcm_silk = st->delay_buffer; |
#else |
@@ -1727,15 +1749,18 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_ |
ALLOC(tmp_prefill, st->channels*st->Fs/400, opus_val16); |
if (st->mode != MODE_SILK_ONLY && st->mode != st->prev_mode && st->prev_mode > 0) |
{ |
- for (i=0;i<st->channels*st->Fs/400;i++) |
- tmp_prefill[i] = st->delay_buffer[(st->encoder_buffer-total_buffer-st->Fs/400)*st->channels + i]; |
+ OPUS_COPY(tmp_prefill, &st->delay_buffer[(st->encoder_buffer-total_buffer-st->Fs/400)*st->channels], st->channels*st->Fs/400); |
} |
- for (i=0;i<st->channels*(st->encoder_buffer-(frame_size+total_buffer));i++) |
- st->delay_buffer[i] = st->delay_buffer[i+st->channels*frame_size]; |
- for (;i<st->encoder_buffer*st->channels;i++) |
- st->delay_buffer[i] = pcm_buf[(frame_size+total_buffer-st->encoder_buffer)*st->channels+i]; |
- |
+ if (st->channels*(st->encoder_buffer-(frame_size+total_buffer)) > 0) |
+ { |
+ OPUS_MOVE(st->delay_buffer, &st->delay_buffer[st->channels*frame_size], st->channels*(st->encoder_buffer-frame_size-total_buffer)); |
+ OPUS_COPY(&st->delay_buffer[st->channels*(st->encoder_buffer-frame_size-total_buffer)], |
+ &pcm_buf[0], |
+ (frame_size+total_buffer)*st->channels); |
+ } else { |
+ OPUS_COPY(st->delay_buffer, &pcm_buf[(frame_size+total_buffer-st->encoder_buffer)*st->channels], st->encoder_buffer*st->channels); |
+ } |
/* gain_fade() and stereo_fade() need to be after the buffer copying |
because we don't want any of this to affect the SILK part */ |
if( st->prev_HB_gain < Q15ONE || HB_gain < Q15ONE ) { |
@@ -1955,7 +1980,8 @@ opus_int32 opus_encode_float(OpusEncoder *st, const float *pcm, int analysis_fra |
for (i=0;i<frame_size*st->channels;i++) |
in[i] = FLOAT2INT16(pcm[i]); |
- ret = opus_encode_native(st, in, frame_size, data, max_data_bytes, 16, pcm, analysis_frame_size, 0, -2, st->channels, downmix_float); |
+ ret = opus_encode_native(st, in, frame_size, data, max_data_bytes, 16, |
+ pcm, analysis_frame_size, 0, -2, st->channels, downmix_float, 1); |
RESTORE_STACK; |
return ret; |
} |
@@ -1977,7 +2003,8 @@ opus_int32 opus_encode(OpusEncoder *st, const opus_int16 *pcm, int analysis_fram |
, st->analysis.subframe_mem |
#endif |
); |
- return opus_encode_native(st, pcm, frame_size, data, out_data_bytes, 16, pcm, analysis_frame_size, 0, -2, st->channels, downmix_int); |
+ return opus_encode_native(st, pcm, frame_size, data, out_data_bytes, 16, |
+ pcm, analysis_frame_size, 0, -2, st->channels, downmix_int, 0); |
} |
#else |
@@ -2002,7 +2029,8 @@ opus_int32 opus_encode(OpusEncoder *st, const opus_int16 *pcm, int analysis_fram |
for (i=0;i<frame_size*st->channels;i++) |
in[i] = (1.0f/32768)*pcm[i]; |
- ret = opus_encode_native(st, in, frame_size, data, max_data_bytes, 16, pcm, analysis_frame_size, 0, -2, st->channels, downmix_int); |
+ ret = opus_encode_native(st, in, frame_size, data, max_data_bytes, 16, |
+ pcm, analysis_frame_size, 0, -2, st->channels, downmix_int, 0); |
RESTORE_STACK; |
return ret; |
} |
@@ -2019,7 +2047,7 @@ opus_int32 opus_encode_float(OpusEncoder *st, const float *pcm, int analysis_fra |
st->variable_duration, st->channels, st->Fs, st->bitrate_bps, |
delay_compensation, downmix_float, st->analysis.subframe_mem); |
return opus_encode_native(st, pcm, frame_size, data, out_data_bytes, 24, |
- pcm, analysis_frame_size, 0, -2, st->channels, downmix_float); |
+ pcm, analysis_frame_size, 0, -2, st->channels, downmix_float, 1); |
} |
#endif |
@@ -2108,7 +2136,7 @@ int opus_encoder_ctl(OpusEncoder *st, int request, ...) |
case OPUS_SET_MAX_BANDWIDTH_REQUEST: |
{ |
opus_int32 value = va_arg(ap, opus_int32); |
- if (value < OPUS_BANDWIDTH_NARROWBAND || value > OPUS_BANDWIDTH_FULLBAND) |
+ if (value < OPUS_BANDWIDTH_NARROWBAND || value > OPUS_BANDWIDTH_FULLBAND) |
{ |
goto bad_arg; |
} |