in reply to ID3 tag version 2.4.0 Pack and Unpack
Why all the seeks?
Why *not* read the frames when an extended header was found?
Why not use MP3::Tag?
Why not exit if $type is invalid?
I have no knoledge of MP3 and/or MP3-tags at all, but your code looks very very suspiciously wrong. Let me start by posting a simplified version. I only simplified it, because it is a perfect example for something I want to talk about next AmsterdamX.pm meeting :)
The code is not made to work. It is restyled to what I *think* it is supposed to do and I tried to make it a bit more readable/maintainable.
Your version has 219 lines, mine less than half (106) and they did the same on the mp3 files I could find on my system (not that many btw)
use 5.18.2; use warnings; sub usage { my $err = shift and select STDERR; say "usage: $0 file.mp3"; exit $err; } # usage use Data::Peek; my $source = shift or usage (1); @ARGV and usage (1); open my $in, "<:raw", $source or die "Can not open file '$source': $!\ +n"; say "\nUser has chosen file: $source to open for reading!"; read $in, my $dta, 10; DHexDump $dta; # Header 10 Bytes in total 3 Bytes + 1 Byte + 1 Byte + 1 Byte + 4 Byte +s = 10 Bytes my ($type, $major_version, $revision_number, $flags, $mp3_size) = unpa +ck "A3". # 24 bits (3 Bytes, ASCII text) "ID3". (3 Bytes Heade +r_ID). "h". # 8 bits (1 Byte, hex string) Version (1 Byte Major +_Version). "h". # 8 bits (1 Byte, hex string) Version (1 Byte Revis +ion number). "h". # 8 bits (1 Byte, hex string) Flags (1 Byte Flags +). "N", # 32 bits (4 Bytes, Integer), Size (4 Bytes Size) +. $dta; $type =~ m/^[ -~]{3}/ or die "Not a Tagged MP3 file\n"; say "TAG Detected: $type v2.$major_version.$revision_number"; DDumper [ $type, $major_version, $revision_number, $flags, $mp3_size ] +; $flags ? say "Flags are not empty, we have found these characters: $fl +ags\n" : say "\nThe extended flags has no corresponding data: \$00 was + detected. Proceeding!\n\n"; my $length_of_data = $mp3_size; # say "This is the mp3_size after sync_safe: $mp3_size"; # End of Header # At this point we want to make sure that we have an extended header ( +ID3v2 flags %abcd0000) # Bit 7 of (ID3v2 flags %abcd0000) if is 1 (active indicates that ther +e is extended header # if is 0 it means there is no extended header. If extended header exi +st proceed else skip. if ($flags & 0b01000000) { # Begging Extended header (Optional not vital for correct parsing) +. # Extended Header in tppotal 6 Bytes, size 4 bytes memory size 4 B +ytes is enough to read binary no characters # no need for binary to string conversion no need for terminating +string character ('\0'). # Emptying memory for future use. read $in, $dta, 6; my ($extended_size, $number_flags, $extended_flags) = unpack "N". # 32 bits (4 Bytes) Extended size. "c". # 8 bits (1 Byte) Flags (1 Byte Flags). "C", # 8 bits (1 Byte) Extended flags (1 Byte Flags). $dta; # Due to Sync_safe remove the 0 from the beggining of each stored +element and Bitwise, # although we are working with unsigned characters and integers it + is a good practice. # Synchsafe integers are integers that keep its highest bit (bit 7 +) zeroed, making # seven bits out of eight available. say "This is the number of flags: $number_flags"; say "This is the extended header flags: $extended_flags"; say "This is the extended header size, after sync_safe: $extended_ +size"; # From the stored value we substract the Extended Header to get th +e total size so far. $length_of_data -= $extended_size; } # say "This is the length of data: $length_of_data"; while ($length_of_data) { # Beginning of Mp3 Frame (10 Bytes in total), 4 Bytes Frame_ID + 4 + Bytes Frame_Size + 2 Bytes Frame_Flags = 10 Bytes. # Loop through until the end of length of data previously measured +. read $in, $dta, 10 or die "Couldn't read from $source: $!\n"; my ($frame_id, $frame_size, $frame_flags) = unpack "A4". # 32 bits (4 Bytes) Frame_ID. "N". # 32 bits (4 Bytes) Frame_Size. "C2", # 16 bits (2 Bytes) Frame Flags. $dta; $length_of_data -= 10 + $frame_size; print "Third Part Frame id: $frame_id, Frame Size: $frame_size, F +lags: "; if ($frame_size) { read $in, $dta, $frame_size; if ($frame_id =~ m{^( TPE1 | TALB | TYER | TCON | TRCK )$}) { say $dta; next; } if ($frame_id eq "TIT2") { say $dta; last; } } } say "\nFinished reading file: $source Closing file! Goodbye!"; close $in or die "Can not close file: $source: $!\n";
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re^2: ID3 tag version 2.4.0 Pack and Unpack
by thanos1983 (Parson) on Sep 04, 2014 at 22:47 UTC |