Browse code

lavfi: add sine audio source.

Nicolas George authored on 2013/03/17 00:33:05
Showing 6 changed files
... ...
@@ -10,6 +10,7 @@ version <next>:
10 10
 - perms and aperms filters
11 11
 - audio filtering support in ffplay
12 12
 - 10% faster aac encoding on x86 and MIPS
13
+- sine audio filter source
13 14
 
14 15
 
15 16
 version 1.2:
... ...
@@ -1653,6 +1653,57 @@ ffplay -f lavfi flite=text='No more be grieved for which that thou hast done.'
1653 1653
 For more information about libflite, check:
1654 1654
 @url{http://www.speech.cs.cmu.edu/flite/}
1655 1655
 
1656
+@section sine
1657
+
1658
+Generate an audio signal made of a sine wave with amplitude 1/8.
1659
+
1660
+The audio signal is bit-exact.
1661
+
1662
+It accepts a list of options in the form of @var{key}=@var{value} pairs
1663
+separated by ":". If the option name is omitted, the first option is the
1664
+frequency and the second option is the beep factor.
1665
+
1666
+The supported options are:
1667
+
1668
+@table @option
1669
+
1670
+@item frequency, f
1671
+Set the carrier frequency. Default is 440 Hz.
1672
+
1673
+@item beep_factor, b
1674
+Enable a periodic beep every second with frequency @var{beep_factor} times
1675
+the carrier frequency. Default is 0, meaning the beep is disabled.
1676
+
1677
+@item sample_rate, s
1678
+Specify the sample rate, default is 44100.
1679
+
1680
+@item duration, d
1681
+Specify the duration of the generated audio stream.
1682
+
1683
+@item samples_per_frame
1684
+Set the number of samples per output frame, default is 1024.
1685
+@end table
1686
+
1687
+@subsection Examples
1688
+
1689
+@itemize
1690
+
1691
+@item
1692
+Generate a simple 440 Hz sine wave:
1693
+@example
1694
+sine
1695
+@end example
1696
+
1697
+@item
1698
+Generate a 220 Hz sine wave with a 880 Hz beep each second, for 5 seconds:
1699
+@example
1700
+sine=220:4:d=5
1701
+sine=f=220:b=4:d=5
1702
+sine=frequency=220:beep_factor=4:duration=5
1703
+@end example
1704
+
1705
+@end itemize
1706
+
1656 1707
 @c man end AUDIO SOURCES
1657 1708
 
1658 1709
 @chapter Audio Sinks
... ...
@@ -90,6 +90,7 @@ OBJS-$(CONFIG_VOLUMEDETECT_FILTER)           += af_volumedetect.o
90 90
 OBJS-$(CONFIG_AEVALSRC_FILTER)               += asrc_aevalsrc.o
91 91
 OBJS-$(CONFIG_ANULLSRC_FILTER)               += asrc_anullsrc.o
92 92
 OBJS-$(CONFIG_FLITE_FILTER)                  += asrc_flite.o
93
+OBJS-$(CONFIG_SINE_FILTER)                   += asrc_sine.o
93 94
 
94 95
 OBJS-$(CONFIG_ANULLSINK_FILTER)              += asink_anullsink.o
95 96
 
... ...
@@ -86,6 +86,7 @@ void avfilter_register_all(void)
86 86
     REGISTER_FILTER(AEVALSRC,       aevalsrc,       asrc);
87 87
     REGISTER_FILTER(ANULLSRC,       anullsrc,       asrc);
88 88
     REGISTER_FILTER(FLITE,          flite,          asrc);
89
+    REGISTER_FILTER(SINE,           sine,           asrc);
89 90
 
90 91
     REGISTER_FILTER(ANULLSINK,      anullsink,      asink);
91 92
 
92 93
new file mode 100644
... ...
@@ -0,0 +1,228 @@
0
+/*
1
+ * Copyright (c) 2013 Nicolas George
2
+ *
3
+ * This file is part of FFmpeg.
4
+ *
5
+ * FFmpeg is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public License
7
+ * as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * FFmpeg is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
+ * GNU Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public License
16
+ * along with FFmpeg; if not, write to the Free Software Foundation, Inc.,
17
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
+ */
19
+
20
+#include "libavutil/avassert.h"
21
+#include "libavutil/channel_layout.h"
22
+#include "libavutil/opt.h"
23
+#include "audio.h"
24
+#include "avfilter.h"
25
+#include "internal.h"
26
+
27
+typedef struct {
28
+    const AVClass *class;
29
+    double frequency;
30
+    double beep_factor;
31
+    int samples_per_frame;
32
+    int sample_rate;
33
+    int64_t duration;
34
+    int16_t *sin;
35
+    int64_t pts;
36
+    uint32_t phi;  ///< current phase of the sine (2pi = 1<<32)
37
+    uint32_t dphi; ///< phase increment between two samples
38
+    unsigned beep_period;
39
+    unsigned beep_index;
40
+    unsigned beep_length;
41
+    uint32_t phi_beep;  ///< current phase of the beep
42
+    uint32_t dphi_beep; ///< phase increment of the beep
43
+} SineContext;
44
+
45
+#define CONTEXT SineContext
46
+#define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
47
+
48
+#define OPT_GENERIC(name, field, def, min, max, descr, type, deffield, ...) \
49
+    { name, descr, offsetof(CONTEXT, field), AV_OPT_TYPE_ ## type,          \
50
+      { .deffield = def }, min, max, FLAGS, __VA_ARGS__ }
51
+
52
+#define OPT_INT(name, field, def, min, max, descr, ...) \
53
+    OPT_GENERIC(name, field, def, min, max, descr, INT, i64, __VA_ARGS__)
54
+
55
+#define OPT_DBL(name, field, def, min, max, descr, ...) \
56
+    OPT_GENERIC(name, field, def, min, max, descr, DOUBLE, dbl, __VA_ARGS__)
57
+
58
+#define OPT_DUR(name, field, def, min, max, descr, ...) \
59
+    OPT_GENERIC(name, field, def, min, max, descr, DURATION, str, __VA_ARGS__)
60
+
61
+static const AVOption sine_options[] = {
62
+    OPT_DBL("frequency",         frequency,            440, 0, INFINITY,  "set the sine frequency"),
63
+    OPT_DBL("f",                 frequency,            440, 0, INFINITY,  "set the sine frequency"),
64
+    OPT_DBL("beep_factor",       beep_factor,            0, 0, INFINITY,  "set the beep fequency factor"),
65
+    OPT_DBL("b",                 beep_factor,            0, 0, INFINITY,  "set the beep fequency factor"),
66
+    OPT_INT("sample_rate",       sample_rate,        44100, 1, INT_MAX,   "set the sample rate"),
67
+    OPT_INT("r",                 sample_rate,        44100, 1, INT_MAX,   "set the sample rate"),
68
+    OPT_DUR("duration",          duration,               0, 0, INT64_MAX, "set the audio duration"),
69
+    OPT_DUR("d",                 duration,               0, 0, INT64_MAX, "set the audio duration"),
70
+    OPT_INT("samples_per_frame", samples_per_frame,   1024, 0, INT_MAX,   "set the number of samples per frame"),
71
+    {NULL},
72
+};
73
+
74
+AVFILTER_DEFINE_CLASS(sine);
75
+
76
+#define LOG_PERIOD 15
77
+#define AMPLITUDE 4095
78
+#define AMPLITUDE_SHIFT 3
79
+
80
+static void make_sin_table(int16_t *sin)
81
+{
82
+    unsigned half_pi = 1 << (LOG_PERIOD - 2);
83
+    unsigned ampls = AMPLITUDE << AMPLITUDE_SHIFT;
84
+    uint64_t unit2 = (uint64_t)(ampls * ampls) << 32;
85
+    unsigned step, i, c, s, k, new_k, n2;
86
+
87
+    /* Principle: if u = exp(i*a1) and v = exp(i*a2), then
88
+       exp(i*(a1+a2)/2) = (u+v) / length(u+v) */
89
+    sin[0] = 0;
90
+    sin[half_pi] = ampls;
91
+    for (step = half_pi; step > 1; step /= 2) {
92
+        /* k = (1 << 16) * amplitude / length(u+v)
93
+           In exact values, k is constant at a given step */
94
+        k = 0x10000;
95
+        for (i = 0; i < half_pi / 2; i += step) {
96
+            s = sin[i] + sin[i + step];
97
+            c = sin[half_pi - i] + sin[half_pi - i - step];
98
+            n2 = s * s + c * c;
99
+            /* Newton's method to solve n² * k² = unit² */
100
+            while (1) {
101
+                new_k = (k + unit2 / ((uint64_t)k * n2) + 1) >> 1;
102
+                if (k == new_k)
103
+                    break;
104
+                k = new_k;
105
+            }
106
+            sin[i + step / 2] = (k * s + 0x7FFF) >> 16;
107
+            sin[half_pi - i - step / 2] = (k * c + 0x8000) >> 16;
108
+        }
109
+    }
110
+    /* Unshift amplitude */
111
+    for (i = 0; i <= half_pi; i++)
112
+        sin[i] = (sin[i] + (1 << (AMPLITUDE_SHIFT - 1))) >> AMPLITUDE_SHIFT;
113
+    /* Use symmetries to fill the other three quarters */
114
+    for (i = 0; i < half_pi; i++)
115
+        sin[half_pi * 2 - i] = sin[i];
116
+    for (i = 0; i < 2 * half_pi; i++)
117
+        sin[i + 2 * half_pi] = -sin[i];
118
+}
119
+
120
+static av_cold int init(AVFilterContext *ctx, const char *args)
121
+{
122
+    SineContext *sine = ctx->priv;
123
+    static const char *shorthand[] = { "frequency", "beep_factor", NULL };
124
+    int ret;
125
+
126
+    sine->class = &sine_class;
127
+    av_opt_set_defaults(sine);
128
+
129
+    if ((ret = av_opt_set_from_string(sine, args, shorthand, "=", ":")) < 0)
130
+        return ret;
131
+    if (!(sine->sin = av_malloc(sizeof(*sine->sin) << LOG_PERIOD)))
132
+        return AVERROR(ENOMEM);
133
+    sine->dphi = ldexp(sine->frequency, 32) / sine->sample_rate + 0.5;
134
+    make_sin_table(sine->sin);
135
+
136
+    if (sine->beep_factor) {
137
+        sine->beep_period = sine->sample_rate;
138
+        sine->beep_length = sine->beep_period / 25;
139
+        sine->dphi_beep = ldexp(sine->beep_factor * sine->frequency, 32) /
140
+                          sine->sample_rate + 0.5;
141
+    }
142
+
143
+    return 0;
144
+}
145
+
146
+static av_cold void uninit(AVFilterContext *ctx)
147
+{
148
+    SineContext *sine = ctx->priv;
149
+
150
+    av_freep(&sine->sin);
151
+}
152
+
153
+static av_cold int query_formats(AVFilterContext *ctx)
154
+{
155
+    SineContext *sine = ctx->priv;
156
+    static const int64_t chlayouts[] = { AV_CH_LAYOUT_MONO, -1 };
157
+    int sample_rates[] = { sine->sample_rate, -1 };
158
+    static const enum AVSampleFormat sample_fmts[] = { AV_SAMPLE_FMT_S16,
159
+                                                       AV_SAMPLE_FMT_NONE };
160
+
161
+    ff_set_common_formats (ctx, ff_make_format_list(sample_fmts));
162
+    ff_set_common_channel_layouts(ctx, avfilter_make_format64_list(chlayouts));
163
+    ff_set_common_samplerates(ctx, ff_make_format_list(sample_rates));
164
+    return 0;
165
+}
166
+
167
+static av_cold int config_props(AVFilterLink *outlink)
168
+{
169
+    SineContext *sine = outlink->src->priv;
170
+    sine->duration = av_rescale(sine->duration, sine->sample_rate, AV_TIME_BASE);
171
+    return 0;
172
+}
173
+
174
+static int request_frame(AVFilterLink *outlink)
175
+{
176
+    SineContext *sine = outlink->src->priv;
177
+    AVFrame *frame;
178
+    int i, nb_samples = sine->samples_per_frame;
179
+    int16_t *samples;
180
+
181
+    if (sine->duration) {
182
+        nb_samples = FFMIN(nb_samples, sine->duration - sine->pts);
183
+        av_assert1(nb_samples >= 0);
184
+        if (!nb_samples)
185
+            return AVERROR_EOF;
186
+    }
187
+    if (!(frame = ff_get_audio_buffer(outlink, nb_samples)))
188
+        return AVERROR(ENOMEM);
189
+    samples = (int16_t *)frame->data[0];
190
+
191
+    for (i = 0; i < nb_samples; i++) {
192
+        samples[i] = sine->sin[sine->phi >> (32 - LOG_PERIOD)];
193
+        sine->phi += sine->dphi;
194
+        if (sine->beep_index < sine->beep_length) {
195
+            samples[i] += sine->sin[sine->phi_beep >> (32 - LOG_PERIOD)] << 1;
196
+            sine->phi_beep += sine->dphi_beep;
197
+        }
198
+        if (++sine->beep_index == sine->beep_period)
199
+            sine->beep_index = 0;
200
+    }
201
+
202
+    frame->pts = sine->pts;
203
+    sine->pts += nb_samples;
204
+    return ff_filter_frame(outlink, frame);
205
+}
206
+
207
+static const AVFilterPad sine_outputs[] = {
208
+    {
209
+        .name          = "default",
210
+        .type          = AVMEDIA_TYPE_AUDIO,
211
+        .request_frame = request_frame,
212
+        .config_props  = config_props,
213
+    },
214
+    { NULL }
215
+};
216
+
217
+AVFilter avfilter_asrc_sine = {
218
+    .name          = "sine",
219
+    .description   = NULL_IF_CONFIG_SMALL("Generate sine wave audio signal."),
220
+    .query_formats = query_formats,
221
+    .init          = init,
222
+    .uninit        = uninit,
223
+    .priv_size     = sizeof(SineContext),
224
+    .inputs        = NULL,
225
+    .outputs       = sine_outputs,
226
+    .priv_class    = &sine_class,
227
+};
... ...
@@ -29,8 +29,8 @@
29 29
 #include "libavutil/avutil.h"
30 30
 
31 31
 #define LIBAVFILTER_VERSION_MAJOR  3
32
-#define LIBAVFILTER_VERSION_MINOR  47
33
-#define LIBAVFILTER_VERSION_MICRO 104
32
+#define LIBAVFILTER_VERSION_MINOR  48
33
+#define LIBAVFILTER_VERSION_MICRO 100
34 34
 
35 35
 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \
36 36
                                                LIBAVFILTER_VERSION_MINOR, \