Shaper wave shaper


Shaper.ar(bufnum, in, mul, add)


Performs waveshaping on the input signal by indexing into the table.

bufnum - the number of a buffer filled in wavetable format containing the transfer function.

in - the input signal.


Examples use the Internal Server to show the effect of waveshaping via a scope. Use .play instead if necessary.  


Server.default = s = Server.internal; s.boot;


b = Buffer.alloc(s, 512, 1, {arg buf; buf.chebyMsg([1,0,1,1,0,1])});

(

{ 

Shaper.ar(

b, 

SinOsc.ar(300, 0, Line.kr(0,1,6)),

0.5

) 

}.scope;

)



For those who's like to make their own wavetables for arbitrary shapers, your buffer must be in wavetable format to have a valid transfer function. Wavetable format is a special representation which includes an extra number between each sample containing the difference between two adjacent samples, to make linear interpolation faster.


Signal: [a0, a1, a2...]

Wavetable: [a0, a1-a0, a1, a2-a1, a2, a3-a2...]


If your buffer doesn't have the deltas between adjacent samples, the calculations are wrong and you get distortion.


There are two ways to get wavetables into a server buffer. The server can generate them (see the Buffer help file for the methods sine1, sine2, sine3 and cheby).


b = Buffer.alloc(s, 1024, 1);

b.cheby([1, 0.5, 0.25, 0.125]);


(

{ var sig = Shaper.ar(b, SinOsc.ar(440, 0, 0.4));

sig ! 2

}.scope;

)


Or, you can calculate the transfer function in a client-side array (Signal class) then convert it to a wavetable and send the data over.


// or, for an arbitrary transfer function, create the data at 1/2 buffer size

t = Signal.fill(512, { |i| i.linlin(0.0, 511.0, -1.0, 1.0) });


//linear function

t.plot


//t.asWavetable will convert it to the official Wavetable format at twice the size

b.sendCollection(t.asWavetable);  // may also use loadCollection here


//shaper has no effect because of the linear transfer function

(

{ var sig = Shaper.ar(b, SinOsc.ar(440, 0, 0.4));

sig ! 2

}.scope;

)



// now for a twist

a = Signal.fill(256, {arg i; var t= i/255.0;  t+(0.1*(t.max(0.1)-0.1)*sin(2pi*t*80+sin(2pi*25.6*t)))});


a.plot


d= (a.copy.reverse.neg) ++ a;


d.plot


(

b = Buffer.alloc(s, 1024, 1);

b.sendCollection(d.asWavetable);  // may also use loadCollection here

)


b.plot //wavetable format! 


//test shaper

(

{ 

Shaper.ar(

b, 

SinOsc.ar(440, 0.5, Line.kr(0,0.9,6))

) 

}.scope

)