ChevCast
ChevCast

Reputation: 59234

What is the simplest way to extract bits from a byte in a byte array (buffer)?

I'm writing a tool to convert a VBAN stream into a raw PCM audio stream. It's working but there are a few areas in the packet header where the information I want is only a few bits rather than a full octet. I'm not very familiar with bitwise operators and the like so I'm wondering what the best way to extract this info is. For example, here is the anatomy of a VBAN packet header.

You can see the 5th byte (index 4 in a byte array) contains the SR index in the first 5 bits and the sub protocol selection in the remaining 3 bits. Here's some more info on those to help illustrate.

So I need to read the first 5 bits to get an index integer to look up the sample rate for this audio stream on the table above. Then I need to get the last three bits to look up the protocol. I've read up on bitwise operators and at a very basic level I understand some of them like how 1 & 1 = 1 but once we get to bit shifting and stuff I'm starting to get lost, and I can't seem to figure out how to use this stuff to get what I need from this byte.

I'm already able to receive the VBAN packets and parse out the byte I'm interested in. The only thing I need is how to pull bits out of the byte.

const dgram = require("dgram");
const udp = dgram.createSocket("udp4");

udp.on("message", (msg, rinfo) => {
  let srpByte = msg[4];

  // This is where I'm stuck
  let srIndex = ???;
  let subProtocol = ???;
});

udp.bind(6980, "0.0.0.0"); // Listening for VBAN packets on port 6980 from any IP.

PS - Here's a link to the full VBAN specification in case it helps or you're just interested.

Upvotes: 1

Views: 1659

Answers (1)

Matt
Matt

Reputation: 74879

Not an expert at this but had to do something similar recently, apologies if my terminology or methodology is odd...

Using a 0xab as an example (integer Number that can be represented in 8 bits)

> 0xab.toString(2)
'10101011'

For the first 3 bits 101 and the final 5 bits 01011 as standalone values:

Right shift >> the value to remove the lower 5 bits:

> (0xab >> 5).toString(2)
'101'

AND & the value with a 00011111 mask to remove the highest 3 bits.

> 0x1f.toString(2)
'11111'
> (0xab & 0x1f).toString(2)
'1011'

The leading 0 in this result is chomped, like the 3 bits that were masked out.

Upvotes: 2

Related Questions