github.com/256dpi/max-go@v0.7.0/lib/msp/z_dsp.h (about) 1 // z_dsp.h -- the main header file for all DSP objects copyright 1997-2003 Cycling '74 2 3 // DSP services: 4 5 #ifndef _Z_DSP_H 6 #define _Z_DSP_H 7 8 #include "z_sampletype.h" 9 #include "ext_systhread.h" 10 #include "ext_linklist.h" 11 #include "ext_atomic.h" 12 #include "ext_maxtypes.h" 13 14 #if C74_PRAGMA_STRUCT_PACKPUSH 15 #pragma pack(push, 2) 16 #elif C74_PRAGMA_STRUCT_PACK 17 #pragma pack(2) 18 #endif 19 20 /** MSP System Properties. 21 @ingroup msp */ 22 enum { 23 SYS_MAXBLKSIZE = 2048 ///< a good number for a maximum signal vector size 24 }; 25 26 // maximum channels in a multi-channel signal 27 28 #define MC_MAX_CHANS 1024 29 30 // suggested maximum number of inlets or outlets in a multi-channel object 31 // this is not a hard limit, just a way to keep people from making objects 32 // with huge numbers of inlets and outlets by mistake 33 34 #define MC_MAX_IO 64 35 36 // header for all DSP objects. Provides a proxy. 37 38 // z_misc flags: 39 40 #define Z_NO_INPLACE 1 ///< flag indicating the object doesn't want signals in place @ingroup msp 41 #define Z_PUT_LAST 2 ///< when list of ugens is resorted, put this object at end @ingroup msp 42 #define Z_PUT_FIRST 4 ///< when list of ugens is resorted, put this object at beginning @ingroup msp 43 #define Z_IGNORE_DISABLE 8 ///< ignore the disable field when executing the chain, e.g. to process the pass~ object in a muted patcher. 44 #define Z_DONT_ADD 16 ///< if this flag is set the object will be ignored and its dsp method won't be called. 45 #define Z_MC_INLETS 32 ///< object knows how to count channels of incoming multi-channel signals 46 47 #define SIXTEENIZE(p) ((((t_ptr_uint)(p)) + 16) & (~(t_ptr_uint)0xF)) 48 #define THIRTYTWOIZE(p) ((((t_ptr_uint)(p)) + 32) & (~(t_ptr_uint)0x1F)) 49 50 typedef void *t_proxy; 51 52 /** Common struct for MSP objects. 53 @ingroup msp */ 54 typedef struct _pxdata { 55 long z_in; 56 void *z_proxy; 57 long z_disabled; ///< set to non-zero if this object is muted (using the pcontrol or mute~ objects) 58 short z_count; ///< the number of signal inlets 59 short z_misc; ///< flags (bitmask) determining object behaviour, such as #Z_NO_INPLACE, #Z_PUT_FIRST, or #Z_PUT_LAST 60 } t_pxdata; 61 62 /** Header for any non-ui signal processing object. 63 For ui objects use #t_pxjbox. 64 @ingroup msp */ 65 typedef struct t_pxobject { 66 struct object z_ob; ///< The standard #t_object struct. 67 long z_in; 68 void *z_proxy; 69 long z_disabled; ///< set to non-zero if this object is muted (using the pcontrol or mute~ objects) 70 short z_count; ///< the number of signal inlets 71 short z_misc; ///< flags (bitmask) determining object behaviour, such as #Z_NO_INPLACE, #Z_PUT_FIRST, or #Z_PUT_LAST 72 } t_pxobject; 73 74 75 #define MAXLOGSIG 13 76 #define MAXSIGSIZE (1 << MAXLOGSIG) 77 /** The signal data structure. 78 @ingroup msp */ 79 typedef struct _signal 80 { 81 long s_n; ///< The vector size of the signal. 82 t_sample *s_vec; ///< A buffer holding the vector of audio samples. 83 float s_sr; ///< The sample rate of the signal. 84 struct _signal *s_next; 85 struct _signal *s_nextused; 86 short s_refcount; 87 short s_size; // element size (* s_n == memory) 88 char *s_ptr; // what to free 89 } t_signal; 90 91 92 // c74 private 93 94 struct _chain64item; 95 struct _chain64item_extra; 96 97 typedef struct _dspchain 98 { 99 t_object c_ob; 100 t_int *c_chain; 101 long c_chainsize; 102 long c_callcount; 103 long c_usedcount; 104 long c_reusedcount; 105 long c_freedcount; 106 long c_sr; 107 long c_bs; 108 t_signal *c_usedlist; 109 t_signal *c_freelist; 110 t_signal *c_zero; 111 struct _ugenbox *c_ugenlist; // temporary variable, allows reentrant compiling 112 struct _dspchain *c_prev; 113 void *c_patcher; // top-level parent or 0 if global 114 void *c_inlets; // collection of inlets 115 void *c_outlets; // collection of outlets 116 void *c_inputs; // signal input list (zero before first exec) 117 void *c_outputs; // signal output list 118 // have to determine whether freelist is global or local 119 volatile long c_broken; // object being freed, don't run it 120 long c_intype; // using old signal linklist (0) or array 121 long c_outtype; // using old signal linklist (0) or array 122 t_int32_atomic c_dontbreak; // temporarily prevent chain from being broken 123 t_int32_atomic c_wantsbreak; // so main thread can tell audio thread it wants to become broken 124 void *c_patchers; // used to keep track of all patchers in chain 125 void *c_posttickobjects; // list of objects to be ticked after process (called from same thread as dspchain is ticked from) 126 void *c_mixerlisteners; // list of objects listening to various mixer notifications 127 void *unused; // was c_chain64 but no longer used 128 struct _ugenbox *c_curugen; // internal use: ugenbox pointer to current box during dsp64 method call 129 t_object *c_implicitugens; // internal use 130 long c_32bitchain; // flag set when this is really a 32 bit chain (for wrapper) 131 long c_benchmark; // flag set when benchmarking cpu consumption 132 double c_benchtime_used; // cumulative cputime (in milliseconds) used for ticking all objects in the chain (only when benchmarking is enabled) 133 double c_benchtime_available; // cumulative time (in milliseconds) since this dspchain has been started (only when benchmarking is enabled) 134 long c_chain64_alloclen; 135 long c_chain64_len; 136 struct _chain64item *c_chain64_array; 137 struct _chain64item_extra *c_chain64_extra_array; 138 } t_dspchain; 139 140 #ifndef VPTR_TYPEDEF 141 /** A void pointer. @ingroup msp */ 142 typedef void *t_vptr; 143 /** A void pointer. @ingroup msp */ 144 typedef void *vptr; 145 #define VPTR_TYPEDEF 146 #endif 147 148 // useful define 149 150 #ifndef PI 151 /** The pi constant. @ingroup msp */ 152 #define PI 3.14159265358979323846 153 #endif 154 #ifndef TWOPI 155 /** Twice the pi constant. @ingroup msp */ 156 #define TWOPI 6.28318530717958647692 157 #endif // TWOPI 158 #ifndef PIOVERTWO 159 /** Half of the pi constant. @ingroup msp */ 160 #define PIOVERTWO 1.57079632679489661923 161 #endif // PIOVERTWO 162 163 // system access prototypes 164 165 BEGIN_USING_C_LINKAGE 166 167 /** A function pointer for the audio perform routine used by MSP objects to process blocks of samples. @ingroup msp */ 168 typedef t_int *(*t_perfroutine)(t_int *args); 169 170 typedef void (*t_perfroutine64)(t_object *x, t_object *dsp64, double **ins, long numins, double **outs, long numouts, long sampleframes, long flags, void *userparam); 171 172 // messages to the dsp object 173 174 void *dspmess(t_symbol *mess); 175 176 // access to DSP system variables 177 178 /** Query MSP for the maximum global vector (block) size. 179 @ingroup msp 180 @return The maximum global vector size for the MSP environment. */ 181 int sys_getmaxblksize(void); 182 183 /** Query MSP for the current global vector (block) size. 184 @ingroup msp 185 @return The current global vector size for the MSP environment. */ 186 int sys_getblksize(void); 187 188 /** Query MSP for the global sample rate. 189 @ingroup msp 190 @return The global sample rate of the MSP environment. */ 191 float sys_getsr(void); 192 193 int sys_getch(void); // returns current number of channels 194 int sys_optimize(void); // returns whether to optimize or not 195 int sys_altivec(void); // returns whether machine has vector processing 196 197 /** Query MSP to determine whether or not it is running. 198 @ingroup msp 199 @return Returns true if the DSP is turned on, otherwise returns false. */ 200 int sys_getdspstate(void); // returns whether audio is on or off 201 202 /** Query MSP to determine whether or not a given audio object is 203 in a running dsp chain. This is preferable over sys_getdspstate() 204 since global audio can be on but an object could be in a patcher that 205 is not running. 206 @ingroup msp 207 @return Returns true if the MSP object is in a patcher that has audio on, otherwise returns false. 208 */ 209 int sys_getdspobjdspstate(t_object *o); 210 211 // controlling the DSP 212 213 void canvas_start_dsp(void); 214 void canvas_stop_dsp(void); 215 void dsp_tick(void); // no longer used 216 217 // the dspchain object 218 219 #define DSPCHAIN_MIXERLISTENER_WILLPROCESSIOVECTOR (0x00000001) 220 #define DSPCHAIN_MIXERLISTENER_WILLPROCESSMIXER (0x00000002) 221 #define DSPCHAIN_MIXERLISTENER_DIDPROCESSMIXER (0x00000004) 222 #define DSPCHAIN_MIXERLISTENER_DIDPROCESSIOVECTOR (0x00000008) 223 #define DSPCHAIN_MIXERLISTENER_MIXERGRAPHWILLSTART (0x00000010) 224 #define DSPCHAIN_MIXERLISTENER_MIXERGRAPHWILLSTOP (0x00000020) 225 226 t_dspchain *dspchain_start(long bs, long sr); 227 t_dspchain *dspchain_get(void); 228 t_dspchain *dspchain_compile(t_patcher *p, long bs, long sr); 229 t_dspchain *dspchain_compile2(t_patcher *p, t_dspchain *x); 230 void dspchain_tick(t_dspchain *c); 231 void canvas_start_onedsp(t_patcher *p, t_dspchain **c, long bs, long sr); 232 void canvas_stop_onedsp(t_dspchain *c); 233 void dspchain_setbroken(t_dspchain *c); 234 t_max_err dspchain_lock(t_dspchain *c); 235 void dspchain_unlock(t_dspchain *c); 236 t_dspchain *dspchain_fromobject(t_object *o); 237 void dspchain_addmixerlistener(t_dspchain *chain, t_object *listener, long notifications); 238 239 // utility perform routines 240 241 void set_zero(float *dst, long n); 242 void set_zero64(double *dst, long n); 243 void copy_64from32(t_double *dst, const t_float *src, long n); 244 void copy_32from64(t_float *dst, const t_double *src, long n); 245 t_int *plus_perform(t_int *args); 246 t_int *plus_perform64(t_int *args); 247 t_int *sig_perform(t_int *args); 248 t_int *sig_perform64(t_int *args); 249 t_int *copy_perform(t_int *args); 250 t_int *copy_perform64(t_int *args); 251 t_int *plus2_perform(t_int *w); 252 t_int *plus2_perform64(t_int *w); 253 254 // setup routines used by DSP objects 255 256 /** Call this function in your MSP object's dsp method. 257 This function adds your object's perform method to the DSP call chain 258 and specifies the arguments it will be passed. 259 n, the number of arguments to your perform method, should be followed by n 260 additional arguments, all of which must be the size of a pointer or a long. 261 262 @ingroup msp 263 @param f The perform routine to use for processing audio. 264 @param n The number of arguments that will follow 265 @param ... The arguments that will be passed to the perform routine. 266 @see @ref chapter_msp_anatomy_dsp 267 @see @ref chapter_msp_advanced_connections */ 268 C74_DEPRECATED( void dsp_add(t_perfroutine f, int n, ...) ); 269 270 /** Call this function in your MSP object's dsp method. 271 Use dsp_addv() to add your object's perform routine to the DSP call 272 chain and specify its arguments in an array rather than as arguments to 273 a function. 274 275 @ingroup msp 276 @param f The perform routine to use for processing audio. 277 @param n The number of arguments that will follow in the vector parameter. 278 @param vector The arguments that will be passed to the perform routine. 279 @see @ref chapter_msp_anatomy_dsp 280 @see @ref chapter_msp_advanced_connections */ 281 C74_DEPRECATED( void dsp_addv(t_perfroutine f, int n, void **vector) ); 282 283 // objects should only have one perform method 284 // in exceptional cases there may be a situation where warnings about this need to be disabled. 285 // this flag to dsp_add64 will accomplish that 286 // for internal use only 287 #define DSP_ADD64_FLAG_INTERNALITEM (0x00000001) 288 289 void dsp_add64(t_object *chain, t_object *x, t_perfroutine64 f, long flags, void *userparam); 290 291 /** Call this routine after creating your object in the new instance routine 292 with object_alloc(). Cast your object to #t_pxobject as the first 293 argument, then specify the number of signal inputs your object will 294 have. dsp_setup() initializes fields of the #t_pxobject header and 295 allocates any proxies needed (if num_signal_inputs is greater than 1). 296 297 Some signal objects have no inputs; you should pass 0 for 298 num_signal_inputs in this case. After calling dsp_setup(), you can 299 create additional non-signal inlets using intin(), floatin(), or 300 inlet_new(). 301 302 @ingroup msp 303 @param x Your object's pointer. 304 @param nsignals The number of signal/proxy inlets to create for the object. 305 @see #dsp_setup */ 306 void z_dsp_setup(t_pxobject *x, long nsignals); // called in new method 307 308 /** This is commonly used rather than directly calling z_dsp_setup() in MSP objects. 309 @ingroup msp */ 310 #define dsp_setup z_dsp_setup 311 312 void dsp_resize(t_pxobject *x, long nsignals); // for dynamic inlets 313 314 315 /** This function disposes of any memory used by proxies allocated by 316 dsp_setup(). It also notifies the signal compiler that the DSP call chain 317 needs to be rebuilt if signal processing is active. You should be sure to 318 call this before de-allocating any memory that might be in use by your 319 object’s perform routine, in the event that signal processing is on when 320 your object is freed. 321 322 @ingroup msp 323 @param x The object to free. 324 @see #dsp_free */ 325 void z_dsp_free(t_pxobject *x); 326 327 /** This is commonly used rather than directly calling z_dsp_free() in MSP objects. 328 @ingroup msp */ 329 #define dsp_free z_dsp_free 330 331 332 C74_DEPRECATED ( void z_add_signalmethod(void) ); // called in initialization routine 333 #define dsp_initclass z_add_signalmethod 334 335 void z_sysinit(void); 336 #define dsp_sysinit z_sysinit 337 338 void dsp_setpatcher(void *p); 339 void *dsp_getpatcher(); 340 341 short z_isconnected(t_object *x, t_object *dst, short *index); 342 #define dsp_isconnected z_isconnected 343 344 short z_dsp_setloadupdate(short way); 345 #define dsp_setloadupdate z_dsp_setloadupdate 346 347 void *dsp_setpostprocess(method pm); 348 void *dsp_setpreprocess(method pm); 349 350 // used only by audio driver objects 351 352 void sys_setprocessflag(short way); 353 354 // lame audio file utility (do not use) 355 356 short aiff_parse(char *header, long *offset, long *size, long *nchans, long *ssize, 357 long *srate, void *chunk, void *markers); 358 359 // memory utilities 360 361 void *t_resizebytes(char *old, long oldsize, long newsize); 362 void *t_getbytes(long size); 363 void *t_freebytes(void *fatso, long size); 364 365 // atom utilities 366 367 t_int atom_getintarg(short which, short argc, t_atom *argv); 368 float atom_getfloatarg(short which, short argc, t_atom *argv); 369 t_symbol *atom_getsymarg(short which, short argc, t_atom *argv); 370 371 #define PROXY_GETINLET(x) proxy_getinlet(x) 372 373 374 /** This routine must be called in your object's initialization routine. It 375 adds a set of methods to your object's class that are called by MSP to 376 build the DSP call chain. These methods function entirely 377 transparently to your object so you don't have to worry about them. 378 However, you should avoid binding anything to their names: signal, 379 userconnect, nsiginlets, and enable. 380 381 This routine is for non-user-interface objects only 382 (where the first item in your object's struct is a t_pxobject). 383 It must be called prior to calling class_register() for your class. 384 385 @ingroup msp 386 @param c The class to make dsp-ready. 387 @see class_dspinitjbox() */ 388 void class_dspinit(t_class *c); 389 390 /** This routine must be called in your object's initialization routine. It 391 adds a set of methods to your object's class that are called by MSP to 392 build the DSP call chain. These methods function entirely 393 transparently to your object so you don't have to worry about them. 394 However, you should avoid binding anything to their names: signal, 395 userconnect, nsiginlets, and enable. 396 397 This routine is for user-interface objects only 398 (where the first item in your object's struct is a t_jbox). 399 400 @ingroup msp 401 @param c The class to make dsp-ready. 402 @see class_dspinit() */ 403 void class_dspinitjbox(t_class *c); 404 405 406 // defines for SIMD optimization 407 408 // minimum vector size to use SIMD optimization 409 #define DSP_OPTIMIZE_MIN 64 410 411 // simple (e.g. times, minus) not worth optimizing, disabled 412 #define DSP_SIMPLE_OPTIMIZE_TEST(sigptr) (FALSE) 413 414 // simple parameter setting test (e.g. times, minus) not worth optimizing, disabled 415 #define DSP_SIMPLE_OPTIMIZE_TEST_PARAM (FALSE) 416 417 // complex (e.g. cos, log, sqrt, fft family) optimize as long as enabled and vector is large enough 418 #define DSP_COMPLEX_OPTIMIZE_TEST(sigptr) (FALSE) 419 //#define DSP_COMPLEX_OPTIMIZE_TEST(sigptr) (sys_optimize()&&(sigptr)&&(sigptr)->s_n>=DSP_OPTIMIZE_MIN) 420 421 // buffered routines optimize always if enabled since signal vector isn't relevant 422 #define DSP_BUFFERED_OPTIMIZE_TEST(sigptr) (FALSE) 423 //#define DSP_BUFFERED_OPTIMIZE_TEST(sigptr) (sys_optimize()) 424 425 426 427 END_USING_C_LINKAGE 428 429 #if C74_PRAGMA_STRUCT_PACKPUSH 430 #pragma pack(pop) 431 #elif C74_PRAGMA_STRUCT_PACK 432 #pragma pack() 433 #endif 434 435 //-- ddz, so this is OK, just needs jpatcher_api.h first, right? 436 437 #if defined(_JPATCHER_API_H_) || defined(_DOXY_) 438 BEGIN_USING_C_LINKAGE 439 440 441 /** Header for any ui signal processing object. 442 For non-ui objects use #t_pxobject. 443 @ingroup msp */ 444 typedef struct _pxjbox { 445 t_jbox z_box; ///< The box struct used by all ui objects. 446 long z_in; 447 void *z_proxy; 448 long z_disabled; ///< set to non-zero if this object is muted (using the pcontrol or mute~ objects) 449 short z_count; ///< the number of signal inlets 450 short z_misc; ///< flags (bitmask) determining object behaviour, such as #Z_NO_INPLACE, #Z_PUT_FIRST, or #Z_PUT_LAST 451 } t_pxjbox; 452 453 void z_jbox_dsp_setup(t_pxjbox *x, long nsignals); 454 void z_jbox_dsp_free(t_pxjbox *x); 455 456 #define dsp_setupjbox z_jbox_dsp_setup 457 #define dsp_freejbox z_jbox_dsp_free 458 459 END_USING_C_LINKAGE 460 461 462 #endif // _JPATCHER_API_H_ 463 #endif // _Z_DSP_H 464