//----------------------------------------------------------------------------- // Entaro ChucK Developer! // This is a Chugin boilerplate, generated by chuginate! //----------------------------------------------------------------------------- // this should align with the correct versions of these ChucK files #include "chuck_dl.h" #include "chuck_def.h" #include "chuck_oo.h" // general includes #include #include #include class AmbPan3 { public: // constructor AmbPan3( t_CKFLOAT fs) : SQRT3(sqrtf(3)), SQRT5(sqrtf(5)), SQRT15(sqrtf(15)) { m_azimuth = 0; m_elevation = 0; compute_gains(); for(int i = 0; i < 16; i++) { m_channel_map[i] = i; } } // for Chugins extending UGen void tick( SAMPLE * in, SAMPLE * out, int nframes ) { for(int f = 0; f < nframes; f++) { for(int c = 0; c < 16; c++) { out[f*16+m_channel_map[c]] = m_gain[c] * in[f*16]; } } } // set parameter example float setAzimuth( t_CKFLOAT a ) { m_azimuth = a; compute_gains(); return m_azimuth; } // get parameter example float getAzimuth() { return m_azimuth; } // set parameter example float setElevation( t_CKFLOAT e ) { m_elevation = e; compute_gains(); return m_elevation; } // get parameter example float getElevation() { return m_elevation; } void setChannelMap(Chuck_Array4 * map) { int len = ck_min(map->m_vector.size(), 16); for(int i = 0; i < len; i++) m_channel_map[i] = map->m_vector[i]; } private: void compute_gains() { t_CKFLOAT cosA = cosf(m_azimuth); t_CKFLOAT sinA = sinf(m_azimuth); t_CKFLOAT cos2A = cosA*cosA - sinA*sinA; t_CKFLOAT sin2A = 2*cosA*sinA; t_CKFLOAT cos3A = cosA*cos2A - sinA*sin2A; t_CKFLOAT sin3A = sin2A*cosA + sinA*cos2A; t_CKFLOAT cosE = cosf(m_elevation); t_CKFLOAT sinE = sinf(m_elevation); t_CKFLOAT cos2E = cosE*cosE - sinE*sinE; t_CKFLOAT sin2E = 2*cosE*sinE; /* m_gain[0] = 1.; //W m_gain[1] = cosA*cosE; //X m_gain[2] = sinA*cosE; //Y m_gain[3] = sinE; //Z m_gain[4] = (3.*sinE*sinE-1) / 2.; //R m_gain[5] = SQRT3 * cosA * sin2E / 2.; //S m_gain[6] = SQRT3 * sinA * sin2E / 2.; //T m_gain[7] = SQRT3 * cos2A * cosE * cosE / 2.; //U m_gain[8] = SQRT3 * sin2A * cosE * cosE / 2.; //V m_gain[9] = sinE * (5.*sinE*sinE - 3.) / 2.; //K m_gain[10] = SQRT3 * cosA * cosE * (5*sinE*sinE - 1) / 8.; //L m_gain[11] = SQRT3 * sinA * cosE * (5*sinE*sinE - 1) / 8.; //M m_gain[12] = SQRT15 * cos2A * sinE * cosE * cosE / 2.; //N m_gain[13] = SQRT15 * sin2A * sinE * cosE * cosE / 2.; //O m_gain[14] = SQRT5 * cos3A * cosE * cosE * cosE / 8.; //P m_gain[15] = SQRT5 * sin3A * cosE * cosE * cosE / 8.; //Q //*/ // constant = sqrt(21 / 8) / sqrt(224 / 45) t_CKFLOAT k_lmt = sqrtf(21.0f/8.0f)/sqrtf(224.0f/45.0f); // constant = sqrt(3) * 3 / 2 t_CKFLOAT k_ont = sqrtf(3.0f)*3.0f/2.0f; t_CKFLOAT W = 1.0f/sqrtf(2.0f); t_CKFLOAT X = cosA*cosE; t_CKFLOAT Y = sinA*cosE; t_CKFLOAT Z = sinE; t_CKFLOAT R = (3.0f*Z*Z-1.0f)/2.0f; t_CKFLOAT S = 2.0f*Z*X; t_CKFLOAT T = 2.0f*Z*Y; t_CKFLOAT U = X*X-Y*Y; t_CKFLOAT V = 2.0f*X*Y; t_CKFLOAT K = Z*((5.0f*Z*Z)-3.0f)/2.0f; t_CKFLOAT L = k_lmt*((5.0f*Z*Z)-1.0f)*X; t_CKFLOAT M = k_lmt*((5.0f*Z*Z)-1.0f)*Y; t_CKFLOAT N = k_ont*Z*U; t_CKFLOAT O = k_ont*Z*V; t_CKFLOAT P = (X*X-(3.0f*Y*Y))*X; t_CKFLOAT Q = ((3*X*X)-Y*Y)*Y; m_gain[0] = W; m_gain[1] = X; m_gain[2] = Y; m_gain[3] = Z; m_gain[4] = R; m_gain[5] = S; m_gain[6] = T; m_gain[7] = U; m_gain[8] = V; m_gain[9] = K; m_gain[10] = L; m_gain[11] = M; m_gain[12] = N; m_gain[13] = O; m_gain[14] = P; m_gain[15] = Q; //*/ } // instance data t_CKFLOAT m_azimuth; t_CKFLOAT m_elevation; t_CKFLOAT m_gain[16]; t_CKUINT m_channel_map[16]; const t_CKFLOAT SQRT3; const t_CKFLOAT SQRT5; const t_CKFLOAT SQRT15; }; // declaration of chugin constructor CK_DLL_CTOR(ambpan3_ctor); // declaration of chugin desctructor CK_DLL_DTOR(ambpan3_dtor); // example of getter/setter CK_DLL_MFUN(ambpan3_setAzimuth); CK_DLL_MFUN(ambpan3_getAzimuth); CK_DLL_MFUN(ambpan3_setElevation); CK_DLL_MFUN(ambpan3_getElevation); CK_DLL_MFUN(ambpan3_setChannelMap); // for Chugins extending UGen, this is mono synthesis function for 1 sample CK_DLL_TICKF(ambpan3_tickf); // this is a special offset reserved for Chugin internal data t_CKINT ambpan3_data_offset = 0; // query function: chuck calls this when loading the Chugin CK_DLL_QUERY( AmbPan3 ) { // hmm, don't change this... QUERY->setname(QUERY, "AmbPan"); // begin the class definition // can change the second argument to extend a different ChucK class QUERY->begin_class(QUERY, "AmbPan3", "UGen"); QUERY->doc_class(QUERY, "Third-order ambisonics panner (https://en.wikipedia.org/wiki/Ambisonics)"); QUERY->add_ex(QUERY, "spatial/AmbPan3-CCRMA.ck"); // register the constructor (probably no need to change) QUERY->add_ctor(QUERY, ambpan3_ctor); // register the destructor (probably no need to change) QUERY->add_dtor(QUERY, ambpan3_dtor); // for UGen's only: add tick function QUERY->add_ugen_funcf(QUERY, ambpan3_tickf, NULL, 16, 16); // example of adding setter method QUERY->add_mfun(QUERY, ambpan3_setAzimuth, "float", "azimuth"); // example of adding argument to the above method QUERY->add_arg(QUERY, "float", "arg"); QUERY->doc_func(QUERY, "Set horizontal angle of point source"); // example of adding getter method QUERY->add_mfun(QUERY, ambpan3_getAzimuth, "float", "azimuth"); QUERY->doc_func(QUERY, "Get horizontal angle of point source"); // example of adding setter method QUERY->add_mfun(QUERY, ambpan3_setElevation, "float", "elevation"); // example of adding argument to the above method QUERY->add_arg(QUERY, "float", "arg"); QUERY->doc_func(QUERY, "Set vertical angle of point source"); // example of adding getter method QUERY->add_mfun(QUERY, ambpan3_getElevation, "float", "elevation"); QUERY->doc_func(QUERY, "Get vertical angle of point source"); // example of adding setter method QUERY->add_mfun(QUERY, ambpan3_setChannelMap, "void", "channelMap"); // example of adding argument to the above method QUERY->add_arg(QUERY, "int[]", "arg"); QUERY->doc_func(QUERY, "Set the mapping of channels for the amibsonic system"); // this reserves a variable in the ChucK internal class to store // referene to the c++ class we defined above ambpan3_data_offset = QUERY->add_mvar(QUERY, "int", "@ap_data", false); // end the class definition // IMPORTANT: this MUST be called! QUERY->end_class(QUERY); // wasn't that a breeze? return TRUE; } // implementation for the constructor CK_DLL_CTOR(ambpan3_ctor) { // get the offset where we'll store our internal c++ class pointer OBJ_MEMBER_INT(SELF, ambpan3_data_offset) = 0; // instantiate our internal c++ class representation AmbPan3 * bcdata = new AmbPan3(API->vm->get_srate(API, SHRED)); // store the pointer in the ChucK object member OBJ_MEMBER_INT(SELF, ambpan3_data_offset) = (t_CKINT) bcdata; } // implementation for the destructor CK_DLL_DTOR(ambpan3_dtor) { // get our c++ class pointer AmbPan3 * bcdata = (AmbPan3 *) OBJ_MEMBER_INT(SELF, ambpan3_data_offset); // check it if( bcdata ) { // clean up delete bcdata; OBJ_MEMBER_INT(SELF, ambpan3_data_offset) = 0; bcdata = NULL; } } // implementation for tick function CK_DLL_TICKF(ambpan3_tickf) { // get our c++ class pointer AmbPan3 * c = (AmbPan3 *) OBJ_MEMBER_INT(SELF, ambpan3_data_offset); // invoke our tick function; store in the magical out variable if(c) c->tick(in, out, nframes); // yes return TRUE; } // example implementation for setter CK_DLL_MFUN(ambpan3_setAzimuth) { // get our c++ class pointer AmbPan3 * bcdata = (AmbPan3 *) OBJ_MEMBER_INT(SELF, ambpan3_data_offset); // set the return value RETURN->v_float = bcdata->setAzimuth(GET_NEXT_FLOAT(ARGS)); } // example implementation for getter CK_DLL_MFUN(ambpan3_getAzimuth) { // get our c++ class pointer AmbPan3 * bcdata = (AmbPan3 *) OBJ_MEMBER_INT(SELF, ambpan3_data_offset); // set the return value RETURN->v_float = bcdata->getAzimuth(); } // example implementation for setter CK_DLL_MFUN(ambpan3_setElevation) { // get our c++ class pointer AmbPan3 * bcdata = (AmbPan3 *) OBJ_MEMBER_INT(SELF, ambpan3_data_offset); // set the return value RETURN->v_float = bcdata->setElevation(GET_NEXT_FLOAT(ARGS)); } // example implementation for getter CK_DLL_MFUN(ambpan3_getElevation) { // get our c++ class pointer AmbPan3 * bcdata = (AmbPan3 *) OBJ_MEMBER_INT(SELF, ambpan3_data_offset); // set the return value RETURN->v_float = bcdata->getElevation(); } CK_DLL_MFUN(ambpan3_setChannelMap) { // get our c++ class pointer AmbPan3 * bcdata = (AmbPan3 *) OBJ_MEMBER_INT(SELF, ambpan3_data_offset); Chuck_Array4 * map = (Chuck_Array4 *) GET_NEXT_OBJECT(ARGS); bcdata->setChannelMap(map); }