📄 id3.c
字号:
//#include "stdio.h"
#include "../include/audio_main.h"
#include "../include/audio_globals.h"
#include "ID3.H"
#include "../include/file_access.h"
#ifdef LRC3_SUPPORT
extern int LRC3_State;
#endif
#define DEBUG_OPT 0
const char* ID3_GenreTable[] =
{
"Blues", "Classic Rock", "Country", "Dance", "Disco", "Funk",
"Grunge", "Hip-Hop" , "Jazz", "Metal", "New Age", "Oldies",
"Other", "Pop", "R&B", "Rap", "Reggae", "Rock",
"Techno", "Industrial", "Alternative", "Ska", "Death Metal", "Pranks",
"Soundtrack", "Euro-Techno", "Ambient", "Trip-Hop", "Vocal", "Jazz+Funk",
"Fusion", "Trance", "Classical", "Instrumental", "Acid", "House",
"Game", "Sound Clip", "Gospel", "Noise", "Alt. Rock", "Bass",
"Soul", "Punk", "Space", "Meditative", "Instrum. Pop", "Instrum. Rock",
"Ethnic", "Gothic", "Darkwave", "Techno-Indust.", "Electronic", "Pop-Folk",
"Eurodance", "Dream", "Southern Rock", "Comedy", "Cult", "Gangsta",
"Top 40", "Christian Rap", "Pop/Funk", "Jungle", "Native American", "Cabaret",
"New Wave", "Psychadelic", "Rave", "Showtunes", "Trailer", "Lo-Fi",
"Tribal", "Acid Punk", "Acid Jazz", "Polka", "Retro", "Musical",
"Rock & Roll", "Hard Rock", "Folk", "Folk/Rock", "National Folk", "Swing",
"Fusion", "Bebob", "Latin", "Revival", "Celtic", "Bluegrass",
"Avantgarde", "Gothic Rock", "Progress. Rock", "Psychadel. Rock", "Symphonic Rock", "Slow Rock",
"Big Band", "Chorus", "Easy Listening", "Acoustic", "Humour", "Speech",
"Chanson", "Opera", "Chamber Music", "Sonata", "Symphony", "Booty Bass",
"Primus", "Porn Groove", "Satire",
//extended
"Slow Jam", "Club", "Tango", "Samba", "Folklore", "Ballad",
"Power Ballad", "Rhythmic Soul", "Freestyle", "Duet", "Punk Rock", "Drum Solo",
"A Capella", "Euro-House", "Dance Hall", "Goa", "Drum & Bass", "Club-House",
"Hardcore", "Terror", "Indie", "BritPop", "Negerpunk", "Polsk Punk",
"Beat", "Christian Gangsta Rap", "Heavy Metal", "Black Metal", "Crossover", "Contemporary Christian",
"Christian Rock",
// winamp 1.91 genres
"Merengue", "Salsa", "Thrash Metal",
// winamp 1.92 genres
"Anime", "Jpop", "Synthpop", NULL
};
#ifdef MTP_INCLUDE
const char* ID3_GenreTable[] =
{
"Blues", "Classic Rock", "Country", "Dance", "Disco", "Funk",
"Grunge", "Hip-Hop" , "Jazz", "Metal", "New Age", "Oldies",
"Other", "Pop", "R&B", "Rap", "Reggae", "Rock",
"Techno", "Industrial", "Alternative", "Ska", "Death Metal", "Pranks",
"Soundtrack", "Euro-Techno", "Ambient", "Trip-Hop", "Vocal", "Jazz+Funk",
"Fusion", "Trance", "Classical", "Instrumental", "Acid", "House",
"Game", "Sound Clip", "Gospel", "Noise", "Alt. Rock", "Bass",
"Soul", "Punk", "Space", "Meditative", "Instrum. Pop", "Instrum. Rock",
"Ethnic", "Gothic", "Darkwave", "Techno-Indust.", "Electronic", "Pop-Folk",
"Eurodance", "Dream", "Southern Rock", "Comedy", "Cult", "Gangsta",
"Top 40", "Christian Rap", "Pop/Funk", "Jungle", "Native American", "Cabaret",
"New Wave", "Psychadelic", "Rave", "Showtunes", "Trailer", "Lo-Fi",
"Tribal", "Acid Punk", "Acid Jazz", "Polka", "Retro", "Musical",
"Rock & Roll", "Hard Rock", "Folk", "Folk/Rock", "National Folk", "Swing",
"Fusion", "Bebob", "Latin", "Revival", "Celtic", "Bluegrass",
"Avantgarde", "Gothic Rock", "Progress. Rock", "Psychadel. Rock", "Symphonic Rock", "Slow Rock",
"Big Band", "Chorus", "Easy Listening", "Acoustic", "Humour", "Speech",
"Chanson", "Opera", "Chamber Music", "Sonata", "Symphony", "Booty Bass",
"Primus", "Porn Groove", "Satire",
//extended
"Slow Jam", "Club", "Tango", "Samba", "Folklore", "Ballad",
"Power Ballad", "Rhythmic Soul", "Freestyle", "Duet", "Punk Rock", "Drum Solo",
"A Capella", "Euro-House", "Dance Hall", "Goa", "Drum & Bass", "Club-House",
"Hardcore", "Terror", "Indie", "BritPop", "Negerpunk", "Polsk Punk",
"Beat", "Christian Gangsta Rap", "Heavy Metal", "Black Metal", "Crossover", "Contemporary Christian",
"Christian Rock",
// winamp 1.91 genres
"Merengue", "Salsa", "Thrash Metal",
// winamp 1.92 genres
"Anime", "Jpop", "Synthpop", NULL
};
#else
unsigned char ID3TempBuff[MAX_ID3_FIND_SIZE];
stID3V2XInfoType ID3V2XInfo;
#endif
extern unsigned char UTF8_Targetbuf;
/******************************************************
Name: ID3_SeekData
Desc: Seek data in a File
Param: fd 文件指针 offset 偏移 iwhence 方式
Return: 0-失败 1-成功
Global: 无
Note: 无
Author: FSH
Log:
/******************************************************/
int ID3_SeekData(int fd, int offset, int iwhence)
{
int result;
result = RKFIO_FSeek((MY_FILE*)fd, offset, iwhence);
return result;
}
/******************************************************
Name: ID3_ReadData
Desc: Read data from a File
Param: fd 文件指针 buff 缓冲区 iSize 大小
Return: 0-失败 1-成功
Global: 无
Note: 无
Author: FSH
Log:
/******************************************************/
int ID3_ReadData(int fd, char *buff, int iSize)
{
int result;
result = RKFIO_FRead((MY_FILE*)fd, buff, iSize);
return result;
}
#ifdef MTP_INCLUDE
/******************************************************
Name: ID3_MakeAscii2Unicode
Desc: 将ASCII转为UNICODE
Param: 源缓冲区,目标缓冲区,源最大长度,目标最大长度
Return:
Global: 无
Note: 无
Author: FSH
Log:
/******************************************************/
void ID3_MakeAscii2Unicode(char *SourceBuf, char *TargetBuf, int iSourceMaxSize, int iTargetMaxSize)
{
//int i,j;
if ((SourceBuf[0] != NULL) && (TargetBuf[0] == NULL))
{
ID3_MakeWideChar2Unicode(SourceBuf, TargetBuf, iSourceMaxSize);
}
}
/******************************************************
Name: ID3_MakeWideChar2Unicode
Desc: 将WIDE CHAR转为UNICODE
Param: 源缓冲区,目标缓冲区,源最大长度
Return:
Global: 无
Note: 无
Author: FSH
Log:
/******************************************************/
void ID3_MakeWideChar2Unicode(char *SourceBuf, char *TargetBuf, int iSourceMaxSize)
{
int iStringSize;
int i;
if (iSourceMaxSize > 1)
{
for (i = iSourceMaxSize - 1 ; i > 0; i--)
{
if (SourceBuf[i] != ' ' && SourceBuf[i] != 0x00)
{
break;
}
}
if (i == 0)
{
return;
}
}
else
{
i = 0;
if (!iSourceMaxSize || SourceBuf[i] == ' ' || SourceBuf[i] == 0x00)
{
return;
}
}
if (i != (iSourceMaxSize - 1))
{
memset(&SourceBuf[i+1], 0x00, iSourceMaxSize - (i + 1));
iSourceMaxSize = i + 1;
}
iStringSize = UNI_ConvertStringToUnicode(SourceBuf, &TargetBuf[1], iSourceMaxSize);
if (iStringSize)
{
TargetBuf[0] = (iStringSize / 2) + 1; // Length field , The length must include space for null value.
}
}
#endif
/******************************************************
Name: ID3_GetID3_V1X
Desc: 读取ID3 V1信息
Param: 文件指针,ID3信息,字符缓冲
Return:
Global: 无
Note: 无
Author: FSH
Log:
/******************************************************/
int ID3_GetID3_V1X(int fHandle, pstID3V2XInfoType pstID3V2XInfo, char *tempbuf)
{
pstID3InfoType pID3Info;
int result;
result = ID3_SeekData(fHandle, MAX_ID3V1_SIZE, FSEEK_END);
result = ID3_ReadData(fHandle, tempbuf, MAX_ID3V1_SIZE);
if (result <= 0)
{
return -1;
}
pID3Info = (pstID3InfoType)tempbuf;
if (!memcmp((INT8U *)pID3Info->mTAG, "TAG", 3))
{
#ifdef MTP_INCLUDE
if (pstID3V2XInfo->mMetaData[ID3_TITLE][0] < 2)
{
ID3_MakeWideChar2Unicode(pID3Info->mTitle , pstID3V2XInfo->mMetaData[ID3_TITLE] , 30);
}
if (pstID3V2XInfo->mMetaData[ID3_ARTIST][0] < 2)
{
ID3_MakeWideChar2Unicode(pID3Info->mArtist, pstID3V2XInfo->mMetaData[ID3_ARTIST], 30);
}
if (pstID3V2XInfo->mMetaData[ID3_ALBUM][0] < 2)
{
ID3_MakeWideChar2Unicode(pID3Info->mAlbum , pstID3V2XInfo->mMetaData[ID3_ALBUM] , 30);
}
if ((pstID3V2XInfo->mMetaData[ID3_GENRE][0] < 2) && (pID3Info->mGenre < ID3_GENRE_MAX_CNT))
{
ID3_MakeWideChar2Unicode(ID3_GenreTable[pID3Info->mGenre], pstID3V2XInfo->mMetaData[ID3_GENRE] , 30);
}
if ((pID3Info->mTrack != NULL) && (pID3Info->mTrack < 30) && (pstID3V2XInfo->mTrack == NULL))
{
pstID3V2XInfo->mTrack = pID3Info->mTrack;
}
if ((pstID3V2XInfo->mYear[0] < 2) && (pID3Info->mYear[0] && pID3Info->mYear[1] && pID3Info->mYear[2] && pID3Info->mYear[3]))
{
if (pID3Info->mYear[0] != 0x20 && pID3Info->mYear[1] != 0x20
&& pID3Info->mYear[2] != 0x20 && pID3Info->mYear[3] != 0x20)
{
memset(pstID3V2XInfo->mYear, 0x00, MAX_ID3V2_YEAR);
pstID3V2XInfo->mYear[0] = 9;
pstID3V2XInfo->mYear[1] = pID3Info->mYear[0];
pstID3V2XInfo->mYear[3] = pID3Info->mYear[1];
pstID3V2XInfo->mYear[5] = pID3Info->mYear[2];
pstID3V2XInfo->mYear[7] = pID3Info->mYear[3];
}
}
#else
if ((pID3Info->mTitle[0] != NULL) && (pstID3V2XInfo->mMetaData[ID3_TITLE][0] == NULL))
{
RKmemcpy(pstID3V2XInfo->mMetaData[ID3_TITLE], pID3Info->mTitle, 30);
pstID3V2XInfo->mMetaData[ID3_TITLE][30] = 0;
}
if ((pID3Info->mArtist[0] != NULL) && (pstID3V2XInfo->mMetaData[ID3_ARTIST][0] == NULL))
{
RKmemcpy(pstID3V2XInfo->mMetaData[ID3_ARTIST], pID3Info->mArtist, 30);
pstID3V2XInfo->mMetaData[ID3_ARTIST][30] = 0;
}
if ((pID3Info->mAlbum[0] != NULL) && (pstID3V2XInfo->mMetaData[ID3_ALBUM][0] == NULL))
{
RKmemcpy(pstID3V2XInfo->mMetaData[ID3_ALBUM], pID3Info->mAlbum, 30);
pstID3V2XInfo->mMetaData[ID3_ALBUM][30] = 0;
}
if (pID3Info->mGenre < 148)
{
//RKmemcpy(pstID3V2XInfo->mMetaData[ID3_ALBUM],pID3Info->mAlbum,30);
RKmemcpy(pstID3V2XInfo->mMetaData[ID3_GENRE], ID3_GenreTable[pID3Info->mGenre], 30);
pstID3V2XInfo->mMetaData[ID3_GENRE][30] = 0;
}
#endif
#ifdef LRC3_SUPPORT
LRC3_State = 1;
#endif
return 1;
}
return -1;
}
/******************************************************
Name: ID3_GetID3V2xHeader
Desc: 读取ID3 V2头
Param: 字符缓冲,帧偏移,版本
Return:
Global: 无
Note: 无
Author: FSH
Log:
/******************************************************/
int ID3_GetID3V2xHeader(unsigned char *tempbuf, int *iFrameOffset, int *iVersion)
{
int iTotalSize;
pID3V2XHeaderType pID3V2XHeader;
pID3V2XHeader = (pID3V2XHeaderType)tempbuf;
if (pID3V2XHeader->mVersion > 4) // because big endian
{
return -1; //not support
}
*iVersion = (int)pID3V2XHeader->mVersion;
//iTotalSize = (ID3_GetIntValue(pID3V2XHeader->mSize) + (int)sizeof(ID3V2XHeaderType));
iTotalSize = ID3_GetIntValue(pID3V2XHeader->mSize); // changed by phc, 2007-11-08
if (pID3V2XHeader->mFlags & ID3_FLAG_FOOTER)
{
iTotalSize += sizeof(ID3V2XFooterType);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -