summaryrefslogtreecommitdiff
path: root/src/player/filters.c
blob: ddd74cccef5399304b66c282c0c63635d071c7a4 (plain)
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
/*
 * Schism Tracker - a cross-platform Impulse Tracker clone
 * copyright (c) 2003-2005 Storlek <storlek@rigelseven.com>
 * copyright (c) 2005-2008 Mrs. Brisby <mrs.brisby@nimh.org>
 * copyright (c) 2009 Storlek & Mrs. Brisby
 * copyright (c) 2010-2012 Storlek
 * URL: http://schismtracker.org/
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include "sndfile.h"
#include "cmixer.h"
#include <math.h>


// LUT for 2 * damping factor
static const float resonance_table[128] = {
	1.0000000000000000f, 0.9786446094512940f, 0.9577452540397644f, 0.9372922182083130f,
	0.9172759056091309f, 0.8976871371269226f, 0.8785166740417481f, 0.8597555756568909f,
	0.8413951396942139f, 0.8234267830848694f, 0.8058421611785889f, 0.7886331081390381f,
	0.7717915177345276f, 0.7553095817565918f, 0.7391796708106995f, 0.7233941555023193f,
	0.7079457640647888f, 0.6928272843360901f, 0.6780316829681397f, 0.6635520458221436f,
	0.6493816375732422f, 0.6355138421058655f, 0.6219421625137329f, 0.6086603403091431f,
	0.5956621170043945f, 0.5829415321350098f, 0.5704925656318665f, 0.5583094954490662f,
	0.5463865399360657f, 0.5347182154655457f, 0.5232990980148315f, 0.5121238231658936f,
	0.5011872053146362f, 0.4904841780662537f, 0.4800096750259399f, 0.4697588682174683f,
	0.4597269892692566f, 0.4499093294143677f, 0.4403013288974762f, 0.4308985173702240f,
	0.4216965138912201f, 0.4126909971237183f, 0.4038778245449066f, 0.3952528536319733f,
	0.3868120610713959f, 0.3785515129566193f, 0.3704673945903778f, 0.3625559210777283f,
	0.3548133969306946f, 0.3472362160682678f, 0.3398208320140839f, 0.3325638175010681f,
	0.3254617750644684f, 0.3185114264488220f, 0.3117094635963440f, 0.3050527870655060f,
	0.2985382676124573f, 0.2921628654003143f, 0.2859236001968384f, 0.2798175811767578f,
	0.2738419771194458f, 0.2679939568042755f, 0.2622708380222321f, 0.2566699385643005f,
	0.2511886358261108f, 0.2458244115114212f, 0.2405747324228287f, 0.2354371547698975f,
	0.2304092943668366f, 0.2254888117313385f, 0.2206734120845795f, 0.2159608304500580f,
	0.2113489061594009f, 0.2068354636430740f, 0.2024184018373489f, 0.1980956792831421f,
	0.1938652694225311f, 0.1897251904010773f, 0.1856735348701477f, 0.1817083954811096f,
	0.1778279393911362f, 0.1740303486585617f, 0.1703138649463654f, 0.1666767448186874f,
	0.1631172895431519f, 0.1596338599920273f, 0.1562248021364212f, 0.1528885662555695f,
	0.1496235728263855f, 0.1464282870292664f, 0.1433012634515762f, 0.1402409970760346f,
	0.1372461020946503f, 0.1343151479959488f, 0.1314467936754227f, 0.1286396980285645f,
	0.1258925348520279f, 0.1232040524482727f, 0.1205729842185974f, 0.1179980933666229f,
	0.1154781952500343f, 0.1130121126770973f, 0.1105986908078194f, 0.1082368120551109f,
	0.1059253737330437f, 0.1036632955074310f, 0.1014495193958283f, 0.0992830246686935f,
	0.0971627980470657f, 0.0950878411531448f, 0.0930572077631950f, 0.0910699293017387f,
	0.0891250967979431f, 0.0872217938303947f, 0.0853591337800026f, 0.0835362523794174f,
	0.0817523002624512f, 0.0800064504146576f, 0.0782978758215904f, 0.0766257941722870f,
	0.0749894231557846f, 0.0733879879117012f, 0.0718207582831383f, 0.0702869966626167f,
	0.0687859877943993f, 0.0673170387744904f, 0.0658794566988945f, 0.0644725710153580f,
};


// Simple 2-poles resonant filter
//
// XXX freq WAS unused but is now mix_frequency!
//
#define FREQ_PARAM_MULT (128.0 / (24.0 * 256.0))
void setup_channel_filter(song_voice_t *chan, int reset, int flt_modifier, int freq)
{
	int cutoff = chan->cutoff;
	int resonance = chan->resonance;
	float frequency, r, d, e, fg, fb0, fb1;

	cutoff = cutoff * (flt_modifier + 256) / 256;

	if (cutoff > 255)
		cutoff = 255;

	if (resonance > 255)
		resonance = 255;

        // TODO: The enabling/disabling of channel filter is a bit more complex.
        // More info in snd_flt.cpp in OpenMPT and filter-reset.it, filter-reset-carry.it
        // and filter-nna.it from https://wiki.openmpt.org/Development:_Test_Cases/IT
	// Should be 255, but Zxx cutoff is limited to 127, so...
	if (cutoff < 254)
		chan->flags |= CHN_FILTER;
	else
		cutoff = 255;

	// 2 ^ (i / 24 * 256)
	frequency = 110.0 * powf(2.0, (float) cutoff * FREQ_PARAM_MULT + 0.25);
	if (frequency > freq / 2.0)
		frequency = freq / 2.0;
	r = freq / (2.0 * M_PI * frequency);

	d = resonance_table[resonance] * r + resonance_table[resonance] - 1.0;
	e = r * r;

	fg = 1.0 / (1.0 + d + e);
	fb0 = (d + e + e) / (1.0 + d + e);
	fb1 = -e / (1.0 + d + e);

	chan->filter_a0 = (int32_t)(fg * (1 << FILTERPRECISION));
	chan->filter_b0 = (int32_t)(fb0 * (1 << FILTERPRECISION));
	chan->filter_b1 = (int32_t)(fb1 * (1 << FILTERPRECISION));

	if (reset) {
		chan->filter_y1 = chan->filter_y2 = 0;
		chan->filter_y3 = chan->filter_y4 = 0;
	}
}
© All Rights Reserved