C Program for ID3 Tagging

01 Jul, 2020
Introduction:
Digital audio files can contain, in addition to the audio track, related text and/or graphical information. The information you’re probably familiar with takes the form of Song title, Artist name, Album name, Year, and Genre. This is the information displayed when you playback a digital audio file on your computer or portable device.
The process of including information other than sound into these digital audio files is commonly referred to as “tagging” in which you “tag” the audio file with additional information that describes the audio file. The original standard for tagging digital files was developed in 1996 by Eric Kemp and he coined the term ID3. At that time ID3 simply meant “IDentify an MP3”.
Versions of ID3:
There are majorly 2 versions of ID3, ID3v1, and ID3v2 as described below:
1. ID3v1: The MP3 standard did not include a method for storing file metadata. In 1996 Eric Kemp had the idea to add a small chunk of data to the audio file, thus solving the problem. The method, now known as ID3v1, quickly became the standard for storing metadata in MP3s.
The ID3v1 tag occupies 128 bytes, beginning with the string TAG 128 bytes from the end of the file. The tag was placed at the end of the file to maintain compatibility with older media players. Some players would play a small burst of static when they read the tag, but most ignored it, and almost all modern players will correctly skip it. This tag allows 30 bytes each for the title, artist, album, and a “comment”, four bytes for the year, and a byte to identify the genre of the song from a predefined list of 80 values (Winamp later extended this list to 148 values).
One improvement to ID3v1 was made by Michael Mutschler in 1997. Since the comment field was too small to write anything useful, he decided to trim it by two bytes and use those two bytes to store the track number. Such tags are referred to as ID3v1.1
2. ID3v2: In 1998, a new specification called ID3v2 was created by multiple contributors.[13] Although it bears the name ID3, its structure is very different from ID3v1.
ID3v2 tags are of variable size and usually occur at the start of the file, which aids streaming media as the metadata is essentially available as soon as the file starts streaming instead of requiring the entire file to be read first as is the case with ID3v1. ID3v2 tags consist of a number of frames, each of which contains a piece of metadata. For example, the TIT2 frame contains the title, and the WOAR frame contains the URL of the artist’s website. Frames can be up to 16MB in length, while the total tag size is limited to 256MB. The internationalization problem was solved by allowing the encoding of strings not only in ISO-8859-1, but also in Unicode. ID3v2 has further sub-classifications to 3 versions as ID3v2.2, ID3v2.3, and ID3v2.4 with minor changes in frames amongst them.
ID3 Taggers:
ID3 tags may be edited in a variety of ways. On some platforms, the file’s properties may be edited by viewing extended information in the file manager. Additionally, most audio players allow editing single or groups of files. Editing groups of files are often referred to as “batch tagging”. There are also specialized applications, called taggers, which concentrate specifically on editing the tags and related tasks. Some, such as puddletag offer advanced features such as advanced batch tagging or editing based on regular expressions.
Below is the code for implementing your own tagger.
Examples:
Input: Input MP3 file name which needs to tagged like input.mp3 and output MP3 
file name which would be created as a tagged MP3 file like output.mp3.

Output: MP3 file with tagging information as entered by the user.

Below is the C code for implementing your own tagger:
// C program for ID3 tagging of music files#include <stdio.h>#include <stdlib.h>#include <string.h>  struct tags // Structure to store tagging information.{    char title[100], artist[100], album[100],          track_num[100], year[100], genre[100];};  void merge_file(char* file1, char* file2, char* file3){    FILE *f1, *f2, *f3;    int ch;    f1 = fopen(file1, "rb"); // Opening in write mode.    f2 = fopen(file2, "rb");    f3 = fopen(file3, "wb");      if (f1 == NULL || f2 == NULL) {        exit(EXIT_FAILURE);    }      while ((ch = fgetc(f1)) != EOF) // Appending tagging info.        fputc(ch, f3);      while ((ch = fgetc(f2)) != EOF) // Appending media file info.        fputc(ch, f3);      // Closing the files.    fclose(f1);    fclose(f2);    fclose(f3);}  void tagging(char* file1, char* file2, char* file3){    int size = 0;    char clean[100];    struct tags t;    unsigned char pad1[7] = { 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76 };    unsigned char pad2[3] = { 0x00, 0x00, 0x00 };      FILE* f1;    f1 = fopen(file1, "wb");      fprintf(f1, "ID3");    fwrite(pad1, sizeof(pad1), 1, f1); /*Essential tag to identify                                         as an ID3 tagged media file.*/      gets(clean); // Clearing the input stream.      // Taking input from user.    printf("\nEnter the title of the mp3:");    scanf("%[^\n]%*c", t.title);      printf("\nEnter the artist of the mp3:");    scanf("%[^\n]%*c", t.artist);      printf("\nEnter the album of the mp3.\n");    scanf("%[^\n]%*c", t.album);      printf("\nEnter the year of the mp3.\n");    scanf("%[^\n]%*c", t.year);      printf("\nEnter the track number of the mp3.\n");    scanf("%[^\n]%*c", t.track_num);      // Track Number    // Tag to identify track number.    fprintf(f1, "TRCK");       // Essential 3 NULL bits required for separation.    fwrite(pad2, sizeof(pad2), 1, f1);       size = strlen(t.track_num);    size++; // Calculating size.       // Appending the size of the track number to tag.    fprintf(f1, "%c", size);      // Essential 3 NULL bits required for separation.    fwrite(pad2, sizeof(pad2), 1, f1);      // Adding tag number entered by the user.    fprintf(f1, "%s", t.track_num);       // Print Year    fprintf(f1, "TYER");     fwrite(pad2, sizeof(pad2), 1, f1);     size = strlen(t.year);    size++; // Calculating size.    fprintf(f1, "%c", size);    fwrite(pad2, sizeof(pad2), 1, f1);     fprintf(f1, "%s", t.year);       // Print Title    fprintf(f1, "TIT2");     fwrite(pad2, sizeof(pad2), 1, f1);     size = strlen(t.title);    size++; // Calculating size.    fprintf(f1, "%c", size);    fwrite(pad2, sizeof(pad2), 1, f1);     fprintf(f1, "%s", t.title);      // Print Artist    fprintf(f1, "TPE1");     fwrite(pad2, sizeof(pad2), 1, f1);     size = strlen(t.artist);    size++; // Calculating size.    fprintf(f1, "%c", size);    fwrite(pad2, sizeof(pad2), 1, f1);     fprintf(f1, "%s", t.artist);       // Print Album    fprintf(f1, "TALB");     fwrite(pad2, sizeof(pad2), 1, f1);     size = strlen(t.album);    size++; // Calculating size.    fprintf(f1, "%c", size);    fwrite(pad2, sizeof(pad2), 1, f1);     fprintf(f1, "%s", t.album);       // Print Genre    fprintf(f1, "TCON"); // Tag to identify genre.    fwrite(pad2, sizeof(pad2), 1, f1);    size = strlen(t.genre);    size++; // Calculating size.    fprintf(f1, "%c", size);     fwrite(pad2, sizeof(pad2), 1, f1);     fprintf(f1, "%s", t.genre);       fclose(f1); // Closing the file.}  int main(){    char file1[100] = "media_info.txt", file2[100], file3[100];      printf("\nEnter the input mp3 file name\n");    scanf("%s", file2);    printf("\nEnter the output mp3 file name\n");    scanf("%s", file3);      // Function to append media info to input file.    tagging(file1, file2, file3);       // Function to merge media info and media    // input file.    merge_file(file1, file2, file3);     return 0;}
Note: The folder in which you are running the code should contain your input.mp3 file.
References:http://id3.org/id3v2.3.0https://en.wikipedia.org/wiki/ID3#ID3v2
nidhi_biet
C Programs
C++ Programs
Technical Scripter
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
C Program to read contents of Whole File
Producer Consumer Problem in C
Difference between break and continue statement in C
Exit codes in C/C++ with Examples
C Hello World Program
Sorting a Map by value in C++ STL
Shallow Copy and Deep Copy in C++
C++ program for hashing with chaining
C++ Program to check if a given String is Palindrome or not
delete keyword in C++