Synchsafe Integer

BlitzMax Forums/BlitzMax Programming/Synchsafe Integer

Hi,
I'm working on an application which will sort my music after Artist, Album etc. I'm currently working on getting ID3v2 tags from the mp3 files.
I found alot of documentation on the subject, but I don't understand it all :P

Here's some info I found on ID3's website.
The ID3v2 tag size is encoded with four bytes where the most significant bit (bit 7) is set to zero in every byte, making a total of 28 bits. The zeroed bits are ignored, so a 257 bytes long tag is represented as $00 00 02 01.


Here's a c++? example of a decoder.
int unsynchsafe(unsigned int in) {
	int out=0, i;
	unsigned int mask=0x7F000000;
 
	for(i=0; i<4; ++i) {
		out >>= 1;
		out |= in & mask;
		mask >>= 8;
	}
 
	return out;
}


And here's Wikipedia's information :P
Synchsafe integers appear in ID3 tags that are attached to an MP3 file.

An ID3 tag[1] encodes several blocks of data. Some blocks (containing metadata about the content of the file) are variable in length and are encoded as 'synchsafe' integers to distinguish them from data in other blocks.

In a synchsafe integer, the most significant bit of each byte is zero, making seven bits out of eight available. So, for example, a 32-bit synchsafe integer can only store 28 bits of information.

Examples:

    (%11111111) is encoded as a 16-bit synchsafe integer (%00000001 01111111).
    (%11111111 11111111) is encoded as a 24-bit synchsafe integer (%00000011 01111111 01111111).

The ID3 specifications require that multibyte numbers such as these be stored in big-endian order,[1] so the bytes will be ordered exactly as laid out in the examples above.


I can't get my head around this, so anyone knows how to Decode/Encode this? :)

Thanks :)

Brucey has a module to grab the ID3 tags if I'm correct.

Indirectly... BASS can retrieve ID3 tags.

Okey, I've used FMOD before to retrieve ID3 tags, But I'd like to do it myself :P I've almost got my head around this, but I get VERY confused when Binary and Decimal gets mixed up >.<

this is the c to bmx conversion(UNTESTED):
Function unsynchsafe:Int(in:Int) 
	Local out:Int=0, i:Int;
	Local mask:Int= $7F000000;
 
	For i = 0 Until 4
		out = out Shr 1
		out :| in & mask
		mask = mask Shr 8
	Next
 
	Return out
End Function 

this is what I understand from the wikipedia you posted:
it seems to me that you need to grab each byte, the hight byte's firts bit needs to be extracted and moved to the first byte last bit
example 16 bit integer:
local highbyte:int = readbyte(f) ' or something like that
local lowbyte:int = readbyte(f) '        "                   "
lowbyte :| ( highbyte & 1) shl 7 ' extract the first bit of the high byte add it to the end of the low byte
highbyte = highbyte shr 1
int16 =   (highbyte shl 8) | lowbyte


or something similar. that should give you an idea for the 24 bit one. I am not shure the high byte is read first for big endian. if not then read the low byte first.

So to visualize the decoding you can imagine 32 bits sitting on the table in front of you. Just remove every 8th bit starting with the one on the left. These four bits should all be zero. Then push the remaining 28 bits together.

One tricky thing is to make sure you are reading the data correctly. You want to use a BigEndianStream. The default is most likely little endian, the usual Intel order.

Here's a line-by-line translation of unsynchsafe with the two Wikipedia examples.

Print
Print unsynchsafe( %0000000101111111 )
Print unsynchsafe( %000000110111111101111111 )


Function unsynchsafe( in:Int )
	Local out:Int, i:Int
	Int mask=$7F000000
 
	For i = 0 Until 4
		out :Shr 1
		out :| ( in & mask )
		mask :Shr 8
	Next
 
	Return out
End Function


Okey, Thanks alot for the C++ to BlitMax conversions :P
I'll have to get reading some on BigEndian & LittleEndian stuff then :)

Thanks again