blob: cfaea3de43057fc2d37748f9e9e26813ce012de7
1 | /* |
2 | * Copyright (c) 2013 Paul B Mahol |
3 | * |
4 | * This file is part of FFmpeg. |
5 | * |
6 | * FFmpeg is free software; you can redistribute it and/or |
7 | * modify it under the terms of the GNU Lesser General Public |
8 | * License as published by the Free Software Foundation; either |
9 | * version 2.1 of the License, or (at your option) any later version. |
10 | * |
11 | * FFmpeg is distributed in the hope that it will be useful, |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
14 | * Lesser General Public License for more details. |
15 | * |
16 | * You should have received a copy of the GNU Lesser General Public |
17 | * License along with FFmpeg; if not, write to the Free Software |
18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
19 | */ |
20 | |
21 | #include "libavutil/avassert.h" |
22 | #include "libavutil/avstring.h" |
23 | #include "libavutil/opt.h" |
24 | #include "libavutil/samplefmt.h" |
25 | #include "avfilter.h" |
26 | #include "audio.h" |
27 | #include "internal.h" |
28 | |
29 | typedef struct AudioEchoContext { |
30 | const AVClass *class; |
31 | float in_gain, out_gain; |
32 | char *delays, *decays; |
33 | float *delay, *decay; |
34 | int nb_echoes; |
35 | int delay_index; |
36 | uint8_t **delayptrs; |
37 | int max_samples, fade_out; |
38 | int *samples; |
39 | int64_t next_pts; |
40 | |
41 | void (*echo_samples)(struct AudioEchoContext *ctx, uint8_t **delayptrs, |
42 | uint8_t * const *src, uint8_t **dst, |
43 | int nb_samples, int channels); |
44 | } AudioEchoContext; |
45 | |
46 | #define OFFSET(x) offsetof(AudioEchoContext, x) |
47 | #define A AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM |
48 | |
49 | static const AVOption aecho_options[] = { |
50 | { "in_gain", "set signal input gain", OFFSET(in_gain), AV_OPT_TYPE_FLOAT, {.dbl=0.6}, 0, 1, A }, |
51 | { "out_gain", "set signal output gain", OFFSET(out_gain), AV_OPT_TYPE_FLOAT, {.dbl=0.3}, 0, 1, A }, |
52 | { "delays", "set list of signal delays", OFFSET(delays), AV_OPT_TYPE_STRING, {.str="1000"}, 0, 0, A }, |
53 | { "decays", "set list of signal decays", OFFSET(decays), AV_OPT_TYPE_STRING, {.str="0.5"}, 0, 0, A }, |
54 | { NULL } |
55 | }; |
56 | |
57 | AVFILTER_DEFINE_CLASS(aecho); |
58 | |
59 | static void count_items(char *item_str, int *nb_items) |
60 | { |
61 | char *p; |
62 | |
63 | *nb_items = 1; |
64 | for (p = item_str; *p; p++) { |
65 | if (*p == '|') |
66 | (*nb_items)++; |
67 | } |
68 | |
69 | } |
70 | |
71 | static void fill_items(char *item_str, int *nb_items, float *items) |
72 | { |
73 | char *p, *saveptr = NULL; |
74 | int i, new_nb_items = 0; |
75 | |
76 | p = item_str; |
77 | for (i = 0; i < *nb_items; i++) { |
78 | char *tstr = av_strtok(p, "|", &saveptr); |
79 | p = NULL; |
80 | if (tstr) |
81 | new_nb_items += sscanf(tstr, "%f", &items[new_nb_items]) == 1; |
82 | } |
83 | |
84 | *nb_items = new_nb_items; |
85 | } |
86 | |
87 | static av_cold void uninit(AVFilterContext *ctx) |
88 | { |
89 | AudioEchoContext *s = ctx->priv; |
90 | |
91 | av_freep(&s->delay); |
92 | av_freep(&s->decay); |
93 | av_freep(&s->samples); |
94 | |
95 | if (s->delayptrs) |
96 | av_freep(&s->delayptrs[0]); |
97 | av_freep(&s->delayptrs); |
98 | } |
99 | |
100 | static av_cold int init(AVFilterContext *ctx) |
101 | { |
102 | AudioEchoContext *s = ctx->priv; |
103 | int nb_delays, nb_decays, i; |
104 | |
105 | if (!s->delays || !s->decays) { |
106 | av_log(ctx, AV_LOG_ERROR, "Missing delays and/or decays.\n"); |
107 | return AVERROR(EINVAL); |
108 | } |
109 | |
110 | count_items(s->delays, &nb_delays); |
111 | count_items(s->decays, &nb_decays); |
112 | |
113 | s->delay = av_realloc_f(s->delay, nb_delays, sizeof(*s->delay)); |
114 | s->decay = av_realloc_f(s->decay, nb_decays, sizeof(*s->decay)); |
115 | if (!s->delay || !s->decay) |
116 | return AVERROR(ENOMEM); |
117 | |
118 | fill_items(s->delays, &nb_delays, s->delay); |
119 | fill_items(s->decays, &nb_decays, s->decay); |
120 | |
121 | if (nb_delays != nb_decays) { |
122 | av_log(ctx, AV_LOG_ERROR, "Number of delays %d differs from number of decays %d.\n", nb_delays, nb_decays); |
123 | return AVERROR(EINVAL); |
124 | } |
125 | |
126 | s->nb_echoes = nb_delays; |
127 | if (!s->nb_echoes) { |
128 | av_log(ctx, AV_LOG_ERROR, "At least one decay & delay must be set.\n"); |
129 | return AVERROR(EINVAL); |
130 | } |
131 | |
132 | s->samples = av_realloc_f(s->samples, nb_delays, sizeof(*s->samples)); |
133 | if (!s->samples) |
134 | return AVERROR(ENOMEM); |
135 | |
136 | for (i = 0; i < nb_delays; i++) { |
137 | if (s->delay[i] <= 0 || s->delay[i] > 90000) { |
138 | av_log(ctx, AV_LOG_ERROR, "delay[%d]: %f is out of allowed range: (0, 90000]\n", i, s->delay[i]); |
139 | return AVERROR(EINVAL); |
140 | } |
141 | if (s->decay[i] <= 0 || s->decay[i] > 1) { |
142 | av_log(ctx, AV_LOG_ERROR, "decay[%d]: %f is out of allowed range: (0, 1]\n", i, s->decay[i]); |
143 | return AVERROR(EINVAL); |
144 | } |
145 | } |
146 | |
147 | s->next_pts = AV_NOPTS_VALUE; |
148 | |
149 | av_log(ctx, AV_LOG_DEBUG, "nb_echoes:%d\n", s->nb_echoes); |
150 | return 0; |
151 | } |
152 | |
153 | static int query_formats(AVFilterContext *ctx) |
154 | { |
155 | AVFilterChannelLayouts *layouts; |
156 | AVFilterFormats *formats; |
157 | static const enum AVSampleFormat sample_fmts[] = { |
158 | AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_S32P, |
159 | AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_DBLP, |
160 | AV_SAMPLE_FMT_NONE |
161 | }; |
162 | int ret; |
163 | |
164 | layouts = ff_all_channel_counts(); |
165 | if (!layouts) |
166 | return AVERROR(ENOMEM); |
167 | ret = ff_set_common_channel_layouts(ctx, layouts); |
168 | if (ret < 0) |
169 | return ret; |
170 | |
171 | formats = ff_make_format_list(sample_fmts); |
172 | if (!formats) |
173 | return AVERROR(ENOMEM); |
174 | ret = ff_set_common_formats(ctx, formats); |
175 | if (ret < 0) |
176 | return ret; |
177 | |
178 | formats = ff_all_samplerates(); |
179 | if (!formats) |
180 | return AVERROR(ENOMEM); |
181 | return ff_set_common_samplerates(ctx, formats); |
182 | } |
183 | |
184 | #define MOD(a, b) (((a) >= (b)) ? (a) - (b) : (a)) |
185 | |
186 | #define ECHO(name, type, min, max) \ |
187 | static void echo_samples_## name ##p(AudioEchoContext *ctx, \ |
188 | uint8_t **delayptrs, \ |
189 | uint8_t * const *src, uint8_t **dst, \ |
190 | int nb_samples, int channels) \ |
191 | { \ |
192 | const double out_gain = ctx->out_gain; \ |
193 | const double in_gain = ctx->in_gain; \ |
194 | const int nb_echoes = ctx->nb_echoes; \ |
195 | const int max_samples = ctx->max_samples; \ |
196 | int i, j, chan, av_uninit(index); \ |
197 | \ |
198 | av_assert1(channels > 0); /* would corrupt delay_index */ \ |
199 | \ |
200 | for (chan = 0; chan < channels; chan++) { \ |
201 | const type *s = (type *)src[chan]; \ |
202 | type *d = (type *)dst[chan]; \ |
203 | type *dbuf = (type *)delayptrs[chan]; \ |
204 | \ |
205 | index = ctx->delay_index; \ |
206 | for (i = 0; i < nb_samples; i++, s++, d++) { \ |
207 | double out, in; \ |
208 | \ |
209 | in = *s; \ |
210 | out = in * in_gain; \ |
211 | for (j = 0; j < nb_echoes; j++) { \ |
212 | int ix = index + max_samples - ctx->samples[j]; \ |
213 | ix = MOD(ix, max_samples); \ |
214 | out += dbuf[ix] * ctx->decay[j]; \ |
215 | } \ |
216 | out *= out_gain; \ |
217 | \ |
218 | *d = av_clipd(out, min, max); \ |
219 | dbuf[index] = in; \ |
220 | \ |
221 | index = MOD(index + 1, max_samples); \ |
222 | } \ |
223 | } \ |
224 | ctx->delay_index = index; \ |
225 | } |
226 | |
227 | ECHO(dbl, double, -1.0, 1.0 ) |
228 | ECHO(flt, float, -1.0, 1.0 ) |
229 | ECHO(s16, int16_t, INT16_MIN, INT16_MAX) |
230 | ECHO(s32, int32_t, INT32_MIN, INT32_MAX) |
231 | |
232 | static int config_output(AVFilterLink *outlink) |
233 | { |
234 | AVFilterContext *ctx = outlink->src; |
235 | AudioEchoContext *s = ctx->priv; |
236 | float volume = 1.0; |
237 | int i; |
238 | |
239 | for (i = 0; i < s->nb_echoes; i++) { |
240 | s->samples[i] = s->delay[i] * outlink->sample_rate / 1000.0; |
241 | s->max_samples = FFMAX(s->max_samples, s->samples[i]); |
242 | volume += s->decay[i]; |
243 | } |
244 | |
245 | if (s->max_samples <= 0) { |
246 | av_log(ctx, AV_LOG_ERROR, "Nothing to echo - missing delay samples.\n"); |
247 | return AVERROR(EINVAL); |
248 | } |
249 | s->fade_out = s->max_samples; |
250 | |
251 | if (volume * s->in_gain * s->out_gain > 1.0) |
252 | av_log(ctx, AV_LOG_WARNING, |
253 | "out_gain %f can cause saturation of output\n", s->out_gain); |
254 | |
255 | switch (outlink->format) { |
256 | case AV_SAMPLE_FMT_DBLP: s->echo_samples = echo_samples_dblp; break; |
257 | case AV_SAMPLE_FMT_FLTP: s->echo_samples = echo_samples_fltp; break; |
258 | case AV_SAMPLE_FMT_S16P: s->echo_samples = echo_samples_s16p; break; |
259 | case AV_SAMPLE_FMT_S32P: s->echo_samples = echo_samples_s32p; break; |
260 | } |
261 | |
262 | |
263 | if (s->delayptrs) |
264 | av_freep(&s->delayptrs[0]); |
265 | av_freep(&s->delayptrs); |
266 | |
267 | return av_samples_alloc_array_and_samples(&s->delayptrs, NULL, |
268 | outlink->channels, |
269 | s->max_samples, |
270 | outlink->format, 0); |
271 | } |
272 | |
273 | static int filter_frame(AVFilterLink *inlink, AVFrame *frame) |
274 | { |
275 | AVFilterContext *ctx = inlink->dst; |
276 | AudioEchoContext *s = ctx->priv; |
277 | AVFrame *out_frame; |
278 | |
279 | if (av_frame_is_writable(frame)) { |
280 | out_frame = frame; |
281 | } else { |
282 | out_frame = ff_get_audio_buffer(inlink, frame->nb_samples); |
283 | if (!out_frame) { |
284 | av_frame_free(&frame); |
285 | return AVERROR(ENOMEM); |
286 | } |
287 | av_frame_copy_props(out_frame, frame); |
288 | } |
289 | |
290 | s->echo_samples(s, s->delayptrs, frame->extended_data, out_frame->extended_data, |
291 | frame->nb_samples, inlink->channels); |
292 | |
293 | s->next_pts = frame->pts + av_rescale_q(frame->nb_samples, (AVRational){1, inlink->sample_rate}, inlink->time_base); |
294 | |
295 | if (frame != out_frame) |
296 | av_frame_free(&frame); |
297 | |
298 | return ff_filter_frame(ctx->outputs[0], out_frame); |
299 | } |
300 | |
301 | static int request_frame(AVFilterLink *outlink) |
302 | { |
303 | AVFilterContext *ctx = outlink->src; |
304 | AudioEchoContext *s = ctx->priv; |
305 | int ret; |
306 | |
307 | ret = ff_request_frame(ctx->inputs[0]); |
308 | |
309 | if (ret == AVERROR_EOF && !ctx->is_disabled && s->fade_out) { |
310 | int nb_samples = FFMIN(s->fade_out, 2048); |
311 | AVFrame *frame; |
312 | |
313 | frame = ff_get_audio_buffer(outlink, nb_samples); |
314 | if (!frame) |
315 | return AVERROR(ENOMEM); |
316 | s->fade_out -= nb_samples; |
317 | |
318 | av_samples_set_silence(frame->extended_data, 0, |
319 | frame->nb_samples, |
320 | outlink->channels, |
321 | frame->format); |
322 | |
323 | s->echo_samples(s, s->delayptrs, frame->extended_data, frame->extended_data, |
324 | frame->nb_samples, outlink->channels); |
325 | |
326 | frame->pts = s->next_pts; |
327 | if (s->next_pts != AV_NOPTS_VALUE) |
328 | s->next_pts += av_rescale_q(nb_samples, (AVRational){1, outlink->sample_rate}, outlink->time_base); |
329 | |
330 | return ff_filter_frame(outlink, frame); |
331 | } |
332 | |
333 | return ret; |
334 | } |
335 | |
336 | static const AVFilterPad aecho_inputs[] = { |
337 | { |
338 | .name = "default", |
339 | .type = AVMEDIA_TYPE_AUDIO, |
340 | .filter_frame = filter_frame, |
341 | }, |
342 | { NULL } |
343 | }; |
344 | |
345 | static const AVFilterPad aecho_outputs[] = { |
346 | { |
347 | .name = "default", |
348 | .request_frame = request_frame, |
349 | .config_props = config_output, |
350 | .type = AVMEDIA_TYPE_AUDIO, |
351 | }, |
352 | { NULL } |
353 | }; |
354 | |
355 | AVFilter ff_af_aecho = { |
356 | .name = "aecho", |
357 | .description = NULL_IF_CONFIG_SMALL("Add echoing to the audio."), |
358 | .query_formats = query_formats, |
359 | .priv_size = sizeof(AudioEchoContext), |
360 | .priv_class = &aecho_class, |
361 | .init = init, |
362 | .uninit = uninit, |
363 | .inputs = aecho_inputs, |
364 | .outputs = aecho_outputs, |
365 | }; |
366 |