rsc3/doc-schelp/HelpSource/Classes/ScopeView.scrbl

253 lines
6.6 KiB
Racket

#lang scribble/manual
@(require (for-label racket))
@title{ScopeView}
A buffer plotting view.@section{categories}
GUI>Views
@section{related}
Classes/Stethoscope, Classes/FreqScopeView, Classes/FreqScope
@section{description}
ScopeView is mainly intended to support the implementation of link::Classes/Stethoscope:: (an oscilloscope), link::Classes/FreqScopeView:: (a basic frequency spectrum plotting view) and link::Classes/FreqScope:: (a frequency spectrum analyzer tool).
It is optimized to efficiently perform frequent plotting of the contents of a link::Classes/Buffer:: into which a link::Classes/ScopeOut:: UGen is writing. It will periodically poll the buffer for data and update the plot, as long as the ScopeOut UGen is writing into it; the buffer will not be plotted otherwise.
@section{CLASSMETHODS}
@section{PRIVATE}
key
@section{INSTANCEMETHODS}
@section{METHOD}
bufnum
The number of the Buffer to plot.
As soon as a valid buffer number is set and a link::Classes/ScopeOut:: UGen is writing into it, the view starts periodically plotting the buffer. If the ScopeOut UGen stops writing, or an invalid buffer number is set, the plotting will pause.
@section{argument}
An integer.
@section{METHOD}
style
The plotting style:
@section{list}
## 0 = the channels are vertically spaced
## 1 = the channels are overlaid
## 2 = lissajou; the first two channels are used for 2D plotting (as streams of x and y coordinates).
::
@section{argument}
One of the above Integers.
@section{METHOD}
xZoom
The scaling factor on the horizontal axis.
@section{argument}
A Float.
@section{METHOD}
yZoom
The scaling factor on the vertical axis.
@section{argument}
A Float.
@section{METHOD}
x
The horizontal offset.
@section{argument}
A Float.
@section{METHOD}
y
The vertical offset.
@section{argument}
A Float.
@section{METHOD}
fill
Fill area under scope.
@section{argument}
A Boolean.
@section{METHOD}
waveColors
The colors used to plot each of the channels.
@section{argument}
An Array of Colors, one per channel.
@section{EXAMPLES}
@section{SUBSECTION}
A step-by-step example
@racketblock[
// execute these in succession
(
s.boot;
)
(
f = Buffer.alloc(s,1024,2);
b = Bus.audio(s,1);
w=Window.new.front;
c = ScopeView(w.view,w.view.bounds.insetAll(10,10,10,10));
c.bufnum = f.bufnum;
)
(
// listening to the bus, using ScopeOut to write it to the buffer
a=SynthDef("monoscope", { arg bus, bufnum;
var z;
z = In.ar(bus,2);
// ScopeOut writes the audio to the buffer
ScopeOut.ar(z, bufnum);
}).play(
RootNode(s),
[\bus,b.index, \bufnum, f.bufnum] ,
\addToTail // make sure it goes after what you are scoping
);
// making noise onto the buffer
d=SynthDef("noise", { arg bus;
var z;
z = LFSaw.ar(SinOsc.kr(0.1).range(300,1000),[0,1]*pi) * 0.1;
Out.ar(bus, z);
}).play(
s,
[\bus,b.index]
);
)
c.style = 0 // vertically spaced
c.style = 1 // overlapped
c.style = 2 // x/y
(
//remember to free your stuff when finished
a.free;
d.free;
f.free;
b.free;
w.close;
)
::
]
@section{SUBSECTION}
An interactive example with sound
This explains all the options:
@racketblock[
(
s.waitForBoot(
{
var func, sdef1, sdef2, syn1, syn2,startButton ;
f = Buffer.alloc(s,1024,2);
b = Bus.audio(s,1);
w=Window("Scope", Rect(150, Window.screenBounds.height-500,790,400)).front;
c = ScopeView(w,Rect(10,10,380,380)); // this is SCScope
c.bufnum = f.bufnum;
// IMPORTANT
c.server_(s);
v=CompositeView(w,Rect(400,10,380,380)).background_(Color.rand(0.7));
v.decorator = n = FlowLayout(v.bounds, margin: 0@0, gap: 5@5);
a = StaticText(v, Rect(20, 70, 90, 20)).string_(" xZoom = 1").background_(Color.rand);
m = Slider(v, Rect(20, 60, 285, 20)).background_(a.background).action_({func.value}).value_(0.5);
d = StaticText(v, Rect(20, 70, 90, 20)).string_(" yZoom = 1").background_(Color.rand);
g = Slider(v, Rect(20, 60, 285, 20)).background_(d.background).action_({func.value}).value_(0.5);
h = StaticText(v, Rect(20, 70, 90, 20)).string_(" x = 0").background_(Color.rand);
i = Slider(v, Rect(20, 60, 285, 20)).background_(h.background).action_({func.value}).value_(0.5);
Button(v, Rect(0,0,380, 20))
.states_([["waveColors = [ Color.rand, ... ]",Color.black,Color.rand]])
.action_({c.waveColors = [Color.rand,Color.rand]});
Button(v, Rect(0,0,380, 20))
.states_([[" background = Color.rand(0.1,0.3) ",Color.black,Color.rand]])
.action_({c.background = Color.rand(0.1,0.3) });
t= Button(v, Rect(0,0,380, 20))
.states_([["Current style is 0",Color.black,Color.rand],
["Current style is 1",Color.black,Color.rand],
["Current style is 2",Color.black,Color.rand]])
.action_({func.value});
func={
c.xZoom = ([0.25, 10, \exp, 1/8, 1].asSpec.map(m.value)); a.string = " xZoom = %".format(c.xZoom);
c.yZoom = ([0.25, 10, \exp, 1/8, 1].asSpec.map(g.value)); d.string = " yZoom = %".format(c.yZoom);
c.x = ([ -1024,1024, \linear, 1/8, 1].asSpec.map(i.value)); h.string = " x = %".format(c.x);
c.style=t.value
};
startButton = Button.new(v, Rect(0,0,380, 50))
.states_([["Start Sound",Color.black,Color.green],["Stop Sound",Color.black,Color.red]]).action_({});
startButton.action_{
(startButton.value==1).if{
syn1=SynthDef("test1", { arg bus, bufnum;
var z;
z = In.ar(bus,2);
// ScopeOut writes the audio to the buffer
// ScopeOut.ar(z, bufnum);
// IMPORTANT - ScopeOut2, not ScopeOut
ScopeOut2.ar(z, bufnum);
Out.ar(0,z);
}).play(
RootNode(s),
[\bus,b.index, \bufnum, f.bufnum] ,
\addToTail // make sure it goes after what you are scoping
);
// making noise onto the buffer
syn2=SynthDef("test2", { arg bus;
var z;
z = PMOsc.ar([300,250],*SinOsc.ar([0.027,0.017])*pi) * 0.1;
Out.ar(bus, z);
}).play(s,[\bus,b.index]);
}{syn1.free; syn2.free};
};
// IMPORTANT
c.start;
w.onClose={syn1.free; syn2.free; b.free; f.free};
CmdPeriod.doOnce({w.close});
})
)
::
]