]> git.sesse.net Git - ffmpeg/blob - libavfilter/af_acontrast.c
avfilter/vf_psnr: remove unnecessary check
[ffmpeg] / libavfilter / af_acontrast.c
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
45 static int query_formats(AVFilterContext *ctx)
46 {
47     AVFilterFormats *formats = NULL;
48     AVFilterChannelLayouts *layouts = NULL;
49     static const enum AVSampleFormat sample_fmts[] = {
50         AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_FLTP,
51         AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_DBLP,
52         AV_SAMPLE_FMT_NONE
53     };
54     int ret;
55
56     formats = ff_make_format_list(sample_fmts);
57     if (!formats)
58         return AVERROR(ENOMEM);
59     ret = ff_set_common_formats(ctx, formats);
60     if (ret < 0)
61         return ret;
62
63     layouts = ff_all_channel_counts();
64     if (!layouts)
65         return AVERROR(ENOMEM);
66
67     ret = ff_set_common_channel_layouts(ctx, layouts);
68     if (ret < 0)
69         return ret;
70
71     formats = ff_all_samplerates();
72     return ff_set_common_samplerates(ctx, formats);
73 }
74
75 static void filter_flt(void **d, const void **s,
76                        int nb_samples, int channels,
77                        float contrast)
78 {
79     const float *src = s[0];
80     float *dst = d[0];
81     int n, c;
82
83     for (n = 0; n < nb_samples; n++) {
84         for (c = 0; c < channels; c++) {
85             float d = src[c] * M_PI_2;
86
87             dst[c] = sinf(d + contrast * sinf(d * 4));
88         }
89
90         dst += c;
91         src += c;
92     }
93 }
94
95 static void filter_dbl(void **d, const void **s,
96                        int nb_samples, int channels,
97                        float contrast)
98 {
99     const double *src = s[0];
100     double *dst = d[0];
101     int n, c;
102
103     for (n = 0; n < nb_samples; n++) {
104         for (c = 0; c < channels; c++) {
105             double d = src[c] * M_PI_2;
106
107             dst[c] = sin(d + contrast * sin(d * 4));
108         }
109
110         dst += c;
111         src += c;
112     }
113 }
114
115 static void filter_fltp(void **d, const void **s,
116                         int nb_samples, int channels,
117                         float contrast)
118 {
119     int n, c;
120
121     for (c = 0; c < channels; c++) {
122         const float *src = s[c];
123         float *dst = d[c];
124
125         for (n = 0; n < nb_samples; n++) {
126             float d = src[n] * M_PI_2;
127
128             dst[n] = sinf(d + contrast * sinf(d * 4));
129         }
130     }
131 }
132
133 static void filter_dblp(void **d, const void **s,
134                         int nb_samples, int channels,
135                         float contrast)
136 {
137     int n, c;
138
139     for (c = 0; c < channels; c++) {
140         const double *src = s[c];
141         double *dst = d[c];
142
143         for (n = 0; n < nb_samples; n++) {
144             double d = src[n] * M_PI_2;
145
146             dst[n] = sin(d + contrast * sin(d * 4));
147         }
148     }
149 }
150
151 static int config_input(AVFilterLink *inlink)
152 {
153     AVFilterContext *ctx = inlink->dst;
154     AudioContrastContext *s    = ctx->priv;
155
156     switch (inlink->format) {
157     case AV_SAMPLE_FMT_FLT:  s->filter = filter_flt;  break;
158     case AV_SAMPLE_FMT_DBL:  s->filter = filter_dbl;  break;
159     case AV_SAMPLE_FMT_FLTP: s->filter = filter_fltp; break;
160     case AV_SAMPLE_FMT_DBLP: s->filter = filter_dblp; break;
161     }
162
163     return 0;
164 }
165
166 static int filter_frame(AVFilterLink *inlink, AVFrame *in)
167 {
168     AVFilterContext *ctx = inlink->dst;
169     AVFilterLink *outlink = ctx->outputs[0];
170     AudioContrastContext *s = ctx->priv;
171     AVFrame *out;
172
173     if (av_frame_is_writable(in)) {
174         out = in;
175     } else {
176         out = ff_get_audio_buffer(outlink, in->nb_samples);
177         if (!out) {
178             av_frame_free(&in);
179             return AVERROR(ENOMEM);
180         }
181         av_frame_copy_props(out, in);
182     }
183
184     s->filter((void **)out->extended_data, (const void **)in->extended_data,
185               in->nb_samples, in->channels, s->contrast / 750);
186
187     if (out != in)
188         av_frame_free(&in);
189
190     return ff_filter_frame(outlink, out);
191 }
192
193 static const AVFilterPad inputs[] = {
194     {
195         .name         = "default",
196         .type         = AVMEDIA_TYPE_AUDIO,
197         .filter_frame = filter_frame,
198         .config_props = config_input,
199     },
200     { NULL }
201 };
202
203 static const AVFilterPad outputs[] = {
204     {
205         .name = "default",
206         .type = AVMEDIA_TYPE_AUDIO,
207     },
208     { NULL }
209 };
210
211 const AVFilter ff_af_acontrast = {
212     .name           = "acontrast",
213     .description    = NULL_IF_CONFIG_SMALL("Simple audio dynamic range compression/expansion filter."),
214     .query_formats  = query_formats,
215     .priv_size      = sizeof(AudioContrastContext),
216     .priv_class     = &acontrast_class,
217     .inputs         = inputs,
218     .outputs        = outputs,
219 };