diff --git a/src/analysis.c b/src/analysis.c index b79e869ab73ab5164c664fb85e4e6afc138ab970..e078b4cdba43fcca717f260fcd25f1f39fbdfc2d 100644 --- a/src/analysis.c +++ b/src/analysis.c @@ -618,38 +618,25 @@ void tonality_analysis(TonalityAnalysisState *tonal, AnalysisInfo *info_out, con RESTORE_STACK; } -int run_analysis(TonalityAnalysisState *analysis, const CELTMode *celt_mode, const opus_val16 *pcm, - const void *analysis_pcm, int frame_size, int variable_duration, int c1, int c2, int C, opus_int32 Fs, int bitrate_bps, - int delay_compensation, int lsb_depth, downmix_func downmix, AnalysisInfo *analysis_info) +int run_analysis(TonalityAnalysisState *analysis, const CELTMode *celt_mode, const void *analysis_pcm, + int analysis_frame_size, int frame_size, int c1, int c2, int C, opus_int32 Fs, + int lsb_depth, downmix_func downmix, AnalysisInfo *analysis_info) { int offset; int pcm_len; /* Avoid overflow/wrap-around of the analysis buffer */ - frame_size = IMIN((DETECT_SIZE-5)*Fs/100, frame_size); + analysis_frame_size = IMIN((DETECT_SIZE-5)*Fs/100, analysis_frame_size); - pcm_len = frame_size - analysis->analysis_offset; + pcm_len = analysis_frame_size - analysis->analysis_offset; offset = analysis->analysis_offset; do { tonality_analysis(analysis, NULL, celt_mode, analysis_pcm, IMIN(480, pcm_len), offset, c1, c2, C, lsb_depth, downmix); offset += 480; pcm_len -= 480; } while (pcm_len>0); - analysis->analysis_offset = frame_size; + analysis->analysis_offset = analysis_frame_size; - if (variable_duration == OPUS_FRAMESIZE_VARIABLE && frame_size >= Fs/200) - { - int LM = 3; - LM = optimize_framesize(pcm, frame_size, C, Fs, bitrate_bps, - analysis->prev_tonality, analysis->subframe_mem, delay_compensation, downmix); - while ((Fs/400<<LM)>frame_size) - LM--; - frame_size = (Fs/400<<LM); - } else { - frame_size = frame_size_select(frame_size, variable_duration, Fs); - } - if (frame_size<0) - return -1; analysis->analysis_offset -= frame_size; /* Only perform analysis up to 20-ms frames. Longer ones will be split if diff --git a/src/analysis.h b/src/analysis.h index ebd36c86cae2b72b28fc6963d8ad5cf9fea67710..a4a22caef897039ac1ef47d65b626670199bf03b 100644 --- a/src/analysis.h +++ b/src/analysis.h @@ -83,8 +83,8 @@ void tonality_analysis(TonalityAnalysisState *tonal, AnalysisInfo *info, void tonality_get_info(TonalityAnalysisState *tonal, AnalysisInfo *info_out, int len); -int run_analysis(TonalityAnalysisState *analysis, const CELTMode *celt_mode, const opus_val16 *pcm, - const void *analysis_pcm, int frame_size, int variable_duration, int c1, int c2, int C, opus_int32 Fs, int bitrate_bps, - int delay_compensation, int lsb_depth, downmix_func downmix, AnalysisInfo *analysis_info); +int run_analysis(TonalityAnalysisState *analysis, const CELTMode *celt_mode, const void *analysis_pcm, + int analysis_frame_size, int frame_size, int c1, int c2, int C, opus_int32 Fs, + int lsb_depth, downmix_func downmix, AnalysisInfo *analysis_info); #endif diff --git a/src/opus_encoder.c b/src/opus_encoder.c index 3823272cc7e1cd0e58156ec4aef214761d0c7163..b0ec383a67d36f05037fc2d8cca42d3ef6850bf5 100644 --- a/src/opus_encoder.c +++ b/src/opus_encoder.c @@ -849,6 +849,26 @@ opus_int32 frame_size_select(opus_int32 frame_size, int variable_duration, opus_ return new_size; } +opus_int32 compute_frame_size(const void *analysis_pcm, int frame_size, + int variable_duration, int C, opus_int32 Fs, int bitrate_bps, + int delay_compensation, downmix_func downmix, opus_val32 *subframe_mem) +{ + if (variable_duration == OPUS_FRAMESIZE_VARIABLE && frame_size >= Fs/200) + { + int LM = 3; + LM = optimize_framesize(analysis_pcm, frame_size, C, Fs, bitrate_bps, + 0, subframe_mem, delay_compensation, downmix); + while ((Fs/400<<LM)>frame_size) + LM--; + frame_size = (Fs/400<<LM); + } else { + frame_size = frame_size_select(frame_size, variable_duration, Fs); + } + if (frame_size<0) + return -1; + return frame_size; +} + opus_val16 compute_stereo_width(const opus_val16 *pcm, int frame_size, opus_int32 Fs, StereoWidthState *mem) { opus_val16 corr; @@ -928,7 +948,7 @@ 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, 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) { void *silk_enc; CELTEncoder *celt_enc; @@ -987,10 +1007,11 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_ analysis_info.valid = 0; celt_encoder_ctl(celt_enc, CELT_GET_MODE(&celt_mode)); #ifndef DISABLE_FLOAT_API - if (st->silk_mode.complexity >= 7 && st->Fs==48000) + if (analysis_pcm != NULL && st->silk_mode.complexity >= 7 && st->Fs==48000) { - frame_size = run_analysis(&st->analysis, celt_mode, pcm, analysis_pcm, - frame_size, st->variable_duration, c1, c2, analysis_channels, st->Fs, st->bitrate_bps, delay_compensation, lsb_depth, downmix, &analysis_info); + frame_size = run_analysis(&st->analysis, celt_mode, analysis_pcm, analysis_size, frame_size, + c1, c2, analysis_channels, st->Fs, + lsb_depth, downmix, &analysis_info); } else #endif { @@ -1373,7 +1394,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, - analysis_pcm, c1, c2, analysis_channels, downmix); + NULL, 0, c1, c2, analysis_channels, downmix); if (tmp_len<0) { RESTORE_STACK; @@ -1915,49 +1936,88 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_ #ifdef FIXED_POINT #ifndef DISABLE_FLOAT_API -opus_int32 opus_encode_float(OpusEncoder *st, const float *pcm, int frame_size, +opus_int32 opus_encode_float(OpusEncoder *st, const float *pcm, int analysis_frame_size, unsigned char *data, opus_int32 max_data_bytes) { int i, ret; + int frame_size; + int delay_compensation; VARDECL(opus_int16, in); ALLOC_STACK; + if (st->application == OPUS_APPLICATION_RESTRICTED_LOWDELAY) + delay_compensation = 0; + else + delay_compensation = st->delay_compensation; + frame_size = compute_frame_size(pcm, analysis_frame_size, + st->variable_duration, st->channels, st->Fs, st->bitrate_bps, + delay_compensation, downmix_float, st->analysis.subframe_mem); + 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_native(st, in, frame_size, data, max_data_bytes, 16, pcm, 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); RESTORE_STACK; return ret; } #endif -opus_int32 opus_encode(OpusEncoder *st, const opus_int16 *pcm, int frame_size, +opus_int32 opus_encode(OpusEncoder *st, const opus_int16 *pcm, int analysis_frame_size, unsigned char *data, opus_int32 out_data_bytes) { - return opus_encode_native(st, pcm, frame_size, data, out_data_bytes, 16, pcm, 0, -2, st->channels, downmix_int); + int frame_size; + int delay_compensation; + if (st->application == OPUS_APPLICATION_RESTRICTED_LOWDELAY) + delay_compensation = 0; + else + delay_compensation = st->delay_compensation; + frame_size = compute_frame_size(pcm, analysis_frame_size, + 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, 16, pcm, analysis_frame_size, 0, -2, st->channels, downmix_int); } #else -opus_int32 opus_encode(OpusEncoder *st, const opus_int16 *pcm, int frame_size, +opus_int32 opus_encode(OpusEncoder *st, const opus_int16 *pcm, int analysis_frame_size, unsigned char *data, opus_int32 max_data_bytes) { int i, ret; + int frame_size; + int delay_compensation; VARDECL(float, in); ALLOC_STACK; - ALLOC(in, frame_size*st->channels, float); + if (st->application == OPUS_APPLICATION_RESTRICTED_LOWDELAY) + delay_compensation = 0; + else + delay_compensation = st->delay_compensation; + frame_size = compute_frame_size(pcm, analysis_frame_size, + st->variable_duration, st->channels, st->Fs, st->bitrate_bps, + delay_compensation, downmix_float, st->analysis.subframe_mem); - for (i=0;i<frame_size*st->channels;i++) + ALLOC(in, analysis_frame_size*st->channels, float); + + for (i=0;i<analysis_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, 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); RESTORE_STACK; return ret; } -opus_int32 opus_encode_float(OpusEncoder *st, const float *pcm, int frame_size, +opus_int32 opus_encode_float(OpusEncoder *st, const float *pcm, int analysis_frame_size, unsigned char *data, opus_int32 out_data_bytes) { - return opus_encode_native(st, pcm, frame_size, data, out_data_bytes, 24, pcm, 0, -2, st->channels, downmix_float); + int frame_size; + int delay_compensation; + if (st->application == OPUS_APPLICATION_RESTRICTED_LOWDELAY) + delay_compensation = 0; + else + delay_compensation = st->delay_compensation; + frame_size = compute_frame_size(pcm, analysis_frame_size, + 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); } #endif diff --git a/src/opus_multistream_encoder.c b/src/opus_multistream_encoder.c index 32c6f0aa0f7717b51696ac57d02fcbaa69c3734d..31447bf9c19383890e96baaca2eac4c1a20e53a6 100644 --- a/src/opus_multistream_encoder.c +++ b/src/opus_multistream_encoder.c @@ -72,6 +72,7 @@ typedef void (*opus_copy_channel_in_func)( struct OpusMSEncoder { ChannelLayout layout; int lfe_stream; + int application; int variable_duration; int surround; opus_int32 bitrate_bps; @@ -416,6 +417,7 @@ static int opus_multistream_encoder_init_impl( if (!surround) st->lfe_stream = -1; st->bitrate_bps = OPUS_AUTO; + st->application = application; st->variable_duration = OPUS_FRAMESIZE_ARG; for (i=0;i<st->layout.nb_channels;i++) st->layout.mapping[i] = mapping[i]; @@ -666,7 +668,7 @@ static int opus_multistream_encode_native OpusMSEncoder *st, opus_copy_channel_in_func copy_channel_in, const void *pcm, - int frame_size, + int analysis_frame_size, unsigned char *data, opus_int32 max_data_bytes, int lsb_depth, @@ -689,6 +691,7 @@ static int opus_multistream_encode_native opus_val16 bandLogE[42]; opus_val32 *mem = NULL; opus_val32 *preemph_mem=NULL; + int frame_size; ALLOC_STACK; if (st->surround) @@ -702,6 +705,18 @@ static int opus_multistream_encode_native opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_COMPLEXITY(&complexity)); opus_encoder_ctl((OpusEncoder*)ptr, CELT_GET_MODE(&celt_mode)); + { + opus_int32 delay_compensation; + int channels; + + channels = st->layout.nb_streams + st->layout.nb_coupled_streams; + opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_LOOKAHEAD(&delay_compensation)); + delay_compensation -= Fs/400; + frame_size = compute_frame_size(pcm, analysis_frame_size, + st->variable_duration, channels, Fs, st->bitrate_bps, + delay_compensation, downmix, st->subframe_mem); + } + if (400*frame_size < Fs) { RESTORE_STACK; @@ -822,7 +837,8 @@ static int opus_multistream_encode_native /* Reserve three bytes for the last stream and four for the others */ curr_max -= IMAX(0,4*(st->layout.nb_streams-s-1)-1); curr_max = IMIN(curr_max,MS_FRAME_TMP); - len = opus_encode_native(enc, buf, frame_size, tmp_data, curr_max, lsb_depth, pcm, c1, c2, st->layout.nb_channels, downmix); + len = opus_encode_native(enc, buf, frame_size, tmp_data, curr_max, lsb_depth, + pcm, analysis_frame_size, c1, c2, st->layout.nb_channels, downmix); if (len<0) { RESTORE_STACK; diff --git a/src/opus_private.h b/src/opus_private.h index 64c325ab2b313644aa66c85782abf77f9738ed9b..0e739ebb0b0ed5691425b9a73a78805a930b3e73 100644 --- a/src/opus_private.h +++ b/src/opus_private.h @@ -94,9 +94,13 @@ int encode_size(int size, unsigned char *data); opus_int32 frame_size_select(opus_int32 frame_size, int variable_duration, opus_int32 Fs); +opus_int32 compute_frame_size(const void *analysis_pcm, int frame_size, + int variable_duration, int C, opus_int32 Fs, int bitrate_bps, + int delay_compensation, downmix_func downmix, opus_val32 *subframe_mem); + 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, 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 opus_decode_native(OpusDecoder *st, const unsigned char *data, opus_int32 len, opus_val16 *pcm, int frame_size, int decode_fec, int self_delimited,