mirror of https://github.com/x64dbg/btparser
499 lines
12 KiB
Plaintext
499 lines
12 KiB
Plaintext
1:
|
|
2:
|
|
3:
|
|
4:
|
|
5:
|
|
6:
|
|
7:
|
|
8:
|
|
9:
|
|
10:
|
|
11:
|
|
12:
|
|
13:
|
|
14:
|
|
15:
|
|
16:
|
|
17:
|
|
18:
|
|
19:
|
|
20:
|
|
21:
|
|
22:
|
|
23:
|
|
24:
|
|
25:
|
|
26:
|
|
27:
|
|
28:
|
|
29:
|
|
30:
|
|
31:
|
|
32:
|
|
33:
|
|
34:
|
|
35:
|
|
36:
|
|
37:
|
|
38:
|
|
39:
|
|
40:
|
|
41:
|
|
42:
|
|
43:
|
|
44:
|
|
45:
|
|
46:
|
|
47:
|
|
48:
|
|
49:
|
|
50: local uint32 bitrate , frame_size , sampling_freq , frames_count = 0 ;
|
|
51: local quad frame_header_offset , seek_pos , sum_bitrate = 0 ;
|
|
52: local short data ;
|
|
53: local byte was_bad_sync , id3v1_tag_found = 0 ;
|
|
54: local ubyte buf [ 3 ] ;
|
|
55:
|
|
56:
|
|
57: enum < ubyte > ID3_GENRES
|
|
58: {
|
|
59: Blues , Classic_Rock , Country , Dance , Disco , Funk , Grunge , Hip_Hop ,
|
|
60: Jazz , Metal , New_Age , Oldies , Other , Pop , R_and_B , Rap ,
|
|
61: Reggae , Rock , Techno , Industrial , Alternative , Ska , Death_Metal , Pranks ,
|
|
62: Soundtrack , Euro_Techno , Ambient , Trip_Hop , Vocal , Jazz_Funk , Fusion , Trance ,
|
|
63: Classical , Instrumental , Acid , House , Game , Sound_Clip , Gospel , Noise ,
|
|
64: AlternRock , Bass , Soul , Punk , Space , Meditative , Instrumental_Pop , Instrumental_Rock ,
|
|
65: Ethnic , Gothic , Darkwave , Techno_Industrial , Electronic , Pop_Folk , Eurodance , Dream ,
|
|
66: Southern_Rock , Comedy , Cult , Gangsta , Top_40 , Christian_Rap , Pop_Funk , Jungle ,
|
|
67: Native_American , Cabaret , New_Wave , Psychadelic , Rave , Showtunes , Trailer , Lo_Fi ,
|
|
68: Tribal , Acid_Punk , Acid_Jazz , Polka , Retro , Musical , Rock_n_Roll , Hard_Rock ,
|
|
69: Folk , Folk_Rock , National_Folk , Swing , Fast_Fusion , Bebob , Latin , Revival ,
|
|
70: Celtic , Bluegrass , Avantgarde , Gothic_Rock ,
|
|
71: Progressive_Rock , Psychedelic_Rock , Symphonic_Rock , Slow_Rock ,
|
|
72: Big_Band , Chorus , Easy_Listening , Acoustic , Humour , Speech , Chanson , Opera ,
|
|
73: Chamber_Music , Sonata , Symphony , Booty_Bass , Primus , Porn_Groove , Satire , Slow_Jam ,
|
|
74: Club , Tango , Samba , Folklore , Ballad , Power_Ballad , Rhythmic_Soul , Freestyle ,
|
|
75: Duet , Punk_Rock , Drum_Solo , A_capella , Euro_House , Dance_Hall , Goa , Drum_and_Bass ,
|
|
76: Club_House , Hardcore , Terror , Indie , BritPop , Negerpunk , Polsk_Punk , Beat ,
|
|
77: Christian , Heavy_Metal , Black_Metal , Crossover ,
|
|
78: Contemporary , Christian_Rock , Merengue , Salsa , Thrash_Metal , Anime , JPop , Synthpop
|
|
79: } ;
|
|
80:
|
|
81:
|
|
82: struct ID3v1_TAG
|
|
83: {
|
|
84: DisplayFormatDecimal ( ) ;
|
|
85:
|
|
86: SetBackColor ( 0x33BC55 ) ;
|
|
87: char id [ 3 ] ;
|
|
88:
|
|
89: SetBackColor ( 0x48E048 ) ;
|
|
90: char title [ 30 ] ;
|
|
91:
|
|
92: SetBackColor ( 0x5DE45D ) ;
|
|
93: char artist [ 30 ] ;
|
|
94:
|
|
95: SetBackColor ( 0x72E872 ) ;
|
|
96: char album [ 30 ] ;
|
|
97:
|
|
98: SetBackColor ( 0x87EC87 ) ;
|
|
99: char year [ 4 ] ;
|
|
100:
|
|
101: if ( ReadByte ( FTell ( ) + 28 ) == 0 && ReadByte ( FTell ( ) + 29 ) != 0 )
|
|
102: {
|
|
103:
|
|
104:
|
|
105: SetBackColor ( 0x9CF09C ) ;
|
|
106: char comment [ 28 ] ;
|
|
107:
|
|
108: SetBackColor ( 0xB1F4B1 ) ;
|
|
109: byte zero ;
|
|
110:
|
|
111: SetBackColor ( 0xC6F8C6 ) ;
|
|
112: ubyte track ;
|
|
113: }
|
|
114: else
|
|
115: {
|
|
116:
|
|
117:
|
|
118: SetBackColor ( 0x9CF09C ) ;
|
|
119: char comment [ 30 ] ;
|
|
120: }
|
|
121:
|
|
122: SetBackColor ( 0xDBFCDB ) ;
|
|
123: ID3_GENRES genre ;
|
|
124: } ;
|
|
125:
|
|
126:
|
|
127: struct ID3v2_HEADER
|
|
128: {
|
|
129: SetBackColor ( 0x91C4FF ) ;
|
|
130:
|
|
131: char head [ 3 ] ;
|
|
132:
|
|
133: DisplayFormatDecimal ( ) ;
|
|
134:
|
|
135: ubyte ver_major ;
|
|
136: ubyte ver_revision ;
|
|
137:
|
|
138: struct FLAGS {
|
|
139: ubyte UNSYNCHRONISATION_USED : 1 ;
|
|
140: ubyte EXTENDED_HEADER_PRESENT : 1 ;
|
|
141: ubyte EXPERIMENTAL_TAG : 1 ;
|
|
142: ubyte : 5 ;
|
|
143: } flags ;
|
|
144:
|
|
145: DisplayFormatHex ( ) ;
|
|
146:
|
|
147: ubyte size [ 4 ] ;
|
|
148:
|
|
149:
|
|
150:
|
|
151: } ;
|
|
152:
|
|
153:
|
|
154: struct ID3v2_EXTENDED_HEADER
|
|
155: {
|
|
156: SetBackColor ( 0xA1D4FF ) ;
|
|
157:
|
|
158: DisplayFormatDecimal ( ) ;
|
|
159:
|
|
160: uint32 size ;
|
|
161:
|
|
162: uint16 FLAG_CRC_PRESENT : 1 ;
|
|
163: uint16 : 15 ;
|
|
164:
|
|
165: uint32 padding_sz ;
|
|
166:
|
|
167: if ( FLAG_CRC_PRESENT )
|
|
168: {
|
|
169: DisplayFormatHex ( ) ;
|
|
170: uint32 crc ;
|
|
171: }
|
|
172: } ;
|
|
173:
|
|
174:
|
|
175: struct ID3v2_FRAME
|
|
176: {
|
|
177: char id [ 4 ] ;
|
|
178:
|
|
179: DisplayFormatDecimal ( ) ;
|
|
180:
|
|
181: uint32 size ;
|
|
182:
|
|
183: struct FRAME_FLAGS {
|
|
184: uint16 TAG_ALTER_PRESERV : 1 ;
|
|
185: uint16 FILE_ALTER_PRESERV : 1 ;
|
|
186: uint16 READ_ONLY_FRAME : 1 ;
|
|
187: uint16 : 5 ;
|
|
188: uint16 COMPRESSED_FRAME : 1 ;
|
|
189: uint16 ENCRYPTED_FRAME : 1 ;
|
|
190: uint16 GROUP_MEMBER_FRAME : 1 ;
|
|
191: uint16 : 5 ;
|
|
192: } flags ;
|
|
193:
|
|
194: if ( id [ 0 ] == 'T' )
|
|
195: {
|
|
196:
|
|
197: if ( ReadByte ( FTell ( ) ) == 0 && size > 1 )
|
|
198: {
|
|
199: byte id_asciiz_str ;
|
|
200: char frame_data [ size - 1 ] ;
|
|
201: }
|
|
202: else
|
|
203: char frame_data [ size ] ;
|
|
204: }
|
|
205: else
|
|
206: {
|
|
207: DisplayFormatHex ( ) ;
|
|
208: ubyte frame_data [ size ] ;
|
|
209: }
|
|
210: } ;
|
|
211:
|
|
212:
|
|
213: struct ID3v2_TAG
|
|
214: {
|
|
215: ID3v2_HEADER hdr ;
|
|
216:
|
|
217:
|
|
218: local uint32 tag_sz = hdr . size [ 0 ] ;
|
|
219: tag_sz <<= 7 ;
|
|
220: tag_sz |= hdr . size [ 1 ] ;
|
|
221: tag_sz <<= 7 ;
|
|
222: tag_sz |= hdr . size [ 2 ] ;
|
|
223: tag_sz <<= 7 ;
|
|
224: tag_sz |= hdr . size [ 3 ] ;
|
|
225:
|
|
226:
|
|
227:
|
|
228:
|
|
229:
|
|
230:
|
|
231: if ( hdr . ver_major == 0xFF || hdr . ver_revision == 0xFF ||
|
|
232: hdr . size [ 0 ] >= 0x80 || hdr . size [ 1 ] >= 0x80 ||
|
|
233: hdr . size [ 2 ] >= 0x80 || hdr . size [ 3 ] >= 0x80 )
|
|
234: {
|
|
235: Printf ( "MP3: warning: invalid ID3v2 tag header\n" ) ;
|
|
236: }
|
|
237: else
|
|
238: {
|
|
239: if ( hdr . ver_major != 3 || hdr . flags . UNSYNCHRONISATION_USED || hdr . flags . EXPERIMENTAL_TAG )
|
|
240: {
|
|
241: Printf ( "MP3: warning: skipping unsupported ID3v2.%d tag\n" , hdr . ver_major ) ;
|
|
242: SetBackColor ( 0xA9DCFF ) ;
|
|
243: DisplayFormatHex ( ) ;
|
|
244: ubyte id3v2_data [ tag_sz ] ;
|
|
245: }
|
|
246: else
|
|
247: {
|
|
248: if ( hdr . flags . EXTENDED_HEADER_PRESENT )
|
|
249: ID3v2_EXTENDED_HEADER ext_hdr ;
|
|
250:
|
|
251:
|
|
252:
|
|
253:
|
|
254:
|
|
255: local uint32 frame_color = 0xC9FCFF ;
|
|
256: do
|
|
257: {
|
|
258: SetBackColor ( frame_color ) ;
|
|
259: ID3v2_FRAME tf ;
|
|
260: frame_color -= 0x20200 ;
|
|
261: }
|
|
262: while ( FTell ( ) < tag_sz + sizeof ( hdr ) && ReadByte ( FTell ( ) ) != 0 ) ;
|
|
263:
|
|
264: SetBackColor ( 0x99CCFF ) ;
|
|
265: ubyte id3v2_padding [ tag_sz + sizeof ( hdr ) - FTell ( ) ] ;
|
|
266: }
|
|
267: }
|
|
268: } ;
|
|
269:
|
|
270:
|
|
271:
|
|
272:
|
|
273:
|
|
274: struct MPEG_HEADER
|
|
275: {
|
|
276: SetBackColor ( 0xCC99FF ) ;
|
|
277:
|
|
278: DisplayFormatHex ( ) ;
|
|
279:
|
|
280: uint32 frame_sync : 12 ;
|
|
281:
|
|
282: DisplayFormatDecimal ( ) ;
|
|
283:
|
|
284: uint32 mpeg_id : 1 ;
|
|
285: uint32 layer_id : 2 ;
|
|
286: uint32 protection_bit : 1 ;
|
|
287: uint32 bitrate_index : 4 ;
|
|
288: uint32 frequency_index : 2 ;
|
|
289: uint32 padding_bit : 1 ;
|
|
290: uint32 private_bit : 1 ;
|
|
291: uint32 channel_mode : 2 ;
|
|
292: uint32 mode_extension : 2 ;
|
|
293: uint32 copyright : 1 ;
|
|
294: uint32 original : 1 ;
|
|
295: uint32 emphasis : 2 ;
|
|
296:
|
|
297: if ( protection_bit == 0 )
|
|
298: {
|
|
299: DisplayFormatHex ( ) ;
|
|
300: uint16 checksum ;
|
|
301: }
|
|
302: } ;
|
|
303:
|
|
304:
|
|
305: struct MPEG_FRAME
|
|
306: {
|
|
307: MPEG_HEADER mpeg_hdr ;
|
|
308:
|
|
309:
|
|
310: bitrate = 0 ;
|
|
311:
|
|
312:
|
|
313: if ( mpeg_hdr . frame_sync < 0xFFE || mpeg_hdr . layer_id == 0 ||
|
|
314: mpeg_hdr . bitrate_index == 0 || mpeg_hdr . bitrate_index == 15 ||
|
|
315: mpeg_hdr . frequency_index == 3 )
|
|
316: {
|
|
317: Printf ( "MP3: warning: invalid MPEG header in frame at offset 0x%X\n" ,
|
|
318: FTell ( ) - 4 - ( mpeg_hdr . protection_bit == 0 ? 2 : 0 ) ) ;
|
|
319:
|
|
320:
|
|
321: FSeek ( FTell ( ) - 2 ) ;
|
|
322: }
|
|
323: else
|
|
324: {
|
|
325: if ( mpeg_hdr . layer_id == 3 )
|
|
326: {
|
|
327: bitrate = ( uint32 ) mpeg_hdr . bitrate_index << 5 ;
|
|
328: }
|
|
329: else
|
|
330: {
|
|
331: if ( mpeg_hdr . layer_id == 2 )
|
|
332: {
|
|
333: bitrate = ( uint32 ) mpeg_hdr . bitrate_index == 1 ? 32 :
|
|
334: ( 1 << 5 + ( uint32 ) mpeg_hdr . bitrate_index / 4 ) +
|
|
335: ( ( ( uint32 ) mpeg_hdr . bitrate_index & 3 ) <<
|
|
336: 3 + ( uint32 ) mpeg_hdr . bitrate_index / 4 ) ;
|
|
337: }
|
|
338: else
|
|
339: {
|
|
340: if ( mpeg_hdr . mpeg_id == 1 )
|
|
341: {
|
|
342: bitrate = ( 1 << 5 + ( ( uint32 ) mpeg_hdr . bitrate_index - 1 ) / 4 ) +
|
|
343: ( ( ( uint32 ) mpeg_hdr . bitrate_index - 1 & 3 ) <<
|
|
344: 3 + ( ( uint32 ) mpeg_hdr . bitrate_index - 1 ) / 4 ) ;
|
|
345: }
|
|
346: else
|
|
347: {
|
|
348: bitrate = ( uint32 ) mpeg_hdr . bitrate_index < 4 ?
|
|
349:
|
|
350: 8 * ( uint32 ) mpeg_hdr . bitrate_index :
|
|
351:
|
|
352: ( 1 << 4 + ( uint32 ) mpeg_hdr . bitrate_index / 4 ) +
|
|
353: (
|
|
354: ( ( uint32 ) mpeg_hdr . bitrate_index & 3 ) == 0 ? 0 :
|
|
355:
|
|
356: ( ( uint32 ) mpeg_hdr . bitrate_index & 3 ) == 1 ?
|
|
357: ( 1 << 4 + ( uint32 ) mpeg_hdr . bitrate_index / 4 ) :
|
|
358:
|
|
359: ( ( uint32 ) mpeg_hdr . bitrate_index & 3 ) == 2 ?
|
|
360: ( 1 << 4 + ( uint32 ) mpeg_hdr . bitrate_index / 4 ) +
|
|
361: ( ( 1 << 4 + ( uint32 ) mpeg_hdr . bitrate_index / 4 ) >> 1 ) :
|
|
362:
|
|
363: ( 1 << 4 + ( uint32 ) mpeg_hdr . bitrate_index / 4 ) -
|
|
364: ( ( 1 << 4 + ( uint32 ) mpeg_hdr . bitrate_index / 4 ) >> 2 )
|
|
365: ) ;
|
|
366: }
|
|
367: }
|
|
368: }
|
|
369: }
|
|
370:
|
|
371: if ( bitrate != 0 )
|
|
372: {
|
|
373: local uint16 freq [ 3 ] ;
|
|
374: freq [ 0 ] = 2205 ;
|
|
375: freq [ 1 ] = 2400 ;
|
|
376: freq [ 2 ] = 1600 ;
|
|
377:
|
|
378: sampling_freq = freq [ mpeg_hdr . frequency_index ] ;
|
|
379:
|
|
380: if ( mpeg_hdr . mpeg_id == 1 )
|
|
381: sampling_freq <<= 1 ;
|
|
382:
|
|
383: frame_size = ( bitrate * 14400 ) / sampling_freq ;
|
|
384:
|
|
385: if ( mpeg_hdr . channel_mode == 3 )
|
|
386: frame_size >>= 1 ;
|
|
387:
|
|
388: frame_size -= 4 + ( mpeg_hdr . protection_bit == 0 ? 2 : 0 ) - mpeg_hdr . padding_bit ;
|
|
389:
|
|
390: frame_header_offset = FTell ( ) - 4 - ( mpeg_hdr . protection_bit == 0 ? 2 : 0 ) ;
|
|
391:
|
|
392:
|
|
393: if ( FTell ( ) + frame_size > FileSize ( ) )
|
|
394: {
|
|
395: Printf ( "MP3: warning: cut MPEG frame at end of file (frame header offset = 0x%LX, data length = %u)\n" ,
|
|
396: frame_header_offset , frame_size ) ;
|
|
397:
|
|
398: Printf ( "MP3: file parsing completed!\nMP3: valid MPEG frames found: %d\n" , frames_count ) ;
|
|
399:
|
|
400: if ( frames_count != 0 )
|
|
401: Printf ( "MP3: average frame bitrate: %d kbit\n" , sum_bitrate / frames_count ) ;
|
|
402:
|
|
403: return ;
|
|
404: }
|
|
405: else
|
|
406: {
|
|
407: DisplayFormatHex ( ) ;
|
|
408: SetBackColor ( 0xCCCCFF ) ;
|
|
409: ubyte mpeg_frame_data [ frame_size ] ;
|
|
410: }
|
|
411:
|
|
412: sum_bitrate += bitrate ;
|
|
413:
|
|
414: frames_count ++ ;
|
|
415: }
|
|
416: } ;
|
|
417:
|
|
418:
|
|
419:
|
|
420:
|
|
421:
|
|
422: BigEndian ( ) ;
|
|
423:
|
|
424: ReadBytes ( buf , 0 , 3 ) ;
|
|
425:
|
|
426: if ( ! Strcmp ( buf , "ID3" ) )
|
|
427: {
|
|
428: Printf ( "MP3: ID3v2 tag found\n" ) ;
|
|
429: ID3v2_TAG id3v2_tag ;
|
|
430: }
|
|
431:
|
|
432: while ( ! FEof ( ) && ! id3v1_tag_found )
|
|
433: {
|
|
434:
|
|
435: seek_pos = FTell ( ) ;
|
|
436: was_bad_sync = 0 ;
|
|
437: do
|
|
438: {
|
|
439: data = ReadShort ( seek_pos ) ;
|
|
440:
|
|
441: if ( ( uint16 ) data == 0x5441 && ( uchar ) ReadByte ( seek_pos + 2 ) == 0x47 )
|
|
442: id3v1_tag_found = 1 ;
|
|
443:
|
|
444: if ( ! was_bad_sync && ( uint16 ) data < 0xFFE0 && ! id3v1_tag_found )
|
|
445: {
|
|
446: Printf ( "MP3: warning: invalid MPEG frame synchronization at offset 0x%LX\n" , seek_pos ) ;
|
|
447: was_bad_sync = 1 ;
|
|
448: }
|
|
449:
|
|
450: seek_pos ++ ;
|
|
451: }
|
|
452: while ( ( uint16 ) data < 0xFFE0 && seek_pos < ( FileSize ( ) - 1 ) && ! id3v1_tag_found ) ;
|
|
453:
|
|
454: if ( ( uint16 ) data >= 0xFFE0 || id3v1_tag_found )
|
|
455: {
|
|
456: FSeek ( seek_pos - 1 ) ;
|
|
457: }
|
|
458: else
|
|
459: {
|
|
460: Printf ( "MP3: file parsing completed!\nMP3: valid MPEG frames found: %d\n" , frames_count ) ;
|
|
461:
|
|
462: if ( frames_count != 0 )
|
|
463: Printf ( "MP3: average frame bitrate: %d kbit\n" , sum_bitrate / frames_count ) ;
|
|
464:
|
|
465: return ;
|
|
466: }
|
|
467:
|
|
468: if ( ! id3v1_tag_found )
|
|
469: {
|
|
470: MPEG_FRAME mf ;
|
|
471:
|
|
472: if ( frames_count == 1 && bitrate )
|
|
473: Printf ( "MP3: first found MPEG frame parameters:\nMP3:\t- header ofsset: 0x%LX\nMP3:\t- bitrate: %d kbit\nMP3:\t- MPEG-%d layer %d\nMP3:\t- sampling frequency: %d Hz\nMP3:\t- channel mode: %s\nMP3:\t- CRC protected: %s\n" ,
|
|
474: frame_header_offset ,
|
|
475: bitrate ,
|
|
476: mf . mpeg_hdr . mpeg_id == 1 ? 1 : 2 ,
|
|
477: mf . mpeg_hdr . layer_id == 1 ? 3 : mf . mpeg_hdr . layer_id == 2 ? 2 : 1 ,
|
|
478: sampling_freq * 10 ,
|
|
479: mf . mpeg_hdr . channel_mode == 3 ? "mono" :
|
|
480: mf . mpeg_hdr . channel_mode == 0 ? "stereo" :
|
|
481: mf . mpeg_hdr . channel_mode == 1 ? "joint stereo" : "dual channel" ,
|
|
482: mf . mpeg_hdr . protection_bit == 0 ? "Yes" : "No" ) ;
|
|
483: }
|
|
484: }
|
|
485:
|
|
486: if ( id3v1_tag_found )
|
|
487: {
|
|
488: Printf ( "MP3: ID3v1 tag found\n" ) ;
|
|
489: ID3v1_TAG id3v1_tag ;
|
|
490: }
|
|
491:
|
|
492: if ( ! FEof ( ) )
|
|
493: Printf ( "MP3: warning: there is some unknown extra-data after ID3v1 tag at end of file\n" ) ;
|
|
494:
|
|
495: Printf ( "MP3: file parsing completed!\nMP3: valid MPEG frames found: %d\n" , frames_count ) ;
|
|
496:
|
|
497: if ( frames_count != 0 )
|
|
498: Printf ( "MP3: average frame bitrate: %d kbit\n" , sum_bitrate / frames_count ) ;
|
|
499: tok_eof |