void LoopBuf_Ctor(LoopBuf *unit) { // input 1 => rate // input 2 => gate // if (INRATE(1) == calc_FullRate) { // if (INRATE(2) == calc_FullRate) { // SETCALC(LoopBuf_next_aa); // } else { // SETCALC(LoopBuf_next_ak); // } // } else { // if (INRATE(2) == calc_FullRate) { // SETCALC(LoopBuf_next_ka); // } else { SETCALC(LoopBuf_next_kk); // } // } unit->m_fbufnum = -1e9f; unit->m_prevgate = 0.; unit->m_phase = ZIN0(3); unit->m_playThrough = false; ClearUnitOutputs(unit, 1); }
//include local buffer test in one place static SndBuf * ConvGetBuffer(Unit * unit, uint32 bufnum, const char * ugenName, int inNumSamples) { SndBuf *buf; World *world = unit->mWorld; 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("%s: invalid buffer number (%d).\n", ugenName, bufnum); goto handle_failure; } } else { buf = world->mSndBufs + bufnum; } if (buf->data == NULL) { if (unit->mWorld->mVerbosity > -1) Print("%s: uninitialized buffer (%i).\n", ugenName, bufnum); goto handle_failure; } return buf; handle_failure: SETCALC(*ClearUnitOutputs); ClearUnitOutputs(unit, inNumSamples); unit->mDone = true; return NULL; }
void IFFT_next(IFFT *unit, int wrongNumSamples){ float *out = OUT(0); // NB not ZOUT0 // Load state from struct into local scope int pos = unit->m_pos; int fullbufsize = unit->m_fullbufsize; int audiosize = unit->m_audiosize; // int numSamples = unit->mWorld->mFullRate.mBufLength; int numSamples = unit->m_numSamples; float *olabuf = unit->m_olabuf; float fbufnum = ZIN0(0); // Only run the IFFT if we're receiving a new block of input data - otherwise just output data already received if (fbufnum >= 0.f){ // Ensure it's in cartesian format, not polar ToComplexApx(unit->m_fftsndbuf); float* fftbuf = unit->m_fftsndbuf->data; scfft_doifft(unit->m_scfft); // Then shunt the "old" time-domain output down by one hop int hopsamps = pos; int shuntsamps = audiosize - hopsamps; if(hopsamps != audiosize){ // There's only copying to be done if the position isn't all the way to the end of the buffer memcpy(olabuf, olabuf+hopsamps, shuntsamps * sizeof(float)); } // Then mix the "new" time-domain data in - adding at first, then just setting (copying) where the "old" is supposed to be zero. #if SC_DARWIN vDSP_vadd(olabuf, 1, fftbuf, 1, olabuf, 1, shuntsamps); #else // NB we re-use the "pos" variable temporarily here for write rather than read for(pos = 0; pos < shuntsamps; ++pos){ olabuf[pos] += fftbuf[pos]; } #endif memcpy(olabuf + shuntsamps, fftbuf + shuntsamps, (hopsamps) * sizeof(float)); // Move the pointer back to zero, which is where playback will next begin pos = 0; } // End of has-the-chain-fired // Now we can output some stuff, as long as there is still data waiting to be output. // If there is NOT data waiting to be output, we output zero. (Either irregular/negative-overlap // FFT firing, or FFT has given up, or at very start of execution.) if(pos >= audiosize){ ClearUnitOutputs(unit, numSamples); }else{ memcpy(out, olabuf + pos, numSamples * sizeof(float)); pos += numSamples; } unit->m_pos = pos; }
void TrigControl_Ctor(Unit* unit) { //Print("TrigControl_Ctor\n"); if (unit->mNumOutputs == 1) { SETCALC(TrigControl_next_1); } else { SETCALC(TrigControl_next_k); } ClearUnitOutputs(unit, 1); }
void InTrig_Ctor(IOUnit* unit) { World *world = unit->mWorld; unit->m_fbusChannel = -1.; if (unit->mCalcRate == calc_FullRate) { SETCALC(ClearUnitOutputs); ClearUnitOutputs(unit, 1); } else { SETCALC(InTrig_next_k); unit->m_bus = world->mControlBus; unit->m_busTouched = world->mControlBusTouched; InTrig_next_k(unit, 1); } }
static inline bool bbcheckBuffer(Unit * unit, const float * bufData, uint32 bufChannels, uint32 expectedChannels, int inNumSamples) { if (!bufData){ goto handle_failure; } if (expectedChannels > bufChannels) { if(unit->mWorld->mVerbosity > -1 && !unit->mDone){ Print("Buffer UGen channel mismatch: expected %i, yet buffer has %i channels\n", expectedChannels, bufChannels); } goto handle_failure; } return true; handle_failure: unit->mDone = true; ClearUnitOutputs(unit, inNumSamples); return false; }
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 GVerb_Ctor(GVerb *unit) { SETCALC(GVerb_next); float roomsize = unit->roomsize = IN0(1); float revtime = unit->revtime = IN0(2); float damping = unit->damping = IN0(3); float inputbandwidth = unit->inputbandwidth = 0.; //IN0(4); float spread = unit->spread = IN0(5); unit->drylevel = 0.; //IN0(6); unit->earlylevel = 0.; // IN0(7); unit->taillevel = 0.; //IN0(8); float maxroomsize = unit->maxroomsize = IN0(9); float maxdelay = unit->maxdelay = SAMPLERATE*maxroomsize/340.f; float largestdelay = unit->largestdelay = SAMPLERATE*roomsize/340.f; // make the inputdamper unit->inputdamper = make_damper(unit, 1. - inputbandwidth); //float ga = powf(10.f, -60.f/20.f); float ga = 0.001f; float n = SAMPLERATE * revtime; double alpha = unit->alpha = pow((double)ga, 1./(double)n); float gbmul[4] = {1.000, 0.816490, 0.707100, 0.632450}; for(int i = 0; i < FDNORDER; ++i){ float gb = gbmul[i] * largestdelay; if(i == 0){ unit->fdnlens[i] = nearestprime((int)gb, 0.5); } else { unit->fdnlens[i] = f_round(gb); } unit->fdngains[i] = -powf((float)alpha, unit->fdnlens[i]); } // make the fixeddelay lines and dampers for(int i = 0; i < FDNORDER; i++){ unit->fdndels[i] = make_fixeddelay(unit, (int)unit->fdnlens[i], (int)maxdelay+1000); unit->fdndamps[i] = make_damper(unit, damping); // damping is the same as fdndamping in source } // diffuser section float diffscale = (float)unit->fdnlens[3]/(210. + 159. + 562. + 410.); float spread1 = spread; float spread2 = 3.0 * spread; int b = 210; float r = 0.125541; int a = (int)(spread1 * r); int c = 210+159 + a; int cc = c - b; r = 0.854046; a = (int)(spread2 * r); int d = 210 + 159 + 562 + a; int dd = d - c; int e = 1341 - d; unit->ldifs[0] = make_diffuser(unit, f_round(diffscale * b), 0.75); unit->ldifs[1] = make_diffuser(unit, f_round(diffscale * cc), 0.75); unit->ldifs[2] = make_diffuser(unit, f_round(diffscale * dd), 0.625); unit->ldifs[3] = make_diffuser(unit, f_round(diffscale * e), 0.625); b = 210; r = -0.568366; a = (int)(spread1 * r); c = 210 + 159 + a; cc = c - b; r = -0.126815; a = (int)(spread2 * r); d = 210 + 159 + 562 + a; dd = d - c; e = 1341 - d; unit->rdifs[0] = make_diffuser(unit, f_round(diffscale * b), 0.75); unit->rdifs[1] = make_diffuser(unit, f_round(diffscale * cc), 0.75); unit->rdifs[2] = make_diffuser(unit, f_round(diffscale * dd), 0.625); unit->rdifs[3] = make_diffuser(unit, f_round(diffscale * e), 0.625); unit->taps[0] = 5 + (int)(0.410 * largestdelay); unit->taps[1] = 5 + (int)(0.300 * largestdelay); unit->taps[2] = 5 + (int)(0.155 * largestdelay); unit->taps[3] = 5; //+ f_round(0.000 * largestdelay); for(int i = 0; i < FDNORDER; i++) { unit->tapgains[i] = pow(alpha,(double)unit->taps[i]); } unit->tapdelay = make_fixeddelay(unit, 44000, 44000); // init the slope values unit->earlylevelslope = unit->drylevelslope = unit->taillevelslope = 0.f; ClearUnitOutputs(unit, 1); }
void PartConv_next( PartConv *unit, int inNumSamples ) { float *in = IN(0); float *out = OUT(0); int pos = unit->m_pos; //safety check if (!(unit->mWorld->mSndBufs + unit->m_specbufnumcheck)->data) { printf("PartConv Error: Spectral data buffer not allocated \n"); ClearUnitOutputs(unit, inNumSamples); SETCALC(*ClearUnitOutputs); unit->mDone = true; return; } float * input= unit->m_inputbuf; float * output= unit->m_output; int outputpos= unit->m_outputpos; //into input buffer memcpy(input+pos, in, inNumSamples * sizeof(float)); pos += inNumSamples; //if ready for new FFT int nover2 = unit->m_nover2; //assumes that blocksize perfectly divides windowsize if (pos == nover2) { //FFT this input, second half of input always zero //memset(input+unit->m_nover2, 0, sizeof(float)*unit->m_nover2); scfft_dofft(unit->m_scfft); //reset pos into input buffer pos=0; //reset outputpos outputpos= 0; float * spectrum = unit->m_spectrum; float * spectrum2 = unit->m_spectrum2; //multiply spectra and accumulate for all ir spectra across storage buffer int fftsize = unit->m_fftsize; int accumpos = unit->m_fd_accum_pos; float * accumbuffer = unit->m_fd_accumulate; float * irspectrum = unit->m_irspectra; int fullsize = unit->m_fullsize; //JUST DO FIRST ONE FOR NOW, AMORTISED FOR OTHERS //frames for (int i=0; i<1; ++i) { int irpos= (i*fftsize); int posnow= (accumpos+irpos)%fullsize; float * target= accumbuffer+posnow; float * ir= irspectrum+irpos; //real multiply for dc and nyquist target[0] += ir[0]*spectrum[0]; target[1] += ir[1]*spectrum[1]; //complex multiply for frequency bins for (int j=1; j<nover2; ++j) { int binposr= 2*j; int binposi= binposr+1; target[binposr] += (ir[binposr]*spectrum[binposr]) - (ir[binposi]*spectrum[binposi]); target[binposi] += (ir[binposi]*spectrum[binposr]) + (ir[binposr]*spectrum[binposi]); } } //IFFT this partition float * input2 = unit->m_inputbuf2; memcpy(input2, accumbuffer+accumpos, fftsize * sizeof(float)); scfft_doifft(unit->m_scifft); //shunt output data down and zero top bit memcpy(output, output+nover2, nover2 * sizeof(float)); memset(output+nover2, 0, nover2 * sizeof(float)); //sum into output for (int j=0; j<fftsize; ++j) output[j] += spectrum2[j]; //zero this partition memset(accumbuffer+accumpos, 0, fftsize * sizeof(float)); //ONLY DO AT END OF AMORTISATION???? no, amort code has extra -1 in indexing to cope //update partition counter accumpos= (accumpos+fftsize)%fullsize; unit->m_fd_accum_pos= accumpos; //set up for amortisation (calculate output for other partitions of impulse response) unit->m_amortcount=0; unit->m_partitionsdone=1; } else { //amortisation steps: //complex multiply of this new fft spectrum against existing irspectrums and sum to accumbuffer if (unit->m_amortcount>=0) { float * spectrum= unit->m_spectrum; //multiply spectra and accumulate for all ir spectra across storage buffer int fftsize= unit->m_fftsize; int nover2= unit->m_nover2; //int frames= unit->m_partitions; int accumpos= unit->m_fd_accum_pos; float * accumbuffer= unit->m_fd_accumulate; float * irspectrum= unit->m_irspectra; int fullsize= unit->m_fullsize; int starti, stopi; int number; if(unit->m_amortcount==(unit->m_spareblocks-1)) { number= unit->m_lastamort; }else{ number= unit->m_numamort; } starti= unit->m_partitionsdone-1; stopi= starti+number-1; //printf("amort check count %d starti %d stopi %d number %d framesdone %d \n",unit->m_amortcount, starti, stopi, number, unit->m_partitionsdone); unit->m_partitionsdone += number; ++unit->m_amortcount; for (int i=starti; i<=stopi; ++i) { int posnow= (accumpos+(i*fftsize))%fullsize; float * target= accumbuffer+posnow; int irpos= (i*fftsize); float * ir= irspectrum+irpos; //real multiply for dc and nyquist target[0]+= ir[0]*spectrum[0]; target[1]+= ir[1]*spectrum[1]; //complex multiply for frequency bins for (int j=1; j<nover2; ++j) { int binposr= 2*j; int binposi= binposr+1; target[binposr]+= (ir[binposr]*spectrum[binposr]) - (ir[binposi]*spectrum[binposi]); target[binposi]+= (ir[binposi]*spectrum[binposr]) + (ir[binposr]*spectrum[binposi]); } } } } //do this second! memcpy(out, output+outputpos, inNumSamples * sizeof(float)); //debugging tests: output values tend to be fftsize too big, probably due to complex multiply and also summation over all partitions // RGen& rgen = *unit->mParent->mRGen; // int testindex= rgen.irand(inNumSamples-1); // printf("inNumSamples %d testindex %d out %f output %f \n",inNumSamples, testindex, out[testindex], *(output+outputpos+testindex)); outputpos+=inNumSamples; unit->m_outputpos= outputpos; unit->m_pos= pos; }