How to send data of type double over a Server. (server.write(double))

edited June 2019 in Library Questions

Hey there, I am working on a project that sends data from Processing to Houdini( a procedural modelling program). Houdini needs to receive the data in 8 byte chunks of type int and double.

In my code below I am successfully sending the cmdType and channels ints by packing them out. However, the structure of a double cannot be simply packed out and the server.write() will on use int, char and byte.

Is there a way I can send a double or convert it to bytes/bits?

import processing.net.*;
Server myServer;
int val = 0;
int cmdType = 1;
int channels = 3;
double[] samples = {5.3,2.3,1.2};

void setup() {
  size(200, 200);
  // Starts a myServer on port 5204
  myServer = new Server(this, 5204);
  frameRate(5);
  sendReset();
}

void draw() {
  val = (val + 1) % 255;
  background(val);
  sendSetup(cmdType);
  sendSetup(channels);
  sendSamples(samples);
}

void sendSetup(int d){
  myServer.write(0);
  myServer.write(0);
  myServer.write(0);
  myServer.write(0);
  myServer.write(0);
  myServer.write(0);
  myServer.write(0);
  myServer.write(d);
}

void sendSamples(double[] sample){
  for(int i = 0; i < sample.length; i++){
    myServer.write(sample[i]);
  }
}

Answers

  • edited May 2014

    If the double values got only 1 digit after the decimal point, you can multiply it by 10 before sending it out!

  • edited May 2014

    Are you suggesting multiplying the double so that I can then send it as an int and then just adjust for that in Houdini? Good idea, but Houdini has to receive the samples data as doubles rather than ints.

    For example, it receives the cmdType and channels like so:
    int cmdType = 1 --- becomes '\x00\x00\x00\x00\x00\x00\x00\x01'
    int channels = 3 --- becomes '\x00\x00\x00\x00\x00\x00\x00\x03'

    But has to receive the sample as a double like so:
    double sample = 5 --- becomes '@\x14\x00\x00\x00\x00\x00\x00'

  • edited May 2014

    Just took a look at class Serial's source for method write():

    public OutputStream output;
    
    public void write(int what) {  // will also cover char
      try {
        output.write(what & 0xff);  // for good measure do the &
        output.flush();   // hmm, not sure if a good idea
    
      } catch (Exception e) { // null pointer or serial port dead
        errorMessage("write", e);
      }
    }
    

    As you can see above, it's based on class OutputStream:
    http://docs.oracle.com/javase/8/docs/api/java/io/OutputStream.html

    And I'm afraid it can only send a single byte. Therefore, every other bytes beyond the lowest 1st are ignored!

  • edited May 2014 Answer ✓

    If you wanna send the whole double as a full sequence of 8 bytes, you're gonna need to convert it to a byte[8]!
    Afterwards, you can call the other overloaded Serial's write() method:

    public void write(byte bytes[]) {
      try {
        output.write(bytes);
        output.flush();   // hmm, not sure if a good idea
    
      } catch (Exception e) { // null pointer or serial port dead
        //errorMessage("write", e);
        e.printStackTrace();
      }
    }
    

    Check it out my conversion solution below: :D

    /**
     * DoubleToBytes (v2.02)
     * by  lynks (2012/Oct)
     * mod GoToLoop (2014/May)
     *
     * stackoverflow.com/questions/13071777/convert-double-to-byte-array
     *
     * forum.processing.org/two/discussion/5486/
     * how-to-send-data-of-type-double-over-a-server-server-writedouble
     */
    
    void setup() {
      final double d = Math.PI;
      final byte[] bytedDouble = new byte[8];
    
      println(doubleToBytes(d, bytedDouble));
      println();
    
      for (byte b: bytedDouble) print(hex(b) + " ");
    
      println("\n" + d);
      exit();
    }
    
    static final byte[] doubleToBytes(final double d, final byte[] bytes) {
      final long bits = Double.doubleToLongBits(d);
      for ( int i = 8; i-- != 0; bytes[i] = (byte) (bits >> (7-i << 3)) );
      return bytes;
    }
    
  • Hey GoTo, Thanks for the above reply, after reading that it can only send single Bytes I went about looking how I could split my double up into a byte[]. Found a good example and this is what I came up with. Working fine at the moment.

    void sendSamples(double[] sample){
      for(int i = 0; i < sample.length; i++){
        double s = sample[i];
        byte[] output = new byte[8];
        long lng = Double.doubleToLongBits(s);
        for(int j = 0; j < 8; j++){
          output[j] = (byte)((lng >> ((7 - j) * 8)) & 0xff);
          myServer.write(output[j]);
        }
      }
    }
    
  • Hey just saw your edit to the discussion after I posted the above. Looks pretty similar to what I came up with. Thanks Heaps.

  • edited May 2014

    Looks pretty similar to what I came up with.

    Perhaps we both searched @ StackOverflow.com. ;)
    Anyways, I've tweaked your version to use my doubleToBytes() snippet: O:-)

    // forum.processing.org/two/discussion/5486/
    // how-to-send-data-of-type-double-over-a-server-server-writedouble
    
    import processing.net.Server;
    
    static final void sendSamples(final double[] sample, final Server server) {
      final byte[] bytedDouble = new byte[8];
      for (final double d: sample)  server.write(doubleToBytes(d, bytedDouble));
    }
    
    static final byte[] doubleToBytes(final double d, final byte[] bytes) {
      final long bits = Double.doubleToLongBits(d);
      for ( int i = 8; i-- != 0; bytes[i] = (byte) (bits >> (7-i << 3)) );
      return bytes;
    }
    
  • Hey, can you tell me the your workflow of how to send processing data in Houdini or export maybe directly to fbx. thanks.

Sign In or Register to comment.