FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
af_aphaser.c
Go to the documentation of this file.
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 /**
22  * @file
23  * phaser audio filter
24  */
25 
26 #include "libavutil/avassert.h"
27 #include "libavutil/opt.h"
28 #include "audio.h"
29 #include "avfilter.h"
30 #include "internal.h"
31 #include "generate_wave_table.h"
32 
33 typedef struct AudioPhaserContext {
34  const AVClass *class;
35  double in_gain, out_gain;
36  double delay;
37  double decay;
38  double speed;
39 
40  int type;
41 
43  double *delay_buffer;
44 
47 
49 
51  uint8_t * const *src, uint8_t **dst,
52  int nb_samples, int channels);
54 
55 #define OFFSET(x) offsetof(AudioPhaserContext, x)
56 #define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
57 
58 static const AVOption aphaser_options[] = {
59  { "in_gain", "set input gain", OFFSET(in_gain), AV_OPT_TYPE_DOUBLE, {.dbl=.4}, 0, 1, FLAGS },
60  { "out_gain", "set output gain", OFFSET(out_gain), AV_OPT_TYPE_DOUBLE, {.dbl=.74}, 0, 1e9, FLAGS },
61  { "delay", "set delay in milliseconds", OFFSET(delay), AV_OPT_TYPE_DOUBLE, {.dbl=3.}, 0, 5, FLAGS },
62  { "decay", "set decay", OFFSET(decay), AV_OPT_TYPE_DOUBLE, {.dbl=.4}, 0, .99, FLAGS },
63  { "speed", "set modulation speed", OFFSET(speed), AV_OPT_TYPE_DOUBLE, {.dbl=.5}, .1, 2, FLAGS },
64  { "type", "set modulation type", OFFSET(type), AV_OPT_TYPE_INT, {.i64=WAVE_TRI}, 0, WAVE_NB-1, FLAGS, "type" },
65  { "triangular", NULL, 0, AV_OPT_TYPE_CONST, {.i64=WAVE_TRI}, 0, 0, FLAGS, "type" },
66  { "t", NULL, 0, AV_OPT_TYPE_CONST, {.i64=WAVE_TRI}, 0, 0, FLAGS, "type" },
67  { "sinusoidal", NULL, 0, AV_OPT_TYPE_CONST, {.i64=WAVE_SIN}, 0, 0, FLAGS, "type" },
68  { "s", NULL, 0, AV_OPT_TYPE_CONST, {.i64=WAVE_SIN}, 0, 0, FLAGS, "type" },
69  { NULL }
70 };
71 
72 AVFILTER_DEFINE_CLASS(aphaser);
73 
75 {
76  AudioPhaserContext *s = ctx->priv;
77 
78  if (s->in_gain > (1 - s->decay * s->decay))
79  av_log(ctx, AV_LOG_WARNING, "in_gain may cause clipping\n");
80  if (s->in_gain / (1 - s->decay) > 1 / s->out_gain)
81  av_log(ctx, AV_LOG_WARNING, "out_gain may cause clipping\n");
82 
83  return 0;
84 }
85 
87 {
90  static const enum AVSampleFormat sample_fmts[] = {
96  };
97  int ret;
98 
99  layouts = ff_all_channel_counts();
100  if (!layouts)
101  return AVERROR(ENOMEM);
102  ret = ff_set_common_channel_layouts(ctx, layouts);
103  if (ret < 0)
104  return ret;
105 
106  formats = ff_make_format_list(sample_fmts);
107  if (!formats)
108  return AVERROR(ENOMEM);
109  ret = ff_set_common_formats(ctx, formats);
110  if (ret < 0)
111  return ret;
112 
113  formats = ff_all_samplerates();
114  if (!formats)
115  return AVERROR(ENOMEM);
116  return ff_set_common_samplerates(ctx, formats);
117 }
118 
119 #define MOD(a, b) (((a) >= (b)) ? (a) - (b) : (a))
120 
121 #define PHASER_PLANAR(name, type) \
122 static void phaser_## name ##p(AudioPhaserContext *s, \
123  uint8_t * const *ssrc, uint8_t **ddst, \
124  int nb_samples, int channels) \
125 { \
126  int i, c, delay_pos, modulation_pos; \
127  \
128  av_assert0(channels > 0); \
129  for (c = 0; c < channels; c++) { \
130  type *src = (type *)ssrc[c]; \
131  type *dst = (type *)ddst[c]; \
132  double *buffer = s->delay_buffer + \
133  c * s->delay_buffer_length; \
134  \
135  delay_pos = s->delay_pos; \
136  modulation_pos = s->modulation_pos; \
137  \
138  for (i = 0; i < nb_samples; i++, src++, dst++) { \
139  double v = *src * s->in_gain + buffer[ \
140  MOD(delay_pos + s->modulation_buffer[ \
141  modulation_pos], \
142  s->delay_buffer_length)] * s->decay; \
143  \
144  modulation_pos = MOD(modulation_pos + 1, \
145  s->modulation_buffer_length); \
146  delay_pos = MOD(delay_pos + 1, s->delay_buffer_length); \
147  buffer[delay_pos] = v; \
148  \
149  *dst = v * s->out_gain; \
150  } \
151  } \
152  \
153  s->delay_pos = delay_pos; \
154  s->modulation_pos = modulation_pos; \
155 }
156 
157 #define PHASER(name, type) \
158 static void phaser_## name (AudioPhaserContext *s, \
159  uint8_t * const *ssrc, uint8_t **ddst, \
160  int nb_samples, int channels) \
161 { \
162  int i, c, delay_pos, modulation_pos; \
163  type *src = (type *)ssrc[0]; \
164  type *dst = (type *)ddst[0]; \
165  double *buffer = s->delay_buffer; \
166  \
167  delay_pos = s->delay_pos; \
168  modulation_pos = s->modulation_pos; \
169  \
170  for (i = 0; i < nb_samples; i++) { \
171  int pos = MOD(delay_pos + s->modulation_buffer[modulation_pos], \
172  s->delay_buffer_length) * channels; \
173  int npos; \
174  \
175  delay_pos = MOD(delay_pos + 1, s->delay_buffer_length); \
176  npos = delay_pos * channels; \
177  for (c = 0; c < channels; c++, src++, dst++) { \
178  double v = *src * s->in_gain + buffer[pos + c] * s->decay; \
179  \
180  buffer[npos + c] = v; \
181  \
182  *dst = v * s->out_gain; \
183  } \
184  \
185  modulation_pos = MOD(modulation_pos + 1, \
186  s->modulation_buffer_length); \
187  } \
188  \
189  s->delay_pos = delay_pos; \
190  s->modulation_pos = modulation_pos; \
191 }
192 
193 PHASER_PLANAR(dbl, double)
194 PHASER_PLANAR(flt, float)
195 PHASER_PLANAR(s16, int16_t)
197 
198 PHASER(dbl, double)
199 PHASER(flt, float)
200 PHASER(s16, int16_t)
201 PHASER(s32, int32_t)
202 
203 static int config_output(AVFilterLink *outlink)
204 {
205  AudioPhaserContext *s = outlink->src->priv;
206  AVFilterLink *inlink = outlink->src->inputs[0];
207 
208  s->delay_buffer_length = s->delay * 0.001 * inlink->sample_rate + 0.5;
209  if (s->delay_buffer_length <= 0) {
210  av_log(outlink->src, AV_LOG_ERROR, "delay is too small\n");
211  return AVERROR(EINVAL);
212  }
213  s->delay_buffer = av_calloc(s->delay_buffer_length, sizeof(*s->delay_buffer) * inlink->channels);
214  s->modulation_buffer_length = inlink->sample_rate / s->speed + 0.5;
216 
217  if (!s->modulation_buffer || !s->delay_buffer)
218  return AVERROR(ENOMEM);
219 
222  1., s->delay_buffer_length, M_PI / 2.0);
223 
224  s->delay_pos = s->modulation_pos = 0;
225 
226  switch (inlink->format) {
227  case AV_SAMPLE_FMT_DBL: s->phaser = phaser_dbl; break;
228  case AV_SAMPLE_FMT_DBLP: s->phaser = phaser_dblp; break;
229  case AV_SAMPLE_FMT_FLT: s->phaser = phaser_flt; break;
230  case AV_SAMPLE_FMT_FLTP: s->phaser = phaser_fltp; break;
231  case AV_SAMPLE_FMT_S16: s->phaser = phaser_s16; break;
232  case AV_SAMPLE_FMT_S16P: s->phaser = phaser_s16p; break;
233  case AV_SAMPLE_FMT_S32: s->phaser = phaser_s32; break;
234  case AV_SAMPLE_FMT_S32P: s->phaser = phaser_s32p; break;
235  default: av_assert0(0);
236  }
237 
238  return 0;
239 }
240 
241 static int filter_frame(AVFilterLink *inlink, AVFrame *inbuf)
242 {
243  AudioPhaserContext *s = inlink->dst->priv;
244  AVFilterLink *outlink = inlink->dst->outputs[0];
245  AVFrame *outbuf;
246 
247  if (av_frame_is_writable(inbuf)) {
248  outbuf = inbuf;
249  } else {
250  outbuf = ff_get_audio_buffer(inlink, inbuf->nb_samples);
251  if (!outbuf)
252  return AVERROR(ENOMEM);
253  av_frame_copy_props(outbuf, inbuf);
254  }
255 
256  s->phaser(s, inbuf->extended_data, outbuf->extended_data,
257  outbuf->nb_samples, av_frame_get_channels(outbuf));
258 
259  if (inbuf != outbuf)
260  av_frame_free(&inbuf);
261 
262  return ff_filter_frame(outlink, outbuf);
263 }
264 
266 {
267  AudioPhaserContext *s = ctx->priv;
268 
269  av_freep(&s->delay_buffer);
271 }
272 
273 static const AVFilterPad aphaser_inputs[] = {
274  {
275  .name = "default",
276  .type = AVMEDIA_TYPE_AUDIO,
277  .filter_frame = filter_frame,
278  },
279  { NULL }
280 };
281 
282 static const AVFilterPad aphaser_outputs[] = {
283  {
284  .name = "default",
285  .type = AVMEDIA_TYPE_AUDIO,
286  .config_props = config_output,
287  },
288  { NULL }
289 };
290 
292  .name = "aphaser",
293  .description = NULL_IF_CONFIG_SMALL("Add a phasing effect to the audio."),
294  .query_formats = query_formats,
295  .priv_size = sizeof(AudioPhaserContext),
296  .init = init,
297  .uninit = uninit,
298  .inputs = aphaser_inputs,
299  .outputs = aphaser_outputs,
300  .priv_class = &aphaser_class,
301 };
float, planar
Definition: samplefmt.h:69
#define NULL
Definition: coverity.c:32
int ff_set_common_channel_layouts(AVFilterContext *ctx, AVFilterChannelLayouts *layouts)
A helper for query_formats() which sets all links to the same list of channel layouts/sample rates...
Definition: formats.c:549
static const AVOption aphaser_options[]
Definition: af_aphaser.c:58
const char * s
Definition: avisynth_c.h:768
This structure describes decoded (raw) audio or video data.
Definition: frame.h:184
AVOption.
Definition: opt.h:245
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:182
Main libavfilter public API header.
static enum AVSampleFormat formats[]
Definition: avresample.c:163
double, planar
Definition: samplefmt.h:70
void * av_calloc(size_t nmemb, size_t size)
Non-inlined equivalent of av_mallocz_array().
Definition: mem.c:260
AVFilterFormats * ff_make_format_list(const int *fmts)
Create a list of supported formats.
Definition: formats.c:283
const char * name
Pad name.
Definition: internal.h:59
AVFilterLink ** inputs
array of pointers to input links
Definition: avfilter.h:315
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:1189
uint8_t
#define av_cold
Definition: attributes.h:82
AVOptions.
static const AVFilterPad aphaser_outputs[]
Definition: af_aphaser.c:282
static av_cold void uninit(AVFilterContext *ctx)
Definition: af_aphaser.c:265
signed 32 bits
Definition: samplefmt.h:62
#define av_log(a,...)
A filter pad used for either input or output.
Definition: internal.h:53
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
int ff_set_common_formats(AVFilterContext *ctx, AVFilterFormats *formats)
A helper for query_formats() which sets all links to the same list of formats.
Definition: formats.c:568
AVFrame * ff_get_audio_buffer(AVFilterLink *link, int nb_samples)
Request an audio samples buffer with a specific set of permissions.
Definition: audio.c:64
#define AVERROR(e)
Definition: error.h:43
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:158
#define PHASER(name, type)
Definition: af_aphaser.c:157
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:176
void * priv
private data for use by the filter
Definition: avfilter.h:322
#define FLAGS
Definition: af_aphaser.c:56
simple assert() macros that are a bit more flexible than ISO C assert().
static int config_output(AVFilterLink *outlink)
Definition: af_aphaser.c:203
static int filter_frame(AVFilterLink *inlink, AVFrame *inbuf)
Definition: af_aphaser.c:241
signed 32 bits, planar
Definition: samplefmt.h:68
typedef void(APIENTRY *FF_PFNGLACTIVETEXTUREPROC)(GLenum texture)
int32_t
AVFormatContext * ctx
Definition: movenc.c:48
static av_cold int init(AVFilterContext *ctx)
Definition: af_aphaser.c:74
static const AVFilterPad outputs[]
Definition: af_afftfilt.c:386
#define src
Definition: vp9dsp.c:530
void ff_generate_wave_table(enum WaveType wave_type, enum AVSampleFormat sample_fmt, void *table, int table_size, double min, double max, double phase)
A list of supported channel layouts.
Definition: formats.h:85
static const AVFilterPad inputs[]
Definition: af_afftfilt.c:376
AVSampleFormat
Audio sample formats.
Definition: samplefmt.h:58
int av_frame_is_writable(AVFrame *frame)
Check if the frame data is writable.
Definition: frame.c:529
AVFILTER_DEFINE_CLASS(aphaser)
GLint GLenum type
Definition: opengl_enc.c:105
double * delay_buffer
Definition: af_aphaser.c:43
#define OFFSET(x)
Definition: af_aphaser.c:55
Describe the class of an AVClass context structure.
Definition: log.h:67
int av_frame_get_channels(const AVFrame *frame)
Filter definition.
Definition: avfilter.h:144
const char * name
Filter name.
Definition: avfilter.h:148
AVFilterLink ** outputs
array of pointers to output links
Definition: avfilter.h:319
enum MovChannelLayoutTag * layouts
Definition: mov_chan.c:434
AVFilterFormats * ff_all_samplerates(void)
Definition: formats.c:395
void(* phaser)(struct AudioPhaserContext *s, uint8_t *const *src, uint8_t **dst, int nb_samples, int channels)
Definition: af_aphaser.c:50
AVFilter ff_af_aphaser
Definition: af_aphaser.c:291
int modulation_buffer_length
Definition: af_aphaser.c:45
signed 16 bits
Definition: samplefmt.h:61
static int query_formats(AVFilterContext *ctx)
Definition: af_aphaser.c:86
A list of supported formats for one end of a filter link.
Definition: formats.h:64
int32_t * modulation_buffer
Definition: af_aphaser.c:46
An instance of a filter.
Definition: avfilter.h:307
static enum AVSampleFormat sample_fmts[]
Definition: adpcmenc.c:701
static const AVFilterPad aphaser_inputs[]
Definition: af_aphaser.c:273
#define av_freep(p)
signed 16 bits, planar
Definition: samplefmt.h:67
#define M_PI
Definition: mathematics.h:52
#define av_malloc_array(a, b)
internal API functions
AVFilterChannelLayouts * ff_all_channel_counts(void)
Construct an AVFilterChannelLayouts coding for any channel layout, with known or unknown disposition...
Definition: formats.c:410
uint8_t ** extended_data
pointers to the data planes/channels.
Definition: frame.h:231
int nb_samples
number of audio samples (per channel) described by this frame
Definition: frame.h:241
#define PHASER_PLANAR(name, type)
Definition: af_aphaser.c:121
int ff_set_common_samplerates(AVFilterContext *ctx, AVFilterFormats *samplerates)
Definition: formats.c:556
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
Definition: frame.c:589