http://www.perlmonks.org?node_id=1069598


in reply to Re^2: ID3v2 TAG Footer Reading goes wrong
in thread ID3v2 TAG Footer Reading goes wrong

The basic problem still seems to be that you're not doing anything about the frame data. You might try something like this:

$position = 10; $id3_end = 10 + $id3_size; while ($position < $id3_end) { seek FH, $position, SEEK_SET; # read $frame_id, $frame_size, and $frame_flags $position += 10 + $frame_size; last if $frame_id =~ /\W/ || $position > $id3_end; # do something with $frame_id }

The "last if" line is a sanity check, because some ID3 writers leave a mess behind them.

Replies are listed 'Best First'.
Re^4: ID3v2 TAG Footer Reading goes wrong
by thanos1983 (Parson) on Jan 10, 2014 at 23:51 UTC
    To: Anonymous Monk,

    Thanks for the suggestion and possible really interesting implementation to my code. While I was working with my code I came with another possible mistake that I trying to explain but for the moment not successfully. I noticed that the sync_safe process at the header:

    $mp3_size = ($memory[0] & 0xFF) | (( $memory[1] & 0xFF ) << 7) | (( $memory[2] & 0xFF ) << 14) | (( $memory[3] & 0xFF ) << 21);

    If I do print Dumper(@memory); before the sync_safe process, it will print out:

    $VAR1 = 0; $VAR2 = 0; $VAR3 = 5; $VAR4 = 59;

    After the sync_safe process if I do print Dumper(@memory); again, it will print out:

    $VAR1 = 123813888;

    I am curious, I know that the sync_safe process is shifting 7 bits to the left of eac byte. So no I am comfused is it operating correctly? or am I doing something wrong?

    Maybe I am missing something really basic here and this is the reason that I do not understand. Sorry for asking too many questions but since I am going through the learning curve process I have so many queries that I can not find information that will provide me a clear answer.

    Thank you again for your time and effort.

      thanos1983:

      Questions about manipulating binary numbers like that are often best solved by looking them over in binary. Using a little bit of perl:

      #!/usr/bin/perl use strict; use warnings; my @memory = (0, 0, 5, 59); print "Original values:\n"; printf "% 3u : %08b\n", $_, $_ for @memory; $memory[1] = $memory[1] << 7; $memory[2] = $memory[2] << 14; $memory[3] = $memory[3] << 21; print "\nAfter shifting the values\n"; printf "% 10u : %032b\n", $_, $_ for @memory; my $t = 0; $t += $_ for @memory; print "\nThe sum:\n"; printf "% 10u : %032b\n", $t, $t;

      Running it gives a hopefully familiar number: ;^D

      Original values: 0 : 00000000 0 : 00000000 5 : 00000101 59 : 00111011 After shifting the values 0 : 00000000000000000000000000000000 0 : 00000000000000000000000000000000 81920 : 00000000000000010100000000000000 123731968 : 00000111011000000000000000000000 The sum: 123813888 : 00000111011000010100000000000000

      Update: I just read the thread, and noticed that in your code, you use the same construct several times. Additionally, you mention that you only want seven bits. So I'd suggest writing a subroutine that masks off the high bit of your bytes and packs the number for you. Something like the following, but with a better name:

      sub plonk { my ($b0, $b1, $b2, $b3) = @_; return $b0 & 0x7f + ($b1 & 0x7f) << 7 + ($b2 & 0x7f) << 14 + ($b3 & 0x7f) << 21; }

      ...roboticus

      When your only tool is a hammer, all problems look like your thumb.

      ID3 uses big-endian byte order (high byte first), so you've got them backwards. Also, think about using a sub, like roboticus says.