2

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]);
    }
BSchlinker
  • 3,401
  • 11
  • 51
  • 82
  • I seem to recall that ID3v2 integrates into the MP3 structure to store it's info at the start of the file, but with the sync bits not matching. That's not your main problem, though - refer to the other answers for that. – Michael Madsen Nov 05 '09 at 20:27
  • 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 Nov 05 '09 at 20:29
  • 1
    In this case, have a look at your SVG image: "The MP3 file structure may be 'encapsulated' within an ID3 tag." Open your MP3 file with an (hex-)editor of your choice, you'll most probably see that it starts with 'ID3' which means you'll parse/skip the ID3 metadata before starting with the MP3 header. – schnaader Nov 05 '09 at 20:44

7 Answers7

2

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 Sieker
  • 9,349
  • 2
  • 25
  • 43
  • 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 Nov 05 '09 at 21:12
  • 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 Sieker Nov 05 '09 at 21:31
1
fseek(mp3file,1,SEEK_SET);

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

Aaron
  • 9,123
  • 5
  • 40
  • 38
1

Try

fseek(mp3file,0,SEEK_SET)

instead of

fseek(mp3file,1,SEEK_SET).

Files start at byte position 0.

schnaader
  • 49,103
  • 10
  • 104
  • 136
  • or failing that .. don't even bother seeking as you are already pointing at byte 0 ... – Goz Nov 05 '09 at 20:26
  • Well, I prefer to do it anyway. You know, "never assume anything" :) – schnaader Nov 05 '09 at 20:28
  • 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 Nov 05 '09 at 20:29
1

I think you probably want

fseek(mp3file,0,SEEK_SET);
Grumdrig
  • 16,588
  • 14
  • 58
  • 69
  • 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 Nov 05 '09 at 20:31
1

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

eduffy
  • 39,140
  • 13
  • 95
  • 92
  • 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 Nov 05 '09 at 20:33
  • 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 Nov 05 '09 at 20:54
  • @BSchlinker What you are seeing is memory arranged in "little endian order". See this: http://www.music.mcgill.ca/~gary/307/week4/audiofile.html#SECTION00013000000000000000 – oligofren Jun 29 '13 at 18:09
  • 1
    @oligofren Yeah this was years ago -- I think I figured out shortly after this post that it was an endianness issue. Thanks. – BSchlinker Jul 30 '13 at 23:06
0

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

f3lix
  • 29,500
  • 10
  • 66
  • 86
  • 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 Nov 05 '09 at 20:32
0

This approach worked for me. But I had to remove the int i; under //counter

That might be what you need to do. All the bits printed 1.