Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer
 
PerlMonks  

Re: ID3v2 TAG unpack uninitialized value

by BrowserUk (Pope)
on Jan 05, 2014 at 04:32 UTC ( #1069349=note: print w/ replies, xml ) Need Help??


in reply to ID3v2 TAG unpack uninitialized value

You are reading 4 bytes:

read( FH , $lines, 4 ); # Read 32 bits (4 Bytes) and store the data in + $lines Size (4 Bytes Size).

And then attempting to unpack four x 4-byte integers ("I I I I"):

( $lines_1, $lines_2, $lines_3, $lines_4 ) = unpack ( "I I I I" , + $lines ); # (I) An unsigned integer.

Fix: read enough data to satisfy the unpack template (ie. 16 bytes):

read( FH , $lines, 16 ); # Read 4x 32 bits (4 Bytes) and store the dat +a in $lines Size (16 Bytes Size). ( $lines_1, $lines_2, $lines_3, $lines_4 ) = unpack ( "I I I I" , + $lines ); # (I I I I ) FOUR unsigned integer(S).

With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.


Comment on Re: ID3v2 TAG unpack uninitialized value
Select or Download Code
Re^2: ID3v2 TAG unpack uninitialized value
by no_slogan (Deacon) on Jan 05, 2014 at 15:46 UTC

    Actually, you want to unpack them as four bytes. unpack "CCCC". ID3 has this wacky format that stores a 28-bit integer with 7 bits per byte, which I see the OP is already aware of.

    The pack "I" format is not nearly as useful as you might think, because the length and byte order are both platform-dependent. You usually want to stick with "N" or "V".

      Thanks for the tip no_slogan, I actually print tried all of them and I got the same result for (I An unsigned integer and for V A long integer in VAX order). Output can be viewed under:

      This is the content of lines_0 with I: 990183424 This is the content of lines_1 with I: 826626132 This is the content of lines_2 with I: 167772160 This is the content of lines_3 with I: 1090519040 This is the content of lines_0 with V: 990183424 This is the content of lines_1 with V: 826626132 This is the content of lines_2 with V: 167772160 This is the content of lines_3 with V: 1090519040

      When I tried to print the (N A long integer in network order) option I got this result:

      This is the content of lines_0: 1339 This is the content of lines_1: 1414546737 This is the content of lines_2: 10 This is the content of lines_3: 65

      The reason that I was using the (I An unsigned integer) characters is that on the official website description says:

      http://id3.org/id3v2.4.0-structure
      %x is used to indicate a bit with unknown content. ID3v2 size 4 * %0xxxxxxx
      The ID3v2 tag size is stored as a 32 bit synchsafe integer (section 6. +2), making a total of 28 effective bits (representing up to 256MB).
Re^2: ID3v2 TAG unpack uninitialized value
by thanos1983 (Pilgrim) on Jan 05, 2014 at 23:42 UTC

    Thanks a lot it works just fine, but I am really confused. I have been trying to understand how the ID3v2 TAG works and I can not figure out this part (header size). Theoretically the whole header should be 10 Bytes. The size part is 4 Unsigned Bytes. So based on this theory if I read 4 Bytes I should be able to get the whole header size. In practice I failed.

    The information that I have take is from the official page of the TAG given under:

    http://id3.org/id3v2.3.0

    I can not still figure this out, because then by adding 16 Bytes (16 Bytes = 4 Unsigned Bytes x 32 Bits size each). So in theory the header size is 4 Bytes now will be 16 Bytes.

    Please correct me if I am wrong

      I can not still figure this out, because then by adding 16 Bytes (16 Bytes = 4 Unsigned Bytes x 32 Bits size each). So in theory the header size is 4 Bytes now will be 16 Bytes.

      As the spec you've now linked indicates that the 'size' field is a 28-bit value encoded in 7-lsbs of each of 4 bytes, my correction of your code was wrong. You should not read 16 byte and decode with a template of "I I I I" as I suggested.

      But rather read 4 bytes as you were, but then decode with a template of 'C C C C' (or 'CCCC' or 'C4').

      And if you unpack to a variable called my @size = unpack 'C4', ...; (rather than the 4 separate $lines_* variables), then the following code from your OP:

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

      starts to make sense. It extracts the 7-bit values from the 4 bytes and combines them together to produce the required 28-bit numeric value.

      BTW: reading 4 bytes into a variable called $lines is also misleading.


      With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      "Science is about questioning the status quo. Questioning authority".
      In the absence of evidence, opinion is indistinguishable from prejudice.

        It seems correct reading 4 Bytes and printing with C4 but I thought that I should print 4 Unsigned Integers this is the reason that I was using I4. Maybe I was wrong.

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others lurking in the Monastery: (4)
As of 2014-11-23 09:07 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    My preferred Perl binaries come from:














    Results (129 votes), past polls