[FFmpeg-cvslog] avfilter/sine: support expression in the number of output samples
Clément Bœsch
git at videolan.org
Sun Sep 6 15:29:20 CEST 2015
ffmpeg | branch: master | Clément Bœsch <u at pkh.me> | Mon Aug 10 21:03:11 2015 +0200| [a388ca359d78c6fa00c75b326ada11048b1226ba] | committer: Clément Bœsch
avfilter/sine: support expression in the number of output samples
> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=a388ca359d78c6fa00c75b326ada11048b1226ba
---
doc/filters.texi | 27 +++++++++++++++++++++++++-
libavfilter/asrc_sine.c | 48 ++++++++++++++++++++++++++++++++++++++++++++---
2 files changed, 71 insertions(+), 4 deletions(-)
diff --git a/doc/filters.texi b/doc/filters.texi
index d506d68..7b9d665 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -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:
+
+ at table @option
+ at item n
+The (sequential) number of the output audio frame, starting from 0.
+
+ at item pts
+The PTS (Presentation TimeStamp) of the output audio frame,
+expressed in @var{TB} units.
+
+ at item t
+The PTS of the output audio frame, expressed in seconds.
+
+ at item TB
+The timebase of the output audio frames.
+ at 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
+ at item
+Generate a 1 kHz sine wave following @code{1602,1601,1602,1601,1602} NTSC
+pattern:
+ at example
+sine=1000:samples_per_frame='st(0,mod(n,5)); 1602-not(not(eq(ld(0),1)+eq(ld(0),3)))'
+ at end example
@end itemize
@c man end AUDIO SOURCES
diff --git a/libavfilter/asrc_sine.c b/libavfilter/asrc_sine.c
index 6aa01d5..cd43ae4 100644
--- a/libavfilter/asrc_sine.c
+++ b/libavfilter/asrc_sine.c
@@ -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);
More information about the ffmpeg-cvslog
mailing list