Using the incoming data
Now that we are receiving data, we can do something useful with the data by adapting the OSCdef
:
OSCdef( \minibeedata, { |data,time,source| data.postln; }, '/minibee/data' );
Routing per MiniBee
The first thing is to separate the data per MiniBee, especially when you use more than one! For this you can use the argument template of OSCFunc
or OSCdef
. So to make two different functions for MiniBee id 1 and id 2:
(
OSCdef( \minibee1,
{ |data,time,source| "bee 1: ".post; data.postln; },
'/minibee/data',
argTemplate: [1]
);
OSCdef( \minibee2,
{ |data,time,source| "bee 2: ".post; data.postln; },
'/minibee/data',
argTemplate: [2]
);
);
Viewing the data
The responders above will print out the data to the post window.
To look at the data in a graph, we can use the class SWPlotterMonitor
, this class is part of the SenseWorld
quark.
Firs we set up the OSC function to put the data in a variable we can use elsewhere in the code:
(
OSCdef( \minibee1,
{ |data,time,source|
~minibee1data = data.copyToEnd(2);
},
'/minibee/data',
argTemplate: [1] );
);
As the first two items of the data are: [ /minibee/data, 1, ]
, we just want the data after the second index assigned to our variable.
Then we create the monitor:
m = SWPlotterMonitor.new( { ~minibee1data }, 200, 3, 0.005, 10 );
The arguments are:
- a Function that returns data
- number of points to plot
- number of channels (in our case 3)
- delta time for evaluating the function (this is roughly how often data arrives)
- update the plot every N points (slow down the graphics a bit to save CPU)
And then we can start the display:
m.start; // start the plot
With the key s
the view will change between superposing the three lines and making a graph for each.
To stop watching the data we can do:
m.stop; // stop the plot
Simple example of using the data to control a synth
To start using the data to control sound we must first boot the server:
s.boot; // boot server
And we want as little latency as possible, so we set the server latency to a very low number:
s.latency_(0.001);
We create a simple three tone sine oscillator:
Ndef( \sines, {
SinOsc.ar(
\freq.kr( [1,1,1], 0.1 ) * 300, // an array argument with 3 values
0,
\amp.kr([0,0,0], 0.1)
).sum
} );
and play it:
Ndef( \sines ).play;
And then we map the data from MiniBee 1 to it:
(
OSCdef( \minibee1,
{ |msg,time,source|
var data = msg.copyToEnd(2);
~minibee1data = data;
Ndef( \sines ).setn( \freq, data * 2 * [1,2,3] );
Ndef( \sines ).setn( \amp, (data - 0.5).abs * 5 );
},
'/minibee/data',
argTemplate: [1] );
);
To look at the sound, we scope it:
Ndef( \sines ).scope
And if we’re fed up with it, we stop the sound again:
Ndef( \sines ).stop;
Another example, using the ControlSpec
that is available in SuperCollider:
// single sinetone
Ndef( \sines, { SinOsc.ar( \freq.kr( 300, 0.1 ), 0, \amp.kr(0.1, 0.1) ) } );
(
OSCdef( \minibee1,
{ |msg,time,source|
var data = msg.copyToEnd(2);
~minibee1data = data;
Ndef( \sines ).set( \freq, ([300, 5000, \exp].asSpec.map( data[0] )) );
Ndef( \sines ).set( \amp, (data[2] - 0.5).abs * 5 );
};
}, '/minibee/data',
argTemplate: [1] );
);
Ndef( \sines ).play;
And also using a ControlSpec
for the range of the accelerometer:
// specs for mapping:
~accMap = [0.44,0.56].asSpec; // range of accelerometer
~freqMap = [300, 5000, \exp].asSpec; // range of frequency
(
OSCdef( \minibee1,
{ |msg,time,source|
var data = msg.copyToEnd(2);
// using the method .specMap from SenseWorld quark
Ndef( \sines ).set( \freq, data[0].specMap( ~accMap, ~freqMap ) );
Ndef( \sines ).set( \amp, (data[2] - 0.5).abs * 5 );
},
'/minibee/data',
argTemplate: [1] );
);
To stop the sound:
Ndef( \sines ).stop;