Sign in to follow this  
DrTwox

Swap endianness of a 24bit int?

Recommended Posts

Hi everyone. I've found plenty of help and code snippits to swap endianness of common types like int, long etc, but I can't find (or work out) how to swap a 24bit int. Here's where I'm stuck:
.... blah code ....

typedef struct {
    unsigned char   flags:8;   
    unsigned int    length:24;
} __attribute__ ((packed)) BLOCK_HEADER;
BLOCK_HEADER *block_header;

.... blah code ....

block_header = malloc(sizeof(BLOCK_HEADER));
fread(block_header, 1, sizeof(BLOCK_HEADER), fp);
// Insert some swap magic here!

I need to swap the endianness of block_header->length. My attempts give a number I know can't be correct. Then again, maybe my approach is incorrect?

Share this post


Link to post
Share on other sites
This should do it:

block_header->length =
((block_header->length & 0x00ff0000) >> 16) |
((block_header->length & 0x0000ff00)) |
((block_header->length & 0x000000ff) << 16);

Share this post


Link to post
Share on other sites
This makes no sense to me, and I bet a lot of other people have glanced over this thread thinking the same thing. If the endianness of incomming data is wrong then it has to be the case that the order of either 2, 4 or 8 bytes etc is reversed. It is logically impossible for only 3 bytes to be out of order due to wrong-endian reasons.

If this really is an endian related issue then I'm pretty sure you'll find that you actually need to swap all four bytes of the BLOCK_HEADER structure around.

If the flags do currently appear to be correct then I suspect you're off-by-one in your reading of the data, which would happen to place the flags byte where you want it.
Are you sure you need to dynamically allocate such a small structure?

Share this post


Link to post
Share on other sites
Quote:
Original post by iMalc

If this really is an endian related issue then I'm pretty sure you'll find that you actually need to swap all four bytes of the BLOCK_HEADER structure around.

Why do you say this? a byte is not effected by endianess.

Share this post


Link to post
Share on other sites
Quote:
Original post by iMalc
This makes no sense to me, and I bet a lot of other people have glanced over this thread thinking the same thing. If the endianness of incomming data is wrong then it has to be the case that the order of either 2, 4 or 8 bytes etc is reversed. It is logically impossible for only 3 bytes to be out of order due to wrong-endian reasons.
If this really is an endian related issue then I'm pretty sure you'll find that you actually need to swap all four bytes of the BLOCK_HEADER structure around.

I'm scanning through .flac files to extract the metadata, specifically the Vorbis comments. The spec for the block header is here:
http://flac.sourceforge.net/format.html#metadata_block_header
Quote:
METADATA_BLOCK_HEADER
<1>Last-metadata-block flag: '1' if this block is the last metadata block before the audio blocks, '0' otherwise.
<7>BLOCK_TYPE
0 : STREAMINFO
1 : PADDING
2 : APPLICATION
3 : SEEKTABLE
4 : VORBIS_COMMENT
5 : CUESHEET
6 : PICTURE
7-126 : reserved
127 : invalid, to avoid confusion with a frame sync code
<24>Length (in bytes) of metadata to follow (does not include the size of the METADATA_BLOCK_HEADER)

The spec also states: "All numbers are big-endian coded." So I use Evil Steve's
code above to flip block_header->length once it's read in.

Basically what I'm doing is reading the METADATA_BLOCK_HEADER, checking if the BLOCK_TYPE == 4, and fseek-ing 'length' to the next METADATA_BLOCK_HEADER if it isn't. Repeat until I'm at the Vorbis comments. It works perfectly.
Quote:
If the flags do currently appear to be correct then I suspect you're off-by-one in your reading of the data, which would happen to place the flags byte where you want it.

If I was off by one, wouldn't that make the fseek jump to the wrong position? If the position was off by just one the Vorbis comments (vorbis-spec-comment) would be read incorrectly? My code appears to work on every .flac file (from various encoders, downloads etc) I've tried it with.
Quote:
Are you sure you need to dynamically allocate such a small structure?

I dunno! [embarrass] Probably not. I'm still a newbie, slowly learning though! [smile]

Share this post


Link to post
Share on other sites
Okay that makes sense now.
I think that they probably expect people to extract the bytes individually and reconstruct the length value by shifting and ORing, rather than reading it directly into the struct and then rearranging it later. An advantage of this is that your code would then work the same on either endian machine, without any kind of compile switches etc.
But what Evil Steve has posted will work for you too.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this