blob: 23629f85db7e97955d2632a5d6405e27de4da24d [file] [log] [blame]
/* libSoX earwax - makes listening to headphones easier 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.
*
* This effect takes a 44.1kHz stereo (CD format) signal 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.
*/
#include "third_party/sox/src/src/sox_i.h"
#include <string.h>
static const sox_sample_t filt[32 * 2] = {
/* 30° 330° */
4, -6, /* 32 tap stereo FIR filter. */
4, -11, /* One side filters as if the */
-1, -5, /* signal was from 30 degrees */
3, 3, /* from the ear, the other as */
-2, 5, /* if 330 degrees. */
-5, 0,
9, 1,
6, 3, /* Input */
-4, -1, /* Left Right */
-5, -3, /* __________ __________ */
-2, -5, /* | | | | */
-7, 1, /* .---| Hh,0(f) | | Hh,0(f) |---. */
6, -7, /* / |__________| |__________| \ */
30, -29, /* / \ / \ */
12, -3, /* / X \ */
-11, 4, /* / / \ \ */
-3, 7, /* ____V_____ __________V V__________ _____V____ */
-20, 23, /* | | | | | | | | */
2, 0, /* | Hh,30(f) | | Hh,330(f)| | Hh,330(f)| | Hh,30(f) | */
1, -6, /* |__________| |__________| |__________| |__________| */
-14, -5, /* \ ___ / \ ___ / */
15, -18, /* \ / \ / _____ \ / \ / */
6, 7, /* `->| + |<--' / \ `-->| + |<-' */
15, -10, /* \___/ _/ \_ \___/ */
-14, 22, /* \ / \ / \ / */
-7, -2, /* `--->| | | |<---' */
-4, 9, /* \_/ \_/ */
6, -12, /* */
6, -6, /* Headphones */
0, -11,
0, -5,
4, 0};
#define NUMTAPS array_length(filt)
typedef struct {sox_sample_t tap[NUMTAPS];} priv_t; /* FIR filter z^-1 delays */
static int start(sox_effect_t * effp)
{
priv_t * p = (priv_t *)effp->priv;
if (effp->in_signal.rate != 44100 || effp->in_signal.channels != 2) {
lsx_fail("works only with stereo audio sampled at 44100Hz (i.e. CDDA)");
return SOX_EOF;
}
memset(p->tap, 0, NUMTAPS * sizeof(*p->tap)); /* zero tap memory */
if (effp->in_signal.mult)
*effp->in_signal.mult *= dB_to_linear(-4.4);
return SOX_SUCCESS;
}
static int flow(sox_effect_t * effp, const sox_sample_t * ibuf,
sox_sample_t * obuf, size_t * isamp, size_t * osamp)
{
priv_t * p = (priv_t *)effp->priv;
size_t i, len = *isamp = *osamp = min(*isamp, *osamp);
while (len--) { /* update taps and calculate output */
double output = 0;
for (i = NUMTAPS - 1; i; --i) {
p->tap[i] = p->tap[i - 1];
output += p->tap[i] * filt[i];
}
p->tap[0] = *ibuf++ / 64; /* scale output */
output += p->tap[0] * filt[0];
*obuf++ = SOX_ROUND_CLIP_COUNT(output, effp->clips);
}
return SOX_SUCCESS;
}
/* No drain: preserve audio file length; it's only 32 samples anyway. */
sox_effect_handler_t const *lsx_earwax_effect_fn(void)
{
static sox_effect_handler_t handler = {"earwax", NULL, SOX_EFF_MCHAN,
NULL, start, flow, NULL, NULL, NULL, sizeof(priv_t)};
return &handler;
}