Created
October 4, 2015 19:42
-
-
Save xavriley/af7c756a057a7f35524e to your computer and use it in GitHub Desktop.
Revisions
-
xavriley created this gist
Oct 4, 2015 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,6 @@ This doesn't currently work because the OSC spec calls for the ints to be packed with a "twos complement" which basically means they are packed unsigned and converted when they get decoded. ``` [-1].pack('N').unpack('N') # => 16777216 [-1].pack('N').unpack('N').pack('V').unpack('l') # => -1 ``` This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,119 @@ #-- # This file is part of Sonic Pi: http://sonic-pi.net # Full project source: https://github.com/samaaron/sonic-pi # License: https://github.com/samaaron/sonic-pi/blob/master/LICENSE.md # # Copyright 2013, 2014, 2015 by Sam Aaron (http://sam.aaron.name). # All rights reserved. # # Permission is granted for use, copying, modification, and # distribution of modified versions of this work as long as this # notice is included. #++ require 'strscan' module SonicPi class OscDecode def initialize(use_cache = false, cache_size=1000) @float_cache = {} @integer_cache = {} @cache_size = cache_size @num_cached_integers = 0 @num_cached_floats = 0 @string_terminator = Regexp.new("\x00") @tag_separator = ',' @args = [] @i_tag = "i" @f_tag = "f" @s_tag = "s" @d_tag = "d" @h_tag = "h" @b_tag = "b" @cap_n = 'N' @cap_g = 'G' @low_g = 'g' @low_l = 'l' @q_lt = 'q>' @binary_encoding = "BINARY" end def decode_single_message(msg) ## Note everything is inlined here for effienciency to remove the ## cost of method dispatch. Apologies if this makes it harder to ## read & understand. See http://opensoundcontrol.org for spec. m = StringScanner.new(msg) pack_string = "" # Get OSC address e.g. /foo m.skip_until(@string_terminator) m.pos = 4 * ((m.pos + 0.01)/4).ceil pack_string << "Z#{m.pos}" # Let's see if we have some args.. # check the next char to see if it's a comma if m.peek(1) == @tag_separator # Get type tags orig_idx = m.pos tags = m.scan_until(@string_terminator) m.pos = 4 * ((m.pos + 0.01)/4).ceil if tags.length > 1 pack_string << "Z#{m.pos - orig_idx}" end # skip the comma tags.each_char do |t| case t when @tag_separator # skip the comma nil when @string_terminator # skip the null bytes nil when @i_tag # int32 m.pos = m.pos+4 pack_string << @cap_n when @f_tag # float32 m.pos = m.pos+4 pack_string << @low_g when @s_tag # string orig_idx = m.pos m.skip_until(@string_terminator) m.pos = 4 * ((m.pos + 0.01)/4).ceil pack_string << "Z#{m.pos - orig_idx}" when @d_tag # double64 m.pos = m.pos+8 pack_string << @cap_g when @h_tag # int64 m.pos = m.pos+8 pack_string << @q_lt when @b_tag # binary blob orig_idx = m.pos pack_string << @cap_n blob_length = m.getch.unpack(@cap_n)[0] m.skip(Regexp.new(".#{blob_length}")) pack_string << "Z#{m.pos - orig_idx}" m.pos = 4 * ((m.pos + 0.01)/4).ceil else raise "Unknown OSC type #{t}" end end end address, tags, *args = msg.unpack(pack_string) [address, args] end end end