«3D Scope» by rukano

on 10 Dec'12 13:45 in scopeplot3d

This was inspired by http://sccode.org/1-1HR and a student wanted to do a 3D freq/spectrum plot over time. The colors are just for extra funkyness.... feel free to change it to standerd retro green and scale the freqs and magnitudes at will ;)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
/////////////////////////////////////////////////////////////////
// 3D Freq Scope
// You will need PV_MagBuffer (sc3-PlugIns: JoshUGens) and GUI.qt
// heavily inspired by redFrik's "bufferdisplay" (http://sccode.org/1-1HR)

(
b = Buffer.alloc(s, 1024, 1); // FFT
c = Buffer.alloc(s, 1024/2, 1); // Mags
SynthDef(\magbuf, { |fftbuf, magbuf, freqbuf|
	var in, chain;
	in = SoundIn.ar(0); // <---------- change your input here
//	in = PMOsc.ar(800, MouseX.kr(10, 800), MouseY.kr(0,40));
	chain = FFT(fftbuf, in);
	PV_MagBuffer(chain, magbuf);
//	Out.ar(0, in)
}).add;
)

////////////////////////////////////////////////////////////////
// 3D Spectrum vs. Time plotting
(
t = true;
~case = 0;
~amp = 100;
x = Synth(\magbuf, [\fftbuf, b, \magbuf, c]); 
w = Window("3D SCOPE", Rect(600, 400, 800, 600)).front;
w.view.keyDownAction_{ |view, char, xxx, code| if(code==32){ w.refresh; t = t.not; u.animate = t; } };
u = UserView(w, w.view.bounds);
u.background = Color.black;
u.animate = t;
u.frameRate = 30;
u.clearOnRefresh = false;
u.drawFunc = { |view|
	var i = view.frame;
	var ypos = i % 500;
	var xpos = 200 - (ypos/3);
	var numFreqs = 512;
	var lineColor = Color.hsv(ypos/500, 0.5, 0.5, 0.3);
	// var lineColor = Color.green.alpha_(0.5); // for retro style
	
	if( ypos == 0 ) { Pen.fillColor = Color.black; Pen.fillRect(view.bounds) }; // clear on new begin

	c.getn(0, numFreqs-1, { |v| d = v }); // get mag buffer data
	
	Pen.strokeColor = lineColor;
	Pen.moveTo(0, 0); // init
	Pen.translate(xpos, ypos + 100); // scan down
	
	switch(~case,
		// lines
		0, {
			d.do{ |y, x|
				if(y.isNil.not){ Pen.lineTo(Point(x*(600/numFreqs), (y/64).tanh.neg * ~amp)) };
			};
			Pen.stroke;
		},
		// dots
		1, {
			d.do{ |y, x|
				Pen.fillColor = lineColor;
				if(y.isNil.not){ Pen.addOval(Rect.aboutPoint(Point(x*(600/numFreqs), (y/64).tanh.neg * ~amp), 1, 1)) };
				Pen.fill;
			};
		},
		{ nil }
	);
	
};
w.onClose_{ x.free };
);

~case = 0; // draw continuous lines
~case = 1; // draw points
~amp = 200; // change the amp scaling
raw 2102 chars (focus & ctrl+a+c to copy)
reception
comments
grirgz user 10 Dec'12 16:53

really cool, I didn't know SC could do that in so few lines!

rukano user 10 Dec'12 20:33

thanks to the PV_MagBuffer :)