📄 mahelper.cpp
字号:
#include <windows.h>
#include <tchar.h>
#include "maplay.h"
#include "reader.h"
#include "mahelper.h"
const int tabbitrate[3][3][16] =
{
{{0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,}, //V1L1
{0,32,48,56, 64, 80, 96,112,128,160,192,224,256,320,384,}, //V1L2
{0,32,40,48, 56, 64, 80, 96,112,128,160,192,224,256,320,} }, //V1L3
{{0,32,48,56,64,80,96,112,128,144,160,176,192,224,256,}, //V2L1
{0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,}, //V2L2
{0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,} }, //V2L3
{{0,32,48,56,64,80,96,112,128,144,160,176,192,224,256,}, //V2.5L1
{0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,}, //V2.5L2
{0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,} } //V2.5L3
};
const int tabsamplingrate[3][4] =
{
{44100, 48000, 32000, 0},
{22050, 24000, 16000, 0},
{11025, 12000, 8000, 0}
};
const LPTSTR genre_strings[] = {
_T("Blues"), _T("Classic Rock"), _T("Country"), _T("Dance"), _T("Disco"),
_T("Funk"), _T("Grunge"), _T("Hip-Hop"), _T("Jazz"), _T("Metal"),
_T("New Age"), _T("Oldies"), _T("Other"), _T("Pop"), _T("R&B"),
_T("Rap"), _T("Reggae"), _T("Rock"), _T("Techno"), _T("Industrial"),
_T("Alternative"), _T("Ska"), _T("Death Metal"), _T("Pranks"), _T("Soundtrack"),
_T("Euro-Techno"), _T("Ambient"), _T("Trip-Hop"), _T("Vocal"), _T("Jazz+Funk"),
_T("Fusion"), _T("Trance"), _T("Classical"), _T("Instrumental"), _T("Acid"),
_T("House"), _T("Game"), _T("Sound Clip"), _T("Gospel"), _T("Noise"),
_T("Alternative Rock"), _T("Bass"), _T("Soul"), _T("Punk"), _T("Space"),
_T("Meditative"), _T("Instrumental Pop"), _T("Instrumental Rock"), _T("Ethnic"), _T("Gothic"),
_T("Darkwave"), _T("Techno-Industrial"), _T("Electronic"), _T("Pop-Folk"), _T("Eurodance"),
_T("Dream"), _T("Southern Rock"), _T("Comedy"), _T("Cult"), _T("Gangsta"),
_T("Top 40"), _T("Christian Rap"), _T("Pop/Funk"), _T("Jungle"), _T("Native American"),
_T("Cabaret"), _T("New Wave"), _T("Psychadelic"), _T("Rave"), _T("Showtunes"),
_T("Trailer"), _T("Lo-Fi"), _T("Tribal"), _T("Acid Punk"), _T("Acid Jazz"),
_T("Polka"), _T("Retro"), _T("Musical"), _T("Rock & Roll"), _T("Hard Rock"),
_T("Folk"), _T("Folk-Rock"), _T("National Folk"), _T("Swing"), _T("Fast Fusion"),
_T("Bebob"), _T("Latin"), _T("Revival"), _T("Celtic"), _T("Bluegrass"),
_T("Avantgarde"), _T("Gothic Rock"), _T("Progressive Rock"), _T("Psychedelic Rock"), _T("Symphonic Rock"),
_T("Slow Rock"), _T("Big Band"), _T("Chorus"), _T("Easy Listening"), _T("Acoustic"),
_T("Humour"), _T("Speech"), _T("Chanson"), _T("Opera"), _T("Chamber Music"),
_T("Sonata"), _T("Symphony"), _T("Booty Bass"), _T("Primus"), _T("Porn Groove"),
_T("Satire"), _T("Slow Jam"), _T("Club"), _T("Tango"), _T("Samba"),
_T("Folklore"), _T("Ballad"), _T("Power Ballad"), _T("Rhythmic Soul"), _T("Freestyle"),
_T("Duet"), _T("Punk Rock"), _T("Drum Solo"), _T("Acapella"), _T("Euro-House"),
_T("Dance Hall"), _T("Goa"), _T("Drum & Bass"), _T("Club-House"), _T("Hardcore"),
_T("Terror"), _T("Indie"), _T("BritPop"), _T("Negerpunk"), _T("Polsk Punk"),
_T("Beat"), _T("Christian Gangsta Rap"), _T("Heavy Metal"), _T("Black Metal"), _T("Crossover"),
_T("Contemporary Christian"), _T("Christian Rock"), _T("Merengue"), _T("Salsa"), _T("Thrash Metal"),
_T("Anime"), _T("Jpop"), _T("Synthpop"), NULL
};
BOOL IsValidFile(LPCTSTR pszFile)
{
BOOL fRet = FALSE;
CReader* pReader = new CReader();
if (!pReader->Open(pszFile))
return FALSE;
// scan first 4096 bytes
DWORD dwRead;
BYTE bBuff[4096];
if (pReader->Read(bBuff, sizeof(bBuff), &dwRead) && dwRead >= 4) {
DWORD dwBuff = MAKELONG(MAKEWORD(bBuff[3], bBuff[2]), MAKEWORD(bBuff[1], bBuff[0]));
if ((dwBuff & 0xFFFFFF00) == 0x49443300)
fRet = TRUE; // ID3v2 = MP3
else if (dwBuff == 0x52494646) {
// RIFF
if (dwRead >= 12) {
dwBuff = MAKELONG(MAKEWORD(bBuff[11], bBuff[10]), MAKEWORD(bBuff[9], bBuff[8]));
if (dwBuff == 0x524D5033) // RMP3
fRet = TRUE;
else if (dwBuff == 0x57415645) { // RIFF Wave
if (dwRead >= 16) {
dwBuff = MAKELONG(MAKEWORD(bBuff[15], bBuff[14]), MAKEWORD(bBuff[13], bBuff[12]));
if (dwBuff == 0x666D7420) { // fmt
if (dwRead >= 21) {
dwBuff = MAKELONG(MAKEWORD(bBuff[20], bBuff[21]), 0);
if (dwBuff == 0x55 ||
dwBuff == 0x50) // format id
fRet = TRUE;
}
}
}
}
}
}
else {
DWORD cb = 0;
while (cb < dwRead - 4) {
MPEG_AUDIO_INFO info1, info2;
if (ParseHeader(bBuff + cb, &info1)) {
if (cb + info1.nFrameSize + 4 < dwRead) {
ParseHeader(bBuff + cb + info1.nFrameSize, &info2);
if (info1.nVersion == info2.nVersion &&
info1.nLayer == info2.nLayer &&
info1.nSamplingRate == info2.nSamplingRate) {
fRet = TRUE;
break;
}
}
}
cb++;
}
}
}
pReader->Close();
delete pReader;
return fRet;
}
BOOL ParseHeader(DWORD dwHeader, MPEG_AUDIO_INFO* pinfo)
{
if (!CheckAudioHeader(dwHeader))
return FALSE;
int nPadding;
MPEG_AUDIO_INFO info;
info.nVersion = (dwHeader & 0x00100000) ? 2 - ((dwHeader & 0x00080000) >> 19) : 3;
info.nLayer = 4 - ((dwHeader & 0x00060000) >> 17);
info.nBitRate = tabbitrate[info.nVersion - 1][info.nLayer - 1][(dwHeader & 0x0000F000) >> 12];
info.nSamplingRate = tabsamplingrate[info.nVersion - 1][(dwHeader & 0x00000C00) >> 10];
nPadding = (dwHeader & 0x00000200) >> 9;
info.nChannels = (((dwHeader & 0x000000C0) >> 6) == 3) ? 1 : 2;
if (!info.nSamplingRate)
return FALSE;
if (!info.nBitRate)
return FALSE; // freeformat
if (info.nLayer == 1) {
info.nFrameSize = (12 * info.nBitRate * 1000 / info.nSamplingRate + nPadding) * 4;
info.nSamplesPerFrame = 384;
}
else {
if (info.nLayer >= 2 && info.nVersion >= 2) {
// LSF
info.nFrameSize = 72 * info.nBitRate * 1000 / info.nSamplingRate + nPadding;
info.nSamplesPerFrame = 576;
}
else {
info.nFrameSize = 144 * info.nBitRate * 1000 / info.nSamplingRate + nPadding;
info.nSamplesPerFrame = 1152;
}
}
*pinfo = info;
return TRUE;
}
BOOL ParseHeader(LPBYTE pbHeader, MPEG_AUDIO_INFO* pinfo)
{
DWORD dwHeader = MAKELONG(MAKEWORD(pbHeader[3], pbHeader[2]),
MAKEWORD(pbHeader[1], pbHeader[0]));
return ParseHeader(dwHeader, pinfo);
}
int GetFrameSize(DWORD dwHeader)
{
if (CheckAudioHeader(dwHeader))
return 0;
MPEG_AUDIO_INFO info;
if (!ParseHeader(dwHeader, &info))
return 0;
return info.nFrameSize;
}
int GetFrameSize(LPBYTE pbHeader)
{
DWORD dwHeader = MAKELONG(MAKEWORD(pbHeader[3], pbHeader[2]),
MAKEWORD(pbHeader[1], pbHeader[0]));
return GetFrameSize(dwHeader);
}
void ConvertFromTagStr(BYTE buff[30], LPTSTR pszBuff, int nLen)
{
char szBuff[31];
memset(szBuff, 0, sizeof(szBuff));
memcpy(szBuff, buff, sizeof(BYTE) * nLen);
for (int i = nLen - 1; szBuff[i] == ' '; i--)
szBuff[i] = '\0';
#ifdef _UNICODE
MultiByteToWideChar(CP_ACP, 0, (char*)szBuff, -1, pszBuff, 31);
#else
strcpy(pszBuff, szBuff);
#endif
}
BOOL GetId3Tag(LPCTSTR pszFile, ID3TAGV1* pTag)
{
memset(pTag, 0, sizeof(ID3_TAG_V1));
BOOL fRet = FALSE;
// this supports ID3TAG v1 only !!
CReader* pReader = new CReader();
if (!pReader->Open(pszFile))
return FALSE;
LONGLONG llSize = pReader->GetSize();
llSize -= sizeof(ID3_TAG_V1);
pReader->SetPointer(llSize, FILE_BEGIN);
DWORD dwRead;
ID3_TAG_V1 id3tag;
if (pReader->Read((LPBYTE)&id3tag, sizeof(id3tag), &dwRead) &&
dwRead == sizeof(id3tag)) {
if (id3tag.tag[0] == 'T' && id3tag.tag[1] == 'A' && id3tag.tag[2] == 'G') {
// it's ID3TAG v1 !!
fRet = TRUE;
pTag->nTrackNum = 0;
char buff[5];
memset(buff, 0, sizeof(buff));
memcpy(buff, id3tag.year, sizeof(id3tag.year));
pTag->nYear = atoi(buff);
ConvertFromTagStr(id3tag.albumName, pTag->szAlbum);
ConvertFromTagStr(id3tag.artistName, pTag->szArtist);
ConvertFromTagStr(id3tag.trackName, pTag->szTrack);
//ID3TAG v1.1
if (id3tag.comment[28] == NULL) {
pTag->nTrackNum = id3tag.comment[29];
ConvertFromTagStr(id3tag.comment, pTag->szComment, 28);
}
else
ConvertFromTagStr(id3tag.comment, pTag->szComment);
if (id3tag.genre < 148)
_tcscpy(pTag->szGenre, genre_strings[id3tag.genre]);
else
memset(pTag->szGenre, 0, sizeof(pTag->szGenre));
}
}
pReader->Close();
delete pReader;
return fRet;
}
BOOL SetId3Tag(LPCTSTR pszFile, ID3TAGV1* pTag)
{
return FALSE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -