byteextractnode-redx32behringer

Decoding X32 Behringer mixer response


I would like help please to get the 4 Return meter values (post gain/trim, gate, dyn gain reduction and post‐fade) from the X32 behringer mixer, these are in 32 bits floats, little‐endian coded. to do this I request the x32 Behringer mixer to return the meters value for a certain channel, i.e. OSC command being /meters/6 1, see below extract from the OSC manual:

The data returned by the X32/M32 server for /meters is an OSC‐blob, an abitrary set of binary data. 
As a result,  the format differs from what is typically returned by the X32/M32. 
This is essentially for efficiency/performance  reasons. The format of a returned blob is as follows:  

    <meter id> ,b~~<int1><int2><nativefloat>…<nativefloat>   
 
    <meter id>:    see possible values below (padded with null bytes)  
    ,b~~: indicates a blob format, padded with null bytes  
    <int1>:    the length of the blob in bytes, 32 bits big‐endian coded  
    <int2>:    the number of <nativefloats>, 32 bits little‐endian coded  
    <nativefloat>: data or meter value(s), 32 bits floats, little‐endian coded

/meters/6 <channel_id>
Returns meter values from Channel Strip Meters (post gain/trim, gate, dyn gain reduction and post‐fade): 
4 channel strip meters: <channel_id> channel 0…71] 
 returns 4 float values a as single OSC blob 

to obtain the meter values i first strip the and i.e. in the code below using nodered

const bytes = msg.payload;
msg.payload = bytes.slice(4);
return msg;

A typical return value is i.e.

4,0,0,0,230,123,133,57,128,2,165,58,32,250,127,63,111,187,213,52

so leaves me with a striped value of

230,123,133,57,128,2,165,58,32,250,127,63,111,187,213,52

then i use the function below to split into an array

[{"0":230,"1":123,"2":133,"3":57,"4":128,"5":2,"6":165,"7":58,"8":32,"9":250,"10":127,"11":63,"12":111,"13":187,"14":213,"15":52}]

Function:

  const bytes = msg.payload;
    const chunkSize = msg.chunkSize || 16; // Default chunk size
    
    const chunks = [];
    for (let i = 0; i < bytes.length; i += chunkSize) {
        const chunk = bytes.slice(i, i + chunkSize);
        chunks.push(chunk);
    }
    
    msg.payload = chunks;
    return msg;

any help please to get the 4 Return meter values (post gain/trim, gate, dyn gain reduction and post‐fade), these are in 32 bits floats, little‐endian coded


Solution

  • Here is the function i came up with at the end:

    function byteArrayToFloat32(byteArray) {
      const buffer = new ArrayBuffer(4);
      const view = new DataView(buffer);
      byteArray.forEach((byte, i) => view.setUint8(i, byte));
      return view.getFloat32(0, true); // true for little-endian
    }
    
    const bytes = msg.payload;
    
    
    
    const output1 = byteArrayToFloat32(bytes.slice(0, 4));
    const output2 = byteArrayToFloat32(bytes.slice(4, 8));
    const output3 = byteArrayToFloat32(bytes.slice(8, 12));
    const output4 = byteArrayToFloat32(bytes.slice(12, 16));
    
    
    return [ {"payload": output1}, {"payload": output2}, {"payload": output3}, {"payload": output4} ];