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
)