xref: /MusicPlayer2/MusicPlayer2/AudioTagOld.cpp (revision 1598e86c976ecacad15f3f6383421bb42cf540a7)
1 #include "stdafx.h"
2 #include "AudioTagOld.h"
3 #include "FilePathHelper.h"
4 #include "Common.h"
5 
6 const string jpg_head{ '\xff', '\xd8', '\xff' };
7 const string jpg_tail{ '\xff', '\xd9' };
8 const string png_head{ '\x89', '\x50', '\x4e', '\x47' };
9 const string png_tail{ '\x49', '\x45', '\x4e', '\x44', '\xae', '\x42', '\x60', '\x82' };
10 const string gif_head{ "GIF89a" };
11 const string gif_tail{ '\x80', '\x00', '\x00', '\x3b' };
12 const string bmp_head{ "BM" };
13 
CAudioTagOld(HSTREAM hStream,SongInfo & song_info,AudioType type)14 CAudioTagOld::CAudioTagOld(HSTREAM hStream, SongInfo & song_info, AudioType type)
15     : m_hStream{ hStream }, m_song_info{ song_info }, m_type{ type }
16 {
17     ASSERT(!m_song_info.file_path.empty());
18 }
19 
~CAudioTagOld()20 CAudioTagOld::~CAudioTagOld()
21 {
22 }
23 
GetAudioLyric()24 wstring CAudioTagOld::GetAudioLyric()
25 {
26 	string tag_contents;
27 	if (m_type == AU_MP3)
28 	{
29 		tag_contents = GetID3V2TagContents();
30 		if (!tag_contents.empty())
31 		{
32 			wstring lyric_str = GetSpecifiedId3V2Tag(tag_contents, "USLT");
33 			return lyric_str;
34 		}
35 	}
36 	else if(m_type == AU_MP4)
37 	{
38 		tag_contents = GetMp4TagContents();
39 		if (!tag_contents.empty())
40 		{
41 			wstring lyric_str = GetSpecifiedUtf8Tag(tag_contents, "Lyrics");
42 			return lyric_str;
43 		}
44 	}
45     else if (m_type == AU_FLAC)
46     {
47         GetFlacTagContents(m_song_info.file_path, tag_contents);
48 #ifdef _DEBUG
49         CFilePathHelper helper(m_song_info.file_path);
50         CCommon::SaveDataToFile(tag_contents, L"D:\\Temp\\audio_tags\\" + helper.GetFileName() + L".bin");
51 #endif
52         if (!tag_contents.empty())
53         {
54             wstring lyric_str = GetSpecifiedFlacTag(tag_contents, "Lyrics");
55             return lyric_str;
56         }
57     }
58 
59 	return wstring();
60 }
61 
WriteMp3Tag(LPCTSTR file_path,SongInfo song_info,bool & text_cut_off)62 bool CAudioTagOld::WriteMp3Tag(LPCTSTR file_path, SongInfo song_info, bool & text_cut_off)
63 {
64     song_info.Normalize();
65     string title, artist, album, year, comment;
66     title = CCommon::UnicodeToStr(song_info.title, CodeType::ANSI);
67     artist = CCommon::UnicodeToStr(song_info.artist, CodeType::ANSI);
68     album = CCommon::UnicodeToStr(song_info.album, CodeType::ANSI);
69 
70 	year = CCommon::UnicodeToStr(song_info.get_year(), CodeType::ANSI);
71 	comment = CCommon::UnicodeToStr(song_info.comment, CodeType::ANSI);
72 	TAG_ID3V1 id3{};
73 	CCommon::StringCopy(id3.id, 3, "TAG");
74 	CCommon::StringCopy(id3.title, 30, title.c_str());
75 	CCommon::StringCopy(id3.artist, 30, artist.c_str());
76 	CCommon::StringCopy(id3.album, 30, album.c_str());
77 	CCommon::StringCopy(id3.year, 4, year.c_str());
78 	CCommon::StringCopy(id3.comment, 28, comment.c_str());
79 	id3.track[1] = song_info.track;
80 	id3.genre = song_info.genre_idx;
81 	text_cut_off = (title.size() > 30 || artist.size() > 30 || album.size() > 30 || year.size() > 4 || comment.size() > 28);
82 
83 	std::fstream fout;
84 	fout.open(file_path, std::fstream::binary | std::fstream::out | std::fstream::in);
85 	if (fout.fail())
86 		return false;
87 	fout.seekp(-128, std::ios::end);		//移动到文件末尾的128个字节处
88 	//char buff[4];
89 	//fout.get(buff, 4);
90 	//if (buff[0] == 'T'&&buff[1] == 'A'&&buff[2] == 'G')		//如果已经有ID3V1标签
91 	//{
92 	fout.write((const char*)&id3, 128);		//将TAG_ID3V1结构体的128个字节写到文件末尾
93 	fout.close();
94 	//}
95 	//else
96 	//{
97 	//	//文件没有ID3V1标签,则在文件末尾追加
98 	//	fout.close();
99 	//	fout.open(file_name, std::fstream::binary | std::fstream::out | std::fstream::app);
100 	//	if (fout.fail())
101 	//		return false;
102 	//	fout.write((const char*)&id3, 128);
103 	//	fout.close();
104 	//}
105 	return true;
106 }
107 
GetID3V1Tag()108 bool CAudioTagOld::GetID3V1Tag()
109 {
110 	const TAG_ID3V1* id3;
111 	id3 = (const TAG_ID3V1*)BASS_ChannelGetTags(m_hStream, BASS_TAG_ID3);
112 	bool success;
113 	if (id3 != nullptr)
114 	{
115 		string temp;
116 		temp = string(id3->title, 30);
117 		CCommon::DeleteEndSpace(temp);
118 		if (!temp.empty() && temp.front() != L'\0')
119 			m_song_info.title = CCommon::StrToUnicode(temp, CodeType::AUTO);
120 
121 		temp = string(id3->artist, 30);
122 		CCommon::DeleteEndSpace(temp);
123 		if (!temp.empty() && temp.front() != L'\0')
124 			m_song_info.artist = CCommon::StrToUnicode(temp, CodeType::AUTO);
125 
126 		temp = string(id3->album, 30);
127 		CCommon::DeleteEndSpace(temp);
128 		if (!temp.empty() && temp.front() != L'\0')
129 			m_song_info.album = CCommon::StrToUnicode(temp, CodeType::AUTO);
130 
131 		temp = string(id3->year, 4);
132 		CCommon::DeleteEndSpace(temp);
133 		if (!temp.empty() && temp.front() != L'\0')
134 			m_song_info.year = atoi(temp.c_str());
135 
136 		temp = string(id3->comment, 28);
137 		CCommon::DeleteEndSpace(temp);
138 		if (!temp.empty() && temp.front() != L'\0')
139 			m_song_info.comment = CCommon::StrToUnicode(temp, CodeType::AUTO);
140 		m_song_info.track = id3->track[1];
141 		m_song_info.genre = CAudioCommon::GetGenre(id3->genre);
142 		m_song_info.genre_idx = id3->genre;
143 
144 		bool id3_empty;		//ID3V1标签信息是否为空
145 		id3_empty = (m_song_info.IsTitleEmpty() && m_song_info.IsArtistEmpty() && m_song_info.IsAlbumEmpty()
146 			&& m_song_info.track == 0 && m_song_info.IsYearEmpty());
147 		success = !id3_empty;
148 	}
149 	else
150 	{
151 		success = false;
152 	}
153 	m_song_info.tag_type = (success ? T_ID3V1 : T_OTHER_TAG);
154 	return success;
155 }
156 
GetID3V2Tag()157 bool CAudioTagOld::GetID3V2Tag()
158 {
159 	bool success;
160 	string tag_content = GetID3V2TagContents();
161 #ifdef _DEBUG
162     CFilePathHelper helper(m_song_info.file_path);
163     CCommon::SaveDataToFile(tag_content, L"D:\\Temp\\audio_tags\\" + helper.GetFileName() + L".bin");
164 #endif
165 	if (!tag_content.empty())
166 	{
167 		const int TAG_NUM{ 7 };
168 		//要查找的标签标识字符串(标题、艺术家、唱片集、年份、注释、流派、音轨号)
169 		const string tag_identify[TAG_NUM]{ "TIT2","TPE1","TALB","TYER","COMM","TCON","TRCK" };
170 		for (int i{}; i < TAG_NUM; i++)
171 		{
172 			wstring tag_info;
173 			tag_info = GetSpecifiedId3V2Tag(tag_content, tag_identify[i]);
174 			if (!tag_info.empty())
175 			{
176 				switch (i)
177 				{
178 				case 0: m_song_info.title = tag_info; break;
179 				case 1: m_song_info.artist = tag_info; break;
180 				case 2: m_song_info.album = tag_info; break;
181 				case 3: m_song_info.SetYear(tag_info.c_str()); break;
182 				case 4: m_song_info.comment = tag_info; break;
183 				case 5: m_song_info.genre = CAudioCommon::GenreConvert(tag_info); break;
184 				case 6: m_song_info.track = _wtoi(tag_info.c_str()); break;
185 				}
186 			}
187 		}
188 		CAudioCommon::TagStrNormalize(m_song_info.title);
189 		CAudioCommon::TagStrNormalize(m_song_info.artist);
190 		CAudioCommon::TagStrNormalize(m_song_info.album);
191 		bool id3_empty;		//ID3标签信息是否为空
192 		id3_empty = ((m_song_info.IsTitleEmpty()) && (m_song_info.IsArtistEmpty()) && (m_song_info.IsAlbumEmpty())
193 			&& m_song_info.track == 0 && m_song_info.IsYearEmpty());
194 		success = !id3_empty;
195 
196 	}
197 	else
198 	{
199 		success = false;
200 	}
201 	m_song_info.tag_type = (success ? T_ID3V2 : T_OTHER_TAG);
202 	return success;
203 }
204 
GetWmaTag()205 bool CAudioTagOld::GetWmaTag()
206 {
207 	string tag_content = GetWmaTagContents();
208 	if (!tag_content.empty())
209 	{
210 		m_song_info.title = GetSpecifiedUtf8Tag(tag_content, "Title");
211 		m_song_info.artist = GetSpecifiedUtf8Tag(tag_content, "Author");
212 		m_song_info.album = GetSpecifiedUtf8Tag(tag_content, "WM/AlbumTitle");
213 		m_song_info.SetYear(GetSpecifiedUtf8Tag(tag_content, "WM/Year").c_str());
214 		m_song_info.genre = GetSpecifiedUtf8Tag(tag_content, "WM/Genre");
215 		if (CCommon::StrIsNumber(m_song_info.genre))
216 		{
217 			int genre_num = _wtoi(m_song_info.genre.c_str());
218 			m_song_info.genre = CAudioCommon::GetGenre(static_cast<BYTE>(genre_num - 1));
219 		}
220 		wstring track_str = GetSpecifiedUtf8Tag(tag_content, "WM/TrackNumber");
221 		m_song_info.track = _wtoi(track_str.c_str());
222 		m_song_info.comment = GetSpecifiedUtf8Tag(tag_content, "Description");
223 
224 		return true;
225 	}
226 	return false;
227 }
228 
GetMp4Tag()229 bool CAudioTagOld::GetMp4Tag()
230 {
231 	string tag_content = GetMp4TagContents();
232 #ifdef _DEBUG
233     CFilePathHelper helper(m_song_info.file_path);
234     CCommon::SaveDataToFile(tag_content, L"D:\\Temp\\audio_tags\\" + helper.GetFileName() + L".bin");
235 #endif
236     if (!tag_content.empty())
237 	{
238 		m_song_info.title = GetSpecifiedUtf8Tag(tag_content, "Title");
239 		m_song_info.artist = GetSpecifiedUtf8Tag(tag_content, "Artist");
240 		m_song_info.album = GetSpecifiedUtf8Tag(tag_content, "Album");
241 		m_song_info.SetYear(GetSpecifiedUtf8Tag(tag_content, "Date").c_str());
242 		m_song_info.genre = GetSpecifiedUtf8Tag(tag_content, "Genre");
243 		if (CCommon::StrIsNumber(m_song_info.genre))
244 		{
245 			int genre_num = _wtoi(m_song_info.genre.c_str());
246 			m_song_info.genre = CAudioCommon::GetGenre(static_cast<BYTE>(genre_num - 1));
247 		}
248 		wstring track_str = GetSpecifiedUtf8Tag(tag_content, "TrackNumber");
249 		if(track_str.empty())
250 			track_str = GetSpecifiedUtf8Tag(tag_content, "Track");
251 		m_song_info.track = _wtoi(track_str.c_str());
252         m_song_info.comment = GetSpecifiedUtf8Tag(tag_content, "Comment");
253 
254 		return true;
255 	}
256 	return false;
257 }
258 
GetOggTag()259 bool CAudioTagOld::GetOggTag()
260 {
261 	string tag_content = GetOggTagContents();
262 	if (!tag_content.empty())
263 	{
264 		m_song_info.title = GetSpecifiedUtf8Tag(tag_content, "Title");
265 		m_song_info.artist = GetSpecifiedUtf8Tag(tag_content, "Artist");
266 		m_song_info.album = GetSpecifiedUtf8Tag(tag_content, "Album");
267 		m_song_info.SetYear(GetSpecifiedUtf8Tag(tag_content, "Date").c_str());
268 		m_song_info.genre = GetSpecifiedUtf8Tag(tag_content, "Genre");
269 		if (CCommon::StrIsNumber(m_song_info.genre))
270 		{
271 			int genre_num = _wtoi(m_song_info.genre.c_str());
272 			m_song_info.genre = CAudioCommon::GetGenre(static_cast<BYTE>(genre_num - 1));
273 		}
274 		wstring track_str = GetSpecifiedUtf8Tag(tag_content, "TrackNumber");
275 		if (track_str.empty())
276 			track_str = GetSpecifiedUtf8Tag(tag_content, "Track");
277 		m_song_info.track = _wtoi(track_str.c_str());
278         m_song_info.comment = GetSpecifiedUtf8Tag(tag_content, "Comment");
279 
280 		return true;
281 	}
282 	return false;
283 }
284 
GetApeTag()285 bool CAudioTagOld::GetApeTag()
286 {
287 	string tag_content = GetApeTagContents();
288 #ifdef _DEBUG
289     CFilePathHelper helper(m_song_info.file_path);
290     CCommon::SaveDataToFile(tag_content, L"D:\\Temp\\audio_tags\\" + helper.GetFileName() + L"_ape_tag.bin");
291 #endif
292     bool succeed{};
293 	if (!tag_content.empty())
294 	{
295 		m_song_info.title = GetSpecifiedUtf8Tag(tag_content, "Title");
296 		m_song_info.artist = GetSpecifiedUtf8Tag(tag_content, "Artist");
297 		m_song_info.album = GetSpecifiedUtf8Tag(tag_content, "Album");
298 		m_song_info.SetYear(GetSpecifiedUtf8Tag(tag_content, "Year").c_str());
299 		m_song_info.genre = GetSpecifiedUtf8Tag(tag_content, "Genre");
300 		if (CCommon::StrIsNumber(m_song_info.genre))
301 		{
302 			int genre_num = _wtoi(m_song_info.genre.c_str());
303 			m_song_info.genre = CAudioCommon::GetGenre(static_cast<BYTE>(genre_num - 1));
304 		}
305 		wstring track_str = GetSpecifiedUtf8Tag(tag_content, "TrackNumber");
306 		if (track_str.empty())
307 			track_str = GetSpecifiedUtf8Tag(tag_content, "Track");
308 		m_song_info.track = _wtoi(track_str.c_str());
309         m_song_info.comment = GetSpecifiedUtf8Tag(tag_content, "Comment");
310 
311         bool tag_empty = ((m_song_info.IsTitleEmpty()) && (m_song_info.IsArtistEmpty()) && (m_song_info.IsAlbumEmpty())
312             && m_song_info.track == 0 && m_song_info.IsYearEmpty());
313         succeed = !tag_empty;
314 	}
315     else
316     {
317         succeed = false;
318     }
319     m_song_info.tag_type = (succeed ? T_APE : T_OTHER_TAG);
320     return succeed;
321 }
322 
GetFlacTag()323 bool CAudioTagOld::GetFlacTag()
324 {
325 	string tag_content;		//整个标签区域的内容
326 	GetFlacTagContents(m_song_info.file_path, tag_content);
327 #ifdef _DEBUG
328     CFilePathHelper helper(m_song_info.file_path);
329     CCommon::SaveDataToFile(tag_content, L"D:\\Temp\\audio_tags\\" + helper.GetFileName() + L".bin");
330 #endif
331 
332     if (!tag_content.empty())
333     {
334         m_song_info.title = GetSpecifiedFlacTag(tag_content, "Title");
335         m_song_info.artist = GetSpecifiedFlacTag(tag_content, "Artist");
336         m_song_info.album = GetSpecifiedFlacTag(tag_content, "Album");
337         m_song_info.SetYear(GetSpecifiedFlacTag(tag_content, "Year").c_str());
338         if(m_song_info.IsYearEmpty())
339             m_song_info.SetYear(GetSpecifiedFlacTag(tag_content, "Date").c_str());
340         m_song_info.genre = GetSpecifiedFlacTag(tag_content, "Genre");
341         m_song_info.comment = GetSpecifiedFlacTag(tag_content, "Comment");
342         if (CCommon::StrIsNumber(m_song_info.genre))
343         {
344             int genre_num = _wtoi(m_song_info.genre.c_str());
345             m_song_info.genre = CAudioCommon::GetGenre(static_cast<BYTE>(genre_num - 1));
346         }
347         wstring track_str = GetSpecifiedFlacTag(tag_content, "TrackNumber");
348         if (track_str.empty())
349             track_str = GetSpecifiedFlacTag(tag_content, "Track");
350         m_song_info.track = _wtoi(track_str.c_str());
351 
352         CCommon::StringNormalize(m_song_info.title);
353         CCommon::StringNormalize(m_song_info.artist);
354         CCommon::StringNormalize(m_song_info.album);
355         //CCommon::StringNormalize(m_song_info.year);
356         //if (m_song_info.year.size() > 8)
357         //    m_song_info.year.clear();
358         CCommon::StringNormalize(m_song_info.genre);
359         CCommon::StringNormalize(m_song_info.comment);
360 
361         return true;
362     }
363     return true;
364 }
365 
GetTagDefault()366 bool CAudioTagOld::GetTagDefault()
367 {
368     bool tag_exist{ false };
369     tag_exist = GetID3V2Tag();
370     if (!tag_exist)
371         tag_exist = GetApeTag();
372     if (!tag_exist)
373         tag_exist = GetID3V1Tag();
374     return tag_exist;
375 }
376 
377 
GetAlbumCoverDefault(int & image_type)378 string CAudioTagOld::GetAlbumCoverDefault(int& image_type)
379 {
380     string tag_content = GetID3V2TagContents();
381     if (!tag_content.empty())
382         return FindID3V2AlbumCover(tag_content, image_type);
383     return string();
384 }
385 
GetID3V2TagContents() const386 string CAudioTagOld::GetID3V2TagContents() const
387 {
388 	string tag_content;
389     //从BASS句柄获取id3v2标签内容
390     if (m_hStream != NULL)
391     {
392         const char* id3v2;
393         id3v2 = BASS_ChannelGetTags(m_hStream, BASS_TAG_ID3V2);
394         if (id3v2 != nullptr)
395         {
396             const char* size;
397             size = id3v2 + 6;	//标签头开始往后偏移6个字节开始的4个字节是整个标签的大小
398             const int tag_size{ (size[0] & 0x7F) * 0x200000 + (size[1] & 0x7F) * 0x4000 + (size[2] & 0x7F) * 0x80 + (size[3] & 0x7F) };	//获取标签区域的总大小
399             tag_content.assign(id3v2, tag_size);	//将标签区域的内容保存到一个string对象里
400         }
401     }
402     //直接从文件获取id3v2标签内容
403     else
404     {
405         std::ifstream file{ m_song_info.file_path.c_str(), std::ios::binary };
406         if (!file.fail())
407         {
408             //从文件前10个字节获取标签大小
409             char tag_head[10];
410             file.read(tag_head, 10);
411 
412             int tag_size{};
413 
414             //id3v2标签位于文件头部,且前3个字节必须是"ID3",否则认为标签不存在
415             if (std::string(tag_head, 3) == "ID3")
416             {
417                 //读取大小
418                 tag_size = (tag_head[6] & 0x7F) * 0x200000 + (tag_head[7] & 0x7F) * 0x4000 + (tag_head[8] & 0x7F) * 0x80 + (tag_head[9] & 0x7F);	//获取标签区域的总大小
419             }
420 
421             //读取到了标签大小,开始获取标签内容
422             if (tag_size > 0)
423             {
424                 file.seekg(std::ios::beg);  //移动到文件最前面
425                 char* buff = new char[tag_size];
426                 file.read(buff, tag_size);
427                 tag_content.assign(buff, tag_size);
428                 delete[] buff;
429             }
430         }
431     }
432 	return tag_content;
433 }
434 
GetSpecifiedId3V2Tag(const string & tag_contents,const string & tag_identify)435 wstring CAudioTagOld::GetSpecifiedId3V2Tag(const string& tag_contents, const string& tag_identify)
436 {
437 	wstring tag_info;
438 	size_t tag_index;
439 	tag_index = tag_contents.find(tag_identify);	//查找一个标签标识字符串
440 	if (tag_identify == "TPE1" && tag_index == string::npos)	//如果在查找艺术家时找不到TPE1标签,尝试查找TPE2标签
441 	{
442 		tag_index = tag_contents.find("TPE2");
443 	}
444 	if (tag_identify == "TYER" && tag_index == string::npos)	//如果在查找年份时找不到TYER标签,尝试查找TDRC标签
445 	{
446 		tag_index = tag_contents.find("TDRC");
447 	}
448 	if (tag_index != string::npos && tag_index < tag_contents.size() - 8)
449 	{
450 		string size = tag_contents.substr(tag_index + 4, 4);
451 		const size_t tag_size = (BYTE)size[0] * 0x1000000 + (BYTE)size[1] * 0x10000 + (BYTE)size[2] * 0x100 + (BYTE)size[3];	//获取当前标签的大小
452 		if (tag_size <= 0)
453 			return wstring();
454 		if (tag_index + 11 >= tag_contents.size())
455 			return wstring();
456 		//判断标签的编码格式
457 		CodeType default_code;
458 		switch (tag_contents[tag_index + 10])
459 		{
460 		case 1: case 2:
461 			default_code = CodeType::UTF16LE;
462 			break;
463 		case 3:
464 			default_code = CodeType::UTF8;
465 			break;
466 		default:
467 			default_code = CodeType::ANSI;
468 			break;
469 		}
470 		string tag_info_str;
471 		if (tag_identify == "COMM" || tag_identify == "USLT")
472 		{
473 			if (default_code == CodeType::UTF16LE)
474 				tag_info_str = tag_contents.substr(tag_index + 18, tag_size - 8);
475 			else
476 				tag_info_str = tag_contents.substr(tag_index + 15, tag_size - 5);
477 		}
478 		else
479 		{
480 			tag_info_str = tag_contents.substr(tag_index + 11, tag_size - 1);
481 		}
482 		tag_info = CCommon::StrToUnicode(tag_info_str, default_code);
483 	}
484 	return tag_info;
485 }
486 
487 
FindOneFlacTag(const string & tag_contents,const string & tag_identify,size_t & index)488 wstring CAudioTagOld::FindOneFlacTag(const string& tag_contents, const string& tag_identify, size_t& index)
489 {
490 	string find_str = '\0' + tag_identify + '=';
491     index = CCommon::StringFindNoCase(tag_contents, find_str, index + 1);
492 	if (index == string::npos || index < 3)
493 		return wstring();
494 
495 	//FLAC标签标识字符串前面有两个字节的'\0',再往前两个字节就是当前标签的长度
496 	size_t tag_size = tag_contents[index - 2] * 256 + tag_contents[index - 3];
497 
498 	string tag_str = tag_contents.substr(index + find_str.size(), tag_size - find_str.size() + 1);
499 	wstring tag_wcs = CCommon::StrToUnicode(tag_str, CodeType::UTF8);
500 	return tag_wcs;
501 }
502 
GetSpecifiedFlacTag(const string & tag_contents,const string & tag_identify)503 wstring CAudioTagOld::GetSpecifiedFlacTag(const string& tag_contents, const string& tag_identify)
504 {
505 	size_t index{ static_cast<size_t>(-1) };
506 	wstring tag_wcs;
507 	//Flac标签中可能会有多个相同的标签,这里通过循环找到所有的标签,将它们连接起来,并用分号分隔
508 	while (true)
509 	{
510 		wstring contents = FindOneFlacTag(tag_contents, tag_identify, index);
511 		if (contents.empty())
512 			break;
513 		tag_wcs += contents;
514 		tag_wcs.push_back(L';');
515 	}
516 	if(!tag_wcs.empty())
517 		tag_wcs.pop_back();
518 	return tag_wcs;
519 }
520 
GetUtf8TagContents(const char * tag_start)521 string CAudioTagOld::GetUtf8TagContents(const char* tag_start)
522 {
523 	string tag_contents;
524 	for (int i = 0; ; i++)
525 	{
526 		if (!tag_contents.empty() && tag_contents.back() == '\0' && tag_start[i] == '\0')		//遇到两个连续的0则退出
527 			break;
528 		tag_contents.push_back(tag_start[i]);
529 	}
530     tag_contents = '\0' + tag_contents;     //由于每个标签是用'\0'分隔的,在查找标签时会在要查找的标签前面加一个'\0',因此为了避免标签在文件的最前面导致查找不到的情况,在整个标签区域的最前面添加一个'\0'
531 	return tag_contents;
532 }
533 
GetWmaTagContents()534 string CAudioTagOld::GetWmaTagContents()
535 {
536 	const char* wma_tag;
537 	wma_tag = BASS_ChannelGetTags(m_hStream, BASS_TAG_WMA);
538 	if(wma_tag != nullptr)
539 	{
540 		string tag_content = GetUtf8TagContents(wma_tag);
541 		return tag_content;
542 	}
543 	return string();
544 }
545 
GetMp4TagContents()546 string CAudioTagOld::GetMp4TagContents()
547 {
548 	const char* mp4_tag;
549 	mp4_tag = BASS_ChannelGetTags(m_hStream, BASS_TAG_MP4);
550 	if (mp4_tag != nullptr)
551 	{
552 		string tag_content = GetUtf8TagContents(mp4_tag);
553 		return tag_content;
554 	}
555 	return string();
556 }
557 
GetOggTagContents()558 string CAudioTagOld::GetOggTagContents()
559 {
560 	const char* ogg_tag;
561 	ogg_tag = BASS_ChannelGetTags(m_hStream, BASS_TAG_OGG);
562 	if (ogg_tag != nullptr)
563 	{
564 		string tag_content = GetUtf8TagContents(ogg_tag);
565 		return tag_content;
566 	}
567 	return string();
568 }
569 
GetApeTagContents()570 string CAudioTagOld::GetApeTagContents()
571 {
572 	const char* ape_tag;
573 	ape_tag = BASS_ChannelGetTags(m_hStream, BASS_TAG_APE);
574 	if (ape_tag != nullptr)
575 	{
576 		string tag_content = GetUtf8TagContents(ape_tag);
577 		return tag_content;
578 	}
579 	return string();
580 }
581 
GetSpecifiedUtf8Tag(const string & tag_contents,const string & tag_identify)582 wstring CAudioTagOld::GetSpecifiedUtf8Tag(const string& tag_contents, const string& tag_identify)
583 {
584 	string find_str = '\0' + tag_identify;
585 	size_t index = CCommon::StringFindNoCase(tag_contents, find_str);
586 	if (index == string::npos)
587 		return wstring();
588 
589 	size_t index1 = tag_contents.find('=', index + 2);
590 	if (index1 == string::npos)
591 		return wstring();
592 
593 	size_t index2 = tag_contents.find('\0', index1 + 1);
594 
595 	string tag_str = tag_contents.substr(index1 + 1, index2 - index1 - 1);
596 	wstring tag_wcs = CCommon::StrToUnicode(tag_str, CodeType::UTF8);
597 	return tag_wcs;
598 }
599 
GetFlacTagContents(wstring file_path,string & contents_buff)600 void CAudioTagOld::GetFlacTagContents(wstring file_path, string & contents_buff)
601 {
602 	ifstream file{ file_path.c_str(), std::ios::binary };
603 	size_t size;
604 	if (file.fail())
605 		return;
606 	contents_buff.clear();
607 	while (!file.eof())
608 	{
609 		size = contents_buff.size();
610 		contents_buff.push_back(file.get());
611 		//if (size > 1024 * 1024)
612 		//	break;
613 		//找到flac音频的起始字节时(二进制13个1,1个0),表示标签信息已经读取完了
614 		if (size > 5 && (contents_buff[size - 1] & (BYTE)0xFC) == (BYTE)0xF8 && contents_buff[size - 2] == -1 && contents_buff[size - 3] == 0)
615 			break;
616 	}
617 }
618 
619 
FindID3V2AlbumCover(const string & tag_content,int & image_type)620 string CAudioTagOld::FindID3V2AlbumCover(const string & tag_content, int & image_type)
621 {
622     size_t cover_index = tag_content.find("APIC");		//查找专辑封面的标识字符串
623     if (cover_index == string::npos)
624         return string();
625     string size_btyes = tag_content.substr(cover_index + 4, 4);     //"APIC"后面4个字节是专辑封面的大小
626     unsigned int cover_size = ((static_cast<unsigned int>(size_btyes[0]) & 0x000000ff) << 24)
627         + ((static_cast<unsigned int>(size_btyes[1]) & 0x000000ff) << 16)
628         + ((static_cast<unsigned int>(size_btyes[2]) & 0x000000ff) << 8)
629         + (static_cast<unsigned int>(size_btyes[3]) & 0x000000ff); //APIC标签的大小
630     string apic_tag_content = tag_content.substr(cover_index + 8, cover_size + 2);
631     size_t image_index{};
632     image_index = apic_tag_content.find(jpg_head);
633     image_type = -1;
634     if (image_index < cover_index + 100)
635     {
636         image_type = 0;
637     }
638     else
639     {
640         image_index = apic_tag_content.find(png_head);
641         if (image_index < cover_index + 100)
642         {
643             image_type = 1;
644         }
645         else
646         {
647             image_index = apic_tag_content.find(gif_head);
648             if (image_index < cover_index + 100)
649             {
650                 image_type = 2;
651             }
652             else
653             {
654                 image_index = apic_tag_content.find(bmp_head);
655                 if (image_index < cover_index + 100)
656                 {
657                     image_type = 3;
658                 }
659             }
660         }
661     }
662     if (image_type != -1)
663         return apic_tag_content.substr(image_index);
664     else
665         return string();
666 }
667 
668