int PVTransBend::init(double *pp, int nargs) { _totalCalls = (int) pp[0]; if (_totalCalls <= 0) { return die("init_filter", "total_calls must be > 0"); } _currentCall = 0; _exptable = new double[2048]; if (nargs >= 3) { float *pvals = new float[nargs - 1]; float timeZero = pp[1]; float totalTime = pp[nargs - 2], prevTime = timeZero; int pIndex = 0; for (int arg=1; arg<nargs; arg+=2) { if (pp[arg] < prevTime) { return die("init_filter", "Time values must be in ascending order"); } pvals[pIndex] = (pp[arg] - timeZero) * (kArraySize-1) / totalTime; // position pvals[pIndex+1] = cpsoct(10.0 + octpch(pp[arg+1])) / cpsoct(10.0); // transp pIndex += 2; } struct gen gen; gen.size = 2048; gen.nargs = nargs-2; gen.pvals = &pvals[1]; // skip initial time value gen.array = _exptable; gen.slot = -1; // don't rescale gen5(&gen); delete [] pvals; return 0; } return die("init_filter", "PVTransBend usage: init_filter(total_calls, time0, intrvl0, ..., timeN, intrvlN)"); }
void TRANS3::doupdate() { double p[7]; update(p, 7); amp = p[3]; if (amptable) amp *= tablei(currentFrame(), amptable, amptabs); pctleft = (nargs > 6) ? p[6] : 0.5; float newtransp = p[4]; if (newtransp != transp) { transp = newtransp; _increment = cpsoct(10.0 + octpch(transp)) * oneover_cpsoct10; #ifdef DEBUG printf("_increment: %g\n", _increment); #endif } }
int TRANS::init(double p[], int n_args) { nargs = n_args; if (nargs < 5) return die("TRANS", "Usage: TRANS(start, inskip, dur, amp, trans[, inchan, pan])"); const float outskip = p[0]; const float inskip = p[1]; float dur = p[2]; if (dur < 0.0) dur = -dur - inskip; inchan = (nargs > 5) ? (int) p[5] : 0; pctleft = (nargs > 6) ? p[6] : 0.5; if (rtsetoutput(outskip, dur, this) == -1) return DONT_SCHEDULE; if (rtsetinput(inskip, this) == -1) return DONT_SCHEDULE; if (inchan >= inputChannels()) { return die("TRANS", "You asked for channel %d of a %d-channel file.", inchan, inputChannels()); } // to trigger first read in run() inframe = RTBUFSAMPS; initamp(dur, p, 3, 1); oneover_cpsoct10 = 1.0 / cpsoct(10.0); if (fastUpdate) // no transp updates _increment = cpsoct(10.0 + octpch(p[4])) * oneover_cpsoct10; return nSamps(); }
int TRANSBEND :: init(double p[], int n_args) { float outskip, inskip, dur, transp, interval = 0, total_indur, dur_to_read; float averageInc; int pgen; if (n_args < 5) { die("TRANSBEND", "Wrong number of args."); return(DONT_SCHEDULE); } outskip = p[0]; inskip = p[1]; dur = p[2]; amp = p[3]; pgen = (int) p[4]; inchan = (n_args > 5) ? (int) p[5] : 0; pctleft = (n_args > 6) ? p[6] : 0.5; if (dur < 0.0) dur = -dur - inskip; if (rtsetoutput(outskip, dur, this) == -1) return DONT_SCHEDULE; if (rtsetinput(inskip, this) == -1) return DONT_SCHEDULE; if (inchan >= inputChannels()) { return die("TRANSBEND", "You asked for channel %d of a %d-channel file.", inchan, inputChannels()); } pitchtable = floc(pgen); if (pitchtable) { int plen = fsize(pgen); float isum = 0; for (int loc = 0; loc < plen; loc++) { float pch = pitchtable[loc]; isum += octpch(pch); } interval = isum / plen; #ifdef DEBUG printf("average interval: %g\n", interval); #endif tableset(SR, dur, plen, ptabs); } else { die("TRANSBEND", "Unable to load pitch curve (table %d)!", pgen); return(DONT_SCHEDULE); } averageInc = (double) cpsoct(10.0 + interval) / cpsoct(10.0); #ifdef NOTYET total_indur = (float) m_DUR(NULL, 0); dur_to_read = dur * averageInc; if (inskip + dur_to_read > total_indur) { warn("TRANSBEND", "This note will read off the end of the input file.\n" "You might not get the envelope decay you " "expect from setline.\nReduce output duration."); /* no exit() */ } #endif /* total number of frames to read during life of inst */ in_frames_left = (int) (nSamps() * averageInc + 0.5); /* to trigger first read in run() */ inframe = RTBUFSAMPS; amptable = floc(1); if (amptable) { int amplen = fsize(1); tableset(SR, dur, amplen, tabs); } else rtcmix_advise("TRANSBEND", "Setting phrase curve to all 1's."); skip = (int) (SR / (float) resetval); return nSamps(); }
INLINE double midipch(double pch) { int midinote = (int) (((octpch(pch) - 3.0) * 12.0) + 0.5); return midinote; }
INLINE double cpspch(double pch) { double oct = octpch(pch); return cpsoct(oct); }
static float getIncrement(float pchOct) { return cpsoct(10.0 + octpch(pchOct)) * kOneover_cpsoct10; }
int STGRANR::run() { long i,attacksamps,j,thechunksamp,waitsamps,left,ngrains,rsamps; float *outp; float loc, ampfac, interval; double frac; const int frameCount = framesToRun(); if (in == NULL) /* first time, so allocate it */ in = new float [RTBUFSAMPS * inputChannels()]; // if ( (durhi*(float)SR) > frameCount()) // rtcmix_advise("STGRANR", "Grain duration larger than buffer."); outp = outbuf; /* point to inst private out buffer */ // figure out how many grains are in this chunk ngrains = (int)((float)frameCount/(rate*(float)SR)); if ( ngrains < 1 ) { if ( grainoverlap ) ngrains = 1; else { if ( (rrand()*.5+.5) < ((float)frameCount/(rate*(float)SR)) ) ngrains = 1; else ngrains = 0; } } thechunksamp = 0; if ( ngrains ) { for (i = 0; i < ngrains; i++) { attacksamps = frameCount/ngrains; // no grainoverlap yet transp = (float)prob(transplo, transpmid, transphi, transpti); interval = octpch(transp); increment = (double) cpsoct(10.0 + interval) / cpsoct(10.0); gdur = (float)prob(durlo,durmid,durhi,durti); grainsamps = (long)(gdur*(float)SR); if ( grainsamps > attacksamps) { overlapsample = grainsamps - attacksamps; // where to start in next attacksamps in envelop grainoverlap = 1; grainsamps = attacksamps; } ratevar = (float)prob(ratevarlo, ratevarmid, ratevarhi, ratevarti); waitsamps = (long)(ratevar*(float)(attacksamps - grainsamps)); spread = (float)prob(loclo,locmid,lochi,locti); tableset(SR, gdur, grlen, tabg); for ( j = 0; j < attacksamps; j++ ) { if (--branch < 0) { aamp = tablei(currentFrame(), amptable, tabs) * amp; branch = skip; } while (get_frame) { if (inframe >= attacksamps) { rtgetin(in, this, attacksamps * inputChannels()); inframe = 0; } oldersig[0] = oldsig[0]; oldsig[0] = newsig[0]; newsig[0] = in[(inframe * inputChannels())/* + inchan*/]; if ( inputChannels() == 2 ) { oldersig[1] = oldsig[1]; oldsig[1] = newsig[1]; newsig[1] = in[(inframe * inputChannels())+1]; } inframe++; incount++; if (counter - (double) incount < 0.5) get_frame = 0; } if(( j < grainsamps + waitsamps) && ( j > waitsamps )) { ampfac = tablei(j-waitsamps,grenvtable,tabg); frac = (counter - (double) incount) + 2.0; outp[0] = interp(oldersig[0], oldsig[0], newsig[0], frac) * ampfac; if (inputChannels() == 2 && outputChannels() == 2) // split stereo files between the channels outp[1] = interp(oldersig[1], oldsig[1], newsig[1], frac) * ampfac; } else outp[0] = 0.0; if (outputChannels() == 2 ) { // split stereo files between the channels outp[1] = (1.0 - spread) * outp[0]; outp[0] *= spread; } Instrument::increment(); // sample of whole note thechunksamp++; // sample within chunk outp += outputChannels(); counter += increment; /* keeps track of interp pointer */ if (counter - (double) incount >= -0.5) get_frame = 1; } totalgrains++; } } else { // ngrains = 0 for ( j = 0; j < frameCount; j++ ) { outp[0] = 0.0; if (outputChannels() == 2) outp[1] = 0.0; outp += outputChannels(); Instrument::increment(); // sample of whole note thechunksamp++; // sample within chunk } } // rtcmix_advise("STGRANR", "totalgrains: %ld\n",totalgrains); return thechunksamp; }
double stgran(float p[], int n_args) { int inchans, outchans, inchan; float indur, outdur, insk, outsk; long bgrainsamps, bgraindist, bgrainslide, inbgraindist; long i, nsamps, gstt_var, in_gstt_var, count, outcount, branch, skip; long s; /* sample number */ long egrainsamps, egraindist, egrainslide, inegraindist; long grainsamps, grainslide, graindistdiff; long ingrainsamps, ingrainslide, ingraindistdiff; long maxinsamps, maxoutsamps; float val, amp, aamp; float gdist_inc, in_gdist_inc; float tab1[2], tab2[2], tab3[2], tab4[2], tab5[2], tab6[2], tab7[2], tab8[2]; double *in_rate_shape, *rate_shape, *dur_shape, *transp_shape, *amp_shape; double *loc_shape, *envel, *slarray; float *inarr, *outarr; double gstt_per, in_gstt_per, lo, mid, hi, ti, sig, table_val; double slodiff, smiddiff, shidiff, stidiff; double ilodiff, imiddiff, ihidiff, itidiff; double dlodiff, dmiddiff, dhidiff, dtidiff; double alodiff, amiddiff, ahidiff, atidiff, grainamp; double tlodiff, tmiddiff, thidiff, ttidiff; double llodiff, lmiddiff, lhidiff, ltidiff, pctleft = 0.0; double tlobeg, tmidbeg, thibeg, tloend, tmidend, thiend; double voldsig = 0.0, oldsig, newsig, interval, increment; double counter = 0., frac; register int incount = 1, getflag = 1; outsk = p[0]; insk = p[1]; outdur = p[2]; indur = p[3]; amp = p[4]; setnote(insk, indur, INPUT); nsamps = setnote(outsk, outdur, OUTPUT); tlobeg = (double) octpch(p[33]); tmidbeg = (double) octpch(p[34]); thibeg = (double) octpch(p[35]); tloend = (double) octpch(p[37]); tmidend = (double) octpch(p[38]); thiend = (double) octpch(p[39]); inchan = (int) p[58]; inchans = sfchans(&sfdesc[INPUT]); if (inchan >= inchans) die("stgran", "You asked for channel %d of a %d-channel file.", inchan, inchans); outchans = sfchans(&sfdesc[OUTPUT]); if (outchans > 2) die("stgran", "Output file must be either mono or stereo."); /* allocate input and output buffers */ interval = MAX(thibeg, thiend); /* maximum transp. value (lin oct) */ increment = cpsoct(10.0 + interval) / cpsoct(10.0); hi = MAX(p[31], p[27]) * SR(); /* maximum grain duration */ maxinsamps = (long) (hi * increment + 1.0); inarr = malloc(maxinsamps * inchans * sizeof(float)); if (inarr == NULL) die("stgran", "Can't allocate input buffer."); maxoutsamps = (long) (hi + 1.0); outarr = malloc(maxoutsamps * outchans * sizeof(float)); if (outarr == NULL) die("stgran", "Can't allocate output buffer."); bgrainsamps = grainsamps = p[26] * SR(); bgraindist = p[7] * SR(); bgrainslide = grainslide = bgraindist - bgrainsamps; egrainsamps = p[30] * SR(); egraindist = p[8] * SR(); egrainslide = egraindist - egrainsamps; graindistdiff = egraindist - bgraindist; inbgraindist = p[5] * SR(); inegraindist = p[6] * SR(); ingraindistdiff = inegraindist - inbgraindist; in_rate_shape = floc(2); if (in_rate_shape == NULL) die("stgran", "You haven't made the grain input rate function (table 2)."); tableset(SR(), indur - p[6], fsize(2), tab2); rate_shape = floc(3); if (rate_shape == NULL) die("stgran", "You haven't made the grain output rate function (table 3)."); tableset(SR(), outdur - p[8], fsize(3), tab3); dur_shape = floc(4); if (dur_shape == NULL) die("stgran", "You haven't made the grain duration function (table 4)."); tableset(SR(), outdur - p[8], fsize(4), tab4); transp_shape = floc(5); if (transp_shape == NULL) die("stgran", "You haven't made the grain transposition function (table 5)."); tableset(SR(), outdur - p[8], fsize(5), tab5); amp_shape = floc(6); if (amp_shape == NULL) die("stgran", "You haven't made the grain amplitude function (table 6)."); tableset(SR(), outdur - p[8], fsize(6), tab6); loc_shape = floc(7); if (loc_shape == NULL) die("stgran", "You haven't made the grain stereo location function (table 7)."); tableset(SR(), outdur - p[8], fsize(7), tab7); envel = floc(8); /* tableset in sample loop */ if (envel == NULL) die("stgran", "You haven't made the grain envelope (table 8)."); /* get infile stt var zero/one differences */ ilodiff = (double) (p[13] - p[9]) / nsamps; imiddiff = (double) (p[14] - p[10]) / nsamps; ihidiff = (double) (p[15] - p[11]) / nsamps; itidiff = (double) (p[16] - p[12]) / nsamps; /* get outfile stt var zero/one differences */ slodiff = (double) (p[21] - p[17]) / nsamps; smiddiff = (double) (p[22] - p[18]) / nsamps; shidiff = (double) (p[23] - p[19]) / nsamps; stidiff = (double) (p[24] - p[20]) / nsamps; /* get dur zero/one differences */ dlodiff = (double) (p[29] - p[25]); dmiddiff = (double) (p[30] - p[26]); dhidiff = (double) (p[31] - p[27]); dtidiff = (double) (p[32] - p[28]); /* transp zero/one differences */ tlodiff = tloend - tlobeg; tmiddiff = tmidend - tmidbeg; thidiff = thiend - thibeg; ttidiff = (double) (p[40] - p[36]); /* amp zero/one differences */ alodiff = (double) (p[45] - p[41]); amiddiff = (double) (p[46] - p[42]); ahidiff = (double) (p[47] - p[43]); atidiff = (double) (p[48] - p[44]); /* loc zero/one differences */ llodiff = (double) (p[53] - p[49]); lmiddiff = (double) (p[54] - p[50]); lhidiff = (double) (p[55] - p[51]); ltidiff = (double) (p[56] - p[52]); if (p[57] > 0) srrand(p[57]); else srrand(.3); /* JGG: srrand takes unsigned int! */ skip = SR() / (float) resetval; /* control rate for amp curve */ gstt_var = in_gstt_var = 0; count = 0; aamp = amp; /* in case there is no setline function */ slarray = floc(1); if (slarray) { int len = fsize(1); tableset(SR(), outdur, len, tab1); } else rtcmix_advise("stgran", "Setting phrase curve to all 1's."); for (i = 0; i < nsamps; i++) { count++; table_val = (double) tablei(i, transp_shape, tab5); lo = tlobeg + (tlodiff * table_val); mid = tmidbeg + (tmiddiff * table_val); hi = thibeg + (thidiff * table_val); ti = p[36] + (ttidiff * table_val); lo = (lo > mid) ? mid : lo; hi = (hi < mid) ? mid : hi; interval = prob(lo, mid, hi, ti); /* in lin oct */ increment = cpsoct(10.0 + interval) / cpsoct(10.0); /* samp incr. */ /* calculate next grain duration */ table_val = (double) tablei(i, dur_shape, tab4); lo = p[25] + (dlodiff * table_val); mid = p[26] + (dmiddiff * table_val); hi = p[27] + (dhidiff * table_val); ti = p[28] + (dtidiff * table_val); lo = (lo > mid) ? mid : lo; hi = (hi < mid) ? mid : hi; grainsamps = (long) (prob(lo, mid, hi, ti) * SR()); tableset(SR(), grainsamps / SR(), fsize(8), tab8); /* calculate grain amplitude */ table_val = (double) tablei(i, amp_shape, tab6); lo = p[41] + (alodiff * table_val); mid = p[42] + (amiddiff * table_val); hi = p[43] + (ahidiff * table_val); ti = p[44] + (atidiff * table_val); lo = (lo > mid) ? mid : lo; hi = (hi < mid) ? mid : hi; grainamp = prob(lo, mid, hi, ti); /* calculate grain stereo location */ if (outchans > 1) { table_val = (double) tablei(i, amp_shape, tab7); lo = p[49] + (llodiff * table_val); mid = p[50] + (lmiddiff * table_val); hi = p[51] + (lhidiff * table_val); ti = p[52] + (ltidiff * table_val); lo = (lo > mid) ? mid : lo; hi = (hi < mid) ? mid : hi; pctleft = prob(lo, mid, hi, ti); } /* get percentage to vary next stt of grain */ lo = p[17] + slodiff * i; mid = p[18] + smiddiff * i; hi = p[19] + shidiff * i; ti = p[20] + stidiff * i; lo = (lo > mid) ? mid : lo; hi = (hi < mid) ? mid : hi; gstt_per = prob(lo, mid, hi, ti); gstt_var = (long) (gstt_per * (grainsamps + grainslide)); /* calculate grainslide */ gdist_inc = tablei(i, rate_shape, tab3); grainslide = (float) bgraindist + (float) graindistdiff * gdist_inc - grainsamps; ingrainsamps = grainsamps * increment; #ifdef DEBUG printf("ingrainsamps: %ld, maxinsamps: %ld\n", ingrainsamps, maxinsamps); assert(ingrainsamps <= maxinsamps); assert(grainsamps <= maxoutsamps); #endif bgetin(inarr, INPUT, ingrainsamps * inchans); /* read in grain */ ingrainslide = ((float) inbgraindist) * increment + (float) ingraindistdiff * increment - ingrainsamps; /* transpose the grain and write it to output file */ oldsig = inarr[inchan]; newsig = inarr[inchans + inchan]; incount = 1; outcount = 0; counter = 0; branch = 0; for (s = 0; s < grainsamps; s++) { while (getflag) { voldsig = oldsig; oldsig = newsig; newsig = inarr[(incount * inchans) + inchan]; incount++; if ((counter - (float) incount) < 0.5) { getflag = 0; } } /* update overall amp envelope at control rate */ while (!branch--) { if (slarray) aamp = tablei(i, slarray, tab1) * amp; branch = skip; } /* update grain envelope on every sample */ val = tablei(s, envel, tab8) * grainamp * aamp; frac = counter - incount + 2.0; /* the interp value */ sig = interp(voldsig, oldsig, newsig, frac) * val; if (outchans == 2) { outarr[outcount] = sqrt(pctleft) * sig; outarr[outcount + 1] = sqrt(1.0 - pctleft) * sig; } else outarr[outcount] = sig; counter += increment; /* keeps track of interp pointer */ if ((counter - (float) incount) >= -0.5) { getflag = 1; } outcount += outchans; } baddout(outarr, OUTPUT, grainsamps * outchans); inrepos(ingrainslide, INPUT); if ((i + grainslide + gstt_var + grainsamps) < 0) { outrepos(grainslide, OUTPUT); i += grainsamps; i += grainslide; } else { outrepos((grainslide + gstt_var), OUTPUT); i += grainsamps; i += grainslide; i += gstt_var; } } printf("\n%ld grains\n", count); endnote(OUTPUT); free(inarr); free(outarr); return 0.0; }