Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine
 
PerlMonks  

Re: ID3 tag version 2.4.0 Pack and Unpack

by Tux (Canon)
on Sep 04, 2014 at 17:37 UTC ( [id://1099572]=note: print w/replies, xml ) Need Help??


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";

Enjoy, Have FUN! H.Merijn

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

    Hello Tux,

    Thank you for your time and effort. Indeed your code it is extremely smaller than mine and better I assume. It is always nice to see better coders so I could pick up a few things.

    Regarding the questions, why I did not use MP3::Tag the reason is that I wanted to practice my self with a challenging task. I wanted to introduce my self to pack and unpack. I did not even thought to check if $type is invalid.

    Again thank you for your time and effort your gave me a lot of ideas and also for future implementation.

    Seeking for Perl wisdom...on the process of learning...not there...yet!

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://1099572]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (7)
As of 2024-04-23 15:02 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found