~ubuntu-branches/ubuntu/vivid/ffmpeg/vivid

« back to all changes in this revision

Viewing changes to libavfilter/af_aphaser.c

  • Committer: Package Import Robot
  • Author(s): Andreas Cadhalpun
  • Date: 2014-11-05 01:18:23 UTC
  • mfrom: (0.2.17 sid)
  • Revision ID: package-import@ubuntu.com-20141105011823-xsbeceffs43wtkn7
Tags: 7:2.4.3-1
* Import new upstream bugfix release 2.4.3.
   - Refresh Change-symbol-versioning.patch.
   - Add new symbols to the libavdevice symbols file.
* Enable libbs2b on arm64, since it is now available.
* Disable frei0r and libx264 on x32, libsoxr and openal on sparc64
  and libopencv on m68k, sh4, sparc64 and x32, because they are not
  (yet) avialable there.
* Disable assembler optimizations on x32, as they wouldn't work there.
* Include config.log in the build-log, when compiling fails.
* Add fix-hppa-tests.patch to work around a gcc bug on hppa.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
    enum WaveType 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
};