We are about to switch to a new forum software. Until then we have removed the registration on this forum.
Hi everyone,
Long-time Pd user, fairly new to Processing.
I have built a 'visualization' sketch receiving Cartesian coordinate data sent from a Pd patch (Pure Data) via oscP5 (OSC). For the most part, the data from Pd is float data, until it reaches zero, then Processing thinks that it is dealing with an integer, yielding the error, 'ClassCastException: java.lang.Integer cannot be cast to java.lang.Float.' Is there a way around this without omitting the value 0 or 0.0 from this program?
Code is included below. Any advice would be greatly appreciated.
import oscP5.*;
import netP5.*;
OscP5 oscP5;
NetAddress myRemoteLocation;
SoundObject one;
SoundObject two;
SoundObject three;
SoundObject four;
SoundObject five;
SoundObject six;
SoundObject center;
void setup() {
size(900, 900);
noStroke();
smooth();
oscP5 = new OscP5(this, 8080);
frameRate(100);
one = new SoundObject("/xpos1", "/ypos1", "/amp1", width/2, height/2, 100); //osc tags, pos, size
two = new SoundObject("/xpos2", "/ypos2", "/amp2", width/2, height/2, 100); //osc tags, pos, size
three = new SoundObject("/xpos3", "/ypos3", "/amp3", width/2, height/2, 100); //osc tags, pos, size
four = new SoundObject("/xpos4", "/ypos4", "/amp4", width/2, height/2, 100); //osc tags, pos, size
five = new SoundObject("/xpos5", "/ypos5", "/amp5", width/2, height/2, 100); //osc tags, pos, size
six = new SoundObject("/xpos6", "/ypos6", "/amp6", width/2, height/2, 100); //osc tags, pos, size
center = new SoundObject("/cx", "/cy", "/ca", width/2, height/2, 100); //osc tags, pos, size
oscP5.addListener(one);
oscP5.addListener(two);
oscP5.addListener(three);
oscP5.addListener(four);
oscP5.addListener(five);
oscP5.addListener(six);
oscP5.addListener(center);
}
void draw() {
background(51);
one.circle(); //Display ellipse
two.circle(); //Display ellipse
three.circle();
four.circle();
five.circle();
six.circle();
center.cpoint();
}
public class SoundObject implements OscEventListener { //class name
//#Instance variables
float r = random(0, 255); //defining data; fields or 'instance variables' for class
float g = random(0, 255);
float b = random(0, 255);
float a = random(50, 255);
color c_rand = color(r, g, b, a); //random color scheme for each object
String x_tag; //passed to constructor - osc ids
String y_tag;
String amp_tag;
float xpos_t;
float ypos_t;
float amp_t;
float xpos_temp;
float ypos_temp;
float amp_temp;
//#Constructor
SoundObject(String tempx, String tempy, String tempamp, float temp_xpos, float temp_ypos, float temp_amp) {
x_tag = tempx; //strings - osc tags - x
y_tag = tempy; //- y
amp_tag = tempamp; //- amp
xpos_t = temp_xpos; //-init x from 'main'
ypos_t = temp_ypos; //-init y from 'main'
amp_t = temp_amp; //init amp from 'main'
}
//#Methods
void oscStatus(OscStatus theStatus) {
println(theStatus);
}
void oscEvent(OscMessage theOscMessage) { //values assigned through constructor
if(theOscMessage.checkAddrPattern(x_tag)==true) {
//if(theOscMessage.checkTypetag("f")) {
// println("this is a float"); //check if pd passes 0.0 as int - it is this case! recasting/data type handling is needed!
xpos_temp = theOscMessage.get(0).floatValue();
xpos_t = map(xpos_temp, -5, 5, 0, width);
//println(xpos_temp);
}
if(theOscMessage.checkAddrPattern(y_tag)==true) {
ypos_temp = theOscMessage.get(0).floatValue();
ypos_t = map(ypos_temp, -5, 5, 0, height);
//println(ypos_t);
}
if(theOscMessage.checkAddrPattern(amp_tag)==true) {
amp_temp = theOscMessage.get(0).floatValue();
amp_t = map(amp_temp, 0, 5, 0, 50);
//println(amp_t);
}
}
void circle() { //simple circles
fill(c_rand);
ellipseMode(CENTER);
ellipse(xpos_t, ypos_t, amp_t, amp_t);
}
void rectangle() { //simple circles
fill(c_rand);
rectMode(CENTER);
rect(xpos_t, ypos_t, amp_t, amp_t);
}
void cpoint() { //simple circles
fill(c_rand);
rect(xpos_t, ypos_t, 20, 20);
}
}
Answers
You coulda told us which line the Exception occurs.
Also, I don't think it's safe to re-define the Java's root class Object! :-SS
Admittedly, the limitation may be with the way Pd is formatting data before it reaches Processing and not with a specific line of code in this sketch (although I could very well be wrong about that). The exception occurs when said data stream from Pd reaches a zero from within a range between -1.0 and +1.0. The zero is treated as an int by Processing which causes, I suspect, lines 80 through 94 to give out.
With that said, I am sure there is probably a more effective way to code this and I am open to suggestions. ;)
Is there a fancy way for Processing to recognize a change in data type and pass the incoming stream to another function that supports that change?
I can include the a link to the Pd patch for anyone interested.
Fair point. I renamed the class. Still having the same issue, though. Can some kind of recasting help?
I don't think there are any errors in such line:
float xpos_temp = theOscMessage.get(0).floatValue();
Method floatValue() is supposed to return either a
float
or a Float datatype.I'm suspicious that the ClassCastException happens inside floatValue() itself! :-?
If it is so, a
try/catch
block could potentially fix that!So I've made a separate getOscFloat() method for the sole purpose of safely invoking floatValue().
Here's the blueprint:
Perhaps OSC tries to guess the type of the value depending on presence of decimal point (and other factors like exponents) and returns an object whose type depends on the formatting of the value.
The code above (untested!) shows how to deal with data of unknown / variable type.
Hi, GoToLoop's and PhiLho's suggestions will work best in this case, I am just wondering if pd sends a 0 as int instead of a float (you could check this with reading the typetag)? type casting is handled better with an updated version of oscP5 though there is no compiled download available as of now - but you could compile from source if you want. With this version casting works like this:
I think that is exactly what is happening! Thanks for the suggestions, all. I will try tomorrow and get back to you.
Gents,
After throwing in a simple if statement to read the typetag...
if(theOscMessage.checkTypetag("i")) {
...it is indeed an issue with data type formatting in pd (cannot treat 0.0 as float; it is treated as an integer - as I suspected). I can add a miniscule decimal value to the outgoing data stream to overcome this problem, but this is a horrible hack.
Sojamo, I am keen to implement your suggestion. Can you (or anyone) point me in the direction on a quick 'howto' on compiling a library for Processing?
In the meantime, I will also try GoToLoop's and PhiLho's suggestions. Thank you.
GoToLoop, the purpose of the 'width>>1' bit shift is a rather elaborate way to ensure a float value, yes?
The try-catch method produces the following error:
I'd be keen to get this approach to work, if possible.
just a faster integer division by 2. That is, same as
width/2
.It's supposed to
catch
the Exception. I've leftprintln(e);
just to flag it's happened!Thanks for the clarification. I guess I'm not entirely sure of the usage, though.
(getOscFloat(oscMsg.get(0)) + 1.0) * (width>>1);
It seems somewhat superfluous to me. I understand that it assigns some kind of float to 'xpos_t'. Re: try/catch, the sketch is catching and printing the exception as intended. Thanks for your help.
@signals_ here is the compiled and downloadable zip version of oscP5 2.0.1; download and put the oscP5 folder inside the libraries folder of your processing sketchbook (on osx this is ~/Documents/Processing/libraries).
Sorry for the delay.
PhiLho, what you say seems to be correct, although I am not sure how you can assign an integer value to 'xpos_temp' when it has been declared as a float. Forgive me if I am overlooking something very simple. I fear I may have confused things by using 'Object' as a class name above and so I have since updated the sketch in the original post.
Sojamo,
Thank you! oscP5 no longer recognizes 'OscStatus', correct? Otherwise, the library seems to be working fine. Please allow me some time to try out your type casting example.
Ricky
The solution is always simpler than it would first appear! Simple datatype conversion. D'oh: http://processing.org/examples/datatypeconversion.html
See lines 100++.
This works but I'm sure there is a better way. Open to suggestions. Sojamo, I never did get your approach to work. Thank you all for you help. Here's a little video of the working sketch:
xpos_t = (getOscFloat(oscMsg.get(0)) + 1.0) * (width>>1);
The statement above is a faster analogous calc to your old original using map():
xpos_t = map(getOscFloat(oscMsg.get(0)), -1, 1, 0, width);
Dunno why are you picking on it though. I only offered getOscFloat() method as a temporary fix!
The rest of the sample is merely enough bogus code in order to be compiled & "run"! Since I don't have the hardware!
Seems like you've found out another way and decided to use that instead: checkTypetag().
I've made an alternate getOscFloat() using your new finding:
And my sample code which merely demonstrates how to call the new getOscFloat().
Adapt it to your own code if you wish to make it more compact: %%-
GoToLoop, I'm so sorry, I meant no disrespect! :) It's purely my own ignorance. I didn't realize that it was filler. Thanks for the additional suggestion. I will certainly give it a go!
Another little update on how this is coming along: