// new SAOL translation attempt global { srate 44100; krate 8820; outchannels 1; ksig gkLFO, gkamp; } instr globalfade (risetime) { // p4 is rise AND decay time exports ksig gkamp; // WARNING: this will break if tempo goes too fast! // Time args are in seconds, not score beats!!! gkamp = kexpon(0.005, risetime, 1, dur - (risetime * 2), 1, risetime , 0.005); } instr globalLFO (startrate, endrate) { ksig lfo_freq; exports ksig gkLFO; imports table f1; lfo_freq = kline(startrate, dur, endrate); gkLFO = 0.5 + 0.5 * koscil(f1, lfo_freq); // normalized from 0 to 1 } instr pwm(initpitch, endpitch, moddepth) { // another try by PW // We simulate a square wave by overdriving a table index, // with a sine wav; thus, aliasing can be reduced by // scaling the amount of overdrive inversely with pitch. // It's not strictly band-limited, but it sounds pretty good. // We then simulate pulse-width modulation by // varying an offset to the index. imports table f1, f5; imports ksig gkLFO; imports ksig gkamp; ivar initfreq, endfreq, iantialias; ksig ksquareness; ksig kfreq; ksig f5len; // only needed at i-rate, but oh well. ksig knarrowness, kamp; asig index, aout, afiltered; initfreq = cpspch(initpitch); endfreq = cpspch(endpitch); kfreq = kline(initfreq, dur, endfreq); iantialias = 10; //recommended range is 4 to about 30 ksquareness = s_rate/(kfreq * iantialias); // squareness range: infinity yields a square, // less than 1 yields a pure sine wave. // This could really use a better algorithm, // I'd like the result to be larger than it is at low pitches // and smaller at high pitches. knarrowness = gkLFO * moddepth * ksquareness ; // Modulate! // Suggested range for moddepth is 0 to 1. index = knarrowness + (ksquareness * oscil(f1, kfreq)); f5len = ftlen(f5); index = index * f5len; // scale to length of table // Unlike in csound, index must be explicitly clipped. // Exceeding the size of the table will cause an error // instead of silently clipping. index = min(index, f5len -1); index = max(0, index); aout = tableread(f5, index); // f5 should be straight line +-1 // also, notice that we have to normalize the table index // manually. // Attempt to remove DC offset... better filter needed? afiltered = hipass(aout, 20); // and smooth it a bit. afiltered = lopass(afiltered, 8000); kamp = gkamp * kline(0, .01, 1, .02, .5, dur -.23, .5, .2, 0); output(afiltered * kamp); }