2 * Copyright (c) 2013 Nicolas George
4 * This file is part of FFmpeg.
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public License
8 * as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
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
14 * GNU Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with FFmpeg; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 #include "libavutil/avassert.h"
24 #include "libavutil/channel_layout.h"
25 #include "libavutil/opt.h"
34 int samples_per_frame
;
39 uint32_t phi
; ///< current phase of the sine (2pi = 1<<32)
40 uint32_t dphi
; ///< phase increment between two samples
44 uint32_t phi_beep
; ///< current phase of the beep
45 uint32_t dphi_beep
; ///< phase increment of the beep
48 #define CONTEXT SineContext
49 #define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
51 #define OPT_GENERIC(name, field, def, min, max, descr, type, deffield, ...) \
52 { name, descr, offsetof(CONTEXT, field), AV_OPT_TYPE_ ## type, \
53 { .deffield = def }, min, max, FLAGS, __VA_ARGS__ }
55 #define OPT_INT(name, field, def, min, max, descr, ...) \
56 OPT_GENERIC(name, field, def, min, max, descr, INT, i64, __VA_ARGS__)
58 #define OPT_DBL(name, field, def, min, max, descr, ...) \
59 OPT_GENERIC(name, field, def, min, max, descr, DOUBLE, dbl, __VA_ARGS__)
61 #define OPT_DUR(name, field, def, min, max, descr, ...) \
62 OPT_GENERIC(name, field, def, min, max, descr, DURATION, str, __VA_ARGS__)
64 static const AVOption sine_options
[] = {
65 OPT_DBL("frequency", frequency
, 440, 0, DBL_MAX
, "set the sine frequency"),
66 OPT_DBL("f", frequency
, 440, 0, DBL_MAX
, "set the sine frequency"),
67 OPT_DBL("beep_factor", beep_factor
, 0, 0, DBL_MAX
, "set the beep fequency factor"),
68 OPT_DBL("b", beep_factor
, 0, 0, DBL_MAX
, "set the beep fequency factor"),
69 OPT_INT("sample_rate", sample_rate
, 44100, 1, INT_MAX
, "set the sample rate"),
70 OPT_INT("r", sample_rate
, 44100, 1, INT_MAX
, "set the sample rate"),
71 OPT_DUR("duration", duration
, 0, 0, INT64_MAX
, "set the audio duration"),
72 OPT_DUR("d", duration
, 0, 0, INT64_MAX
, "set the audio duration"),
73 OPT_INT("samples_per_frame", samples_per_frame
, 1024, 0, INT_MAX
, "set the number of samples per frame"),
77 AVFILTER_DEFINE_CLASS(sine
);
80 #define AMPLITUDE 4095
81 #define AMPLITUDE_SHIFT 3
83 static void make_sin_table(int16_t *sin
)
85 unsigned half_pi
= 1 << (LOG_PERIOD
- 2);
86 unsigned ampls
= AMPLITUDE
<< AMPLITUDE_SHIFT
;
87 uint64_t unit2
= (uint64_t)(ampls
* ampls
) << 32;
88 unsigned step
, i
, c
, s
, k
, new_k
, n2
;
90 /* Principle: if u = exp(i*a1) and v = exp(i*a2), then
91 exp(i*(a1+a2)/2) = (u+v) / length(u+v) */
94 for (step
= half_pi
; step
> 1; step
/= 2) {
95 /* k = (1 << 16) * amplitude / length(u+v)
96 In exact values, k is constant at a given step */
98 for (i
= 0; i
< half_pi
/ 2; i
+= step
) {
99 s
= sin
[i
] + sin
[i
+ step
];
100 c
= sin
[half_pi
- i
] + sin
[half_pi
- i
- step
];
102 /* Newton's method to solve n² * k² = unit² */
104 new_k
= (k
+ unit2
/ ((uint64_t)k
* n2
) + 1) >> 1;
109 sin
[i
+ step
/ 2] = (k
* s
+ 0x7FFF) >> 16;
110 sin
[half_pi
- i
- step
/ 2] = (k
* c
+ 0x8000) >> 16;
113 /* Unshift amplitude */
114 for (i
= 0; i
<= half_pi
; i
++)
115 sin
[i
] = (sin
[i
] + (1 << (AMPLITUDE_SHIFT
- 1))) >> AMPLITUDE_SHIFT
;
116 /* Use symmetries to fill the other three quarters */
117 for (i
= 0; i
< half_pi
; i
++)
118 sin
[half_pi
* 2 - i
] = sin
[i
];
119 for (i
= 0; i
< 2 * half_pi
; i
++)
120 sin
[i
+ 2 * half_pi
] = -sin
[i
];
123 static av_cold
int init(AVFilterContext
*ctx
)
125 SineContext
*sine
= ctx
->priv
;
127 if (!(sine
->sin
= av_malloc(sizeof(*sine
->sin
) << LOG_PERIOD
)))
128 return AVERROR(ENOMEM
);
129 sine
->dphi
= ldexp(sine
->frequency
, 32) / sine
->sample_rate
+ 0.5;
130 make_sin_table(sine
->sin
);
132 if (sine
->beep_factor
) {
133 sine
->beep_period
= sine
->sample_rate
;
134 sine
->beep_length
= sine
->beep_period
/ 25;
135 sine
->dphi_beep
= ldexp(sine
->beep_factor
* sine
->frequency
, 32) /
136 sine
->sample_rate
+ 0.5;
142 static av_cold
void uninit(AVFilterContext
*ctx
)
144 SineContext
*sine
= ctx
->priv
;
146 av_freep(&sine
->sin
);
149 static av_cold
int query_formats(AVFilterContext
*ctx
)
151 SineContext
*sine
= ctx
->priv
;
152 static const int64_t chlayouts
[] = { AV_CH_LAYOUT_MONO
, -1 };
153 int sample_rates
[] = { sine
->sample_rate
, -1 };
154 static const enum AVSampleFormat sample_fmts
[] = { AV_SAMPLE_FMT_S16
,
155 AV_SAMPLE_FMT_NONE
};
157 ff_set_common_formats (ctx
, ff_make_format_list(sample_fmts
));
158 ff_set_common_channel_layouts(ctx
, avfilter_make_format64_list(chlayouts
));
159 ff_set_common_samplerates(ctx
, ff_make_format_list(sample_rates
));
163 static av_cold
int config_props(AVFilterLink
*outlink
)
165 SineContext
*sine
= outlink
->src
->priv
;
166 sine
->duration
= av_rescale(sine
->duration
, sine
->sample_rate
, AV_TIME_BASE
);
170 static int request_frame(AVFilterLink
*outlink
)
172 SineContext
*sine
= outlink
->src
->priv
;
174 int i
, nb_samples
= sine
->samples_per_frame
;
177 if (sine
->duration
) {
178 nb_samples
= FFMIN(nb_samples
, sine
->duration
- sine
->pts
);
179 av_assert1(nb_samples
>= 0);
183 if (!(frame
= ff_get_audio_buffer(outlink
, nb_samples
)))
184 return AVERROR(ENOMEM
);
185 samples
= (int16_t *)frame
->data
[0];
187 for (i
= 0; i
< nb_samples
; i
++) {
188 samples
[i
] = sine
->sin
[sine
->phi
>> (32 - LOG_PERIOD
)];
189 sine
->phi
+= sine
->dphi
;
190 if (sine
->beep_index
< sine
->beep_length
) {
191 samples
[i
] += sine
->sin
[sine
->phi_beep
>> (32 - LOG_PERIOD
)] << 1;
192 sine
->phi_beep
+= sine
->dphi_beep
;
194 if (++sine
->beep_index
== sine
->beep_period
)
195 sine
->beep_index
= 0;
198 frame
->pts
= sine
->pts
;
199 sine
->pts
+= nb_samples
;
200 return ff_filter_frame(outlink
, frame
);
203 static const AVFilterPad sine_outputs
[] = {
206 .type
= AVMEDIA_TYPE_AUDIO
,
207 .request_frame
= request_frame
,
208 .config_props
= config_props
,
213 AVFilter ff_asrc_sine
= {
215 .description
= NULL_IF_CONFIG_SMALL("Generate sine wave audio signal."),
216 .query_formats
= query_formats
,
219 .priv_size
= sizeof(SineContext
),
221 .outputs
= sine_outputs
,
222 .priv_class
= &sine_class
,