Apology: I used global variables a lot in this effort, and in fact it was a dumb thing to do, predictably causing me to get mixed up when I reset one locally. In particular I wound up redefining N about once per file. Do what I say, not what I do. UTILITIES: Sound I/O: getsound, putsound, (obvious) normwav(wavin,maxsiz): scales wavin array presumably meant to become a wav array so that its maximum extent is + or - maxsiz. Always used here with maxsiz = 1. interpol(y,xi), interpolnd(y,xi): what is the y(x) value corresponding to interpolating the "index" value xi into it, for a single- or multi- dimensional array y, here presumed to be indexed by x. cbexp(x,e): raise a sine to exponent > or < 1, returns sine^exp of x. it was an idea for generating interesting sweep functions, not much used. make_input: create a simple ramp function as a wav file, ditto a sine wave, for use in debugging where plot commands are used instead of wavplay. Shows visually what happens to simple inputs...very useful. Conversions: I kept getting confused converting between the INDexes of arrays, milliseconds, the period of sine waves. Especially since the relation of indexes to time is governed by the sampling rate (global Fs). Hence: ang2ind(a,hz): what index < wavelength (for frequency of hz hertz) does angle a (<2pi) correspond to? hz2wlind(hz): how many indices correspond to a wavelength at hz hertz? (uses global Fs) ind2ang(i,hz,p): what angle at hz hertz corresponds to index i and phase p? time2ind(secs): how many indices correspond to a time interval? Effects: Newchorus: main script Bit of a mess. Give option of chorus or flanger. All effects use sweep and depth etc parameters, which live in arrays set up in Newinit. For chorus option, user chooses the delay, pitch, and vibrato voices he wants, puts their voice index into the corresponding for loops. The final chorus is sum of that many individual voices, each with one effect done to it. PLUS a single call to cascade, which is a pitch effect in series with a vibrato effect. In contrast, for flanging, only one for loop is executed but the output of that time thru is used as the input for the next time thru, so the effects are either fed back (say with a for v = [4 4 4], Delay voice 4 is applied and the output becomes input for two more times thru the effect. for v = [4 5], output of delay effect 4 is input to delay 5 (sounds from these two flangers are given on the assignment page). Note the flanger effect is just a delay with a smaller sweep depth (maximum delay) and in the example I saw the delay was always positive. Newinit: sets up voice parameters for Delay (and Flangers), Vibrato, and Pitch effects. Declares globals. NewDelay(i,v) : implements my version of a swept delay, used for flangers too. input is a 1:N index of the effected wav array we are creating, along with the index of the "voice array" (giving the delay effect parameters). Its output is the (usually non-integer) 'index' used to interpolate into the original wav array to create the value at index i of the effected array. Pitch(i,v): Same semantics and parameters: my version of pitch change, but has to be pretty much same effect, just parameterized differently and also implemented differently. cascade(dv, vv, wav): a hack that transforms the wav array first with pitch-effect voice dv, and then does a vibrato (voice vv) effect on the pitch-effected wave. It thus puts two effects in series, which the Newchorus script only does with flangers.