Path: blob/master/libs/fluidsynth/src/utils/fluid_sys.h
8669 views
/* FluidSynth - A Software Synthesizer1*2* Copyright (C) 2003 Peter Hanappe and others.3*4* This library is free software; you can redistribute it and/or5* modify it under the terms of the GNU Lesser General Public License6* as published by the Free Software Foundation; either version 2.1 of7* the License, or (at your option) any later version.8*9* This library is distributed in the hope that it will be useful, but10* WITHOUT ANY WARRANTY; without even the implied warranty of11* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU12* Lesser General Public License for more details.13*14* You should have received a copy of the GNU Lesser General Public15* License along with this library; if not, write to the Free16* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA17* 02110-1301, USA18*/192021/*22* @file fluid_sys.h23*24* This header contains a bunch of (mostly) system and machine25* dependent functions:26*27* - timers28* - current time in milliseconds and microseconds29* - debug logging30* - profiling31* - memory locking32* - checking for floating point exceptions33*34* fluidsynth's wrapper OSAL so to say; include it in .c files, be careful to include35* it in fluidsynth's private header files (see comment in fluid_coreaudio.c)36*/3738#ifndef _FLUID_SYS_H39#define _FLUID_SYS_H4041#include "fluidsynth_priv.h"4243#if HAVE_MATH_H44#include <math.h>45#endif4647#if HAVE_ERRNO_H48#include <errno.h>49#endif5051#if HAVE_STDARG_H52#include <stdarg.h>53#endif5455#if HAVE_UNISTD_H56#include <unistd.h>57#endif5859#if HAVE_FCNTL_H60#include <fcntl.h>61#endif6263#if HAVE_SYS_MMAN_H64#include <sys/mman.h>65#endif6667#if HAVE_SYS_TYPES_H68#include <sys/types.h>69#endif7071#if HAVE_SYS_STAT_H72#include <sys/stat.h>73#endif7475#if HAVE_SYS_TIME_H76#include <sys/time.h>77#endif7879#if HAVE_SYS_SOCKET_H80#include <sys/socket.h>81#endif8283#if HAVE_NETINET_IN_H84#include <netinet/in.h>85#endif8687#if HAVE_NETINET_TCP_H88#include <netinet/tcp.h>89#endif9091#if HAVE_ARPA_INET_H92#include <arpa/inet.h>93#endif9495#if HAVE_LIMITS_H96#include <limits.h>97#endif9899#if HAVE_OPENMP100#include <omp.h>101#endif102103#if HAVE_IO_H104#include <io.h> // _open(), _close(), read(), write() on windows105#endif106107#if HAVE_SIGNAL_H108#include <signal.h>109#endif110111/** Integer types */112#if HAVE_STDINT_H113#include <stdint.h>114115#else116117/* Assume GLIB types */118typedef gint8 int8_t;119typedef guint8 uint8_t;120typedef gint16 int16_t;121typedef guint16 uint16_t;122typedef gint32 int32_t;123typedef guint32 uint32_t;124typedef gint64 int64_t;125typedef guint64 uint64_t;126typedef guintptr uintptr_t;127typedef gintptr intptr_t;128129#endif130131/*132* CYGWIN has its own version of <windows.h>, which can be133* safely included together with POSIX includes.134* Thanks to this, CYGWIN can also run audio output and MIDI135* input drivers from traditional interfaces of Windows.136*/137#if defined(__CYGWIN__) && HAVE_WINDOWS_H138#include <windows.h>139#include <wchar.h>140#endif141142#if defined(_WIN32) && HAVE_WINDOWS_H143#include <winsock2.h>144#include <ws2tcpip.h> /* Provides also socklen_t */145146/* WIN32 special defines */147#define STDIN_FILENO 0148#define STDOUT_FILENO 1149#define STDERR_FILENO 2150151#ifdef _MSC_VER152#pragma warning(disable : 4244)153#pragma warning(disable : 4101)154#pragma warning(disable : 4305)155#pragma warning(disable : 4996)156#endif157158/*159* Required by Windows-specific sf_wchar_open() from old libsndfile160* versions before v1.1.0, that takes a UTF16_BE encoded filename.161* Note that FluidSynth needs libsndfile >= v1.2.1 anyway.162*/163#define ENABLE_SNDFILE_WINDOWS_PROTOTYPES 1164165#endif166167/* Darwin special defines (taken from config_macosx.h) */168#ifdef DARWIN169# define MACINTOSH170# define __Types__171#endif172173#ifdef LADSPA174#include <gmodule.h>175#endif176177/* #include <glib/gstdio.h> */178179/**180* Macro used for safely accessing a message from a GError and using a default181* message if it is NULL.182* @param err Pointer to a GError to access the message field of.183* @return Message string184*/185#define fluid_gerror_message(err) ((err) ? err->message : "No error details")186187#if defined(_WIN32) || defined(__CYGWIN__)188char* fluid_get_windows_error(void);189#endif190191#define FLUID_INLINE inline192193#define FLUID_VERSION_CHECK(major, minor, patch) ((major<<16)|(minor<<8)|(patch))194195/* Integer<->pointer conversion */196#define FLUID_POINTER_TO_UINT(x) ((unsigned int)(uintptr_t)(x))197#define FLUID_UINT_TO_POINTER(x) ((void *)(uintptr_t)(x))198#define FLUID_POINTER_TO_INT(x) ((signed int)(intptr_t)(x))199#define FLUID_INT_TO_POINTER(x) ((void *)(intptr_t)(x))200201/* Endian detection */202#define FLUID_IS_BIG_ENDIAN (G_BYTE_ORDER == G_BIG_ENDIAN)203204#define FLUID_LE32TOH(x) GINT32_FROM_LE(x)205#define FLUID_LE16TOH(x) GINT16_FROM_LE(x)206207#if FLUID_IS_BIG_ENDIAN208#define FLUID_FOURCC(_a, _b, _c, _d) \209(uint32_t)(((uint32_t)(_a) << 24) | ((uint32_t)(_b) << 16) | ((uint32_t)(_c) << 8) | (uint32_t)(_d))210#else211#define FLUID_FOURCC(_a, _b, _c, _d) \212(uint32_t)(((uint32_t)(_d) << 24) | ((uint32_t)(_c) << 16) | ((uint32_t)(_b) << 8) | (uint32_t)(_a))213#endif214215/*216* Utility functions217*/218char *fluid_strtok(char **str, char *delim);219220#define FLUID_FILE_TEST_EXISTS G_FILE_TEST_EXISTS221#define FLUID_FILE_TEST_IS_REGULAR G_FILE_TEST_IS_REGULAR222#define fluid_file_test(path, flags) g_file_test(path, flags)223224#define fluid_shell_parse_argv(command_line, argcp, argvp) g_shell_parse_argv(command_line, argcp, argvp, NULL)225#define fluid_strfreev g_strfreev226227#if defined(__OS2__)228#define INCL_DOS229#include <os2.h>230231/* Define socklen_t if not provided */232#if !HAVE_SOCKLEN_T233typedef int socklen_t;234#endif235#endif236237/**238Time functions239240*/241242unsigned int fluid_curtime(void);243double fluid_utime(void);244245246/**247Timers248249*/250251/* if the callback function returns 1 the timer will continue; if it252returns 0 it will stop */253typedef int (*fluid_timer_callback_t)(void *data, unsigned int msec);254255typedef struct _fluid_timer_t fluid_timer_t;256257fluid_timer_t *new_fluid_timer(int msec, fluid_timer_callback_t callback,258void *data, int new_thread, int auto_destroy,259int high_priority);260261void delete_fluid_timer(fluid_timer_t *timer);262int fluid_timer_join(fluid_timer_t *timer);263int fluid_timer_stop(fluid_timer_t *timer);264int fluid_timer_is_running(const fluid_timer_t *timer);265long fluid_timer_get_interval(const fluid_timer_t * timer);266267// Macros to use for pre-processor if statements to test which Glib thread API we have (pre or post 2.32)268#define NEW_GLIB_THREAD_API GLIB_CHECK_VERSION(2,32,0)269#define OLD_GLIB_THREAD_API !GLIB_CHECK_VERSION(2,32,0)270271/* Muteces */272273#if NEW_GLIB_THREAD_API274275/* glib 2.32 and newer */276277/* Regular mutex */278typedef GMutex fluid_mutex_t;279#define FLUID_MUTEX_INIT { 0 }280#define fluid_mutex_init(_m) g_mutex_init (&(_m))281#define fluid_mutex_destroy(_m) g_mutex_clear (&(_m))282#define fluid_mutex_lock(_m) g_mutex_lock(&(_m))283#define fluid_mutex_unlock(_m) g_mutex_unlock(&(_m))284285/* Recursive lock capable mutex */286typedef GRecMutex fluid_rec_mutex_t;287#define fluid_rec_mutex_init(_m) g_rec_mutex_init(&(_m))288#define fluid_rec_mutex_destroy(_m) g_rec_mutex_clear(&(_m))289#define fluid_rec_mutex_lock(_m) g_rec_mutex_lock(&(_m))290#define fluid_rec_mutex_unlock(_m) g_rec_mutex_unlock(&(_m))291292/* Dynamically allocated mutex suitable for fluid_cond_t use */293typedef GMutex fluid_cond_mutex_t;294#define fluid_cond_mutex_lock(m) g_mutex_lock(m)295#define fluid_cond_mutex_unlock(m) g_mutex_unlock(m)296297static FLUID_INLINE fluid_cond_mutex_t *298new_fluid_cond_mutex(void)299{300GMutex *mutex;301mutex = g_new(GMutex, 1);302g_mutex_init(mutex);303return (mutex);304}305306static FLUID_INLINE void307delete_fluid_cond_mutex(fluid_cond_mutex_t *m)308{309fluid_return_if_fail(m != NULL);310g_mutex_clear(m);311g_free(m);312}313314/* Thread condition signaling */315typedef GCond fluid_cond_t;316#define fluid_cond_signal(cond) g_cond_signal(cond)317#define fluid_cond_broadcast(cond) g_cond_broadcast(cond)318#define fluid_cond_wait(cond, mutex) g_cond_wait(cond, mutex)319320static FLUID_INLINE fluid_cond_t *321new_fluid_cond(void)322{323GCond *cond;324cond = g_new(GCond, 1);325g_cond_init(cond);326return (cond);327}328329static FLUID_INLINE void330delete_fluid_cond(fluid_cond_t *cond)331{332fluid_return_if_fail(cond != NULL);333g_cond_clear(cond);334g_free(cond);335}336337/* Thread private data */338339#ifdef _WIN32 /* Wine-specific code */340341typedef DWORD fluid_private_t;342#define fluid_private_init(_priv) (_priv = TlsAlloc())343#define fluid_private_free(_priv) TlsFree(_priv);344#define fluid_private_get(_priv) TlsGetValue(_priv)345#define fluid_private_set(_priv, _data) TlsSetValue(_priv, _data)346347#else /* Wine-specific code */348349typedef GPrivate fluid_private_t;350#define fluid_private_init(_priv) memset (&_priv, 0, sizeof (_priv))351#define fluid_private_free(_priv)352#define fluid_private_get(_priv) g_private_get(&(_priv))353#define fluid_private_set(_priv, _data) g_private_set(&(_priv), _data)354355#endif /* Wine-specific code */356357#else358359/* glib prior to 2.32 */360361/* Regular mutex */362typedef GStaticMutex fluid_mutex_t;363#define FLUID_MUTEX_INIT G_STATIC_MUTEX_INIT364#define fluid_mutex_destroy(_m) g_static_mutex_free(&(_m))365#define fluid_mutex_lock(_m) g_static_mutex_lock(&(_m))366#define fluid_mutex_unlock(_m) g_static_mutex_unlock(&(_m))367368#define fluid_mutex_init(_m) do { \369if (!g_thread_supported ()) g_thread_init (NULL); \370g_static_mutex_init (&(_m)); \371} while(0)372373/* Recursive lock capable mutex */374typedef GStaticRecMutex fluid_rec_mutex_t;375#define fluid_rec_mutex_destroy(_m) g_static_rec_mutex_free(&(_m))376#define fluid_rec_mutex_lock(_m) g_static_rec_mutex_lock(&(_m))377#define fluid_rec_mutex_unlock(_m) g_static_rec_mutex_unlock(&(_m))378379#define fluid_rec_mutex_init(_m) do { \380if (!g_thread_supported ()) g_thread_init (NULL); \381g_static_rec_mutex_init (&(_m)); \382} while(0)383384/* Dynamically allocated mutex suitable for fluid_cond_t use */385typedef GMutex fluid_cond_mutex_t;386#define delete_fluid_cond_mutex(m) g_mutex_free(m)387#define fluid_cond_mutex_lock(m) g_mutex_lock(m)388#define fluid_cond_mutex_unlock(m) g_mutex_unlock(m)389390static FLUID_INLINE fluid_cond_mutex_t *391new_fluid_cond_mutex(void)392{393if(!g_thread_supported())394{395g_thread_init(NULL);396}397398return g_mutex_new();399}400401/* Thread condition signaling */402typedef GCond fluid_cond_t;403fluid_cond_t *new_fluid_cond(void);404#define delete_fluid_cond(cond) g_cond_free(cond)405#define fluid_cond_signal(cond) g_cond_signal(cond)406#define fluid_cond_broadcast(cond) g_cond_broadcast(cond)407#define fluid_cond_wait(cond, mutex) g_cond_wait(cond, mutex)408409/* Thread private data */410typedef GStaticPrivate fluid_private_t;411#define fluid_private_get(_priv) g_static_private_get(&(_priv))412#define fluid_private_set(_priv, _data) g_static_private_set(&(_priv), _data, NULL)413#define fluid_private_free(_priv) g_static_private_free(&(_priv))414415#define fluid_private_init(_priv) do { \416if (!g_thread_supported ()) g_thread_init (NULL); \417g_static_private_init (&(_priv)); \418} while(0)419420#endif421422423/* Atomic operations */424425#define fluid_atomic_int_inc(_pi) g_atomic_int_inc(_pi)426#define fluid_atomic_int_get(_pi) g_atomic_int_get(_pi)427#define fluid_atomic_int_set(_pi, _val) g_atomic_int_set(_pi, _val)428#define fluid_atomic_int_dec_and_test(_pi) g_atomic_int_dec_and_test(_pi)429#define fluid_atomic_int_compare_and_exchange(_pi, _old, _new) \430g_atomic_int_compare_and_exchange(_pi, _old, _new)431432#if GLIB_MAJOR_VERSION > 2 || (GLIB_MAJOR_VERSION == 2 && GLIB_MINOR_VERSION >= 30)433#define fluid_atomic_int_exchange_and_add(_pi, _add) \434g_atomic_int_add(_pi, _add)435#define fluid_atomic_int_add(_pi, _add) \436g_atomic_int_add(_pi, _add)437#else438#define fluid_atomic_int_exchange_and_add(_pi, _add) \439g_atomic_int_exchange_and_add(_pi, _add)440#define fluid_atomic_int_add(_pi, _add) \441g_atomic_int_exchange_and_add(_pi, _add)442#endif443444#define fluid_atomic_pointer_get(_pp) g_atomic_pointer_get(_pp)445#define fluid_atomic_pointer_set(_pp, val) g_atomic_pointer_set(_pp, val)446#define fluid_atomic_pointer_compare_and_exchange(_pp, _old, _new) \447g_atomic_pointer_compare_and_exchange(_pp, _old, _new)448449static FLUID_INLINE void450fluid_atomic_float_set(fluid_atomic_float_t *fptr, float val)451{452int32_t ival;453memcpy(&ival, &val, 4);454fluid_atomic_int_set((fluid_atomic_int_t *)fptr, ival);455}456457static FLUID_INLINE float458fluid_atomic_float_get(fluid_atomic_float_t *fptr)459{460int32_t ival;461float fval;462ival = fluid_atomic_int_get((fluid_atomic_int_t *)fptr);463memcpy(&fval, &ival, 4);464return fval;465}466467468/* Threads */469470/* other thread implementations might change this for their needs */471typedef void *fluid_thread_return_t;472/* static return value for thread functions which requires a return value */473#define FLUID_THREAD_RETURN_VALUE (NULL)474475typedef GThread fluid_thread_t;476typedef fluid_thread_return_t (*fluid_thread_func_t)(void *data);477478#define FLUID_THREAD_ID_NULL NULL /* A NULL "ID" value */479#define fluid_thread_id_t GThread * /* Data type for a thread ID */480#define fluid_thread_get_id() g_thread_self() /* Get unique "ID" for current thread */481482fluid_thread_t *new_fluid_thread(const char *name, fluid_thread_func_t func, void *data,483int prio_level, int detach);484void delete_fluid_thread(fluid_thread_t *thread);485void fluid_thread_self_set_prio(int prio_level);486int fluid_thread_join(fluid_thread_t *thread);487488/* Dynamic Module Loading, currently only used by LADSPA subsystem */489#ifdef LADSPA490491typedef GModule fluid_module_t;492493#define fluid_module_open(_name) g_module_open((_name), G_MODULE_BIND_LOCAL)494#define fluid_module_close(_mod) g_module_close(_mod)495#define fluid_module_error() g_module_error()496#define fluid_module_name(_mod) g_module_name(_mod)497#define fluid_module_symbol(_mod, _name, _ptr) g_module_symbol((_mod), (_name), (_ptr))498499#endif /* LADSPA */500501/* Sockets and I/O */502503int fluid_istream_readline(fluid_istream_t in, fluid_ostream_t out, char *prompt, char *buf, int len);504int fluid_ostream_printf(fluid_ostream_t out, const char *format, ...);505506#if defined(_WIN32)507typedef SOCKET fluid_socket_t;508#else509typedef int fluid_socket_t;510#endif511512/* The function should return 0 if no error occurred, non-zero513otherwise. If the function return non-zero, the socket will be514closed by the server. */515typedef int (*fluid_server_func_t)(void *data, fluid_socket_t client_socket, char *addr);516517fluid_server_socket_t *new_fluid_server_socket(int port, fluid_server_func_t func, void *data);518void delete_fluid_server_socket(fluid_server_socket_t *sock);519int fluid_server_socket_join(fluid_server_socket_t *sock);520void fluid_socket_close(fluid_socket_t sock);521fluid_istream_t fluid_socket_get_istream(fluid_socket_t sock);522fluid_ostream_t fluid_socket_get_ostream(fluid_socket_t sock);523524/* File access */525#define fluid_stat(_filename, _statbuf) g_stat((_filename), (_statbuf))526#if !GLIB_CHECK_VERSION(2, 26, 0)527/* GStatBuf has not been introduced yet, manually typedef to what they had at that time:528* https://github.com/GNOME/glib/blob/e7763678b56e3be073cc55d707a6e92fc2055ee0/glib/gstdio.h#L98-L115529*/530#if defined(_WIN32) || HAVE_WINDOWS_H // somehow reliably mock G_OS_WIN32??531// Any effort from our side to reliably mock GStatBuf on Windows is in vain. E.g. glib-2.16 is broken as it uses struct stat rather than struct _stat32 on Win x86.532// Disable it (the user has been warned by cmake).533#undef fluid_stat534#define fluid_stat(_filename, _statbuf) (-1)535typedef struct _fluid_stat_buf_t{int st_mtime;} fluid_stat_buf_t;536#else537/* posix, OS/2, etc. */538typedef struct stat fluid_stat_buf_t;539#endif540#else541typedef GStatBuf fluid_stat_buf_t;542#endif543544FILE* fluid_file_open(const char* filename, const char** errMsg);545fluid_long_long_t fluid_file_tell(FILE* f);546547548/* Profiling */549#if WITH_PROFILING550/** profiling interface between Profiling command shell and Audio551rendering API (FluidProfile_0004.pdf- 3.2.2)552*/553554/*555-----------------------------------------------------------------------------556Shell task side | Profiling interface | Audio task side557-----------------------------------------------------------------------------558profiling | Internal | | | Audio559command <---> |<-- profiling -->| Data |<--macros -->| <--> rendering560shell | API | | | API561562*/563564/* default parameters for shell command "prof_start" in fluid_sys.c */565#define FLUID_PROFILE_DEFAULT_BANK 0 /* default bank */566#define FLUID_PROFILE_DEFAULT_PROG 16 /* default prog (organ) */567#define FLUID_PROFILE_FIRST_KEY 12 /* first key generated */568#define FLUID_PROFILE_LAST_KEY 108 /* last key generated */569#define FLUID_PROFILE_DEFAULT_VEL 64 /* default note velocity */570#define FLUID_PROFILE_VOICE_ATTEN -0.04f /* gain attenuation per voice (dB) */571572573#define FLUID_PROFILE_DEFAULT_PRINT 0 /* default print mode */574#define FLUID_PROFILE_DEFAULT_N_PROF 1 /* default number of measures */575#define FLUID_PROFILE_DEFAULT_DURATION 500 /* default duration (ms) */576577578extern unsigned short fluid_profile_notes; /* number of generated notes */579extern unsigned char fluid_profile_bank; /* bank,prog preset used by */580extern unsigned char fluid_profile_prog; /* generated notes */581extern unsigned char fluid_profile_print; /* print mode */582583extern unsigned short fluid_profile_n_prof;/* number of measures */584extern unsigned short fluid_profile_dur; /* measure duration in ms */585extern fluid_atomic_int_t fluid_profile_lock ; /* lock between multiple shell */586/**/587588/*----------------------------------------------589Internal profiling API (in fluid_sys.c)590-----------------------------------------------*/591/* Starts a profiling measure used in shell command "prof_start" */592void fluid_profile_start_stop(unsigned int end_ticks, short clear_data);593594/* Returns status used in shell command "prof_start" */595int fluid_profile_get_status(void);596597/* Prints profiling data used in shell command "prof_start" */598void fluid_profiling_print_data(double sample_rate, fluid_ostream_t out);599600/* Returns True if profiling cancellation has been requested */601int fluid_profile_is_cancel_req(void);602603/* For OS that implement <ENTER> key for profile cancellation:6041) Adds #define FLUID_PROFILE_CANCEL6052) Adds the necessary code inside fluid_profile_is_cancel() see fluid_sys.c606*/607#if defined(_WIN32) /* Profile cancellation is supported for Windows */608#define FLUID_PROFILE_CANCEL609610#elif defined(__OS2__) /* OS/2 specific stuff */611/* Profile cancellation isn't yet supported for OS2 */612613#else /* POSIX stuff */614#define FLUID_PROFILE_CANCEL /* Profile cancellation is supported for linux */615#include <unistd.h> /* STDIN_FILENO */616#include <sys/select.h> /* select() */617#endif /* posix */618619/* logging profiling data (used on synthesizer instance deletion) */620void fluid_profiling_print(void);621622/*----------------------------------------------623Profiling Data (in fluid_sys.c)624-----------------------------------------------*/625/** Profiling data. Keep track of min/avg/max values to profile a626piece of code. */627typedef struct _fluid_profile_data_t628{629const char *description; /* name of the piece of code under profiling */630double min, max, total; /* duration (microsecond) */631unsigned int count; /* total count */632unsigned int n_voices; /* voices number */633unsigned int n_samples; /* audio samples number */634} fluid_profile_data_t;635636enum637{638/* commands/status (profiling interface) */639PROFILE_STOP, /* command to stop a profiling measure */640PROFILE_START, /* command to start a profile measure */641PROFILE_READY, /* status to signal that a profiling measure has finished642and ready to be printed */643/*- State returned by fluid_profile_get_status() -*/644/* between profiling commands and internal profiling API */645PROFILE_RUNNING, /* a profiling measure is running */646PROFILE_CANCELED,/* a profiling measure has been canceled */647};648649/* Data interface */650extern unsigned char fluid_profile_status ; /* command and status */651extern unsigned int fluid_profile_end_ticks; /* ending position (in ticks) */652extern fluid_profile_data_t fluid_profile_data[]; /* Profiling data */653654/*----------------------------------------------655Probes macros656-----------------------------------------------*/657/** Macro to obtain a time reference used for the profiling */658#define fluid_profile_ref() fluid_utime()659660/** Macro to create a variable and assign the current reference time for profiling.661* So we don't get unused variable warnings when profiling is disabled. */662#define fluid_profile_ref_var(name) double name = fluid_utime()663664/**665* Profile identifier numbers. List all the pieces of code you want to profile666* here. Be sure to add an entry in the fluid_profile_data table in667* fluid_sys.c668*/669enum670{671FLUID_PROF_WRITE,672FLUID_PROF_ONE_BLOCK,673FLUID_PROF_ONE_BLOCK_CLEAR,674FLUID_PROF_ONE_BLOCK_VOICE,675FLUID_PROF_ONE_BLOCK_VOICES,676FLUID_PROF_ONE_BLOCK_REVERB,677FLUID_PROF_ONE_BLOCK_CHORUS,678FLUID_PROF_VOICE_NOTE,679FLUID_PROF_VOICE_RELEASE,680FLUID_PROFILE_NBR /* number of profile probes */681};682/** Those macros are used to calculate the min/avg/max. Needs a profile number, a683time reference, the voices and samples number. */684685/* local macro : acquiere data */686#define fluid_profile_data(_num, _ref, voices, samples)\687{\688double _now = fluid_utime();\689double _delta = _now - _ref;\690fluid_profile_data[_num].min = _delta < fluid_profile_data[_num].min ?\691_delta : fluid_profile_data[_num].min; \692fluid_profile_data[_num].max = _delta > fluid_profile_data[_num].max ?\693_delta : fluid_profile_data[_num].max;\694fluid_profile_data[_num].total += _delta;\695fluid_profile_data[_num].count++;\696fluid_profile_data[_num].n_voices += voices;\697fluid_profile_data[_num].n_samples += samples;\698_ref = _now;\699}700701/** Macro to collect data, called from inner functions inside audio702rendering API */703#define fluid_profile(_num, _ref, voices, samples)\704{\705if ( fluid_profile_status == PROFILE_START)\706{ /* acquires data */\707fluid_profile_data(_num, _ref, voices, samples)\708}\709}710711/** Macro to collect data, called from audio rendering API (fluid_write_xxxx()).712This macro control profiling ending position (in ticks).713*/714#define fluid_profile_write(_num, _ref, voices, samples)\715{\716if (fluid_profile_status == PROFILE_START)\717{\718/* acquires data first: must be done before checking that profile is719finished to ensure at least one valid data sample.720*/\721fluid_profile_data(_num, _ref, voices, samples)\722if (fluid_synth_get_ticks(synth) >= fluid_profile_end_ticks)\723{\724/* profiling is finished */\725fluid_profile_status = PROFILE_READY;\726}\727}\728}729730#else731732/* No profiling */733#define fluid_profiling_print()734#define fluid_profile_ref() 0735#define fluid_profile_ref_var(name)736#define fluid_profile(_num,_ref,voices, samples)737#define fluid_profile_write(_num,_ref, voices, samples)738#endif /* WITH_PROFILING */739740/**741742Memory locking743744Memory locking is used to avoid swapping of the large block of745sample data.746*/747748#if defined(HAVE_SYS_MMAN_H) && !defined(__OS2__)749#define fluid_mlock(_p,_n) mlock(_p, _n)750#define fluid_munlock(_p,_n) munlock(_p,_n)751#else752#define fluid_mlock(_p,_n) 0753#define fluid_munlock(_p,_n)754#endif755756757/**758759Floating point exceptions760761fluid_check_fpe() checks for "unnormalized numbers" and other762exceptions of the floating point processor.763*/764#ifdef FPE_CHECK765#define fluid_check_fpe(expl) fluid_check_fpe_i386(expl)766#define fluid_clear_fpe() fluid_clear_fpe_i386()767unsigned int fluid_check_fpe_i386(char *explanation_in_case_of_fpe);768void fluid_clear_fpe_i386(void);769#else770#define fluid_check_fpe(expl)771#define fluid_clear_fpe()772#endif773774775/* System control */776void fluid_msleep(unsigned int msecs);777778/**779* Advances the given \c ptr to the next \c alignment byte boundary.780* Make sure you've allocated an extra of \c alignment bytes to avoid a buffer overflow.781*782* @note \c alignment must be a power of two783* @return Returned pointer is guaranteed to be aligned to \c alignment boundary and in range \f[ ptr <= returned_ptr < ptr + alignment \f].784*/785static FLUID_INLINE void *fluid_align_ptr(const void *ptr, unsigned int alignment)786{787uintptr_t ptr_int = (uintptr_t)ptr;788unsigned int offset = ptr_int & (alignment - 1);789unsigned int add = (alignment - offset) & (alignment - 1); // advance the pointer to the next alignment boundary790ptr_int += add;791792/* assert alignment is power of two */793FLUID_ASSERT(!(alignment == 0) && !(alignment & (alignment - 1)));794795return (void *)ptr_int;796}797798#define FLUID_DEFAULT_ALIGNMENT (64U)799800#endif /* _FLUID_SYS_H */801802803