1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
|
/*
* Sound Tools High-Pass effect file.
*
* (C) 2000 Chris Bagwell <cbagwell@sprynet.com>
* See License file for further copyright information.
*
* Algorithm: Recursive single pole high-pass filter
*
* Reference: The Scientist and Engineer's Guide to Digital Processing
*
* output[N] = A0 * input[N] + A1 * input[N-1] + B1 * output[N-1]
*
* X = exp(-2.0 * pi * Fc)
* A0 = (1 + X) / 2
* A1 = -(1 + X) / 2
* B1 = X
* Fc = cutoff freq / sample rate
*
* Mimics an RC high-pass filter:
*
* || C
* ----||--------->
* || |
* <
* > R
* <
* |
* V
*
*/
#include <math.h>
#include "st_i.h"
/* Private data for Highpass effect */
typedef struct highpstuff {
float cutoff;
double A0, A1, B1;
double inm1, outm1;
} *highp_t;
/*
* Process options
*/
int st_highp_getopts(eff_t effp, int n, char **argv)
{
highp_t highp = (highp_t) effp->priv;
if ((n < 1) || !sscanf(argv[0], "%f", &highp->cutoff))
{
st_fail("Usage: highp cutoff");
return (ST_EOF);
}
return (ST_SUCCESS);
}
/*
* Prepare processing.
*/
int st_highp_start(eff_t effp)
{
highp_t highp = (highp_t) effp->priv;
if (highp->cutoff > effp->ininfo.rate/2)
{
st_fail("Highpass: cutoff must be < sample rate / 2 (Nyquest rate)\n");
return (ST_EOF);
}
highp->B1 = exp((-2.0 * M_PI * (highp->cutoff / effp->ininfo.rate)));
highp->A0 = (1 + highp->B1) / 2;
highp->A1 = (-1 * (1 + highp->B1)) / 2;
highp->inm1 = 0.0;
highp->outm1 = 0.0;
return (ST_SUCCESS);
}
/*
* Processed signed long samples from ibuf to obuf.
* Return number of samples processed.
*/
int st_highp_flow(eff_t effp, st_sample_t *ibuf, st_sample_t *obuf,
st_size_t *isamp, st_size_t *osamp)
{
highp_t highp = (highp_t) effp->priv;
int len, done;
double d;
st_sample_t l;
len = ((*isamp > *osamp) ? *osamp : *isamp);
for(done = 0; done < len; done++) {
l = *ibuf++;
d = highp->A0 * l +
highp->A1 * highp->inm1 +
highp->B1 * highp->outm1;
if (d < -2147483647L)
d = -2147483647L;
else if (d > 2147483647L)
d = 2147483647L;
highp->inm1 = l;
highp->outm1 = d;
*obuf++ = d;
}
*isamp = len;
*osamp = len;
return (ST_SUCCESS);
}
/*
* Do anything required when you stop reading samples.
* Don't close input file!
*/
int st_highp_stop(eff_t effp)
{
/* nothing to do */
return (ST_SUCCESS);
}
|