1 // ----------------------------------------------------------------------------
3 // Copyright (C) 2006-2018 Fons Adriaensen <fons@linuxaudio.org>
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.
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.
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/>.
18 // ----------------------------------------------------------------------------
25 #include "zita-convolver/zita-convolver.h"
27 using namespace ArdourZita;
29 float Convproc::_mac_cost = 1.0f;
30 float Convproc::_fft_cost = 5.0f;
33 calloc_real (uint32_t k)
35 float* p = fftwf_alloc_real (k);
37 throw (Converror (Converror::MEM_ALLOC));
38 memset (p, 0, k * sizeof (float));
43 calloc_complex (uint32_t k)
45 fftwf_complex* p = fftwf_alloc_complex (k);
47 throw (Converror (Converror::MEM_ALLOC));
48 memset (p, 0, k * sizeof (fftwf_complex));
52 Convproc::Convproc (void)
64 memset (_inpbuff, 0, MAXINP * sizeof (float*));
65 memset (_outbuff, 0, MAXOUT * sizeof (float*));
66 memset (_convlev, 0, MAXLEV * sizeof (Convlevel*));
69 Convproc::~Convproc (void)
76 Convproc::set_options (uint32_t options)
82 Convproc::set_skipcnt (uint32_t skipcnt)
84 if ((_quantum == _minpart) && (_quantum == _maxpart))
89 Convproc::configure (uint32_t ninp,
97 uint32_t offs, npar, size, pind, nmin, i;
98 int prio, step, d, r, s;
101 if (_state != ST_IDLE)
102 return Converror::BAD_STATE;
103 if ( (ninp < 1) || (ninp > MAXINP)
104 || (nout < 1) || (nout > MAXOUT)
105 || (quantum & (quantum - 1))
106 || (quantum < MINQUANT)
107 || (quantum > MAXQUANT)
108 || (minpart & (minpart - 1))
109 || (minpart < MINPART)
110 || (minpart < quantum)
111 || (minpart > MAXDIVIS * quantum)
112 || (maxpart & (maxpart - 1))
113 || (maxpart > MAXPART)
114 || (maxpart < minpart))
115 return Converror::BAD_PARAM;
117 nmin = (ninp < nout) ? ninp : nout;
119 density = 1.0f / nmin;
122 cfft = _fft_cost * (ninp + nout);
123 cmac = _mac_cost * ninp * nout * density;
124 step = (cfft < 4 * cmac) ? 1 : 2;
126 r = maxpart / minpart;
127 s = (r & 0xAAAA) ? 1 : 2;
130 nmin = (s == 1) ? 2 : 6;
131 if (minpart == quantum)
135 while (size < minpart) {
141 for (offs = pind = 0; offs < maxsize; pind++) {
142 npar = (maxsize - offs + size - 1) / size;
143 if ((size < maxpart) && (npar > nmin)) {
146 d = d - (d + r - 1) / r;
150 _convlev[pind] = new Convlevel ();
151 _convlev[pind]->configure (prio, offs, npar, size, _options);
153 if (offs < maxsize) {
157 nmin = (s == 1) ? 2 : 6;
170 for (i = 0; i < ninp; i++)
171 _inpbuff[i] = new float[_inpsize];
172 for (i = 0; i < nout; i++)
173 _outbuff[i] = new float[_minpart];
176 return Converror::MEM_ALLOC;
184 Convproc::impdata_create (uint32_t inp,
193 if (_state != ST_STOP)
194 return Converror::BAD_STATE;
195 if ((inp >= _ninp) || (out >= _nout))
196 return Converror::BAD_PARAM;
198 for (j = 0; j < _nlevels; j++) {
199 _convlev[j]->impdata_write (inp, out, step, data, ind0, ind1, true);
203 return Converror::MEM_ALLOC;
209 Convproc::impdata_clear (uint32_t inp, uint32_t out)
213 if (_state < ST_STOP)
214 return Converror::BAD_STATE;
215 for (k = 0; k < _nlevels; k++)
216 _convlev[k]->impdata_clear (inp, out);
221 Convproc::impdata_update (uint32_t inp,
230 if (_state < ST_STOP)
231 return Converror::BAD_STATE;
232 if ((inp >= _ninp) || (out >= _nout))
233 return Converror::BAD_PARAM;
234 for (j = 0; j < _nlevels; j++) {
235 _convlev[j]->impdata_write (inp, out, step, data, ind0, ind1, false);
241 Convproc::impdata_link (uint32_t inp1,
248 if ((inp1 >= _ninp) || (out1 >= _nout))
249 return Converror::BAD_PARAM;
250 if ((inp2 >= _ninp) || (out2 >= _nout))
251 return Converror::BAD_PARAM;
252 if ((inp1 == inp2) && (out1 == out2))
253 return Converror::BAD_PARAM;
254 if (_state != ST_STOP)
255 return Converror::BAD_STATE;
257 for (j = 0; j < _nlevels; j++) {
258 _convlev[j]->impdata_link (inp1, out1, inp2, out2);
262 return Converror::MEM_ALLOC;
268 Convproc::reset (void)
272 if (_state == ST_IDLE)
273 return Converror::BAD_STATE;
274 for (k = 0; k < _ninp; k++)
275 memset (_inpbuff[k], 0, _inpsize * sizeof (float));
276 for (k = 0; k < _nout; k++)
277 memset (_outbuff[k], 0, _minpart * sizeof (float));
278 for (k = 0; k < _nlevels; k++)
279 _convlev[k]->reset (_inpsize, _minpart, _inpbuff, _outbuff);
284 Convproc::start_process (int abspri, int policy)
288 if (_state != ST_STOP)
289 return Converror::BAD_STATE;
295 for (k = (_minpart == _quantum) ? 1 : 0; k < _nlevels; k++) {
296 _convlev[k]->start (abspri, policy);
303 Convproc::process (bool sync)
308 if (_state != ST_PROC)
310 _inpoffs += _quantum;
311 if (_inpoffs == _inpsize)
313 _outoffs += _quantum;
314 if (_outoffs == _minpart) {
316 for (k = 0; k < _nout; k++)
317 memset (_outbuff[k], 0, _minpart * sizeof (float));
318 for (k = 0; k < _nlevels; k++)
319 f |= _convlev[k]->readout (sync, _skipcnt);
320 if (_skipcnt < _minpart)
323 _skipcnt -= _minpart;
325 if (++_latecnt >= 5) {
326 if (~_options & OPT_LATE_CONTIN)
337 Convproc::stop_process (void)
341 if (_state != ST_PROC)
342 return Converror::BAD_STATE;
343 for (k = 0; k < _nlevels; k++)
344 _convlev[k]->stop ();
350 Convproc::cleanup (void)
354 while (!check_stop ()) {
357 for (k = 0; k < _ninp; k++) {
358 delete[] _inpbuff[k];
361 for (k = 0; k < _nout; k++) {
362 delete[] _outbuff[k];
365 for (k = 0; k < _nlevels; k++) {
384 Convproc::check_stop (void)
388 for (k = 0; (k < _nlevels) && (_convlev[k]->_stat == Convlevel::ST_IDLE); k++)
398 Convproc::print (FILE* F)
402 for (k = 0; k < _nlevels; k++)
403 _convlev[k]->print (F);
406 typedef float FV4 __attribute__ ((vector_size (16)));
408 Convlevel::Convlevel (void)
413 #ifndef PTW32_VERSION
426 Convlevel::~Convlevel (void)
432 Convlevel::configure (int prio,
438 int fftwopt = (options & OPT_FFTW_MEASURE) ? FFTW_MEASURE : FFTW_ESTIMATE;
446 _time_data = calloc_real (2 * _parsize);
447 _prep_data = calloc_real (2 * _parsize);
448 _freq_data = calloc_complex (_parsize + 1);
449 _plan_r2c = fftwf_plan_dft_r2c_1d (2 * _parsize, _time_data, _freq_data, fftwopt);
450 _plan_c2r = fftwf_plan_dft_c2r_1d (2 * _parsize, _freq_data, _time_data, fftwopt);
451 if (_plan_r2c && _plan_c2r)
453 throw (Converror (Converror::MEM_ALLOC));
457 Convlevel::impdata_write (uint32_t inp,
466 int32_t j, j0, j1, n;
473 i1 = i0 + _npar * _parsize;
474 if ((i0 >= n) || (i1 <= 0))
478 M = findmacnode (inp, out, true);
479 if (M == 0 || M->_link)
482 M->alloc_fftb (_npar);
484 M = findmacnode (inp, out, false);
485 if (M == 0 || M->_link || M->_fftb == 0)
489 norm = 0.5f / _parsize;
490 for (k = 0; k < _npar; k++) {
492 if ((i0 < n) && (i1 > 0)) {
494 if (fftb == 0 && create) {
495 M->_fftb[k] = fftb = calloc_complex (_parsize + 1);
498 memset (_prep_data, 0, 2 * _parsize * sizeof (float));
499 j0 = (i0 < 0) ? 0 : i0;
500 j1 = (i1 > n) ? n : i1;
501 for (j = j0; j < j1; j++)
502 _prep_data[j - i0] = norm * data[j * step];
503 fftwf_execute_dft_r2c (_plan_r2c, _prep_data, _freq_data);
504 #ifdef ENABLE_VECTOR_MODE
505 if (_options & OPT_VECTOR_MODE)
506 fftswap (_freq_data);
508 for (j = 0; j <= (int)_parsize; j++) {
509 fftb[j][0] += _freq_data[j][0];
510 fftb[j][1] += _freq_data[j][1];
519 Convlevel::impdata_clear (uint32_t inp, uint32_t out)
524 M = findmacnode (inp, out, false);
525 if (M == 0 || M->_link || M->_fftb == 0)
527 for (i = 0; i < _npar; i++) {
529 memset (M->_fftb[i], 0, (_parsize + 1) * sizeof (fftwf_complex));
535 Convlevel::impdata_link (uint32_t inp1,
543 M1 = findmacnode (inp1, out1, false);
546 M2 = findmacnode (inp2, out2, true);
552 Convlevel::reset (uint32_t inpsize,
565 for (X = _inp_list; X; X = X->_next) {
566 for (i = 0; i < _npar; i++) {
567 memset (X->_ffta[i], 0, (_parsize + 1) * sizeof (fftwf_complex));
570 for (Y = _out_list; Y; Y = Y->_next) {
571 for (i = 0; i < 3; i++) {
572 memset (Y->_buff[i], 0, _parsize * sizeof (float));
575 if (_parsize == _outsize) {
579 _outoffs = _parsize / 2;
580 _inpoffs = _inpsize - _outoffs;
582 _bits = _parsize / _outsize;
591 Convlevel::start (int abspri, int policy)
595 struct sched_param parm;
597 #ifndef PTW32_VERSION
600 min = sched_get_priority_min (policy);
601 max = sched_get_priority_max (policy);
607 parm.sched_priority = abspri;
608 pthread_attr_init (&attr);
609 pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
610 pthread_attr_setschedpolicy (&attr, policy);
611 pthread_attr_setschedparam (&attr, &parm);
612 pthread_attr_setscope (&attr, PTHREAD_SCOPE_SYSTEM);
613 pthread_attr_setinheritsched (&attr, PTHREAD_EXPLICIT_SCHED);
614 pthread_attr_setstacksize (&attr, 0x10000);
615 pthread_create (&_pthr, &attr, static_main, this);
616 pthread_attr_destroy (&attr);
620 Convlevel::stop (void)
622 if (_stat != ST_IDLE) {
629 Convlevel::cleanup (void)
657 fftwf_destroy_plan (_plan_r2c);
658 fftwf_destroy_plan (_plan_c2r);
659 fftwf_free (_time_data);
660 fftwf_free (_prep_data);
661 fftwf_free (_freq_data);
670 Convlevel::static_main (void* arg)
672 ((Convlevel*)arg)->main ();
677 Convlevel::main (void)
682 if (_stat == ST_TERM) {
684 #ifndef PTW32_VERSION
695 Convlevel::process (bool skip)
697 uint32_t i, i1, j, k, n1, n2, opi1, opi2;
710 if (_inpoffs >= _inpsize) {
711 _inpoffs -= _inpsize;
716 opi1 = (_opind + 1) % 3;
717 opi2 = (_opind + 2) % 3;
719 for (X = _inp_list; X; X = X->_next) {
720 inpd = _inpbuff[X->_inp];
722 memcpy (_time_data, inpd + i1, n1 * sizeof (float));
724 memcpy (_time_data + n1, inpd, n2 * sizeof (float));
725 memset (_time_data + _parsize, 0, _parsize * sizeof (float));
726 fftwf_execute_dft_r2c (_plan_r2c, _time_data, X->_ffta[_ptind]);
727 #ifdef ENABLE_VECTOR_MODE
728 if (_options & OPT_VECTOR_MODE)
729 fftswap (X->_ffta[_ptind]);
734 for (Y = _out_list; Y; Y = Y->_next) {
735 outd = Y->_buff[opi2];
736 memset (outd, 0, _parsize * sizeof (float));
739 for (Y = _out_list; Y; Y = Y->_next) {
740 memset (_freq_data, 0, (_parsize + 1) * sizeof (fftwf_complex));
741 for (M = Y->_list; M; M = M->_next) {
744 for (j = 0; j < _npar; j++) {
746 fftb = M->_link ? M->_link->_fftb[j] : M->_fftb[j];
748 #ifdef ENABLE_VECTOR_MODE
749 if (_options & OPT_VECTOR_MODE) {
752 FV4* D = (FV4*)_freq_data;
753 for (k = 0; k < _parsize; k += 4) {
754 D[0] += A[0] * B[0] - A[1] * B[1];
755 D[1] += A[0] * B[1] + A[1] * B[0];
760 _freq_data[_parsize][0] += ffta[_parsize][0] * fftb[_parsize][0];
761 _freq_data[_parsize][1] = 0;
765 for (k = 0; k <= _parsize; k++) {
766 _freq_data[k][0] += ffta[k][0] * fftb[k][0] - ffta[k][1] * fftb[k][1];
767 _freq_data[k][1] += ffta[k][0] * fftb[k][1] + ffta[k][1] * fftb[k][0];
777 #ifdef ENABLE_VECTOR_MODE
778 if (_options & OPT_VECTOR_MODE)
779 fftswap (_freq_data);
781 fftwf_execute_dft_c2r (_plan_c2r, _freq_data, _time_data);
782 outd = Y->_buff[opi1];
783 for (k = 0; k < _parsize; k++)
784 outd[k] += _time_data[k];
785 outd = Y->_buff[opi2];
786 memcpy (outd, _time_data + _parsize, _parsize * sizeof (float));
796 Convlevel::readout (bool sync, uint32_t skipcnt)
802 _outoffs += _outsize;
803 if (_outoffs == _parsize) {
805 if (_stat == ST_PROC) {
809 else if (_done.trywait ())
818 process (skipcnt >= 2 * _parsize);
824 for (Y = _out_list; Y; Y = Y->_next) {
825 p = Y->_buff[_opind] + _outoffs;
826 q = _outbuff[Y->_out];
827 for (i = 0; i < _outsize; i++)
831 return (_wait > 1) ? _bits : 0;
835 Convlevel::print (FILE* F)
837 fprintf (F, "prio = %4d, offs = %6d, parsize = %5d, npar = %3d\n", _prio, _offs, _parsize, _npar);
841 Convlevel::findmacnode (uint32_t inp, uint32_t out, bool create)
847 for (X = _inp_list; X && (X->_inp != inp); X = X->_next)
852 X = new Inpnode (inp);
853 X->_next = _inp_list;
855 X->alloc_ffta (_npar, _parsize);
858 for (Y = _out_list; Y && (Y->_out != out); Y = Y->_next)
863 Y = new Outnode (out, _parsize);
864 Y->_next = _out_list;
868 for (M = Y->_list; M && (M->_inpn != X); M = M->_next)
881 #ifdef ENABLE_VECTOR_MODE
884 Convlevel::fftswap (fftwf_complex* p)
886 uint32_t n = _parsize;
903 Inpnode::Inpnode (uint16_t inp)
911 Inpnode::~Inpnode (void)
917 Inpnode::alloc_ffta (uint16_t npar, int32_t size)
920 _ffta = new fftwf_complex*[_npar];
921 for (int i = 0; i < _npar; i++) {
922 _ffta[i] = calloc_complex (size + 1);
927 Inpnode::free_ffta (void)
931 for (uint16_t i = 0; i < _npar; i++) {
932 fftwf_free (_ffta[i]);
939 Macnode::Macnode (Inpnode* inpn)
948 Macnode::~Macnode (void)
954 Macnode::alloc_fftb (uint16_t npar)
957 _fftb = new fftwf_complex*[_npar];
958 for (uint16_t i = 0; i < _npar; i++) {
964 Macnode::free_fftb (void)
968 for (uint16_t i = 0; i < _npar; i++) {
969 fftwf_free (_fftb[i]);
976 Outnode::Outnode (uint16_t out, int32_t size)
981 _buff[0] = calloc_real (size);
982 _buff[1] = calloc_real (size);
983 _buff[2] = calloc_real (size);
986 Outnode::~Outnode (void)
988 fftwf_free (_buff[0]);
989 fftwf_free (_buff[1]);
990 fftwf_free (_buff[2]);