| @@ -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 */ | |||||
| 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) | 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 */ | |||||