cmake build system: visiblity support for clang
[supercollider.git] / SCClassLibrary / Common / GUI / PlusGUI / Math / SignalPlusGUI.sc
blobdc5ce26bbe1b86a02afdd991200eb227b1ca3057
1 + ArrayedCollection {
3         plot { arg name, bounds, discrete=false, numChannels, minval, maxval, parent, labels=true;
4                 var plotter, txt, chanArray, unlaced, val, window, thumbsize, zoom, width,
5                         layout, write=false, msresize, gui;
6                 var flattened;
8                 gui = GUI.current;
10                 bounds = bounds ?? {
11                                 if(parent.notNil) {
12                                         if(parent.respondsTo(\view)) {
13                                                 parent.view.bounds
14                                         } {
15                                                 parent.bounds
16                                         }
17                         } {
18                                 Rect(200 ,140, 705, 410);
19                         }
20                 };
22                 width = bounds.width - 8;
24                 name = name ? "plot";
26                 numChannels = numChannels ? this.first.size.max(1);
27                 flattened = if(numChannels > 1) { this.flat } { this };
28                 unlaced = flattened.unlace(numChannels);
30                 minval = if(minval.isArray) {
31                         numChannels.collect {|index| minval.wrapAt(index) ?? { unlaced[index].minItem } }
32                 } {
33                         { minval ?? { flattened.minItem } }.dup(numChannels);
34                 };
35                 maxval = if(maxval.isArray) {
36                         numChannels.collect{|index| maxval.wrapAt(index) ?? { unlaced[index].maxItem } }
37                 } {
38                         {maxval ?? { flattened.maxItem }}.dup(numChannels);
39                 };
41                 chanArray = Array.newClear(numChannels);
42                 if(discrete) {
43                         zoom = 1;
44                         thumbsize = max(1.0, width / (flattened.size / numChannels));
45                         unlaced.do { |chan, j|
46                                 chanArray[j] = chan.linlin( minval[j], maxval[j], 0.0, 1.0 );
47                         };
48                 } {
49                         zoom = (width / (flattened.size / numChannels));
50                         thumbsize = 1;
51                         unlaced.do { |chan, j|
52                                 val = Array.newClear(width);
53                                 width.do { arg i;
54                                         var x;
55                                         x = chan.blendAt(i / zoom);
56                                         val[i] = x.linlin(minval[j], maxval[j], 0.0, 1.0);
57                                 };
58                                 chanArray[j] = val;
59                         }
60                 };
61                 window = parent ?? { gui.window.new( name, bounds ) };
63                 layout = gui.vLayoutView.new(window,
64                         if(parent.notNil) {
65                                 Rect(bounds.left + 4, bounds.top + 4, bounds.width - 10, bounds.height - 10)
66                         } {
67                                 Rect(4, 4, bounds.width - 10, bounds.height - 10)
68                         }
69                 ).resize_(5);
71                 if(labels) {
72                         txt = gui.staticText.new(layout, Rect( 8, 0, width, 18))
73                                         .string_("index: 0, value: " ++ flattened[0].asString);
74                 };
76                 numChannels.do { |i|
77                         plotter = gui.multiSliderView.new(layout,
78                                 Rect(0, 0,
79                                         // compensate for the text
80                                         layout.bounds.width, layout.bounds.height - if(labels, {26}, {0})
81                                 ))
82                                 .readOnly_(true)
83                                 .drawLines_(discrete.not)
84                                 .drawRects_(discrete)
85                                 .indexThumbSize_(thumbsize)
86                                 .valueThumbSize_(1)
87                                 .background_(Color.white)
88                                 .colors_(Color.black, Color.blue(1.0,1.0))
89                                 .action_({|v|
90                                         var curval;
91                                         curval = v.currentvalue.linlin(0.0, 1.0, minval[i], maxval[i]);
93                                         if(labels){
94                                                 txt.string_("index: " ++ (v.index / zoom).roundUp(0.01).asString ++
95                                                 ", value: " ++ curval);
96                                         };
97                                         if(write) { flattened[(v.index / zoom).asInteger * numChannels + i ]  = curval };
98                                 })
99                                 .keyDownAction_({ |v, char|
100                                         if(char === $l) { write = write.not; v.readOnly = write.not;  };
101                                 })
102                                 .value_(chanArray[i])
103                                 .elasticMode_(1);
104                         if(numChannels > 1) { plotter.resize_(5) };
105                 };
107                 ^window.tryPerform(\front) ?? { window }
109         }
113 + Signal {
114         plot { arg name, bounds;
115                 //this.asciiPlot;
116                 super.plot(name, bounds);
118         }
122 + Wavetable {
123         plot { arg name, bounds, minval, maxval, parent, labels=true;
124                 ^this.asSignal.plot(name, bounds, minval: minval, maxval: maxval, parent: parent, labels: labels);
125         }
128 + Buffer {
129         plot { arg name, bounds, minval = -1.0, maxval = 1.0, parent, labels=true;
130                 var gui;
131                 gui = GUI.current;
132                 this.loadToFloatArray(action: { |array, buf|
133                         {
134                                 GUI.use( gui, {
135                                         array.plot(name, bounds, numChannels: buf.numChannels, minval: minval, maxval: maxval, parent: parent, labels: labels);
136                                 });
137                         }.defer;
138                 });
139         }
142 + Function {
144         loadToFloatArray { arg duration = 0.01, server, action;
145                 var buffer, def, synth, name, numChannels, val, rate;
146                 server = server ? Server.default;
147                 if(server.serverRunning.not) { "Server not running!".warn; ^nil };
149                 name = this.hash.asString;
150                 def = SynthDef(name, { |bufnum|
151                         var     val = this.value;
152                         if(val.isValidUGenInput.not) {
153                                 val.dump;
154                                 Error("loadToFloatArray failed: % is no valid UGen input".format(val)).throw
155                         };
156                         val = UGen.replaceZeroesWithSilence(val.asArray);
157                         rate = val.rate;
158                         if(rate == \audio) { // convert mixed rate outputs:
159                                 val = val.collect { |x| if(x.rate != \audio) { K2A.ar(x) } { x } }
160                         };
161                         if(val.size == 0) { numChannels = 1 } { numChannels = val.size };
162                         RecordBuf.perform(RecordBuf.methodSelectorForRate(rate), val, bufnum, loop:0);
163                         Line.perform(Line.methodSelectorForRate(rate), dur: duration, doneAction: 2);
164                 });
166                 Routine.run({
167                         var c, numFrames;
168                         c = Condition.new;
169                         numFrames = duration * server.sampleRate;
170                         if(rate == \control) { numFrames = numFrames / server.options.blockSize };
171                         buffer = Buffer.new(server, numFrames, numChannels);
172                         server.sendMsgSync(c, *buffer.allocMsg);
173                         server.sendMsgSync(c, "/d_recv", def.asBytes);
174                         synth = Synth(name, [\bufnum, buffer], server);
175                         OSCpathResponder(server.addr, ['/n_end', synth.nodeID], {
176                                 buffer.loadToFloatArray(action: { |array, buf|
177                                         action.value(array, buf);
178                                         buffer.free;
179                                         server.sendMsg("/d_free", name);
180                                 });
181                         }).add.removeWhenDone;
182                 });
183         }
185         plot { arg duration  = 0.01, server, bounds, minval = -1.0, maxval = 1.0, parent, labels=true;
186                 var gui;
187                 gui = GUI.current;
188                 this.loadToFloatArray(duration, server, { |array, buf|
189                         var numChan;
190                         numChan = buf.numChannels;
191                         {
192                                 GUI.use( gui, {
193                                         array.plot(bounds: bounds, numChannels: numChan, minval: minval, maxval: maxval,
194                                                 parent: parent, labels: labels)
195                                 });
196                         }.defer;
197                 })
198         }
201 + AbstractFunction{
203         plotGraph { arg n=500, from = 0.0, to = 1.0, name, bounds, discrete = false,
204                                 numChannels, minval, maxval, parent, labels = true;
205                 var array = Array.interpolation(n, from, to);
206                 var res = array.collect { |x| this.value(x) };
207                 res.plot(name, bounds, discrete, numChannels, minval, maxval, parent, labels)
208         }
210         plotGraph2 { arg n=500, from = 0.0, to = 1.0, name, bounds, discrete = false,Ê
211                 numChannels, minval, maxval, parent, labels = true;
212                 var array = Array.interpolation(n, from, to);
213                 var res = array.collect { |x| this.value(x) };
214                 res.plot2(name, bounds, discrete, numChannels, minval, maxval, parent, labels)
215         }
219 + SoundFile {
220         plot { arg bounds;
221                 var win, view, gui;
222                 gui = GUI.current;
223                 bounds = bounds ?? { Rect( 200, 140, 705, 410 )};
224                 win = gui.window.new(this.path.split.last, bounds);
225                 view = gui.soundFileView.new(win, win.bounds.width@win.bounds.height).resize_(5);
226                 view.soundfile_(this);
227                 view.elasticMode_(1);
228                 win.front;
229                 view.readWithTask;
230         }