Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to write low-precision numbers (2-10 bits) to an array buffer / blob?

problem: in video-games there are tons of low precision numbers that can be packed together over the network to dramatically save bandwidth compared to sending strings. Strings are allocated to UTF-8 which uses 1 byte for each character.

Ideally there should be a way to write these numbers together:

  • player id in game- precision 0-1023 range, 10 bits
  • player rotation- quaternion- a few numbers ending up as 24 bits after some math simplification
  • player inputs- 0-1 range x2, 2 bits

How do you take low precision numbers like this and put them in a array buffer / blob?

like image 560
hydrix Avatar asked Dec 28 '16 08:12

hydrix


2 Answers

You can use a Uint32Array, and then use bit shift and mask operations to store values in that array.

For example, if you wanted to store a 4 bit number, and then a 10 bit number (leaving 18 bits left over for more fields):

array[0] = (num0 & 0x0f) << 0) |
           (num1 & 0x3ff) << 4);

and to extract those fields:

num0 = (array[0] >>> 0) & 0x0f;
num1 = (array[0] >>> 4) & 0x3ff;

The array can be accessed as an ArrayBuffer for serialisation by accessing its .buffer property.

like image 133
Alnitak Avatar answered Nov 19 '22 23:11

Alnitak


based on Alnitak's answer:

function binPush(arr, i, num, max) {
     arr[i] = arr[i] << max.toString(2).length; //shift int32 $max (in base 2) bits to the left to allow for allocation
     arr[i] |= num; // OR bitwise operation, which copies the 1s from $num

}

var myArr = new Uint32Array(1);

binPush(myArr, 0, 3, 3);     // push 11:       00000000000000000000000000000011
binPush(myArr, 0, 10, 15);   // push 1010:     00000000000000000000000000111010
binPush(myArr, 0, 120, 127); // push 1111000:  00000000000000000001110101111000
binPush(myArr, 0, 120, 255); // push 01111000: 00000000000111010111100001111000

notice how the last binPush adds an extra 0 to the front because the max is 255, which is exactly 8 bits whereas 120 is 7 bits

jsfiddle

like image 1
hydrix Avatar answered Nov 19 '22 23:11

hydrix