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