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 vOut_next_a(IOUnit *unit, int inNumSamples) { //Print("Out_next_a %d\n", unit->mNumInputs); World *world = unit->mWorld; int bufLength = world->mBufLength; int numChannels = unit->mNumInputs - 1; float fbusChannel = ZIN0(0); if (fbusChannel != unit->m_fbusChannel) { unit->m_fbusChannel = fbusChannel; int busChannel = (int)fbusChannel; int lastChannel = busChannel + numChannels; if (!(busChannel < 0 || lastChannel > (int)world->mNumAudioBusChannels)) { unit->m_bus = world->mAudioBus + (busChannel * bufLength); unit->m_busTouched = world->mAudioBusTouched + busChannel; } } float *out = unit->m_bus; int32 *touched = unit->m_busTouched; int32 bufCounter = unit->mWorld->mBufCounter; for (int i=0; i<numChannels; ++i, out+=bufLength) { ACQUIRE_BUS_AUDIO((int32)fbusChannel + i); float *in = IN(i+1); if (touched[i] == bufCounter) { vadd(out, out, in, inNumSamples); } else { vcopy(out, in, inNumSamples); touched[i] = bufCounter; } //Print("out %d %g %g\n", i, in[0], out[0]); RELEASE_BUS_AUDIO((int32)fbusChannel + i); } }
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; }
void Crest_next(Crest* unit, int inNumSamples) { float *in = ZIN(0); float gate = ZIN0(1); // Get state and instance variables from the struct float* circbuf = unit->m_circbuf; int circbufpos = unit->m_circbufpos; int length = unit->m_length; float result = unit->m_result; bool notfullyet = unit->m_notfullyet; int realNumSamples = unit->m_realNumSamples; LOOP(realNumSamples, // Always add to the ringbuf, even if we're not calculating circbuf[circbufpos++] = std::fabs(ZXP(in)); if(circbufpos == length) { circbufpos = 0U; if(notfullyet) { notfullyet = unit->m_notfullyet = false; } } );
void LagControl_Ctor(LagControl* unit) { int numChannels = unit->mNumInputs; float **mapin = unit->mParent->mMapControls + unit->mSpecialIndex; char * chunk = (char*)RTAlloc(unit->mWorld, numChannels * 2 * sizeof(float)); unit->m_y1 = (float*)chunk; unit->m_b1 = unit->m_y1 + numChannels; for (int i=0; i<numChannels; ++i, mapin++) { unit->m_y1[i] = **mapin; float lag = ZIN0(i); unit->m_b1[i] = lag == 0.f ? 0.f : (float)exp(log001 / (lag * unit->mRate->mSampleRate)); } if (unit->mNumOutputs == 1) { SETCALC(LagControl_next_1); LagControl_next_1(unit, 1); } else { SETCALC(LagControl_next_k); LagControl_next_k(unit, 1); } }
void IFFT_Ctor(IFFT* unit){ int winType = sc_clip((int)ZIN0(1), -1, 1); // wintype may be used by the base ctor unit->m_wintype = winType; if(!FFTBase_Ctor(unit, 2)){ SETCALC(*ClearUnitOutputs); // These zeroes are to prevent the dtor freeing things that don't exist: unit->m_olabuf = 0; return; } // This will hold the transformed and progressively overlap-added data ready for outputting. unit->m_olabuf = (float*)RTAlloc(unit->mWorld, unit->m_audiosize * sizeof(float)); memset(unit->m_olabuf, 0, unit->m_audiosize * sizeof(float)); SCWorld_Allocator alloc(ft, unit->mWorld); unit->m_scfft = scfft_create(unit->m_fullbufsize, unit->m_audiosize, (SCFFT_WindowFunction)unit->m_wintype, unit->m_fftsndbuf->data, unit->m_fftsndbuf->data, kBackward, alloc); if (!unit->m_scfft) { SETCALC(*ClearUnitOutputs); unit->m_olabuf = 0; return; } // "pos" will be reset to zero when each frame comes in. Until then, the following ensures silent output at first: unit->m_pos = 0; //unit->m_audiosize; if (unit->mCalcRate == calc_FullRate) { unit->m_numSamples = unit->mWorld->mFullRate.mBufLength; } else { unit->m_numSamples = 1; } SETCALC(IFFT_next); ClearUnitOutputs(unit, 1); }
void BLOscWithComplexSinusoid_next(BLOscWithComplexSinusoid *unit, int inNumSamples) { float *out = ZOUT(0); float freqin = ZIN0(0); int32 loHarmonics = ZIN0(1); int32 numHarmonics = ZIN0(2); float slope = ZIN0(3); float evenOddRatio = ZIN0(4); int32 hiHarmonics = loHarmonics + numHarmonics - 1; // The highest harmonic index int32 hiHarmonicsPlusOne = hiHarmonics + 1; int32 loEvenHarmonics = loHarmonics%2 == 0? loHarmonics : loHarmonics + 1; // The lowest even harmonic index int32 hiEvenHarmonics = hiHarmonics%2 == 0? hiHarmonics : hiHarmonics - 1; // The highest even harmonic index int32 hiEvenHarmonicsPlusTwo = hiEvenHarmonics + 2; int32 numEvenHarmonics = (hiEvenHarmonics - loEvenHarmonics) / 2 + 1; //The total number of even harmonics float evenOddFactor = 1 - evenOddRatio; std::complex<double> evenOddFactorC(evenOddFactor, 0); float ampFactor = 0.99<slope&&slope<1.01? numHarmonics - evenOddFactor * numEvenHarmonics:((pow(slope,loHarmonics) - pow(slope,hiHarmonicsPlusOne)) / (1 - slope)) - (evenOddFactor * (pow(slope, loEvenHarmonics) - pow(slope, hiEvenHarmonicsPlusTwo)) / (1 - pow(slope, 2))); //ampFactor will be used to normalize the output amplitude. To avoid the denominator of this calculation to be 0 when slope = 1, the different formula is used when slope falls between 0.99 and 1.01. float phaseinc = ZIN0(0) * unit->partialTheta; float currentphase = unit->currentphase; std::complex<double> baseOsc; std::complex<double> r; std::complex<double> signalC; // signal as complex number float signalR; // signal as real number std::complex<double> oneC(1,0); std::complex<double> slopeC(slope, 0); float z; LOOP(inNumSamples, baseOsc = std::exp(std::complex<double>(0, currentphase)); r = slopeC * baseOsc; signalC = (std::pow(r, loHarmonics) - std::pow(r, hiHarmonicsPlusOne))/(oneC - r) - evenOddFactorC * (std::pow(r, loEvenHarmonics) - std::pow(r, hiEvenHarmonicsPlusTwo))/(oneC - std::pow(r, 2)); signalR = signalC.real(); z = signalR/ampFactor; currentphase += phaseinc; while (currentphase >= twopi_f) currentphase -= twopi_f; ZXP(out) = z; )
void AverageOutput_next( AverageOutput *unit, int inNumSamples ) { int i; float *in = IN(0); float *out = ZOUT(0); float trig = ZIN0(1); float prev_trig = unit->prev_trig; double average = unit->average; uint32 count = unit->count; if(prev_trig <= 0. && trig > 0.) { average = 0.; count = 0; } for (i=0; i<inNumSamples; ++i) { average = ((count * average) + *(in+i)) / (count + 1); ++count; ZXP(out) = average; } unit->prev_trig = trig; unit->count = count; unit->average = average; }
void LFDNoise3_next_k(LFDNoise3 *unit, int inNumSamples) { float *out = ZOUT(0); float freq = ZIN0(0); float a = unit->mLevelA; float b = unit->mLevelB; float c = unit->mLevelC; float d = unit->mLevelD; float phase = unit->mPhase; float dphase = freq * SAMPLEDUR; RGET LOOP1(inNumSamples, phase -= dphase; if (phase < 0) { phase = sc_wrap(phase, 0.f, 1.f); a = b; b = c; c = d; d = frand2(s1,s2,s3) * 0.8f; // limits max interpol. overshoot to 1. } ZXP(out) = cubicinterp(1.f - phase, a, b, c, d); )
void vIn_next_a(IOUnit *unit, int inNumSamples) { World *world = unit->mWorld; int bufLength = world->mBufLength; int numChannels = unit->mNumOutputs; float fbusChannel = ZIN0(0); if (fbusChannel != unit->m_fbusChannel) { unit->m_fbusChannel = fbusChannel; int busChannel = (uint32)fbusChannel; int lastChannel = busChannel + numChannels; if (!(busChannel < 0 || lastChannel > (int)world->mNumAudioBusChannels)) { unit->m_bus = world->mAudioBus + (busChannel * bufLength); unit->m_busTouched = world->mAudioBusTouched + busChannel; } } float *in = unit->m_bus; int32 *touched = unit->m_busTouched; int32 bufCounter = unit->mWorld->mBufCounter; for (int i=0; i<numChannels; ++i, in += bufLength) { ACQUIRE_BUS_AUDIO_SHARED((int32)fbusChannel + i); float *out = OUT(i); if (touched[i] == bufCounter) { vcopy(out, in, inNumSamples); } else { vfill(out, 0.f, inNumSamples); } RELEASE_BUS_AUDIO_SHARED((int32)fbusChannel + i); } }
void In_next_k(IOUnit *unit, int inNumSamples) { //Print("->In_next_k\n"); World *world = unit->mWorld; uint32 numChannels = unit->mNumOutputs; float fbusChannel = ZIN0(0); if (fbusChannel != unit->m_fbusChannel) { unit->m_fbusChannel = fbusChannel; uint32 busChannel = (uint32)fbusChannel; uint32 lastChannel = busChannel + numChannels; if (!(lastChannel > world->mNumControlBusChannels)) { unit->m_bus = world->mControlBus + busChannel; } } float *in = unit->m_bus; for (uint32 i=0; i<numChannels; ++i, in++) { float *out = OUT(i); *out = *in; } //Print("<-In_next_k\n"); }
void DWGPlucked_next(DWGPlucked *unit, int inNumSamples) { float *out = OUT(0); float freq = ZIN0(0); float amp = ZIN0(1); float trig = ZIN0(2); float pos = ZIN0(3); float c1 = ZIN0(4); float c3 = std::max(ZIN0(5),(float)1e-9); float *in = IN(6); unit->Loss.setcoeffs(freq,c1,c3); float lossdelay = unit->Loss.groupdelay(freq,SAMPLERATE); float deltot = SAMPLERATE/freq; float del1 = (deltot - lossdelay )*0.5 - 1; float PMAS,PMAS2; float PMENOS; for (int i=0; i < inNumSamples; ++i) { unit->DWGF[0].add(in[i],pos*del1); unit->DWGF[1].add(in[i],del1*(1-pos)); PMAS = unit->DWGF[0].delay(del1); PMAS2 = unit->Loss.filter(PMAS); PMENOS = unit->DWGF[1].delay(del1); unit->DWGF[1].push(-PMAS2); unit->DWGF[0].push(-PMENOS); out[i] = PMAS + PMAS2; } unit->Release(trig,out,inNumSamples); }
float relaxtime = ZIN0(3); int medspan = (int)ZIN0(6); if(unit->m_needsinit){ // Init happens here because we need to be sure about FFT size. unit->m_odsdata = (float*) RTAlloc(unit->mWorld, onsetsds_memneeded(odftype, buf->samples, medspan) ); onsetsds_init(ods, unit->m_odsdata, ODS_FFT_SC3_POLAR, odftype, buf->samples, medspan, FULLRATE); onsetsds_setrelax(ods, relaxtime, buf->samples>>1); unit->m_needsinit = false; } // Here is the best place to set parameters - after init is ensured // These are "painless" to set: ods->thresh = ZIN0(1); ods->floor = ZIN0(4); ods->mingap = (int)ZIN0(5); ods->whtype = (int)ZIN0(7); // Now to process unit->outval = onsetsds_process(ods, (float*) p); ZOUT0(0) = unit->outval; } void Onsets_next_rawodf(Onsets *unit, int inNumSamples) { Onsets_GET_BUF // In practice, making the polar conversion here in SC is more efficient because SC provides a lookup table method.
void CheckBadValues_next(CheckBadValues* unit, int inNumSamples) { float *in = ZIN(0); float *out = ZOUT(0); float id = ZIN0(1); int post = (int) ZIN0(2); float samp; int classification; switch(post) { case 1: // post a line on every bad value LOOP(inNumSamples, samp = ZXP(in); classification = sc_fpclassify(samp); switch (classification) { case FP_INFINITE: printf("Infinite number found in Synth %d, ID: %d\n", unit->mParent->mNode.mID, (int)id); ZXP(out) = 2; break; case FP_NAN: printf("NaN found in Synth %d, ID: %d\n", unit->mParent->mNode.mID, (int)id); ZXP(out) = 1; break; case FP_SUBNORMAL: printf("Denormal found in Synth %d, ID: %d\n", unit->mParent->mNode.mID, (int)id); ZXP(out) = 3; break; default: ZXP(out) = 0; }; ); break; case 2: LOOP(inNumSamples, samp = ZXP(in); classification = CheckBadValues_fold_fpclasses(sc_fpclassify(samp)); if(classification != unit->prevclass) { if(unit->sameCount == 0) { printf("CheckBadValues: %s found in Synth %d, ID %d\n", CheckBadValues_fpclassString(classification), unit->mParent->mNode.mID, (int)id); } else { printf("CheckBadValues: %s found in Synth %d, ID %d (previous %d values were %s)\n", CheckBadValues_fpclassString(classification), unit->mParent->mNode.mID, (int)id, (int)unit->sameCount, CheckBadValues_fpclassString(unit->prevclass) ); }; unit->sameCount = 0; }; switch (classification) { case FP_INFINITE: ZXP(out) = 2; break; case FP_NAN: ZXP(out) = 1; break; case FP_SUBNORMAL: ZXP(out) = 3; break; default: ZXP(out) = 0; }; unit->sameCount++; unit->prevclass = classification; );
//calculation function once FFT data ready void Loudness_dofft(Loudness *unit, uint32 ibufnum) { World *world = unit->mWorld; //if (ibufnum >= world->mNumSndBufs) ibufnum = 0; SndBuf *buf; // = world->mSndBufs + ibufnum; //int numbins = buf->samples - 2 >> 1; //support LocalBuf 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; } LOCK_SNDBUF(buf); float * data= buf->data; float loudsum=0.0; float smask= ZIN0(1); float tmask= ZIN0(2); for (int k=0; k<unit->m_numbands; ++k){ int bandstart=eqlbandbins[k]; //int bandend=eqlbandbins[k+1]; int bandsize= eqlbandsizes[k]; int bandend= bandstart+bandsize; float bsum=0.0; float real, imag, power; int index; float lastpower=0.0; for (int h=bandstart; h<bandend;++h) { index = 2*h; real= data[index]; imag= data[index+1]; power = (real*real) + (imag*imag); //would involve spectral masking here power = sc_max(lastpower*smask,power); //sideways spectral masking with leaky integration lastpower= power; //psychophysical sensation; within critical band, sum using a p metric, (sum m^p)^(1/p) //compresses the gain //power of three combination //bsum= bsum+(power*power*power); //won't sum up power very well //if(power>bsum) bsum=power; bsum= bsum+power; } //store recips of bandsizes? //why average? surely just take max or sum is better! //bsum= bsum/bandsize; //into dB, avoid log of 0 //float db= 10*log10((bsum*10000000)+0.001); //float db= 10*log10((bsum*32382)+0.001); //empricially derived 32382*2.348 float db= 10*log10((bsum*76032.936f)+0.001f); //correct multipler until you get loudness output of 1! //correcting for power of three combination //bsum=bsum+0.001; //4.8810017610244 = log10(76032.936) //float db= 10*((0.33334*log10(bsum)) + 4.8810017610244); //correct multipler until you get loudness output of 1! //printf("bsum %f db %f \n",bsum,db); //convert via contour if(db<contours[k][0]) db=0; else if (db>contours[k][10]) db=phons[10]; else { float prop=0.0; int j; for (j=1; j<11; ++j) { if(db<contours[k][j]) { prop= (db-contours[k][j-1])/(contours[k][j]-contours[k][j-1]); break; } if(j==10) prop=1.0; } db= (1.f-prop)*phons[j-1]+ prop*phons[j]; //printf("prop %f db %f j %d\n",prop,db,j); } //spectralmasking, 6dB drop per frame? //try also with just take db unit->m_ERBbands[k] = sc_max(db, (unit->m_ERBbands[k]) - tmask); //printf("db %f erbband %f \n",db, unit->m_ERBbands[k]); //must sum as intensities, not dbs once corrected, pow used to be other way around //loudsum+= ((pow(10, 0.1*unit->m_ERBbands[k])-0.001)*0.0000308813538386); // loudsum+= ((pow(10, 0.1*unit->m_ERBbands[k])-0.001)); //multiplier not needed since invert below; can trust no overflow? } //total excitation, correct back to dB scale in phons //float phontotal= 10*log10((loudsum*32382)+0.001); float phontotal= 10*log10((loudsum)+0.001); //didn't use divisor above, so no need to restore here //unit->m_phontotal= phontotal; //now to sones: /* from Praat: Excitation.c Sones = 2 ** ((Phones - 40) / 10) */ unit->m_sones= pow (2.f, (phontotal - 40) / 10); //printf("phontotal %f sones %f \n",phontotal, unit->m_sones); //about 5 times per second //if((unit->m_triggerid) && ((unit->m_frame%2==0))) SendTrigger(&unit->mParent->mNode, unit->m_triggerid, bestkey); }
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 ArneodoCoulletTresser_next(ArneodoCoulletTresser *unit, int inNumSamples) { float *xout = ZOUT(0); float *yout = ZOUT(1); float *zout = ZOUT(2); float freq = ZIN0(0); double alpha = ZIN0(1); double h = ZIN0(2); double x0 = ZIN0(3); double y0 = ZIN0(4); double z0 = ZIN0(5); double xn = unit->xn; double yn = unit->yn; double zn = unit->zn; float counter = unit->counter; double xnm1 = unit->xnm1; double ynm1 = unit->ynm1; double znm1 = unit->znm1; double frac = unit->frac; float samplesPerCycle; double slope; if(freq < unit->mRate->mSampleRate){ samplesPerCycle = unit->mRate->mSampleRate / sc_max(freq, 0.001f); slope = 1.f / samplesPerCycle; } else { samplesPerCycle = 1.f; slope = 1.f; } // reset if start values change if((unit->x0 != x0) || (unit->y0 != y0) || (unit->z0 != z0)){ xnm1 = xn; ynm1 = yn; znm1 = zn; unit->x0 = xn = x0; unit->y0 = yn = y0; unit->z0 = zn = z0; } double dx = xn - xnm1; double dy = yn - ynm1; double dz = zn - znm1; for (int i=0; i<inNumSamples; ++i) { if(counter >= samplesPerCycle){ counter -= samplesPerCycle; frac = 0.f; xnm1 = xn; ynm1 = yn; znm1 = zn; double k1x, k2x, k3x, k4x, k1y, k2y, k3y, k4y, k1z, k2z, k3z, k4z, kxHalf, kyHalf, kzHalf; // 4th order Runge-Kutta approximate solution for differential equations k1x = h * (xnm1 * (1.1 - xnm1 / 2 - ynm1 / 2 - znm1 / 10)); k1y = h * (ynm1 * (-0.5 + xnm1 / 2 + ynm1 / 10 - znm1 / 10)); k1z = h * (znm1 * (alpha + 0.2 - alpha * xnm1 - ynm1 / 10 - znm1 / 10)); kxHalf = k1x * 0.5; kyHalf = k1y * 0.5; kzHalf = k1z * 0.5; k2x = h * ((xnm1 + kxHalf) * (1.1 - (xnm1 + kxHalf) / 2 - (ynm1 + kyHalf) / 2 - (znm1 + kzHalf) / 10)); k2y = h * ((ynm1 + kyHalf) * (-0.5 + (xnm1 + kxHalf) / 2 + (ynm1 + kyHalf) / 10 - (znm1 + kzHalf) / 10)); k2z = h * ((znm1 + kzHalf) * (alpha + 0.2 - alpha * (xnm1 + kxHalf) - (ynm1 + kyHalf) / 10 - (znm1 + kzHalf) / 10)); kxHalf = k2x * 0.5; kyHalf = k2y * 0.5; kzHalf = k2z * 0.5; k3x = h * ((xnm1 + kxHalf) * (1.1 - (xnm1 + kxHalf) / 2 - (ynm1 + kyHalf) / 2 - (znm1 + kzHalf) / 10)); k3y = h * ((ynm1 + kyHalf) * (-0.5 + (xnm1 + kxHalf) / 2 + (ynm1 + kyHalf) / 10 - (znm1 + kzHalf) / 10)); k3z = h * ((znm1 + kzHalf) * (alpha + 0.2 - alpha * (xnm1 + kxHalf) - (ynm1 + kyHalf) / 10 - (znm1 + kzHalf) / 10)); k4x = h * ((xnm1 + k3x) * (1.1 - (xnm1 + k3x) / 2 - (ynm1 + k3y) / 2 - (znm1 + k3z) / 10)); k4y = h * ((ynm1 + k3y) * (-0.5 + (xnm1 + k3x) / 2 + (ynm1 + k3y) / 10 - (znm1 + k3z) / 10)); k4z = h * ((znm1 + k3z) * (alpha + 0.2 - alpha * (xnm1 + k3x) - (ynm1 + k3y) / 10 - (znm1 + k3z) / 10)); xn = xn + (k1x + 2.0*(k2x + k3x) + k4x) * ONESIXTH; yn = yn + (k1y + 2.0*(k2y + k3y) + k4y) * ONESIXTH; zn = zn + (k1z + 2.0*(k2z + k3z) + k4z) * ONESIXTH; dx = xn - xnm1; dy = yn - ynm1; dz = zn - znm1; } counter++; ZXP(xout) = (xnm1 + dx * frac) * 0.5f; ZXP(yout) = (ynm1 + dy * frac) * 0.5f; ZXP(zout) = (znm1 + dz * frac) * 1.0f; frac += slope; } unit->xn = xn; unit->yn = yn; unit->zn = zn; unit->counter = counter; unit->xnm1 = xnm1; unit->ynm1 = ynm1; unit->znm1 = znm1; unit->frac = frac; }
void LotkaVolterra_next(LotkaVolterra *unit, int inNumSamples) { float *xout = ZOUT(0); float *yout = ZOUT(1); float freq = ZIN0(0); double a = ZIN0(1); double b = ZIN0(2); double c = ZIN0(3); double d = ZIN0(4); double h = ZIN0(5); double x0 = ZIN0(6); double y0 = ZIN0(7); double xn = unit->xn; double yn = unit->yn; float counter = unit->counter; double xnm1 = unit->xnm1; double ynm1 = unit->ynm1; double frac = unit->frac; float samplesPerCycle; double slope; if(freq < unit->mRate->mSampleRate){ samplesPerCycle = unit->mRate->mSampleRate / sc_max(freq, 0.001f); slope = 1.f / samplesPerCycle; } else { samplesPerCycle = 1.f; slope = 1.f; } // reset if start values change if((unit->x0 != x0) || (unit->y0 != y0)){ xnm1 = xn; ynm1 = yn; unit->x0 = xn = x0; unit->y0 = yn = y0; } double dx = xn - xnm1; double dy = yn - ynm1; for (int i=0; i<inNumSamples; ++i) { if(counter >= samplesPerCycle){ counter -= samplesPerCycle; frac = 0.f; xnm1 = xn; ynm1 = yn; double k1x, k2x, k3x, k4x, k1y, k2y, k3y, k4y, kxHalf, kyHalf; // 4th order Runge-Kutta approximate solution for differential equations k1x = h * (xnm1 * (a - b * ynm1)); k1y = h * (ynm1 * (c * xnm1 - d)); kxHalf = k1x * 0.5; kyHalf = k1y * 0.5; k2x = h * ((xnm1 + kxHalf) * (a - b * (ynm1 + kyHalf))); k2y = h * ((ynm1 + kyHalf) * (c * (xnm1 + kxHalf) - d)); kxHalf = k2x * 0.5; kyHalf = k2y * 0.5; k3x = h * ((xnm1 + kxHalf) * (a - b * (ynm1 + kyHalf))); k3y = h * ((ynm1 + kyHalf) * (c * (xnm1 + kxHalf) - d)); k4x = h * ((xnm1 + k3x) * (a - b * (ynm1 + k3y))); k4y = h * ((ynm1 + k3y) * (c * (xnm1 + k3x) - d)); xn = xn + (k1x + 2.0*(k2x + k3x) + k4x) * ONESIXTH; yn = yn + (k1y + 2.0*(k2y + k3y) + k4y) * ONESIXTH; dx = xn - xnm1; dy = yn - ynm1; } counter++; ZXP(xout) = (xnm1 + dx * frac) * 0.5f; ZXP(yout) = (ynm1 + dy * frac) * 0.5f; frac += slope; } unit->xn = xn; unit->yn = yn; unit->counter = counter; unit->xnm1 = xnm1; unit->ynm1 = ynm1; unit->frac = frac; }
void Convolution2_Ctor(Convolution2 *unit) { //require size N+M-1 to be a power of two unit->m_insize=(int)ZIN0(3); //could be input parameter // printf( "unit->m_insize %i\n", unit->m_insize ); // printf( "unit->mWorld->mFullRate.mBufLength %i\n", unit->mWorld->mFullRate.mBufLength ); //float fbufnum = ZIN0(1); uint32 bufnum = (int)ZIN0(1); //fbufnum; World *world = unit->mWorld; //before added check for LocalBuf //if (bufnum >= world->mNumSndBufs) bufnum = 0; // SndBuf *buf = world->mSndBufs + bufnum; SndBuf *buf = ConvGetBuffer(unit, bufnum, "Convolution2", 1); if(buf) { if ( unit->m_insize <= 0 ) // if smaller than zero, equal to size of buffer unit->m_insize=buf->frames; //could be input parameter unit->m_fftsize=2*(unit->m_insize); //printf("hello %i, %i\n", unit->m_insize, unit->m_fftsize); //just use memory for the input buffers and fft buffers int insize = unit->m_insize * sizeof(float); int fftsize = unit->m_fftsize * sizeof(float); // // unit->m_inbuf1 = (float*)RTAlloc(unit->mWorld, insize); //// unit->m_inbuf2 = (float*)RTAlloc(unit->mWorld, insize); // // unit->m_fftbuf1 = (float*)RTAlloc(unit->mWorld, fftsize); // unit->m_fftbuf2 = (float*)RTAlloc(unit->mWorld, fftsize); unit->m_inbuf1 = (float*)RTAlloc(world, insize); unit->m_fftbuf1 = (float*)RTAlloc(world, fftsize); unit->m_fftbuf2 = (float*)RTAlloc(world, fftsize); unit->m_outbuf = (float*)RTAlloc(world, fftsize); unit->m_overlapbuf = (float*)RTAlloc(world, insize); memset(unit->m_outbuf, 0, fftsize); memset(unit->m_overlapbuf, 0, insize); //unit->m_log2n = LOG2CEIL(unit->m_fftsize); unit->m_pos = 0; memset(unit->m_outbuf, 0, fftsize); memset(unit->m_overlapbuf, 0, insize); SCWorld_Allocator alloc(ft, unit->mWorld); unit->m_scfft1 = scfft_create(unit->m_fftsize, unit->m_fftsize, kRectWindow, unit->m_fftbuf1, unit->m_fftbuf1, kForward, alloc); unit->m_scfft2 = scfft_create(unit->m_fftsize, unit->m_fftsize, kRectWindow, unit->m_fftbuf2, unit->m_fftbuf2, kForward, alloc); unit->m_scfftR = scfft_create(unit->m_fftsize, unit->m_fftsize, kRectWindow, unit->m_fftbuf1, unit->m_outbuf, kBackward, alloc); //calculate fft for kernel straight away memcpy(unit->m_fftbuf2, buf->data, insize); //zero pad second part of buffer to allow for convolution memset(unit->m_fftbuf2+unit->m_insize, 0, insize); scfft_dofft(unit->m_scfft2); unit->m_pos = 0; // unit->m_log2n = LOG2CEIL(unit->m_fftsize); // // int log2n = unit->m_log2n; // // //test for full input buffer // //unit->m_mask = unit->m_insize; // // //in place transform for now // rffts(unit->m_fftbuf2, log2n, 1, cosTable[log2n]); unit->m_prevtrig = 0.f; unit->m_prevtrig = ZIN0(2); // printf( "unit->m_insize %i\n", unit->m_insize ); // printf( "world->mFullRate.mBufLength %i\n", world->mFullRate.mBufLength ); if ( unit->m_insize >= world->mFullRate.mBufLength ) { // printf( "insize bigger than blocksize\n" ); SETCALC(Convolution2_next); } else { printf( "Convolution2 framesize smaller than blocksize \n" ); SETCALC(*ClearUnitOutputs); unit->mDone = true; //SETCALC(Convolution2_next2); } } else { unit->m_scfft2 = unit->m_scfft1 = unit->m_scfftR = NULL; } }
void Convolution2_next(Convolution2 *unit, int wrongNumSamples) { float *in1 = IN(0); float curtrig = ZIN0(2); float *inbuf1writepos = unit->m_inbuf1 + unit->m_pos; int numSamples = unit->mWorld->mFullRate.mBufLength; uint32 framesize = unit->m_framesize; uint32 framesize_f = framesize * sizeof(float); // copy input Copy(numSamples, inbuf1writepos, in1); unit->m_pos += numSamples; if (unit->m_prevtrig <= 0.f && curtrig > 0.f){ SndBuf *kernelbuf = ConvGetBuffer(unit,(uint32)ZIN0(1), "Convolution2", numSamples); if (!kernelbuf) return; LOCK_SNDBUF_SHARED(kernelbuf); // we cannot use a kernel larger than the fft size, so truncate if needed. the kernel may be smaller though. size_t kernelcopysize = sc_min(kernelbuf->frames, framesize); memcpy(unit->m_fftbuf2, kernelbuf->data, kernelcopysize * sizeof(float)); memset(unit->m_fftbuf2 + kernelcopysize, 0, (2 * framesize - kernelcopysize) * sizeof(float)); scfft_dofft(unit->m_scfft2); } if (unit->m_pos >= framesize) { //have collected enough samples to transform next frame unit->m_pos = 0; //reset collection counter // copy to fftbuf memcpy(unit->m_fftbuf1, unit->m_inbuf1, framesize_f); //zero pad second part of buffer to allow for convolution memset(unit->m_fftbuf1+unit->m_framesize, 0, framesize_f); scfft_dofft(unit->m_scfft1); //complex multiply time int numbins = unit->m_fftsize >> 1; float * p1= unit->m_fftbuf1; float * p2= unit->m_fftbuf2; p1[0] *= p2[0]; p1[1] *= p2[1]; //complex multiply for (int i=1; i<numbins; ++i) { float real,imag; int realind,imagind; realind= 2*i; imagind= realind+1; real= p1[realind]*p2[realind]- p1[imagind]*p2[imagind]; imag= p1[realind]*p2[imagind]+ p1[imagind]*p2[realind]; p1[realind] = real; p1[imagind]= imag; } //copy second part from before to overlap memcpy(unit->m_overlapbuf, unit->m_outbuf+unit->m_framesize, framesize_f); //inverse fft into outbuf scfft_doifft(unit->m_scfftR); }
void SOMTrain_next(SOMTrain *unit, int inNumSamples) { int traincountdown = unit->m_traincountdown; if(ZIN0(5) > 0.f){ // If gate > 0 // Get the buffer and some other standard stuff... SOM_GET_BUF // Get data inputs for(int chan=0; chan<numinputdims; ++chan){ inputdata[chan] = ZIN0(chan + 7); } // Get state from struct float mfactor = unit->m_mfactor; float weightfactor = unit->m_weightfactor; //RM float alpha = (float)unit->m_alpha; // get "nhood" as an integer, NB use ceil to make sure the neighbourhood errs on side of bigness int nhoodi = (int)ceil(unit->m_nhood); // squared distance comparisons are used in the neighbourhood-update function. The "plus one" is done so we can use "<" rather than "<=" later int nhoodisq = nhoodi * nhoodi + 1; // DO THE NEAREST-NEIGHBOUR SEARCH switch(numdims){ case 1: unit->m_reconsterror = SOM_findnearest_1d(bufData, inputdata, bestcoords, netsize, numinputdims); unit->m_writeloc = (float)SOM_SERIALISEINDEX_1D(bestcoords[0]); break; case 2: unit->m_reconsterror = SOM_findnearest_2d(bufData, inputdata, bestcoords, netsize, numinputdims); unit->m_writeloc = (float)SOM_SERIALISEINDEX_2D(bestcoords[0], bestcoords[1]); break; case 3: unit->m_reconsterror = SOM_findnearest_3d(bufData, inputdata, bestcoords, netsize, numinputdims); unit->m_writeloc = (float)SOM_SERIALISEINDEX_3D(bestcoords[0], bestcoords[1], bestcoords[2]); break; case 4: unit->m_reconsterror = SOM_findnearest_4d(bufData, inputdata, bestcoords, netsize, numinputdims); unit->m_writeloc = (float)SOM_SERIALISEINDEX_4D(bestcoords[0], bestcoords[1], bestcoords[2], bestcoords[3]); break; } if(traincountdown != 0){ //float alpha = weightfactor / (mfactor * unit->m_traincountup + 1.f); // mulier's approach float alpha = weightfactor * mfactor / (mfactor + unit->m_traincountup); // dan's empirical approach // UPDATE THE NODES switch(numdims){ case 1: SOMTrain_updatenodes_1d(bufData, inputdata, bestcoords, netsize, numinputdims, alpha, nhoodi, nhoodisq); break; case 2: SOMTrain_updatenodes_2d(bufData, inputdata, bestcoords, netsize, numinputdims, alpha, nhoodi, nhoodisq); break; case 3: SOMTrain_updatenodes_3d(bufData, inputdata, bestcoords, netsize, numinputdims, alpha, nhoodi, nhoodisq); break; case 4: SOMTrain_updatenodes_4d(bufData, inputdata, bestcoords, netsize, numinputdims, alpha, nhoodi, nhoodisq); break; } // Save state to struct. unit->m_nhood = unit->m_nhood - unit->m_nhooddelta; ++(unit->m_traincountup); unit->m_traincountdown = traincountdown = traincountdown - 1; if(traincountdown==0){ unit->mDone = true; } } // End still-training-check } // End gate check
void MedianSeparation_next( MedianSeparation *unit, int inNumSamples ) { int i,j; //calculate medians around pos-midpoint int medsize = unit->mediansize_; int mid = unit->midpoint_; float * mags = unit->magnitudes_; float * phases = unit->phases_; float * array = unit->collection_; int numbands = unit->fftbins_; int top = numbands-1; int pos = unit->magnitudeposition_; int midindex = (pos+medsize-mid)%medsize; float * vertical = unit->verticalmedians_; float * horizontal = unit->horizontalmedians_; float * magsnow = mags + (midindex*numbands); //cover outputs before early return in macro OUT0(0) = -1.f; OUT0(1) = -1.f; //0 normal, //1 vertical sort //2 horizontal sort //3 final output switch (unit->amortisationstep_) { case 0: { //printf("case 0 %f \n",ZIN0(0)); PV_GET_BUF //avoid output being overwritten by macro to pass input FFT buffer OUT0(0) = -1.f; OUT0(1) = -1.f; SCPolarBuf *polar = ToPolarApx(buf); //update data stored SCPolar * data = polar->bin; int base = unit->magnitudeposition_ * numbands; mags[base] = polar->dc; mags[base+numbands-1] = polar->nyq; //no need to set phases for these indices, since will always be 0.0 and initialised in constructor for (i=0; i<numbands-2; ++i) mags[base+i+1] = data[i].mag; base = unit->phaseposition_ * numbands; for (i=0; i<numbands-2; ++i) phases[base+i+1] = data[i].phase; uint32 bufnum1 = (uint32) IN0(1); //ZIN0(1); uint32 bufnum2 = (uint32) IN0(2); //ZIN0(2); //store for recall in step 3 unit->bufnum1_ = bufnum1; unit->bufnum2_ = bufnum2; //printf("store for recall %d %d what? %d uh? %d %f %f \n",bufnum1,bufnum2,(uint32) IN0(3), (uint32) ZIN0(3), IN0(1),IN0(2)); //will have returned early otherwise unit->amortisationstep_ =1; break; } case 1: { //printf("case 1\n"); float medianormean = ZIN0(7); //to avoid if inside loop, code copied twice with difference at point of array calculation (median or mean) if(medianormean<0.5f) { //printf("median calc vertical\n"); //vertical; easier to do in indexing for (i=0; i<numbands; ++i) { int lower = i-mid; if(lower<0) lower =0; int higher = i+mid; if(higher>top) higher = top; int number = higher-lower+1; float * pnow = magsnow + lower; //collect into array for (j=0; j<number; ++j) array[j] = pnow[j]; qsort(array,number,sizeof(float),cmp); //result is midpoint of magnitudes vertical[i] = array[number/2]; } } else { float sum; for (i=0; i<numbands; ++i) { int lower = i-mid; if(lower<0) lower =0; int higher = i+mid; if(higher>top) higher = top; int number = higher-lower+1; float * pnow = magsnow + lower; // // //collect into array // for (j=0; j<number; ++j) // array[j] = pnow[j]; // sum = 0.0f; //no need for intermediate array for (j=0; j<number; ++j) sum += pnow[j]; vertical[i] = sum/number; } } unit->amortisationstep_ = 2; break; } case 2: { //printf("case 2\n"); //horizontal, requires cross steps within 2D array float medianormean = ZIN0(7); if(medianormean<0.5f) { //printf("median calc horizontal\n"); for (i=0; i<numbands; ++i) { //no checks required for the medsize, but have to get correct indices //collect into array for (j=0; j<medsize; ++j) array[j] = mags[(j*numbands) + i]; qsort(array,medsize,sizeof(float),cmp); //result is midpoint of magnitudes horizontal[i] = array[mid]; } } else { //mean float sum; float recip = 1.0f/medsize; for (i=0; i<numbands; ++i) { //no checks required for the medsize, but have to get correct indices sum = 0.0f; //sum up directly, no need for array for (j=0; j<medsize; ++j) sum+= mags[(j*numbands) + i]; horizontal[i] = sum*recip; } } unit->amortisationstep_ = 3; break; } case 3: { //printf("case 3\n"); uint32 bufnum1 = unit->bufnum1_; //(uint32) ZIN0(1); uint32 bufnum2 = unit->bufnum2_; //(uint32) ZIN0(2); //printf("now recall %d %d \n",bufnum1,bufnum2); World *world = unit->mWorld; SndBuf *buf1, *buf2; if (bufnum1 >= world->mNumSndBufs) { int localBufNum = bufnum1 - world->mNumSndBufs; Graph *parent = unit->mParent; if(localBufNum <= parent->localBufNum) { buf1 = parent->mLocalSndBufs + localBufNum; } else { buf1 = world->mSndBufs; } } else { buf1 = world->mSndBufs + bufnum1; } LOCK_SNDBUF(buf1); if (bufnum2 >= world->mNumSndBufs) { int localBufNum = bufnum2 - world->mNumSndBufs; Graph *parent = unit->mParent; if(localBufNum <= parent->localBufNum) { buf2 = parent->mLocalSndBufs + localBufNum; } else { buf2 = world->mSndBufs; } } else { buf2 = world->mSndBufs + bufnum2; } LOCK_SNDBUF(buf2); int numbins1 = (buf1->samples >> 1) + 1; int numbins2 = (buf2->samples >> 1) + 1; //printf("check %d %d numbands %d further check %d %d \n",numbins1,numbins2,numbands,buf1->samples,buf2->samples); if((numbins1 == numbands) && (numbins2 ==numbands)) { int hardorsoft = ZIN0(5); //unit->hardorsoft_ = ZIN0(5); //unit->p_ = ZIN0(6); //to magnitude and phase representation SCPolarBuf *polar1 = ToPolarApx(buf1); SCPolarBuf *polar2 = ToPolarApx(buf2); SCPolar * data1 = polar1->bin; SCPolar * data2 = polar2->bin; //writing into the two output arrays of the buffers //magsnow already pointing to write place in magnitudes //magsnow = mags + (midindex*numbands); //+mid+2, adding so no danger, just add 1 int phaseindex = (unit->phaseposition_+1)%(mid+1); //midpoint is next one (about to be overwritten after increment below) float * phasesnow = phases + (phaseindex*numbands); //dc, nyquist, phase to zero //buf1,polar 1 is harmonic, 2 is percussive //0 larger of horizontal and vertical is winner, or 1 more subtle blend if(hardorsoft==0) { //hard //printf("hard calc \n"); if(horizontal[0]>vertical[0]) { polar1->dc = magsnow[0]; polar2->dc = 0.f; } else { polar2->dc = magsnow[0]; polar1->dc = 0.f; } if(horizontal[top]>vertical[top]) { polar1->nyq = magsnow[top]; polar2->nyq = 0.f; } else { polar2->nyq = magsnow[top]; polar1->nyq = 0.f; } int count = 0; //setting for (i=0; i<numbands-2; ++i) { int indexnow = i+1; //if(i==20) {data1[i].mag=1024; data2[i].mag=1024;} //else {data1[i].mag = 0.0f; data2[i].mag = 0.f;} if(horizontal[indexnow]>vertical[indexnow]) { ++count; data1[i].mag = magsnow[indexnow]; data1[i].phase = phasesnow[indexnow]; data2[i].mag = 0.0f; data2[i].phase = 0.0f; //phasesnow[i+1]; } else { data2[i].mag = magsnow[indexnow]; data2[i].phase = phasesnow[indexnow]; data1[i].mag = 0.0f; data1[i].phase = 0.0f; //phasesnow[i+1]; } // if(i<10) { // // printf("mag %d %f %f horiz %f vert %f further %f %f \n ",i, data1[i].mag,data2[i].mag,horizontal[indexnow],vertical[indexnow],polar1->bin[i].mag,polar2->bin[i].mag); // // } // } //printf("count %d \n",count); } else { //printf("I hope not!\n"); //soft, Wiener filtering float pfactor = ZIN0(6); float maskp, maskh, hp, pp, combine; //dc hp = powf(horizontal[0],pfactor); pp = powf(vertical[0],pfactor); combine = hp+pp; maskh = 0.f; maskp = 0.f; //watch for zeroes if(combine>0.00000000001f) { maskh = hp/combine; maskp = pp/combine; } polar1->dc = magsnow[0] * maskh; polar2->dc = magsnow[0] * maskp; //nyquist hp = powf(horizontal[top],pfactor); pp = powf(vertical[top],pfactor); combine = hp+pp; maskh = 0.f; maskp = 0.f; //watch for zeroes if(combine>0.00000000001f) { maskh = hp/combine; maskp = pp/combine; } polar1->nyq = magsnow[top] * maskh; polar2->nyq = magsnow[top] * maskp; //setting for (i=0; i<numbands-2; ++i) { int indexnow = i+1; hp = powf(horizontal[indexnow],pfactor); pp = powf(vertical[indexnow],pfactor); combine = hp+pp; //if(i<5) { // printf("mag %d %f %f %f %f %f \n",i ,horizontal[indexnow],vertical[indexnow],hp,pp,combine); //} maskh = 0.f; maskp = 0.f; //watch for zeroes if(combine>0.00000000001f) { maskh = hp/combine; maskp = pp/combine; } data1[i].mag = magsnow[indexnow] * maskh; data1[i].phase = phasesnow[indexnow]; data2[i].mag = magsnow[indexnow] * maskp; data2[i].phase = phasesnow[indexnow]; } } //printf("now output %d %d \n",bufnum1,bufnum2); //update output OUT0(0) = bufnum1; //2.f; //-1.f; //bufnum1; //-1; OUT0(1) = bufnum2; //-1; } unit->magnitudeposition_ = (unit->magnitudeposition_+1)%medsize; unit->phaseposition_ = (unit->phaseposition_+1)%(mid+1); unit->amortisationstep_ = 0; break; } default: //printf("default\n"); break; } //printf("actual output %f %f \n",OUT0(0),OUT0(1)); // for(j=0; j<inNumSamples; ++j) { // // output[j]= input[j]*0.1; //((float)j/inNumSamples); // } }
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 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 DWGPlucked2_next(DWGPlucked2 *unit, int inNumSamples) { float *out = OUT(0); float freq = ZIN0(0); float amp = ZIN0(1); float trig = ZIN0(2); float pos = ZIN0(3); float c1 = ZIN0(4); float c3 = std::max(ZIN0(5),(float)1e-9); float *in = IN(6); float mistune = ZIN0(8); float mp = sc_clip(ZIN0(9),0,1); float gc = ZIN0(10); unit->Loss.setcoeffs(freq,c1,c3); float lossdelay = unit->Loss.groupdelay(freq,SAMPLERATE); float deltot = SAMPLERATE/freq; float del1 = (deltot - lossdelay )*0.5 - 1; float freq2 = freq * mistune; unit->Loss2.setcoeffs(freq2,c1,c3); lossdelay = unit->Loss2.groupdelay(freq2,SAMPLERATE); deltot = SAMPLERATE/freq2; float del2 = (deltot - lossdelay )*0.5 - 1; float PMAS,PMAS2; float PMENOS,OUT1,OUT2; for (int i=0; i < inNumSamples; ++i) { unit->DWGF[0].add(in[i]*mp,pos*del1); unit->DWGF[1].add(in[i]*mp,del1*(1-pos)); PMAS = unit->DWGF[0].delay(del1); PMAS2 = unit->Loss.filter(PMAS); PMENOS = unit->DWGF[1].delay(del1); unit->DWGF[1].push(-PMAS2); unit->DWGF[0].push(-PMENOS); OUT1 = PMAS + PMAS2; unit->DWGF2[0].add(in[i]*(1-mp)+OUT1*gc,pos*del2); unit->DWGF2[1].add(in[i]*(1-mp)+OUT1*gc,del2*(1-pos)); PMAS = unit->DWGF2[0].delay(del2); PMAS2 = unit->Loss2.filter(PMAS); PMENOS = unit->DWGF2[1].delay(del2); unit->DWGF2[1].push(-PMAS2);//*0.9999); unit->DWGF2[0].push(-PMENOS); OUT2 = PMAS + PMAS2; out[i] = OUT1 + OUT2; } unit->Release(trig,out,inNumSamples); }
void SwitchDelay_next( SwitchDelay *unit, int inNumSamples ) { int i; float recval, readval, ratio; float *out = OUT(0); float *in = IN(0); float *buffer = unit->buffer; float drylevel = ZIN0(1); float wetlevel = ZIN0(2); float delayfactor = ZIN0(4); float prev_samp = unit->prev_samp; float offset_current = unit->offset_current; float offset_start = unit->offset_start; uint32 decaytime = (uint32)(ZIN0(3) * SAMPLERATE); uint32 bufsize = unit->bufsize; uint32 offset_timer = unit->offset_timer; uint32 writepos = unit->writepos; uint32 readpos = ((writepos - decaytime) + (bufsize)) % bufsize; char crossfading = unit->crossfading; if(decaytime != unit->decaytime) { // move the read pointer float newval, oldval, offset; newval = buffer[((readpos - decaytime) + bufsize) % bufsize]; oldval = buffer[readpos] + offset_current; // adding the current offset means that we can modulate again mid-crossfade. offset = oldval - newval; crossfading = 1; offset_start = offset; offset_current = offset; offset_timer = ENVLEN; } for(i=0; i < inNumSamples; ++i) { recval = in[i]; readval = buffer[readpos] + offset_current; recval = recval + (prev_samp * delayfactor); out[i] = (in[i] * drylevel) + (readval * wetlevel); buffer[writepos] = recval; prev_samp = readval; readpos = (readpos + 1) % bufsize; writepos = (writepos + 1) % bufsize; if(crossfading) { --offset_timer; if(offset_timer > 0.) { // still crossfading ratio = (offset_timer / ENVLEN); offset_current = offset_start * ratio; } else { // all done crossfading = 0; offset_current = 0.; } } } unit->crossfading = crossfading; unit->offset_start = offset_start; unit->offset_current = offset_current; unit->offset_timer = offset_timer; unit->decaytime = decaytime; unit->writepos = writepos; unit->readpos = readpos; unit->prev_samp = prev_samp; }
void Friction_next(Friction *unit, int inNumSamples) { float *out = OUT(0); float *in = IN(0); // Control-rate parameters float friction = ZIN0(1); float spring = ZIN0(2); float damp = ZIN0(3); float mass = ZIN0(4); float beltmass = ZIN0(5); // Retrive state float beltpos = unit->m_beltpos; float V = unit->m_V; float x = unit->m_x; float dx = unit->m_dx; // vars used in the loop float F_N, relspeed, F_f, drivingforce, F_s, F, ddx, oldbeltpos, oldV, beltaccn; bool sticking; // The normal force is just due to the weight of the object F_N = mass * 9.81f; float frictimesF_N = (friction * F_N); for (int i=0; i < inNumSamples; ++i) { oldbeltpos = beltpos; oldV = V; beltpos = in[i]; V = beltpos - oldbeltpos; beltaccn = V - oldV; // Calc the kinetic friction force relspeed = dx - V; if(relspeed==0.f) { F_f = 0.f; // No kinetic friction when no relative motion } else if (relspeed > 0.f) { F_f = frictimesF_N; } else { F_f = 0.f - frictimesF_N; } drivingforce = beltaccn * beltmass; // Calc the nonfriction force that would occur if moving along with the belt F_s = drivingforce - (damp * V) - (spring * x); // Decide if we're sticking or not sticking = sc_abs(F_s) < frictimesF_N; // NOW TO UPDATE THE MASS'S POSITION. // If sticking it's easy. Mass speed == belt speed if(sticking) { dx = V; } else { // Based on eq (5) F = F_s - F_f; ddx = F / mass; dx += ddx; } x += dx; // write the output out[i] = x; } // Store state unit->m_beltpos = beltpos; unit->m_V = V; unit->m_x = x; unit->m_dx = dx; }
void RosslerL_next(RosslerL *unit, int inNumSamples) { float *xout = ZOUT(0); float *yout = ZOUT(1); float *zout = ZOUT(2); float freq = ZIN0(0); double a = ZIN0(1); double b = ZIN0(2); double c = ZIN0(3); double h = ZIN0(4); double x0 = ZIN0(5); double y0 = ZIN0(6); double z0 = ZIN0(7); double xn = unit->xn; double yn = unit->yn; double zn = unit->zn; float counter = unit->counter; double xnm1 = unit->xnm1; double ynm1 = unit->ynm1; double znm1 = unit->znm1; double frac = unit->frac; float samplesPerCycle; double slope; if(freq < unit->mRate->mSampleRate){ samplesPerCycle = unit->mRate->mSampleRate / sc_max(freq, 0.001f); slope = 1.f / samplesPerCycle; } else { samplesPerCycle = 1.f; slope = 1.f; } if((unit->x0 != x0) || (unit->y0 != y0) || (unit->z0 != z0)){ xnm1 = xn; ynm1 = yn; znm1 = zn; unit->x0 = xn = x0; unit->y0 = yn = y0; unit->z0 = zn = z0; } double dx = xn - xnm1; double dy = yn - ynm1; double dz = zn - znm1; for (int i=0; i<inNumSamples; ++i) { if(counter >= samplesPerCycle){ counter -= samplesPerCycle; frac = 0.f; xnm1 = xn; ynm1 = yn; znm1 = zn; double k1x, k2x, k3x, k4x, k1y, k2y, k3y, k4y, k1z, k2z, k3z, k4z, kxHalf, kyHalf, kzHalf; // 4th order Runge-Kutta approximate solution for differential equations k1x = - (h * (ynm1 + znm1)); k1y = h * (xnm1 + a * ynm1); k1z = h * (b + znm1 * (xnm1 - c)); kxHalf = k1x * 0.5; kyHalf = k1y * 0.5; kzHalf = k1z * 0.5; k2x = - (h * (ynm1 + kyHalf + znm1 + kzHalf)); k2y = h * (xnm1 + kxHalf + a * (ynm1 + kyHalf)); k2z = h * (b + (znm1 + kzHalf) * (xnm1 + kxHalf - c)); kxHalf = k2x * 0.5; kyHalf = k2y * 0.5; kzHalf = k2z * 0.5; k3x = - (h * (ynm1 + kyHalf + znm1 + kzHalf)); k3y = h * (xnm1 + kxHalf + a * (ynm1 + kyHalf)); k3z = h * (b + (znm1 + kzHalf) * (xnm1 + kxHalf - c)); k4x = - (h * (ynm1 + k3y + znm1 + k3z)); k4y = h * (xnm1 + k3x + a * (ynm1 + k3y)); k4z = h * (b + (znm1 + k3z) * (xnm1 + k3x - c)); xn = xn + (k1x + 2.0*(k2x + k3x) + k4x) * ONESIXTH; yn = yn + (k1y + 2.0*(k2y + k3y) + k4y) * ONESIXTH; zn = zn + (k1z + 2.0*(k2z + k3z) + k4z) * ONESIXTH; dx = xn - xnm1; dy = yn - ynm1; dz = zn - znm1; } counter++; ZXP(xout) = (xnm1 + dx * frac) * 0.5f; ZXP(yout) = (ynm1 + dy * frac) * 0.5f; ZXP(zout) = (znm1 + dz * frac) * 1.0f; frac += slope; } unit->xn = xn; unit->yn = yn; unit->zn = zn; unit->counter = counter; unit->xnm1 = xnm1; unit->ynm1 = ynm1; unit->znm1 = znm1; unit->frac = frac; }
void Convolution2_next(Convolution2 *unit, int wrongNumSamples) { float *in1 = IN(0); //float *in2 = IN(1); float curtrig = ZIN0(2); float *out1 = unit->m_inbuf1 + unit->m_pos; // float *out2 = unit->m_inbuf2 + unit->m_pos; int numSamples = unit->mWorld->mFullRate.mBufLength; uint32 insize=unit->m_insize * sizeof(float); // copy input Copy(numSamples, out1, in1); unit->m_pos += numSamples; if (unit->m_prevtrig <= 0.f && curtrig > 0.f){ //float fbufnum = ZIN0(1); //int log2n2 = unit->m_log2n; //uint32 bufnum = (int)fbufnum; //printf("bufnum %i \n", bufnum); //World *world = unit->mWorld; //if (bufnum >= world->mNumSndBufs) bufnum = 0; //SndBuf *buf = world->mSndBufs + bufnum; SndBuf *buf = ConvGetBuffer(unit,(uint32)ZIN0(1), "Convolution2", numSamples); if (!buf) return; LOCK_SNDBUF_SHARED(buf); memcpy(unit->m_fftbuf2, buf->data, insize); memset(unit->m_fftbuf2+unit->m_insize, 0, insize); //rffts(unit->m_fftbuf2, log2n2, 1, cosTable[log2n2]); scfft_dofft(unit->m_scfft2); } if (unit->m_pos & unit->m_insize) { //have collected enough samples to transform next frame unit->m_pos = 0; //reset collection counter // copy to fftbuf //int log2n = unit->m_log2n; memcpy(unit->m_fftbuf1, unit->m_inbuf1, insize); //zero pad second part of buffer to allow for convolution memset(unit->m_fftbuf1+unit->m_insize, 0, insize); //if (unit->m_prevtrig <= 0.f && curtrig > 0.f) scfft_dofft(unit->m_scfft1); //in place transform for now // rffts(unit->m_fftbuf1, log2n, 1, cosTable[log2n]); //complex multiply time int numbins = unit->m_fftsize >> 1; //unit->m_fftsize - 2 >> 1; float * p1= unit->m_fftbuf1; float * p2= unit->m_fftbuf2; p1[0] *= p2[0]; p1[1] *= p2[1]; //complex multiply for (int i=1; i<numbins; ++i) { float real,imag; int realind,imagind; realind= 2*i; imagind= realind+1; real= p1[realind]*p2[realind]- p1[imagind]*p2[imagind]; imag= p1[realind]*p2[imagind]+ p1[imagind]*p2[realind]; p1[realind] = real; //p2->bin[i]; p1[imagind]= imag; } //copy second part from before to overlap memcpy(unit->m_overlapbuf, unit->m_outbuf+unit->m_insize, insize); //inverse fft into outbuf memcpy(unit->m_outbuf, unit->m_fftbuf1, unit->m_fftsize * sizeof(float)); //in place //riffts(unit->m_outbuf, log2n, 1, cosTable[log2n]); scfft_doifft(unit->m_scfftR); // DoWindowing(log2n, unit->m_outbuf, unit->m_fftsize); }
void PartConv_Ctor( PartConv* unit ) { unit->m_fftsize= (int) ZIN0(1); unit->m_nover2= unit->m_fftsize>>1; unit->m_inputbuf= (float*)RTAlloc(unit->mWorld, unit->m_fftsize * sizeof(float)); unit->m_spectrum= (float*)RTAlloc(unit->mWorld, unit->m_fftsize * sizeof(float)); SCWorld_Allocator alloc(ft, unit->mWorld); unit->m_scfft = scfft_create(unit->m_fftsize, unit->m_fftsize, kRectWindow, unit->m_inputbuf, unit->m_spectrum, kForward, alloc); //inverse unit->m_inputbuf2= (float*)RTAlloc(unit->mWorld, unit->m_fftsize * sizeof(float)); unit->m_spectrum2= (float*)RTAlloc(unit->mWorld, unit->m_fftsize * sizeof(float)); //in place this time unit->m_scifft = scfft_create(unit->m_fftsize, unit->m_fftsize, kRectWindow, unit->m_inputbuf2, unit->m_spectrum2, kBackward, alloc); //debug test: changing scale factors in case amplitude summation is a problem //unit->m_scfft->scalefac=1.0/45.254833995939; //unit->m_scifft->scalefac=1.0/45.254833995939; unit->m_output= (float*)RTAlloc(unit->mWorld, unit->m_fftsize * sizeof(float)); unit->m_outputpos=0; memset(unit->m_output, 0, unit->m_fftsize * sizeof(float)); memset(unit->m_inputbuf, 0, unit->m_fftsize * sizeof(float)); unit->m_pos=0; //get passed in buffer unit->m_fd_accumulate=NULL; uint32 bufnum = (uint32)ZIN0(2); SndBuf *buf; if (bufnum >= unit->mWorld->mNumSndBufs) { int localBufNum = bufnum - unit->mWorld->mNumSndBufs; Graph *parent = unit->mParent; if(localBufNum <= parent->localMaxBufNum) { buf = parent->mLocalSndBufs + localBufNum; } else { printf("PartConv Error: Invalid Spectral data bufnum %d \n", bufnum); SETCALC(*ClearUnitOutputs); unit->mDone = true; return; } } buf = unit->mWorld->mSndBufs + bufnum; unit->m_specbufnumcheck = bufnum; if (!buf->data) { //unit->mDone = true; printf("PartConv Error: Spectral data buffer not allocated \n"); SETCALC(*ClearUnitOutputs); unit->mDone = true; return; } unit->m_irspectra = buf->data; unit->m_fullsize = buf->samples; unit->m_partitions=buf->samples/(unit->m_fftsize); //should be exact //printf("another check partitions %d irspecsize %d fftsize %d \n", unit->m_partitions,unit->m_fullsize, unit->m_fftsize); if((buf->samples % unit->m_fftsize !=0) || (buf->samples==0)) { printf("PartConv Error: fftsize doesn't divide spectral data buffer size or spectral data buffer size is zero\n"); SETCALC(*ClearUnitOutputs); unit->mDone = true; return; } //CHECK SAMPLING RATE AND BUFFER SIZE unit->m_blocksize = unit->mWorld->mFullRate.mBufLength; //if(unit->m_blocksize!=64) printf("TPV complains: block size not 64, you have %d\n", unit->m_blocksize); unit->m_sr = unit->mWorld->mSampleRate; //if(unit->m_sr!=44100) printf("TPV complains: sample rate not 44100, you have %d\n", unit->m_sr); if(unit->m_nover2 % unit->m_blocksize !=0) { printf("PartConv Error: block size doesn't divide partition size\n"); SETCALC(*ClearUnitOutputs); unit->mDone = true; return; } else { //must be exact divisor int blocksperpartition = unit->m_nover2/unit->m_blocksize; unit->m_spareblocks = blocksperpartition-1; if(unit->m_spareblocks<1) { printf("PartConv Error: no spareblocks, amortisation not possible! \n"); SETCALC(*ClearUnitOutputs); unit->mDone = true; return; } //won't be exact unit->m_numamort = (unit->m_partitions-1)/unit->m_spareblocks; //will relate number of partitions to number of spare blocks unit->m_lastamort= (unit->m_partitions-1)- ((unit->m_spareblocks-1)*(unit->m_numamort)); //allow for error on last one unit->m_amortcount= -1; //starts as flag to avoid any amortisation before have first fft done unit->m_partitionsdone=1; //printf("Amortisation stats partitions %d nover2 %d blocksize %d spareblocks %d numamort %d lastamort %d \n", unit->m_partitions,unit->m_nover2, unit->m_blocksize, unit->m_spareblocks, unit->m_numamort, unit->m_lastamort); unit->m_fd_accumulate= (float*)RTAlloc(unit->mWorld, unit->m_fullsize * sizeof(float)); memset(unit->m_fd_accumulate, 0, unit->m_fullsize * sizeof(float)); unit->m_fd_accum_pos=0; SETCALC(PartConv_next); } }