diff options
| author | Jean-Marc Valin <jmvalin@jmvalin.ca> | 2013-02-18 18:17:03 -0500 |
|---|---|---|
| committer | Jean-Marc Valin <jmvalin@jmvalin.ca> | 2013-02-18 18:17:03 -0500 |
| commit | a465956cc84b9e9a8d5cafbb0f591be59530acab (patch) | |
| tree | d6927e750d5a0db1fdddc2103d68b13389e7d98d | |
| parent | 4b70dddfe980225922d154647c8aaf9c47c30728 (diff) | |
| download | opus-a465956cc84b9e9a8d5cafbb0f591be59530acab.tar.gz | |
Moves tonality_get_info() with the analysis
Avoids the special case for >20 ms CELT packets
| -rw-r--r-- | src/analysis.c | 43 | ||||
| -rw-r--r-- | src/analysis.h | 6 | ||||
| -rw-r--r-- | src/opus_encoder.c | 115 | ||||
| -rw-r--r-- | src/opus_multistream_encoder.c | 33 | ||||
| -rw-r--r-- | src/opus_private.h | 7 |
5 files changed, 108 insertions, 96 deletions
diff --git a/src/analysis.c b/src/analysis.c index ba684d57..18e6ee8f 100644 --- a/src/analysis.c +++ b/src/analysis.c @@ -211,10 +211,9 @@ void tonality_get_info(TonalityAnalysisState *tonal, AnalysisInfo *info_out, int #endif } -void tonality_analysis(TonalityAnalysisState *tonal, AnalysisInfo *info_out, CELTEncoder *celt_enc, const void *x, int len, int offset, int C, int lsb_depth, downmix_func downmix) +void tonality_analysis(TonalityAnalysisState *tonal, AnalysisInfo *info_out, const CELTMode *celt_mode, const void *x, int len, int offset, int C, int lsb_depth, downmix_func downmix) { int i, b; - const CELTMode *mode; const kiss_fft_state *kfft; kiss_fft_cpx in[480], out[480]; int N = 480, N2=240; @@ -245,8 +244,6 @@ void tonality_analysis(TonalityAnalysisState *tonal, AnalysisInfo *info_out, CEL int remaining; AnalysisInfo *info; - celt_encoder_ctl(celt_enc, CELT_GET_MODE(&mode)); - tonal->last_transition++; alpha = 1.f/IMIN(20, 1+tonal->count); alphaE = 1.f/IMIN(50, 1+tonal->count); @@ -254,7 +251,7 @@ void tonality_analysis(TonalityAnalysisState *tonal, AnalysisInfo *info_out, CEL if (tonal->count<4) tonal->music_prob = .5; - kfft = mode->mdct.kfft[0]; + kfft = celt_mode->mdct.kfft[0]; if (tonal->count==0) tonal->mem_fill = 240; downmix(x, &tonal->inmem[tonal->mem_fill], IMIN(len, ANALYSIS_BUF_SIZE-tonal->mem_fill), offset, C); @@ -584,3 +581,39 @@ void tonality_analysis(TonalityAnalysisState *tonal, AnalysisInfo *info_out, CEL if (info_out!=NULL) OPUS_COPY(info_out, info, 1); } + +int run_analysis(TonalityAnalysisState *analysis, const CELTMode *celt_mode, const void *pcm, + const void *analysis_pcm, int frame_size, int C, int Fs, int bitrate_bps, + int delay_compensation, int lsb_depth, downmix_func downmix, AnalysisInfo *analysis_info) +{ + int offset; + int pcm_len; + int LM = 3; + + pcm_len = frame_size - analysis->analysis_offset; + offset = 0; + do { + tonality_analysis(analysis, NULL, celt_mode, analysis_pcm, IMIN(480, pcm_len), offset, C, lsb_depth, downmix); + offset += 480; + pcm_len -= 480; + } while (pcm_len>0); + analysis->analysis_offset = frame_size; + + //return frame_size; +#ifndef FIXED_POINT + LM = optimize_framesize(pcm, frame_size, C, Fs, bitrate_bps, + analysis->prev_tonality, analysis->subframe_mem, delay_compensation, downmix); +#endif + while ((Fs/400<<LM)>frame_size) + LM--; + frame_size = (Fs/400<<LM); + //frame_size = st->Fs/50; + analysis->analysis_offset -= frame_size; + + /* Only perform analysis up to 20-ms frames. Longer ones will be split if + they're in CELT-only mode. */ + analysis_info->valid = 0; + tonality_get_info(analysis, analysis_info, frame_size); + + return frame_size; +} diff --git a/src/analysis.h b/src/analysis.h index 28db0f89..b5e53d72 100644 --- a/src/analysis.h +++ b/src/analysis.h @@ -72,8 +72,12 @@ typedef struct { } TonalityAnalysisState; void tonality_analysis(TonalityAnalysisState *tonal, AnalysisInfo *info, - CELTEncoder *celt_enc, const void *x, int len, int offset, int C, int lsb_depth, downmix_func downmix); + const CELTMode *celt_mode, const void *x, int len, int offset, int C, int lsb_depth, downmix_func downmix); void tonality_get_info(TonalityAnalysisState *tonal, AnalysisInfo *info_out, int len); +int run_analysis(TonalityAnalysisState *analysis, const CELTMode *celt_mode, const void *pcm, + const void *analysis_pcm, int frame_size, int C, int Fs, int bitrate_bps, + int delay_compensation, int lsb_depth, downmix_func downmix, AnalysisInfo *analysis_info); + #endif diff --git a/src/opus_encoder.c b/src/opus_encoder.c index 560f9b14..94b8becc 100644 --- a/src/opus_encoder.c +++ b/src/opus_encoder.c @@ -760,38 +760,14 @@ int optimize_framesize(const opus_val16 *x, int len, int C, opus_int32 Fs, return bestLM; } -static int run_analysis(TonalityAnalysisState *analysis, CELTEncoder *celt_enc, const void *pcm, const void *analysis_pcm, - int frame_size, int C, int Fs, int bitrate_bps, int delay_compensation, int lsb_depth, downmix_func downmix) -{ - int offset; - int pcm_len; - int LM = 3; - - pcm_len = frame_size - analysis->analysis_offset; - offset = 0; - do { - tonality_analysis(analysis, NULL, celt_enc, analysis_pcm, IMIN(480, pcm_len), offset, C, lsb_depth, downmix); - offset += 480; - pcm_len -= 480; - } while (pcm_len>0); - analysis->analysis_offset = frame_size; - - //return frame_size; -#ifndef FIXED_POINT - LM = optimize_framesize(pcm, frame_size, C, Fs, bitrate_bps, - analysis->prev_tonality, analysis->subframe_mem, delay_compensation, downmix); -#endif - while ((Fs/400<<LM)>frame_size) - LM--; - frame_size = (Fs/400<<LM); - //frame_size = st->Fs/50; - analysis->analysis_offset -= frame_size; - return frame_size; -} #endif 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) + unsigned char *data, opus_int32 out_data_bytes, int lsb_depth +#ifndef FIXED_POINT + , AnalysisInfo *analysis_info +#endif + ) { void *silk_enc; CELTEncoder *celt_enc; @@ -819,11 +795,7 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_ opus_val16 HB_gain; opus_int32 max_data_bytes; /* Max number of bytes we're allowed to use */ int total_buffer; - int perform_analysis=0; int orig_frame_size; -#ifndef FIXED_POINT - AnalysisInfo analysis_info; -#endif VARDECL(opus_val16, tmp_prefill); ALLOC_STACK; @@ -853,26 +825,12 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_ st->voice_ratio = -1; st->detected_bandwidth = 0; -#if 0 - perform_analysis = st->silk_mode.complexity >= 7 && st->Fs==48000; - if (perform_analysis) - frame_size = run_analysis(&st->analysis, celt_enc, pcm, pcm+st->channels*st->analysis.analysis_offset, frame_size, st->channels, st->Fs, st->bitrate_bps, delay_compensation, lsb_depth, downmix_float); -#endif - #ifndef FIXED_POINT - /* Only perform analysis up to 20-ms frames. Longer ones will be split if - they're in CELT-only mode. */ - analysis_info.valid = 0; - perform_analysis = st->silk_mode.complexity >= 7 && st->Fs==48000; - if (perform_analysis && frame_size <= st->Fs/50) + if (analysis_info->valid) { - tonality_get_info(&st->analysis, &analysis_info, frame_size); - if (analysis_info.valid) - { - if (st->signal_type == OPUS_AUTO) - st->voice_ratio = (int)floor(.5+100*(1-analysis_info.music_prob)); - st->detected_bandwidth = analysis_info.opus_bandwidth; - } + if (st->signal_type == OPUS_AUTO) + st->voice_ratio = (int)floor(.5+100*(1-analysis_info->music_prob)); + st->detected_bandwidth = analysis_info->opus_bandwidth; } #endif @@ -1182,7 +1140,7 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_ /* When switching from SILK/Hybrid to CELT, only ask for a switch at the last frame */ if (to_celt && i==nb_frames-1) 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); + 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_info); if (tmp_len<0) { RESTORE_STACK; @@ -1208,17 +1166,6 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_ RESTORE_STACK; return ret; } -#ifndef FIXED_POINT - /* FIXME: This needs to go */ - /* Perform analysis for 40-60 ms frames */ - if (perform_analysis && frame_size > st->Fs/50) - { - int nb_analysis = frame_size/(st->Fs/100); - //for (i=0;i<nb_analysis;i++) - // tonality_analysis(&st->analysis, &analysis_info, celt_enc, pcm+i*(st->Fs/100)*st->channels, 480, st->channels, lsb_depth, downmix_float); - st->voice_ratio = (int)floor(.5+100*(1-analysis_info.music_prob)); - } -#endif curr_bandwidth = st->bandwidth; /* Chooses the appropriate mode for speech @@ -1470,9 +1417,9 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_ #ifndef FIXED_POINT if (st->variable_duration && orig_frame_size != frame_size) { - bonus = (40*st->stream_channels+40)*(48000/frame_size-48000/orig_frame_size); - if (analysis_info.valid) - bonus = bonus*(1.f+.5*analysis_info.tonality); + bonus = (40*st->stream_channels+40)*(48000/frame_size-50); + if (analysis_info->valid) + bonus = bonus*(1.f+.5*analysis_info->tonality); } #endif celt_encoder_ctl(celt_enc, OPUS_SET_VBR(1)); @@ -1609,8 +1556,7 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_ if (ec_tell(&enc) <= 8*nb_compr_bytes) { #ifndef FIXED_POINT - if (perform_analysis) - celt_encoder_ctl(celt_enc, CELT_SET_ANALYSIS(&analysis_info)); + celt_encoder_ctl(celt_enc, CELT_SET_ANALYSIS(analysis_info)); #endif ret = celt_encode_with_ec(celt_enc, pcm_buf, frame_size, NULL, nb_compr_bytes, &enc); if (ret < 0) @@ -1737,13 +1683,14 @@ opus_int32 opus_encode(OpusEncoder *st, const opus_int16 *pcm, int frame_size, unsigned char *data, opus_int32 max_data_bytes) { int i, ret; - CELTEncoder *celt_enc; + const CELTMode *celt_mode; int delay_compensation; int lsb_depth; VARDECL(float, in); + AnalysisInfo analysis_info; ALLOC_STACK; - celt_enc = (CELTEncoder*)((char*)st+st->celt_enc_offset); + opus_encoder_ctl(st, CELT_GET_MODE(&celt_mode)); if (st->application == OPUS_APPLICATION_RESTRICTED_LOWDELAY) delay_compensation = 0; else @@ -1752,24 +1699,28 @@ opus_int32 opus_encode(OpusEncoder *st, const opus_int16 *pcm, int frame_size, lsb_depth = IMIN(16, st->lsb_depth); if (st->silk_mode.complexity >= 7 && st->Fs==48000) - frame_size = run_analysis(&st->analysis, celt_enc, pcm, pcm+st->channels*st->analysis.analysis_offset, frame_size, st->channels, st->Fs, st->bitrate_bps, delay_compensation, lsb_depth, downmix_int); + { + frame_size = run_analysis(&st->analysis, celt_mode, pcm, pcm+st->channels*st->analysis.analysis_offset, + frame_size, st->channels, st->Fs, st->bitrate_bps, delay_compensation, lsb_depth, downmix_int, &analysis_info); + } ALLOC(in, frame_size*st->channels, float); 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); + ret = opus_encode_native(st, in, frame_size, data, max_data_bytes, 16, &analysis_info); RESTORE_STACK; return ret; } opus_int32 opus_encode_float(OpusEncoder *st, const float *pcm, int frame_size, unsigned char *data, opus_int32 out_data_bytes) { - CELTEncoder *celt_enc; + const CELTMode *celt_mode; int delay_compensation; int lsb_depth; + AnalysisInfo analysis_info; - celt_enc = (CELTEncoder*)((char*)st+st->celt_enc_offset); + opus_encoder_ctl(st, CELT_GET_MODE(&celt_mode)); if (st->application == OPUS_APPLICATION_RESTRICTED_LOWDELAY) delay_compensation = 0; else @@ -1778,9 +1729,12 @@ opus_int32 opus_encode_float(OpusEncoder *st, const float *pcm, int frame_size, lsb_depth = IMIN(24, st->lsb_depth); if (st->silk_mode.complexity >= 7 && st->Fs==48000) - frame_size = run_analysis(&st->analysis, celt_enc, pcm, pcm+st->channels*st->analysis.analysis_offset, frame_size, st->channels, st->Fs, st->bitrate_bps, delay_compensation, lsb_depth, downmix_float); + { + frame_size = run_analysis(&st->analysis, celt_mode, pcm, pcm+st->channels*st->analysis.analysis_offset, + frame_size, st->channels, st->Fs, st->bitrate_bps, delay_compensation, lsb_depth, downmix_float, &analysis_info); + } - return opus_encode_native(st, pcm, frame_size, data, out_data_bytes, 24); + return opus_encode_native(st, pcm, frame_size, data, out_data_bytes, 24, &analysis_info); } #endif @@ -2092,6 +2046,15 @@ int opus_encoder_ctl(OpusEncoder *st, int request, ...) st->user_forced_mode = value; } break; + + case CELT_GET_MODE_REQUEST: + { + const CELTMode ** value = va_arg(ap, const CELTMode**); + if (value==0) + goto bad_arg; + celt_encoder_ctl(celt_enc, CELT_GET_MODE(value)); + } + break; default: /* fprintf(stderr, "unknown opus_encoder_ctl() request: %d", request);*/ ret = OPUS_UNIMPLEMENTED; diff --git a/src/opus_multistream_encoder.c b/src/opus_multistream_encoder.c index c5fb3669..be96efc4 100644 --- a/src/opus_multistream_encoder.c +++ b/src/opus_multistream_encoder.c @@ -36,8 +36,10 @@ #include <stdarg.h> #include "float_cast.h" #include "os_support.h" +#include "analysis.h" struct OpusMSEncoder { + TonalityAnalysisState analysis; ChannelLayout layout; int variable_duration; opus_int32 bitrate_bps; @@ -187,6 +189,7 @@ static int opus_multistream_encode_native int lsb_depth #ifndef FIXED_POINT , downmix_func downmix + , const void *pcm_analysis #endif ) { @@ -202,10 +205,15 @@ static int opus_multistream_encode_native int orig_frame_size; int coded_channels; opus_int32 channel_rate; + opus_int32 complexity; + AnalysisInfo analysis_info; + const CELTMode *celt_mode; ALLOC_STACK; ptr = (char*)st + align(sizeof(OpusMSEncoder)); opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs)); + opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_COMPLEXITY(&complexity)); + opus_encoder_ctl((OpusEncoder*)ptr, CELT_GET_MODE(&celt_mode)); if (400*frame_size < Fs) { @@ -213,23 +221,20 @@ static int opus_multistream_encode_native return OPUS_BAD_ARG; } orig_frame_size = IMIN(frame_size,Fs/50); - if (st->variable_duration) +#ifndef FIXED_POINT + if (complexity >= 7 && Fs==48000) { - int LM = 3; - int channels; 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; -#ifndef FIXED_POINT - LM = optimize_framesize(pcm, frame_size, channels, Fs, st->bitrate_bps, - 0.f, st->subframe_mem, delay_compensation, downmix); -#endif - while ((Fs/400<<LM)>frame_size) - LM--; - frame_size = (Fs/400<<LM); + + frame_size = run_analysis(&st->analysis, celt_mode, pcm, pcm_analysis, + frame_size, channels, Fs, st->bitrate_bps, delay_compensation, lsb_depth, downmix, &analysis_info); } +#endif /* Validate frame_size before using it to allocate stack space. This mirrors the checks in opus_encode[_float](). */ @@ -313,7 +318,7 @@ 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); + len = opus_encode_native(enc, buf, frame_size, tmp_data, curr_max, lsb_depth, &analysis_info); if (len<0) { RESTORE_STACK; @@ -412,8 +417,9 @@ int opus_multistream_encode_float opus_int32 max_data_bytes ) { + int channels = st->layout.nb_streams + st->layout.nb_coupled_streams; return opus_multistream_encode_native(st, opus_copy_channel_in_float, - pcm, frame_size, data, max_data_bytes, 24, downmix_float); + pcm, frame_size, data, max_data_bytes, 24, downmix_float, pcm+channels*st->analysis.analysis_offset); } int opus_multistream_encode( @@ -424,8 +430,9 @@ int opus_multistream_encode( opus_int32 max_data_bytes ) { + int channels = st->layout.nb_streams + st->layout.nb_coupled_streams; return opus_multistream_encode_native(st, opus_copy_channel_in_short, - pcm, frame_size, data, max_data_bytes, 16, downmix_int); + pcm, frame_size, data, max_data_bytes, 16, downmix_int, pcm+channels*st->analysis.analysis_offset); } #endif diff --git a/src/opus_private.h b/src/opus_private.h index e39e06f6..e615e295 100644 --- a/src/opus_private.h +++ b/src/opus_private.h @@ -31,6 +31,7 @@ #include "arch.h" #include "opus.h" +#include "celt.h" struct OpusRepacketizer { unsigned char toc; @@ -92,7 +93,11 @@ int optimize_framesize(const opus_val16 *x, int len, int C, opus_int32 Fs, int encode_size(int size, unsigned char *data); 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); + unsigned char *data, opus_int32 out_data_bytes, int lsb_depth +#ifndef FIXED_POINT + , AnalysisInfo *analysis_info +#endif + ); 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, int *packet_offset); |
