wav: simplify extended fmt chunk handling [bug #198]
[sox.git] / src / hilbert.c
blobae289f29b75b881bfe09fa2eda3236a658a0b65d
1 /* libSoX effect: Hilbert transform filter
3 * First version of this effect written 11/2011 by Ulrich Klauer, using maths
4 * from "Understanding digital signal processing" by Richard G. Lyons.
6 * Copyright 2011 Chris Bagwell and SoX Contributors
8 * This library is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU Lesser General Public License as published by
10 * the Free Software Foundation; either version 2.1 of the License, or (at
11 * your option) any later version.
13 * This library is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
16 * General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this library; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 #include "sox_i.h"
24 #include "dft_filter.h"
26 typedef struct {
27 dft_filter_priv_t base;
28 double *h;
29 int taps;
30 } priv_t;
32 static int getopts(sox_effect_t *effp, int argc, char **argv)
34 lsx_getopt_t optstate;
35 int c;
36 priv_t *p = (priv_t*)effp->priv;
37 dft_filter_priv_t *b = &p->base;
39 b->filter_ptr = &b->filter;
41 lsx_getopt_init(argc, argv, "+n:", NULL, lsx_getopt_flag_none, 1, &optstate);
43 while ((c = lsx_getopt(&optstate)) != -1) switch (c) {
44 GETOPT_NUMERIC(optstate, 'n', taps, 3, 32767)
45 default: lsx_fail("invalid option `-%c'", optstate.opt); return lsx_usage(effp);
47 if (p->taps && p->taps%2 == 0) {
48 lsx_fail("only filters with an odd number of taps are supported");
49 return SOX_EOF;
51 return optstate.ind != argc ? lsx_usage(effp) : SOX_SUCCESS;
54 static int start(sox_effect_t *effp)
56 priv_t *p = (priv_t*)effp->priv;
57 dft_filter_t *f = p->base.filter_ptr;
59 if (!f->num_taps) {
60 int i;
61 if (!p->taps) {
62 p->taps = effp->in_signal.rate/76.5 + 2;
63 p->taps += 1 - (p->taps%2);
64 /* results in a cutoff frequency of about 75 Hz with a Blackman window */
65 lsx_debug("choosing number of taps = %d (override with -n)", p->taps);
67 lsx_valloc(p->h, p->taps);
68 for (i = 0; i < p->taps; i++) {
69 int k = -(p->taps/2) + i;
70 if (k%2 == 0) {
71 p->h[i] = 0.0;
72 } else {
73 double pk = M_PI * k;
74 p->h[i] = (1 - cos(pk))/pk;
77 lsx_apply_blackman(p->h, p->taps, .16);
79 if (effp->global_info->plot != sox_plot_off) {
80 char title[100];
81 sprintf(title, "SoX effect: hilbert (%d taps)", p->taps);
82 lsx_plot_fir(p->h, p->taps, effp->in_signal.rate,
83 effp->global_info->plot, title, -20., 5.);
84 free(p->h);
85 return SOX_EOF;
87 lsx_set_dft_filter(f, p->h, p->taps, p->taps/2);
89 return lsx_dft_filter_effect_fn()->start(effp);
92 sox_effect_handler_t const *lsx_hilbert_effect_fn(void)
94 static sox_effect_handler_t handler;
95 handler = *lsx_dft_filter_effect_fn();
96 handler.name = "hilbert";
97 handler.usage = "[-n taps]";
98 handler.getopts = getopts;
99 handler.start = start;
100 handler.priv_size = sizeof(priv_t);
101 return &handler;