Update Fluidsynth to 2.0.1
[ardour.git] / libs / fluidsynth / src / fluid_sys.h
1 /* FluidSynth - A Software Synthesizer
2  *
3  * Copyright (C) 2003  Peter Hanappe and others.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public License
7  * as published by the Free Software Foundation; either version 2.1 of
8  * the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free
17  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18  * 02110-1301, USA
19  */
20
21
22 /**
23
24    This header contains a bunch of (mostly) system and machine
25    dependent functions:
26
27    - timers
28    - current time in milliseconds and microseconds
29    - debug logging
30    - profiling
31    - memory locking
32    - checking for floating point exceptions
33
34  */
35
36 #ifndef _FLUID_SYS_H
37 #define _FLUID_SYS_H
38
39 #include "fluidsynth_priv.h"
40
41 #ifdef LADSPA
42 #include <gmodule.h>
43 #endif
44
45 #include <glib/gstdio.h>
46
47 /**
48  * Macro used for safely accessing a message from a GError and using a default
49  * message if it is NULL.
50  * @param err Pointer to a GError to access the message field of.
51  * @return Message string
52  */
53 #define fluid_gerror_message(err)  ((err) ? err->message : "No error details")
54
55 /* Misc */
56 #if defined(__INTEL_COMPILER)
57 #define FLUID_RESTRICT restrict
58 #elif defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
59 #define FLUID_RESTRICT __restrict__
60 #elif defined(_MSC_VER) && _MSC_VER >= 1400
61 #define FLUID_RESTRICT __restrict
62 #else
63 #warning "Dont know how this compiler handles restrict pointers, refuse to use them."
64 #define FLUID_RESTRICT
65 #endif
66
67 #define FLUID_INLINE              inline
68 #define FLUID_POINTER_TO_UINT     GPOINTER_TO_UINT
69 #define FLUID_UINT_TO_POINTER     GUINT_TO_POINTER
70 #define FLUID_POINTER_TO_INT      GPOINTER_TO_INT
71 #define FLUID_INT_TO_POINTER      GINT_TO_POINTER
72 #define FLUID_N_ELEMENTS(struct)  (sizeof (struct) / sizeof (struct[0]))
73 #define FLUID_MEMBER_SIZE(struct, member)  ( sizeof (((struct *)0)->member) )
74
75 #define FLUID_IS_BIG_ENDIAN       (G_BYTE_ORDER == G_BIG_ENDIAN)
76
77 #define FLUID_LE32TOH(x)          GINT32_FROM_LE(x)
78 #define FLUID_LE16TOH(x)          GINT16_FROM_LE(x)
79
80
81 #define fluid_return_if_fail(cond) \
82 if(cond) \
83     ; \
84 else \
85     return
86
87 #define fluid_return_val_if_fail(cond, val) \
88  fluid_return_if_fail(cond) (val)
89
90
91 /*
92  * Utility functions
93  */
94 char *fluid_strtok(char **str, const char *delim);
95
96
97 #if defined(__OS2__)
98 #define INCL_DOS
99 #include <os2.h>
100
101 typedef int socklen_t;
102 #endif
103
104 unsigned int fluid_curtime(void);
105 double fluid_utime(void);
106
107
108 /**
109     Timers
110
111  */
112
113 /* if the callback function returns 1 the timer will continue; if it
114    returns 0 it will stop */
115 typedef int (*fluid_timer_callback_t)(void *data, unsigned int msec);
116
117 typedef struct _fluid_timer_t fluid_timer_t;
118
119 fluid_timer_t *new_fluid_timer(int msec, fluid_timer_callback_t callback,
120                                void *data, int new_thread, int auto_destroy,
121                                int high_priority);
122
123 void delete_fluid_timer(fluid_timer_t *timer);
124 int fluid_timer_join(fluid_timer_t *timer);
125 int fluid_timer_stop(fluid_timer_t *timer);
126
127 // Macros to use for pre-processor if statements to test which Glib thread API we have (pre or post 2.32)
128 #define NEW_GLIB_THREAD_API  (GLIB_MAJOR_VERSION > 2 || (GLIB_MAJOR_VERSION == 2 && GLIB_MINOR_VERSION >= 32))
129 #define OLD_GLIB_THREAD_API  (GLIB_MAJOR_VERSION < 2 || (GLIB_MAJOR_VERSION == 2 && GLIB_MINOR_VERSION < 32))
130
131 /* Muteces */
132
133 #if NEW_GLIB_THREAD_API
134
135 /* glib 2.32 and newer */
136
137 /* Regular mutex */
138 typedef GMutex fluid_mutex_t;
139 #define FLUID_MUTEX_INIT          { 0 }
140 #define fluid_mutex_init(_m)      g_mutex_init (&(_m))
141 #define fluid_mutex_destroy(_m)   g_mutex_clear (&(_m))
142 #define fluid_mutex_lock(_m)      g_mutex_lock(&(_m))
143 #define fluid_mutex_unlock(_m)    g_mutex_unlock(&(_m))
144
145 /* Recursive lock capable mutex */
146 typedef GRecMutex fluid_rec_mutex_t;
147 #define fluid_rec_mutex_init(_m)      g_rec_mutex_init(&(_m))
148 #define fluid_rec_mutex_destroy(_m)   g_rec_mutex_clear(&(_m))
149 #define fluid_rec_mutex_lock(_m)      g_rec_mutex_lock(&(_m))
150 #define fluid_rec_mutex_unlock(_m)    g_rec_mutex_unlock(&(_m))
151
152 /* Dynamically allocated mutex suitable for fluid_cond_t use */
153 typedef GMutex    fluid_cond_mutex_t;
154 #define fluid_cond_mutex_lock(m)        g_mutex_lock(m)
155 #define fluid_cond_mutex_unlock(m)      g_mutex_unlock(m)
156
157 static FLUID_INLINE fluid_cond_mutex_t *
158 new_fluid_cond_mutex(void)
159 {
160     GMutex *mutex;
161     mutex = g_new(GMutex, 1);
162     g_mutex_init(mutex);
163     return (mutex);
164 }
165
166 static FLUID_INLINE void
167 delete_fluid_cond_mutex(fluid_cond_mutex_t *m)
168 {
169     fluid_return_if_fail(m != NULL);
170     g_mutex_clear(m);
171     g_free(m);
172 }
173
174 /* Thread condition signaling */
175 typedef GCond fluid_cond_t;
176 #define fluid_cond_signal(cond)         g_cond_signal(cond)
177 #define fluid_cond_broadcast(cond)      g_cond_broadcast(cond)
178 #define fluid_cond_wait(cond, mutex)    g_cond_wait(cond, mutex)
179
180 static FLUID_INLINE fluid_cond_t *
181 new_fluid_cond(void)
182 {
183     GCond *cond;
184     cond = g_new(GCond, 1);
185     g_cond_init(cond);
186     return (cond);
187 }
188
189 static FLUID_INLINE void
190 delete_fluid_cond(fluid_cond_t *cond)
191 {
192     fluid_return_if_fail(cond != NULL);
193     g_cond_clear(cond);
194     g_free(cond);
195 }
196
197 /* Thread private data */
198
199 typedef GPrivate fluid_private_t;
200 #define fluid_private_init(_priv)                  memset (&_priv, 0, sizeof (_priv))
201 #define fluid_private_free(_priv)
202 #define fluid_private_get(_priv)                   g_private_get(&(_priv))
203 #define fluid_private_set(_priv, _data)            g_private_set(&(_priv), _data)
204
205 #else
206
207 /* glib prior to 2.32 */
208
209 /* Regular mutex */
210 typedef GStaticMutex fluid_mutex_t;
211 #define FLUID_MUTEX_INIT          G_STATIC_MUTEX_INIT
212 #define fluid_mutex_destroy(_m)   g_static_mutex_free(&(_m))
213 #define fluid_mutex_lock(_m)      g_static_mutex_lock(&(_m))
214 #define fluid_mutex_unlock(_m)    g_static_mutex_unlock(&(_m))
215
216 #define fluid_mutex_init(_m)      do { \
217   if (!g_thread_supported ()) g_thread_init (NULL); \
218   g_static_mutex_init (&(_m)); \
219 } while(0)
220
221 /* Recursive lock capable mutex */
222 typedef GStaticRecMutex fluid_rec_mutex_t;
223 #define fluid_rec_mutex_destroy(_m)   g_static_rec_mutex_free(&(_m))
224 #define fluid_rec_mutex_lock(_m)      g_static_rec_mutex_lock(&(_m))
225 #define fluid_rec_mutex_unlock(_m)    g_static_rec_mutex_unlock(&(_m))
226
227 #define fluid_rec_mutex_init(_m)      do { \
228   if (!g_thread_supported ()) g_thread_init (NULL); \
229   g_static_rec_mutex_init (&(_m)); \
230 } while(0)
231
232 /* Dynamically allocated mutex suitable for fluid_cond_t use */
233 typedef GMutex    fluid_cond_mutex_t;
234 #define delete_fluid_cond_mutex(m)      g_mutex_free(m)
235 #define fluid_cond_mutex_lock(m)        g_mutex_lock(m)
236 #define fluid_cond_mutex_unlock(m)      g_mutex_unlock(m)
237
238 static FLUID_INLINE fluid_cond_mutex_t *
239 new_fluid_cond_mutex(void)
240 {
241     if(!g_thread_supported())
242     {
243         g_thread_init(NULL);
244     }
245
246     return g_mutex_new();
247 }
248
249 /* Thread condition signaling */
250 typedef GCond fluid_cond_t;
251 fluid_cond_t *new_fluid_cond(void);
252 #define delete_fluid_cond(cond)         g_cond_free(cond)
253 #define fluid_cond_signal(cond)         g_cond_signal(cond)
254 #define fluid_cond_broadcast(cond)      g_cond_broadcast(cond)
255 #define fluid_cond_wait(cond, mutex)    g_cond_wait(cond, mutex)
256
257 /* Thread private data */
258 typedef GStaticPrivate fluid_private_t;
259 #define fluid_private_get(_priv)                   g_static_private_get(&(_priv))
260 #define fluid_private_set(_priv, _data)            g_static_private_set(&(_priv), _data, NULL)
261 #define fluid_private_free(_priv)                  g_static_private_free(&(_priv))
262
263 #define fluid_private_init(_priv)                  do { \
264   if (!g_thread_supported ()) g_thread_init (NULL); \
265   g_static_private_init (&(_priv)); \
266 } while(0)
267
268 #endif
269
270
271 /* Atomic operations */
272
273 #define fluid_atomic_int_inc(_pi) g_atomic_int_inc(_pi)
274 #define fluid_atomic_int_get(_pi) g_atomic_int_get(_pi)
275 #define fluid_atomic_int_set(_pi, _val) g_atomic_int_set(_pi, _val)
276 #define fluid_atomic_int_dec_and_test(_pi) g_atomic_int_dec_and_test(_pi)
277 #define fluid_atomic_int_compare_and_exchange(_pi, _old, _new) \
278   g_atomic_int_compare_and_exchange(_pi, _old, _new)
279
280 #if GLIB_MAJOR_VERSION > 2 || (GLIB_MAJOR_VERSION == 2 && GLIB_MINOR_VERSION >= 30)
281 #define fluid_atomic_int_exchange_and_add(_pi, _add) \
282   g_atomic_int_add(_pi, _add)
283 #define fluid_atomic_int_add(_pi, _add) \
284   g_atomic_int_add(_pi, _add)
285 #else
286 #define fluid_atomic_int_exchange_and_add(_pi, _add) \
287   g_atomic_int_exchange_and_add(_pi, _add)
288 #define fluid_atomic_int_add(_pi, _add) \
289   g_atomic_int_exchange_and_add(_pi, _add)
290 #endif
291
292 #define fluid_atomic_pointer_get(_pp)           g_atomic_pointer_get(_pp)
293 #define fluid_atomic_pointer_set(_pp, val)      g_atomic_pointer_set(_pp, val)
294 #define fluid_atomic_pointer_compare_and_exchange(_pp, _old, _new) \
295   g_atomic_pointer_compare_and_exchange(_pp, _old, _new)
296
297 static FLUID_INLINE void
298 fluid_atomic_float_set(volatile float *fptr, float val)
299 {
300     int32_t ival;
301     memcpy(&ival, &val, 4);
302     fluid_atomic_int_set((volatile int *)fptr, ival);
303 }
304
305 static FLUID_INLINE float
306 fluid_atomic_float_get(volatile float *fptr)
307 {
308     int32_t ival;
309     float fval;
310     ival = fluid_atomic_int_get((volatile int *)fptr);
311     memcpy(&fval, &ival, 4);
312     return fval;
313 }
314
315
316 /* Threads */
317
318 /* other thread implementations might change this for their needs */
319 typedef void *fluid_thread_return_t;
320 /* static return value for thread functions which requires a return value */
321 #define FLUID_THREAD_RETURN_VALUE (NULL)
322
323 typedef GThread fluid_thread_t;
324 typedef fluid_thread_return_t (*fluid_thread_func_t)(void *data);
325
326 #define FLUID_THREAD_ID_NULL            NULL                    /* A NULL "ID" value */
327 #define fluid_thread_id_t               GThread *               /* Data type for a thread ID */
328 #define fluid_thread_get_id()           g_thread_self()         /* Get unique "ID" for current thread */
329
330 fluid_thread_t *new_fluid_thread(const char *name, fluid_thread_func_t func, void *data,
331                                  int prio_level, int detach);
332 void delete_fluid_thread(fluid_thread_t *thread);
333 void fluid_thread_self_set_prio(int prio_level);
334 int fluid_thread_join(fluid_thread_t *thread);
335
336 /* Dynamic Module Loading, currently only used by LADSPA subsystem */
337 #ifdef LADSPA
338
339 typedef GModule fluid_module_t;
340
341 #define fluid_module_open(_name)        g_module_open((_name), G_MODULE_BIND_LOCAL)
342 #define fluid_module_close(_mod)        g_module_close(_mod)
343 #define fluid_module_error()            g_module_error()
344 #define fluid_module_name(_mod)         g_module_name(_mod)
345 #define fluid_module_symbol(_mod, _name, _ptr) g_module_symbol((_mod), (_name), (_ptr))
346
347 #endif /* LADSPA */
348
349 /* Sockets and I/O */
350
351 fluid_istream_t fluid_get_stdin(void);
352 fluid_ostream_t fluid_get_stdout(void);
353 int fluid_istream_readline(fluid_istream_t in, fluid_ostream_t out, char *prompt, char *buf, int len);
354 int fluid_ostream_printf(fluid_ostream_t out, const char *format, ...);
355
356 /* The function should return 0 if no error occured, non-zero
357    otherwise. If the function return non-zero, the socket will be
358    closed by the server. */
359 typedef int (*fluid_server_func_t)(void *data, fluid_socket_t client_socket, char *addr);
360
361 fluid_server_socket_t *new_fluid_server_socket(int port, fluid_server_func_t func, void *data);
362 void delete_fluid_server_socket(fluid_server_socket_t *sock);
363 int fluid_server_socket_join(fluid_server_socket_t *sock);
364 void fluid_socket_close(fluid_socket_t sock);
365 fluid_istream_t fluid_socket_get_istream(fluid_socket_t sock);
366 fluid_ostream_t fluid_socket_get_ostream(fluid_socket_t sock);
367
368 /* File access */
369 #if !GLIB_CHECK_VERSION(2, 26, 0)
370     /* GStatBuf has not been introduced yet, manually typedef to what they had at that time:
371      * https://github.com/GNOME/glib/blob/e7763678b56e3be073cc55d707a6e92fc2055ee0/glib/gstdio.h#L98-L115
372      */
373     #if defined(WIN32) || HAVE_WINDOWS_H // somehow reliably mock G_OS_WIN32??
374         #if defined (_MSC_VER) && !defined(_WIN64)
375         typedef struct _stat32 fluid_stat_buf_t;
376         #else
377         typedef struct _stat fluid_stat_buf_t;
378         #endif
379     #else
380     /* posix, OS/2, etc. */
381     typedef struct stat fluid_stat_buf_t;
382     #endif
383 #else
384 typedef GStatBuf fluid_stat_buf_t;
385 #endif
386 #define fluid_stat(_filename, _statbuf)   g_stat((_filename), (_statbuf))
387
388
389 /* Profiling */
390 #if WITH_PROFILING
391 /** profiling interface beetween Profiling command shell and Audio
392     rendering  API (FluidProfile_0004.pdf- 3.2.2)
393 */
394
395 /*
396   -----------------------------------------------------------------------------
397   Shell task side |    Profiling interface              |  Audio task side
398   -----------------------------------------------------------------------------
399   profiling       |    Internal    |      |             |      Audio
400   command   <---> |<-- profling -->| Data |<--macros -->| <--> rendering
401   shell           |    API         |      |             |      API
402
403 */
404
405 /* default parameters for shell command "prof_start" in fluid_sys.c */
406 #define FLUID_PROFILE_DEFAULT_BANK 0       /* default bank */
407 #define FLUID_PROFILE_DEFAULT_PROG 16      /* default prog (organ) */
408 #define FLUID_PROFILE_FIRST_KEY 12         /* first key generated */
409 #define FLUID_PROFILE_LAST_KEY 108         /* last key generated */
410 #define FLUID_PROFILE_DEFAULT_VEL 64       /* default note velocity */
411 #define FLUID_PROFILE_VOICE_ATTEN -0.04f   /* gain attenuation per voice (dB) */
412
413
414 #define FLUID_PROFILE_DEFAULT_PRINT 0      /* default print mode */
415 #define FLUID_PROFILE_DEFAULT_N_PROF 1     /* default number of measures */
416 #define FLUID_PROFILE_DEFAULT_DURATION 500 /* default duration (ms)  */
417
418
419 extern unsigned short fluid_profile_notes; /* number of generated notes */
420 extern unsigned char fluid_profile_bank;   /* bank,prog preset used by */
421 extern unsigned char fluid_profile_prog;   /* generated notes */
422 extern unsigned char fluid_profile_print;  /* print mode */
423
424 extern unsigned short fluid_profile_n_prof;/* number of measures */
425 extern unsigned short fluid_profile_dur;   /* measure duration in ms */
426 extern fluid_atomic_int_t fluid_profile_lock ; /* lock between multiple shell */
427 /**/
428
429 /*----------------------------------------------
430   Internal profiling API (in fluid_sys.c)
431 -----------------------------------------------*/
432 /* Starts a profiling measure used in shell command "prof_start" */
433 void fluid_profile_start_stop(unsigned int end_ticks, short clear_data);
434
435 /* Returns status used in shell command "prof_start" */
436 int fluid_profile_get_status(void);
437
438 /* Prints profiling data used in shell command "prof_start" */
439 void fluid_profiling_print_data(double sample_rate, fluid_ostream_t out);
440
441 /* Returns True if profiling cancellation has been requested */
442 int fluid_profile_is_cancel_req(void);
443
444 /* For OS that implement <ENTER> key for profile cancellation:
445  1) Adds #define FLUID_PROFILE_CANCEL
446  2) Adds the necessary code inside fluid_profile_is_cancel() see fluid_sys.c
447 */
448 #if defined(WIN32)      /* Profile cancellation is supported for Windows */
449 #define FLUID_PROFILE_CANCEL
450
451 #elif defined(__OS2__)  /* OS/2 specific stuff */
452 /* Profile cancellation isn't yet supported for OS2 */
453
454 #else   /* POSIX stuff */
455 #define FLUID_PROFILE_CANCEL /* Profile cancellation is supported for linux */
456 #include <unistd.h> /* STDIN_FILENO */
457 #include <sys/select.h> /* select() */
458 #endif /* posix */
459
460 /* logging profiling data (used on synthesizer instance deletion) */
461 void fluid_profiling_print(void);
462
463 /*----------------------------------------------
464   Profiling Data (in fluid_sys.c)
465 -----------------------------------------------*/
466 /** Profiling data. Keep track of min/avg/max values to profile a
467     piece of code. */
468 typedef struct _fluid_profile_data_t
469 {
470     const char *description;        /* name of the piece of code under profiling */
471     double min, max, total;   /* duration (microsecond) */
472     unsigned int count;       /* total count */
473     unsigned int n_voices;    /* voices number */
474     unsigned int n_samples;   /* audio samples number */
475 } fluid_profile_data_t;
476
477 enum
478 {
479     /* commands/status  (profiling interface) */
480     PROFILE_STOP,    /* command to stop a profiling measure */
481     PROFILE_START,   /* command to start a profile measure */
482     PROFILE_READY,   /* status to signal that a profiling measure has finished
483                             and ready to be printed */
484     /*- State returned by fluid_profile_get_status() -*/
485     /* between profiling commands and internal profiling API */
486     PROFILE_RUNNING, /* a profiling measure is running */
487     PROFILE_CANCELED,/* a profiling measure has been canceled */
488 };
489
490 /* Data interface */
491 extern unsigned char fluid_profile_status ;       /* command and status */
492 extern unsigned int fluid_profile_end_ticks;      /* ending position (in ticks) */
493 extern fluid_profile_data_t fluid_profile_data[]; /* Profiling data */
494
495 /*----------------------------------------------
496   Probes macros
497 -----------------------------------------------*/
498 /** Macro to obtain a time reference used for the profiling */
499 #define fluid_profile_ref() fluid_utime()
500
501 /** Macro to create a variable and assign the current reference time for profiling.
502  * So we don't get unused variable warnings when profiling is disabled. */
503 #define fluid_profile_ref_var(name)     double name = fluid_utime()
504
505 /**
506  * Profile identifier numbers. List all the pieces of code you want to profile
507  * here. Be sure to add an entry in the fluid_profile_data table in
508  * fluid_sys.c
509  */
510 enum
511 {
512     FLUID_PROF_WRITE,
513     FLUID_PROF_ONE_BLOCK,
514     FLUID_PROF_ONE_BLOCK_CLEAR,
515     FLUID_PROF_ONE_BLOCK_VOICE,
516     FLUID_PROF_ONE_BLOCK_VOICES,
517     FLUID_PROF_ONE_BLOCK_REVERB,
518     FLUID_PROF_ONE_BLOCK_CHORUS,
519     FLUID_PROF_VOICE_NOTE,
520     FLUID_PROF_VOICE_RELEASE,
521     FLUID_PROFILE_NBR   /* number of profile probes */
522 };
523 /** Those macros are used to calculate the min/avg/max. Needs a profile number, a
524     time reference, the voices and samples number. */
525
526 /* local macro : acquiere data */
527 #define fluid_profile_data(_num, _ref, voices, samples)\
528 {\
529         double _now = fluid_utime();\
530         double _delta = _now - _ref;\
531         fluid_profile_data[_num].min = _delta < fluid_profile_data[_num].min ?\
532                                    _delta : fluid_profile_data[_num].min; \
533         fluid_profile_data[_num].max = _delta > fluid_profile_data[_num].max ?\
534                                    _delta : fluid_profile_data[_num].max;\
535         fluid_profile_data[_num].total += _delta;\
536         fluid_profile_data[_num].count++;\
537         fluid_profile_data[_num].n_voices += voices;\
538         fluid_profile_data[_num].n_samples += samples;\
539         _ref = _now;\
540 }
541
542 /** Macro to collect data, called from inner functions inside audio
543     rendering API */
544 #define fluid_profile(_num, _ref, voices, samples)\
545 {\
546         if ( fluid_profile_status == PROFILE_START)\
547         {       /* acquires data */\
548                 fluid_profile_data(_num, _ref, voices, samples)\
549         }\
550 }
551
552 /** Macro to collect data, called from audio rendering API (fluid_write_xxxx()).
553  This macro control profiling ending position (in ticks).
554 */
555 #define fluid_profile_write(_num, _ref, voices, samples)\
556 {\
557         if (fluid_profile_status == PROFILE_START)\
558         {\
559                 /* acquires data first: must be done before checking that profile is
560            finished to ensure at least one valid data sample.
561                 */\
562                 fluid_profile_data(_num, _ref, voices, samples)\
563                 if (fluid_synth_get_ticks(synth) >= fluid_profile_end_ticks)\
564                 {\
565                         /* profiling is finished */\
566                         fluid_profile_status = PROFILE_READY;\
567                 }\
568         }\
569 }
570
571 #else
572
573 /* No profiling */
574 #define fluid_profiling_print()
575 #define fluid_profile_ref()  0
576 #define fluid_profile_ref_var(name)
577 #define fluid_profile(_num,_ref,voices, samples)
578 #define fluid_profile_write(_num,_ref, voices, samples)
579 #endif /* WITH_PROFILING */
580
581 /**
582
583     Memory locking
584
585     Memory locking is used to avoid swapping of the large block of
586     sample data.
587  */
588
589 #if defined(HAVE_SYS_MMAN_H) && !defined(__OS2__)
590 #define fluid_mlock(_p,_n)      mlock(_p, _n)
591 #define fluid_munlock(_p,_n)    munlock(_p,_n)
592 #else
593 #define fluid_mlock(_p,_n)      0
594 #define fluid_munlock(_p,_n)
595 #endif
596
597
598 /**
599
600     Floating point exceptions
601
602     fluid_check_fpe() checks for "unnormalized numbers" and other
603     exceptions of the floating point processsor.
604 */
605 #ifdef FPE_CHECK
606 #define fluid_check_fpe(expl) fluid_check_fpe_i386(expl)
607 #define fluid_clear_fpe() fluid_clear_fpe_i386()
608 #else
609 #define fluid_check_fpe(expl)
610 #define fluid_clear_fpe()
611 #endif
612
613 unsigned int fluid_check_fpe_i386(char *explanation_in_case_of_fpe);
614 void fluid_clear_fpe_i386(void);
615
616 /* System control */
617 void fluid_msleep(unsigned int msecs);
618
619 /**
620  * Advances the given \c ptr to the next \c alignment byte boundary.
621  * Make sure you've allocated an extra of \c alignment bytes to avoid a buffer overflow.
622  *
623  * @note \c alignment must be a power of two
624  * @return Returned pointer is guarenteed to be aligned to \c alignment boundary and in range \f[ ptr <= returned_ptr < ptr + alignment \f].
625  */
626 static FLUID_INLINE void *fluid_align_ptr(const void *ptr, unsigned int alignment)
627 {
628     uintptr_t ptr_int = (uintptr_t)ptr;
629     unsigned int offset = ptr_int & (alignment - 1);
630     unsigned int add = (alignment - offset) & (alignment - 1); // advance the pointer to the next alignment boundary
631     ptr_int += add;
632
633     /* assert alignment is power of two */
634     FLUID_ASSERT(!(alignment == 0) && !(alignment & (alignment - 1)));
635
636     return (void *)ptr_int;
637 }
638
639 #define FLUID_DEFAULT_ALIGNMENT (64U)
640
641 #endif /* _FLUID_SYS_H */