Search code examples
cbinaryheadermp3decoding

Decoding Binary via fget / buffer string (Trying to get mp3 header)


I'm writing some quick code to try and extract data from an mp3 file header.

The objective is to extract information from the header such as the bitrate and other vital information so that I can appropriately stream the file to a mp3decoder with the necessary arguments.

Here is a wikipedia image showing the mp3header information: http://upload.wikimedia.org/wikipedia/commons/0/01/Mp3filestructure.svg

My question is, am I attacking this correctly? Printing the data received is worthless -- I just get a bunch of random characters. I need to get to the binary so that I can decode it and determine vital information.

Here is my baseline code:

// mp3 Header File IO.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "stdio.h"
#include "string.h"
#include "stdlib.h"

// Main function
int main (void)
{
    // Declare variables
    FILE *mp3file;
    char *mp3syncword; // we will need to allocate memory to this!!
    char requestedFile[255] = "";
    unsigned long fileLength;

    // Counters
    int i;

    // Memory allocation with malloc
    mp3syncword=(char *)malloc(2000);

    // Let's get the name of the requested file (hard-coded for now)
    strcpy(requestedFile,"testmp3.mp3");

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

    // Let's get some header data from the file
    fseek(mp3file,1,SEEK_SET);
    fread(mp3syncword,32,1,mp3file);

    // For debug purposes, lets print the received data
     for(i = 0; i < 32; ++i)
        printf("%c", ((char *)mp3syncword)[i]);
    enter code here
    return 0;
}

Help appreciated.


Solution

  • You are printing the bytes out using %c as the format specifier. You need to use an unsigned numeric format specifier (e.g. %u for a decimal number or %x or %X for hexadecimal) to print the byte values.

    You should also declare your byte arrays as unsigned char as they are signed by default on Windows.

    You might also want to print out a space (or other separator) after each byte value to make the output clearer.

    The standard printf does not provide a binary representation type specifier. Some implementations do have this but the version supplied with Visual Studio does not. In order to output this you will need to perform bit operations on the number to extract the individual bits and print each of them in turn for each byte. For example:

    unsigned char byte = // Read from file
    unsigned char mask = 1; // Bit mask
    unsigned char bits[8];
    
    // Extract the bits
    for (int i = 0; i < 8; i++) {
        // Mask each bit in the byte and store it
        bits[i] = (byte & (mask << i)) >> i;
    }
    
    // The bits array now contains eight 1 or 0 values
    // bits[0] contains the least significant bit
    // bits[7] contains the most significant bit