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