Skip to content

Commit b08c4ca

Browse files
committed
Surround: Better LFE handling
Forces CELT-only mode for LFE (despite the rate) and "locks" most of the CELT analysis: - No transient or TF - Band boost on first band - Only first two bands get PVQ bits - Forced energy decay after the first two bands
1 parent 1b72386 commit b08c4ca

File tree

6 files changed

+48
-16
lines changed

6 files changed

+48
-16
lines changed

celt/celt.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ typedef struct {
107107
#define CELT_SET_ANALYSIS_REQUEST 10022
108108
#define CELT_SET_ANALYSIS(x) CELT_SET_ANALYSIS_REQUEST, __celt_check_analysis_ptr(x)
109109

110-
#define OPUS_SET_LFE_REQUEST 10022
110+
#define OPUS_SET_LFE_REQUEST 10024
111111
#define OPUS_SET_LFE(x) OPUS_SET_LFE_REQUEST, __opus_check_int(x)
112112

113113
/* Encoder stuff */

celt/celt_encoder.c

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ struct OpusCustomEncoder {
7474
int loss_rate;
7575
int lsb_depth;
7676
int variable_duration;
77+
int lfe;
7778

7879
/* Everything beyond this point gets cleared on a reset */
7980
#define ENCODER_RESET_START rng
@@ -869,7 +870,7 @@ static int stereo_analysis(const CELTMode *m, const celt_norm *X,
869870
static opus_val16 dynalloc_analysis(const opus_val16 *bandLogE, const opus_val16 *bandLogE2,
870871
int nbEBands, int start, int end, int C, int *offsets, int lsb_depth, const opus_int16 *logN,
871872
int isTransient, int vbr, int constrained_vbr, const opus_int16 *eBands, int LM,
872-
int effectiveBytes, opus_int32 *tot_boost_)
873+
int effectiveBytes, opus_int32 *tot_boost_, int lfe)
873874
{
874875
int i, c;
875876
opus_int32 tot_boost=0;
@@ -897,7 +898,7 @@ static opus_val16 dynalloc_analysis(const opus_val16 *bandLogE, const opus_val16
897898
maxDepth = MAX16(maxDepth, bandLogE[c*nbEBands+i]-noise_floor[i]);
898899
} while (++c<C);
899900
/* Make sure that dynamic allocation can't make us bust the budget */
900-
if (effectiveBytes > 50 && LM>=1)
901+
if (effectiveBytes > 50 && LM>=1 && !lfe)
901902
{
902903
int last=0;
903904
c=0;do
@@ -1356,7 +1357,7 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm,
13561357

13571358
isTransient = 0;
13581359
shortBlocks = 0;
1359-
if (st->complexity >= 1)
1360+
if (st->complexity >= 1 && !st->lfe)
13601361
{
13611362
isTransient = transient_analysis(in, N+st->overlap, CC,
13621363
&tf_estimate, &tf_chan);
@@ -1429,7 +1430,7 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm,
14291430

14301431
ALLOC(tf_res, nbEBands, int);
14311432
/* Disable variable tf resolution for hybrid and at very low bitrate */
1432-
if (effectiveBytes>=15*C && st->start==0 && st->complexity>=2)
1433+
if (effectiveBytes>=15*C && st->start==0 && st->complexity>=2 && !st->lfe)
14331434
{
14341435
int lambda;
14351436
if (effectiveBytes<40)
@@ -1455,7 +1456,7 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm,
14551456
quant_coarse_energy(mode, st->start, st->end, effEnd, bandLogE,
14561457
oldBandE, total_bits, error, enc,
14571458
C, LM, nbAvailableBytes, st->force_intra,
1458-
&st->delayedIntra, st->complexity >= 4, st->loss_rate);
1459+
&st->delayedIntra, st->complexity >= 4, st->loss_rate, st->lfe);
14591460

14601461
tf_encode(st->start, st->end, isTransient, tf_res, LM, tf_select, enc);
14611462

@@ -1494,7 +1495,10 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm,
14941495

14951496
maxDepth = dynalloc_analysis(bandLogE, bandLogE2, nbEBands, st->start, st->end, C, offsets,
14961497
st->lsb_depth, mode->logN, isTransient, st->vbr, st->constrained_vbr,
1497-
eBands, LM, effectiveBytes, &tot_boost);
1498+
eBands, LM, effectiveBytes, &tot_boost, st->lfe);
1499+
/* For LFE, everything interesting is in the first band */
1500+
if (st->lfe)
1501+
offsets[0] = IMIN(8, effectiveBytes/3);
14981502
ALLOC(cap, nbEBands, int);
14991503
init_caps(mode,cap,LM,C);
15001504

@@ -1560,7 +1564,10 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm,
15601564
alloc_trim = 5;
15611565
if (tell+(6<<BITRES) <= total_bits - total_boost)
15621566
{
1563-
alloc_trim = alloc_trim_analysis(mode, X, bandLogE,
1567+
if (st->lfe)
1568+
alloc_trim = 5;
1569+
else
1570+
alloc_trim = alloc_trim_analysis(mode, X, bandLogE,
15641571
st->end, LM, C, N, &st->analysis, &st->stereo_saving, tf_estimate, st->intensity);
15651572
ec_enc_icdf(enc, alloc_trim, trim_icdf, 7);
15661573
tell = ec_tell_frac(enc);
@@ -1738,6 +1745,8 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm,
17381745
if (st->analysis.valid)
17391746
signalBandwidth = st->analysis.bandwidth;
17401747
#endif
1748+
if (st->lfe)
1749+
signalBandwidth = 1;
17411750
codedBands = compute_allocation(mode, st->start, st->end, offsets, cap,
17421751
alloc_trim, &st->intensity, &dual_stereo, bits, &balance, pulses,
17431752
fine_quant, fine_priority, C, LM, enc, 1, st->lastCodedBands, signalBandwidth);
@@ -2127,6 +2136,12 @@ int opus_custom_encoder_ctl(CELTEncoder * OPUS_RESTRICT st, int request, ...)
21272136
*value=st->rng;
21282137
}
21292138
break;
2139+
case OPUS_SET_LFE_REQUEST:
2140+
{
2141+
opus_int32 value = va_arg(ap, opus_int32);
2142+
st->lfe = value;
2143+
}
2144+
break;
21302145
default:
21312146
goto bad_request;
21322147
}

celt/quant_bands.c

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ static int quant_coarse_energy_impl(const CELTMode *m, int start, int end,
157157
const opus_val16 *eBands, opus_val16 *oldEBands,
158158
opus_int32 budget, opus_int32 tell,
159159
const unsigned char *prob_model, opus_val16 *error, ec_enc *enc,
160-
int C, int LM, int intra, opus_val16 max_decay)
160+
int C, int LM, int intra, opus_val16 max_decay, int lfe)
161161
{
162162
int i, c;
163163
int badness = 0;
@@ -222,6 +222,8 @@ static int quant_coarse_energy_impl(const CELTMode *m, int start, int end,
222222
if (bits_left < 16)
223223
qi = IMAX(-1, qi);
224224
}
225+
if (lfe && i>=2)
226+
qi = IMIN(qi, 0);
225227
if (budget-tell >= 15)
226228
{
227229
int pi;
@@ -253,13 +255,13 @@ static int quant_coarse_energy_impl(const CELTMode *m, int start, int end,
253255
prev[c] = prev[c] + SHL32(q,7) - MULT16_16(beta,PSHR32(q,8));
254256
} while (++c < C);
255257
}
256-
return badness;
258+
return lfe ? 0 : badness;
257259
}
258260

259261
void quant_coarse_energy(const CELTMode *m, int start, int end, int effEnd,
260262
const opus_val16 *eBands, opus_val16 *oldEBands, opus_uint32 budget,
261263
opus_val16 *error, ec_enc *enc, int C, int LM, int nbAvailableBytes,
262-
int force_intra, opus_val32 *delayedIntra, int two_pass, int loss_rate)
264+
int force_intra, opus_val32 *delayedIntra, int two_pass, int loss_rate, int lfe)
263265
{
264266
int intra;
265267
opus_val16 max_decay;
@@ -289,6 +291,8 @@ void quant_coarse_energy(const CELTMode *m, int start, int end, int effEnd,
289291
max_decay = MIN32(max_decay, .125f*nbAvailableBytes);
290292
#endif
291293
}
294+
if (lfe)
295+
max_decay=3;
292296
enc_start_state = *enc;
293297

294298
ALLOC(oldEBands_intra, C*m->nbEBands, opus_val16);
@@ -298,7 +302,7 @@ void quant_coarse_energy(const CELTMode *m, int start, int end, int effEnd,
298302
if (two_pass || intra)
299303
{
300304
badness1 = quant_coarse_energy_impl(m, start, end, eBands, oldEBands_intra, budget,
301-
tell, e_prob_model[LM][1], error_intra, enc, C, LM, 1, max_decay);
305+
tell, e_prob_model[LM][1], error_intra, enc, C, LM, 1, max_decay, lfe);
302306
}
303307

304308
if (!intra)
@@ -325,7 +329,7 @@ void quant_coarse_energy(const CELTMode *m, int start, int end, int effEnd,
325329
*enc = enc_start_state;
326330

327331
badness2 = quant_coarse_energy_impl(m, start, end, eBands, oldEBands, budget,
328-
tell, e_prob_model[LM][intra], error, enc, C, LM, 0, max_decay);
332+
tell, e_prob_model[LM][intra], error, enc, C, LM, 0, max_decay, lfe);
329333

330334
if (two_pass && (badness1 < badness2 || (badness1 == badness2 && ((opus_int32)ec_tell_frac(enc))+intra_bias > tell_intra)))
331335
{

celt/quant_bands.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ void quant_coarse_energy(const CELTMode *m, int start, int end, int effEnd,
5151
const opus_val16 *eBands, opus_val16 *oldEBands, opus_uint32 budget,
5252
opus_val16 *error, ec_enc *enc, int C, int LM,
5353
int nbAvailableBytes, int force_intra, opus_val32 *delayedIntra,
54-
int two_pass, int loss_rate);
54+
int two_pass, int loss_rate, int lfe);
5555

5656
void quant_fine_energy(const CELTMode *m, int start, int end, opus_val16 *oldEBands, opus_val16 *error, int *fine_quant, ec_enc *enc, int C);
5757

src/opus_encoder.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ struct OpusEncoder {
7878
opus_int32 user_bitrate_bps;
7979
int lsb_depth;
8080
int encoder_buffer;
81+
int lfe;
8182

8283
#define OPUS_ENCODER_RESET_START stream_channels
8384
int stream_channels;
@@ -1234,6 +1235,11 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_
12341235
/* CELT mode doesn't support mediumband, use wideband instead */
12351236
if (st->mode == MODE_CELT_ONLY && st->bandwidth == OPUS_BANDWIDTH_MEDIUMBAND)
12361237
st->bandwidth = OPUS_BANDWIDTH_WIDEBAND;
1238+
if (st->lfe)
1239+
{
1240+
st->bandwidth = OPUS_BANDWIDTH_NARROWBAND;
1241+
st->mode = MODE_CELT_ONLY;
1242+
}
12371243

12381244
/* Can't support higher than wideband for >20 ms frames */
12391245
if (frame_size > st->Fs/50 && (st->mode == MODE_CELT_ONLY || st->bandwidth > OPUS_BANDWIDTH_WIDEBAND))
@@ -2203,6 +2209,13 @@ int opus_encoder_ctl(OpusEncoder *st, int request, ...)
22032209
st->user_forced_mode = value;
22042210
}
22052211
break;
2212+
case OPUS_SET_LFE_REQUEST:
2213+
{
2214+
opus_int32 value = va_arg(ap, opus_int32);
2215+
st->lfe = value;
2216+
celt_encoder_ctl(celt_enc, OPUS_SET_LFE(value));
2217+
}
2218+
break;
22062219

22072220
case CELT_GET_MODE_REQUEST:
22082221
{

src/opus_multistream_encoder.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,7 @@ static void surround_rate_allocation(
329329
int total = ((st->layout.nb_streams-st->layout.nb_coupled_streams-(st->lfe_stream!=-1))<<8) /* mono */
330330
+ coupled_ratio*st->layout.nb_coupled_streams /* stereo */
331331
+ (st->lfe_stream!=-1)*lfe_ratio;
332-
channel_rate = 256*st->bitrate_bps/total;
332+
channel_rate = 256*(st->bitrate_bps-2000)/total;
333333
}
334334
#ifndef FIXED_POINT
335335
if (st->variable_duration==OPUS_FRAMESIZE_VARIABLE && frame_size != Fs/50)
@@ -347,7 +347,7 @@ static void surround_rate_allocation(
347347
else if (i!=st->lfe_stream)
348348
rate[i] = channel_rate;
349349
else
350-
rate[i] = channel_rate*lfe_ratio>>8;
350+
rate[i] = 2000+(channel_rate*lfe_ratio>>8);
351351
}
352352

353353

0 commit comments

Comments
 (0)