Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/libs/fluidsynth/src/utils/fluid_sys.h
4396 views
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
* @file fluid_sys.h
24
*
25
* This header contains a bunch of (mostly) system and machine
26
* dependent functions:
27
*
28
* - timers
29
* - current time in milliseconds and microseconds
30
* - debug logging
31
* - profiling
32
* - memory locking
33
* - checking for floating point exceptions
34
*
35
* fluidsynth's wrapper OSAL so to say; include it in .c files, be careful to include
36
* it in fluidsynth's private header files (see comment in fluid_coreaudio.c)
37
*/
38
39
#ifndef _FLUID_SYS_H
40
#define _FLUID_SYS_H
41
42
#include "fluidsynth_priv.h"
43
44
#if HAVE_MATH_H
45
#include <math.h>
46
#endif
47
48
#if HAVE_ERRNO_H
49
#include <errno.h>
50
#endif
51
52
#if HAVE_STDARG_H
53
#include <stdarg.h>
54
#endif
55
56
#if HAVE_UNISTD_H
57
#include <unistd.h>
58
#endif
59
60
#if HAVE_FCNTL_H
61
#include <fcntl.h>
62
#endif
63
64
#if HAVE_SYS_MMAN_H
65
#include <sys/mman.h>
66
#endif
67
68
#if HAVE_SYS_TYPES_H
69
#include <sys/types.h>
70
#endif
71
72
#if HAVE_SYS_STAT_H
73
#include <sys/stat.h>
74
#endif
75
76
#if HAVE_SYS_TIME_H
77
#include <sys/time.h>
78
#endif
79
80
#if HAVE_SYS_SOCKET_H
81
#include <sys/socket.h>
82
#endif
83
84
#if HAVE_NETINET_IN_H
85
#include <netinet/in.h>
86
#endif
87
88
#if HAVE_NETINET_TCP_H
89
#include <netinet/tcp.h>
90
#endif
91
92
#if HAVE_ARPA_INET_H
93
#include <arpa/inet.h>
94
#endif
95
96
#if HAVE_LIMITS_H
97
#include <limits.h>
98
#endif
99
100
#if HAVE_OPENMP
101
#include <omp.h>
102
#endif
103
104
#if HAVE_IO_H
105
#include <io.h> // _open(), _close(), read(), write() on windows
106
#endif
107
108
#if HAVE_SIGNAL_H
109
#include <signal.h>
110
#endif
111
112
/** Integer types */
113
#if HAVE_STDINT_H
114
#include <stdint.h>
115
116
#else
117
118
/* Assume GLIB types */
119
typedef gint8 int8_t;
120
typedef guint8 uint8_t;
121
typedef gint16 int16_t;
122
typedef guint16 uint16_t;
123
typedef gint32 int32_t;
124
typedef guint32 uint32_t;
125
typedef gint64 int64_t;
126
typedef guint64 uint64_t;
127
typedef guintptr uintptr_t;
128
typedef gintptr intptr_t;
129
130
#endif
131
132
/*
133
* CYGWIN has its own version of <windows.h>, which can be
134
* safely included together with POSIX includes.
135
* Thanks to this, CYGWIN can also run audio output and MIDI
136
* input drivers from traditional interfaces of Windows.
137
*/
138
#if defined(__CYGWIN__) && HAVE_WINDOWS_H
139
#include <windows.h>
140
#include <wchar.h>
141
#endif
142
143
#if defined(_WIN32) && HAVE_WINDOWS_H
144
#include <winsock2.h>
145
#include <ws2tcpip.h> /* Provides also socklen_t */
146
147
/* WIN32 special defines */
148
#define STDIN_FILENO 0
149
#define STDOUT_FILENO 1
150
#define STDERR_FILENO 2
151
152
#ifdef _MSC_VER
153
#pragma warning(disable : 4244)
154
#pragma warning(disable : 4101)
155
#pragma warning(disable : 4305)
156
#pragma warning(disable : 4996)
157
#endif
158
159
#endif
160
161
/* Darwin special defines (taken from config_macosx.h) */
162
#ifdef DARWIN
163
# define MACINTOSH
164
# define __Types__
165
#endif
166
167
#ifdef LADSPA
168
#include <gmodule.h>
169
#endif
170
171
/* #include <glib/gstdio.h> */
172
173
/**
174
* Macro used for safely accessing a message from a GError and using a default
175
* message if it is NULL.
176
* @param err Pointer to a GError to access the message field of.
177
* @return Message string
178
*/
179
#define fluid_gerror_message(err) ((err) ? err->message : "No error details")
180
181
#if defined(_WIN32) || defined(__CYGWIN__)
182
char* fluid_get_windows_error(void);
183
#endif
184
185
#define FLUID_INLINE inline
186
187
#define FLUID_VERSION_CHECK(major, minor, patch) ((major<<16)|(minor<<8)|(patch))
188
189
/* Integer<->pointer conversion */
190
#define FLUID_POINTER_TO_UINT(x) ((unsigned int)(uintptr_t)(x))
191
#define FLUID_UINT_TO_POINTER(x) ((void *)(uintptr_t)(x))
192
#define FLUID_POINTER_TO_INT(x) ((signed int)(intptr_t)(x))
193
#define FLUID_INT_TO_POINTER(x) ((void *)(intptr_t)(x))
194
195
/* Endian detection */
196
#define FLUID_IS_BIG_ENDIAN (G_BYTE_ORDER == G_BIG_ENDIAN)
197
198
#define FLUID_LE32TOH(x) GINT32_FROM_LE(x)
199
#define FLUID_LE16TOH(x) GINT16_FROM_LE(x)
200
201
#if FLUID_IS_BIG_ENDIAN
202
#define FLUID_FOURCC(_a, _b, _c, _d) \
203
(uint32_t)(((uint32_t)(_a) << 24) | ((uint32_t)(_b) << 16) | ((uint32_t)(_c) << 8) | (uint32_t)(_d))
204
#else
205
#define FLUID_FOURCC(_a, _b, _c, _d) \
206
(uint32_t)(((uint32_t)(_d) << 24) | ((uint32_t)(_c) << 16) | ((uint32_t)(_b) << 8) | (uint32_t)(_a))
207
#endif
208
209
/*
210
* Utility functions
211
*/
212
char *fluid_strtok(char **str, char *delim);
213
214
#define FLUID_FILE_TEST_EXISTS G_FILE_TEST_EXISTS
215
#define FLUID_FILE_TEST_IS_REGULAR G_FILE_TEST_IS_REGULAR
216
#define fluid_file_test(path, flags) g_file_test(path, flags)
217
218
#define fluid_shell_parse_argv(command_line, argcp, argvp) g_shell_parse_argv(command_line, argcp, argvp, NULL)
219
#define fluid_strfreev g_strfreev
220
221
#if defined(__OS2__)
222
#define INCL_DOS
223
#include <os2.h>
224
225
/* Define socklen_t if not provided */
226
#if !HAVE_SOCKLEN_T
227
typedef int socklen_t;
228
#endif
229
#endif
230
231
/**
232
Time functions
233
234
*/
235
236
unsigned int fluid_curtime(void);
237
double fluid_utime(void);
238
239
240
/**
241
Timers
242
243
*/
244
245
/* if the callback function returns 1 the timer will continue; if it
246
returns 0 it will stop */
247
typedef int (*fluid_timer_callback_t)(void *data, unsigned int msec);
248
249
typedef struct _fluid_timer_t fluid_timer_t;
250
251
fluid_timer_t *new_fluid_timer(int msec, fluid_timer_callback_t callback,
252
void *data, int new_thread, int auto_destroy,
253
int high_priority);
254
255
void delete_fluid_timer(fluid_timer_t *timer);
256
int fluid_timer_join(fluid_timer_t *timer);
257
int fluid_timer_stop(fluid_timer_t *timer);
258
int fluid_timer_is_running(const fluid_timer_t *timer);
259
long fluid_timer_get_interval(const fluid_timer_t * timer);
260
261
// Macros to use for pre-processor if statements to test which Glib thread API we have (pre or post 2.32)
262
#define NEW_GLIB_THREAD_API GLIB_CHECK_VERSION(2,32,0)
263
#define OLD_GLIB_THREAD_API !GLIB_CHECK_VERSION(2,32,0)
264
265
/* Muteces */
266
267
#if NEW_GLIB_THREAD_API
268
269
/* glib 2.32 and newer */
270
271
/* Regular mutex */
272
typedef GMutex fluid_mutex_t;
273
#define FLUID_MUTEX_INIT { 0 }
274
#define fluid_mutex_init(_m) g_mutex_init (&(_m))
275
#define fluid_mutex_destroy(_m) g_mutex_clear (&(_m))
276
#define fluid_mutex_lock(_m) g_mutex_lock(&(_m))
277
#define fluid_mutex_unlock(_m) g_mutex_unlock(&(_m))
278
279
/* Recursive lock capable mutex */
280
typedef GRecMutex fluid_rec_mutex_t;
281
#define fluid_rec_mutex_init(_m) g_rec_mutex_init(&(_m))
282
#define fluid_rec_mutex_destroy(_m) g_rec_mutex_clear(&(_m))
283
#define fluid_rec_mutex_lock(_m) g_rec_mutex_lock(&(_m))
284
#define fluid_rec_mutex_unlock(_m) g_rec_mutex_unlock(&(_m))
285
286
/* Dynamically allocated mutex suitable for fluid_cond_t use */
287
typedef GMutex fluid_cond_mutex_t;
288
#define fluid_cond_mutex_lock(m) g_mutex_lock(m)
289
#define fluid_cond_mutex_unlock(m) g_mutex_unlock(m)
290
291
static FLUID_INLINE fluid_cond_mutex_t *
292
new_fluid_cond_mutex(void)
293
{
294
GMutex *mutex;
295
mutex = g_new(GMutex, 1);
296
g_mutex_init(mutex);
297
return (mutex);
298
}
299
300
static FLUID_INLINE void
301
delete_fluid_cond_mutex(fluid_cond_mutex_t *m)
302
{
303
fluid_return_if_fail(m != NULL);
304
g_mutex_clear(m);
305
g_free(m);
306
}
307
308
/* Thread condition signaling */
309
typedef GCond fluid_cond_t;
310
#define fluid_cond_signal(cond) g_cond_signal(cond)
311
#define fluid_cond_broadcast(cond) g_cond_broadcast(cond)
312
#define fluid_cond_wait(cond, mutex) g_cond_wait(cond, mutex)
313
314
static FLUID_INLINE fluid_cond_t *
315
new_fluid_cond(void)
316
{
317
GCond *cond;
318
cond = g_new(GCond, 1);
319
g_cond_init(cond);
320
return (cond);
321
}
322
323
static FLUID_INLINE void
324
delete_fluid_cond(fluid_cond_t *cond)
325
{
326
fluid_return_if_fail(cond != NULL);
327
g_cond_clear(cond);
328
g_free(cond);
329
}
330
331
/* Thread private data */
332
333
#ifdef _WIN32 /* Wine-specific code */
334
335
typedef DWORD fluid_private_t;
336
#define fluid_private_init(_priv) (_priv = TlsAlloc())
337
#define fluid_private_free(_priv) TlsFree(_priv);
338
#define fluid_private_get(_priv) TlsGetValue(_priv)
339
#define fluid_private_set(_priv, _data) TlsSetValue(_priv, _data)
340
341
#else /* Wine-specific code */
342
343
typedef GPrivate fluid_private_t;
344
#define fluid_private_init(_priv) memset (&_priv, 0, sizeof (_priv))
345
#define fluid_private_free(_priv)
346
#define fluid_private_get(_priv) g_private_get(&(_priv))
347
#define fluid_private_set(_priv, _data) g_private_set(&(_priv), _data)
348
349
#endif /* Wine-specific code */
350
351
#else
352
353
/* glib prior to 2.32 */
354
355
/* Regular mutex */
356
typedef GStaticMutex fluid_mutex_t;
357
#define FLUID_MUTEX_INIT G_STATIC_MUTEX_INIT
358
#define fluid_mutex_destroy(_m) g_static_mutex_free(&(_m))
359
#define fluid_mutex_lock(_m) g_static_mutex_lock(&(_m))
360
#define fluid_mutex_unlock(_m) g_static_mutex_unlock(&(_m))
361
362
#define fluid_mutex_init(_m) do { \
363
if (!g_thread_supported ()) g_thread_init (NULL); \
364
g_static_mutex_init (&(_m)); \
365
} while(0)
366
367
/* Recursive lock capable mutex */
368
typedef GStaticRecMutex fluid_rec_mutex_t;
369
#define fluid_rec_mutex_destroy(_m) g_static_rec_mutex_free(&(_m))
370
#define fluid_rec_mutex_lock(_m) g_static_rec_mutex_lock(&(_m))
371
#define fluid_rec_mutex_unlock(_m) g_static_rec_mutex_unlock(&(_m))
372
373
#define fluid_rec_mutex_init(_m) do { \
374
if (!g_thread_supported ()) g_thread_init (NULL); \
375
g_static_rec_mutex_init (&(_m)); \
376
} while(0)
377
378
/* Dynamically allocated mutex suitable for fluid_cond_t use */
379
typedef GMutex fluid_cond_mutex_t;
380
#define delete_fluid_cond_mutex(m) g_mutex_free(m)
381
#define fluid_cond_mutex_lock(m) g_mutex_lock(m)
382
#define fluid_cond_mutex_unlock(m) g_mutex_unlock(m)
383
384
static FLUID_INLINE fluid_cond_mutex_t *
385
new_fluid_cond_mutex(void)
386
{
387
if(!g_thread_supported())
388
{
389
g_thread_init(NULL);
390
}
391
392
return g_mutex_new();
393
}
394
395
/* Thread condition signaling */
396
typedef GCond fluid_cond_t;
397
fluid_cond_t *new_fluid_cond(void);
398
#define delete_fluid_cond(cond) g_cond_free(cond)
399
#define fluid_cond_signal(cond) g_cond_signal(cond)
400
#define fluid_cond_broadcast(cond) g_cond_broadcast(cond)
401
#define fluid_cond_wait(cond, mutex) g_cond_wait(cond, mutex)
402
403
/* Thread private data */
404
typedef GStaticPrivate fluid_private_t;
405
#define fluid_private_get(_priv) g_static_private_get(&(_priv))
406
#define fluid_private_set(_priv, _data) g_static_private_set(&(_priv), _data, NULL)
407
#define fluid_private_free(_priv) g_static_private_free(&(_priv))
408
409
#define fluid_private_init(_priv) do { \
410
if (!g_thread_supported ()) g_thread_init (NULL); \
411
g_static_private_init (&(_priv)); \
412
} while(0)
413
414
#endif
415
416
417
/* Atomic operations */
418
419
#define fluid_atomic_int_inc(_pi) g_atomic_int_inc(_pi)
420
#define fluid_atomic_int_get(_pi) g_atomic_int_get(_pi)
421
#define fluid_atomic_int_set(_pi, _val) g_atomic_int_set(_pi, _val)
422
#define fluid_atomic_int_dec_and_test(_pi) g_atomic_int_dec_and_test(_pi)
423
#define fluid_atomic_int_compare_and_exchange(_pi, _old, _new) \
424
g_atomic_int_compare_and_exchange(_pi, _old, _new)
425
426
#if GLIB_MAJOR_VERSION > 2 || (GLIB_MAJOR_VERSION == 2 && GLIB_MINOR_VERSION >= 30)
427
#define fluid_atomic_int_exchange_and_add(_pi, _add) \
428
g_atomic_int_add(_pi, _add)
429
#define fluid_atomic_int_add(_pi, _add) \
430
g_atomic_int_add(_pi, _add)
431
#else
432
#define fluid_atomic_int_exchange_and_add(_pi, _add) \
433
g_atomic_int_exchange_and_add(_pi, _add)
434
#define fluid_atomic_int_add(_pi, _add) \
435
g_atomic_int_exchange_and_add(_pi, _add)
436
#endif
437
438
#define fluid_atomic_pointer_get(_pp) g_atomic_pointer_get(_pp)
439
#define fluid_atomic_pointer_set(_pp, val) g_atomic_pointer_set(_pp, val)
440
#define fluid_atomic_pointer_compare_and_exchange(_pp, _old, _new) \
441
g_atomic_pointer_compare_and_exchange(_pp, _old, _new)
442
443
static FLUID_INLINE void
444
fluid_atomic_float_set(fluid_atomic_float_t *fptr, float val)
445
{
446
int32_t ival;
447
memcpy(&ival, &val, 4);
448
fluid_atomic_int_set((fluid_atomic_int_t *)fptr, ival);
449
}
450
451
static FLUID_INLINE float
452
fluid_atomic_float_get(fluid_atomic_float_t *fptr)
453
{
454
int32_t ival;
455
float fval;
456
ival = fluid_atomic_int_get((fluid_atomic_int_t *)fptr);
457
memcpy(&fval, &ival, 4);
458
return fval;
459
}
460
461
462
/* Threads */
463
464
/* other thread implementations might change this for their needs */
465
typedef void *fluid_thread_return_t;
466
/* static return value for thread functions which requires a return value */
467
#define FLUID_THREAD_RETURN_VALUE (NULL)
468
469
typedef GThread fluid_thread_t;
470
typedef fluid_thread_return_t (*fluid_thread_func_t)(void *data);
471
472
#define FLUID_THREAD_ID_NULL NULL /* A NULL "ID" value */
473
#define fluid_thread_id_t GThread * /* Data type for a thread ID */
474
#define fluid_thread_get_id() g_thread_self() /* Get unique "ID" for current thread */
475
476
fluid_thread_t *new_fluid_thread(const char *name, fluid_thread_func_t func, void *data,
477
int prio_level, int detach);
478
void delete_fluid_thread(fluid_thread_t *thread);
479
void fluid_thread_self_set_prio(int prio_level);
480
int fluid_thread_join(fluid_thread_t *thread);
481
482
/* Dynamic Module Loading, currently only used by LADSPA subsystem */
483
#ifdef LADSPA
484
485
typedef GModule fluid_module_t;
486
487
#define fluid_module_open(_name) g_module_open((_name), G_MODULE_BIND_LOCAL)
488
#define fluid_module_close(_mod) g_module_close(_mod)
489
#define fluid_module_error() g_module_error()
490
#define fluid_module_name(_mod) g_module_name(_mod)
491
#define fluid_module_symbol(_mod, _name, _ptr) g_module_symbol((_mod), (_name), (_ptr))
492
493
#endif /* LADSPA */
494
495
/* Sockets and I/O */
496
497
int fluid_istream_readline(fluid_istream_t in, fluid_ostream_t out, char *prompt, char *buf, int len);
498
int fluid_ostream_printf(fluid_ostream_t out, const char *format, ...);
499
500
#if defined(_WIN32)
501
typedef SOCKET fluid_socket_t;
502
#else
503
typedef int fluid_socket_t;
504
#endif
505
506
/* The function should return 0 if no error occurred, non-zero
507
otherwise. If the function return non-zero, the socket will be
508
closed by the server. */
509
typedef int (*fluid_server_func_t)(void *data, fluid_socket_t client_socket, char *addr);
510
511
fluid_server_socket_t *new_fluid_server_socket(int port, fluid_server_func_t func, void *data);
512
void delete_fluid_server_socket(fluid_server_socket_t *sock);
513
int fluid_server_socket_join(fluid_server_socket_t *sock);
514
void fluid_socket_close(fluid_socket_t sock);
515
fluid_istream_t fluid_socket_get_istream(fluid_socket_t sock);
516
fluid_ostream_t fluid_socket_get_ostream(fluid_socket_t sock);
517
518
/* File access */
519
#define fluid_stat(_filename, _statbuf) g_stat((_filename), (_statbuf))
520
#if !GLIB_CHECK_VERSION(2, 26, 0)
521
/* GStatBuf has not been introduced yet, manually typedef to what they had at that time:
522
* https://github.com/GNOME/glib/blob/e7763678b56e3be073cc55d707a6e92fc2055ee0/glib/gstdio.h#L98-L115
523
*/
524
#if defined(_WIN32) || HAVE_WINDOWS_H // somehow reliably mock G_OS_WIN32??
525
// 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.
526
// Disable it (the user has been warned by cmake).
527
#undef fluid_stat
528
#define fluid_stat(_filename, _statbuf) (-1)
529
typedef struct _fluid_stat_buf_t{int st_mtime;} fluid_stat_buf_t;
530
#else
531
/* posix, OS/2, etc. */
532
typedef struct stat fluid_stat_buf_t;
533
#endif
534
#else
535
typedef GStatBuf fluid_stat_buf_t;
536
#endif
537
538
FILE* fluid_file_open(const char* filename, const char** errMsg);
539
fluid_long_long_t fluid_file_tell(FILE* f);
540
541
542
/* Profiling */
543
#if WITH_PROFILING
544
/** profiling interface between Profiling command shell and Audio
545
rendering API (FluidProfile_0004.pdf- 3.2.2)
546
*/
547
548
/*
549
-----------------------------------------------------------------------------
550
Shell task side | Profiling interface | Audio task side
551
-----------------------------------------------------------------------------
552
profiling | Internal | | | Audio
553
command <---> |<-- profiling -->| Data |<--macros -->| <--> rendering
554
shell | API | | | API
555
556
*/
557
558
/* default parameters for shell command "prof_start" in fluid_sys.c */
559
#define FLUID_PROFILE_DEFAULT_BANK 0 /* default bank */
560
#define FLUID_PROFILE_DEFAULT_PROG 16 /* default prog (organ) */
561
#define FLUID_PROFILE_FIRST_KEY 12 /* first key generated */
562
#define FLUID_PROFILE_LAST_KEY 108 /* last key generated */
563
#define FLUID_PROFILE_DEFAULT_VEL 64 /* default note velocity */
564
#define FLUID_PROFILE_VOICE_ATTEN -0.04f /* gain attenuation per voice (dB) */
565
566
567
#define FLUID_PROFILE_DEFAULT_PRINT 0 /* default print mode */
568
#define FLUID_PROFILE_DEFAULT_N_PROF 1 /* default number of measures */
569
#define FLUID_PROFILE_DEFAULT_DURATION 500 /* default duration (ms) */
570
571
572
extern unsigned short fluid_profile_notes; /* number of generated notes */
573
extern unsigned char fluid_profile_bank; /* bank,prog preset used by */
574
extern unsigned char fluid_profile_prog; /* generated notes */
575
extern unsigned char fluid_profile_print; /* print mode */
576
577
extern unsigned short fluid_profile_n_prof;/* number of measures */
578
extern unsigned short fluid_profile_dur; /* measure duration in ms */
579
extern fluid_atomic_int_t fluid_profile_lock ; /* lock between multiple shell */
580
/**/
581
582
/*----------------------------------------------
583
Internal profiling API (in fluid_sys.c)
584
-----------------------------------------------*/
585
/* Starts a profiling measure used in shell command "prof_start" */
586
void fluid_profile_start_stop(unsigned int end_ticks, short clear_data);
587
588
/* Returns status used in shell command "prof_start" */
589
int fluid_profile_get_status(void);
590
591
/* Prints profiling data used in shell command "prof_start" */
592
void fluid_profiling_print_data(double sample_rate, fluid_ostream_t out);
593
594
/* Returns True if profiling cancellation has been requested */
595
int fluid_profile_is_cancel_req(void);
596
597
/* For OS that implement <ENTER> key for profile cancellation:
598
1) Adds #define FLUID_PROFILE_CANCEL
599
2) Adds the necessary code inside fluid_profile_is_cancel() see fluid_sys.c
600
*/
601
#if defined(_WIN32) /* Profile cancellation is supported for Windows */
602
#define FLUID_PROFILE_CANCEL
603
604
#elif defined(__OS2__) /* OS/2 specific stuff */
605
/* Profile cancellation isn't yet supported for OS2 */
606
607
#else /* POSIX stuff */
608
#define FLUID_PROFILE_CANCEL /* Profile cancellation is supported for linux */
609
#include <unistd.h> /* STDIN_FILENO */
610
#include <sys/select.h> /* select() */
611
#endif /* posix */
612
613
/* logging profiling data (used on synthesizer instance deletion) */
614
void fluid_profiling_print(void);
615
616
/*----------------------------------------------
617
Profiling Data (in fluid_sys.c)
618
-----------------------------------------------*/
619
/** Profiling data. Keep track of min/avg/max values to profile a
620
piece of code. */
621
typedef struct _fluid_profile_data_t
622
{
623
const char *description; /* name of the piece of code under profiling */
624
double min, max, total; /* duration (microsecond) */
625
unsigned int count; /* total count */
626
unsigned int n_voices; /* voices number */
627
unsigned int n_samples; /* audio samples number */
628
} fluid_profile_data_t;
629
630
enum
631
{
632
/* commands/status (profiling interface) */
633
PROFILE_STOP, /* command to stop a profiling measure */
634
PROFILE_START, /* command to start a profile measure */
635
PROFILE_READY, /* status to signal that a profiling measure has finished
636
and ready to be printed */
637
/*- State returned by fluid_profile_get_status() -*/
638
/* between profiling commands and internal profiling API */
639
PROFILE_RUNNING, /* a profiling measure is running */
640
PROFILE_CANCELED,/* a profiling measure has been canceled */
641
};
642
643
/* Data interface */
644
extern unsigned char fluid_profile_status ; /* command and status */
645
extern unsigned int fluid_profile_end_ticks; /* ending position (in ticks) */
646
extern fluid_profile_data_t fluid_profile_data[]; /* Profiling data */
647
648
/*----------------------------------------------
649
Probes macros
650
-----------------------------------------------*/
651
/** Macro to obtain a time reference used for the profiling */
652
#define fluid_profile_ref() fluid_utime()
653
654
/** Macro to create a variable and assign the current reference time for profiling.
655
* So we don't get unused variable warnings when profiling is disabled. */
656
#define fluid_profile_ref_var(name) double name = fluid_utime()
657
658
/**
659
* Profile identifier numbers. List all the pieces of code you want to profile
660
* here. Be sure to add an entry in the fluid_profile_data table in
661
* fluid_sys.c
662
*/
663
enum
664
{
665
FLUID_PROF_WRITE,
666
FLUID_PROF_ONE_BLOCK,
667
FLUID_PROF_ONE_BLOCK_CLEAR,
668
FLUID_PROF_ONE_BLOCK_VOICE,
669
FLUID_PROF_ONE_BLOCK_VOICES,
670
FLUID_PROF_ONE_BLOCK_REVERB,
671
FLUID_PROF_ONE_BLOCK_CHORUS,
672
FLUID_PROF_VOICE_NOTE,
673
FLUID_PROF_VOICE_RELEASE,
674
FLUID_PROFILE_NBR /* number of profile probes */
675
};
676
/** Those macros are used to calculate the min/avg/max. Needs a profile number, a
677
time reference, the voices and samples number. */
678
679
/* local macro : acquiere data */
680
#define fluid_profile_data(_num, _ref, voices, samples)\
681
{\
682
double _now = fluid_utime();\
683
double _delta = _now - _ref;\
684
fluid_profile_data[_num].min = _delta < fluid_profile_data[_num].min ?\
685
_delta : fluid_profile_data[_num].min; \
686
fluid_profile_data[_num].max = _delta > fluid_profile_data[_num].max ?\
687
_delta : fluid_profile_data[_num].max;\
688
fluid_profile_data[_num].total += _delta;\
689
fluid_profile_data[_num].count++;\
690
fluid_profile_data[_num].n_voices += voices;\
691
fluid_profile_data[_num].n_samples += samples;\
692
_ref = _now;\
693
}
694
695
/** Macro to collect data, called from inner functions inside audio
696
rendering API */
697
#define fluid_profile(_num, _ref, voices, samples)\
698
{\
699
if ( fluid_profile_status == PROFILE_START)\
700
{ /* acquires data */\
701
fluid_profile_data(_num, _ref, voices, samples)\
702
}\
703
}
704
705
/** Macro to collect data, called from audio rendering API (fluid_write_xxxx()).
706
This macro control profiling ending position (in ticks).
707
*/
708
#define fluid_profile_write(_num, _ref, voices, samples)\
709
{\
710
if (fluid_profile_status == PROFILE_START)\
711
{\
712
/* acquires data first: must be done before checking that profile is
713
finished to ensure at least one valid data sample.
714
*/\
715
fluid_profile_data(_num, _ref, voices, samples)\
716
if (fluid_synth_get_ticks(synth) >= fluid_profile_end_ticks)\
717
{\
718
/* profiling is finished */\
719
fluid_profile_status = PROFILE_READY;\
720
}\
721
}\
722
}
723
724
#else
725
726
/* No profiling */
727
#define fluid_profiling_print()
728
#define fluid_profile_ref() 0
729
#define fluid_profile_ref_var(name)
730
#define fluid_profile(_num,_ref,voices, samples)
731
#define fluid_profile_write(_num,_ref, voices, samples)
732
#endif /* WITH_PROFILING */
733
734
/**
735
736
Memory locking
737
738
Memory locking is used to avoid swapping of the large block of
739
sample data.
740
*/
741
742
#if defined(HAVE_SYS_MMAN_H) && !defined(__OS2__)
743
#define fluid_mlock(_p,_n) mlock(_p, _n)
744
#define fluid_munlock(_p,_n) munlock(_p,_n)
745
#else
746
#define fluid_mlock(_p,_n) 0
747
#define fluid_munlock(_p,_n)
748
#endif
749
750
751
/**
752
753
Floating point exceptions
754
755
fluid_check_fpe() checks for "unnormalized numbers" and other
756
exceptions of the floating point processor.
757
*/
758
#ifdef FPE_CHECK
759
#define fluid_check_fpe(expl) fluid_check_fpe_i386(expl)
760
#define fluid_clear_fpe() fluid_clear_fpe_i386()
761
unsigned int fluid_check_fpe_i386(char *explanation_in_case_of_fpe);
762
void fluid_clear_fpe_i386(void);
763
#else
764
#define fluid_check_fpe(expl)
765
#define fluid_clear_fpe()
766
#endif
767
768
769
/* System control */
770
void fluid_msleep(unsigned int msecs);
771
772
/**
773
* Advances the given \c ptr to the next \c alignment byte boundary.
774
* Make sure you've allocated an extra of \c alignment bytes to avoid a buffer overflow.
775
*
776
* @note \c alignment must be a power of two
777
* @return Returned pointer is guaranteed to be aligned to \c alignment boundary and in range \f[ ptr <= returned_ptr < ptr + alignment \f].
778
*/
779
static FLUID_INLINE void *fluid_align_ptr(const void *ptr, unsigned int alignment)
780
{
781
uintptr_t ptr_int = (uintptr_t)ptr;
782
unsigned int offset = ptr_int & (alignment - 1);
783
unsigned int add = (alignment - offset) & (alignment - 1); // advance the pointer to the next alignment boundary
784
ptr_int += add;
785
786
/* assert alignment is power of two */
787
FLUID_ASSERT(!(alignment == 0) && !(alignment & (alignment - 1)));
788
789
return (void *)ptr_int;
790
}
791
792
#define FLUID_DEFAULT_ALIGNMENT (64U)
793
794
#endif /* _FLUID_SYS_H */
795
796