#include "chuck_dl.h" #include "chuck_def.h" #include #include #include CK_DLL_CTOR(ZCs_ctor); CK_DLL_DTOR(ZCs_dtor); CK_DLL_MFUN(ZCs_setFrame); // set frame, allocate memory (default 4410) CK_DLL_MFUN(ZCs_getFrame); // query frame size, in samples CK_DLL_MFUN(ZCs_getZCs); // get all zero crossings in frame / 2 CK_DLL_TICK(ZCs_tick); t_CKINT ZCs_data_offset = 0; struct ZCsData { int frame; // frame, size of buffer, update this often int count; // where are we in frame, circular buffer pointer int zcs; // number of positive-going ZCs in last frame int zcsTemp; // temp accumulator float lastIn; // last input sample }; CK_DLL_QUERY(ZCs) { QUERY->setname(QUERY, "ZCs"); QUERY->begin_class(QUERY, "ZCs", "UGen"); QUERY->add_ctor(QUERY, ZCs_ctor); QUERY->add_dtor(QUERY, ZCs_dtor); QUERY->add_ugen_func(QUERY, ZCs_tick, NULL, 1, 1); QUERY->add_mfun(QUERY, ZCs_setFrame, "int", "frame"); QUERY->add_arg(QUERY, "int", "arg"); QUERY->add_mfun(QUERY, ZCs_getFrame, "int", "frame"); QUERY->add_mfun(QUERY, ZCs_getZCs, "float", "ZCs"); ZCs_data_offset = QUERY->add_mvar(QUERY, "int", "@lpc_data", false); QUERY->end_class(QUERY); return TRUE; } CK_DLL_CTOR(ZCs_ctor) { OBJ_MEMBER_INT(SELF, ZCs_data_offset) = 0; ZCsData * tdfdata = new ZCsData; tdfdata->frame = 4410; // default, can reset after construct tdfdata->count = 0; tdfdata->zcs = 0; tdfdata->zcsTemp = 0; tdfdata->lastIn = 0.0; OBJ_MEMBER_INT(SELF, ZCs_data_offset) = (t_CKINT) tdfdata; } CK_DLL_DTOR(ZCs_dtor) { ZCsData * tdfdata = (ZCsData *) OBJ_MEMBER_INT(SELF, ZCs_data_offset); if(tdfdata) { delete tdfdata; OBJ_MEMBER_INT(SELF, ZCs_data_offset) = 0; tdfdata = NULL; } } CK_DLL_TICK(ZCs_tick) { ZCsData * tdfdata = (ZCsData *) OBJ_MEMBER_INT(SELF, ZCs_data_offset); *out = in; // first things first; if (in > 0.0 && tdfdata->lastIn<= 0.0) { tdfdata->zcsTemp++; } tdfdata->count++; if (tdfdata->count >= tdfdata->frame) { tdfdata->zcs = tdfdata->zcsTemp; tdfdata->zcsTemp = 0; tdfdata->count = 0; } tdfdata->lastIn = in; return TRUE; } CK_DLL_MFUN(ZCs_setFrame) { ZCsData * tdfdata = (ZCsData *) OBJ_MEMBER_INT(SELF, ZCs_data_offset); // TODO: sanity check tdfdata->frame = GET_NEXT_INT(ARGS); RETURN->v_int = tdfdata->frame; } CK_DLL_MFUN(ZCs_getFrame) { ZCsData * tdfdata = (ZCsData *) OBJ_MEMBER_INT(SELF, ZCs_data_offset); RETURN->v_int = tdfdata->frame; } CK_DLL_MFUN(ZCs_getZCs) { ZCsData * tdfdata = (ZCsData *) OBJ_MEMBER_INT(SELF, ZCs_data_offset); RETURN->v_float = tdfdata->zcs; }