// z_dsp.h -- the main header file for all DSP objects copyright 1997-2003 Cycling '74

// DSP services:

#ifndef _Z_DSP_H
#define _Z_DSP_H

#ifndef SAMPLE_TYPEDEF
typedef int t_int;
typedef float t_sample, t_float;
#define SAMPLE_TYPEDEF
#endif

#include "z_altivec.h"

#if C74_PRAGMA_STRUCT_PACKPUSH
    #pragma pack(push, 2)
#elif C74_PRAGMA_STRUCT_PACK
    #pragma pack(2)
#endif

enum {
	SYS_MAXBLKSIZE = 2048,	// a good number for a maximum signal vector size
	SYS_MAXSIGS = 250		// number of signal inlets you can have in an object
};

// macro loop for checking for NAN/INF

// note: this may be platform-dependent

#define NAN_MASK 0x7F800000

#define NAN_CHECK(n,o) \
while (n--) { if ((*(o) & NAN_MASK) == NAN_MASK) *(o) = 0; (o)++; } // now post inc/dec -Rd jun 05

#define IS_DENORM_FLOAT(v)		((((*(unsigned long *)&(v))&0x7f800000)==0)&&((v)!=0.f))
#define IS_DENORM_DOUBLE(v)		((((((unsigned long *)&(v))[1])&0x7fe00000)==0)&&((v)!=0.))			

#define IS_NAN_FLOAT(v)			(((*(unsigned long *)&(v))&0x7f800000)==0x7f800000)
#define IS_NAN_DOUBLE(v)		(((((unsigned long *)&(v))[1])&0x7fe00000)==0x7fe00000) 

#define IS_DENORM_NAN_FLOAT(v)		(IS_DENORM_FLOAT(v)||IS_NAN_FLOAT(v))
#define IS_DENORM_NAN_DOUBLE(v)		(IS_DENORM_DOUBLE(v)||IS_NAN_DOUBLE(v))			

// currently all little endian processors are x86
#if defined(WIN_VERSION) || (defined(MAC_VERSION)&&TARGET_RT_LITTLE_ENDIAN)
#define DENORM_WANT_FIX		1
#endif

#ifdef DENORM_WANT_FIX

#define FIX_DENORM_FLOAT(v)		((v)=IS_DENORM_FLOAT(v)?0.f:(v))
#define FIX_DENORM_DOUBLE(v)	((v)=IS_DENORM_DOUBLE(v)?0.f:(v))

#define FIX_DENORM_NAN_FLOAT(v)		((v)=IS_DENORM_NAN_FLOAT(v)?0.f:(v))
#define FIX_DENORM_NAN_DOUBLE(v)	((v)=IS_DENORM_NAN_DOUBLE(v)?0.:(v))

#else

#define FIX_DENORM_FLOAT(v)		
#define FIX_DENORM_DOUBLE(v)	

#define FIX_DENORM_NAN_FLOAT(v)		
#define FIX_DENORM_NAN_DOUBLE(v)

#endif


// header for all DSP objects. Provides a proxy.

// z_misc flags:

#define Z_NO_INPLACE 1			// flag indicating the object doesn't want signals in place
#define Z_PUT_LAST 2			// when list of ugens is resorted, put this object at end
#define Z_PUT_FIRST 4			// when list of ugens is resorted, put this object at beginning

typedef void *t_proxy;

typedef struct t_pxobject {
	struct object z_ob;
	long z_in;
#ifdef PROBE_TEST
	void *z_proxy;
#else
	t_proxy *z_proxy;
#endif
	long z_disabled;
	short z_count;
	short z_misc;
} t_pxobject;

// the signal data structure

#define MAXLOGSIG 13
#define MAXSIGSIZE (1 << MAXLOGSIG)

typedef struct _signal
{
    long s_n;
    t_sample *s_vec;
    float s_sr;
    struct _signal *s_next;
    struct _signal *s_nextused;
    short s_refcount;
    short s_size;					// element size (* s_n == memory)
    char *s_ptr;					// what to free
} t_signal;

typedef struct _dspchain
{
	t_object c_ob;
	t_int *c_chain;
	long c_chainsize;
	long c_callcount;
	long c_usedcount;
	long c_reusedcount;
	long c_freedcount;
	long c_sr;
	long c_bs;
	t_signal *c_usedlist;
	t_signal *c_freelist;
	t_signal *c_zero;
	struct _ugenbox *c_ugenlist;	// temporary variable, allows reentrant compiling
	struct _dspchain *c_prev;
	void *c_patcher;	// top-level parent or 0 if global
	void *c_inlets;		// collection of inlets
	void *c_outlets;	// collection of outlets
	void *c_inputs;		// signal input list (zero before first exec)
	void *c_outputs; 	// signal output list
	// have to determine whether freelist is global or local
	long c_broken;		// object being freed, don't run it
	long c_intype;		// using old signal linklist (0) or array
	long c_outtype;		// using old signal linklist (0) or array
} t_dspchain;

typedef t_int *(*t_perfroutine)(t_int *args);

#ifndef VPTR_TYPEDEF
typedef void *vptr,*t_vptr;
#define VPTR_TYPEDEF
#endif 

// useful define

#ifndef PI
#define PI 3.14159265358979323846
#endif
#ifndef TWOPI
#define TWOPI		6.28318530717958647692
#endif  // TWOPI
#ifndef PIOVERTWO
#define PIOVERTWO	1.57079632679489661923
#endif  // PIOVERTWO

// system access prototypes

BEGIN_USING_C_LINKAGE 

// messages to the dsp object

void *dspmess(t_symbol *mess);

// access to DSP system variables

int sys_getmaxblksize(void);	// returns current max blk size
int sys_getblksize(void);		// returns current blk size
float sys_getsr(void);			// returns current sampling rate
int sys_getch(void);			// returns current number of channels

int sys_optimize(void);			// returns whether to optimize or not
int sys_altivec(void);			// returns whether machine has vector processing

int sys_getdspstate(void);		// returns whether audio is on or off

// controlling the DSP

void canvas_start_dsp(void);
void canvas_stop_dsp(void);
void dsp_tick(void);			// no longer used

// the dspchain object

t_dspchain *dspchain_start(long bs, long sr);
t_dspchain *dspchain_get(void);
t_dspchain *dspchain_compile(t_patcher *p, long bs, long sr);
t_dspchain *dspchain_compile2(t_patcher *p, t_dspchain *x);
void dspchain_tick(t_dspchain *c);
void canvas_start_onedsp(t_patcher *p, t_dspchain **c, long bs, long sr); 
void canvas_stop_onedsp(t_dspchain *c);

// utility perform routines

void set_zero(float *dst, long n);
t_int *plus_perform(t_int *args);
t_int *sig_perform(t_int *args);
t_int *copy_perform(t_int *args);
t_int *plus2_perform(t_int *w);

// setup routines used by DSP objects

void dsp_add(t_perfroutine f, int n, ...);			// called in dsp method
void dsp_addv(t_perfroutine f, int n, void **vector);	 // called in dsp method

void z_dsp_setup(t_pxobject *x, long nsignals);		// called in new method
#define dsp_setup z_dsp_setup

void z_dsp_free(t_pxobject *x);						// default object free
#define dsp_free z_dsp_free

void z_add_signalmethod(void);						// called in initialization routine
#define dsp_initclass z_add_signalmethod

void z_sysinit(void);
#define dsp_sysinit z_sysinit

void z_patcher_for_dsp(t_object *x);
#define dsp_patcher z_patcher_for_dsp

void dsp_setpatcher(void *p);

short z_isconnected(t_object *x, t_object *dst, short *index);
#define dsp_isconnected z_isconnected

short z_dsp_setloadupdate(short way);
#define dsp_setloadupdate z_dsp_setloadupdate

void *dsp_setpostprocess(method pm);
void *dsp_setpreprocess(method pm);

// used only by audio driver objects

void sys_setprocessflag(short way);

// lame audio file utility (do not use)

short aiff_parse(char *header, long *offset, long *size, long *nchans, long *ssize,
	long *srate, void *chunk, void *markers);

// memory utilities

void *t_resizebytes(char *old, long oldsize, long newsize);
void *t_getbytes(long size);
void *t_freebytes(void *fatso, long size);

// atom utilities

t_int atom_getintarg(short which, short argc, t_atom *argv);
float atom_getfloatarg(short which, short argc, t_atom *argv);
t_symbol *atom_getsymarg(short which, short argc, t_atom *argv);

#define PROXY_GETINLET(x) proxy_getinlet(x)

void class_dspinit(t_class *c);
void class_dspinitbox(t_class *c);

// defines for SIMD optimization

// minimum vector size to use SIMD optimization
#define DSP_OPTIMIZE_MIN	64

// simple (e.g. times, minus) not worth optimizing, disabled
#define DSP_SIMPLE_OPTIMIZE_TEST(sigptr)		(FALSE)

// simple parameter setting test (e.g. times, minus) not worth optimizing, disabled
#define DSP_SIMPLE_OPTIMIZE_TEST_PARAM			(FALSE)

// complex (e.g. cos, log, sqrt, fft family) optimize as long as enabled and vector is large enough
#define DSP_COMPLEX_OPTIMIZE_TEST(sigptr)		(FALSE)
//#define DSP_COMPLEX_OPTIMIZE_TEST(sigptr)		(sys_optimize()&&(sigptr)&&(sigptr)->s_n>=DSP_OPTIMIZE_MIN)

// buffered routines optimize always if enabled since signal vector isn't relevant
#define DSP_BUFFERED_OPTIMIZE_TEST(sigptr)		(FALSE)
//#define DSP_BUFFERED_OPTIMIZE_TEST(sigptr)	(sys_optimize())



END_USING_C_LINKAGE 

#if C74_PRAGMA_STRUCT_PACKPUSH
    #pragma pack(pop)
#elif C74_PRAGMA_STRUCT_PACK
    #pragma pack()
#endif

//-- ddz, so this is OK, just needs jpatcher_api.h first, right?

#ifdef _JPATCHER_API_H_

typedef struct _pxjbox {
	t_jbox z_box;
	long z_in;
#ifdef PROBE_TEST
	void *z_proxy;
#else
	t_proxy *z_proxy;
#endif
	long z_disabled;
	short z_count;
	short z_misc;
} t_pxjbox;

BEGIN_USING_C_LINKAGE

void class_dspinitjbox(t_class *c);
void z_jbox_dsp_setup(t_pxjbox *x, long nsignals); 
void z_jbox_dsp_free(t_pxjbox *x);

#define dsp_setupjbox z_jbox_dsp_setup
#define dsp_freejbox z_jbox_dsp_free

END_USING_C_LINKAGE

#endif // _JPATCHER_API_H_

#endif // _Z_DSP_H

