rtoss - Blame information for rev 14

Subversion Repositories:
Rev:
Rev Author Line No. Line
14 roytam 1 #include <windows.h>
2 #include <tchar.h>
3 #include "maplay.h"
4 #include "reader.h"
5 #include "mahelper.h"
6  
7 const int tabbitrate[3][3][16] =
8 {
9    {{0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,},          //V1L1
10         {0,32,48,56, 64, 80, 96,112,128,160,192,224,256,320,384,},              //V1L2
11         {0,32,40,48, 56, 64, 80, 96,112,128,160,192,224,256,320,} },    //V1L3
12  
13    {{0,32,48,56,64,80,96,112,128,144,160,176,192,224,256,},                     //V2L1
14         {0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,},                              //V2L2
15         {0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,} },                    //V2L3
16  
17    {{0,32,48,56,64,80,96,112,128,144,160,176,192,224,256,},                     //V2.5L1
18         {0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,},                              //V2.5L2
19         {0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,} }                             //V2.5L3
20 };
21  
22 const int tabsamplingrate[3][4] =
23 {
24         {44100, 48000, 32000, 0},
25         {22050, 24000, 16000, 0},
26         {11025, 12000, 8000, 0}
27 };
28  
29 const LPTSTR genre_strings[] = {
30         _T("Blues"), _T("Classic Rock"), _T("Country"), _T("Dance"), _T("Disco"),
31         _T("Funk"), _T("Grunge"), _T("Hip-Hop"), _T("Jazz"), _T("Metal"),
32         _T("New Age"), _T("Oldies"), _T("Other"), _T("Pop"), _T("R&B"),
33         _T("Rap"), _T("Reggae"), _T("Rock"), _T("Techno"), _T("Industrial"),
34         _T("Alternative"), _T("Ska"), _T("Death Metal"), _T("Pranks"), _T("Soundtrack"),
35         _T("Euro-Techno"), _T("Ambient"), _T("Trip-Hop"), _T("Vocal"), _T("Jazz+Funk"),
36         _T("Fusion"), _T("Trance"), _T("Classical"), _T("Instrumental"), _T("Acid"),
37         _T("House"), _T("Game"), _T("Sound Clip"), _T("Gospel"), _T("Noise"),
38         _T("Alternative Rock"), _T("Bass"), _T("Soul"), _T("Punk"), _T("Space"),
39         _T("Meditative"), _T("Instrumental Pop"), _T("Instrumental Rock"), _T("Ethnic"), _T("Gothic"),
40         _T("Darkwave"), _T("Techno-Industrial"), _T("Electronic"), _T("Pop-Folk"), _T("Eurodance"),
41         _T("Dream"), _T("Southern Rock"), _T("Comedy"), _T("Cult"), _T("Gangsta"),
42         _T("Top 40"), _T("Christian Rap"), _T("Pop/Funk"), _T("Jungle"), _T("Native American"),
43         _T("Cabaret"), _T("New Wave"), _T("Psychadelic"), _T("Rave"), _T("Showtunes"),
44         _T("Trailer"), _T("Lo-Fi"), _T("Tribal"), _T("Acid Punk"), _T("Acid Jazz"),
45         _T("Polka"), _T("Retro"), _T("Musical"), _T("Rock & Roll"), _T("Hard Rock"),
46         _T("Folk"), _T("Folk-Rock"), _T("National Folk"), _T("Swing"), _T("Fast Fusion"),
47         _T("Bebob"), _T("Latin"), _T("Revival"), _T("Celtic"), _T("Bluegrass"),
48         _T("Avantgarde"), _T("Gothic Rock"), _T("Progressive Rock"), _T("Psychedelic Rock"), _T("Symphonic Rock"),
49         _T("Slow Rock"), _T("Big Band"), _T("Chorus"), _T("Easy Listening"), _T("Acoustic"),
50         _T("Humour"), _T("Speech"), _T("Chanson"), _T("Opera"), _T("Chamber Music"),
51         _T("Sonata"), _T("Symphony"), _T("Booty Bass"), _T("Primus"), _T("Porn Groove"),
52         _T("Satire"), _T("Slow Jam"), _T("Club"), _T("Tango"), _T("Samba"),
53         _T("Folklore"), _T("Ballad"), _T("Power Ballad"), _T("Rhythmic Soul"), _T("Freestyle"),
54         _T("Duet"), _T("Punk Rock"), _T("Drum Solo"), _T("Acapella"), _T("Euro-House"),
55         _T("Dance Hall"), _T("Goa"), _T("Drum & Bass"), _T("Club-House"), _T("Hardcore"),
56         _T("Terror"), _T("Indie"), _T("BritPop"), _T("Negerpunk"), _T("Polsk Punk"),
57         _T("Beat"), _T("Christian Gangsta Rap"), _T("Heavy Metal"), _T("Black Metal"), _T("Crossover"),
58         _T("Contemporary Christian"), _T("Christian Rock"), _T("Merengue"), _T("Salsa"), _T("Thrash Metal"),
59         _T("Anime"), _T("Jpop"), _T("Synthpop"), NULL
60 };
61  
62 BOOL IsValidFile(LPCTSTR pszFile)
63 {
64         BOOL fRet = FALSE;
65         CReader* pReader = new CReader();
66         if (!pReader->Open(pszFile))
67                 return FALSE;
68  
69         // scan first 4096 bytes
70         DWORD dwRead;
71         BYTE bBuff[4096];
72         if (pReader->Read(bBuff, sizeof(bBuff), &dwRead) && dwRead >= 4) {
73                 DWORD dwBuff = MAKELONG(MAKEWORD(bBuff[3], bBuff[2]), MAKEWORD(bBuff[1], bBuff[0]));
74                 if ((dwBuff & 0xFFFFFF00) == 0x49443300)
75                         fRet = TRUE; // ID3v2 = MP3
76                 else if (dwBuff == 0x52494646) {
77                         // RIFF
78                         if (dwRead >= 12) {
79                                 dwBuff = MAKELONG(MAKEWORD(bBuff[11], bBuff[10]), MAKEWORD(bBuff[9], bBuff[8]));
80                                 if (dwBuff == 0x524D5033) // RMP3
81                                         fRet = TRUE;
82                                 else if (dwBuff == 0x57415645) { // RIFF Wave
83                                         if (dwRead >= 16) {
84                                                 dwBuff = MAKELONG(MAKEWORD(bBuff[15], bBuff[14]), MAKEWORD(bBuff[13], bBuff[12]));
85                                                 if (dwBuff == 0x666D7420) { // fmt
86                                                         if (dwRead >= 21) {
87                                                                 dwBuff = MAKELONG(MAKEWORD(bBuff[20], bBuff[21]), 0);
88                                                                 if (dwBuff == 0x55 ||
89                                                                         dwBuff == 0x50) // format id
90                                                                         fRet = TRUE;
91                                                         }
92                                                 }
93                                         }
94                                 }
95                         }
96                 }
97                 else {
98                         DWORD cb = 0;
99                         while (cb < dwRead - 4) {
100                                 MPEG_AUDIO_INFO info1, info2;
101                                 if (ParseHeader(bBuff + cb, &info1)) {
102                                         if (cb + info1.nFrameSize + 4 < dwRead) {
103                                                 ParseHeader(bBuff + cb + info1.nFrameSize, &info2);
104                                                 if (info1.nVersion == info2.nVersion &&
105                                                         info1.nLayer == info2.nLayer &&
106                                                         info1.nSamplingRate == info2.nSamplingRate) {
107                                                                 fRet = TRUE;
108                                                                 break;
109                                                 }
110                                         }
111                                 }
112                                 cb++;
113                         }
114                 }
115         }
116         pReader->Close();
117         delete pReader;
118         return fRet;
119 }
120  
121 BOOL ParseHeader(DWORD dwHeader, MPEG_AUDIO_INFO* pinfo)
122 {
123         if (!CheckAudioHeader(dwHeader))
124                 return FALSE;
125  
126         int nPadding;
127         MPEG_AUDIO_INFO info;
128         info.nVersion = (dwHeader & 0x00100000) ? 2 - ((dwHeader & 0x00080000) >> 19) : 3;
129         info.nLayer = 4 - ((dwHeader & 0x00060000) >> 17);
130         info.nBitRate = tabbitrate[info.nVersion - 1][info.nLayer - 1][(dwHeader & 0x0000F000) >> 12];
131         info.nSamplingRate = tabsamplingrate[info.nVersion - 1][(dwHeader & 0x00000C00) >> 10];
132         nPadding = (dwHeader & 0x00000200) >> 9;
133         info.nChannels = (((dwHeader & 0x000000C0) >> 6) == 3) ? 1 : 2;
134         if (!info.nSamplingRate)
135                 return FALSE;
136  
137         if (!info.nBitRate)
138                 return FALSE;   // freeformat
139  
140         if (info.nLayer == 1) {
141                 info.nFrameSize = (12 * info.nBitRate * 1000 / info.nSamplingRate + nPadding) * 4;
142                 info.nSamplesPerFrame = 384;
143         }
144         else {
145                 if (info.nLayer >= 2 && info.nVersion >= 2) {
146                         // LSF
147                         info.nFrameSize = 72 * info.nBitRate * 1000 / info.nSamplingRate + nPadding;
148                         info.nSamplesPerFrame = 576;
149                 }
150                 else {
151                         info.nFrameSize = 144 * info.nBitRate * 1000 / info.nSamplingRate + nPadding;
152                         info.nSamplesPerFrame = 1152;
153                 }
154         }
155         *pinfo = info;
156         return TRUE;
157 }
158  
159 BOOL ParseHeader(LPBYTE pbHeader, MPEG_AUDIO_INFO* pinfo)
160 {
161         DWORD dwHeader = MAKELONG(MAKEWORD(pbHeader[3], pbHeader[2]),
162                                                                 MAKEWORD(pbHeader[1], pbHeader[0]));
163         return ParseHeader(dwHeader, pinfo);
164 }
165  
166 int GetFrameSize(DWORD dwHeader)
167 {
168         if (CheckAudioHeader(dwHeader))
169                 return 0;
170  
171         MPEG_AUDIO_INFO info;
172         if (!ParseHeader(dwHeader, &info))
173                 return 0;
174  
175         return info.nFrameSize;
176 }
177  
178 int GetFrameSize(LPBYTE pbHeader)
179 {
180         DWORD dwHeader = MAKELONG(MAKEWORD(pbHeader[3], pbHeader[2]),
181                                                                 MAKEWORD(pbHeader[1], pbHeader[0]));
182         return GetFrameSize(dwHeader);
183 }
184  
185 void ConvertFromTagStr(BYTE buff[30], LPTSTR pszBuff, int nLen)
186 {
187         char szBuff[31];
188         memset(szBuff, 0, sizeof(szBuff));
189         memcpy(szBuff, buff, sizeof(BYTE) * nLen);
190         for (int i = nLen - 1; szBuff[i] == ' '; i--)
191                 szBuff[i] = '\0';
192  
193 #ifdef _UNICODE
194         MultiByteToWideChar(CP_ACP, 0, (char*)szBuff, -1, pszBuff, 31);
195 #else
196         strcpy(pszBuff, szBuff);
197 #endif
198 }
199  
200 BOOL GetId3Tag(LPCTSTR pszFile, ID3TAGV1* pTag)
201 {
202         memset(pTag, 0, sizeof(ID3_TAG_V1));
203         BOOL fRet = FALSE;
204  
205         // this supports ID3TAG v1 only !!
206         CReader* pReader = new CReader();
207         if (!pReader->Open(pszFile))
208                 return FALSE;
209  
210         LONGLONG llSize = pReader->GetSize();
211         llSize -= sizeof(ID3_TAG_V1);
212         pReader->SetPointer(llSize, FILE_BEGIN);
213  
214         DWORD dwRead;
215         ID3_TAG_V1 id3tag;
216         if (pReader->Read((LPBYTE)&id3tag, sizeof(id3tag), &dwRead) &&
217                 dwRead == sizeof(id3tag)) {
218                 if (id3tag.tag[0] == 'T' && id3tag.tag[1] == 'A' && id3tag.tag[2] == 'G') {
219                         // it's ID3TAG v1 !!
220                         fRet = TRUE;
221                         pTag->nTrackNum = 0;
222  
223                         char buff[5];
224                         memset(buff, 0, sizeof(buff));
225                         memcpy(buff, id3tag.year, sizeof(id3tag.year));
226                         pTag->nYear = atoi(buff);
227  
228                         ConvertFromTagStr(id3tag.albumName, pTag->szAlbum);
229                         ConvertFromTagStr(id3tag.artistName, pTag->szArtist);
230                         ConvertFromTagStr(id3tag.trackName, pTag->szTrack);
231  
232                         //ID3TAG v1.1
233                         if (id3tag.comment[28] == NULL) {
234                                 pTag->nTrackNum = id3tag.comment[29];
235                                 ConvertFromTagStr(id3tag.comment, pTag->szComment, 28);
236                         }
237                         else
238                                 ConvertFromTagStr(id3tag.comment, pTag->szComment);
239  
240                         if (id3tag.genre < 148)
241                                 _tcscpy(pTag->szGenre, genre_strings[id3tag.genre]);
242                         else
243                                 memset(pTag->szGenre, 0, sizeof(pTag->szGenre));
244                 }
245         }
246         pReader->Close();
247         delete pReader;
248         return fRet;
249 }
250  
251 BOOL SetId3Tag(LPCTSTR pszFile, ID3TAGV1* pTag)
252 {
253         return FALSE;
254 }