opus: add an option to toggle intensity stereo phase inversion

Due to a somewhat high volume of complains, phase inversion has
been made optional with RFC8251. This allows for better bass
frequency response when partially downmixing to play on systems
with an LFE speaker.

Signed-off-by: Rostislav Pehlivanov <atomnuker@gmail.com>
pull/272/head
Rostislav Pehlivanov 7 years ago
parent fe05f93013
commit 1b8649c2ce
  1. 2
      libavcodec/opus.h
  2. 4
      libavcodec/opus_celt.c
  3. 4
      libavcodec/opus_celt.h
  4. 1
      libavcodec/opus_pvq.c
  5. 17
      libavcodec/opusdec.c

@ -150,7 +150,9 @@ typedef struct ChannelMap {
} ChannelMap;
typedef struct OpusContext {
AVClass *av_class;
OpusStreamContext *streams;
int apply_phase_inv;
/* current output buffers for each streams */
float **out;

@ -997,7 +997,8 @@ void ff_celt_free(CeltFrame **f)
av_freep(f);
}
int ff_celt_init(AVCodecContext *avctx, CeltFrame **f, int output_channels)
int ff_celt_init(AVCodecContext *avctx, CeltFrame **f, int output_channels,
int apply_phase_inv)
{
CeltFrame *frm;
int i, ret;
@ -1014,6 +1015,7 @@ int ff_celt_init(AVCodecContext *avctx, CeltFrame **f, int output_channels)
frm->avctx = avctx;
frm->output_channels = output_channels;
frm->apply_phase_inv = apply_phase_inv;
for (i = 0; i < FF_ARRAY_ELEMS(frm->imdct); i++)
if ((ret = ff_mdct15_init(&frm->imdct[i], 1, i + 3, -1.0f/32768)) < 0)

@ -98,6 +98,7 @@ struct CeltFrame {
CeltPVQ *pvq;
int channels;
int output_channels;
int apply_phase_inv;
enum CeltBlockSize size;
int start_band;
@ -156,7 +157,8 @@ static av_always_inline void celt_renormalize_vector(float *X, int N, float gain
X[i] *= g;
}
int ff_celt_init(AVCodecContext *avctx, CeltFrame **f, int output_channels);
int ff_celt_init(AVCodecContext *avctx, CeltFrame **f, int output_channels,
int apply_phase_inv);
void ff_celt_free(CeltFrame **f);

@ -643,6 +643,7 @@ static av_always_inline uint32_t quant_band_template(CeltPVQ *pvq, CeltFrame *f,
}
} else {
inv = (b > 2 << 3 && f->remaining2 > 2 << 3) ? ff_opus_rc_dec_log(rc, 2) : 0;
inv = f->apply_phase_inv ? inv : 0;
}
itheta = 0;
}

@ -687,7 +687,7 @@ static av_cold int opus_decode_init(AVCodecContext *avctx)
if (ret < 0)
goto fail;
ret = ff_celt_init(avctx, &s->celt, s->output_channels);
ret = ff_celt_init(avctx, &s->celt, s->output_channels, c->apply_phase_inv);
if (ret < 0)
goto fail;
@ -712,9 +712,24 @@ fail:
return ret;
}
#define OFFSET(x) offsetof(OpusContext, x)
#define AD AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_DECODING_PARAM
static const AVOption opus_options[] = {
{ "apply_phase_inv", "Apply intensity stereo phase inversion", OFFSET(apply_phase_inv), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, AD },
{ NULL },
};
static const AVClass opus_class = {
.class_name = "Opus Decoder",
.item_name = av_default_item_name,
.option = opus_options,
.version = LIBAVUTIL_VERSION_INT,
};
AVCodec ff_opus_decoder = {
.name = "opus",
.long_name = NULL_IF_CONFIG_SMALL("Opus"),
.priv_class = &opus_class,
.type = AVMEDIA_TYPE_AUDIO,
.id = AV_CODEC_ID_OPUS,
.priv_data_size = sizeof(OpusContext),

Loading…
Cancel
Save