zita-convolver: add namespace & visibility, remove global externs
[ardour.git] / libs / zita-convolver / zita-convolver / zita-convolver.h
1 // ----------------------------------------------------------------------------
2 //
3 //  Copyright (C) 2006-2018 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 #ifndef _ZITA_CONVOLVER_H
22 #define _ZITA_CONVOLVER_H
23
24
25 #include <pthread.h>
26 #include <stdint.h>
27 #include <fftw3.h>
28
29 #include "zita-convolver/zconvolver_visibility.h"
30
31 namespace ArdourZita {
32
33
34 #ifdef ZCSEMA_IS_IMPLEMENTED
35 #undef ZCSEMA_IS_IMPLEMENTED
36 #endif
37
38
39 #if defined(__linux__)  || defined(__GNU__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
40
41 #include <semaphore.h>
42
43 class LIBZCONVOLVER_API ZCsema
44 {
45 public:
46
47     ZCsema (void) { init (0, 0); }
48     ~ZCsema (void) { sem_destroy (&_sema); }
49
50     ZCsema (const ZCsema&); // disabled
51     ZCsema& operator= (const ZCsema&); // disabled
52
53     int init (int s, int v) { return sem_init (&_sema, s, v); }
54     int post (void) { return sem_post (&_sema); }
55     int wait (void) { return sem_wait (&_sema); }
56     int trywait (void) { return sem_trywait (&_sema); }
57
58 private:
59
60     sem_t  _sema;
61 };
62
63 #define ZCSEMA_IS_IMPLEMENTED
64 #endif
65
66
67 #ifdef __APPLE__
68
69 // NOTE:  ***** I DO NOT REPEAT NOT PROVIDE SUPPORT FOR OSX *****
70 // 
71 // The following code partially emulates the POSIX sem_t for which
72 // OSX has only a crippled implementation. It may or may not compile,
73 // and if it compiles it may or may not work correctly. Blame APPLE
74 // for not following POSIX standards.
75
76 class LIBZCONVOLVER_API ZCsema
77 {
78 public:
79
80     ZCsema (void) : _count (0)
81     {
82         init (0, 0);
83     }
84
85     ~ZCsema (void)
86     {
87         pthread_mutex_destroy (&_mutex);
88         pthread_cond_destroy (&_cond);
89     }
90
91     ZCsema (const ZCsema&); // disabled
92     ZCsema& operator= (const ZCsema&); // disabled
93
94     int init (int s, int v)
95     {
96         _count = v;
97         return pthread_mutex_init (&_mutex, 0) || pthread_cond_init (&_cond, 0);
98     }
99
100     int post (void)
101     {
102         pthread_mutex_lock (&_mutex);
103         _count++;
104         if (_count == 1) pthread_cond_signal (&_cond);
105         pthread_mutex_unlock (&_mutex);
106         return 0;
107     }
108
109     int wait (void)
110     {
111         pthread_mutex_lock (&_mutex);
112         while (_count < 1) pthread_cond_wait (&_cond, &_mutex);
113         _count--;
114         pthread_mutex_unlock (&_mutex);
115         return 0;
116     }
117
118     int trywait (void)
119     {
120         if (pthread_mutex_trylock (&_mutex)) return -1;
121         if (_count < 1)
122         {
123             pthread_mutex_unlock (&_mutex);
124             return -1;
125         }
126         _count--;
127         pthread_mutex_unlock (&_mutex);
128         return 0;
129     }
130
131 private:
132
133     int              _count;
134     pthread_mutex_t  _mutex;
135     pthread_cond_t   _cond;
136 };
137
138 #define ZCSEMA_IS_IMPLEMENTED
139 #endif
140
141
142 #ifndef ZCSEMA_IS_IMPLEMENTED
143 #error "The ZCsema class is not implemented."
144 #endif
145
146
147 // ----------------------------------------------------------------------------
148
149
150 class LIBZCONVOLVER_API Inpnode   
151 {
152 private:
153
154     friend class Convlevel;
155
156     Inpnode (uint16_t inp);
157     ~Inpnode (void);
158     void alloc_ffta (uint16_t npar, int32_t size);
159     void free_ffta (void);
160     
161     Inpnode        *_next;
162     fftwf_complex **_ffta;
163     uint16_t        _npar;
164     uint16_t        _inp;
165 };
166
167
168 class LIBZCONVOLVER_API Macnode  
169 {
170 private:
171
172     friend class Convlevel;
173
174     Macnode (Inpnode *inpn);
175     ~Macnode (void);
176     void alloc_fftb (uint16_t npar);
177     void free_fftb (void);
178
179     Macnode        *_next;
180     Inpnode        *_inpn;
181     Macnode        *_link;
182     fftwf_complex **_fftb;
183     uint16_t        _npar;
184 };
185
186
187 class LIBZCONVOLVER_API Outnode   
188 {
189 private:
190
191     friend class Convlevel;
192
193     Outnode (uint16_t out, int32_t size);
194     ~Outnode (void);
195     
196     Outnode        *_next;
197     Macnode        *_list;
198     float          *_buff [3];
199     uint16_t        _out;
200 };
201
202
203 class LIBZCONVOLVER_API Converror
204 {
205 public:
206
207     enum
208     {
209         BAD_STATE = -1,
210         BAD_PARAM = -2,
211         MEM_ALLOC = -3
212     };
213
214     Converror (int error) : _error (error) {}
215
216 private:
217
218     int _error;
219 };
220
221
222 class LIBZCONVOLVER_API Convlevel
223 {
224 private:
225
226     friend class Convproc;
227
228     enum 
229     {
230         OPT_FFTW_MEASURE = 1,
231         OPT_VECTOR_MODE  = 2,
232         OPT_LATE_CONTIN  = 4
233     };
234
235     enum
236     {
237         ST_IDLE,
238         ST_TERM,
239         ST_PROC
240     };
241
242     Convlevel (void);
243     ~Convlevel (void);
244
245     void configure (int      prio,
246                     uint32_t offs,
247                     uint32_t npar,
248                     uint32_t parsize,
249                     uint32_t options);
250
251     void impdata_write (uint32_t  inp,
252                         uint32_t  out,
253                         int32_t   step,
254                         float     *data,
255                         int32_t   ind0,
256                         int32_t   ind1,
257                         bool      create);
258
259     void impdata_clear (uint32_t  inp,
260                         uint32_t  out);
261
262     void impdata_link (uint32_t  inp1,
263                        uint32_t  out1,
264                        uint32_t  inp2,
265                        uint32_t  out2);
266
267     void reset (uint32_t  inpsize,
268                 uint32_t  outsize,
269                 float     **inpbuff,
270                 float     **outbuff);
271
272     void start (int absprio, int policy);
273
274     void process (bool sync);
275
276     int  readout (bool sync, uint32_t skipcnt);
277
278     void stop (void);
279
280     void cleanup (void);
281
282     void fftswap (fftwf_complex *p);
283
284     void print (FILE *F);
285
286     static void *static_main (void *arg);
287
288     void main (void);
289
290     Macnode *findmacnode (uint32_t inp, uint32_t out, bool create);
291
292
293     volatile uint32_t   _stat;           // current processing state
294     int                 _prio;           // relative priority
295     uint32_t            _offs;           // offset from start of impulse response
296     uint32_t            _npar;           // number of partitions
297     uint32_t            _parsize;        // partition and outbut buffer size
298     uint32_t            _outsize;        // step size for output buffer
299     uint32_t            _outoffs;        // offset into output buffer
300     uint32_t            _inpsize;        // size of shared input buffer 
301     uint32_t            _inpoffs;        // offset into input buffer
302     uint32_t            _options;        // various options
303     uint32_t            _ptind;          // rotating partition index
304     uint32_t            _opind;          // rotating output buffer index
305     int                 _bits;           // bit identifiying this level
306     int                 _wait;           // number of unfinished cycles
307     pthread_t           _pthr;           // posix thread executing this level
308     ZCsema              _trig;           // sema used to trigger a cycle
309     ZCsema              _done;           // sema used to wait for a cycle
310     Inpnode            *_inp_list;       // linked list of active inputs
311     Outnode            *_out_list;       // linked list of active outputs
312     fftwf_plan          _plan_r2c;       // FFTW plan, forward FFT
313     fftwf_plan          _plan_c2r;       // FFTW plan, inverse FFT
314     float              *_time_data;      // workspace
315     float              *_prep_data;      // workspace
316     fftwf_complex      *_freq_data;      // workspace
317     float             **_inpbuff;        // array of shared input buffers
318     float             **_outbuff;        // array of shared output buffers
319 };
320
321
322 // ----------------------------------------------------------------------------
323
324
325 class LIBZCONVOLVER_API Convproc
326 {
327 public:
328
329     Convproc (void);
330     ~Convproc (void);
331
332     enum
333     {
334         ST_IDLE,
335         ST_STOP,
336         ST_WAIT,
337         ST_PROC
338     };
339
340     enum
341     {
342         FL_LATE = 0x0000FFFF,
343         FL_LOAD = 0x01000000
344     };
345
346     enum 
347     {
348         OPT_FFTW_MEASURE = Convlevel::OPT_FFTW_MEASURE, 
349         OPT_VECTOR_MODE  = Convlevel::OPT_VECTOR_MODE,
350         OPT_LATE_CONTIN  = Convlevel::OPT_LATE_CONTIN
351     };
352
353     enum
354     {
355         MAXINP   = 64,
356         MAXOUT   = 64,
357         MAXLEV   = 8,
358         MINPART  = 64,
359         MAXPART  = 8192,
360         MAXDIVIS = 16,
361         MINQUANT = 16,
362         MAXQUANT = 8192
363     };
364
365     uint32_t state (void) const
366     {
367         return _state;
368     }
369
370     float *inpdata (uint32_t inp) const
371     {
372         return _inpbuff [inp] + _inpoffs;
373     }
374
375     float *outdata (uint32_t out) const
376     {
377         return _outbuff [out] + _outoffs;
378     }
379
380     int configure (uint32_t  ninp,
381                    uint32_t  nout,
382                    uint32_t  maxsize,
383                    uint32_t  quantum,
384                    uint32_t  minpart,
385                    uint32_t  maxpart,
386                    float     density);
387
388     int impdata_create (uint32_t  inp,
389                         uint32_t  out,
390                         int32_t   step,
391                         float     *data,
392                         int32_t   ind0,
393                         int32_t   ind1); 
394
395     int impdata_clear (uint32_t  inp,
396                        uint32_t  out);
397
398     int impdata_update (uint32_t  inp,
399                         uint32_t  out,
400                         int32_t   step,
401                         float     *data,
402                         int32_t   ind0,
403                         int32_t   ind1); 
404
405     int impdata_link (uint32_t  inp1,
406                       uint32_t  out1,
407                       uint32_t  inp2,
408                       uint32_t  out2);
409
410     // Deprecated, use impdata_link() instead.
411     int impdata_copy (uint32_t  inp1,
412                       uint32_t  out1,
413                       uint32_t  inp2,
414                       uint32_t  out2)
415     {
416         return impdata_link (inp1, out1, inp2, out2);
417     }
418     
419     void set_options (uint32_t options);
420
421     void set_skipcnt (uint32_t skipcnt);
422
423     int  reset (void);
424
425     int  start_process (int abspri, int policy);
426
427     int  process (bool sync = false);
428
429     int  stop_process (void);
430
431     bool check_stop (void);
432
433     int  cleanup (void);
434
435     void print (FILE *F = stdout);
436
437 private:
438
439     uint32_t    _state;                   // current state
440     float      *_inpbuff [MAXINP];        // input buffers
441     float      *_outbuff [MAXOUT];        // output buffers
442     uint32_t    _inpoffs;                 // current offset in input buffers
443     uint32_t    _outoffs;                 // current offset in output buffers
444     uint32_t    _options;                 // option bits
445     uint32_t    _skipcnt;                 // number of frames to skip 
446     uint32_t    _ninp;                    // number of inputs
447     uint32_t    _nout;                    // number of outputs
448     uint32_t    _quantum;                 // processing block size
449     uint32_t    _minpart;                 // smallest partition size
450     uint32_t    _maxpart;                 // largest allowed partition size
451     uint32_t    _nlevels;                 // number of partition sizes
452     uint32_t    _inpsize;                 // size of input buffers
453     uint32_t    _latecnt;                 // count of cycles ending too late
454     Convlevel  *_convlev [MAXLEV];        // array of processors 
455     void       *_dummy [64];
456
457     static float  _mac_cost;
458     static float  _fft_cost;
459 };
460
461
462 // ----------------------------------------------------------------------------
463
464 } /* end namespace */
465
466 #endif
467