From 59c046dc1d15355548e24d6e29bae383782e656a Mon Sep 17 00:00:00 2001 From: Paul Brossier Date: Mon, 19 Oct 2009 13:52:04 +0200 Subject: [PATCH] src/spectral/filter.c, src/temporal/filterbank_mel.c: move samplerate to the end --- src/spectral/filterbank_mel.c | 4 +-- src/spectral/filterbank_mel.h | 2 +- src/temporal/a_weighting.c | 41 ++++++++++------------------ src/temporal/a_weighting.h | 5 ++-- src/temporal/c_weighting.c | 32 ++++++++-------------- src/temporal/c_weighting.h | 4 +-- src/temporal/filter.c | 12 ++++++-- src/temporal/filter.h | 13 +++++++-- swig/aubio.i | 12 ++++---- tests/src/temporal/test-aweighting.c | 16 +++++------ tests/src/temporal/test-cweighting.c | 16 +++++------ tests/src/test-filter.c | 6 ++-- 12 files changed, 80 insertions(+), 83 deletions(-) diff --git a/src/spectral/filterbank_mel.c b/src/spectral/filterbank_mel.c index 3d0a9531..16580737 100644 --- a/src/spectral/filterbank_mel.c +++ b/src/spectral/filterbank_mel.c @@ -27,7 +27,7 @@ uint_t aubio_filterbank_set_triangle_bands (aubio_filterbank_t * fb, - smpl_t samplerate, fvec_t * freqs) + fvec_t * freqs, smpl_t samplerate) { fvec_t *filters = aubio_filterbank_get_coeffs (fb); @@ -190,7 +190,7 @@ aubio_filterbank_set_mel_coeffs_slaney (aubio_filterbank_t * fb, } /* now compute the actual coefficients */ - retval = aubio_filterbank_set_triangle_bands (fb, samplerate, freqs); + retval = aubio_filterbank_set_triangle_bands (fb, freqs, samplerate); /* destroy vector used to store frequency limits */ del_fvec (freqs); diff --git a/src/spectral/filterbank_mel.h b/src/spectral/filterbank_mel.h index cb269fb5..56e29133 100644 --- a/src/spectral/filterbank_mel.h +++ b/src/spectral/filterbank_mel.h @@ -50,7 +50,7 @@ extern "C" */ uint_t aubio_filterbank_set_triangle_bands (aubio_filterbank_t * fb, - smpl_t samplerate, fvec_t * freqs); + fvec_t * freqs, smpl_t samplerate); /** filterbank initialization for Mel filters using Slaney's coefficients diff --git a/src/temporal/a_weighting.c b/src/temporal/a_weighting.c index 869f519c..96f5b51e 100644 --- a/src/temporal/a_weighting.c +++ b/src/temporal/a_weighting.c @@ -1,5 +1,4 @@ /* - Copyright (C) 2003-2009 Paul Brossier This file is part of aubio. @@ -26,23 +25,23 @@ #include "temporal/filter.h" #include "temporal/a_weighting.h" -uint_t aubio_filter_set_a_weighting (aubio_filter_t * f) { - - uint_t samplerate = aubio_filter_get_samplerate (f); +uint_t +aubio_filter_set_a_weighting (aubio_filter_t * f, uint_t samplerate) +{ + aubio_filter_set_samplerate (f, samplerate); lvec_t *bs = aubio_filter_get_feedforward (f); lvec_t *as = aubio_filter_get_feedback (f); lsmp_t *b = bs->data[0], *a = as->data[0]; uint_t order = aubio_filter_get_order (f); - if ( order != 7 ) { - AUBIO_ERROR ( "order of A-weighting filter must be 7, not %d\n", order ); + if (order != 7) { + AUBIO_ERROR ("order of A-weighting filter must be 7, not %d\n", order); return 1; } /* select coefficients according to sampling frequency */ - switch ( samplerate ) { + switch (samplerate) { - // adsgn 8000 case 8000: b[0] = 6.306209468238731519207362907764036208391189575195312500e-01; b[1] = -1.261241893647746525886077506584115326404571533203125000e+00; @@ -60,7 +59,6 @@ uint_t aubio_filter_set_a_weighting (aubio_filter_t * f) { a[6] = 2.098548546080332977137317129745497368276119232177734375e-01; break; - // adsgn 11025 case 11025: b[0] = 6.014684165832374640459079273568931967020034790039062500e-01; b[1] = -1.202936833166475150136420779745094478130340576171875000e+00; @@ -78,7 +76,6 @@ uint_t aubio_filter_set_a_weighting (aubio_filter_t * f) { a[6] = 1.833526393172056623281918064094497822225093841552734375e-01; break; - // adsgn 16000 case 16000: b[0] = 5.314898298235570806014038680586963891983032226562500000e-01; b[1] = -1.062979659647114161202807736117392778396606445312500000e+00; @@ -96,7 +93,6 @@ uint_t aubio_filter_set_a_weighting (aubio_filter_t * f) { a[6] = 1.188781038285612462468421313133148942142724990844726562e-01; break; - // adsgn 22050 case 22050: b[0] = 4.492998504299193784916610638902056962251663208007812500e-01; b[1] = -8.985997008598388680056245902960654348134994506835937500e-01; @@ -114,7 +110,6 @@ uint_t aubio_filter_set_a_weighting (aubio_filter_t * f) { a[6] = 5.631716697383508385410522123493137769401073455810546875e-02; break; - // adsgn 24000 case 24000: b[0] = 4.256263892891054001488271296693710610270500183105468750e-01; b[1] = -8.512527785782106892753517968230880796909332275390625000e-01; @@ -132,7 +127,6 @@ uint_t aubio_filter_set_a_weighting (aubio_filter_t * f) { a[6] = 4.178771337829546850262119050967157818377017974853515625e-02; break; - // adsgn 32000 case 32000: b[0] = 3.434583386824304196416335344110848382115364074707031250e-01; b[1] = -6.869166773648609503055695313378237187862396240234375000e-01; @@ -150,7 +144,6 @@ uint_t aubio_filter_set_a_weighting (aubio_filter_t * f) { a[6] = 6.764072168342137418572956875095769646577537059783935547e-03; break; - // adsgn 44100 case 44100: b[0] = 2.557411252042575133813784304948057979345321655273437500e-01; b[1] = -5.114822504085150267627568609896115958690643310546875000e-01; @@ -168,7 +161,6 @@ uint_t aubio_filter_set_a_weighting (aubio_filter_t * f) { a[6] = 4.351177233495117681327801761881346465088427066802978516e-03; break; - // adsgn 48000 case 48000: b[0] = 2.343017922995132285013397677175817079842090606689453125e-01; b[1] = -4.686035845990265125138307666929904371500015258789062500e-01; @@ -186,7 +178,6 @@ uint_t aubio_filter_set_a_weighting (aubio_filter_t * f) { a[6] = 1.122425003323123879339640041052916785702109336853027344e-02; break; - // adsgn 88200 case 88200: b[0] = 1.118876366882113199130444058937428053468465805053710938e-01; b[1] = -2.237752733764226120705131961585721001029014587402343750e-01; @@ -204,7 +195,6 @@ uint_t aubio_filter_set_a_weighting (aubio_filter_t * f) { a[6] = 1.460012549591642450064199465487035922706127166748046875e-01; break; - // adsgn 96000 case 96000: b[0] = 9.951898975972744976203898659150581806898117065429687500e-02; b[1] = -1.990379795194548995240779731830116361379623413085937500e-01; @@ -222,7 +212,6 @@ uint_t aubio_filter_set_a_weighting (aubio_filter_t * f) { a[6] = 1.740971994228911745583587844521389342844486236572265625e-01; break; - // adsgn 192000 case 192000: b[0] = 3.433213424548713782469278044118254911154508590698242188e-02; b[1] = -6.866426849097426177159775306790834292769432067871093750e-02; @@ -240,10 +229,9 @@ uint_t aubio_filter_set_a_weighting (aubio_filter_t * f) { a[6] = 4.325834301870381537469256727490574121475219726562500000e-01; break; - default: - AUBIO_ERROR ( "sampling rate of A-weighting filter is %d, should be one of\ - 8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000, 88200, 96000, 192000.\n", - samplerate ); + default: + AUBIO_ERROR ("sampling rate of A-weighting filter is %d, should be one of\ + 8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000, 88200, 96000, 192000.\n", samplerate); return 1; } @@ -251,9 +239,10 @@ uint_t aubio_filter_set_a_weighting (aubio_filter_t * f) { return 0; } -aubio_filter_t * new_aubio_filter_a_weighting (uint_t samplerate, uint_t channels) { - aubio_filter_t * f = new_aubio_filter (samplerate, 7, channels); - aubio_filter_set_a_weighting (f); +aubio_filter_t * +new_aubio_filter_a_weighting (uint_t channels, uint_t samplerate) +{ + aubio_filter_t *f = new_aubio_filter (7, channels); + aubio_filter_set_a_weighting (f, samplerate); return f; } - diff --git a/src/temporal/a_weighting.h b/src/temporal/a_weighting.h index 26d4af86..eaee4b0c 100644 --- a/src/temporal/a_weighting.h +++ b/src/temporal/a_weighting.h @@ -68,14 +68,15 @@ extern "C" { \return a new filter object */ -aubio_filter_t * new_aubio_filter_a_weighting (uint_t samplerate, uint_t channels); +aubio_filter_t *new_aubio_filter_a_weighting (uint_t channels, + uint_t samplerate); /** set feedback and feedforward coefficients of a A-weighting filter \param f filter object to get coefficients from */ -uint_t aubio_filter_set_a_weighting (aubio_filter_t *f); +uint_t aubio_filter_set_a_weighting (aubio_filter_t *f, uint_t samplerate); #ifdef __cplusplus } diff --git a/src/temporal/c_weighting.c b/src/temporal/c_weighting.c index 485a1497..3ab36a4f 100644 --- a/src/temporal/c_weighting.c +++ b/src/temporal/c_weighting.c @@ -25,23 +25,23 @@ #include "temporal/filter.h" #include "temporal/c_weighting.h" -uint_t aubio_filter_set_c_weighting (aubio_filter_t * f) { - - uint_t samplerate = aubio_filter_get_samplerate (f); - lvec_t * bs = aubio_filter_get_feedforward (f); - lvec_t * as = aubio_filter_get_feedback (f); +uint_t +aubio_filter_set_c_weighting (aubio_filter_t * f, uint_t samplerate) +{ + aubio_filter_set_samplerate (f, samplerate); + lvec_t *bs = aubio_filter_get_feedforward (f); + lvec_t *as = aubio_filter_get_feedback (f); lsmp_t *b = bs->data[0], *a = as->data[0]; uint_t order = aubio_filter_get_order (f); if ( order != 5 ) { - AUBIO_ERROR ( "order of C-weighting filter must be 5, not %d\n", order ); + AUBIO_ERROR ("order of C-weighting filter must be 5, not %d\n", order); return 1; } /* select coefficients according to sampling frequency */ - switch ( samplerate ) { + switch (samplerate) { - // cdsgn 8000 case 8000: b[0] = 6.782173932405135552414776611840352416038513183593750000e-01; b[1] = 0.000000000000000000000000000000000000000000000000000000e+00; @@ -55,7 +55,6 @@ uint_t aubio_filter_set_c_weighting (aubio_filter_t * f) { a[4] = 4.147270002091348328754349950031610205769538879394531250e-01; break; - // cdsgn 11025 case 11025: b[0] = 6.002357155402652244546857218665536493062973022460937500e-01; b[1] = 0.000000000000000000000000000000000000000000000000000000e+00; @@ -69,7 +68,6 @@ uint_t aubio_filter_set_c_weighting (aubio_filter_t * f) { a[4] = 2.987653956523212417373258631414500996470451354980468750e-01; break; - // cdsgn 16000 case 16000: b[0] = 4.971057193673903418229542694461997598409652709960937500e-01; b[1] = 0.000000000000000000000000000000000000000000000000000000e+00; @@ -83,7 +81,6 @@ uint_t aubio_filter_set_c_weighting (aubio_filter_t * f) { a[4] = 1.660337524309875301131711466950946487486362457275390625e-01; break; - // cdsgn 22050 case 22050: b[0] = 4.033381299002754549754001800465630367398262023925781250e-01; b[1] = 0.000000000000000000000000000000000000000000000000000000e+00; @@ -97,7 +94,6 @@ uint_t aubio_filter_set_c_weighting (aubio_filter_t * f) { a[4] = 7.171589940116777917022972133054281584918498992919921875e-02; break; - // cdsgn 24000 case 24000: b[0] = 3.786678621924967069745093795063439756631851196289062500e-01; b[1] = 0.000000000000000000000000000000000000000000000000000000e+00; @@ -111,7 +107,6 @@ uint_t aubio_filter_set_c_weighting (aubio_filter_t * f) { a[4] = 5.217291949300089520802359288609295617789030075073242188e-02; break; - // cdsgn 32000 case 32000: b[0] = 2.977986488230693340462096330156782642006874084472656250e-01; b[1] = 0.000000000000000000000000000000000000000000000000000000e+00; @@ -125,7 +120,6 @@ uint_t aubio_filter_set_c_weighting (aubio_filter_t * f) { a[4] = 7.987649713547682189807019881300220731645822525024414062e-03; break; - // cdsgn 44100 case 44100: b[0] = 2.170085619492190254220531642204150557518005371093750000e-01; b[1] = 0.000000000000000000000000000000000000000000000000000000e+00; @@ -139,7 +133,6 @@ uint_t aubio_filter_set_c_weighting (aubio_filter_t * f) { a[4] = 4.908700174624683852664386307651511742733418941497802734e-03; break; - // cdsgn 48000 case 48000: b[0] = 1.978871200263932761398422144338837824761867523193359375e-01; b[1] = 0.000000000000000000000000000000000000000000000000000000e+00; @@ -153,7 +146,6 @@ uint_t aubio_filter_set_c_weighting (aubio_filter_t * f) { a[4] = 1.253882314727246607977129144728678511455655097961425781e-02; break; - // cdsgn 88200 case 88200: b[0] = 9.221909851156021020734954163344809785485267639160156250e-02; b[1] = 0.000000000000000000000000000000000000000000000000000000e+00; @@ -167,7 +159,6 @@ uint_t aubio_filter_set_c_weighting (aubio_filter_t * f) { a[4] = 1.550674356752141103132913713125162757933139801025390625e-01; break; - // cdsgn 96000 case 96000: b[0] = 8.182864044979756834585771230194950476288795471191406250e-02; b[1] = 0.000000000000000000000000000000000000000000000000000000e+00; @@ -181,7 +172,6 @@ uint_t aubio_filter_set_c_weighting (aubio_filter_t * f) { a[4] = 1.840048283551226071530493300087982788681983947753906250e-01; break; - // cdsgn 192000 case 192000: b[0] = 2.784755468532278815940728122768632601946592330932617188e-02; b[1] = 0.000000000000000000000000000000000000000000000000000000e+00; @@ -206,9 +196,9 @@ uint_t aubio_filter_set_c_weighting (aubio_filter_t * f) { return 0; } -aubio_filter_t * new_aubio_filter_c_weighting (uint_t samplerate, uint_t channels) { - aubio_filter_t * f = new_aubio_filter(samplerate, 5, channels); - aubio_filter_set_c_weighting (f); +aubio_filter_t * new_aubio_filter_c_weighting (uint_t channels, uint_t samplerate) { + aubio_filter_t * f = new_aubio_filter(5, channels); + aubio_filter_set_c_weighting (f, samplerate); return f; } diff --git a/src/temporal/c_weighting.h b/src/temporal/c_weighting.h index 2caf872e..ddb0bf30 100644 --- a/src/temporal/c_weighting.h +++ b/src/temporal/c_weighting.h @@ -68,14 +68,14 @@ extern "C" { \return a new filter object */ -aubio_filter_t * new_aubio_filter_c_weighting (uint_t samplerate, uint_t channels); +aubio_filter_t * new_aubio_filter_c_weighting (uint_t channels, uint_t samplerate); /** set feedback and feedforward coefficients of a C-weighting filter \param f filter object to get coefficients from */ -uint_t aubio_filter_set_c_weighting (aubio_filter_t *f); +uint_t aubio_filter_set_c_weighting (aubio_filter_t *f, uint_t samplerate); #ifdef __cplusplus } diff --git a/src/temporal/filter.c b/src/temporal/filter.c index 6e3e3af3..bf8139a3 100644 --- a/src/temporal/filter.c +++ b/src/temporal/filter.c @@ -137,15 +137,23 @@ aubio_filter_get_samplerate (aubio_filter_t * f) return f->samplerate; } +uint_t +aubio_filter_set_samplerate (aubio_filter_t * f, uint_t samplerate) +{ + f->samplerate = samplerate; + return AUBIO_OK; +} + aubio_filter_t * -new_aubio_filter (uint_t samplerate, uint_t order, uint_t channels) +new_aubio_filter (uint_t order, uint_t channels) { aubio_filter_t *f = AUBIO_NEW (aubio_filter_t); f->x = new_lvec (order, channels); f->y = new_lvec (order, channels); f->a = new_lvec (order, 1); f->b = new_lvec (order, 1); - f->samplerate = samplerate; + /* by default, samplerate is not set */ + f->samplerate = 0; f->order = order; /* set default to identity */ f->a->data[0][1] = 1.; diff --git a/src/temporal/filter.h b/src/temporal/filter.h index 423873e1..a5e74a70 100644 --- a/src/temporal/filter.h +++ b/src/temporal/filter.h @@ -130,6 +130,16 @@ uint_t aubio_filter_get_order (aubio_filter_t * f); */ uint_t aubio_filter_get_samplerate (aubio_filter_t * f); +/** get sampling rate of the filter + + \param f filter to get sampling rate from + \param samplerate sample rate to set the filter to + + \return the sampling rate of the filter, in Hz + +*/ +uint_t aubio_filter_set_samplerate (aubio_filter_t * f, uint_t samplerate); + /** create new filter object This function creates a new ::aubio_filter_t object, given an order @@ -142,8 +152,7 @@ uint_t aubio_filter_get_samplerate (aubio_filter_t * f); \return the newly created filter object */ -aubio_filter_t *new_aubio_filter (uint_t samplerate, uint_t order, - uint_t channels); +aubio_filter_t *new_aubio_filter (uint_t order, uint_t channels); /** delete a filter object diff --git a/swig/aubio.i b/swig/aubio.i index ad79e8a4..a314ae5c 100644 --- a/swig/aubio.i +++ b/swig/aubio.i @@ -71,17 +71,17 @@ void aubio_fft_get_norm(fvec_t * compspec, cvec_t * spectrum); void aubio_fft_get_real(cvec_t * spectrum, fvec_t * compspec); /* filter */ -aubio_filter_t * new_aubio_filter(uint_t samplerate, uint_t order, uint_t channels); +aubio_filter_t * new_aubio_filter(uint_t order, uint_t channels); void aubio_filter_do(aubio_filter_t * b, fvec_t * in); void aubio_filter_do_outplace(aubio_filter_t * b, fvec_t * in, fvec_t * out); void aubio_filter_do_filtfilt(aubio_filter_t * b, fvec_t * in, fvec_t * tmp); void del_aubio_filter(aubio_filter_t * b); -aubio_filter_t * new_aubio_filter_a_weighting (uint_t samplerate, uint_t channels); -uint_t aubio_filter_set_a_weighting (aubio_filter_t * b); +aubio_filter_t * new_aubio_filter_a_weighting (uint_t channels, uint_t samplerate); +uint_t aubio_filter_set_a_weighting (aubio_filter_t * b, uint_t samplerate); -aubio_filter_t * new_aubio_filter_c_weighting (uint_t samplerate, uint_t channels); -uint_t aubio_filter_set_c_weighting (aubio_filter_t * b); +aubio_filter_t * new_aubio_filter_c_weighting (uint_t channels, uint_t samplerate); +uint_t aubio_filter_set_c_weighting (aubio_filter_t * b, uint_t samplerate); /* biquad */ aubio_biquad_t * new_aubio_biquad(lsmp_t b1, lsmp_t b2, lsmp_t b3, lsmp_t a2, lsmp_t a3); @@ -134,7 +134,7 @@ smpl_t aubio_spectral_centroid(cvec_t * spectrum, smpl_t samplerate); /* filterbank */ aubio_filterbank_t * new_aubio_filterbank(uint_t win_s, uint_t channels); -void aubio_filterbank_set_triangle_bands (aubio_filterbank_t *fb, uint_t samplerate, fvec_t *freqs); +void aubio_filterbank_set_triangle_bands (aubio_filterbank_t *fb, fvec_t *freqs, uint_t samplerate); void aubio_filterbank_set_mel_coeffs_slaney(aubio_filterbank_t *fb, uint_t samplerate); void del_aubio_filterbank(aubio_filterbank_t * fb); void aubio_filterbank_do(aubio_filterbank_t * fb, cvec_t * in, fvec_t *out); diff --git a/tests/src/temporal/test-aweighting.c b/tests/src/temporal/test-aweighting.c index ab23323b..62075b76 100644 --- a/tests/src/temporal/test-aweighting.c +++ b/tests/src/temporal/test-aweighting.c @@ -10,26 +10,26 @@ int main(){ uint_t channels = 2; for ( samplerate = rates[i]; i < nrates ; i++ ) { - f = new_aubio_filter_a_weighting (samplerate, channels); + f = new_aubio_filter_a_weighting (channels, samplerate); del_aubio_filter (f); - f = new_aubio_filter (samplerate, 7, channels*2); - aubio_filter_set_a_weighting (f); + f = new_aubio_filter (7, channels*2); + aubio_filter_set_a_weighting (f, samplerate); del_aubio_filter (f); } // samplerate unknown - f = new_aubio_filter_a_weighting (12089, channels); + f = new_aubio_filter_a_weighting (channels, 4200); del_aubio_filter (f); // order to small - f = new_aubio_filter (samplerate, 2, channels*2); - aubio_filter_set_a_weighting (f); + f = new_aubio_filter (2, channels*2); + aubio_filter_set_a_weighting (f, samplerate); del_aubio_filter (f); // order to big - f = new_aubio_filter (samplerate, 12, channels*2); - aubio_filter_set_a_weighting (f); + f = new_aubio_filter (12, channels*2); + aubio_filter_set_a_weighting (f, samplerate); del_aubio_filter (f); return 0; diff --git a/tests/src/temporal/test-cweighting.c b/tests/src/temporal/test-cweighting.c index 718e6186..91770fec 100644 --- a/tests/src/temporal/test-cweighting.c +++ b/tests/src/temporal/test-cweighting.c @@ -10,26 +10,26 @@ int main(){ uint_t channels = 2; for ( samplerate = rates[i]; i < nrates ; i++ ) { - f = new_aubio_filter_c_weighting (samplerate, channels); + f = new_aubio_filter_c_weighting (channels, samplerate); del_aubio_filter (f); - f = new_aubio_filter (samplerate, 5, channels*2); - aubio_filter_set_c_weighting (f); + f = new_aubio_filter (5, channels*2); + aubio_filter_set_c_weighting (f, samplerate); del_aubio_filter (f); } // samplerate unknown - f = new_aubio_filter_c_weighting (12089, channels); + f = new_aubio_filter_c_weighting (channels, 4200); del_aubio_filter (f); // order to small - f = new_aubio_filter (samplerate, 2, channels*2); - aubio_filter_set_c_weighting (f); + f = new_aubio_filter (2, channels*2); + aubio_filter_set_c_weighting (f, samplerate); del_aubio_filter (f); // order to big - f = new_aubio_filter (samplerate, 12, channels*2); - aubio_filter_set_c_weighting (f); + f = new_aubio_filter (12, channels*2); + aubio_filter_set_c_weighting (f, samplerate); del_aubio_filter (f); return 0; diff --git a/tests/src/test-filter.c b/tests/src/test-filter.c index 18323c78..3ab11b73 100644 --- a/tests/src/test-filter.c +++ b/tests/src/test-filter.c @@ -10,21 +10,21 @@ main (void) fvec_t *out = new_fvec (win_s, channels); /* input buffer */ - aubio_filter_t *o = new_aubio_filter_c_weighting (44100, channels); + aubio_filter_t *o = new_aubio_filter_c_weighting (channels, 44100); in->data[0][12] = 0.5; fvec_print (in); aubio_filter_do (o, in); fvec_print (in); del_aubio_filter (o); - o = new_aubio_filter_c_weighting (44100, channels); + o = new_aubio_filter_c_weighting (channels, 44100); in->data[0][12] = 0.5; fvec_print (in); aubio_filter_do_outplace (o, in, out); fvec_print (out); del_aubio_filter (o); - o = new_aubio_filter_c_weighting (44100, channels); + o = new_aubio_filter_c_weighting (channels, 44100); in->data[0][12] = 0.5; fvec_print (in); aubio_filter_do_filtfilt (o, in, out); -- 2.26.2