class:: VOsc3
summary:: Three variable wavetable oscillators.
related:: Classes/COsc, Classes/Osc, Classes/OscN, Classes/VOsc
categories::  UGens>Generators>Deterministic


Description::

A wavetable lookup oscillator which can be swept smoothly across
wavetables. Fractional values of table will interpolate between two adjacent tables.
While link::Classes/VOsc:: cycles through its wavetable at one frequency,
this unit generator contains three oscillators at different frequencies,
mixed together.


This oscillator requires at least two buffers to be filled with a wavetable format
signal. This preprocesses the signal into a form which can be used efficiently by
the oscillator. All the wavetables must be allocated to the same size, and the size
must be a power of two.

subsection:: Setting your tables with Buffers
The wavetable can be generated by filling a buffer via the
link::Classes/Buffer#Buffer Fill Commands:: (e.g. link::Classes/Buffer#-sine1::).
Set code::wavetable: true:: to ensure the proper data formatting.

Identically, you can create a link::Classes/Buffer:: object by sending one of the
code::\b_gen:: messages code::\sine1::, code::\sine2::,
code::\sine3:: (see
link::Reference/Server-Command-Reference#Wave Fill Commands:: and examples below),
again remembering to enable the wavetable format.

You can use link::Classes/Buffer#*allocConsecutive:: to ensure a contiguous buffers
numbers to be interpolated.

subsection:: Setting your tables with Signals
This can also be achieved by creating a link::Classes/Signal:: object and sending
it the link::Classes/Signal#-asWavetable:: message, saving it to disk, and having
the server load it from there.

classmethods::

method::ar, kr

argument::bufpos

Buffer index. Can be swept continuously among adjacent wavetable
buffers of the same size.


argument::freq1

Frequency in Hertz of the 1st oscillator. (non-interpolated control-rate)


argument::freq2

Frequency in Hertz of the 2nd oscillator. (non-interpolated control-rate)


argument::freq3

Frequency in Hertz of the 3rd oscillator. (non-interpolated control-rate)


argument::mul

Output will be multiplied by this value.


argument::add

This value will be added to the output.


Examples::

code::

// allocate and fill the buffers to be used by VOsc3
(
s.waitForBoot({

	var numBufs = 8;

	// allocate table of consecutive buffers
	~bufs = Buffer.allocConsecutive(numBufs, s, 1024, 1);
	s.sync;

	~bufs.do({ arg buf, i;
		var n, a;

		// generate array of harmonic amplitudes
		n = (i+1)**2;
		a = Array.fill(n, { arg j; ((n-j)/n).squared.round(0.001) });

		// fill table
		// argument '7': flag for the \sine1 wave fill method
		// see "Wave Fill Commands" in the Server Command Reference
		s.performList(\sendMsg, \b_gen, buf.bufnum, \sine1, 7, a);

		s.sync;
	});
	"Buffers prepared.".postln;
})
)

// play the synth, indexing into the buffers with MouseX
(
x = SynthDef("help-VOsc", { arg out = 0, bufoffset = 0, freq = 240;
	// mouse x controls the wavetable position
	var bufindex = MouseX.kr(0, ~bufs.size - 1) + bufoffset;

	Out.ar(out,
		VOsc3.ar(
			bufindex,
			freq + [0,1],
			freq + [0.37, 1.1],
			freq + [0.43, -0.29],
			0.3
		)
	)
}).play(s,[\out, 0, \bufoffset, ~bufs.first.bufnum, \freq, 240]);
)

// fill the buffers with new harmonics on-the-fly
(
~bufs.do({ arg buf, i;
	var a;
	a = Array.fill(i, 0) ++ [0.5, 1, 0.5];
	s.performList(\sendMsg, \b_gen, buf.bufnum, \sine1, 7, a);
});
)

// new harmonics...
(
~bufs.do({ arg buf, i;
	var a, n;
	n = (i+1)*8;
	a = Array.fill(n,0);
	(n>>1).do({ arg i; a.put(n.rand, 1) });

	s.performList(\sendMsg, \b_gen, buf.bufnum, \sine1, 7, a);
});
)

// new harmonics...
(
~bufs.do({ arg buf, i;
	var a, n;
	n = (i+1)**2;
	a = Array.fill(n, { 1.0.rand2 });

	s.performList(\sendMsg, \b_gen, buf.bufnum, \sine1, 7, a);
});
)

// new harmonics...
(
var a = Array.fill(64, { 1.0.rand2 });
var n = [1, a.size].interpolate(~bufs.size-1);
~bufs.do({ arg buf, i;
	n[i].postln;
	s.performList(\sendMsg, \b_gen, buf.bufnum, \sine1, 7, a.keep(n[i].asInteger).postln);
});
)

// cleanup
(
x.free;
~bufs.do(_.free);
)

::
