kobodl/sound/a_filters.c
Ville Lindholm dbc223eb84
Initial commit
Import existing source tree; original VCS history is no longer available.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-05-28 16:35:31 +03:00

354 lines
7.0 KiB
C

/*(LGPL)
---------------------------------------------------------------------------
a_filters.c - Various Audio Signal Filters
---------------------------------------------------------------------------
* Copyright (C) 2001, 2002, David Olofson
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <stdlib.h>
#include "a_math.h"
#include "a_tools.h"
#include "a_filters.h"
/*--------------------------------------------------------------------
f6_t - Simple mono 6 dB/oct state variable filter
--------------------------------------------------------------------*/
void f6_process_lp(f6_t *fil, int *buf, unsigned frames)
{
int f = fil->f;
int d = fil->d;
unsigned s;
for(s = 0; s < frames; ++s)
{
d += (buf[s] - (d>>12)) * f;
buf[s] = d>>12;
}
fil->d = d;
}
void f6_process_hp(f6_t *fil, int *buf, unsigned frames)
{
int f = fil->f;
int d = fil->d;
unsigned s;
for(s = 0; s < frames; ++s)
{
d += (buf[s] - (d>>12)) * f;
buf[s] -= d>>12;
}
fil->d = d;
}
void f6_set_f(f6_t *fil, int f)
{
fil->f = (f<<13) / fil->rate;
if(fil->f > 1<<13)
fil->f = 1<<13;
}
void f6_init(f6_t *fil, int fs)
{
fil->rate = fs;
fil->d = 0;
f6_set_f(fil, 400);
}
/*--------------------------------------------------------------------
f6s_t - Simple stereo 6 dB/oct state variable filter
--------------------------------------------------------------------*/
void f6s_process_lp(f6s_t *fil, int *buf, unsigned frames)
{
int f = fil->f;
int dl = fil->dl;
int dr = fil->dr;
unsigned s;
frames <<= 1;
for(s = 0; s < frames; s += 2)
{
dl += (buf[s] - (dl>>12)) * f;
dr += (buf[s+1] - (dr>>12)) * f;
buf[s] = dl>>12;
buf[s+1] = dr>>12;
}
fil->dl = dl;
fil->dr = dr;
}
void f6s_process_hp(f6s_t *fil, int *buf, unsigned frames)
{
int f = fil->f;
int dl = fil->dl;
int dr = fil->dr;
unsigned s;
frames <<= 1;
for(s = 0; s < frames; s += 2)
{
dl += (buf[s] - (dl>>12)) * f;
dr += (buf[s+1] - (dr>>12)) * f;
buf[s] -= dl>>12;
buf[s+1] -= dr>>12;
}
fil->dl = dl;
fil->dr = dr;
}
void f6s_set_f(f6s_t *fil, int f)
{
fil->f = (f<<13) / fil->rate;
if(fil->f > 1<<13)
fil->f = 1<<13;
}
void f6s_init(f6s_t *fil, int fs)
{
fil->rate = fs;
fil->dl = fil->dr = 0;
f6s_set_f(fil, 400);
}
/*--------------------------------------------------------------------
dcf6s_t - Fast stereo 6 dB/oct HPF for DC suppression
--------------------------------------------------------------------*/
void dcf6s_process(dcf6s_t *fil, int *buf, unsigned frames)
{
int f = fil->f;
int dl = fil->dl;
int dr = fil->dr;
unsigned s;
frames <<= 1;
for(s = 0; s < frames; s += 2)
{
dl += (buf[s] - (dl>>12)) >> f;
dr += (buf[s+1] - (dr>>12)) >> f;
buf[s] -= dl>>12;
buf[s+1] -= dr>>12;
}
fil->dl = dl;
fil->dr = dr;
}
int dcf6s_silent(dcf6s_t *fil)
{
if(labs(fil->dl) > 4096)
return 0;
if(labs(fil->dr) > 4096)
return 0;
return 1;
}
void dcf6s_set_f(dcf6s_t *fil, int f)
{
fil->f = int2shift(fil->rate / f) - 13;
if(fil->f < 0)
fil->f = 0;
}
void dcf6s_init(dcf6s_t *fil, int fs)
{
fil->rate = fs;
fil->dl = fil->dr = 0;
dcf6s_set_f(fil, 10);
}
/*--------------------------------------------------------------------
resof12_t - Resonant mono 12 dB/oct state variable filter
--------------------------------------------------------------------*/
/* In-place LP */
void resof12_process_lp(resof12_t *rf, int *buf, unsigned frames)
{
int d1 = rf->d1;
int d2 = rf->d2;
int f = rf->f;
int q = rf->q;
int l, b, h;
unsigned s;
for(s = 0; s < frames; ++s)
{
l = d2 + (f*d1 >> 8);
h = (buf[s] << 4) - l - (q*d1 >> 8);
b = (f*h >> 8) + d1;
buf[s] = l >> 4;
d1 = b;
d2 = l;
}
rf->d1 = d1;
rf->d2 = d2;
}
/* In-place HP */
void resof12_process_hp(resof12_t *rf, int *buf, unsigned frames)
{
int d1 = rf->d1;
int d2 = rf->d2;
int f = rf->f;
int q = rf->q;
int l, b, h;
unsigned s;
for(s = 0; s < frames; ++s)
{
l = d2 + (f*d1 >> 8);
h = (buf[s] << 4) - l - (q*d1 >> 8);
b = (f*h >> 8) + d1;
buf[s] = h >> 4;
d1 = b;
d2 = l;
}
rf->d1 = d1;
rf->d2 = d2;
}
/* In-place BP */
void resof12_process_bp(resof12_t *rf, int *buf, unsigned frames)
{
int d1 = rf->d1;
int d2 = rf->d2;
int f = rf->f;
int q = rf->q;
int l, b, h;
unsigned s;
for(s = 0; s < frames; ++s)
{
l = d2 + (f*d1 >> 8);
h = (buf[s] << 4) - l - (q*d1 >> 8);
b = (f*h >> 8) + d1;
buf[s] = b >> 4;
d1 = b;
d2 = l;
}
rf->d1 = d1;
rf->d2 = d2;
}
/*
* LP filter the 'buf' buffer, while separating off
* the HP part into buffer 'out'.
*/
void resof12_process_split(resof12_t *rf, int *buf, int *out, unsigned frames)
{
int d1 = rf->d1;
int d2 = rf->d2;
int f = rf->f;
int q = rf->q;
int l, b, h;
unsigned s;
for(s = 0; s < frames; ++s)
{
l = d2 + (f*d1 >> 8);
h = (buf[s] << 4) - l - (q*d1 >> 8);
b = (f*h >> 8) + d1;
buf[s] = l >> 4;
out[s] = h >> 4;
d1 = b;
d2 = l;
}
rf->d1 = d1;
rf->d2 = d2;
}
void resof12_set_f(resof12_t *rf, int f)
{
rf->f = (int)(512.0 * sin(M_PI * (float)f / rf->rate));
if(rf->f > 256)
rf->f = 256;
}
void resof12_set_q(resof12_t *rf, int q)
{
if(q < 1)
rf->q = 256;
else
rf->q = 256 / q;
}
void resof12_init(resof12_t *rf, int fs)
{
rf->rate = fs;
rf->d1 = rf->d2 = 0;
resof12_set_f(rf, 400);
resof12_set_q(rf, 10);
}
/*--------------------------------------------------------------------
resof12s_t - Resonant stereo 12 dB/oct state variable filter
--------------------------------------------------------------------*/
/* In-place LP */
void resof12s_process_lp(resof12s_t *rf, int *buf, unsigned frames)
{
int d1l = rf->d1l;
int d1r = rf->d1r;
int d2l = rf->d2l;
int d2r = rf->d2r;
int f = rf->f;
int q = rf->q;
int ll, bl, hl;
int lr, br, hr;
unsigned s;
frames <<= 1;
for(s = 0; s < frames; s += 2)
{
ll = d2l + (f*d1l >> 8);
lr = d2r + (f*d1r >> 8);
hl = (buf[s] << 4) - ll - (q*d1l >> 8);
hr = (buf[s+1] << 4) - lr - (q*d1r >> 8);
bl = (f*hl >> 8) + d1l;
br = (f*hr >> 8) + d1r;
buf[s] = ll >> 4;
buf[s+1] = lr >> 4;
d1l = bl;
d1r = br;
d2l = ll;
d2r = lr;
}
rf->d1l = d1l;
rf->d1r = d1r;
rf->d2l = d2l;
rf->d2r = d2r;
}
void resof12s_set_f(resof12s_t *rf, int f)
{
rf->f = (int)(512.0 * sin(M_PI * (float)f / rf->rate));
if(rf->f > 256)
rf->f = 256;
}
void resof12s_set_q(resof12s_t *rf, int q)
{
if(q < 1)
rf->q = 256;
else
rf->q = 256 / q;
}
void resof12s_init(resof12s_t *rf, int fs)
{
rf->rate = fs;
rf->d1l = rf->d2l = 0;
rf->d1r = rf->d2r = 0;
resof12s_set_f(rf, 400);
resof12s_set_q(rf, 10);
}