2 * Copyright (c) 2018 Paul B Mahol
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
21 #include "libavutil/channel_layout.h"
22 #include "libavutil/mem.h"
23 #include "libavutil/opt.h"
28 #include "window_func.h"
30 typedef struct HilbertContext
{
42 #define OFFSET(x) offsetof(HilbertContext, x)
43 #define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
45 static const AVOption hilbert_options
[] = {
46 { "sample_rate", "set sample rate", OFFSET(sample_rate
), AV_OPT_TYPE_INT
, {.i64
=44100}, 1, INT_MAX
, FLAGS
},
47 { "r", "set sample rate", OFFSET(sample_rate
), AV_OPT_TYPE_INT
, {.i64
=44100}, 1, INT_MAX
, FLAGS
},
48 { "taps", "set number of taps", OFFSET(nb_taps
), AV_OPT_TYPE_INT
, {.i64
=22051}, 11, UINT16_MAX
, FLAGS
},
49 { "t", "set number of taps", OFFSET(nb_taps
), AV_OPT_TYPE_INT
, {.i64
=22051}, 11, UINT16_MAX
, FLAGS
},
50 { "nb_samples", "set the number of samples per requested frame", OFFSET(nb_samples
), AV_OPT_TYPE_INT
, {.i64
= 1024}, 1, INT_MAX
, FLAGS
},
51 { "n", "set the number of samples per requested frame", OFFSET(nb_samples
), AV_OPT_TYPE_INT
, {.i64
= 1024}, 1, INT_MAX
, FLAGS
},
52 WIN_FUNC_OPTION("win_func", OFFSET(win_func
), FLAGS
, WFUNC_BLACKMAN
),
53 WIN_FUNC_OPTION("w", OFFSET(win_func
), FLAGS
, WFUNC_BLACKMAN
),
57 AVFILTER_DEFINE_CLASS(hilbert
);
59 static av_cold
int init(AVFilterContext
*ctx
)
61 HilbertContext
*s
= ctx
->priv
;
63 if (!(s
->nb_taps
& 1)) {
64 av_log(s
, AV_LOG_ERROR
, "Number of taps %d must be odd length.\n", s
->nb_taps
);
65 return AVERROR(EINVAL
);
71 static av_cold
void uninit(AVFilterContext
*ctx
)
73 HilbertContext
*s
= ctx
->priv
;
78 static av_cold
int query_formats(const AVFilterContext
*ctx
,
79 AVFilterFormatsConfig
**cfg_in
,
80 AVFilterFormatsConfig
**cfg_out
)
82 HilbertContext
*s
= ctx
->priv
;
83 static const AVChannelLayout chlayouts
[] = { AV_CHANNEL_LAYOUT_MONO
, { 0 } };
84 int sample_rates
[] = { s
->sample_rate
, -1 };
85 static const enum AVSampleFormat sample_fmts
[] = {
89 int ret
= ff_set_common_formats_from_list2(ctx
, cfg_in
, cfg_out
, sample_fmts
);
93 ret
= ff_set_common_channel_layouts_from_list2(ctx
, cfg_in
, cfg_out
, chlayouts
);
97 return ff_set_common_samplerates_from_list2(ctx
, cfg_in
, cfg_out
, sample_rates
);
100 static av_cold
int config_props(AVFilterLink
*outlink
)
102 AVFilterContext
*ctx
= outlink
->src
;
103 HilbertContext
*s
= ctx
->priv
;
107 s
->taps
= av_malloc_array(s
->nb_taps
, sizeof(*s
->taps
));
109 return AVERROR(ENOMEM
);
111 generate_window_func(s
->taps
, s
->nb_taps
, s
->win_func
, &overlap
);
113 for (i
= 0; i
< s
->nb_taps
; i
++) {
114 int k
= -(s
->nb_taps
/ 2) + i
;
119 s
->taps
[i
] *= (1.f
- cosf(pk
)) / pk
;
130 static int activate(AVFilterContext
*ctx
)
132 AVFilterLink
*outlink
= ctx
->outputs
[0];
133 HilbertContext
*s
= ctx
->priv
;
137 if (!ff_outlink_frame_wanted(outlink
))
138 return FFERROR_NOT_READY
;
140 nb_samples
= FFMIN(s
->nb_samples
, s
->nb_taps
- s
->pts
);
141 if (nb_samples
<= 0) {
142 ff_outlink_set_status(outlink
, AVERROR_EOF
, s
->pts
);
146 if (!(frame
= ff_get_audio_buffer(outlink
, nb_samples
)))
147 return AVERROR(ENOMEM
);
149 memcpy(frame
->data
[0], s
->taps
+ s
->pts
, nb_samples
* sizeof(float));
152 s
->pts
+= nb_samples
;
153 return ff_filter_frame(outlink
, frame
);
156 static const AVFilterPad hilbert_outputs
[] = {
159 .type
= AVMEDIA_TYPE_AUDIO
,
160 .config_props
= config_props
,
164 const FFFilter ff_asrc_hilbert
= {
166 .p
.description
= NULL_IF_CONFIG_SMALL("Generate a Hilbert transform FIR coefficients."),
167 .p
.priv_class
= &hilbert_class
,
170 .activate
= activate
,
171 .priv_size
= sizeof(HilbertContext
),
172 FILTER_OUTPUTS(hilbert_outputs
),
173 FILTER_QUERY_FUNC2(query_formats
),