• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2008 Rob Sykes
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/channel_layout.h"
23 #include "libavutil/opt.h"
24 #include "avfilter.h"
25 #include "audio.h"
26 #include "formats.h"
27 
28 typedef struct AudioContrastContext {
29     const AVClass *class;
30     float contrast;
31     void (*filter)(void **dst, const void **src,
32                    int nb_samples, int channels, float contrast);
33 } AudioContrastContext;
34 
35 #define OFFSET(x) offsetof(AudioContrastContext, x)
36 #define A AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
37 
38 static const AVOption acontrast_options[] = {
39     { "contrast", "set contrast", OFFSET(contrast), AV_OPT_TYPE_FLOAT, {.dbl=33}, 0, 100, A },
40     { NULL }
41 };
42 
43 AVFILTER_DEFINE_CLASS(acontrast);
44 
filter_flt(void ** d,const void ** s,int nb_samples,int channels,float contrast)45 static void filter_flt(void **d, const void **s,
46                        int nb_samples, int channels,
47                        float contrast)
48 {
49     const float *src = s[0];
50     float *dst = d[0];
51     int n, c;
52 
53     for (n = 0; n < nb_samples; n++) {
54         for (c = 0; c < channels; c++) {
55             float d = src[c] * M_PI_2;
56 
57             dst[c] = sinf(d + contrast * sinf(d * 4));
58         }
59 
60         dst += c;
61         src += c;
62     }
63 }
64 
filter_dbl(void ** d,const void ** s,int nb_samples,int channels,float contrast)65 static void filter_dbl(void **d, const void **s,
66                        int nb_samples, int channels,
67                        float contrast)
68 {
69     const double *src = s[0];
70     double *dst = d[0];
71     int n, c;
72 
73     for (n = 0; n < nb_samples; n++) {
74         for (c = 0; c < channels; c++) {
75             double d = src[c] * M_PI_2;
76 
77             dst[c] = sin(d + contrast * sin(d * 4));
78         }
79 
80         dst += c;
81         src += c;
82     }
83 }
84 
filter_fltp(void ** d,const void ** s,int nb_samples,int channels,float contrast)85 static void filter_fltp(void **d, const void **s,
86                         int nb_samples, int channels,
87                         float contrast)
88 {
89     int n, c;
90 
91     for (c = 0; c < channels; c++) {
92         const float *src = s[c];
93         float *dst = d[c];
94 
95         for (n = 0; n < nb_samples; n++) {
96             float d = src[n] * M_PI_2;
97 
98             dst[n] = sinf(d + contrast * sinf(d * 4));
99         }
100     }
101 }
102 
filter_dblp(void ** d,const void ** s,int nb_samples,int channels,float contrast)103 static void filter_dblp(void **d, const void **s,
104                         int nb_samples, int channels,
105                         float contrast)
106 {
107     int n, c;
108 
109     for (c = 0; c < channels; c++) {
110         const double *src = s[c];
111         double *dst = d[c];
112 
113         for (n = 0; n < nb_samples; n++) {
114             double d = src[n] * M_PI_2;
115 
116             dst[n] = sin(d + contrast * sin(d * 4));
117         }
118     }
119 }
120 
config_input(AVFilterLink * inlink)121 static int config_input(AVFilterLink *inlink)
122 {
123     AVFilterContext *ctx = inlink->dst;
124     AudioContrastContext *s    = ctx->priv;
125 
126     switch (inlink->format) {
127     case AV_SAMPLE_FMT_FLT:  s->filter = filter_flt;  break;
128     case AV_SAMPLE_FMT_DBL:  s->filter = filter_dbl;  break;
129     case AV_SAMPLE_FMT_FLTP: s->filter = filter_fltp; break;
130     case AV_SAMPLE_FMT_DBLP: s->filter = filter_dblp; break;
131     }
132 
133     return 0;
134 }
135 
filter_frame(AVFilterLink * inlink,AVFrame * in)136 static int filter_frame(AVFilterLink *inlink, AVFrame *in)
137 {
138     AVFilterContext *ctx = inlink->dst;
139     AVFilterLink *outlink = ctx->outputs[0];
140     AudioContrastContext *s = ctx->priv;
141     AVFrame *out;
142 
143     if (av_frame_is_writable(in)) {
144         out = in;
145     } else {
146         out = ff_get_audio_buffer(outlink, in->nb_samples);
147         if (!out) {
148             av_frame_free(&in);
149             return AVERROR(ENOMEM);
150         }
151         av_frame_copy_props(out, in);
152     }
153 
154     s->filter((void **)out->extended_data, (const void **)in->extended_data,
155               in->nb_samples, in->ch_layout.nb_channels, s->contrast / 750);
156 
157     if (out != in)
158         av_frame_free(&in);
159 
160     return ff_filter_frame(outlink, out);
161 }
162 
163 static const AVFilterPad inputs[] = {
164     {
165         .name         = "default",
166         .type         = AVMEDIA_TYPE_AUDIO,
167         .filter_frame = filter_frame,
168         .config_props = config_input,
169     },
170 };
171 
172 static const AVFilterPad outputs[] = {
173     {
174         .name = "default",
175         .type = AVMEDIA_TYPE_AUDIO,
176     },
177 };
178 
179 const AVFilter ff_af_acontrast = {
180     .name           = "acontrast",
181     .description    = NULL_IF_CONFIG_SMALL("Simple audio dynamic range compression/expansion filter."),
182     .priv_size      = sizeof(AudioContrastContext),
183     .priv_class     = &acontrast_class,
184     FILTER_INPUTS(inputs),
185     FILTER_OUTPUTS(outputs),
186     FILTER_SAMPLEFMTS(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_FLTP,
187                       AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_DBLP),
188 };
189