The byte-order of a file only matters when you are reading multiple bytes into a multi-byte type.
In your code, NSData reads the entire file as a sequence of bytes, thus all chunk types, whether you think of them as single-quoted or double-quoted, will be in-order. Your memcpy() is also copying the bytes in order. Finally, NSString is again copying the bytes in order. At no point was the chunk type stored in a 32-bit integer variable, so your code works correctly.
Where you would have a problem is if you were to use fread() to grab 4 bytes from a CAF directly into a 32-bit integer variable by address. That would produce the wrong result on an Intel machine because CAF is big-endian. Another "incorrect" way to do this would be to use NSData -getBytes:range: and store the result into a 32-bit integer variable by address. Both of those examples start with a 32-bit type, take its address, then read bytes into the variable without accounting for the difference in byte order between the data in the file and the data in memory.
In other words, if you choose to write your program with character strings, then the chunk types will always be in order. You wouldn't be able to use the defined constants, though, since those are 32-bit integer constants initialized by single-quote convenience. One thing you could do is create your own double-quoted string constants to use instead of the single-quoted integers. I think you'd have more portable code that way, although it might be slightly more difficult to maintain.
Brian Willoughby Sound Consulting
P.S. These are really C programming questions that are not particularly related to CoreAudio except that you happen to have discovered the issue while working on CAF. However, the fact that the CAF constants are provided as 32-bit values does lead to byte-order-dependent coding.
On Sep 30, 2009, at 22:01, Darren Minifie wrote: On Wed, Sep 30, 2009 at 8:35 PM, Brian Willoughby <email@hidden> wrote:
Darren, An ASCII string is a sequence of bytes, and thus there is no difference between big-endian and little-endian. It's only when you deal with multi-byte numbers such as 16-bit integer or 32-bit integer or others that you must translate. Thanks for your input here Brian. I have two problems with this still however. My first problem, which was partially answered, is the difference between:
'abcd' "abcd" When you say ASCII are you referring to the double quoted string literal? My understanding is that the first example is in fact an int - a 32 bit value which in hex would be 0x41424344. In this case endianness is important because a big endian machine would store this 4 byte type as: 41 | 42 | 43 | 44
and a little endian machine would store it as
44 | 43 | 42 | 41
I think what I'm confused about is, you say that an ASCII string is a sequence of bytes, so the order does not matter. However, isn't that what endienness is all about? The sequence in which the byes of a datatype are laid out. UInt32 chars = 'ABCD';
would print out 'DCBA' on a little endian machine.
I appreciate you taking the time to help with this basic question
On Sep 30, 2009, at 20:15, Darren Minifie wrote: I have one other related question about CAF files and endian-ness: I have a method that looks at an NSData object (which is a CAF file in memory). The method finds the chunk type and stores it as a string. In the spec, the chunk type is defined as a UInt32, and is a seuqence of 4 chars. Here is my method which produces correct output on a little endian machine: -(NSString*)fileType{ if(!fileType){ char type [5]; type[4] = '\0'; memcpy(type, (char*)[fileData bytes], 4); fileType = [[NSString stringWithCString:type encoding:NSASCIIStringEncoding] retain]; } return fileType; } If CAF files are in big-endian format, why does this method produce the correct result? In other words why don't have i have to do a ntohl() in this case to flip the enianness, like i have to in the case of reading the chunk length etc.
|