📜  ID3标记的C程序

📅  最后修改于: 2021-05-28 02:19:44             🧑  作者: Mango

介绍:

除了音轨之外,数字音频文件还可以包含相关的文本和/或图形信息。您可能熟悉的信息包括歌曲名称,艺术家名称,专辑名称,年份和流派的形式。这是在计算机或便携式设备上播放数字音频文件时显示的信息。

将声音以外的信息包含到这些数字音频文件中的过程通常称为“标记”,其中您用描述音频文件的其他信息“标记”音频文件。标记数字文件的原始标准由埃里克·肯普(Eric Kemp)于1996年开发,他创造了ID3一词。那时,ID3仅表示“识别MP3”。

ID3的版本:

ID3,ID3v1和ID3v2主要有2个版本,如下所述:

1. ID3v1: MP3标准不包括用于存储文件元数据的方法。 1996年,埃里克·坎普(Eric Kemp)提出了将一小部分数据添加到音频文件的想法,从而解决了这一问题。现在被称为ID3v1的方法迅速成为在MP3中存储元数据的标准。

ID3v1标签占用128个字节,从文件末尾开始,字符串TAG 128个字节开始。标签被放置在文件的末尾,以保持与旧媒体播放器的兼容性。有些玩家在读取标签时会播放一阵静电,但大多数人却忽略了它,几乎所有现代玩家都会正确地跳过它。此标签允许标题,艺术家,专辑和“评论”分别使用30个字节,一年中的4个字节和一个字节,以从预定义的80个值列表中识别歌曲的类型(Winamp后来将该列表扩展为148个值)。

ID3v1的一项改进是Michael Mutschler在1997年进行的。由于注释字段太小,无法编写任何有用的东西,因此他决定将其缩小两个字节,并使用这两个字节来存储轨道号。此类标签称为ID3v1.1

2. ID3v2:在1998年,由多个贡献者创建了一个称为ID3v2的新规范。[13]尽管它的名称为ID3,但其结构与ID3v1有很大不同。

ID3v2标签的大小可变,通常出现在文件的开头,这有助于流媒体,因为只要文件开始流传输,元数据就基本上可用,而不是像ID3v1那样要求首先读取整个文件。 ID3v2标签由许多帧组成,每个帧包含一个元数据。例如,TIT2框架包含标题,而WOAR框架包含艺术家网站的URL。帧的最大长度为16MB,而标签的总大小限制为256MB。通过不仅在ISO-8859-1中而且在Unicode中都允许对字符串进行编码,解决了国际化问题。 ID3v2进一步细分为3个版本,分别为ID3v2.2,ID3v2.3和ID3v2.4,它们之间的帧略有变化。

ID3匕首:

ID3标签可以通过多种方式进行编辑。在某些平台上,可以通过在文件管理器中查看扩展信息来编辑文件的属性。此外,大多数音频播放器都允许编辑单个或成组的文件。编辑文件组通常称为“批处理标记”。还有一些专门的应用程序,称为标记程序,专门用于编辑标记和相关任务。某些功能(例如puddletag)提供了高级功能,例如高级批处理标记或基于正则表达式的编辑。

下面是实现自己的标记器的代码。

例子:

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.

以下是用于实现自己的标记器的C代码:

// C program for ID3 tagging of music files
#include 
#include 
#include 
  
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;
}

注意:运行代码的文件夹应包含input.mp3文件。

参考:
http://id3.org/id3v2.3.0
https://zh.wikipedia.org/wiki/ID3#ID3v2

想要从精选的最佳视频中学习和练习问题,请查看有关从基础到高级C++的C++基础课程以及有关语言和STL的C++ STL课程。要完成从学习语言到DS Algo等的更多准备工作,请参阅“完整面试准备课程”