⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 id3tag.c

📁 本程序为ST公司开发的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/************************************************** * * id3tag.c * * CVS ID:   $Id: id3tag.c,v 1.46 2007/11/08 14:18:26 trubac Exp $ * Author:   Jiri Sedmik [JS] - STM * Date:     $Date: 2007/11/08 14:18:26 $ * Revision: $Revision: 1.46 $ *  * Description: *  *  *************************************************** *  * COPYRIGHT (C) ST Microelectronics  2005 *            All Rights Reserved * **************************************************** * * STM CVS Log: * * $Log: id3tag.c,v $ * Revision 1.46  2007/11/08 14:18:26  trubac * Fix for bitrate parser lock inside random data stream * * Revision 1.45  2007/11/06 10:34:41  belardi * Removed code to treat TrackNo for ID3v1.1 as special case and not convert it to UTF-8 * * Revision 1.44  2007/09/11 16:00:07  belardi * Bug fix to avoid overflowing song_info.info array when long tags are present * * Revision 1.43  2007/09/11 14:14:47  sedmik * fix for multiple comments (only one occurrence of comment is stored for id3v2) * * Revision 1.42  2007/09/11 13:34:56  trubac * ID3v2 decoding function skips another comment frames if they are more * * Revision 1.41  2007/09/10 20:02:52  trubac * added test of language code to single byte endoded fields * * Revision 1.40  2007/09/10 18:39:33  trubac * workaround for ISO 639-2 language codes possibly present in ID3 comments * * Revision 1.39  2007/09/10 15:49:36  trubac * Update related to possible string array overflow * * Revision 1.38  2007/07/24 14:17:45  belardi * Fix bug of UTF8 conversion in Track number filed for v1.1 ID3 tags. * * Revision 1.37  2007/07/09 13:59:23  trubac * Fix for ID3v2 decoding, wrong cache filling * * Revision 1.36  2007/06/29 13:18:13  belardi * Added support for Track Number in ID3 v1.1 and v2.x * * Revision 1.35  2007/03/27 10:01:46  trubac * fixed Genre = 0 situation * * Revision 1.34  2007/03/19 14:28:04  trubac * directory names shrinking fixed * * Revision 1.33  2007/03/15 12:53:11  sedmik * fix for id3v2 empty frames * * Revision 1.32  2006/12/11 14:41:31  trubac * bitrate parsing slightly improved * * Revision 1.31  2006/12/08 14:42:09  trubac * Bitrate parser improvement * * Revision 1.30  2006/11/20 09:18:12  chlapik * fixed bugs in GetBitrate(), added workaround for mp1 in DecodeInfo2() * * Revision 1.29  2006/10/31 14:14:19  chlapik * support for Layer I & II: * - Layer type, sample rate and channel number are determined by BitrateParser before playback * - mp3 decoder checks if these parameters found in valid header matches, if not scan bitstream per bytes * * Revision 1.28  2006/10/25 15:22:09  trubac * fixed problem of last frame in ID3.22 tag * * Revision 1.27  2006/10/17 09:54:06  trubac * new id3 tag strings handling + new tag infos in song_info * * Revision 1.26  2006/10/09 12:51:05  trubac * Bitrate parser extensions, more info in song info * * Revision 1.25  2006/10/05 13:49:22  trubac * Improvement, code reduction of ID3v1 decoding * * Revision 1.24  2006/09/27 19:50:04  belardi * Removed (global) unused variables * * Revision 1.23  2006/09/25 16:06:33  belardi * better comment * * Revision 1.22  2006/09/25 15:52:35  belardi * Added #pragma to force ARM compilation in a function that fails otherwise * * Revision 1.21  2006/09/22 14:00:35  belardi * Added configuration.h to list of includes * * Revision 1.20  2006/09/15 19:42:06  belardi * Merged the m8_cav2_cm80506_cs3563. * - renamed CASE labels * * ***************************************************/#include <string.h>#include "configuration.h"#include "mp3_common.h"#include "id3tag.h"#include "tag.h"								//[LL] added#include "utf8.h"#include "ioread.h"#include "filesys.h"#include "debug.h"//extern uint8 tag_length; // [RB] unusedextern uint8 tag_buf[];   //[LL] moved to tag.c; changed name id3_tag[]extern uint8 filesys_sectbuf[];//int32 m,n; // [RB] unusedstatic const unsigned int bitstreamTypes[] = {    0x00000000, // undefined    0x4D504733, // MPG3    0x4D504732, // MPG2    0x4D504731  // MPG1};	/* local functions *//* void ID3_ExtractID3v1(unsigned int pos);	*//* void ID3_ExtractID3v2(unsigned int pos, unsigned int lstart); */GRESULT	GetBitRate(t_SongInfos *songi);/*** Extract the ID3 TAG from the Selected File ***/int ID3_TagDecode(t_SongInfos *song_info, uint32 count_down){//	t_SongInfos temp_song_info;		uint32 identifier = 0;	uint8 * buffer;		int error;	    /* initialise internall buffer for ID3 tag recognition */		buffer = tag_buf; 		//temp_song_info = &song_info;	//work with local copy of file informations	//memcpy(&temp_song_info, song_info, sizeof(t_SongInfos));		/* Test ID3 tag ver 1 */	if (XAR_SeekFile (song_info, song_info->size - 128, 0) == S_OK)	{		if (XAR_ReadFile (song_info, buffer, 128,IO_READ_CACHE)<128 )			return E_READ_FAILURE;		else		{			identifier = (buffer[0] << 16) | (buffer[1] << 8) | (buffer[2]);			if ( ID3_TAG_V1 == identifier )			{				error = ID3_ExtractID3v1(song_info,buffer);				if (S_OK != error)		//pass error code to upper func					return error;			}		}		}			XAR_SeekFile(song_info, 0, 0);		ID3_ExtractID3v2(song_info ,buffer,count_down);		//temp_song_info = &song_info;	//reinit local copy of file informations	//memcpy(&temp_song_info, song_info, sizeof(t_SongInfos));  //JS commented, not needed now	XAR_SeekFile (song_info, 0, 0);	return S_OK;}uint8 const ID3v1_FIELDS[] = { ALBUM_TITLE,ID3_TAG_V1_ALBUM_POSITION,ID3_TAG_V1_ITEM_LENGTH,							SONG_TITLE,ID3_TAG_V1_TITLE_POSITION,ID3_TAG_V1_ITEM_LENGTH,							ARTIST,ID3_TAG_V1_ARTIST_POSITION,ID3_TAG_V1_ITEM_LENGTH,							YEAR,ID3_TAG_V1_YEAR_POSITION,4,							COMMENT,ID3_TAG_V1_COMMENT_POSITION,ID3_TAG_V1_ITEM_LENGTH,							TRACK_NO,ID3_TAG_V1_COMMENT_POSITION,1, /* not an error, Track number is contained in the Comment field */							GENRE,ID3_TAG_V1_GENRE_POSITION,1,							0 };							/*** Extract the ID3 TAG - version 1***/int ID3_ExtractID3v1(t_SongInfos *song_info,uint8 * buffer){	/* found ID3 Tag version 1 - exctract info  (compatible v1.0 and v1.1)*/	uint8 length;	uint8 *len_ptr;	GRESULT wlen;	t_conv_param p;	int id = 0,ID,IDpos,IDlen;	uint8 temp_buf[ID3V1_MAX_TEXT_SIZE*2];	//for charset conversions	/* allocate and assign memory for tag v1 infos */ 	len_ptr = song_info->strings + song_info->strtop;		while(ID3v1_FIELDS[id] !=0 )	{		ID = ID3v1_FIELDS[id++];		IDpos = ID3v1_FIELDS[id++];		IDlen = ID3v1_FIELDS[id++];		if ((song_info->n_infos < XSONG_INFO_TAGS) && (song_info->strtop < MAX_STRINGS_SIZE - 2))		{			if(ID == GENRE)			     length = 1;			else if (ID == TRACK_NO)			{				/* ID3v1.1 track number stored in last byte of comment field */				/* but only if below condition is met */				if ((buffer[IDpos + 28] == 0) && (buffer[IDpos + 29] != 0))				{					length = 1;					IDpos = IDpos + 29;				}				else				{					length = 0;				}			}			else			     length = id3_v1_len(&(buffer[IDpos]),IDlen);			     			if(length>0)			{#if 0				/* [RB] this code created a special case for TrackNo */				/* to return it as single byte instead of UTF-8 as all others */				/* It seemed more efficient but it creates confusion in the Host */				/* and is not compliant with CIS, so it's removed */				if (ID == TRACK_NO)				{					*(len_ptr + 1) = buffer[IDpos];					wlen = 1;				}				else#endif				{			    	estrcpy(temp_buf, &(buffer[IDpos]), length);					str_convert_byte2int(temp_buf, length);						p.be = 1;					p.limit = wmin(255, MAX_STRINGS_SIZE - song_info->strtop - 1);					p.trunc = 0;					wlen = WideStringToUTF8((uint8*)temp_buf,len_ptr+1, length, &p );				}				if((wlen>0)&&(wlen<256))				{										*len_ptr = wlen;				 	song_info->infos[song_info->n_infos].tag_version = 1;      				song_info->infos[song_info->n_infos].enc_of_src = TEXT_ENCODING_ISO_8859_1;				 					 	song_info->infos[song_info->n_infos].info_type = (t_SongTagType) ID;				 	song_info->infos[song_info->n_infos].string_offset = song_info->strtop;				 	song_info->strtop += (wlen + 1);				 	len_ptr += (1 + wlen);				 	song_info->n_infos++;				 					 					}			}		}			}	song_info->end_offset = song_info->size - 128;	//default length of v1 tag	return S_OK;  }/*** Extract the ID3 TAG - version 2 ***/int write_byte(t_SongInfos *si, uint8 b){  if(si->strtop >= MAX_STRINGS_SIZE)        // [OT] to avoid strings array overflow     return 0;    if (si->strings[si->infos[si->n_infos].string_offset] >= ID3V2_MAX_TEXT_SIZE)   // check current length    return 0;  if (si->strings[si->infos[si->n_infos].string_offset] == 0)   // pointer shift at beginning    si->strtop++;  *(si->strings + si->strtop) = b;  si->strtop++;  (si->strings[si->infos[si->n_infos].string_offset])++;  return 1;}int write_utf8(t_SongInfos *si, uint16 w){	if(w<=0x7f)		return write_byte(si,w);	if(w<=0x7ff)	{		if(write_byte(si, 0xC0 | (w >> 6)))		{			return write_byte(si, 0x80 | (w & 0x3F));		}		return 0;	}			if(write_byte(si, 0xE0 | (w >> 12)))	{		if(write_byte(si, 0x80 | (0x3f & (w >> 6))))		{			return write_byte(si, 0x80 | (w & 0x3F));		}			}	return 0;}int ID3_ExtractID3v2(t_SongInfos *song_info, uint8 * buffer, uint32 count_down ){	/* found ID3 Tag version 2 - exctract info */	int32		p,n,cnt,chcnt,i,cnt0;	int     comment = 0;	uint16 		word; 				// pointer inside ID3 tag	ID32_PROCESSING_ENUM	processing_switch = ID32_FIND_FRAME;  //general functionality switch (find frame, parse info from frame)	uint32		frID,frflags,id_be;	uint32		pos,id32rev,id32flags,id_data,id_frtop;	uint32 		load_pos,cmp_enc,gr_iden;static uint32 v2_length;		uint32 		identifier = 0,utf8_conv;	t_TextEncoding id32_encoding;	GRESULT 	res;		/* get length of id3 tag version 2: 7 lsb bits valid on each byte */	/* fill info struct, to inform upper layer funcs where mp3 decoder can start inside file */ 		/* Test ID3 tag ver 2 */	if ( XAR_ReadFile(song_info, buffer, 10, IO_READ_CACHE) < 10 )		{		 XAR_SeekFile (song_info, 0, 0);		 return E_READ_FAILURE;	}	else		{/*			identifier = (buffer[0] << 16) | (buffer[1] << 8) | (buffer[2]);	    if ( 0x524946 != identifier )	    	while(1);*/			identifier = (buffer[0] << 16) | (buffer[1] << 8) | (buffer[2]);		XAR_SeekFile (song_info, 0, 0);		if ( ID3_TAG_V2 != identifier )		{		 //while(1); // debug !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!				return S_FALSE;		}	}			 	 	v2_length = ((buffer[ID3_TAG_V2_LENGTH_POSITION] & 0x7f) <<21) 	                | ((buffer[ID3_TAG_V2_LENGTH_POSITION+1] & 0x7f) <<14) 	                | ((buffer[ID3_TAG_V2_LENGTH_POSITION+2] & 0x7f) <<7) 	                | (buffer[ID3_TAG_V2_LENGTH_POSITION+3] & 0x7f) ;	if((v2_length+ID3_TAG_V2_HEADER_LENGTH)<ID3_BUFFER_LENGTH)		res = XAR_ReadFile(song_info, buffer, v2_length+ID3_TAG_V2_HEADER_LENGTH, IO_READ_CACHE);		else		res = XAR_ReadFile(song_info, buffer, ID3_BUFFER_LENGTH, IO_READ_CACHE);			load_pos = 0;	// what is currently in buffer beginning		if(!res)		return E_READ_FAILURE;	if (count_down==0)			//if ID3 tag is too long, it's  possible to use timeout checking (input nonzero value)		count_down = v2_length + ID3_TAG_V2_HEADER_LENGTH;	// OT 		v2_length += ID3_TAG_V2_HEADER_LENGTH;		song_info->start_offset = v2_length;		id32rev = buffer[ID3_TAG_V2_VERSION_POSITION];	if((id32rev>4)||(id32rev<2))		return E_FAIL;		id32flags = buffer[ID3_TAG_V2_FLAGS_POSITION];	//unsync = (0 != (id32flags&128));	pos = ID3_TAG_V2_HEADER_LENGTH;	p = id32flags&0x4f;	if(p)	{		if(p&0xf)			return E_FAIL;				// extended header present		switch(id32rev)		{			case 3:				pos = buffer[13] + 14;				break;			case 4:				pos = 10+(buffer[11]<<14)+(buffer[12]<<7)+buffer[13];				break;			default:				return E_FAIL;					}			}			 while(1) {	switch(processing_switch)	{		case ID32_FIND_FRAME:			// evaluate frame header size			if(id32rev==2)				p = 6;			else				p = 10;						if(((pos+p)>=v2_length) || (song_info->strtop >= MAX_STRINGS_SIZE))			{				processing_switch = ID32_TERMINATE;				break;			}						if((pos+p)>(load_pos+ID3_BUFFER_LENGTH))			{				n = pos&(~3);   // new load_pos				p = wmin(n+ID3_BUFFER_LENGTH,v2_length);				cnt = p - n;				if(cnt <= 0)				{					processing_switch = ID32_TERMINATE;					break;				}								// how many bytes should be prepared in buffer				if((n - load_pos)<ID3_BUFFER_LENGTH)	// check if data follow continuously				{					p = ID3_BUFFER_LENGTH - (n - load_pos);		// count of present bytes to keep					memcpy(buffer, buffer + (n - load_pos), p );					cnt -= p  ;				}				else	// not continuous jump ( frame is big )				{

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -