Index: src/opus_multistream_encoder.c |
diff --git a/src/opus_multistream_encoder.c b/src/opus_multistream_encoder.c |
index 900c4f4c285284c36449c0f62ffebb50d3f78e65..49e27913ee0cd64887df8e3a04eb24885a3806dc 100644 |
--- a/src/opus_multistream_encoder.c |
+++ b/src/opus_multistream_encoder.c |
@@ -76,7 +76,7 @@ struct OpusMSEncoder { |
int variable_duration; |
int surround; |
opus_int32 bitrate_bps; |
- opus_val32 subframe_mem[3]; |
+ float subframe_mem[3]; |
/* Encoder states go here */ |
/* then opus_val32 window_mem[channels*120]; */ |
/* then opus_val32 preemph_mem[channels]; */ |
@@ -205,7 +205,7 @@ static opus_val16 logSum(opus_val16 a, opus_val16 b) |
low = SHR32(diff, DB_SHIFT-1); |
frac = SHL16(diff - SHL16(low, DB_SHIFT-1), 16-DB_SHIFT); |
#else |
- low = floor(2*diff); |
+ low = (int)floor(2*diff); |
frac = 2*diff - low; |
#endif |
return max + diff_table[low] + MULT16_16_Q15(frac, SUB16(diff_table[low+1], diff_table[low])); |
@@ -238,7 +238,7 @@ void surround_analysis(const CELTMode *celt_mode, const void *pcm, opus_val16 *b |
upsample = resampling_factor(rate); |
frame_size = len*upsample; |
- for (LM=0;LM<=celt_mode->maxLM;LM++) |
+ for (LM=0;LM<celt_mode->maxLM;LM++) |
if (celt_mode->shortMdctSize<<LM==frame_size) |
break; |
@@ -256,7 +256,7 @@ void surround_analysis(const CELTMode *celt_mode, const void *pcm, opus_val16 *b |
{ |
OPUS_COPY(in, mem+c*overlap, overlap); |
(*copy_channel_in)(x, 1, pcm, channels, c, len); |
- preemphasis(x, in+overlap, frame_size, 1, upsample, celt_mode->preemph, preemph_mem+c, 0); |
+ celt_preemphasis(x, in+overlap, frame_size, 1, upsample, celt_mode->preemph, preemph_mem+c, 0); |
clt_mdct_forward(&celt_mode->mdct, in, freq, celt_mode->window, overlap, celt_mode->maxLM-LM, 1); |
if (upsample != 1) |
{ |
@@ -613,10 +613,11 @@ static void surround_rate_allocation( |
stream_offset = 20000; |
else |
stream_offset = st->bitrate_bps/st->layout.nb_channels/2; |
+ stream_offset += 60*(Fs/frame_size-50); |
/* We start by giving each stream (coupled or uncoupled) the same bitrate. |
This models the main saving of coupled channels over uncoupled. */ |
/* The LFE stream is an exception to the above and gets fewer bits. */ |
- lfe_offset = 3500; |
+ lfe_offset = 3500 + 60*(Fs/frame_size-50); |
/* Coupled streams get twice the mono rate after the first 20 kb/s. */ |
coupled_ratio = 512; |
/* Should depend on the bitrate, for now we assume LFE gets 1/8 the bits of mono */ |
@@ -686,7 +687,7 @@ static int opus_multistream_encode_native |
VARDECL(opus_val16, bandSMR); |
unsigned char tmp_data[MS_FRAME_TMP]; |
OpusRepacketizer rp; |
- opus_int32 complexity; |
+ opus_int32 vbr; |
const CELTMode *celt_mode; |
opus_int32 bitrates[256]; |
opus_val16 bandLogE[42]; |
@@ -703,7 +704,7 @@ static int opus_multistream_encode_native |
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, OPUS_GET_VBR(&vbr)); |
opus_encoder_ctl((OpusEncoder*)ptr, CELT_GET_MODE(&celt_mode)); |
{ |
@@ -715,7 +716,11 @@ static int opus_multistream_encode_native |
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); |
+ delay_compensation, downmix |
+#ifndef DISABLE_FLOAT_API |
+ , st->subframe_mem |
+#endif |
+ ); |
} |
if (400*frame_size < Fs) |
@@ -751,6 +756,9 @@ static int opus_multistream_encode_native |
/* Compute bitrate allocation between streams (this could be a lot better) */ |
surround_rate_allocation(st, bitrates, frame_size); |
+ if (!vbr) |
+ max_data_bytes = IMIN(max_data_bytes, 3*st->bitrate_bps/(3*8*Fs/frame_size)); |
+ |
ptr = (char*)st + align(sizeof(OpusMSEncoder)); |
for (s=0;s<st->layout.nb_streams;s++) |
{ |
@@ -767,11 +775,11 @@ static int opus_multistream_encode_native |
equiv_rate = st->bitrate_bps; |
if (frame_size*50 < Fs) |
equiv_rate -= 60*(Fs/frame_size - 50)*st->layout.nb_channels; |
- if (equiv_rate > 112000) |
+ if (equiv_rate > 10000*st->layout.nb_channels) |
opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_FULLBAND)); |
- else if (equiv_rate > 76000) |
+ else if (equiv_rate > 7000*st->layout.nb_channels) |
opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_SUPERWIDEBAND)); |
- else if (equiv_rate > 48000) |
+ else if (equiv_rate > 5000*st->layout.nb_channels) |
opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_WIDEBAND)); |
else |
opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_NARROWBAND)); |
@@ -838,6 +846,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); |
+ if (!vbr && s == st->layout.nb_streams-1) |
+ opus_encoder_ctl(enc, OPUS_SET_BITRATE(curr_max*(8*Fs/frame_size))); |
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) |
@@ -849,14 +859,14 @@ static int opus_multistream_encode_native |
while taking into account the fact that the encoder can now return |
more than one frame at a time (e.g. 60 ms CELT-only) */ |
opus_repacketizer_cat(&rp, tmp_data, len); |
- len = opus_repacketizer_out_range_impl(&rp, 0, opus_repacketizer_get_nb_frames(&rp), data, max_data_bytes-tot_size, s != st->layout.nb_streams-1); |
+ len = opus_repacketizer_out_range_impl(&rp, 0, opus_repacketizer_get_nb_frames(&rp), |
+ data, max_data_bytes-tot_size, s != st->layout.nb_streams-1, !vbr && s == st->layout.nb_streams-1); |
data += len; |
tot_size += len; |
} |
/*printf("\n");*/ |
RESTORE_STACK; |
return tot_size; |
- |
} |
#if !defined(DISABLE_FLOAT_API) |
@@ -1018,6 +1028,7 @@ int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...) |
case OPUS_GET_SAMPLE_RATE_REQUEST: |
case OPUS_GET_INBAND_FEC_REQUEST: |
case OPUS_GET_FORCE_CHANNELS_REQUEST: |
+ case OPUS_GET_PREDICTION_DISABLED_REQUEST: |
{ |
OpusEncoder *enc; |
/* For int32* GET params, just query the first stream */ |
@@ -1063,6 +1074,7 @@ int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...) |
case OPUS_SET_DTX_REQUEST: |
case OPUS_SET_FORCE_MODE_REQUEST: |
case OPUS_SET_FORCE_CHANNELS_REQUEST: |
+ case OPUS_SET_PREDICTION_DISABLED_REQUEST: |
{ |
int s; |
/* This works for int32 params */ |
@@ -1121,6 +1133,29 @@ int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...) |
*value = st->variable_duration; |
} |
break; |
+ case OPUS_RESET_STATE: |
+ { |
+ int s; |
+ st->subframe_mem[0] = st->subframe_mem[1] = st->subframe_mem[2] = 0; |
+ if (st->surround) |
+ { |
+ OPUS_CLEAR(ms_get_preemph_mem(st), st->layout.nb_channels); |
+ OPUS_CLEAR(ms_get_window_mem(st), st->layout.nb_channels*120); |
+ } |
+ for (s=0;s<st->layout.nb_streams;s++) |
+ { |
+ OpusEncoder *enc; |
+ enc = (OpusEncoder*)ptr; |
+ if (s < st->layout.nb_coupled_streams) |
+ ptr += align(coupled_size); |
+ else |
+ ptr += align(mono_size); |
+ ret = opus_encoder_ctl(enc, OPUS_RESET_STATE); |
+ if (ret != OPUS_OK) |
+ break; |
+ } |
+ } |
+ break; |
default: |
ret = OPUS_UNIMPLEMENTED; |
break; |