mirror of
https://github.com/xiph/opus.git
synced 2025-06-02 08:37:43 +00:00
Implements OPUS_{GET,SET}_LSB_DEPTH
This is used to avoid dynalloc doing silly things on periodic LSB patterns and to reduce the bitrate on near-silence.
This commit is contained in:
parent
c5880fe48b
commit
cf1053dc85
7 changed files with 114 additions and 27 deletions
53
celt/celt.c
53
celt/celt.c
|
@ -156,6 +156,7 @@ struct OpusCustomEncoder {
|
|||
int signalling;
|
||||
int constrained_vbr; /* If zero, VBR can do whatever it likes with the rate */
|
||||
int loss_rate;
|
||||
int lsb_depth;
|
||||
|
||||
/* Everything beyond this point gets cleared on a reset */
|
||||
#define ENCODER_RESET_START rng
|
||||
|
@ -187,6 +188,7 @@ struct OpusCustomEncoder {
|
|||
opus_int32 vbr_drift;
|
||||
opus_int32 vbr_offset;
|
||||
opus_int32 vbr_count;
|
||||
opus_val16 overlap_max;
|
||||
|
||||
#ifdef RESYNTH
|
||||
celt_sig syn_mem[2][2*MAX_PERIOD];
|
||||
|
@ -267,6 +269,7 @@ OPUS_CUSTOM_NOSTATIC int opus_custom_encoder_init(CELTEncoder *st, const CELTMod
|
|||
st->vbr = 0;
|
||||
st->force_intra = 0;
|
||||
st->complexity = 5;
|
||||
st->lsb_depth=24;
|
||||
|
||||
opus_custom_encoder_ctl(st, OPUS_RESET_STATE);
|
||||
|
||||
|
@ -987,6 +990,8 @@ int celt_encode_with_ec(CELTEncoder * restrict st, const opus_val16 * pcm, int f
|
|||
opus_val16 stereo_saving = 0;
|
||||
int pitch_change=0;
|
||||
opus_int32 tot_boost=0;
|
||||
opus_val16 sample_max;
|
||||
opus_val16 maxDepth;
|
||||
ALLOC_STACK;
|
||||
|
||||
tf_estimate = QCONST16(1.0f,14);
|
||||
|
@ -1104,6 +1109,9 @@ int celt_encode_with_ec(CELTEncoder * restrict st, const opus_val16 * pcm, int f
|
|||
|
||||
ALLOC(in, CC*(N+st->overlap), celt_sig);
|
||||
|
||||
sample_max=MAX16(st->overlap_max, celt_maxabs16(pcm, C*(N-st->mode->overlap)));
|
||||
st->overlap_max=celt_maxabs16(pcm+C*(N-st->mode->overlap), C*st->mode->overlap);
|
||||
sample_max=MAX16(sample_max, st->overlap_max);
|
||||
/* Find pitch period and gain */
|
||||
{
|
||||
VARDECL(celt_sig, _pre);
|
||||
|
@ -1143,13 +1151,17 @@ int celt_encode_with_ec(CELTEncoder * restrict st, const opus_val16 * pcm, int f
|
|||
*inp = tmp + st->preemph_memE[c];
|
||||
st->preemph_memE[c] = MULT16_32_Q15(st->mode->preemph[1], *inp)
|
||||
- MULT16_32_Q15(st->mode->preemph[0], tmp);
|
||||
silence = silence && *inp == 0;
|
||||
inp++;
|
||||
}
|
||||
OPUS_COPY(pre[c], prefilter_mem+c*COMBFILTER_MAXPERIOD, COMBFILTER_MAXPERIOD);
|
||||
OPUS_COPY(pre[c]+COMBFILTER_MAXPERIOD, in+c*(N+st->overlap)+st->overlap, N);
|
||||
} while (++c<CC);
|
||||
|
||||
#ifdef FIXED_POINT
|
||||
silence = (sample_max==0);
|
||||
#else
|
||||
silence = (sample_max <= (opus_val16)1/(1<<st->lsb_depth));
|
||||
#endif
|
||||
#ifdef FUZZING
|
||||
if ((rand()&0x3F)==0)
|
||||
silence = 1;
|
||||
|
@ -1413,10 +1425,12 @@ int celt_encode_with_ec(CELTEncoder * restrict st, const opus_val16 * pcm, int f
|
|||
for (i=0;i<st->mode->nbEBands;i++)
|
||||
offsets[i] = 0;
|
||||
/* Dynamic allocation code */
|
||||
maxDepth=-QCONST16(32.f, DB_SHIFT);
|
||||
/* Make sure that dynamic allocation can't make us bust the budget */
|
||||
if (effectiveBytes > 50 && LM>=1)
|
||||
{
|
||||
opus_val16 follower[42]={0};
|
||||
VARDECL(opus_val16, follower);
|
||||
ALLOC(follower, C*st->mode->nbEBands, opus_val16);
|
||||
c=0;do
|
||||
{
|
||||
follower[c*st->mode->nbEBands] = bandLogE2[c*st->mode->nbEBands];
|
||||
|
@ -1424,6 +1438,17 @@ int celt_encode_with_ec(CELTEncoder * restrict st, const opus_val16 * pcm, int f
|
|||
follower[c*st->mode->nbEBands+i] = MIN16(follower[c*st->mode->nbEBands+i-1]+QCONST16(1.5f,DB_SHIFT), bandLogE2[c*st->mode->nbEBands+i]);
|
||||
for (i=effEnd-2;i>=0;i--)
|
||||
follower[c*st->mode->nbEBands+i] = MIN16(follower[c*st->mode->nbEBands+i], MIN16(follower[c*st->mode->nbEBands+i+1]+QCONST16(2.f,DB_SHIFT), bandLogE2[c*st->mode->nbEBands+i]));
|
||||
for (i=0;i<st->end;i++)
|
||||
{
|
||||
opus_val16 noise_floor;
|
||||
/* Noise floor must take into account eMeans, the depth, the width of the bands
|
||||
and the preemphasis filter (approx. square of bark band ID) */
|
||||
noise_floor = MULT16_16(QCONST16(0.0625f, DB_SHIFT),st->mode->logN[i])
|
||||
+QCONST16(.5f,DB_SHIFT)+SHL16(9-st->lsb_depth,DB_SHIFT)-SHL16(eMeans[i],6)
|
||||
+MULT16_16(QCONST16(.0062,DB_SHIFT),(i+5)*(i+5));
|
||||
follower[c*st->mode->nbEBands+i] = MAX16(follower[c*st->mode->nbEBands+i], noise_floor);
|
||||
maxDepth = MAX16(maxDepth, bandLogE[i]-noise_floor);
|
||||
}
|
||||
} while (++c<C);
|
||||
if (C==2)
|
||||
{
|
||||
|
@ -1606,6 +1631,16 @@ int celt_encode_with_ec(CELTEncoder * restrict st, const opus_val16 * pcm, int f
|
|||
}
|
||||
#endif
|
||||
|
||||
{
|
||||
opus_int32 floor_depth;
|
||||
int bins;
|
||||
bins = st->mode->eBands[st->mode->nbEBands-2]<<LM;
|
||||
/*floor_depth = SHR32(MULT16_16((C*bins<<BITRES),celt_log2(SHL32(MAX16(1,sample_max),13))), DB_SHIFT);*/
|
||||
floor_depth = SHR32(MULT16_16((C*bins<<BITRES),maxDepth), DB_SHIFT);
|
||||
floor_depth = IMAX(floor_depth, new_target>>2);
|
||||
new_target = IMIN(new_target, floor_depth);
|
||||
/*printf("%f %d\n", maxDepth, floor_depth);*/
|
||||
}
|
||||
/* The current offset is removed from the target and the space used
|
||||
so far is added*/
|
||||
target=new_target+tell;
|
||||
|
@ -2004,6 +2039,20 @@ int opus_custom_encoder_ctl(CELTEncoder * restrict st, int request, ...)
|
|||
st->stream_channels = value;
|
||||
}
|
||||
break;
|
||||
case OPUS_SET_LSB_DEPTH_REQUEST:
|
||||
{
|
||||
opus_int32 value = va_arg(ap, opus_int32);
|
||||
if (value<8 || value>24)
|
||||
goto bad_arg;
|
||||
st->lsb_depth=value;
|
||||
}
|
||||
break;
|
||||
case OPUS_GET_LSB_DEPTH_REQUEST:
|
||||
{
|
||||
opus_int32 *value = va_arg(ap, opus_int32*);
|
||||
*value=st->lsb_depth;
|
||||
}
|
||||
break;
|
||||
case OPUS_RESET_STATE:
|
||||
{
|
||||
int i;
|
||||
|
|
|
@ -43,6 +43,33 @@
|
|||
|
||||
unsigned isqrt32(opus_uint32 _val);
|
||||
|
||||
#ifndef OVERRIDE_CELT_MAXABS16
|
||||
static inline opus_val16 celt_maxabs16(const opus_val16 *x, int len)
|
||||
{
|
||||
int i;
|
||||
opus_val16 maxval = 0;
|
||||
for (i=0;i<len;i++)
|
||||
maxval = MAX16(maxval, ABS16(x[i]));
|
||||
return maxval;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef OVERRIDE_CELT_MAXABS32
|
||||
#ifdef FIXED_POINT
|
||||
static inline opus_val32 celt_maxabs32(const opus_val32 *x, int len)
|
||||
{
|
||||
int i;
|
||||
opus_val32 maxval = 0;
|
||||
for (i=0;i<len;i++)
|
||||
maxval = MAX32(maxval, ABS32(x[i]));
|
||||
return maxval;
|
||||
}
|
||||
#else
|
||||
#define celt_maxabs32(x,len) celt_maxabs16(x,len)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef FIXED_POINT
|
||||
|
||||
#define PI 3.141592653f
|
||||
|
@ -117,27 +144,6 @@ static inline opus_int16 celt_ilog2(opus_int32 x)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifndef OVERRIDE_CELT_MAXABS16
|
||||
static inline opus_val16 celt_maxabs16(opus_val16 *x, int len)
|
||||
{
|
||||
int i;
|
||||
opus_val16 maxval = 0;
|
||||
for (i=0;i<len;i++)
|
||||
maxval = MAX16(maxval, ABS16(x[i]));
|
||||
return maxval;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef OVERRIDE_CELT_MAXABS32
|
||||
static inline opus_val32 celt_maxabs32(opus_val32 *x, int len)
|
||||
{
|
||||
int i;
|
||||
opus_val32 maxval = 0;
|
||||
for (i=0;i<len;i++)
|
||||
maxval = MAX32(maxval, ABS32(x[i]));
|
||||
return maxval;
|
||||
}
|
||||
#endif
|
||||
|
||||
/** Integer log in base2. Defined for zero, but not for negative numbers */
|
||||
static inline opus_int16 celt_zlog2(opus_val32 x)
|
||||
|
|
|
@ -40,8 +40,8 @@
|
|||
#include "rate.h"
|
||||
|
||||
#ifdef FIXED_POINT
|
||||
/* Mean energy in each band quantized in Q6 */
|
||||
static const signed char eMeans[25] = {
|
||||
/* Mean energy in each band quantized in Q4 */
|
||||
const signed char eMeans[25] = {
|
||||
103,100, 92, 85, 81,
|
||||
77, 72, 70, 78, 75,
|
||||
73, 71, 78, 74, 69,
|
||||
|
@ -49,8 +49,8 @@ static const signed char eMeans[25] = {
|
|||
60, 60, 60, 60, 60
|
||||
};
|
||||
#else
|
||||
/* Mean energy in each band quantized in Q6 and converted back to float */
|
||||
static const opus_val16 eMeans[25] = {
|
||||
/* Mean energy in each band quantized in Q4 and converted back to float */
|
||||
const opus_val16 eMeans[25] = {
|
||||
6.437500f, 6.250000f, 5.750000f, 5.312500f, 5.062500f,
|
||||
4.812500f, 4.500000f, 4.375000f, 4.875000f, 4.687500f,
|
||||
4.562500f, 4.437500f, 4.875000f, 4.625000f, 4.312500f,
|
||||
|
|
|
@ -35,6 +35,12 @@
|
|||
#include "entdec.h"
|
||||
#include "mathops.h"
|
||||
|
||||
#ifdef FIXED_POINT
|
||||
extern const signed char eMeans[25];
|
||||
#else
|
||||
extern const opus_val16 eMeans[25];
|
||||
#endif
|
||||
|
||||
void amp2Log2(const CELTMode *m, int effEnd, int end,
|
||||
celt_ener *bandE, opus_val16 *bandLogE, int C);
|
||||
|
||||
|
|
|
@ -130,6 +130,8 @@ extern "C" {
|
|||
#define OPUS_GET_PITCH_REQUEST 4033
|
||||
#define OPUS_SET_GAIN_REQUEST 4034
|
||||
#define OPUS_GET_GAIN_REQUEST 4045
|
||||
#define OPUS_SET_LSB_DEPTH_REQUEST 4036
|
||||
#define OPUS_GET_LSB_DEPTH_REQUEST 4037
|
||||
|
||||
/* Macros to trigger compilation errors when the wrong types are provided to a CTL */
|
||||
#define __opus_check_int(x) (((void)((x) == (opus_int32)0)), (opus_int32)(x))
|
||||
|
@ -440,6 +442,17 @@ extern "C" {
|
|||
* @hideinitializer */
|
||||
#define OPUS_GET_BANDWIDTH(x) OPUS_GET_BANDWIDTH_REQUEST, __opus_check_int_ptr(x)
|
||||
|
||||
/** Configures the depth of signal being encoded.
|
||||
* This is a hint which helps the encoder identify silence and near-silence.
|
||||
* The supported values are between 8 and 24 (default)
|
||||
* @param[in] x <tt>opus_int32</tt>: Input precision
|
||||
* @hideinitializer */
|
||||
#define OPUS_SET_LSB_DEPTH(x) OPUS_SET_LSB_DEPTH_REQUEST, __opus_check_int(x)
|
||||
/** Gets the encoder's configured signal depth. @see OPUS_SET_LSB_DEPTH
|
||||
*
|
||||
* @param[out] x <tt>opus_int32*</tt>: Input precision
|
||||
* @hideinitializer */
|
||||
#define OPUS_GET_LSB_DEPTH(x) OPUS_GET_LSB_DEPTH_REQUEST, __opus_check_int_ptr(x)
|
||||
/**@}*/
|
||||
|
||||
/** @defgroup opus_decoderctls Decoder related CTLs
|
||||
|
|
|
@ -498,6 +498,7 @@ int main(int argc, char *argv[])
|
|||
opus_encoder_ctl(enc, OPUS_SET_PACKET_LOSS_PERC(packet_loss_perc));
|
||||
|
||||
opus_encoder_ctl(enc, OPUS_GET_LOOKAHEAD(&skip));
|
||||
opus_encoder_ctl(enc, OPUS_SET_LSB_DEPTH(16));
|
||||
}
|
||||
if (!encode_only)
|
||||
{
|
||||
|
|
|
@ -1616,6 +1616,18 @@ int opus_encoder_ctl(OpusEncoder *st, int request, ...)
|
|||
*value = st->rangeFinal;
|
||||
}
|
||||
break;
|
||||
case OPUS_SET_LSB_DEPTH_REQUEST:
|
||||
{
|
||||
opus_int32 value = va_arg(ap, opus_int32);
|
||||
ret = celt_encoder_ctl(celt_enc, OPUS_SET_LSB_DEPTH(value));
|
||||
}
|
||||
break;
|
||||
case OPUS_GET_LSB_DEPTH_REQUEST:
|
||||
{
|
||||
opus_int32 *value = va_arg(ap, opus_int32*);
|
||||
celt_encoder_ctl(celt_enc, OPUS_GET_LSB_DEPTH(value));
|
||||
}
|
||||
break;
|
||||
case OPUS_RESET_STATE:
|
||||
{
|
||||
void *silk_enc;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue