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 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
|
/*
* November 9, 2000
* Copyright (C) 2000 Edward Beingessner And Sundry Contributors
* This source code is freely redistributable and may be used for
* any purpose. This copyright notice must be maintained.
* Edward Beingessner And Sundry Contributors are not responsible for
* the consequences of using this software.
*/
/*
* earwax - makes listening to headphones easier
*
* This effect takes a stereo sound that is meant to be listened to
* on headphones, and adds audio cues to move the soundstage from inside
* your head (standard for headphones) to outside and in front of the
* listener (standard for speakers). This makes the sound much easier to
* listen to on headphones. See www.geocities.com/beinges for a full
* explanation.
*
* Usage:
* earwax
*
* Note:
* This filter only works for 44.1 kHz stereo signals (cd format)
*
*/
#include "st_i.h"
#define EARWAX_SCALE 64
/* A stereo fir filter. One side filters as if the signal was from
30 degrees from the ear, the other as if 330 degrees. */
/* 30 330 */
static const st_sample_t filt[] =
{ 4, -6,
4, -11,
-1, -5,
3, 3,
-2, 5,
-5, 0,
9, 1,
6, 3,
-4, -1,
-5, -3,
-2, -5,
-7, 1,
6, -7,
30, -29,
12, -3,
-11, 4,
-3, 7,
-20, 23,
2, 0,
1, -6,
-14, -5,
15, -18,
6, 7,
15, -10,
-14, 22,
-7, -2,
-4, 9,
6, -12,
6, -6,
0, -11,
0, -5,
4, 0};
/* 32 tap stereo FIR filter needs 64 taps */
#define EARWAX_NUMTAPS 64
typedef struct earwaxstuff {
st_sample_t *tap; /* taps are z^-1 delays for the FIR filter */
} *earwax_t;
/*
* Process options
*/
int st_earwax_getopts(eff_t effp, int n, char **argv)
{
/* no options */
if (n){
st_fail("The earwax filtering effect takes no options.\n");
return (ST_EOF);
}
return (ST_SUCCESS);
}
/*
* Prepare for processing.
*/
int st_earwax_start(eff_t effp)
{
earwax_t earwax = (earwax_t) effp->priv;
int i;
/* check the input format */
if (effp->ininfo.encoding != ST_ENCODING_SIGN2
|| effp->ininfo.rate != 44100
|| effp->ininfo.channels != 2){
st_fail("the earwax effect works only with audio cd (44.1 kHz, twos-complement signed linear, stereo) samples.\n");
return (ST_EOF);
}
/* allocate tap memory */
earwax->tap = (st_sample_t*)malloc( sizeof(st_sample_t) * EARWAX_NUMTAPS );
if( !earwax->tap ){
st_fail("earwax: Cannot malloc %d bytes!\n",
sizeof(st_sample_t) * EARWAX_NUMTAPS );
return (ST_EOF);
}
/* zero out the delayed taps */
for(i=0; i < EARWAX_NUMTAPS; i++ ){
earwax->tap[i] = 0;
}
return (ST_SUCCESS);
}
/*
* Processed signed long samples from ibuf to obuf.
* Return number of samples processed.
*/
int st_earwax_flow(eff_t effp, st_sample_t *ibuf, st_sample_t *obuf,
st_size_t *isamp, st_size_t *osamp)
{
earwax_t earwax = (earwax_t) effp->priv;
int len, done;
int i;
st_sample_t output;
len = ((*isamp > *osamp) ? *osamp : *isamp);
for(done = 0; done < len; done++) {
/* update taps and calculate output */
output = 0;
for(i = EARWAX_NUMTAPS-1; i > 0; i--) {
earwax->tap[i] = earwax->tap[i-1];
output += earwax->tap[i] * filt[i];
}
earwax->tap[0] = *ibuf++ / EARWAX_SCALE;
output += earwax->tap[0] * filt[i];
/* store scaled output */
*obuf++ = output;
}
*isamp = *osamp = len;
return (ST_SUCCESS);
}
/*
* Drain out taps.
*/
int st_earwax_drain(eff_t effp, st_sample_t *obuf, st_size_t *osamp)
{
earwax_t earwax = (earwax_t) effp->priv;
int i,j;
st_sample_t output;
for(i = EARWAX_NUMTAPS-1; i >= 0; i--){
output = 0;
for(j = 0; j < i; j++ ){
output += filt[j+(EARWAX_NUMTAPS-i)] * earwax->tap[j];
}
*obuf++ = output;
}
*osamp = EARWAX_NUMTAPS-1;
return (ST_SUCCESS);
}
/*
* Clean up taps.
*/
int st_earwax_stop(eff_t effp)
{
earwax_t earwax = (earwax_t) effp->priv;
free((char *)earwax->tap);
return (ST_SUCCESS);
}
|