Commit a388ca35 authored by Clément Bœsch's avatar Clément Bœsch

avfilter/sine: support expression in the number of output samples

parent db18b3d6
......@@ -2857,7 +2857,26 @@ Specify the sample rate, default is 44100.
Specify the duration of the generated audio stream.
@item samples_per_frame
Set the number of samples per output frame, default is 1024.
Set the number of samples per output frame.
The expression can contain the following constants:
@table @option
@item n
The (sequential) number of the output audio frame, starting from 0.
@item pts
The PTS (Presentation TimeStamp) of the output audio frame,
expressed in @var{TB} units.
@item t
The PTS of the output audio frame, expressed in seconds.
@item TB
The timebase of the output audio frames.
@end table
Default is @code{1024}.
@end table
@subsection Examples
......@@ -2878,6 +2897,12 @@ sine=f=220:b=4:d=5
sine=frequency=220:beep_factor=4:duration=5
@end example
@item
Generate a 1 kHz sine wave following @code{1602,1601,1602,1601,1602} NTSC
pattern:
@example
sine=1000:samples_per_frame='st(0,mod(n,5)); 1602-not(not(eq(ld(0),1)+eq(ld(0),3)))'
@end example
@end itemize
@c man end AUDIO SOURCES
......
......@@ -22,6 +22,7 @@
#include "libavutil/avassert.h"
#include "libavutil/channel_layout.h"
#include "libavutil/eval.h"
#include "libavutil/opt.h"
#include "audio.h"
#include "avfilter.h"
......@@ -31,7 +32,8 @@ typedef struct {
const AVClass *class;
double frequency;
double beep_factor;
int samples_per_frame;
char *samples_per_frame;
AVExpr *samples_per_frame_expr;
int sample_rate;
int64_t duration;
int16_t *sin;
......@@ -61,6 +63,9 @@ typedef struct {
#define OPT_DUR(name, field, def, min, max, descr, ...) \
OPT_GENERIC(name, field, def, min, max, descr, DURATION, str, __VA_ARGS__)
#define OPT_STR(name, field, def, min, max, descr, ...) \
OPT_GENERIC(name, field, def, min, max, descr, STRING, str, __VA_ARGS__)
static const AVOption sine_options[] = {
OPT_DBL("frequency", frequency, 440, 0, DBL_MAX, "set the sine frequency"),
OPT_DBL("f", frequency, 440, 0, DBL_MAX, "set the sine frequency"),
......@@ -70,7 +75,7 @@ static const AVOption sine_options[] = {
OPT_INT("r", sample_rate, 44100, 1, INT_MAX, "set the sample rate"),
OPT_DUR("duration", duration, 0, 0, INT64_MAX, "set the audio duration"),
OPT_DUR("d", duration, 0, 0, INT64_MAX, "set the audio duration"),
OPT_INT("samples_per_frame", samples_per_frame, 1024, 0, INT_MAX, "set the number of samples per frame"),
OPT_STR("samples_per_frame", samples_per_frame, "1024", 0, 0, "set the number of samples per frame"),
{NULL}
};
......@@ -120,8 +125,25 @@ static void make_sin_table(int16_t *sin)
sin[i + 2 * half_pi] = -sin[i];
}
static const char *const var_names[] = {
"n",
"pts",
"t",
"TB",
NULL
};
enum {
VAR_N,
VAR_PTS,
VAR_T,
VAR_TB,
VAR_VARS_NB
};
static av_cold int init(AVFilterContext *ctx)
{
int ret;
SineContext *sine = ctx->priv;
if (!(sine->sin = av_malloc(sizeof(*sine->sin) << LOG_PERIOD)))
......@@ -136,6 +158,12 @@ static av_cold int init(AVFilterContext *ctx)
sine->sample_rate + 0.5;
}
ret = av_expr_parse(&sine->samples_per_frame_expr,
sine->samples_per_frame, var_names,
NULL, NULL, NULL, NULL, 0, sine);
if (ret < 0)
return ret;
return 0;
}
......@@ -143,6 +171,8 @@ static av_cold void uninit(AVFilterContext *ctx)
{
SineContext *sine = ctx->priv;
av_expr_free(sine->samples_per_frame_expr);
sine->samples_per_frame_expr = NULL;
av_freep(&sine->sin);
}
......@@ -188,9 +218,21 @@ static int request_frame(AVFilterLink *outlink)
{
SineContext *sine = outlink->src->priv;
AVFrame *frame;
int i, nb_samples = sine->samples_per_frame;
double values[VAR_VARS_NB] = {
[VAR_N] = outlink->frame_count,
[VAR_PTS] = sine->pts,
[VAR_T] = sine->pts * av_q2d(outlink->time_base),
[VAR_TB] = av_q2d(outlink->time_base),
};
int i, nb_samples = lrint(av_expr_eval(sine->samples_per_frame_expr, values, sine));
int16_t *samples;
if (nb_samples <= 0) {
av_log(sine, AV_LOG_WARNING, "nb samples expression evaluated to %d, "
"defaulting to 1024\n", nb_samples);
nb_samples = 1024;
}
if (sine->duration) {
nb_samples = FFMIN(nb_samples, sine->duration - sine->pts);
av_assert1(nb_samples >= 0);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment