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
29
42
44 uint8_t *
const *
src, uint8_t **dst,
47
48 #define OFFSET(x) offsetof(AudioEchoContext, x)
49 #define A AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
50
57 };
58
60
62 {
63 char *p;
64
65 *nb_items = 1;
66 for (p = item_str; *p; p++) {
67 if (*p == '|')
68 (*nb_items)++;
69 }
70
71 }
72
73 static void fill_items(
char *item_str,
int *nb_items,
float *items)
74 {
75 char *p, *saveptr =
NULL;
76 int i, new_nb_items = 0;
77
78 p = item_str;
79 for (
i = 0;
i < *nb_items;
i++) {
82 if (tstr)
83 new_nb_items +=
av_sscanf(tstr,
"%f", &items[new_nb_items]) == 1;
84 }
85
86 *nb_items = new_nb_items;
87 }
88
90 {
92
96
100 }
101
103 {
105 int nb_delays, nb_decays,
i;
106
107 if (!
s->delays || !
s->decays) {
110 }
111
114
117 if (!
s->delay || !
s->decay)
119
122
123 if (nb_delays != nb_decays) {
124 av_log(
ctx,
AV_LOG_ERROR,
"Number of delays %d differs from number of decays %d.\n", nb_delays, nb_decays);
126 }
127
128 s->nb_echoes = nb_delays;
132 }
133
137
138 for (
i = 0;
i < nb_delays;
i++) {
139 if (
s->delay[
i] <= 0 ||
s->delay[
i] > 90000) {
142 }
143 if (
s->decay[
i] <= 0 ||
s->decay[
i] > 1) {
146 }
147 }
148
150
152 return 0;
153 }
154
155 #define MOD(a, b) (((a) >= (b)) ? (a) - (b) : (a))
156
157 #define ECHO(name, type, min, max) \
158 static void echo_samples_## name ##p(AudioEchoContext *ctx, \
159 uint8_t **delayptrs, \
160 uint8_t * const *src, uint8_t **dst, \
161 int nb_samples, int channels) \
162 { \
163 const double out_gain = ctx->out_gain; \
164 const double in_gain = ctx->in_gain; \
165 const int nb_echoes = ctx->nb_echoes; \
166 const int max_samples = ctx->max_samples; \
167 int i, j, chan, av_uninit(index); \
168 \
169 av_assert1(channels > 0); /* would corrupt delay_index */ \
170 \
171 for (chan = 0; chan < channels; chan++) { \
172 const type *s = (type *)src[chan]; \
173 type *d = (type *)dst[chan]; \
174 type *dbuf = (type *)delayptrs[chan]; \
175 \
176 index = ctx->delay_index; \
177 for (i = 0; i < nb_samples; i++, s++, d++) { \
178 double out, in; \
179 \
180 in = *s; \
181 out = in * in_gain; \
182 for (j = 0; j < nb_echoes; j++) { \
183 int ix = index + max_samples - ctx->samples[j]; \
184 ix = MOD(ix, max_samples); \
185 out += dbuf[ix] * ctx->decay[j]; \
186 } \
187 out *= out_gain; \
188 \
189 *d = av_clipd(out, min, max); \
190 dbuf[index] = in; \
191 \
192 index = MOD(index + 1, max_samples); \
193 } \
194 } \
195 ctx->delay_index = index; \
196 }
197
198 ECHO(dbl,
double, -1.0, 1.0 )
199 ECHO(flt,
float, -1.0, 1.0 )
200 ECHO(s16, int16_t, INT16_MIN, INT16_MAX)
202
204 {
207 float volume = 1.0;
209
210 for (
i = 0;
i <
s->nb_echoes;
i++) {
211 s->samples[
i] =
s->delay[
i] * outlink->sample_rate / 1000.0;
212 s->max_samples =
FFMAX(
s->max_samples,
s->samples[
i]);
213 volume +=
s->decay[
i];
214 }
215
216 if (
s->max_samples <= 0) {
219 }
220 s->fade_out =
s->max_samples;
221
222 if (volume *
s->in_gain *
s->out_gain > 1.0)
224 "out_gain %f can cause saturation of output\n",
s->out_gain);
225
226 switch (outlink->format) {
231 }
232
233
237
239 outlink->ch_layout.nb_channels,
241 outlink->format, 0);
242 }
243
245 {
249
252 } else {
254 if (!out_frame) {
257 }
259 }
260
263
265
266 if (
frame != out_frame)
268
270 }
271
273 {
276 int nb_samples =
FFMIN(
s->fade_out, 2048);
278
281 s->fade_out -= nb_samples;
282
287
288 s->echo_samples(
s,
s->delayptrs,
frame->extended_data,
frame->extended_data,
290
294
296 }
297
299 {
306
308
314
318 }
319
320 if (
s->eof &&
s->fade_out <= 0) {
322 return 0;
323 }
324
327
329 }
330
332 {
335 },
336 };
337
339 {
343 },
344 };
345
350 .priv_class = &aecho_class,
358 };