void SOMTrain_Ctor(SOMTrain* unit) { // set the calculation function. do this before the base ctor because it may want to change it! SETCALC(SOMTrain_next); SOM_Ctor_base(unit, 7); // 7 is the offset before we get input data int traindur = (int)ZIN0(3); int traincountdown = traindur; // Decrement by one on each occasion double nhood = ZIN0(4) * (unit->m_netsize) * 0.5; // Neighbourhood size (fraction of total, here converted to span of nodes) to be included in a training update. Will decrement slowly. // The reason we halve it is for convenience: we look nhood/2 in positive direction, nhood/2 in negative direction. double nhooddelta = nhood / traindur; // This is how much it decrements by, each occasion. float weightfactor = ZIN0(6); // Scaling factor for how much the node "bends" towards the datum float mfactor = traindur * 0.25f; // Empirical scaling - weight falls to half of its value after 0.25 of the training // initialize the unit generator state variables. unit->m_traindur = traindur; unit->m_traincountdown = traincountdown; unit->m_traincountup = 0; unit->m_nhood = nhood; unit->m_nhooddelta = nhooddelta; unit->m_weightfactor = weightfactor; unit->m_mfactor = mfactor; unit->m_writeloc = 0.f; // calculate one sample of output. ZOUT0(0) = 0.f; ZOUT0(1) = 0.f; }
void FFT_next(FFT *unit, int wrongNumSamples) { float *in = IN(1); float *out = unit->m_inbuf + unit->m_pos + unit->m_shuntsize; int numSamples = unit->m_numSamples; // copy input memcpy(out, in, numSamples * sizeof(float)); unit->m_pos += numSamples; bool gate = ZIN0(4) > 0.f; // Buffer shunting continues, but no FFTing if (unit->m_pos != unit->m_hopsize || !unit->m_fftsndbuf->data || unit->m_fftsndbuf->samples != unit->m_fullbufsize) { if(unit->m_pos == unit->m_hopsize) unit->m_pos = 0; ZOUT0(0) = -1.f; } else { unit->m_pos = 0; if(gate){ scfft_dofft(unit->m_scfft); unit->m_fftsndbuf->coord = coord_Complex; ZOUT0(0) = unit->m_fftbufnum; } else { ZOUT0(0) = -1; } // Shunt input buf down memmove(unit->m_inbuf, unit->m_inbuf + unit->m_hopsize, unit->m_shuntsize * sizeof(float)); } }
void FFTTrigger_next(FFTTrigger *unit, int inNumSamples) { if (unit->m_periodsRemain > 0) { ZOUT0(0) = -1.f; unit->m_periodsRemain--; } else { ZOUT0(0) = unit->m_fftbufnum; unit->m_pos = 0; unit->m_periodsRemain = unit->m_numPeriods; } }
void PV_DecorTransExtract_Ctor(PV_DecorTransExtract *unit) { // get input variables unit->retTrans = IN0(1); unit->iVal = IN0(2); unit->jVal = IN0(3); unit->alphaVal = IN0(4); unit->betaVal = IN0(5); unit->dVal = IN0(6); unit->lowFreqCutVal = IN0(7); // set other variables unit->numFreqBins = 0; unit->prevBinsIdx = 0; unit->littleOmegaIdx = 0; unit->bigOmegaIdx = 0; unit->initDebugFlag = true; unit->initFirstCalc = true; // set output ZOUT0(0) = ZIN0(0); // set calculation function (next) SETCALC(PV_DecorTransExtract_next); }
int FFTBase_Ctor(FFTBase *unit, int frmsizinput) { World *world = unit->mWorld; uint32 bufnum = (uint32)ZIN0(0); SndBuf *buf; if (bufnum >= world->mNumSndBufs) { int localBufNum = bufnum - world->mNumSndBufs; Graph *parent = unit->mParent; if(localBufNum <= parent->localMaxBufNum) { buf = parent->mLocalSndBufs + localBufNum; } else { if(unit->mWorld->mVerbosity > -1){ Print("FFTBase_Ctor error: invalid buffer number: %i.\n", bufnum); } return 0; } } else { buf = world->mSndBufs + bufnum; } if (!buf->data) { if(unit->mWorld->mVerbosity > -1){ Print("FFTBase_Ctor error: Buffer %i not initialised.\n", bufnum); } return 0; } unit->m_fftsndbuf = buf; unit->m_fftbufnum = bufnum; unit->m_fullbufsize = buf->samples; int framesize = (int)ZIN0(frmsizinput); if(framesize < 1) unit->m_audiosize = buf->samples; else unit->m_audiosize = sc_min(buf->samples, framesize); unit->m_log2n_full = LOG2CEIL(unit->m_fullbufsize); unit->m_log2n_audio = LOG2CEIL(unit->m_audiosize); // Although FFTW allows non-power-of-two buffers (vDSP doesn't), this would complicate the windowing, so we don't allow it. if (!ISPOWEROFTWO(unit->m_fullbufsize)) { Print("FFTBase_Ctor error: buffer size (%i) not a power of two.\n", unit->m_fullbufsize); return 0; } else if (!ISPOWEROFTWO(unit->m_audiosize)) { Print("FFTBase_Ctor error: audio frame size (%i) not a power of two.\n", unit->m_audiosize); return 0; } else if (unit->m_audiosize < SC_FFT_MINSIZE || (((int)(unit->m_audiosize / unit->mWorld->mFullRate.mBufLength)) * unit->mWorld->mFullRate.mBufLength != unit->m_audiosize)) { Print("FFTBase_Ctor error: audio frame size (%i) not a multiple of the block size (%i).\n", unit->m_audiosize, unit->mWorld->mFullRate.mBufLength); return 0; } unit->m_pos = 0; ZOUT0(0) = ZIN0(0); return 1; }
void KeyState_next(KeyState *unit, int inNumSamples) { // minval, maxval, warp, lag uint8 *keys = (uint8*)unit->gstate->keys; int keynum = (int)ZIN0(0); #ifdef __APPLE__ int byte = (keynum >> 3) & 15; #else int byte = (keynum >> 3) & 31; #endif int bit = keynum & 7; int val = keys[byte] & (1 << bit); float minval = ZIN0(1); float maxval = ZIN0(2); float lag = ZIN0(3); float y1 = unit->m_y1; float b1 = unit->m_b1; if (lag != unit->m_lag) { unit->m_b1 = lag == 0.f ? 0.f : exp(log001 / (lag * unit->mRate->mSampleRate)); unit->m_lag = lag; } float y0 = val ? maxval : minval; ZOUT0(0) = y1 = y0 + b1 * (y1 - y0); unit->m_y1 = zapgremlins(y1); }
void FFTSubbandPower_Ctor(FFTSubbandPower *unit) { SETCALC(FFTSubbandPower_next); ZOUT0(0) = unit->outval = 0.; unit->m_square = ZIN0(2) > 0.f; unit->m_normfactor = 0.f; // ZIN0(1) tells us how many cutoffs we're looking for int numcutoffs = (int)ZIN0(1); int numbands = numcutoffs+1; unit->m_scalemode = (int)ZIN0(3); float * outvals = (float*)RTAlloc(unit->mWorld, numbands * sizeof(float)); for(int i=0; i<numbands; i++) { outvals[i] = 0.f; } unit->m_outvals = outvals; unit->m_cutoffs = (int*)RTAlloc(unit->mWorld, numcutoffs * sizeof(int)); unit->m_cutoff_inited = false; unit->m_numbands = numbands; }
void MouseY_next(MouseInputUGen *unit, int inNumSamples) { // minval, maxval, warp, lag float minval = ZIN0(0); float maxval = ZIN0(1); float warp = ZIN0(2); float lag = ZIN0(3); float y1 = unit->m_y1; float b1 = unit->m_b1; if (lag != unit->m_lag) { unit->m_b1 = lag == 0.f ? 0.f : (float)exp(log001 / (lag * unit->mRate->mSampleRate)); unit->m_lag = lag; } float y0 = gMouseUGenGlobals.mouseY; if (warp == 0.0) { y0 = (maxval - minval) * y0 + minval; } else { y0 = pow(maxval/minval, y0) * minval; } ZOUT0(0) = y1 = y0 + b1 * (y1 - y0); unit->m_y1 = zapgremlins(y1); }
void FrameCompare_Ctor(FrameCompare* unit) { SETCALC(FrameCompare_next); unit->magSum = 0.f, unit->numFrames = 0; ZOUT0(0) = unit->outVal = ZIN0(0); }
void MIDIUIUgen_next(MIDIUIUgen *unit, int inNumSamples) { uint8 device = ZIN0(0); uint8 type = ZIN0(1); uint8 channel = ZIN0(2); float minval = ZIN0(3); float maxval = ZIN0(4); float warp = ZIN0(5); float lag = ZIN0(6); float y1 = unit->m_y1; float b1 = unit->m_b1; if (lag != unit->m_lag) { unit->m_b1 = lag == 0.f ? 0.f : (float)exp(log001 / (lag * unit->mRate->mSampleRate)); unit->m_lag = lag; } float value = (float)(gMIDIUIUgenGlobals[device][type][channel]).value/(float)127; if (warp == 0.0) { value = (maxval - minval) * value + minval; } else { value = pow(maxval/minval, value) * minval; } ZOUT0(0) = y1 = value + b1 * (y1 - value); unit->m_y1 = zapgremlins(y1); }
void FFTPower_Ctor(FFTPower *unit) { SETCALC(FFTPower_next); ZOUT0(0) = unit->outval = 0.; unit->m_square = ZIN0(1) > 0.f; unit->m_normfactor = 0.f; }
void Onsets_Ctor(Onsets *unit) { if(ZIN0(8)>0) SETCALC(Onsets_next_rawodf); else SETCALC(Onsets_next); unit->m_needsinit = true; unit->m_ods = (OnsetsDS*) RTAlloc(unit->mWorld, sizeof(OnsetsDS) ); ZOUT0(0) = unit->outval = 0.f; }
void AmplitudeMod_Ctor(AmplitudeMod* unit) { //printf("AmplitudeMod_Reset\n"); SETCALC(AmplitudeMod_next); float clamp = ZIN0(1); unit->m_clampcoef = clamp == 0.0 ? 0.0 : exp(log1/(clamp * SAMPLERATE)); float relax = ZIN0(2); unit->m_relaxcoef = relax == 0.0 ? 0.0 : exp(log1/(relax * SAMPLERATE)); ZOUT0(0) = unit->m_previn = ZIN0(0); }
void FFTFlux_Ctor(FFTFlux_Unit *unit) { SETCALC(FFTFlux_next); unit->m_tempbuf = 0; unit->m_yesternorm = 1.0f; unit->m_yesterdc = 0.0f; unit->m_yesternyq = 0.0f; unit->m_normalise = ZIN0(1) > 0.f; // Whether we want to normalise or not unit->outval = 0.f; ZOUT0(0) = 0.f; }
void GlitchRHPF_Ctor(GlitchRHPF* unit) { //printf("GlitchRHPF_Reset\n"); if (unit->mBufLength == 1) { SETCALC(GlitchRHPF_next_1); } else { SETCALC(GlitchRHPF_next); }; unit->m_a0 = 0.f; unit->m_b1 = 0.f; unit->m_b2 = 0.f; unit->m_y1 = 0.f; unit->m_y2 = 0.f; unit->m_freq = 0.f; unit->m_reson = 0.f; ZOUT0(0) = 0.f; }
void Loudness_next(Loudness *unit, int wrongNumSamples) { float fbufnum = ZIN0(0); //next FFT bufffer ready, update //assuming at this point that buffer precalculated for any resampling if (fbufnum > -0.01f) Loudness_dofft(unit, (uint32)fbufnum); //always output sones //float outval= unit->m_sones; //printf("sones %f phontotal %f \n",outval, unit->m_phontotal); //control rate output ZOUT0(0)=unit->m_sones; }
void RedPhasor_Ctor(RedPhasor *unit) { if(unit->mCalcRate==calc_FullRate) { if(INRATE(0)==calc_FullRate) { if(INRATE(1)==calc_FullRate) { SETCALC(RedPhasor_next_aa); } else { SETCALC(RedPhasor_next_ak); } } else { SETCALC(RedPhasor_next_kk); } } else { SETCALC(RedPhasor_next_ak); } unit->m_previn= ZIN0(0); unit->ppdir= 1; ZOUT0(0)= unit->mLevel= ZIN0(2); }
void FFTPower_next(FFTPower *unit, int inNumSamples) { FFTAnalyser_GET_BUF float normfactor = unit->m_normfactor; bool square = unit->m_square; if(normfactor == 0.f){ if(square) unit->m_normfactor = normfactor = 1.f / powf(numbins + 2.f, 1.5f); else unit->m_normfactor = normfactor = 1.f / (numbins + 2.f); } SCComplexBuf *p = ToComplexApx(buf); // SCPolarBuf *p = ToPolarApx(buf); float total; if(square){ total = sc_abs(p->dc) * sc_abs(p->dc) + sc_abs(p->nyq) * sc_abs(p->nyq); for (int i=0; i<numbins; ++i) { float rabs = (p->bin[i].real); float iabs = (p->bin[i].imag); total += (rabs*rabs) + (iabs*iabs); } }else{ total = sc_abs(p->dc) + sc_abs(p->nyq); for (int i=0; i<numbins; ++i) { float rabs = (p->bin[i].real); float iabs = (p->bin[i].imag); total += sqrt((rabs*rabs) + (iabs*iabs)); } // for (int i=0; i<numbins; ++i) { // total += sc_abs(p->bin[i].mag); // } } // Store the val for output in future calls unit->outval = total * normfactor; ZOUT0(0) = unit->outval; }
void MouseButton_next(MouseInputUGen *unit, int inNumSamples) { // minval, maxval, warp, lag float minval = ZIN0(0); float maxval = ZIN0(1); float lag = ZIN0(2); float y1 = unit->m_y1; float b1 = unit->m_b1; if (lag != unit->m_lag) { unit->m_b1 = lag == 0.f ? 0.f : (float)exp(log001 / (lag * unit->mRate->mSampleRate)); unit->m_lag = lag; } float y0 = gMouseUGenGlobals.mouseButton ? maxval : minval; ZOUT0(0) = y1 = y0 + b1 * (y1 - y0); unit->m_y1 = zapgremlins(y1); }
void Graph_CalcTrace(Graph *inGraph) { uint32 numCalcUnits = inGraph->mNumCalcUnits; Unit **calcUnits = inGraph->mCalcUnits; scprintf("\nTRACE %d %s #units: %d\n", inGraph->mNode.mID, inGraph->mNode.mDef->mName, numCalcUnits); for (uint32 i=0; i<numCalcUnits; ++i) { Unit *unit = calcUnits[i]; scprintf(" unit %d %s\n in ", i, (char*)unit->mUnitDef->mUnitDefName); for (uint32 j=0; j<unit->mNumInputs; ++j) { scprintf(" %g", ZIN0(j)); } scprintf("\n"); (unit->mCalcFunc)(unit, unit->mBufLength); scprintf(" out"); for (uint32 j=0; j<unit->mNumOutputs; ++j) { scprintf(" %g", ZOUT0(j)); } scprintf("\n"); } inGraph->mNode.mCalcFunc = (NodeCalcFunc)&Graph_Calc; }
void KeyTrack_next(KeyTrack *unit, int wrongNumSamples) { //int numSamples = unit->mWorld->mFullRate.mBufLength; //float *output = ZOUT(0); float fbufnum = ZIN0(0)+0.001; //next FFT bufffer ready, update //assuming at this point that buffer precalculated for any resampling if (fbufnum > -0.01f) { // && ( ZIN0(3)<0.5) //unit->m_frame= unit->m_frame+1; KeyTrack_calculatekey(unit, (uint32)fbufnum); } //always output current best key float outval= unit->m_currentKey; //control rate output ZOUT0(0)=outval; }
void Crest_Ctor(Crest* unit) { SETCALC(Crest_next); unsigned int length = (unsigned int)ZIN0(1); // Fixed number of items to store in the ring buffer if(length==0) length=1; // ...because things would get painful in the stupid scenario of length 0 unit->m_circbuf = (float*)RTAlloc(unit->mWorld, length * sizeof(float)); unit->m_circbuf[0] = ZIN0(0); // Load first sample in... unit->m_circbufpos = 0U; unit->m_length = length; unit->m_notfullyet = true; // Only after first filled do we scan the whole buffer. Otherwise we scan up to and including the current position. if (INRATE(0) == calc_FullRate) { unit->m_realNumSamples = unit->mWorld->mFullRate.mBufLength; } else { unit->m_realNumSamples = 1; } ZOUT0(0) = unit->m_result = 1.f; // Necessarily 1 at first since only 1 sample received. No need to run calc func }
void FrameCompare_next(FrameCompare *unit, int inNumSamples) { PV_GET_BUF2_FCOMPARE float minTargetMag = 900000.f, maxTargetMag = 0.f; float magdiff, magweight, lmtemp, minmaxtemp, p1mag, p2mag, scaleFactor; float wOffset = ZIN0(2); SCPolarBuf *p1 = ToPolarApx(buf1); //rendered SCPolarBuf *p2 = ToPolarApx(buf2); //target scaleFactor = (numbins + 1) * 0.5; //hanning window only //Print("%f\n", p2->bin[100].mag / scaleFactor); for(int i = 0; i < numbins; ++i) { p2mag = p2->bin[i].mag / scaleFactor; minmaxtemp = (p2mag < 2e-42) ? log(2e-42) : log(fabs(p2mag)); minTargetMag = (minmaxtemp <= minTargetMag) ? minmaxtemp : minTargetMag; maxTargetMag = (minmaxtemp >= maxTargetMag) ? minmaxtemp : maxTargetMag; } for(int i = 0; i < numbins; ++i) { p1mag = p1->bin[i].mag / scaleFactor; p2mag = p2->bin[i].mag / scaleFactor; magdiff = fabs(p1mag) - fabs(p2mag); lmtemp = p2mag < 2e-42 ? log(2e-42) : log(fabs(p2mag)); magweight = (1 - wOffset) + (wOffset * ((lmtemp - minTargetMag) / fabs(minTargetMag - maxTargetMag))); unit->magSum = unit->magSum + (magdiff * magdiff * magweight); } unit->numFrames = unit->numFrames + 1; ZOUT0(0) = unit->outVal = unit->magSum/unit->numFrames; }
// calculation function for a control rate threshold argument void PhaseInIrm_next_k(PhaseInIrm *unit, int inNumSamples) { int lastState = unit->curstate; float meanRand; // get the pointer to the output buffer float threshBool = IN0(_threshBool); float callPeriod = IN0(_callPeriod); float restPeriod = IN0(_restPeriod); float inhibitMax = IN0(_inhibitMax); float inhibitDist = IN0(_inhibitDist); float playProb = IN0(_playProb); float restMode = IN0(_restMode); RGen& rgen = *unit->mParent->mRGen; //check for any inputs that have been changed if (unit->lastRestPeriod != restPeriod) { unit->restTime = restPeriod; //reset rest period }; unit->lastRestPeriod = restPeriod; // float sr = unit->mRate->mSampleRate; unit->callPeriod = callPeriod; //store vars for other functions switch (unit->curstate) { case listen1: //ENTRY if (unit->changeState) { updateScore(unit, false); }; //DURING //EXIT if(threshBool > 0) { //update score unit->curstate = call; //exit break; //environment is clear - we're ready to go } else { unit->curstate = inhibit1; //exit } break; case inhibit1: //ENTRY if (unit->changeState) { //get random value for thisTimeInhibited unit->timeInhibited = 0; unit->thisInhibit = randWithScaleAndDist(unit, inhibitMax, inhibitDist); }; //update time inhibited unit->timeInhibited = unit->timeInhibited + SAMPLEDUR; if (unit->timeInhibited >= unit->thisInhibit) { unit->timeInhibitedBeforeCall = unit->timeInhibitedBeforeCall + unit->thisInhibit; //update score updateScore(unit, false); unit->curstate = listen1; //exit }; break; case call: //entry into the state if (unit->changeState) { updateScore(unit, true); unit->timeInhibitedBeforeCall = 0; //update call timer unit->timeCallRest = 0; unit->callTrig = 1; //trig outputs during call period }; //during unit->timeCallRest = unit->timeCallRest + SAMPLEDUR; //increment time in current state if (unit->timeCallRest >= callPeriod) { unit->curstate = listen2; unit->callTrig = 0; //trig outputs during call period break; }; break; case listen2: if (threshBool > 0) { unit->curstate = rest; //not inhibited - exit } else { unit->curstate = inhibit2; //inhibited - go to inhibit 2 } break; case inhibit2: if (unit->changeState) { //positive or negative unit->addToRest = randWithScaleAndDist(unit, inhibitMax, inhibitDist); unit->addToRest = unit->addToRest * rgen.fcoin(); unit->timeInhibitedBeforeCall = unit->timeInhibitedBeforeCall + unit->addToRest; }; //EXIT unit->curstate = rest; break; case rest: if (unit->changeState) { //add accumulated rest time to rest if (restMode == 0) { //fixed restTime unit->restTime = restPeriod + unit->addToRest; } else if (restMode == 1) { //flexible restTime unit->restTime = unit->restTime + unit->addToRest; } //clear rest counter unit->timeCallRest = 0; }; //increment rest counter unit->timeCallRest = unit->timeCallRest + SAMPLEDUR; if (unit->timeCallRest >= unit->restTime) { unit->curstate = listen1; //EXIT }; break; default: //catches outliers //should throw an error here? break; }; //see if we've changed state if (unit->curstate != lastState) { unit->changeState = true; } else { unit->changeState = false; }; ZOUT0(0) = unit->callTrig; ZOUT0(1) = unit->score; ZOUT0(2) = unit->curstate; }
// Ordinary ClearUnitOutputs outputs zero, potentially telling the IFFT (+ PV UGens) to act on buffer zero, so let's skip that: void FFT_ClearUnitOutputs(FFT *unit, int wrongNumSamples) { ZOUT0(0) = -1; }
void BeatTrack2_Ctor(BeatTrack2* unit) { //unit->m_srate = unit->mWorld->mFullRate.mSampleRate; float kblocklength= unit->mWorld->mFullRate.mBufDuration; //seconds per control block unit->m_krlength= kblocklength; //N features per block over numphases*2 variants for one of 120 tempi, so need at least 120 blocks to complete unit->m_phaseaccuracy = ZIN0(3); //0.02; //20 msec resolution; could be argument of UGen unit->m_numphases = (int*)RTAlloc(unit->mWorld, g_numtempi * sizeof(int)); //unit->m_phases = (float**)RTAlloc(unit->mWorld, g_numtempi * sizeof(float*)); for (int j=0; j<g_numtempi; ++j) { float period= g_periods[j]; int num= (int)(period/unit->m_phaseaccuracy); //maximum will be 1.0/0.02 = 50 unit->m_numphases[j]=num; // // unit->m_phases[j]= (float*)RTAlloc(unit->mWorld, unit->m_numphases[j] * sizeof(float)); // // float phase=0.0; // // for (i=0; i<num; ++i) { // unit->m_phases[j][i] = phase; // phase += unit->m_phaseaccuracy; // } } unit->m_numfeatures = (int)(ZIN0(1)+0.001); //for efficiency unit->m_scores= (float*)RTAlloc(unit->mWorld, (2*unit->m_numfeatures) * sizeof(float)); unit->m_temporalwindowsize= ZIN0(2); //typically small, 2 seconds for fast reactions compared to 6 secs for BeatTrack unit->m_fullwindowsize = unit->m_temporalwindowsize + 1.0 + 0.1; //plus one to cover all phases of the 60bpm based period, and a further 0.1 for indexing safety; ie looking at areas around the point you're interested in unit->m_buffersize = (int)(unit->m_fullwindowsize/unit->m_krlength); //in control blocks //printf("loading test blocklength %f numfeatures %d temporal %f full %f blocks %d \n",unit->m_krlength, unit->m_numfeatures, unit->m_temporalwindowsize, unit->m_fullwindowsize, unit->m_buffersize); //float ** m_pastfeatures; //for each feature, a trail of last m_workingmemorysize values unit->m_pastfeatures = (float**)RTAlloc(unit->mWorld, unit->m_numfeatures * sizeof(float*)); for (int j=0; j<unit->m_numfeatures; ++j) { unit->m_pastfeatures[j]= (float*)RTAlloc(unit->mWorld, unit->m_buffersize * sizeof(float)); Clear(unit->m_buffersize, unit->m_pastfeatures[j]); //set all to zero at first //for (i=0; i<unit->m_buffersize; ++i) { // unit->m_pastfeatures[j][i] = 0.0; // } // } //main counter unit->m_counter= 0; //could avoid allocation by having a hard limit on unit->bestscore= (float*)RTAlloc(unit->mWorld, 4 * unit->m_numfeatures * sizeof(float)); unit->bestphase= (int*)RTAlloc(unit->mWorld, 4 * unit->m_numfeatures * sizeof(int)); unit->besttempo= (int*)RTAlloc(unit->mWorld, 4 * unit->m_numfeatures * sizeof(int)); unit->bestgroove= (int*)RTAlloc(unit->mWorld, 4 * unit->m_numfeatures * sizeof(int)); for (int i=0; i<4; ++i) { int basepos= i*unit->m_numfeatures; for (int j=0; j<unit->m_numfeatures; ++j) { unit->bestscore[basepos+j]= -9999.0; unit->bestphase[basepos+j]= 0; unit->besttempo[basepos+j]= 60; unit->bestgroove[basepos+j]= 0; } } unit->m_phase= 0.0; unit->m_period= 0.5; unit->m_groove= 0; unit->m_currtempo=2; unit->m_phaseperblock= unit->m_krlength/unit->m_period; unit->m_predictphase= 0.4f; unit->m_predictperiod = 0.3f; unit->m_outputphase= unit->m_phase; unit->m_outputtempo= unit->m_currtempo; unit->m_outputgroove= unit->m_groove; unit->m_outputphaseperblock= unit->m_phaseperblock; unit->m_calculationperiod= 0.5; //every half second; could also be additional argument to UGen unit->m_calculationschedule= 0.0; //printf("srate %f conversion factor %f frame period %f \n", unit->m_srate, unit->m_srateconversion, unit->m_frameperiod); int bufnum = (int)(ZIN0(5)+0.001f); if (bufnum >= unit->mWorld->mNumSndBufs) bufnum = 0; if (bufnum<0) unit->m_weightingscheme = bufnum<2 ? 0 : 1; else { SndBuf *buf = unit->mWorld->mSndBufs + bufnum; unit->m_tempoweights= buf; unit->m_weightingscheme=2; } //printf("bufnum %d weightingscheme %d check %f %f\n", bufnum, unit->m_weightingscheme, unit->m_tempoweights[0], unit->m_tempoweights[119]); unit->halftrig=0; unit->q1trig=0; unit->q2trig=0; unit->mCalcFunc = (UnitCalcFunc)&BeatTrack2_next; // initialize outputs ZOUT0(0) = 0.0; ZOUT0(1) = 0.0; ZOUT0(2) = 0.0; ZOUT0(3) = unit->m_outputtempo; ZOUT0(4) = unit->m_outputphase; ZOUT0(5) = unit->m_outputgroove; }
void BeatTrack2_next(BeatTrack2 *unit, int wrongNumSamples) { //keep updating feature memories unit->m_counter= (unit->m_counter+1)%(unit->m_buffersize); int busnum = (int)(ZIN0(0)+0.001f); //unit->m_features = unit->mWorld->mControlBus + busnum; float * features= unit->mWorld->mControlBus + busnum; //hmm, is this pointer guaranteed to stay the same? may have to update each time... for (int j=0; j<unit->m_numfeatures; ++j) { unit->m_pastfeatures[j][unit->m_counter]= features[j]; //unit->m_features[j]; } unit->m_calculationschedule += unit->m_krlength; //check for new calculation round if(unit->m_calculationschedule> unit->m_calculationperiod) { unit->m_calculationschedule -= unit->m_calculationperiod; //reset best scores and move old to previous slots for (int i=0; i<2; ++i) { int pos1= (2+i)*unit->m_numfeatures; int pos2= i*unit->m_numfeatures; for (int j=0; j<unit->m_numfeatures; ++j) { unit->bestscore[pos1+j]= unit->bestscore[pos2+j]; unit->bestscore[pos2+j]= -9999.0; unit->bestphase[pos1+j]= unit->bestphase[pos2+j]; unit->bestphase[pos2+j]= 0; unit->besttempo[pos1+j]= unit->besttempo[pos2+j]; unit->besttempo[pos2+j]= 60; } } //state 0 is do nothing unit->m_amortisationstate=1; unit->m_amortcount=0; unit->m_amortlength=g_numtempi*2; // //unit->m_amortisationsteps=0; //store essential data unit->m_startcounter = unit->m_counter; unit->m_currphase=unit->m_phase; } //keeps incrementing but will be reset with each calculation run //unit->m_amortisationsteps=unit->m_amortisationsteps+1; //if state nonzero do something switch(unit->m_amortisationstate) { case 0: break; //do nothing case case 1: //calculate acf calculatetemplate(unit,unit->m_amortcount >> 1, unit->m_amortcount %2); unit->m_amortcount=unit->m_amortcount+1; if(unit->m_amortcount==unit->m_amortlength) { unit->m_amortisationstate=2; //unit->m_amortlength=1; //unit->m_amortcount=0; } break; case 2: //done calculating template matches, now decide whether to follow through finaldecision(unit); unit->m_amortisationstate=0; break; default: break; } //test if impulse to output unit->m_phase+=unit->m_phaseperblock; //if(unit->m_counter%400==0) printf("phase %f period %f\n", unit->m_phase, unit->m_period); //if not locked, update output phase from model phase, else keep a separate output phase float lock= ZIN0(4); //printf("lock %f \n",lock); if(lock<0.5f) { unit->m_outputphase= unit->m_phase; unit->m_outputtempo= unit->m_currtempo; unit->m_outputgroove= unit->m_groove; unit->m_outputphaseperblock= unit->m_phaseperblock; } else { unit->m_outputphase+=unit->m_outputphaseperblock; } if (unit->m_phase >= 1.f) { unit->m_phase-= 1.f; } //0 is beat, 1 is quaver, 2 is semiquaver, 3 is actual current tempo in bps //so no audio accuracy with beats, just asap, may as well be control rate ZOUT0(0)=0.0; ZOUT0(1)=0.0; ZOUT0(2)=0.0; ZOUT0(3)=unit->m_outputtempo; //*0.016666667; ZOUT0(4)=unit->m_outputphase; ZOUT0(5)=unit->m_outputgroove; //output beat if (unit->m_outputphase >= 1.f) { //printf("beat \n"); unit->m_outputphase -= 1.f; ZOUT0(0)=1.0; ZOUT0(1)=1.0; ZOUT0(2)=1.0; unit->halftrig=0; unit->q1trig=0; unit->q2trig=0; } if (unit->m_outputphase>=0.5 && unit->halftrig==0) { ZOUT0(1)=1.0; ZOUT0(2)=1.0; unit->halftrig=1; } float groove= unit->m_outputgroove *0.07; if (unit->m_outputphase>=(0.25+groove) && unit->q1trig==0) { ZOUT0(2)=1.0; unit->q1trig=1; } if (unit->m_outputphase>=(0.75+groove) && unit->q2trig==0) { ZOUT0(2)=1.0; unit->q2trig=1; } }
void FFTSubbandPower_next(FFTSubbandPower *unit, int inNumSamples) { int numbands = unit->m_numbands; int numcutoffs = numbands - 1; // Multi-output equiv of FFTAnalyser_GET_BUF float fbufnum = ZIN0(0); if (fbufnum < 0.f) { for(int i=0; i<numbands; i++){ ZOUT0(i) = unit->m_outvals[i]; } return; } uint32 ibufnum = (uint32)fbufnum; World *world = unit->mWorld; SndBuf *buf; if (ibufnum >= world->mNumSndBufs) { int localBufNum = ibufnum - world->mNumSndBufs; Graph *parent = unit->mParent; if(localBufNum <= parent->localBufNum) { buf = parent->mLocalSndBufs + localBufNum; } else { buf = world->mSndBufs; } } else { buf = world->mSndBufs + ibufnum; } int numbins = (buf->samples - 2) >> 1; // End: Multi-output equiv of FFTAnalyser_GET_BUF int scalemode = unit->m_scalemode; float normfactor = unit->m_normfactor; bool square = unit->m_square; if(normfactor == 0.f){ if(square) unit->m_normfactor = normfactor = 1.f / powf(numbins + 2.f, 1.5f); else unit->m_normfactor = normfactor = 1.f / (numbins + 2.f); } // Now we create the integer lookup list, if it doesn't already exist int * cutoffs = unit->m_cutoffs; if(!unit->m_cutoff_inited){ float srate = world->mFullRate.mSampleRate; for(int i=0; i < numcutoffs; ++i) { cutoffs[i] = (int)(buf->samples * ZIN0(4 + i) / srate); //Print("Allocated bin cutoff #%d, at bin %d\n", i, cutoffs[i]); } unit->m_cutoff_inited = true; } SCComplexBuf *p = ToComplexApx(buf); // Now we can actually calculate the bandwise subtotals float total = sc_abs(p->dc); if(square){ total *= total; // square the DC val } int binaddcount = 1; // Counts how many bins contributed to the current band (1 because of the DC value) int curband = 0; float * outvals = unit->m_outvals; float magsq; for (int i=0; i<numbins; ++i) { if((curband != numbands) && (i >= cutoffs[curband])){ if(scalemode==1){ outvals[curband] = total * normfactor; }else{ if(square) outvals[curband] = total / powf((float)binaddcount, 1.5f); else outvals[curband] = total / binaddcount; } //Print("Finished off band %i while in bin %i\n", curband, i); ++curband; total = 0.f; binaddcount = 0; } float rabs = (p->bin[i].real); float iabs = (p->bin[i].imag); magsq = ((rabs*rabs) + (iabs*iabs)); if(square) total += magsq; else total += std::sqrt(magsq); ++binaddcount; } // Remember to output the very last (highest) band if(square) total += p->nyq * p->nyq; else total += sc_abs(p->nyq); // Pop the last one onto the end of the lovely list if(scalemode==1){ outvals[curband] = total * normfactor; }else{ if(square) outvals[curband] = total / powf((float)binaddcount + 1.f, 1.5f); // Plus one because of the nyq value else outvals[curband] = total / (binaddcount + 1); // Plus one because of the nyq value } // Now we can output the vals for(int i=0; i<numbands; i++) { ZOUT0(i) = outvals[i]; } }
void SpecFlatness_Ctor(SpecFlatness *unit) { SETCALC(SpecFlatness_next); ZOUT0(0) = unit->outval = 0.; unit->m_oneovern = 0.; }