mirror of https://git.ffmpeg.org/ffmpeg.git
opusdsp: create and move deemphasis and postfiltering from opus_celt
This commit is contained in:
parent
5468c1d075
commit
0cea3ca894
|
@ -496,7 +496,8 @@ OBJS-$(CONFIG_NELLYMOSER_ENCODER) += nellymoserenc.o nellymoser.o
|
||||||
OBJS-$(CONFIG_NUV_DECODER) += nuv.o rtjpeg.o
|
OBJS-$(CONFIG_NUV_DECODER) += nuv.o rtjpeg.o
|
||||||
OBJS-$(CONFIG_ON2AVC_DECODER) += on2avc.o on2avcdata.o
|
OBJS-$(CONFIG_ON2AVC_DECODER) += on2avc.o on2avcdata.o
|
||||||
OBJS-$(CONFIG_OPUS_DECODER) += opusdec.o opus.o opus_celt.o opus_rc.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 \
|
OBJS-$(CONFIG_OPUS_ENCODER) += opusenc.o opus.o opus_rc.o opustab.o opus_pvq.o \
|
||||||
opusenc_psy.o
|
opusenc_psy.o
|
||||||
OBJS-$(CONFIG_PAF_AUDIO_DECODER) += pafaudio.o
|
OBJS-$(CONFIG_PAF_AUDIO_DECODER) += pafaudio.o
|
||||||
|
|
|
@ -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)
|
static void celt_postfilter(CeltFrame *f, CeltBlock *block)
|
||||||
{
|
{
|
||||||
int len = f->blocksize * f->blocks;
|
int len = f->blocksize * f->blocks;
|
||||||
|
const int filter_len = len - 2 * CELT_OVERLAP;
|
||||||
|
|
||||||
celt_postfilter_apply_transition(block, block->buf + 1024);
|
celt_postfilter_apply_transition(block, block->buf + 1024);
|
||||||
|
|
||||||
|
@ -247,8 +217,11 @@ static void celt_postfilter(CeltFrame *f, CeltBlock *block)
|
||||||
|
|
||||||
if (len > CELT_OVERLAP) {
|
if (len > CELT_OVERLAP) {
|
||||||
celt_postfilter_apply_transition(block, block->buf + 1024 + 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;
|
block->pf_period_old = block->pf_period;
|
||||||
memcpy(block->pf_gains_old, block->pf_gains, sizeof(block->pf_gains));
|
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 */
|
/* transform and output for each output channel */
|
||||||
for (i = 0; i < f->output_channels; i++) {
|
for (i = 0; i < f->output_channels; i++) {
|
||||||
CeltBlock *block = &f->block[i];
|
CeltBlock *block = &f->block[i];
|
||||||
float m = block->emph_coeff;
|
|
||||||
|
|
||||||
/* iMDCT and overlap-add */
|
/* iMDCT and overlap-add */
|
||||||
for (j = 0; j < f->blocks; j++) {
|
for (j = 0; j < f->blocks; j++) {
|
||||||
|
@ -480,14 +452,10 @@ int ff_celt_decode_frame(CeltFrame *f, OpusRangeCoder *rc,
|
||||||
/* postfilter */
|
/* postfilter */
|
||||||
celt_postfilter(f, block);
|
celt_postfilter(f, block);
|
||||||
|
|
||||||
/* deemphasis and output scaling */
|
/* deemphasis */
|
||||||
for (j = 0; j < frame_size; j++) {
|
block->emph_coeff = f->opusdsp.deemphasis(output[i],
|
||||||
const float tmp = block->buf[1024 - frame_size + j] + m;
|
&block->buf[1024 - frame_size],
|
||||||
m = tmp * CELT_EMPH_COEFF;
|
block->emph_coeff, frame_size);
|
||||||
output[i][j] = tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
block->emph_coeff = m;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (channels == 1)
|
if (channels == 1)
|
||||||
|
@ -596,6 +564,7 @@ int ff_celt_init(AVCodecContext *avctx, CeltFrame **f, int output_channels,
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ff_opus_dsp_init(&frm->opusdsp);
|
||||||
ff_celt_flush(frm);
|
ff_celt_flush(frm);
|
||||||
|
|
||||||
*f = frm;
|
*f = frm;
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
|
|
||||||
#include "opus.h"
|
#include "opus.h"
|
||||||
#include "opus_pvq.h"
|
#include "opus_pvq.h"
|
||||||
|
#include "opusdsp.h"
|
||||||
|
|
||||||
#include "mdct15.h"
|
#include "mdct15.h"
|
||||||
#include "libavutil/float_dsp.h"
|
#include "libavutil/float_dsp.h"
|
||||||
|
@ -40,7 +41,6 @@
|
||||||
#define CELT_NORM_SCALE 16384
|
#define CELT_NORM_SCALE 16384
|
||||||
#define CELT_QTHETA_OFFSET 4
|
#define CELT_QTHETA_OFFSET 4
|
||||||
#define CELT_QTHETA_OFFSET_TWOPHASE 16
|
#define CELT_QTHETA_OFFSET_TWOPHASE 16
|
||||||
#define CELT_EMPH_COEFF 0.85000610f
|
|
||||||
#define CELT_POSTFILTER_MINPERIOD 15
|
#define CELT_POSTFILTER_MINPERIOD 15
|
||||||
#define CELT_ENERGY_SILENCE (-28.0f)
|
#define CELT_ENERGY_SILENCE (-28.0f)
|
||||||
|
|
||||||
|
@ -96,6 +96,7 @@ struct CeltFrame {
|
||||||
AVFloatDSPContext *dsp;
|
AVFloatDSPContext *dsp;
|
||||||
CeltBlock block[2];
|
CeltBlock block[2];
|
||||||
CeltPVQ *pvq;
|
CeltPVQ *pvq;
|
||||||
|
OpusDSP opusdsp;
|
||||||
int channels;
|
int channels;
|
||||||
int output_channels;
|
int output_channels;
|
||||||
int apply_phase_inv;
|
int apply_phase_inv;
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -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 */
|
Loading…
Reference in New Issue