FFmpeg
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
Examples
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
libavfilter
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
42
int
delay_buffer_length
;
43
double
*
delay_buffer
;
44
45
int
modulation_buffer_length
;
46
int32_t
*
modulation_buffer
;
47
48
int
delay_pos
,
modulation_pos
;
49
50
void
(*
phaser
)(
struct
AudioPhaserContext
*p,
51
uint8_t
*
const
*
src
,
uint8_t
**dst,
52
int
nb_samples,
int
channels);
53
}
AudioPhaserContext
;
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
74
static
av_cold
int
init
(
AVFilterContext
*ctx)
75
{
76
AudioPhaserContext
*p = ctx->
priv
;
77
78
if
(p->
in_gain
> (1 - p->
decay
* p->
decay
))
79
av_log
(ctx,
AV_LOG_WARNING
,
"in_gain may cause clipping\n"
);
80
if
(p->
in_gain
/ (1 - p->
decay
) > 1 / p->
out_gain
)
81
av_log
(ctx,
AV_LOG_WARNING
,
"out_gain may cause clipping\n"
);
82
83
return
0;
84
}
85
86
static
int
query_formats
(
AVFilterContext
*ctx)
87
{
88
AVFilterFormats
*
formats
;
89
AVFilterChannelLayouts
*
layouts
;
90
static
const
enum
AVSampleFormat
sample_fmts
[] = {
91
AV_SAMPLE_FMT_DBL
,
AV_SAMPLE_FMT_DBLP
,
92
AV_SAMPLE_FMT_FLT
,
AV_SAMPLE_FMT_FLTP
,
93
AV_SAMPLE_FMT_S32
,
AV_SAMPLE_FMT_S32P
,
94
AV_SAMPLE_FMT_S16
,
AV_SAMPLE_FMT_S16P
,
95
AV_SAMPLE_FMT_NONE
96
};
97
98
layouts =
ff_all_channel_layouts
();
99
if
(!layouts)
100
return
AVERROR
(ENOMEM);
101
ff_set_common_channel_layouts
(ctx, layouts);
102
103
formats =
ff_make_format_list
(sample_fmts);
104
if
(!formats)
105
return
AVERROR
(ENOMEM);
106
ff_set_common_formats
(ctx, formats);
107
108
formats =
ff_all_samplerates
();
109
if
(!formats)
110
return
AVERROR
(ENOMEM);
111
ff_set_common_samplerates
(ctx, formats);
112
113
return
0;
114
}
115
116
#define MOD(a, b) (((a) >= (b)) ? (a) - (b) : (a))
117
118
#define PHASER_PLANAR(name, type) \
119
static void phaser_## name ##p(AudioPhaserContext *p, \
120
uint8_t * const *src, uint8_t **dst, \
121
int nb_samples, int channels) \
122
{ \
123
int i, c, delay_pos, modulation_pos; \
124
\
125
av_assert0(channels > 0); \
126
for (c = 0; c < channels; c++) { \
127
type *s = (type *)src[c]; \
128
type *d = (type *)dst[c]; \
129
double *buffer = p->delay_buffer + \
130
c * p->delay_buffer_length; \
131
\
132
delay_pos = p->delay_pos; \
133
modulation_pos = p->modulation_pos; \
134
\
135
for (i = 0; i < nb_samples; i++, s++, d++) { \
136
double v = *s * p->in_gain + buffer[ \
137
MOD(delay_pos + p->modulation_buffer[ \
138
modulation_pos], \
139
p->delay_buffer_length)] * p->decay; \
140
\
141
modulation_pos = MOD(modulation_pos + 1, \
142
p->modulation_buffer_length); \
143
delay_pos = MOD(delay_pos + 1, p->delay_buffer_length); \
144
buffer[delay_pos] = v; \
145
\
146
*d = v * p->out_gain; \
147
} \
148
} \
149
\
150
p->delay_pos = delay_pos; \
151
p->modulation_pos = modulation_pos; \
152
}
153
154
#define PHASER(name, type) \
155
static void phaser_## name (AudioPhaserContext *p, \
156
uint8_t * const *src, uint8_t **dst, \
157
int nb_samples, int channels) \
158
{ \
159
int i, c, delay_pos, modulation_pos; \
160
type *s = (type *)src[0]; \
161
type *d = (type *)dst[0]; \
162
double *buffer = p->delay_buffer; \
163
\
164
delay_pos = p->delay_pos; \
165
modulation_pos = p->modulation_pos; \
166
\
167
for (i = 0; i < nb_samples; i++) { \
168
int pos = MOD(delay_pos + p->modulation_buffer[modulation_pos], \
169
p->delay_buffer_length) * channels; \
170
int npos; \
171
\
172
delay_pos = MOD(delay_pos + 1, p->delay_buffer_length); \
173
npos = delay_pos * channels; \
174
for (c = 0; c < channels; c++, s++, d++) { \
175
double v = *s * p->in_gain + buffer[pos + c] * p->decay; \
176
\
177
buffer[npos + c] = v; \
178
\
179
*d = v * p->out_gain; \
180
} \
181
\
182
modulation_pos = MOD(modulation_pos + 1, \
183
p->modulation_buffer_length); \
184
} \
185
\
186
p->delay_pos = delay_pos; \
187
p->modulation_pos = modulation_pos; \
188
}
189
190
PHASER_PLANAR
(dbl,
double
)
191
PHASER_PLANAR
(flt,
float
)
192
PHASER_PLANAR
(s16, int16_t)
193
PHASER_PLANAR
(s32,
int32_t
)
194
195
PHASER
(dbl,
double
)
196
PHASER
(flt,
float
)
197
PHASER
(s16, int16_t)
198
PHASER
(s32,
int32_t
)
199
200
static
int
config_output
(
AVFilterLink
*outlink)
201
{
202
AudioPhaserContext
*p = outlink->src->priv;
203
AVFilterLink
*inlink = outlink->
src
->
inputs
[0];
204
205
p->
delay_buffer_length
= p->
delay
* 0.001 * inlink->
sample_rate
+ 0.5;
206
p->
delay_buffer
=
av_calloc
(p->
delay_buffer_length
,
sizeof
(*p->
delay_buffer
) * inlink->
channels
);
207
p->
modulation_buffer_length
= inlink->
sample_rate
/ p->
speed
+ 0.5;
208
p->
modulation_buffer
=
av_malloc_array
(p->
modulation_buffer_length
,
sizeof
(*p->
modulation_buffer
));
209
210
if
(!p->
modulation_buffer
|| !p->
delay_buffer
)
211
return
AVERROR
(ENOMEM);
212
213
ff_generate_wave_table
(p->
type
,
AV_SAMPLE_FMT_S32
,
214
p->
modulation_buffer
, p->
modulation_buffer_length
,
215
1., p->
delay_buffer_length
,
M_PI
/ 2.0);
216
217
p->
delay_pos
= p->
modulation_pos
= 0;
218
219
switch
(inlink->
format
) {
220
case
AV_SAMPLE_FMT_DBL
: p->
phaser
= phaser_dbl;
break
;
221
case
AV_SAMPLE_FMT_DBLP
: p->
phaser
= phaser_dblp;
break
;
222
case
AV_SAMPLE_FMT_FLT
: p->
phaser
= phaser_flt;
break
;
223
case
AV_SAMPLE_FMT_FLTP
: p->
phaser
= phaser_fltp;
break
;
224
case
AV_SAMPLE_FMT_S16
: p->
phaser
= phaser_s16;
break
;
225
case
AV_SAMPLE_FMT_S16P
: p->
phaser
= phaser_s16p;
break
;
226
case
AV_SAMPLE_FMT_S32
: p->
phaser
= phaser_s32;
break
;
227
case
AV_SAMPLE_FMT_S32P
: p->
phaser
= phaser_s32p;
break
;
228
default
:
av_assert0
(0);
229
}
230
231
return
0;
232
}
233
234
static
int
filter_frame
(
AVFilterLink
*inlink,
AVFrame
*inbuf)
235
{
236
AudioPhaserContext
*p = inlink->
dst
->
priv
;
237
AVFilterLink
*outlink = inlink->
dst
->
outputs
[0];
238
AVFrame
*outbuf;
239
240
if
(
av_frame_is_writable
(inbuf)) {
241
outbuf = inbuf;
242
}
else
{
243
outbuf =
ff_get_audio_buffer
(inlink, inbuf->
nb_samples
);
244
if
(!outbuf)
245
return
AVERROR
(ENOMEM);
246
av_frame_copy_props
(outbuf, inbuf);
247
}
248
249
p->
phaser
(p, inbuf->
extended_data
, outbuf->
extended_data
,
250
outbuf->
nb_samples
,
av_frame_get_channels
(outbuf));
251
252
if
(inbuf != outbuf)
253
av_frame_free
(&inbuf);
254
255
return
ff_filter_frame
(outlink, outbuf);
256
}
257
258
static
av_cold
void
uninit
(
AVFilterContext
*ctx)
259
{
260
AudioPhaserContext
*p = ctx->
priv
;
261
262
av_freep
(&p->
delay_buffer
);
263
av_freep
(&p->
modulation_buffer
);
264
}
265
266
static
const
AVFilterPad
aphaser_inputs
[] = {
267
{
268
.
name
=
"default"
,
269
.type =
AVMEDIA_TYPE_AUDIO
,
270
.filter_frame =
filter_frame
,
271
},
272
{
NULL
}
273
};
274
275
static
const
AVFilterPad
aphaser_outputs
[] = {
276
{
277
.
name
=
"default"
,
278
.type =
AVMEDIA_TYPE_AUDIO
,
279
.config_props =
config_output
,
280
},
281
{
NULL
}
282
};
283
284
AVFilter
ff_af_aphaser
= {
285
.
name
=
"aphaser"
,
286
.description =
NULL_IF_CONFIG_SMALL
(
"Add a phasing effect to the audio."
),
287
.query_formats =
query_formats
,
288
.priv_size =
sizeof
(
AudioPhaserContext
),
289
.
init
=
init
,
290
.
uninit
=
uninit
,
291
.
inputs
= aphaser_inputs,
292
.
outputs
= aphaser_outputs,
293
.priv_class = &aphaser_class,
294
};
Generated on Sun Mar 8 2015 02:35:05 for FFmpeg by
1.8.2