1 // ----------------------------------------------------------------------------
2 //
3 //  Copyright (C) 2018-2019 Fons Adriaensen <fons@linuxaudio.org>
4 //
5 //  This program is free software; you can redistribute it and/or modify
6 //  it under the terms of the GNU General Public License as published by
7 //  the Free Software Foundation; either version 3 of the License, or
8 //  (at your option) any later version.
9 //
10 //  This program is distributed in the hope that it will be useful,
11 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 //  GNU General Public License for more details.
14 //
15 //  You should have received a copy of the GNU General Public License
16 //  along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 //
18 // ----------------------------------------------------------------------------
19 
20 
21 #include <math.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include "jlr4filt.h"
25 #include "delay.h"
26 
27 
Jlr4chan(void)28 Jlr4chan::Jlr4chan (void) :
29     _nreq (0),
30     _nack (0),
31     _mode (0),
32     _inp (0),
33     _hpf (0),
34     _hps (0),
35     _lpf (0),
36     _lps (0),
37     _gain (1.0f),
38     _delay (0)
39 {
40 }
41 
42 
~Jlr4chan(void)43 Jlr4chan::~Jlr4chan (void)
44 {
45 }
46 
47 
Jlr4filt(const char * client_name,const char * server_name,int ninp,int nout,float maxdel)48 Jlr4filt::Jlr4filt (const char *client_name, const char *server_name,
49 		    int ninp, int nout, float maxdel) :
50     _chanpar (0),
51     _maxdel (0)
52 {
53     if (ninp < 1) ninp = 1;
54     if (ninp > MAXINP) ninp = MAXINP;
55     if (nout < 1) nout = 1;
56     if (nout > MAXOUT) nout = MAXOUT;
57     if (maxdel < 0.0f) maxdel = 0.0f;
58     if (maxdel > 0.1f) maxdel = 0.1f;
59     if (   open_jack (client_name, server_name, ninp, nout)
60         || create_inp_ports ("in_%d")
61         || create_out_ports ("out_%d"))
62     {
63 	_state = FAILED;
64 	return;
65     }
66     init (maxdel);
67     _state = PROCESS;
68 }
69 
70 
~Jlr4filt(void)71 Jlr4filt::~Jlr4filt (void)
72 {
73     _state = INITIAL;
74     close_jack ();
75     delete[] _chanpar;
76 }
77 
78 
init(float maxdel)79 void Jlr4filt::init (float maxdel)
80 {
81     int       i;
82     Jlr4chan  *C;
83 
84     _chanpar = new Jlr4chan [_nout];
85     _maxdel = (int)(maxdel * jack_rate () + 0.5f);
86     if (_maxdel)
87     {
88 	for (i = 0, C = _chanpar; i < _nout; i++, C++)
89 	{
90 	    C->_dproc.init (_maxdel, jack_size ());
91 	}
92     }
93 }
94 
95 
set_filter(int inp,int out,float hpf,float hps,float lpf,float lps)96 void Jlr4filt::set_filter (int inp, int out, float hpf, float hps, float lpf, float lps)
97 {
98     Jlr4chan *C;
99 
100     if ((inp < 0) || (inp >= _ninp)) return;
101     if ((out < 0) || (out >= _nout)) return;
102     C = _chanpar + out;
103     C->_inp = inp;
104     C->_hpf = hpf / jack_rate ();
105     C->_hps = hps;
106     C->_lpf = lpf / jack_rate ();
107     C->_lps = lps;
108     C->_nreq++;
109 }
110 
111 
set_delay(int out,float delay)112 void Jlr4filt::set_delay (int out, float delay)
113 {
114     int32_t d;
115 
116     if ((out < 0) || (out >= _nout)) return;
117     d = (int32_t)(delay * jack_rate () + 0.5f);
118     if (d < 0)       d = 0;
119     if (d > _maxdel) d = _maxdel;
120     _chanpar [out]._delay = d;
121 }
122 
123 
set_gain(int out,float gain)124 void Jlr4filt::set_gain (int out, float gain)
125 {
126     if ((out < 0) || (out >= _nout)) return;
127     _chanpar [out]._gain = gain;
128 }
129 
130 
jack_process(int nframes)131 int Jlr4filt::jack_process (int nframes)
132 {
133     Jlr4chan     *C;
134     float        *inp [MAXINP];
135     float        *out;
136     const float  *p;
137     int          i, j, m;
138 
139     if (_state < PROCESS) return 0;
140 
141     for (i = 0; i < _ninp; i++)
142     {
143         inp [i] = (float *) jack_port_get_buffer (_inp_ports [i], nframes);
144     }
145 
146     for (i = 0, C = _chanpar; i < _nout; i++, C++)
147     {
148         out = (float *) jack_port_get_buffer (_out_ports [i], nframes);
149 	if (C->_nreq != C->_nack)
150 	{
151 	    C->_mode = 0;
152 	    if (C->_hpf > 0)
153 	    {
154 		C->_hpfilt.setpars (C->_hpf, C->_hps);
155 		C->_mode |= HPF;
156 	    }
157 	    if (C->_lpf > 0)
158 	    {
159 		C->_lpfilt.setpars (C->_lpf, C->_lps);
160 		C->_mode |= LPF;
161 	    }
162 	    C->_nack++;
163 	}
164 	m = C->_mode;
165 	if (m)
166 	{
167 	    p = inp [C->_inp];
168 	    if (C->_delay)
169 	    {
170 		C->_dproc.write (p);
171 		p = C->_dproc.readp (C->_delay);
172 	    }
173 	    if (m & HPF)
174 	    {
175 		C->_hpfilt.process_hipass (nframes, p, out);
176 		p = out;
177 	    }
178 	    if (m & LPF)
179 	    {
180 		C->_lpfilt.process_lopass (nframes, p, out);
181 	    }
182 	    if (C->_gain != 1.0f)
183 	    {
184 		for (j = 0; j < nframes; j++) out [j] *= C->_gain;
185 	    }
186 	}
187 	else memset (out, 0, nframes * sizeof (float));
188     }
189 
190     return 0;
191 }
192 
193