Search Unity

  1. Unity 2019.1 is now released.
    Dismiss Notice

[RELEASED] OSC simpl

Discussion in 'Assets and Asset Store' started by cecarlsen, Jan 27, 2016.

  1. cecarlsen

    cecarlsen

    Joined:
    Jun 30, 2006
    Posts:
    471
    Hi Darius

    Nice, thats a really neat Max trick!

    If we assume that Max treats intergers as 32 bit, then you should be able to convert them like this:

    Code (CSharp):
    1.  
    2. int intByteCount = sizeof( int );
    3.  
    4. // Convert int[] to byte[].
    5. int[] inputValues = new int[]{ 2, 3, 5, 7 };
    6. byte[] bytes = new byte[ inputValues.Length * intByteCount ];
    7. for( int i = 0; i < inputValues.Length; i++ ){
    8.     byte[] intBytes = System.BitConverter.GetBytes( inputValues[i] );
    9.     System.Array.Copy( intBytes, 0, bytes, i * intByteCount, intByteCount );
    10. }
    11.  
    12. // Convert byte[] to int[].
    13. int[] outputValues = new int[ bytes.Length / intByteCount ];
    14. for( int i = 0; i < outputValues.Length; i++ ){
    15.     outputValues[i] = System.BitConverter.ToInt32( bytes, i * intByteCount );
    16. }
    17.  
    18. // Compare.
    19. for( int i = 0; i < inputValues.Length; i++ ) Debug.Log( inputValues[i] );
    20. Debug.Log( "–>" );
    21. for( int i = 0; i < outputValues.Length; i++ ) Debug.Log( outputValues[i] );
    22.  
     
  2. cecarlsen

    cecarlsen

    Joined:
    Jun 30, 2006
    Posts:
    471
    Did you try to disable "filterDuplicates" on your OscIn component?
     
  3. Electrino123456

    Electrino123456

    Joined:
    Feb 26, 2017
    Posts:
    15
    Dear Carl,

    Thanks for Your response and for Your patience.

    I did try to use Your code to decode bytes into ints in Unity but I get strange results:

    From Max I'm sending this:
    /test5 OSCBlob 8 1 2 3 4 5 6 7 8, bang

    I adapted Your code in Unity to work like this:

    Code (CSharp):
    1.   void OnTest5(byte[] bytes)
    2.         {
    3.             int intByteCount = sizeof(int);
    4.             int[] outputValues = new int[bytes.Length / intByteCount];
    5.             for (int i = 0; i < outputValues.Length; i++)
    6.             {
    7.                 outputValues[i] = System.BitConverter.ToInt32(bytes, i * intByteCount);
    8.                 Debug.Log("outputValues[i] = " + outputValues[i]);
    9.             }
    10.         }
    and each time I click on the Max message I get the console readout in unity like so:



    always two messages in the console even though max only sent one.... quite strange as I was expecting to receive:
    1
    2
    3
    4
    5
    6
    7
    8

    To reply to Your other question: Yes I did turn off filter duplicates while sending sequential ints from max to Unity, but even though I'm sending them quite slow (through speedlim 200ms object or even slower) I still only get the first and last number of the 8-int-long sequence in Unity.
     
  4. Electrino123456

    Electrino123456

    Joined:
    Feb 26, 2017
    Posts:
    15
    And when Filter Duplicates is OFF I still get 2 out of 8 different ints - just that those 2 ints are repeated a few times.
     
  5. Electrino123456

    Electrino123456

    Joined:
    Feb 26, 2017
    Posts:
    15
    Ok the ints and duplicates was an error on the max side - terribly sorry to bother You with that.
    It seems like event though the max console properly shows printing a sequence of ints sent to udpsend like so:
    1
    2
    3
    4
    5
    6
    7
    8

    It was still necessary to limit the speed of their sending to Unity to be properly discovered as a sequence of numbers.

    My previous solution with using speedlim was not working for some reason but limiting the numbers via metro wil zl queue and zlgroup did the trick.

    I'm only wondering if it would be possbile to make the transfer faster - 100ms seems like a long time for a few ints...
     
  6. Electrino123456

    Electrino123456

    Joined:
    Feb 26, 2017
    Posts:
    15
    I think it's about the timing of the sequence of numbers sent: when I am sending the ints much faster (each 10ms) Unity starts losing numbers - and only some of them go through. If I send each int every 100ms all works fine.
     
  7. cecarlsen

    cecarlsen

    Joined:
    Jun 30, 2006
    Posts:
    471
    Possible causes for Blob issue:
    1) Perhaps Max is not sending 32 bit intergers. Could it be 16 bit?
    2) Perhaps Max is encoding the integers unexpectedly. Is the incoming bytes dividable by 4 (size of int)?
    3) Perhaps Max is swapping the bytes. Google "Little/big endian". You can try to swap the bytes.

    Regarding filterDuplicates ... is this happening when you send the list of integers as separate messages immediately (for example using the Max object Uzi)?
     
  8. cecarlsen

    cecarlsen

    Joined:
    Jun 30, 2006
    Posts:
    471
    Yes, keep in mind that UDP is not reliable, you never know for sure if the messages go through, this is a general limitation of OSC based on UDP. Best practise is to send the values continuously and check for changes on the receiving side. I usually send messages with 16ms intervals from Max, that's close enough to 60fps on the Unity side.
     
  9. Electrino123456

    Electrino123456

    Joined:
    Feb 26, 2017
    Posts:
    15
    Dear Carl, THank You for Your response,

     
  10. cecarlsen

    cecarlsen

    Joined:
    Jun 30, 2006
    Posts:
    471
    Perhaps try setting up a simpler source of ints in Max for testing, just to isolate the problem.

    To check if the byte array is dividable simply do Debug.Log( bytes.Length / (float) 4 ) and see if it returns a whole number.
     
  11. MikeChr

    MikeChr

    Joined:
    Feb 2, 2018
    Posts:
    17
    Hi. Is there a method of allowing OSCSimpl to process incoming OSC messages when Unity is in edit mode? Thanks!
     
  12. cecarlsen

    cecarlsen

    Joined:
    Jun 30, 2006
    Posts:
    471
    Hi Mike. OscIn and OscOut are MonoBehaviours living in scene land and they are only ment to function at runtime. However, you can look at how the inspector panel for OscIn is implemented. It opens when the inspector is enabled (In Edit Mode!) and displays the incoming messages. You may be able to instantiate a OscIn object from an editor script (perhaps hiding it in the scene) and hook up a listener. However doing this is beyond the scope of my support and you will have to experiment yourself.
     
    MikeChr likes this.
  13. kulpajj

    kulpajj

    Joined:
    Aug 24, 2018
    Posts:
    8
    OSCSimpl was been really great - thank you so much for developing this. I recently ran into a limitation, though, where I am trying to generate a large bundle of many frequencies, amplitudes, and decayrates in Unity, to send into resonators~ in Max/Msp to make sound corresponding to what is happening in Unity. There are a lot of random parameters involved in generating these resonator sound models that make the size of the bundle fluctuate. Unfortunately, often I run into an error like this:

    " Failed to send message. Packet is too big (10828 Bytes)."

    Is there any way around this? I could port this resonator model script into Max and odot ( a scripting language in Max that works with OSC bundles ). I was just hoping to be able to do all my data operations in C# and Unity because I prefer it. Thank you for the guidance.
     
  14. cecarlsen

    cecarlsen

    Joined:
    Jun 30, 2006
    Posts:
    471
    Hi @kulpajj

    Thank you. I can recommend two remedies:

    1) Split messages into multiple bundles. Disable "bundleMessagesOnEndOfFrame" and modify your script to pack a fixed number of messages per bundle.

    2) Take a look at line 229 in OscOut. Try setting SendBufferSize to a larger number.

    The upcoming version of OSC simpl applies solution 1 automatically, but by checking the byte count instead of message count.

    Let me know if it works for you.

    All the best
     
  15. kulpajj

    kulpajj

    Joined:
    Aug 24, 2018
    Posts:
    8
    hmmm...searching OscOut for "SendBufferSize", the closest thing I have are lines 236 and 237 that are commented out as:

    // Set buffer size to windows limit since we can't tell the actual limit.
    //_udpClient.Client.SendBufferSize = OscHelper.udpPacketSizeMaxOnWindows;

    There is no line in this version of the script that actually sets the SendBufferSize. According to the versions doc with my assets package, the latest version appears to be 1.3.
     
  16. cecarlsen

    cecarlsen

    Joined:
    Jun 30, 2006
    Posts:
    471
    Great you found the line. The reason it is commented out is because it needs further testing on different devices (it varies). Try uncommenting the line and setting the value of _udpClient.Client.SendBufferSize to something larger than 10828, say 16384. Of course, you will still get an error if you exceed the new value. The better option (1) is to split the messages into multiple bundles. A new version of OSC simpl (that is coming out very soon) automatically does this. UDP is not designed for very large packets, so it is recommenced to keep them small (less than 8192 to be safe).
     
  17. kulpajj

    kulpajj

    Joined:
    Aug 24, 2018
    Posts:
    8
    oh that's great. It works. Thank you so much! I didn't want to uncheck "bundleMessagesOnEndOfFrame", as that is my favorite feature! =-) I love and need my osc addresses streaming in Max all bundled up, not atomized. And I don't want to have to manage that by each script. A higher byte allowance per bundle is working so far.
     
    cecarlsen likes this.
  18. cecarlsen

    cecarlsen

    Joined:
    Jun 30, 2006
    Posts:
    471
    OSC simpl 2.0 is out and your garbage collector will love it!

    A lot of love has been put into making OSC simpl heap garbage free in the update loop. I use the package extensively myself, and GC hiccups has been a long standing issue for graphic performance in my projects when working with heavy streams of OSC packets. The update involves changes that may seem inconvenient at first, but they are necessary to avoid garbage generation. Please check the updated examples, especially "Optimisations", to fully benefit from the update.

    OSC simpl is now available for the price of a cortado ($5)!

    But why? Because a free alternative now exists; extOSC by Vladimir Sigalkin, an extensively featured, well crafted piece of work and I recommend it, especially for those who want to avoid scripting. Sigalkin decided to MIT-license extOSC last year, a generous gesture that one can't do anything but admire. So why at all continue the work on OSC simpl? Because I still prefer the API (biased of course), I use it in almost every project and need to be able to fix and extend things when needed. Why not free then? Because I think as long as we live in a monetary society, people should be payed for their work.


    NEW FEATURES

    – Introduced ZERO heap garbage in the update loop! (*1)
    – Added full two-way support for OSC 1.0 Address Pattern Matching.
    – Added support for the OSC argument type MIDI message.
    – Added OscMessage methods for containing common Unity types in blobs.
    – Added OscOut.splitBundlesAvoidingBufferOverflow option.

    *1) If used as advised and your strings and blob lengths don't change.


    IMPROVEMENTS

    – Updated examples to promote less heap memory garbage generation.
    – Added OscPool for message recycling. See the "Optimisations" example.
    – Streamlined inspector view of Osc.mappings.
    – Added method chaining to OscMessage.Add, also available for Set and SetAsBlob.


    CHANGES

    – Scripting Runtime Version .NET 3.5 is no longer supported. Set Unity
    to use .NET 4.0 in the player settings.
    – Deprecated OscIn.ipAddress. Use OscIn.localIpAddress instead.
    – Deprecated OscOut.ipAddress. Use OscIn.remoteIpAddress instead.
    – Deprecated onAnyMessage and added MapAnyMessage and UnmapAnyMessage.
    – Deprecated versions of OscMessage constructor and OscMessage.Add that
    accepts params object[] args.
    – Deprecated TryGetNull, TryGetImpulse and replaced with versions of
    TryGet to streamline method naming.
    – Removed Map() support for delegates, methods must be defined in objects
    that derrive from UnityEngine.Object.
    – Removed OscMessage.args and added Set() and RemoveAt methods.


    UPGRADE GUIDE

    This is a major update that can in worst case raise errors when upgrading existing projects. The breaking changes were implemented to completely avoid garbage generation from variable "boxing", a C# phenomena happening when casting primitive types to objects. Arguments are now stored internally as bytes. Here is an upgrade guide to ease your pain.


    1) Delete existing "OSC simpl" folder and import new version


    2) Enable .NET 4.x. Equivalent.

    OSC simpl no longer supports Scripting Runtime Version .NET 3.5. Open the Unity Project Settings panel, find "Player" –> "Other Settings" –> "Configuration" –> "Scripting Runtime Version" and set it to ".NET 4.x Equivalent".


    3) Fix `OscMessage' does not contain a definition for `args' error.

    The OscMessage.args field is no longer directly exposed. Arguments are now accessed via OscMessage using the methods Count(), Add(), Set(), TryGet(), TryGetArgType(), Clear() and RemoveAt().

    Old code:

    Code (CSharp):
    1. if( message.args[0] is string ) {
    2.     string name = (string) message.args[0];
    3.     DoStuff( name );
    4. }  else if( message.args[0] is int ) {
    5.     int index = (int) message.args[0];
    6.     DoStuff( index );
    7. }
    New code:

    Code (CSharp):
    1. OscArgType type;
    2. if( message.TryGetArgType( 0, out type ) ){
    3.     switch( type ) {
    4.         case OscArgType.String:
    5.             string name = string.Empty;
    6.             if( message.TryGet( 0, ref cueName ) ) DoStuff( name );
    7.             break;
    8.         case OscArgType.Int:
    9.             int index;
    10.             if( message.TryGet( 0, out cueIndex ) ) DoStuff( index );
    11.             break;
    12.     }
    13. }

    4) Fix param arguments warnings.

    OscMessage no longer supports params object[] args in constructor and Add methods.

    Old code:

    Code (CSharp):
    1. new OscMessage( address, value1, value2 );
    New code:

    Code (CSharp):
    1. new OscMessage( address ).Add( value1 ).Add( value2 );

    5) Fix delegate issues.

    OscIn.Map is no longer supports delegates. You must pass member methods now. This change was done to streamline the UI experience.
     
    Jon_Olive and ExT_rus like this.