View this PageEdit this PageUploads to this PageHistory of this PageTop of the SwikiRecent ChangesSearch the SwikiHelp Guide

Cottle Chapter 12 - Wave Forms, FM/AM Synthesis, Sequencer, Sample and Hold, Real Time Monitoring with Peep

Home   How To   Code Pool   Public Library   Theory   Events
[Cottle examples]

12. Wave Forms, FM/AM Synthesis, Sequencer, Sample and Hold, Real Time Monitoring with Peep


//12.1 wave forms

//No plot, alas! You'll have to look for a basic computer music text for these.

//(
//Synth.plot({[
//	SinOsc.ar(400, mul: 0.5), 
//	Saw.ar(400, add: -0.4), 
//	LFTri.ar(400, mul: 0.5), 
//	Pulse.ar(400, add: -0.4),
//	PinkNoise.ar,
//	LFNoise0.ar(1200)]})
//)
//
//(
//wave = 0; //change to try each wave
//Synth.play({[
//	SinOsc.ar(400, mul: 0.5), 
//	Saw.ar(400, mul: 0.5), 
//	LFTri.ar(400, mul: 0.5), 
//	Pulse.ar(400, mul: 0.5),
//	PinkNoise.ar,
//	LFNoise0.ar(1200)].at(wave)})
//)


//12.2 Saw, LFSaw

s = Server.internal.boot;

{ Saw.ar(200, mul: 0.5) }.scope;

{ LFSaw.ar(200, mul: 0.5) }.scope;

{ Pulse.ar(200, mul: 0.5) }.scope;

{ LFPulse.ar(200, mul: 0.5) }.scope;


//12.3 LF waves

{SinOsc.ar(LFPulse.kr(3, 0, 0.3, 200, 500), mul: 0.5) }.scope;

{ SinOsc.ar(LFSaw.kr(3, 0, 200, 500), mul: 0.5) }.scope;

{ SinOsc.ar(LFTri.kr(1, 0, 200, 1000), mul: 0.5) }.scope;

//12.4 LF control 

{ SinOsc.ar(LFTri.ar(5, 0, 20, 400), mul: 0.5) }.scope;

{ SinOsc.ar(400, mul: LFTri.ar(5, 0, 0.3, 0.6)) }.scope;

12.5 synthetic sounds

{	SinOsc.ar(400, 
		mul: LFTri.ar(MouseX.kr(1, 1000, 'exponential'), 0, 0.3, 0.6)
	)
}.scope;

{	SinOsc.ar(
		LFTri.ar(MouseX.kr(1, 800, 'exponential'), 0, 100, 400), 
		mul: 0.5)
}.scope;

{	SinOsc.ar(
		LFTri.ar(12, MouseX.kr(20, 800, 'exponential'), 0, 1000), 
		mul: 0.5)
}.scope;

{	SinOsc.ar(
		LFTri.ar(
			MouseY.kr(1, 12000, 'exponential'), 
			0, 
			MouseX.kr(80, 800, 'exponential'), 
			1000), 
		mul: 0.5)
}.scope;

//FM and AM synthesis

//12.6 AM Synthesis

{ SinOsc.ar(500, mul: SinOsc.ar(50, mul: 0.5)) }.scope;

{ Saw.ar(500, mul: SinOsc.ar(50, mul: 0.5)) }.scope;

//12.7 FM Modulation

{ SinOsc.ar(400 + SinOsc.ar(124, mul: 100), mul: 0.5) }.scope;

//12.8 MouseX and MouseY controlling FM frequency and index

{ SinOsc.ar(400 + 
	SinOsc.ar(
		MouseX.kr(100, 500), //control freq 
		mul: 100, //index
	), mul: 0.5)
}.scope;

{ SinOsc.ar(400 + 
	SinOsc.ar(
		111, //control freq
		mul: MouseX.kr(10, 1000) //index
	), mul: 0.5)
}.scope;

{ SinOsc.ar(400 + 
	SinOsc.ar(
		MouseX.kr(100, 500), //control freq
		mul: MouseY.kr(10, 1000) //index
	), mul: 0.5)
}.scope;


//Sequencer

//12.9 midicps

60.midicps;

[60, 62, 64, 65, 67, 69, 71].midicps;

//12.10 sequencer

(
var pitchArray; //Declare a variable to hold the array
	//load the array with midi pitches
pitchArray = [60, 62, 64, 65, 67, 69, 71, 72]; 
pitchArray = pitchArray.midicps; //convert the midi pitches to cps
{	SinOsc.ar(
		Select.kr(
			Stepper.kr(Impulse.kr(8), 0, 0, 
				pitchArray.size-1, 1, pitchArray.size-1), 
			pitchArray),
	mul: 0.5)
}.scope;
)

//12.11 Dust.ar

(
var pitchArray;
pitchArray = [60, 62, 64, 65, 67, 69, 71, 72];
pitchArray = pitchArray.midicps;
{	SinOsc.ar(
		Select.kr(
			Stepper.kr(Dust.kr(8), 0, 0, 
				pitchArray.size-1, 1, pitchArray.size-1), 
			pitchArray),
	mul: 0.5)
}.scope;
)

//12.12 scramble, reverse

var pitchArray;
pitchArray = Array.fill(10, {60 + 24.rand});
pitchArray.postln;
pitchArray.scramble.postln;
pitchArray.reverse.postln;
(pitchArray + 12).postln

//12.13 sequencer variations

(
var pitchArray;
pitchArray = [60, 62, 64, 65, 67, 69, 71, 72];
pitchArray = pitchArray.scramble.midicps;
{	SinOsc.ar(
		Select.kr(
			Stepper.kr(Dust.kr(8), 0, 0, 
				pitchArray.size-1, 1, pitchArray.size-1), 
			pitchArray),
	mul: 0.5)
}.scope;
)

(
var pitchArray;
pitchArray = Array.fill(5, {60 + 12.rand});
pitchArray = pitchArray.midicps;
{	SinOsc.ar(
		Select.kr(
			Stepper.kr(Dust.kr(8), 0, 0, 
				pitchArray.size-1, 1, pitchArray.size-1), 
			pitchArray),
	mul: 0.5)
}.scope;
)

(
var pitchArray;
pitchArray = Array.fill(12, {400 + 1000.rand});
{	SinOsc.ar(
		Select.kr(
			Stepper.kr(Dust.kr(8), 0, 0, 
				pitchArray.size-1, 1, pitchArray.size-1), 
			pitchArray),
	mul: 0.5)
}.scope;
)

(
var pitchArray;
pitchArray = Array.fill((5 + 5.rand), {400 + 1000.rand});
{	SinOsc.ar(
		Select.kr(
			Stepper.kr(Dust.kr(8), 0, 0, 
				pitchArray.size-1, 1, pitchArray.size-1), 
			pitchArray),
	mul: 0.5)
}.scope;
)

//Sample and Hold
//12.14 Latch

(
{	Blip.ar( //Audio Ugen
		Latch.kr( //Freq control Ugen
			LFSaw.kr(1.1, 0, 1000, 2000), //Input for Latch
			Impulse.kr(10)), //Sample trigger rate
		12, //Number of harmonics in Blip
		mul: 0.3 //Volume of Blip
	)
}.scope;
)


//12.15 Complex Wave as Sample Source

// No plot!
//{Mix.ar(SinOsc.ar([1, 2, 3, 5.5], mul: 100, add: 110))}.plot(10)


{	Blip.ar( //Audio Ugen
		Latch.kr( //Freq control Ugen
			Mix.ar(SinOsc.ar([1, 2, 3, 5.5], mul: 100, add: 110)), 
			Impulse.kr(10.2)), //Sample trigger rate
		3, //Number of harmonics in Blip
		mul: 0.3 //Volume of Blip
	)
}.scope;


//12.16 Peep

// Peep is harder because the server and language communicate by messaging.
// You have two choices. The classic way is through server messaging. SendTrig
// sends a message from server to client, to which the client can respond using
// an OSCresponder object. This works for all servers.

// There is some latency between the server sending the message and the client
// receiving and decoding it.

(
a = {	var	freq;
	freq = LFNoise0.kr(5, mul: 300, add: 400);
	SendTrig.kr(Impulse.kr(5), 0, freq);
	SinOsc.ar(freq);
}.play(s);
o = OSCresponder(s.addr, '/tr', { arg time, resp_object, message;
	[\freq, message[3]].postln;
}).add;
)

// when done:
a.free;
o.remove;		// don't forget to do this or the oscresponder will stick around

// Alternately, if you're using the internal server, a shared control bus can be used.
// This is a control bus which the language can read directly. It works only for the internal
// server. If you try this with the local server, you won't get usable results.

// Drawback: there's no way to guarantee sync between the client process reading the
// shared bus and the server process writing to it (or vice versa).

(
a = {	var	freq;
	freq = LFNoise0.kr(5, mul: 300, add: 400);
	SharedOut.kr(0, freq);
	SinOsc.ar(freq);
}.play(s);

r = Routine({
	{	[\freq, s.getSharedControl(0)].postln;
		0.2.wait;
	}.loop;
}).play(SystemClock);
)

r.stop;
a.free;

// Back to the classic way:

(
{	var mousex;
	mousex = MouseX.kr(1.0, 10.0);
	SendTrig.kr(Impulse.kr(8), 0, mousex);
	Blip.ar( //Audio Ugen
		Latch.kr( //Freq control Ugen
			SinOsc.ar(
				mousex,
				mul: 200, add: 300), //Input for Latch
			Impulse.kr(10)), //Sample trigger rate
		3, //Number of harmonics in Blip
		mul: 0.3 //Volume of Blip
	)
}.scope;
o = OSCresponder(s.addr, '/tr', { arg time, resp_object, message;
	[\mousex, message[3]].postln;
}).add;
)

o.remove;

//12.17 Latch and MIDI pitches

(
{	Blip.ar( //Audio Ugen
		Latch.kr( //Freq control Ugen
			SinOsc.ar(
				MouseX.kr(1.0, 10.0), 
				mul: 12, add: 60), //Input for Latch
			Impulse.kr(10)).floor.midicps, //Sample trigger rate
		3, //Number of harmonics in Blip
		mul: 0.3 //Volume of Blip
	)
}.scope;
)


Link to this Page