As an illustration of my newly-released software I dug through the recent archive for something that would be easy and fun to implement in Moselle, and came across this post from forum stalwart Robert Bistow-Johnson.
The following is a Moselle program (or "patch") that implements the first half-dozen functions in Robert's series of soft-clippers. MIDI general controller 1 selects which clipping function to use, while general controller 2 selects the waveform to input. (The oscillator is spec'd as an LFO as the LFO doesn't scale its amplitude with pitch, which saved me a bit of typing.) Each of the functions is repeated in the Oscilloscope module so they can all be seen simultaneously, even though only one is heard at a time. See a screenshot of the Oscilloscope with waveforms and harmonic spectrum at: http://moselle.invisionzone.com/uploads/gallery/album_1/gallery_1_1_12533.gif The self-contained Moselle IDE is available for no-cost download at: http://moselle.invisionzone.com/index.php?/files/file/2-moselle-alpha-release The following is literally the Moselle patch that produced the screenshot (and woke up my wife while I was jamming with it). [LFO] Waveform = Select( General2, Sawtooth, Triangle, Sine) Frequency = Voice:Frequency [Voice] Mono = IF( LFO < -1, -1, LFO > 1, 1, Select( General1, LFO, (LFO - 1 * LFO^3/3 )*3/2, (LFO - 2 * LFO^3/3 + 1 * LFO^5/5 )*15/8, (LFO - 3 * LFO^3/3 + 3 * LFO^5/5 - 1 * LFO^7/7 )*35/16, (LFO - 4 * LFO^3/3 + 6 * LFO^5/5 - 4 * LFO^7/7 + 1 * LFO^9/9 )*315/128, (LFO - 5 * LFO^3/3 + 10 * LFO^5/5 - 10 * LFO^7/7 + 5 * LFO^9/9 - LFO^11/11 )*3465/1280 ) [Scope] Probe1 = LFO Probe2 = (LFO - 1 * LFO^3/3 )*3/2 Probe3 = (LFO - 2 * LFO^3/3 + 1 * LFO^5/5 )*15/8 Probe4 = (LFO - 3 * LFO^3/3 + 3 * LFO^5/5 - 1 * LFO^7/7 )*35/16 Probe5 = (LFO - 4 * LFO^3/3 + 6 * LFO^5/5 - 4 * LFO^7/7 + 1 * LFO^9/9 )*315/128 Probe6 = (LFO - 5 * LFO^3/3 + 10 * LFO^5/5 - 10 * LFO^7/7 + 5 * LFO^9/9 - LFO^11/11 )*3465/1280 Probe7 = Voice:Mono Start = LFO:SyncOut Stop = LFO:SyncOut FreqHint = LFO:Frequency > at the last AES in NYC, i was talking with some other folks (that likely > hang out here, too) about this family of soft clipping curves made outa > polynomials (so you have some idea of how high in frequency any > generated images will appear). > these are odd-order, odd-symmetry polynomials that are monotonic from -1 > < x < +1 and have as many continuous derivatives as possible at +/- 1 > where these curves might be spliced to constant-valued rails. > the whole idea is to integrate the even polynomial (1 - x^2)^N > x > g(x) = integral{ (1 - v^2)^N dv} > 0 > you figger this out using binomial expansion and integrating each power > term. > normalize g(x) with whatever g(1) is so that the curve is g(x)/g(1) and > splice that to two constant functions for the rails > { -1 x <= -1 > { > f(x) = { g(x)/g(1) -1 <= x <= +1 > { > { +1 +1 <= x > > you can "hard limit" (at +/- 1) before passing through this soft clipper > and it still works fine. but it has some gain in the "linear" region > which is g(0). > > if you want to add some "even harmonic distortion" to this, add a little > bit of > (1 - x^2)^M > to f(x) for |x| < 1 and it's still smooth everywhere, but there is a > little DC added (which has to be the case for even-symmetry distortion). > M does not have to be the same as N and i wouldn't expect it to be. > > > you can think of f(x) as a smooth approximation the "sign" or "signum" > function > sgn(x) = lim f(a*x) > a -> +inf > or > sgn(x) = lim f(x) > N -> +inf > which motivates using this as a smooth approximation of the sgn(x) > function as an alternative to > (2/pi)*arctan(a*x) or tanh(a*x). from the sgn(x) function, you can > create smooth versions of the unit step function and use that for > splicing. as many derivatives are continuous in the splice as possible. > and it satisfies conditions of symmetry and complementarity that are > useful in our line of work. > u(x) = 1/2 * (1 + sgn(x)) =approx 1/2*(1 + f(x)) > you can run a raised cosine (Hann) through this and get a more flattened > Hann. in some old stuff i wrote, i dubbed this window: > > w(x) = 1/2 + (9/16)*cos(pi*x) - (1/16)*cos(3*pi*x) > > as the "Flattened Hann Window" but long ago Carla Scaletti called it the > "Bristow-Johnson window" in some Kyma manual. i don't think it deserves > that label (i've seen that function in some wavelet/filterbank lit since > for half-band filters). you get that window by running a simple Hann > through the biased waveshaper: > 1/2 * ( 1 + f(2x-1) ) > with N=1. you will get an even more pronounced effect (of smoothly > flattening the Hann) with higher N. > below is a matlab file that demonstrates this as a soft clipping function. > BTW, Olli N, this can be integrated with that "splicing theory" thing we > were talking about approximately a year ago. it would define the > "odd-symmetry" component. we should do an AES paper about this. i > think now there is nearly enough "meat" to make a decent paper. before > i didn't think so. -- dupswapdrop -- the music-dsp mailing list and website: subscription info, FAQ, source code archive, list archive, book reviews, dsp links http://music.columbia.edu/cmc/music-dsp http://music.columbia.edu/mailman/listinfo/music-dsp