bits, bytes and bitshifts

BlitzMax Forums/BlitzMax Programming/bits, bytes and bitshifts

deps(Posted 2006) [#1]
Hi,

Wanted to try and write some code that could deal with Flac files. (http://flac.sourceforge.net/)

The problem I have now is when I load the Metadata blocks.
Inside the blockheader is 24 bits that shows how long the block is. If I'm not mistaken, 24 bits is equal to 3 bytes. So I need to load these three bytes to get the length. If I use ReadInt( filestream ) it will read four bytes, so I guess I must use ReadByte() and do some bitshifts to get the correct length of the block.
This is what I have at the moment and it's not working at all since it gives me some strange sizes:

	' Length of this block
	Local b1:Byte = ReadByte(fs)
	Local b2:Byte = ReadByte(fs)
	Local b3:Byte = ReadByte(fs)
	
	Local blen:Int = (b3 Shr 0) | (b2 Shr 8) | (b1 Shr 16)
	
	Print "  Block length in bytes: "+blen


The first block (StreamInfo) is reported to be 18 bytes. I guess that could be right since a block can be from 16 to 65535 bytes long.
The next block is reported to be 14483481 bytes long. That doesn't seems right to me, and then the app freezes while trying to jump to the next block after that.

So... What did I do wrong? I have tried to rearrange the b1,b2,b3 vars and then 0,8,16 values but can't get anything that works right. changing Shr to Shl doesn't help either.
The Flac files is written in BigEndian format. (edit: and i load the file using bigendian:: in front of the filename)

Or am I overcomplicating things here?


deps(Posted 2006) [#2]
Think I solved it. :P
Local blen:Int = (b3 Shl 0) | (b2 Shl 8) | (b1 Shl 16)

is the right one to use, at least on a Mac, and the real problem was some lines above, where I read a byte when I should have read a bit.


Haramanai(Posted 2006) [#3]
There is an example that uses this technic to write a pixel in a pixmap in the BlitzWiki : http://www.blitzwiki.org/index.php/WritePixel
Have a look at it, it may help you.


tonyg(Posted 2006) [#4]
Deps, I think you're right. The first byte you have read has been shr 16 by reading it as a single byte so you need to SHL.


ImaginaryHuman(Posted 2006) [#5]
You can get rid of the (b3 Shl 0) and just replace it with b3

ie

Local blen:Int=b3 | (b2 shl 8) | (b1 shl 16)


ImaginaryHuman(Posted 2006) [#6]
Alternatively you can read an Int, shift it once to mask off the unwanted byte (or `and` it with a mask), then set the file position back one byte.