1 /* libSoX earwax - makes listening to headphones easier November 9, 2000
3 * Copyright (c) 2000 Edward Beingessner And Sundry Contributors.
4 * This source code is freely redistributable and may be used for any purpose.
5 * This copyright notice must be maintained. Edward Beingessner And Sundry
6 * Contributors are not responsible for the consequences of using this
9 * This effect takes a 44.1kHz stereo (CD format) signal that is meant to be
10 * listened to on headphones, and adds audio cues to move the soundstage from
11 * inside your head (standard for headphones) to outside and in front of the
12 * listener (standard for speakers). This makes the sound much easier to listen
19 static const sox_sample_t filt
[32 * 2] = {
21 4, -6, /* 32 tap stereo FIR filter. */
22 4, -11, /* One side filters as if the */
23 -1, -5, /* signal was from 30 degrees */
24 3, 3, /* from the ear, the other as */
25 -2, 5, /* if 330 degrees. */
29 -4, -1, /* Left Right */
30 -5, -3, /* __________ __________ */
32 -7, 1, /* .---| Hh,0(f) | | Hh,0(f) |---. */
33 6, -7, /* / |__________| |__________| \ */
34 30, -29, /* / \ / \ */
37 -3, 7, /* ____V_____ __________V V__________ _____V____ */
38 -20, 23, /* | | | | | | | | */
39 2, 0, /* | Hh,30(f) | | Hh,330(f)| | Hh,330(f)| | Hh,30(f) | */
40 1, -6, /* |__________| |__________| |__________| |__________| */
41 -14, -5, /* \ ___ / \ ___ / */
42 15, -18, /* \ / \ / _____ \ / \ / */
43 6, 7, /* `->| + |<--' / \ `-->| + |<-' */
44 15, -10, /* \___/ _/ \_ \___/ */
45 -14, 22, /* \ / \ / \ / */
46 -7, -2, /* `--->| | | |<---' */
49 6, -6, /* Headphones */
54 #define NUMTAPS array_length(filt)
55 typedef struct {sox_sample_t tap
[NUMTAPS
];} priv_t
; /* FIR filter z^-1 delays */
57 static int start(sox_effect_t
* effp
)
59 priv_t
* p
= (priv_t
*)effp
->priv
;
60 if (effp
->in_signal
.rate
!= 44100 || effp
->in_signal
.channels
!= 2) {
61 lsx_fail("works only with stereo audio sampled at 44100Hz (i.e. CDDA)");
64 memset(p
->tap
, 0, NUMTAPS
* sizeof(*p
->tap
)); /* zero tap memory */
65 if (effp
->in_signal
.mult
)
66 *effp
->in_signal
.mult
*= dB_to_linear(-4.4);
70 static int flow(sox_effect_t
* effp
, const sox_sample_t
* ibuf
,
71 sox_sample_t
* obuf
, size_t * isamp
, size_t * osamp
)
73 priv_t
* p
= (priv_t
*)effp
->priv
;
74 size_t i
, len
= *isamp
= *osamp
= min(*isamp
, *osamp
);
76 while (len
--) { /* update taps and calculate output */
79 for (i
= NUMTAPS
- 1; i
; --i
) {
80 p
->tap
[i
] = p
->tap
[i
- 1];
81 output
+= p
->tap
[i
] * filt
[i
];
83 p
->tap
[0] = *ibuf
++ / 64; /* scale output */
84 output
+= p
->tap
[0] * filt
[0];
85 *obuf
++ = SOX_ROUND_CLIP_COUNT(output
, effp
->clips
);
90 /* No drain: preserve audio file length; it's only 32 samples anyway. */
92 sox_effect_handler_t
const *lsx_earwax_effect_fn(void)
94 static sox_effect_handler_t handler
= {"earwax", NULL
, SOX_EFF_MCHAN
,
95 NULL
, start
, flow
, NULL
, NULL
, NULL
, sizeof(priv_t
)};