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