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 Onsets_next(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. SCPolarBuf *p = ToPolarApx(buf); OnsetsDS *ods = unit->m_ods; int odftype = (int)ZIN0(2); 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; }
void PV_DecorTransExtract_next(PV_DecorTransExtract *unit, int inNumSamples) { unsigned int numTransBins = 0; unsigned int diffBins = 0; float kVal = 0.0; float outputVal = 0.0; float gain = 1.0; // this macro gets an FFT chain if it has "fired" // otherwise, returns -1 and we go on our way... PV_GET_BUF // primes the ugen upon first calculation if (unit->initFirstCalc) { unit->numFreqBins = numbins; firstCalc(unit); unit->initFirstCalc = false; } // check that number of bins is static! this can't change! if (unit->numFreqBins != numbins) { printf("PV_DecorTransExtract: num bins mismatch!\n"); printf(" - fft chain must be of constant size with PV_DecoreTransExtract()\n"); printf(" - userbins = %d, numbins = %d\n", unit->numFreqBins, numbins); return; } else if (unit->lowFreqCutVal > unit->numFreqBins) { printf("PV_DecorTransExtract: low cut bin > number of bins\n"); printf("setting low cut to 0\n"); unit->lowFreqCutVal = 0; return; } SCPolarBuf *p = ToPolarApx(buf); // store bin values for (int i = unit->lowFreqCutVal; i < numbins; ++i) unit->prevBins[unit->prevBinsIdx][i] = p->bin[i].mag; // calculate average freq history for each bin for (int j = unit->lowFreqCutVal; j < numbins; ++j) unit->littleOmegaBins[unit->littleOmegaIdx][j] = calcAverageBins(unit, j); // reset transient flag memset(unit->transFlagBins, 0, unit->numFreqBins * sizeof(bool)); // printf("mark transients. little omega index = %d\n", unit->littleOmegaIdx); for (int i = unit->lowFreqCutVal; i < numbins; ++i) { unit->bigOmegaBins[i] = calcMinBin(unit, i); if (p->bin[i].mag > unit->alphaVal * unit->bigOmegaBins[i]) numTransBins++; else { if (numTransBins >= unit->dVal) { diffBins = (i - 1) - numTransBins; for (int j = (i - 1); j >= diffBins; --j) unit->transFlagBins[j] = true; } numTransBins = 0; } } // printf("release stage. little omega index = %d\n", unit->littleOmegaIdx); // this is where the lower freq bins are cut out if (unit->retTrans) for (int i = 0; i < unit->lowFreqCutVal; ++i) p->bin[i].mag = 0.0; for (int i = unit->lowFreqCutVal; i < numbins; ++i) { unit->releaseBins[i] = calcReleaseBin(unit, i); kVal = min(unit->releaseBins[i], p->bin[i].mag); outputVal = kVal / p->bin[i].mag; if (unit->retTrans) gain = 1.0 - outputVal; else gain = outputVal; // apply gain to output p->bin[i].mag = gain * p->bin[i].mag; } // increment circular queue of bins if (unit->prevBinsIdx < unit->iVal - 1) unit->prevBinsIdx++; else unit->prevBinsIdx = 0; if (unit->littleOmegaIdx < unit->jVal - 1) unit->littleOmegaIdx++; else unit->littleOmegaIdx = 0; }
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); // } }