Hi all,
I've just committed changes to ArrayedCollection-plot, which add a
numChannels argument. This treats the array as an interlaced
multichannel dataset. The default is 1, and it comes last, so this
should not break anything. At some point it would probably be good to
move the code which draws the views to a separate method, as this
would allow plotting nested arrays, but for the moment this works well
enough with interlaced data such as one gets from SoundFile, etc. The
option to express things like time rather than index would also be
useful.
This allows for two things: Correct plotting of multichannel Buffers,
and a rudimentary implementation of Function-plot. The latter is
somewhat limited, and could probably be done better another way, but
it's a start. At the moment it's audio rate only (as RecordBuf is as
well...) and operates in realtime. Ideally it would be NRT, but given
the lingering Panther popen bug I figured this was a better way to go.
It also doesn't work with explicit Out UGens (need those
Float-from32bits and Float-from64bits methods to get a SynthDesc
without writing to disk) so your function should return a UGen or an
Array of them. I suppose an alternative implementation would be to
store the def and then just delete it afterwards, but in any case what
I've committed is there and working. Help file is updated with
examples.
Cheers from snowy Poland...
S.
________________
+ ArrayedCollection{
plot { arg name, bounds, discrete=false, numChannels = 1;
var plotter, txt, chanArray, unlaced, val, minval, maxval, window,
thumbsize, zoom, width,
layout;
bounds = bounds ? Rect(200 , 140, 705, 410);
width = bounds.width-8;
zoom = (width / (this.size / numChannels));
if(discrete) {
thumbsize = max(1.0, zoom);
}{
thumbsize = 1;
};
name = name ? "plot";
minval = this.minItem;
maxval = this.maxItem;
unlaced = this.unlace(numChannels);
chanArray = Array.newClear(numChannels);
unlaced.do({ |chan, j|
val = Array.newClear(width);
width.do { arg i;
var x;
x = chan.blendAt(i / zoom);
val[i] = x.linlin(minval, maxval, 0.0, 1.0);
};
chanArray[j] = val;
});
window = SCWindow(name, bounds);
txt = SCStaticText(window, Rect(8, 0, width, 18))
.string_("index: 0, value: " ++ this[0].asString);
layout = SCVLayoutView(window, Rect(4, txt.bounds.height, width,
bounds.height - 30 - txt.bounds.height)).resize_(5);
numChannels.do({ |i|
plotter = SCMultiSliderView(layout, Rect(0, 0,
layout.bounds.width,layout.bounds.height))
.readOnly_(true)
.drawLines_(discrete.not)
.drawRects_(discrete)
.thumbSize_(thumbsize)
.valueThumbSize_(1)
.colors_(Color.black, Color.blue(1.0,1.0))
.action_({|v|
txt.string_("index: " ++ (v.index / zoom).roundUp(0.01).asString
++
", value: " ++ v.currentvalue.linlin(0.0, 1.0, minval,
maxval).asString) })
.value_(chanArray[i])
.resize_(5)
.elasticMode_(1);
});
^window.front;
}
}
+ Function {
plot { arg duration = 0.01, server, bounds;
var buffer, def, synth, name, value, numChannels;
server = server ? Server.default;
server.isLocal.not.if({"Function-plot only works with a localhost
server".warn; ^nil });
server.serverRunning.not.if({"Server not running!".warn; ^nil });
value = this.value;
if(value.size == 0, { numChannels = 1 }, { numChannels = value.size
});
buffer = Buffer.new(server, duration * server.sampleRate,
numChannels);
// no need to check for rate as RecordBuf is ar only
name = this.hash.asString;
def = SynthDef(name, {
RecordBuf.ar(this.value, buffer.bufnum, loop:0);
Line.ar(dur: duration, doneAction: 2);
});
Routine.run({
var c;
c = Condition.new;
server.sendMsgSync(c, *buffer.allocMsg);
server.sendMsgSync(c, "/d_recv", def.asBytes);
synth = Synth.basicNew(name, server);
OSCpathResponder(server.addr, ['/n_end', synth.nodeID], {
buffer.loadToFloatArray(action: { |array, buf|
{array.plot(bounds: bounds, numChannels: buf.numChannels) }.defer;
buffer.free;
});
}).add.removeWhenDone;
server.listSendMsg(synth.newMsg);
});
}
}_______________________________________________
sc-dev mailing list
sc-dev@xxxxxxxxxxxxxxx
http://www.create.ucsb.edu/mailman/listinfo/sc-dev