summaryrefslogtreecommitdiff
path: root/libavcodec
diff options
context:
space:
mode:
authorLynne <dev@lynne.ee>2019-03-15 14:35:03 +0000
committerCarl Eugen Hoyos <ceffmpeg@gmail.com>2019-04-01 00:19:14 +0200
commit0cea3ca8943b5a3f28a3672037f424b4d03853b8 (patch)
treec7056e3dca217790886df80a44d6ba5e2d24584c /libavcodec
parent5468c1d075166fa1a8fea217b07e30abc6bdc4b1 (diff)
opusdsp: create and move deemphasis and postfiltering from opus_celt
Diffstat (limited to 'libavcodec')
-rw-r--r--libavcodec/Makefile3
-rw-r--r--libavcodec/opus_celt.c53
-rw-r--r--libavcodec/opus_celt.h3
-rw-r--r--libavcodec/opusdsp.c61
-rw-r--r--libavcodec/opusdsp.h33
5 files changed, 109 insertions, 44 deletions
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index ad347ec0a2..de873c1643 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -496,7 +496,8 @@ OBJS-$(CONFIG_NELLYMOSER_ENCODER) += nellymoserenc.o nellymoser.o
OBJS-$(CONFIG_NUV_DECODER) += nuv.o rtjpeg.o
OBJS-$(CONFIG_ON2AVC_DECODER) += on2avc.o on2avcdata.o
OBJS-$(CONFIG_OPUS_DECODER) += opusdec.o opus.o opus_celt.o opus_rc.o \
- opus_pvq.o opus_silk.o opustab.o vorbis_data.o
+ opus_pvq.o opus_silk.o opustab.o vorbis_data.o \
+ opusdsp.o
OBJS-$(CONFIG_OPUS_ENCODER) += opusenc.o opus.o opus_rc.o opustab.o opus_pvq.o \
opusenc_psy.o
OBJS-$(CONFIG_PAF_AUDIO_DECODER) += pafaudio.o
diff --git a/libavcodec/opus_celt.c b/libavcodec/opus_celt.c
index 115dd8c63e..4655172b09 100644
--- a/libavcodec/opus_celt.c
+++ b/libavcodec/opus_celt.c
@@ -202,40 +202,10 @@ static void celt_postfilter_apply_transition(CeltBlock *block, float *data)
}
}
-static void celt_postfilter_apply(CeltBlock *block, float *data, int len)
-{
- const int T = block->pf_period;
- float g0, g1, g2;
- float x0, x1, x2, x3, x4;
- int i;
-
- if (block->pf_gains[0] == 0.0 || len <= 0)
- return;
-
- g0 = block->pf_gains[0];
- g1 = block->pf_gains[1];
- g2 = block->pf_gains[2];
-
- x4 = data[-T - 2];
- x3 = data[-T - 1];
- x2 = data[-T];
- x1 = data[-T + 1];
-
- for (i = 0; i < len; i++) {
- x0 = data[i - T + 2];
- data[i] += g0 * x2 +
- g1 * (x1 + x3) +
- g2 * (x0 + x4);
- x4 = x3;
- x3 = x2;
- x2 = x1;
- x1 = x0;
- }
-}
-
static void celt_postfilter(CeltFrame *f, CeltBlock *block)
{
int len = f->blocksize * f->blocks;
+ const int filter_len = len - 2 * CELT_OVERLAP;
celt_postfilter_apply_transition(block, block->buf + 1024);
@@ -247,8 +217,11 @@ static void celt_postfilter(CeltFrame *f, CeltBlock *block)
if (len > CELT_OVERLAP) {
celt_postfilter_apply_transition(block, block->buf + 1024 + CELT_OVERLAP);
- celt_postfilter_apply(block, block->buf + 1024 + 2 * CELT_OVERLAP,
- len - 2 * CELT_OVERLAP);
+
+ if (block->pf_gains[0] > FLT_EPSILON && filter_len > 0)
+ f->opusdsp.postfilter(block->buf + 1024 + 2 * CELT_OVERLAP,
+ block->pf_period, block->pf_gains,
+ filter_len);
block->pf_period_old = block->pf_period;
memcpy(block->pf_gains_old, block->pf_gains, sizeof(block->pf_gains));
@@ -462,7 +435,6 @@ int ff_celt_decode_frame(CeltFrame *f, OpusRangeCoder *rc,
/* transform and output for each output channel */
for (i = 0; i < f->output_channels; i++) {
CeltBlock *block = &f->block[i];
- float m = block->emph_coeff;
/* iMDCT and overlap-add */
for (j = 0; j < f->blocks; j++) {
@@ -480,14 +452,10 @@ int ff_celt_decode_frame(CeltFrame *f, OpusRangeCoder *rc,
/* postfilter */
celt_postfilter(f, block);
- /* deemphasis and output scaling */
- for (j = 0; j < frame_size; j++) {
- const float tmp = block->buf[1024 - frame_size + j] + m;
- m = tmp * CELT_EMPH_COEFF;
- output[i][j] = tmp;
- }
-
- block->emph_coeff = m;
+ /* deemphasis */
+ block->emph_coeff = f->opusdsp.deemphasis(output[i],
+ &block->buf[1024 - frame_size],
+ block->emph_coeff, frame_size);
}
if (channels == 1)
@@ -596,6 +564,7 @@ int ff_celt_init(AVCodecContext *avctx, CeltFrame **f, int output_channels,
goto fail;
}
+ ff_opus_dsp_init(&frm->opusdsp);
ff_celt_flush(frm);
*f = frm;
diff --git a/libavcodec/opus_celt.h b/libavcodec/opus_celt.h
index 9289a1867a..7c1c5316b9 100644
--- a/libavcodec/opus_celt.h
+++ b/libavcodec/opus_celt.h
@@ -28,6 +28,7 @@
#include "opus.h"
#include "opus_pvq.h"
+#include "opusdsp.h"
#include "mdct15.h"
#include "libavutil/float_dsp.h"
@@ -40,7 +41,6 @@
#define CELT_NORM_SCALE 16384
#define CELT_QTHETA_OFFSET 4
#define CELT_QTHETA_OFFSET_TWOPHASE 16
-#define CELT_EMPH_COEFF 0.85000610f
#define CELT_POSTFILTER_MINPERIOD 15
#define CELT_ENERGY_SILENCE (-28.0f)
@@ -96,6 +96,7 @@ struct CeltFrame {
AVFloatDSPContext *dsp;
CeltBlock block[2];
CeltPVQ *pvq;
+ OpusDSP opusdsp;
int channels;
int output_channels;
int apply_phase_inv;
diff --git a/libavcodec/opusdsp.c b/libavcodec/opusdsp.c
new file mode 100644
index 0000000000..615e7d6816
--- /dev/null
+++ b/libavcodec/opusdsp.c
@@ -0,0 +1,61 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "opusdsp.h"
+
+static void postfilter_c(float *data, int period, float *gains, int len)
+{
+ const float g0 = gains[0];
+ const float g1 = gains[1];
+ const float g2 = gains[2];
+
+ float x4 = data[-period - 2];
+ float x3 = data[-period - 1];
+ float x2 = data[-period + 0];
+ float x1 = data[-period + 1];
+
+ for (int i = 0; i < len; i++) {
+ float x0 = data[i - period + 2];
+ data[i] += g0 * x2 +
+ g1 * (x1 + x3) +
+ g2 * (x0 + x4);
+ x4 = x3;
+ x3 = x2;
+ x2 = x1;
+ x1 = x0;
+ }
+}
+
+static float deemphasis_c(float *y, float *x, float coeff, int len)
+{
+ float state = coeff;
+
+ for (int i = 0; i < len; i++) {
+ const float tmp = x[i] + state;
+ state = tmp * CELT_EMPH_COEFF;
+ y[i] = tmp;
+ }
+
+ return state;
+}
+
+av_cold void ff_opus_dsp_init(OpusDSP *ctx)
+{
+ ctx->postfilter = postfilter_c;
+ ctx->deemphasis = deemphasis_c;
+}
diff --git a/libavcodec/opusdsp.h b/libavcodec/opusdsp.h
new file mode 100644
index 0000000000..05bf2ba1a4
--- /dev/null
+++ b/libavcodec/opusdsp.h
@@ -0,0 +1,33 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVCODEC_OPUSDSP_H
+#define AVCODEC_OPUSDSP_H
+
+#include "libavutil/common.h"
+
+#define CELT_EMPH_COEFF 0.8500061035f
+
+typedef struct OpusDSP {
+ void (*postfilter)(float *data, int period, float *gains, int len);
+ float (*deemphasis)(float *out, float *in, float coeff, int len);
+} OpusDSP;
+
+void ff_opus_dsp_init(OpusDSP *ctx);
+
+#endif /* AVCODEC_OPUSDSP_H */