LCOV - code coverage report
Current view: top level - libavfilter - af_superequalizer.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 145 0.0 %
Date: 2017-12-15 11:05:35 Functions: 0 15 0.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2002 Naoki Shibata
       3             :  * Copyright (c) 2017 Paul B Mahol
       4             :  *
       5             :  * This file is part of FFmpeg.
       6             :  *
       7             :  * FFmpeg is free software; you can redistribute it and/or
       8             :  * modify it under the terms of the GNU Lesser General Public
       9             :  * License as published by the Free Software Foundation; either
      10             :  * version 2.1 of the License, or (at your option) any later version.
      11             :  *
      12             :  * FFmpeg is distributed in the hope that it will be useful,
      13             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15             :  * Lesser General Public License for more details.
      16             :  *
      17             :  * You should have received a copy of the GNU Lesser General Public
      18             :  * License along with FFmpeg; if not, write to the Free Software
      19             :  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
      20             :  */
      21             : 
      22             : #include "libavutil/opt.h"
      23             : 
      24             : #include "libavcodec/avfft.h"
      25             : 
      26             : #include "audio.h"
      27             : #include "avfilter.h"
      28             : #include "internal.h"
      29             : 
      30             : #define NBANDS 17
      31             : #define M 15
      32             : 
      33             : typedef struct EqParameter {
      34             :     float lower, upper, gain;
      35             : } EqParameter;
      36             : 
      37             : typedef struct SuperEqualizerContext {
      38             :     const AVClass *class;
      39             : 
      40             :     EqParameter params[NBANDS + 1];
      41             : 
      42             :     float gains[NBANDS + 1];
      43             : 
      44             :     float fact[M + 1];
      45             :     float aa;
      46             :     float iza;
      47             :     float *ires, *irest;
      48             :     float *fsamples;
      49             :     int winlen, tabsize;
      50             : 
      51             :     AVFrame *in, *out;
      52             :     RDFTContext *rdft, *irdft;
      53             : } SuperEqualizerContext;
      54             : 
      55             : static const float bands[] = {
      56             :     65.406392, 92.498606, 130.81278, 184.99721, 261.62557, 369.99442, 523.25113, 739.9884, 1046.5023,
      57             :     1479.9768, 2093.0045, 2959.9536, 4186.0091, 5919.9072, 8372.0181, 11839.814, 16744.036
      58             : };
      59             : 
      60           0 : static float izero(SuperEqualizerContext *s, float x)
      61             : {
      62           0 :     float ret = 1;
      63             :     int m;
      64             : 
      65           0 :     for (m = 1; m <= M; m++) {
      66             :         float t;
      67             : 
      68           0 :         t = pow(x / 2, m) / s->fact[m];
      69           0 :         ret += t*t;
      70             :     }
      71             : 
      72           0 :     return ret;
      73             : }
      74             : 
      75           0 : static float hn_lpf(int n, float f, float fs)
      76             : {
      77           0 :     float t = 1 / fs;
      78           0 :     float omega = 2 * M_PI * f;
      79             : 
      80           0 :     if (n * omega * t == 0)
      81           0 :         return 2 * f * t;
      82           0 :     return 2 * f * t * sinf(n * omega * t) / (n * omega * t);
      83             : }
      84             : 
      85           0 : static float hn_imp(int n)
      86             : {
      87           0 :     return n == 0 ? 1.f : 0.f;
      88             : }
      89             : 
      90           0 : static float hn(int n, EqParameter *param, float fs)
      91             : {
      92             :     float ret, lhn;
      93             :     int i;
      94             : 
      95           0 :     lhn = hn_lpf(n, param[0].upper, fs);
      96           0 :     ret = param[0].gain*lhn;
      97             : 
      98           0 :     for (i = 1; i < NBANDS + 1 && param[i].upper < fs / 2; i++) {
      99           0 :         float lhn2 = hn_lpf(n, param[i].upper, fs);
     100           0 :         ret += param[i].gain * (lhn2 - lhn);
     101           0 :         lhn = lhn2;
     102             :     }
     103             : 
     104           0 :     ret += param[i].gain * (hn_imp(n) - lhn);
     105             : 
     106           0 :     return ret;
     107             : }
     108             : 
     109           0 : static float alpha(float a)
     110             : {
     111           0 :     if (a <= 21)
     112           0 :         return 0;
     113           0 :     if (a <= 50)
     114           0 :         return .5842f * pow(a - 21, 0.4f) + 0.07886f * (a - 21);
     115           0 :     return .1102f * (a - 8.7f);
     116             : }
     117             : 
     118           0 : static float win(SuperEqualizerContext *s, float n, int N)
     119             : {
     120           0 :     return izero(s, alpha(s->aa) * sqrtf(1 - 4 * n * n / ((N - 1) * (N - 1)))) / s->iza;
     121             : }
     122             : 
     123           0 : static void process_param(float *bc, EqParameter *param, float fs)
     124             : {
     125             :     int i;
     126             : 
     127           0 :     for (i = 0; i <= NBANDS; i++) {
     128           0 :         param[i].lower = i == 0 ? 0 : bands[i - 1];
     129           0 :         param[i].upper = i == NBANDS ? fs : bands[i];
     130           0 :         param[i].gain  = bc[i];
     131             :     }
     132           0 : }
     133             : 
     134           0 : static int equ_init(SuperEqualizerContext *s, int wb)
     135             : {
     136             :     int i,j;
     137             : 
     138           0 :     s->rdft  = av_rdft_init(wb, DFT_R2C);
     139           0 :     s->irdft = av_rdft_init(wb, IDFT_C2R);
     140           0 :     if (!s->rdft || !s->irdft)
     141           0 :         return AVERROR(ENOMEM);
     142             : 
     143           0 :     s->aa = 96;
     144           0 :     s->winlen = (1 << (wb-1))-1;
     145           0 :     s->tabsize  = 1 << wb;
     146             : 
     147           0 :     s->ires     = av_calloc(s->tabsize, sizeof(float));
     148           0 :     s->irest    = av_calloc(s->tabsize, sizeof(float));
     149           0 :     s->fsamples = av_calloc(s->tabsize, sizeof(float));
     150             : 
     151           0 :     for (i = 0; i <= M; i++) {
     152           0 :         s->fact[i] = 1;
     153           0 :         for (j = 1; j <= i; j++)
     154           0 :             s->fact[i] *= j;
     155             :     }
     156             : 
     157           0 :     s->iza = izero(s, alpha(s->aa));
     158             : 
     159           0 :     return 0;
     160             : }
     161             : 
     162           0 : static void make_fir(SuperEqualizerContext *s, float *lbc, float *rbc, EqParameter *param, float fs)
     163             : {
     164           0 :     const int winlen = s->winlen;
     165           0 :     const int tabsize = s->tabsize;
     166             :     float *nires;
     167             :     int i;
     168             : 
     169           0 :     if (fs <= 0)
     170           0 :         return;
     171             : 
     172           0 :     process_param(lbc, param, fs);
     173           0 :     for (i = 0; i < winlen; i++)
     174           0 :         s->irest[i] = hn(i - winlen / 2, param, fs) * win(s, i - winlen / 2, winlen);
     175           0 :     for (; i < tabsize; i++)
     176           0 :         s->irest[i] = 0;
     177             : 
     178           0 :     av_rdft_calc(s->rdft, s->irest);
     179           0 :     nires = s->ires;
     180           0 :     for (i = 0; i < tabsize; i++)
     181           0 :         nires[i] = s->irest[i];
     182             : }
     183             : 
     184           0 : static int filter_frame(AVFilterLink *inlink, AVFrame *in)
     185             : {
     186           0 :     AVFilterContext *ctx = inlink->dst;
     187           0 :     SuperEqualizerContext *s = ctx->priv;
     188           0 :     AVFilterLink *outlink = ctx->outputs[0];
     189           0 :     const float *ires = s->ires;
     190           0 :     float *fsamples = s->fsamples;
     191             :     int ch, i;
     192             : 
     193           0 :     AVFrame *out = ff_get_audio_buffer(outlink, s->winlen);
     194             :     float *src, *dst, *ptr;
     195             : 
     196           0 :     if (!out) {
     197           0 :         av_frame_free(&in);
     198           0 :         return AVERROR(ENOMEM);
     199             :     }
     200             : 
     201           0 :     for (ch = 0; ch < in->channels; ch++) {
     202           0 :         ptr = (float *)out->extended_data[ch];
     203           0 :         dst = (float *)s->out->extended_data[ch];
     204           0 :         src = (float *)in->extended_data[ch];
     205             : 
     206           0 :         for (i = 0; i < s->winlen; i++)
     207           0 :             fsamples[i] = src[i];
     208           0 :         for (; i < s->tabsize; i++)
     209           0 :             fsamples[i] = 0;
     210             : 
     211           0 :         av_rdft_calc(s->rdft, fsamples);
     212             : 
     213           0 :         fsamples[0] = ires[0] * fsamples[0];
     214           0 :         fsamples[1] = ires[1] * fsamples[1];
     215           0 :         for (i = 1; i < s->tabsize / 2; i++) {
     216             :             float re, im;
     217             : 
     218           0 :             re = ires[i*2  ] * fsamples[i*2] - ires[i*2+1] * fsamples[i*2+1];
     219           0 :             im = ires[i*2+1] * fsamples[i*2] + ires[i*2  ] * fsamples[i*2+1];
     220             : 
     221           0 :             fsamples[i*2  ] = re;
     222           0 :             fsamples[i*2+1] = im;
     223             :         }
     224             : 
     225           0 :         av_rdft_calc(s->irdft, fsamples);
     226             : 
     227           0 :         for (i = 0; i < s->winlen; i++)
     228           0 :             dst[i] += fsamples[i] / s->tabsize * 2;
     229           0 :         for (i = s->winlen; i < s->tabsize; i++)
     230           0 :             dst[i]  = fsamples[i] / s->tabsize * 2;
     231           0 :         for (i = 0; i < s->winlen; i++)
     232           0 :             ptr[i] = dst[i];
     233           0 :         for (i = 0; i < s->winlen; i++)
     234           0 :             dst[i] = dst[i+s->winlen];
     235             :     }
     236             : 
     237           0 :     out->pts = in->pts;
     238           0 :     av_frame_free(&in);
     239             : 
     240           0 :     return ff_filter_frame(outlink, out);
     241             : }
     242             : 
     243           0 : static av_cold int init(AVFilterContext *ctx)
     244             : {
     245           0 :     SuperEqualizerContext *s = ctx->priv;
     246             : 
     247           0 :     return equ_init(s, 14);
     248             : }
     249             : 
     250           0 : static int query_formats(AVFilterContext *ctx)
     251             : {
     252             :     AVFilterFormats *formats;
     253             :     AVFilterChannelLayouts *layouts;
     254             :     static const enum AVSampleFormat sample_fmts[] = {
     255             :         AV_SAMPLE_FMT_FLTP,
     256             :         AV_SAMPLE_FMT_NONE
     257             :     };
     258             :     int ret;
     259             : 
     260           0 :     layouts = ff_all_channel_counts();
     261           0 :     if (!layouts)
     262           0 :         return AVERROR(ENOMEM);
     263           0 :     ret = ff_set_common_channel_layouts(ctx, layouts);
     264           0 :     if (ret < 0)
     265           0 :         return ret;
     266             : 
     267           0 :     formats = ff_make_format_list(sample_fmts);
     268           0 :     if ((ret = ff_set_common_formats(ctx, formats)) < 0)
     269           0 :         return ret;
     270             : 
     271           0 :     formats = ff_all_samplerates();
     272           0 :     return ff_set_common_samplerates(ctx, formats);
     273             : }
     274             : 
     275           0 : static int config_input(AVFilterLink *inlink)
     276             : {
     277           0 :     AVFilterContext *ctx = inlink->dst;
     278           0 :     SuperEqualizerContext *s = ctx->priv;
     279             : 
     280           0 :     inlink->partial_buf_size =
     281           0 :     inlink->min_samples =
     282           0 :     inlink->max_samples = s->winlen;
     283             : 
     284           0 :     s->out = ff_get_audio_buffer(inlink, s->tabsize);
     285           0 :     if (!s->out)
     286           0 :         return AVERROR(ENOMEM);
     287             : 
     288           0 :     return 0;
     289             : }
     290             : 
     291           0 : static int config_output(AVFilterLink *outlink)
     292             : {
     293           0 :     AVFilterContext *ctx = outlink->src;
     294           0 :     SuperEqualizerContext *s = ctx->priv;
     295             : 
     296           0 :     make_fir(s, s->gains, s->gains, s->params, outlink->sample_rate);
     297             : 
     298           0 :     return 0;
     299             : }
     300             : 
     301           0 : static av_cold void uninit(AVFilterContext *ctx)
     302             : {
     303           0 :     SuperEqualizerContext *s = ctx->priv;
     304             : 
     305           0 :     av_frame_free(&s->out);
     306           0 :     av_freep(&s->irest);
     307           0 :     av_freep(&s->ires);
     308           0 :     av_freep(&s->fsamples);
     309           0 :     av_rdft_end(s->rdft);
     310           0 :     av_rdft_end(s->irdft);
     311           0 : }
     312             : 
     313             : static const AVFilterPad superequalizer_inputs[] = {
     314             :     {
     315             :         .name         = "default",
     316             :         .type         = AVMEDIA_TYPE_AUDIO,
     317             :         .filter_frame = filter_frame,
     318             :         .config_props = config_input,
     319             :     },
     320             :     { NULL }
     321             : };
     322             : 
     323             : static const AVFilterPad superequalizer_outputs[] = {
     324             :     {
     325             :         .name         = "default",
     326             :         .type         = AVMEDIA_TYPE_AUDIO,
     327             :         .config_props = config_output,
     328             :     },
     329             :     { NULL }
     330             : };
     331             : 
     332             : #define AF AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
     333             : #define OFFSET(x) offsetof(SuperEqualizerContext, x)
     334             : 
     335             : static const AVOption superequalizer_options[] = {
     336             :     {  "1b", "set 65Hz band gain",    OFFSET(gains [0]), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 20, AF },
     337             :     {  "2b", "set 92Hz band gain",    OFFSET(gains [1]), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 20, AF },
     338             :     {  "3b", "set 131Hz band gain",   OFFSET(gains [2]), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 20, AF },
     339             :     {  "4b", "set 185Hz band gain",   OFFSET(gains [3]), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 20, AF },
     340             :     {  "5b", "set 262Hz band gain",   OFFSET(gains [4]), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 20, AF },
     341             :     {  "6b", "set 370Hz band gain",   OFFSET(gains [5]), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 20, AF },
     342             :     {  "7b", "set 523Hz band gain",   OFFSET(gains [6]), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 20, AF },
     343             :     {  "8b", "set 740Hz band gain",   OFFSET(gains [7]), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 20, AF },
     344             :     {  "9b", "set 1047Hz band gain",  OFFSET(gains [8]), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 20, AF },
     345             :     { "10b", "set 1480Hz band gain",  OFFSET(gains [9]), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 20, AF },
     346             :     { "11b", "set 2093Hz band gain",  OFFSET(gains[10]), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 20, AF },
     347             :     { "12b", "set 2960Hz band gain",  OFFSET(gains[11]), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 20, AF },
     348             :     { "13b", "set 4186Hz band gain",  OFFSET(gains[12]), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 20, AF },
     349             :     { "14b", "set 5920Hz band gain",  OFFSET(gains[13]), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 20, AF },
     350             :     { "15b", "set 8372Hz band gain",  OFFSET(gains[14]), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 20, AF },
     351             :     { "16b", "set 11840Hz band gain", OFFSET(gains[15]), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 20, AF },
     352             :     { "17b", "set 16744Hz band gain", OFFSET(gains[16]), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 20, AF },
     353             :     { "18b", "set 20000Hz band gain", OFFSET(gains[17]), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 20, AF },
     354             :     { NULL }
     355             : };
     356             : 
     357             : AVFILTER_DEFINE_CLASS(superequalizer);
     358             : 
     359             : AVFilter ff_af_superequalizer = {
     360             :     .name          = "superequalizer",
     361             :     .description   = NULL_IF_CONFIG_SMALL("Apply 18 band equalization filter."),
     362             :     .priv_size     = sizeof(SuperEqualizerContext),
     363             :     .priv_class    = &superequalizer_class,
     364             :     .query_formats = query_formats,
     365             :     .init          = init,
     366             :     .uninit        = uninit,
     367             :     .inputs        = superequalizer_inputs,
     368             :     .outputs       = superequalizer_outputs,
     369             : };

Generated by: LCOV version 1.13