views:

584

answers:

6

I am trying to extract the mp3 header from a file. This is different then the ID3 tags -- the mp3 header is where information about the MPEG version, bit rate, frequency, etc is held.

You can see an overview of the mp3 header structure here: http://upload.wikimedia.org/wikipedia/commons/0/01/Mp3filestructure.svg

My problem is, despite loading the file and now receiving valid (as far as I know) binary output, I am not seeing the expected values. The first 12 bits of the mp3 file should be all ones, for the mp3 sync word. However, I am receiving something different for the first 8 bits alone. This would suggest a problem to me.

As a side note, I have a valid mp3 file being attached via fopen

// Main function
int main (void)
{
    // Declare variables
    FILE *mp3file;
    char requestedFile[255] = "";
    unsigned long fileLength;

    // Counters
    int i;

    // Tryout
    unsigned char byte; // Read from file
    unsigned char mask = 1; // Bit mask
    unsigned char bits[8];

    // Memory allocation with malloc
    // Ignore this at the moment! Will be used in the future
    //mp3syncword=(unsigned int *)malloc(20000);

    // Let's get the name of the file thats requested
    strcpy(requestedFile,"testmp3.mp3"); // lets hardcode this into here for now

    // Open the file
    mp3file = fopen(requestedFile, "rb"); // open the requested file with mode read, binary
    if (!mp3file){
     printf("Not found!"); // if we can't find the file, notify the user of the problem
    }

    // Let's get some header data from the file
    fseek(mp3file,0,SEEK_SET);
    fread(&byte,sizeof(byte),1,mp3file);

    // Extract the bits
    for (int i = 0; i < sizeof(bits); i++) {
     bits[i] = (byte >> i) & mask;
    }

    // For debug purposes, lets print the received data
    for (int i = 0; i < sizeof(bits); i++) {
     printf("Bit: %d\n",bits[i]);
    }
+1  A: 
fseek(mp3file,1,SEEK_SET);

Is there a reason you're skipping the first byte of the file?

Aaron
+1  A: 

Try

fseek(mp3file,0,SEEK_SET)

instead of

fseek(mp3file,1,SEEK_SET).

Files start at byte position 0.

schnaader
or failing that .. don't even bother seeking as you are already pointing at byte 0 ...
Goz
Well, I prefer to do it anyway. You know, "never assume anything" :)
schnaader
Even with sync bit starting at zero, the same problem occurs. I apologize for not setting it back to zero (I have changed it to one for testing purposes)
BSchlinker
+1  A: 

I think you probably want

fseek(mp3file,0,SEEK_SET);
Grumdrig
Even with sync bit starting at zero, the same problem occurs. I apologize for not setting it back to zero (I have changed it to one for testing purposes)
BSchlinker
A: 

fseek(mp3file,1,SEEK_SET); makes you skip the first 8 bits, so what you get with fread are bits 9 to 16

f3lix
Even with sync bit starting at zero, the same problem occurs. I apologize for not setting it back to zero (I have changed it to one for testing purposes)
BSchlinker
+1  A: 

The ID3 info may come first. Are the first 3 characters ID3?

eduffy
Do you have any mp3 header specification information which would show that ID3 information comes first? I thought it was appended to the end.
BSchlinker
That's the right-side of the spec you posted.
eduffy
Despite the fact that humans read left to right... I failed to look all the way to the right this time. I removed the tags and I appear to be receiving significantly improved output (the first byte contains all 1 bits). However, output appears to be reverse -- byte 2, which I would expect to be 10100000 is instead 00000101. Byte 1 appears to be 11011111 instead of 11111011. This is either an error in my understanding, my code, or just a coincidence.
BSchlinker
+2  A: 

ID3v2 occupies the first bit of the MP3 file, if it is there. The first three bytes of the file will be "ID3":

http://www.id3.org/id3v2.4.0-structure

There's two methods of dealing with it. The first is checking for the presence of the ID3 tag, and then parse the 10 byte header for the tag size, and skip ahead that many bytes.

EDIT: If parsing the header, you need to check for the 4th bit in the Flags field to be set to one, if it is, you need to skip an additional 10 bytes to go past the footer.

Or you can just seek through the MP3 until you hit the sync pattern. The way ID3v2 is set up, 11 one bits in a row should not occur, to ensure compatibility with players that do not support it.

Matt S
eduffy mentioned the same thing, so I went ahead and stripped the ID3 tags. This helped, but I now have another problem. However, output appears to be reverse -- byte 2, which I would expect to be 10100000 is instead 00000101. Byte 1 appears to be 11011111 instead of 11111011. This is either an error in my understanding, my code, or just a coincidence.
BSchlinker
White set of bytes are you referring to? Since the first two bytes in an MP3 frame header should be 11111111 11111011. The sync bits are a 11 bits, putting version, layer and error protection in the second read byte from the header. Here's a more complete reference for what the header bits mean: http://www.mp3-tech.org/programmer/frame_header.html
Matt S