mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-02-04 06:08:26 +02:00
avfilter/sine: support expression in the number of output samples
This commit is contained in:
parent
db18b3d6e6
commit
a388ca359d
@ -2857,7 +2857,26 @@ Specify the sample rate, default is 44100.
|
|||||||
Specify the duration of the generated audio stream.
|
Specify the duration of the generated audio stream.
|
||||||
|
|
||||||
@item samples_per_frame
|
@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
|
@end table
|
||||||
|
|
||||||
@subsection Examples
|
@subsection Examples
|
||||||
@ -2878,6 +2897,12 @@ sine=f=220:b=4:d=5
|
|||||||
sine=frequency=220:beep_factor=4:duration=5
|
sine=frequency=220:beep_factor=4:duration=5
|
||||||
@end example
|
@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
|
@end itemize
|
||||||
|
|
||||||
@c man end AUDIO SOURCES
|
@c man end AUDIO SOURCES
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
#include "libavutil/avassert.h"
|
#include "libavutil/avassert.h"
|
||||||
#include "libavutil/channel_layout.h"
|
#include "libavutil/channel_layout.h"
|
||||||
|
#include "libavutil/eval.h"
|
||||||
#include "libavutil/opt.h"
|
#include "libavutil/opt.h"
|
||||||
#include "audio.h"
|
#include "audio.h"
|
||||||
#include "avfilter.h"
|
#include "avfilter.h"
|
||||||
@ -31,7 +32,8 @@ typedef struct {
|
|||||||
const AVClass *class;
|
const AVClass *class;
|
||||||
double frequency;
|
double frequency;
|
||||||
double beep_factor;
|
double beep_factor;
|
||||||
int samples_per_frame;
|
char *samples_per_frame;
|
||||||
|
AVExpr *samples_per_frame_expr;
|
||||||
int sample_rate;
|
int sample_rate;
|
||||||
int64_t duration;
|
int64_t duration;
|
||||||
int16_t *sin;
|
int16_t *sin;
|
||||||
@ -61,6 +63,9 @@ typedef struct {
|
|||||||
#define OPT_DUR(name, field, def, min, max, descr, ...) \
|
#define OPT_DUR(name, field, def, min, max, descr, ...) \
|
||||||
OPT_GENERIC(name, field, def, min, max, descr, DURATION, str, __VA_ARGS__)
|
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[] = {
|
static const AVOption sine_options[] = {
|
||||||
OPT_DBL("frequency", frequency, 440, 0, DBL_MAX, "set the sine frequency"),
|
OPT_DBL("frequency", frequency, 440, 0, DBL_MAX, "set the sine frequency"),
|
||||||
OPT_DBL("f", 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_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("duration", duration, 0, 0, INT64_MAX, "set the audio duration"),
|
||||||
OPT_DUR("d", 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}
|
{NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -120,8 +125,25 @@ static void make_sin_table(int16_t *sin)
|
|||||||
sin[i + 2 * half_pi] = -sin[i];
|
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)
|
static av_cold int init(AVFilterContext *ctx)
|
||||||
{
|
{
|
||||||
|
int ret;
|
||||||
SineContext *sine = ctx->priv;
|
SineContext *sine = ctx->priv;
|
||||||
|
|
||||||
if (!(sine->sin = av_malloc(sizeof(*sine->sin) << LOG_PERIOD)))
|
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;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,6 +171,8 @@ static av_cold void uninit(AVFilterContext *ctx)
|
|||||||
{
|
{
|
||||||
SineContext *sine = ctx->priv;
|
SineContext *sine = ctx->priv;
|
||||||
|
|
||||||
|
av_expr_free(sine->samples_per_frame_expr);
|
||||||
|
sine->samples_per_frame_expr = NULL;
|
||||||
av_freep(&sine->sin);
|
av_freep(&sine->sin);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -188,9 +218,21 @@ static int request_frame(AVFilterLink *outlink)
|
|||||||
{
|
{
|
||||||
SineContext *sine = outlink->src->priv;
|
SineContext *sine = outlink->src->priv;
|
||||||
AVFrame *frame;
|
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;
|
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) {
|
if (sine->duration) {
|
||||||
nb_samples = FFMIN(nb_samples, sine->duration - sine->pts);
|
nb_samples = FFMIN(nb_samples, sine->duration - sine->pts);
|
||||||
av_assert1(nb_samples >= 0);
|
av_assert1(nb_samples >= 0);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user