I designed this superCollider applet after the method described in Roads, 1996 and DePoli, 1984.Â It produces a transfer function in the form of a buffer that is the ratio between two chebychev polynomial sums.Â On the left side is a table of 256 values corresponding to the polynomial orders of the numerator sum, and on the right is a table of 256 values corresponding to the polynomial orders of the denominator sum.Â To update the buffer in realtime, you must first allocate it and press the same button to start streaming into the buffer.Â Press the same button to stop streaming.Â A popup menu to the right of this button denotes the buffer index number where the transfer function can be found.Â Also included is a "plot" button, for a visual read-out of the current transfer function.

the initial screen:

edit the amplitude tables, select the buffer to allocate with the popup menu to the right, and hit the "allocate" button:

stream into buffer:

stop streaming to conserve processor power:

plot the transfer function:

/*Fractional Waveshaper.Â The graph on the left side is the denominator function, the graph on the right is the numerator.Â Be sure to allocate the buffer before playing with this thing.Â It will only update the buffer if you told it to start streaming into the buffer.Â While in "streaming" mode, it will update the buffer twice a second.Â This is to ensure the server doesn't lock up.Â When you're not updating the values, stop the stream.Â When you reallocate it will give you an error message but it means nothing and will still work fine.Â Take it easy on the MultiSliders, going too fast won't fuck up the server like in previous versions of the patch, but it does take up a lot of processing power and will probably freeze everything for a second if you get too excited with it.Â If you're curious as to what the current waveshaper function looks like, press the "plot" button for a printout.Â Enjoy!!!Â (Â© 2007 Joseph Mariglio) */

(

var size, window, sliders, sliders1, init, init1, bufSelect, bn, button, buf, streamer, numerator, denominator, quotient, plotButton;

//make a window with two multislider views:

size = 256;

window = SCWindow("fractional waveshaper", Rect(620 , 450, 10 + (size * 4), 80 + (size * 2)));

sliders = SCMultiSliderView(window, Rect(0, 0, size * 2, size * 2));

sliders.action = {arg xb; ("index: " ++ xb.index ++" value: " ++ xb.currentvalue).postln};

sliders1 = SCMultiSliderView(window, Rect(size*2 +10, 0, size * 2, size * 2));

sliders1.action = {arg xb; ("index: " ++ xb.index ++" value: " ++ xb.currentvalue).postln};

//initialize multisliders with arrays:

init = Array.new;

size.do({arg i;

init = init.add(i/size);

});

init1 = Array.new;

size.do({arg i;

init1 = init1.add(i/size);

});

sliders.value_(init.reverse);

sliders1.value_(init1.reverse);

//some cosmetic considerations:

sliders.isFilled = false;

sliders.xOffset_(5);

sliders.thumbSize_(12.0);

sliders1.isFilled = false;

sliders1.xOffset_(5);

sliders1.thumbSize_(12.0);

sliders.valueThumbSize_(15.0);

sliders1.valueThumbSize_(15.0);

sliders.indexThumbSize_( sliders.bounds.width / init.size );

sliders.gap = 0;

sliders1.indexThumbSize_( sliders1.bounds.width / init1.size );

sliders1.gap = 0;

sliders.strokeColor_(Color.blue);

sliders.fillColor_(Color.yellow);

sliders.background_(Gradient(Color.new255(135, 206, 235), Color.new255(74, 112, 139)));

sliders1.strokeColor_(Color.blue);

sliders1.fillColor_(Color.yellow);

sliders1.background_(Gradient(Color.new255(74, 112, 139), Color.new255(135, 206, 235)));

//make a popup menu to select buffer number:

bufSelect = SCPopUpMenu(window, Rect((size*4/3)+15 + (size * 2) - 80,40 + (size * 2), 60, 20));

bufSelect.items = [

"b0",

"b1",

"b2",

"b3",

"b4",

"b5",

"b6",

"b7",

"b8",

"b9",

"b10",

"b11",

"b12",

"b13",

"b14",

"b15"

];

//make a button for the allocation and streaming into selected buffer, and another button to plot the buffer:

button = SCButton(window, Rect(size*4/3, 40 + (size * 2), 10 + (size * 2) - 80, 20));

plotButton = SCButton(window, Rect(size*2, 15+(size*2), 120, 20));

button.states = [

["allocate b#:", Color.white, Color.black],

["stream into b#:", Color.black, Color.green],

["stop streaming", Color.black, Color.red]

];

plotButton.states = [

["plot", Color.black, Color.white]

];

buf = Buffer;

streamer = Task({

loop({

buf = Buffer.alloc(Server.local, 1024, bufnum:bn);

buf.loadCollection(quotient);

wait(0.5);

});

});

plotButton.action = {

buf.plot;

};

button.action = { arg butt;

butt.value.postln;

if( butt.value == 1,

{buf.free;

buf.alloc(Server.local, 1024, bufnum:bufSelect.value);

"allocated buffer".postln;

bn = bufSelect.value});

if( butt.value == 2,

{streamer.start;});

if( butt.value == 0,

{streamer.stop;

numerator = Signal.chebyFill(1024, sliders.value);

denominator = Signal.chebyFill(1024, sliders1.value);

quotient = Signal.newClear(1024);

quotient.waveFill({|x, i| numerator[x]/(denominator[x]).max(0.00000000001) }, 0, 1023);});

};

//now for the "fractional" part:

numerator = Signal.chebyFill(1024, sliders.value);

denominator = Signal.chebyFill(1024, sliders1.value);

quotient = Signal.newClear(1024);

quotient.waveFill({|x, i| numerator[x]/(denominator[x]).max(0.0078125) }, 0, 1023);

//everytime a slider is touched, update the equation with the new values:

sliders.action = {Â Â Â numerator = Signal.chebyFill(1024, sliders.value);

quotient.waveFill({|x, i| numerator[x]/(denominator[x]).max(0.0078125) }, 0, 1023);

};

sliders1.action = { denominator = Signal.chebyFill(1024, sliders1.value);

quotient.waveFill({|x, i| numerator[x]/(denominator[x]).max(0.0078125) }, 0, 1023);

};

//show the window in front:

window.front

)

Running the above code in superCollider 3 will get you the applet.Â To waveshape a sound, I recommend my ChebyShapers 2.0 applet, or you could just make your own; they're relatively simple.Â Be sure to include a DC notch at the end of it, and possibly some amplitude normalizing.

This waveshaper provides extremely gruesome distortion.Â Fractional Waveshaping has been found to be capable of such timbral effects as exponential spectra and spectra that resemble a dampened periodic function (Roads 1996).

Feel free to use and distribute, but please keep the header commentary, including the copyleft info.