2 Replies - 373 Views - Last Post: 19 February 2013 - 08:22 PM Rate Topic: -----

#1 Thanos_1983  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 13
  • Joined: 05-February 13

ID3v2 ODD output

Posted 14 February 2013 - 06:36 PM

Hello everyone,

I am trying to write a code for my assignment in ID3 version 2 to read some data from an mp3 file. I found some information on the internet and I put together a program. I am beginner in programming and I can not find my mistake. The output is odd, the numbers of the version are not printed and also on the final print parts there are introduced some blank lines. I tried to flush it at the end maybe I was missing something in the buffer but the result is the same. Any help would be appreciated, thank you in advance for your time and effort to my question.

Here is the code:

[
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <unistd.h>

typedef struct{
  unsigned char header_id[3]; /* We indicate that this mp3 file is ID3 format 3 bytes */
   uint8_t major_version; /* We set the size and type of unsigned integer of length 8 bits >to the Major Version, unsigned int minimum value is 0 */
  uint8_t revision_number; /* We set the size and type of unsigned integer of length 8 >bits to the Revision Number, unsigned int minimum value is 0 */
  unsigned char flags; /* We indicate two flag bytes, we use unsigned characters so they >can take values 0 - 255 and not -128 up to 127*/
   uint32_t size; /* We the size is indicated by 4 bytes = 32 bits */
}mp3_Header;

typedef struct{
	uint32_t extended_size;
	unsigned char number_flags;
	unsigned char extended_flags;	
}mp3_Extended_Header;

typedef struct{
	unsigned char frame_id[4]; 
	uint32_t frame_size;
	unsigned char frame_flags[2];	
}mp3_Frame;

 int main (int argc, char *argv[])
  {
	   char a[] = "silence.mp3";
	   if ( argc != 1 )  /* Input from user argc should be 1 for correct
						  *	execution. The argument count >variable
						  * stores the number of arguments plus one. >*/ 
		{
			 /*We print argv[0], if the program that user has chosen for
			  * execution it is not correct as input if has more inputs*/ 
			printf( "Please choose one file: %s  <silence.mp3> \n", argv[0] );
		}
		else 
		{
			mp3_Header first;
			mp3_Extended_Header second;
			mp3_Frame third;
			
			unsigned char loop_memory[4], memory[4], new_flagg[2], characters;
			int i,b=1;
			unsigned long length_of_data = 0;
						
			FILE *file; /* A file pointer is a variable of type FILE, 
						 * we declare a file pointer.*/
						 
			file = fopen("silence.mp3", "rb");  /* Open the file
												 * silence.mp3 in
												 * "reading" mode "r". */
												 
			if (file == NULL) 
				{
					/* If the file could not open for a variety of reasons
					*  the program should inform us by print the document
					*  and exit.*/ 
					printf( "I couldn't open: %s for reading.\n", a );
					exit(0);
				}
			
			else 
				{
				
				/*Set the pointer at the possition at the beggining of the file, 
				 * if the procedure is correct it will return 0 if not it will return -1. */
				if ((int)fseek((FILE *) file, (long int) 0 , (int) SEEK_SET) == -1)
					{
						fprintf(stderr, "Not able to fseek at possition 0");
						return EXIT_FAILURE;
					}

				/* The  function  fread() will read 4 bytes of data, each of them in size
				 * of 1 byte long and they will be stored in memory (givven name) . */
				if ( (size_t) fread( (void *) memory , (size_t) 4 , (size_t) 1 , (FILE *) file) !=1)
				
					{
						printf("Could not read the file\n");
						exit (0);
					}
				
				/* I will copy the string from location (memory) to the destination tag_id from first typedef stuct */
				strncpy( (char *) first.header_id , (char *) memory , (size_t) 4);
								
				if ( (size_t) fread( (void *) &first.major_version , (size_t) 1 , (size_t) 1 , (FILE *) file) != 1) 

					{
						printf("Could not read the major_version\n");
						exit (0);
					}
				
				if ( (size_t) fread( (void *) &first.revision_number , (size_t) 1, (size_t) 1 , (FILE *) file) != 1) 

					{
						printf("Could not read the revision_number\n");
						exit (0);
					}
				
				/* Read the total size of the header */				
				if ( (size_t) fread( (void *) memory , (size_t) sizeof(first.size) , (size_t) 1 , (FILE *) file) != 1) 

					{
						printf("Could not read memory\n");
						exit (0);
					}
				
					/* We break down the packet in bytes and allocate the bytes in memory in a sequence. 
					* After the first sequence is stored for the rest we have to shift them by one possition.
					* Because the first bit determines the sign on the character/ intiger and we have set it to possitive. 
					* We shift the possition every 7 bits because 1 byte has 8 bits - 1 the sign ( + , - ). */
					first.size = (memory[3] & 0xFF) |
								((memory[2] & 0xFF) << 7 ) |
								((memory[1] & 0xFF) << 14 ) |
								((memory[0] & 0xFF) << 21 );
				
					/* Store temporarilly the length of the data */
					length_of_data = first.size;
				
					/* Print the data that we have collect so far */
					((int) fprintf( stdout , "%s version %d . %d\t Size %d\n", first.header_id , first.major_version , first.revision_number , first.size));
					
				/* At this point we want to make sure that the whole header has been executed correctly */
				if (( first.flags & (01000000) ) == 01000000 )
					
					{	
						/* Extended Header 6 Bytes */
						if ( (size_t) fread( (void *) memory , (size_t) sizeof(second.extended_size) , (size_t) 1 , (FILE *) file ) != 1)
						
							{
								printf("Could not read Memory\n");
								exit (0);
							}
						
					/* Break down the packet in pieces and extrac the data */
					second.extended_size = (memory[3] & 0xFF) |
										   ((memory[2] & 0xFF) << 7 ) |
										   ((memory[1] & 0xFF) << 14 ) |
										   ((memory[0] & 0xFF) << 21 );
					if ( (size_t) fread( (void *) &second.number_flags , (size_t) 1 , (size_t) 1 , (FILE *) file ) !=1)
					
							{
								printf("Could not read Number of Flags\n");
								exit (0);
							}
						
					if ( (size_t) fread( (void *) &second.extended_flags , (size_t) 1 , (size_t) 1 , (FILE *) file ) !=1)
					
						{
							printf("Could not read Extended Flags\n");
							exit (0);
						}
						
						fprintf( stdout,"Extended header size: %d\n", second.extended_size);
						/* From the stored value we substract the Extended Header */
						length_of_data = length_of_data - second.extended_size;
						/* Reposition the seek pointer after the Extended Header */
						if ((int)fseek ((FILE *) file , (long int) second.extended_size + 10 , (int) SEEK_SET ) == -1)
						
							{
								fprintf(stderr, "Not able at second.extended_size possition");
								return EXIT_FAILURE;
							}
						
						}
					
				else
					{
						/* If process has been executed correclty proceed and place reader after Extended Header (10 bytes) */
						if ((int)fseek ((FILE *) file , (long int) 10 , (int) SEEK_SET ) == -1)
						
							{
								fprintf(stderr, "Not able to fseek at possition 10");
								return EXIT_FAILURE;
							}
						
					}
						
				while(b!=0) /* Read one by one character until the end of file, again and again. */
						{
							if ( (size_t) fread( (void *) loop_memory , (size_t) 4 , (size_t) 1 , (FILE *) file ) !=1)
							
								{
									printf("Could not read Header_id_1 \n");
									exit (0);
								}
							
							strncpy( (char *) third.frame_id , (char *) loop_memory , (size_t) 4 );
							
							if ( (size_t) fread( (void *) memory , (size_t) sizeof(third.frame_size) , (size_t) 1 , (FILE *) file ) !=1)
							
								{
									printf("Could not read Memory\n");
									exit (0);
								}
							
							/* Extract data and store them */
							third.frame_size = (memory[3] & 0xFF) |
											   ((memory[2] & 0xFF) << 7 ) |
											   ((memory[1] & 0xFF) << 14 ) |
											   ((memory[0] & 0xFF) << 21 );
											   
							if ( (size_t) fread( (void *) new_flagg , (size_t) 2 , (size_t) 1 , (FILE *) file ) !=1)
							
								{
									printf("Could not read Memory\n");
									exit (0);
								}
							
							strncpy( (char *) third.frame_flags , (char *) new_flagg , (size_t) 2 );
							/* Print inforamtion of Frames */
							printf("Third Part Frame id : %s Frame Size : %d Flags : ", third.frame_id , third.frame_size );	  
							
							/* Compare the strings */
							if ( strncmp( (char *) third.frame_id , "TPE1" , (size_t) 4 ) == 0 )  
								{
									for ( i = 1; i <= third.frame_size; i++ )
										{
											characters = fgetc(file);
											printf( "%c" , characters );
										}
								printf("\n");
								}
								
							else if ( strncmp( (char *) third.frame_id , "TALB" , (size_t) 4 ) == 0 )
								{
									for ( i=1 ; i <= third.frame_size; i++ )
										{
											characters = fgetc(file);
											printf( "%c" , characters );
										}
								printf("\n");
								}
								
							else if ( strncmp ( (char *) third.frame_id , "TYER" , (size_t) 4 ) == 0 )
								{
									for ( i = 1; i <= third.frame_size; i++ )
										{
											characters = fgetc(file);
											printf( "%c" , characters );
										}
								printf("\n");
								}
								
							else if ( strncmp ( (char *) third.frame_id , "TCON" , (size_t) 4 ) == 0 )
								{
									for ( i = 1; i <= third.frame_size; i++ )
										{
											characters = fgetc(file);
											printf( "%c" , characters );
										}
								printf("\n");
								}
							
							else if ( strncmp ( (char *) third.frame_id , "TRCK" , (size_t) 4 ) == 0 )
								{
									for ( i = 1; i <= third.frame_size; i++ )
										{
											characters = fgetc(file);
											printf( "%c" , characters );
										}
								printf("\n");
								}
								
							else if ( strncmp ( (char *) third.frame_id , "TIT2" , (size_t) 4 ) == 0 )
								{
									for ( i = 1; i <= third.frame_size; i++ )
										{
											characters = fgetc(file);
											printf( "%c" , characters );
										}
								printf("\n");
								}
							
							else
								{
									printf("\n"); b=0;
								}
						}
						
						if ((int) fflush ((FILE *) file) !=0)
					
						{
							printf("Could not Flush buffer at the end");
						}
					
					printf("\nFinished Reading, Clossing silence.mp3 file! Goodbye!\n");
						
			fclose(file);
			}
		}
	return 0;
	}
	
]

This post has been edited by jimblumberg: 14 February 2013 - 09:16 PM
Reason for edit:: Added missing code tags. Please learn to use them properly.


Is This A Good Question/Topic? 0
  • +

Replies To: ID3v2 ODD output

#2 Skydiver  Icon User is offline

  • Code herder
  • member icon

Reputation: 3168
  • View blog
  • Posts: 9,578
  • Joined: 05-May 12

Re: ID3v2 ODD output

Posted 15 February 2013 - 07:08 AM

First: An overall comment. If a parameter or return value does not need a cast, do not cast it. By putting a cast you are telling compiler, I know what I'm doing trust me. So if you accidentally, put in an integer variable and cast it to a FILE* for a parameter that needs a FILE*, the compiler will go merrily along take your word for it that that integer value in the integer variable is a valid FILE pointer.

Next: That strncpy() should be a memcpy() or whatever your compiler's equivalent is. strncpy() will stop copying if there is a null terminator in the string. So if you had:
memory = { 1, 0, 2, 3 }


You will only end up with the 1 being copied into your header_id.

Next: You read in the major and minor version in lines 87-94, but you never read in the flags, that come before the size field.

Next: On line 102, you read in the size, but then you overwrite that value on lines 113-116. Assuming that you don't overwrite the values. You need to ensure that endianness of your target platform matches the endianess of the size that you just read from disk. As far as I know, ID3v2 tags are big endian. If you are running on an Intel processor, your platform is little endian, so you'll need to do some conversion.

I'll break off at this point since I've got to get back to work, but hopefully this gets you started. I recommend stepping through your code with a debugger to verify that you are getting the values you expect as the program runs, instead of just running the program and looking at the final output on the console.
Was This Post Helpful? 1
  • +
  • -

#3 Thanos_1983  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 13
  • Joined: 05-February 13

Re: ID3v2 ODD output

Posted 19 February 2013 - 08:22 PM

Thank you a lot for your time, your suggestions are very useful to me. I am a beginner and any information that I am collecting is very useful.
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1