I am (for my sins) the maintainer of Audio::TagLib. There, I said it. My question arises out of constructing code that creates a 32-bit header for MPEG files. The header consists of bit fields of various widths.

This question concerns the ordering of bits in a 8-bit byte, packed into an integer. If I number the bits 7..0, the assignment results in a value when unpacked with 'b*' gives me the expected result: 11110010, with bit #7 on the left. The TagLib C++ library with which I communicate expects the field to look like this: 01001111, which is what one gets when unpacking with B*.

A pointer to doc that explains what's behind b vs B decoding would be greatly appreciated.

The actual code is attached.

Thanks.

#!/usr/bin/perl # Reference taglib-1.9.1 doc TagLib::MPEG::Header # and http://www.mp3-tech.org/programmer/frame_header.html package MPEG_Header; my %header = ( 'FrameSync' => [31,21], # Frame sync (all bits m +ust be set) 'VersionID' => [20,19], # MPEG Audio version ID 'Layer' => [18,17], # Layer description 'Protection' => [16,16], # Protection bit 'BitRate' => [15,12], # Bitrate index 'SamplingRate' => [11,10], # Sampling rate frequenc +y index 'Padding' => [9,9], # Padding bit 'Private' => [8,8], # Private bit. This one +is only informative. 'ChannelMode' => [7,6], # Channel Mode 'ModeExtension' => [5,4], # Mode extension (Only u +sed in Joint stereo) 'Copyright' => [3,3], # Copyright 'Original' => [2,2], # Original 'Emphasis' => [1,0], # Emphasis ); my %VersionID = ('2.5' => 0b00, '2' => 0b10, '1' => 0b11, ); my %Layer = ('III' => 0b01, 'II' => 0b10, 'I' => 0b11, ); my %Padding = ('Pad' => 0b1, 'NoPad' => 0b0, ); my %Protection = ('Protected' => 0b0, 'NotProtected' => 0b1, ); my %ChannelMode = ('Stereo' => 0b00, 'JointStereo' => 0b01, 'DualChannel' => 0b10, 'SingleChannel' => 0b11, ); my %Copyright = ('No', => 0b0, 'Yes' => 0b1, ); my %Original = ('Copy' => 0b0, 'Original' => 0b1, ); my %Emphasis = ('None' => 0b00, '5015' => 0b01, 'CCIT' => 0b11, ); sub _set_header_field { my ($hdr, $field, $value) = @_; warn "Field $field is not defined in the MPEG header\n" unless $he +ader{$field}; my $first = $header{$field}->[0]; my $last = $header{$field}->[1]; $hdr = pack("B*", "0"x32) unless defined $hdr; my ($pos, $off); if ( defined $value ) { # Field value assignment # Possible symbolic reference no strict 'refs'; # For symbolic reference $value = $$field{$value} if exists $$field{$value}; my $width = $first - $last + 1; for ($pos = $first; $width; $width --, $pos --) { $off = 31 - $pos; vec($hdr, $off, 1) = vec($value, $width - 1, 1); } return $hdr; } # Fill field with 1s for ($pos = $first; $pos >= $last; $pos --) { $off = 31 - $pos; vec($hdr, $off, 1) = 1; } return $hdr; } sub build_header { my %args = @_; my $header; $header = _set_header_field( $header, 'FrameSync' ); # All headers + have this foreach my $key ( keys %args ) { $header = _set_header_field( $header, $key, $args{$key} ); } return $header; } 1; =if 0 #! /usr/bin/perl use lib '.'; use MPEG_Header; my $mpeg_header = MPEG_Header::build_header( 'VersionID' => 2, 'Layer' => 'III', 'Protection' => 'NotPro +tected', 'BitRate' => 0b1000, + # 64 kbps for V2 and L3 'SamplingRate' => 0b10, # + 16000 Hz for V2 'Padding' => 'Pad', 'ChannelMode' => 'Stereo +', 'Copyright' => 'No', 'Original' => 'Yes', 'Emphasis' => 'CCIT', ); printf "b %-s\n", unpack("b*", $mpeg_header); printf "B %-s\n", unpack("B*", $mpeg_header); Spaces added. Unpack with b vs B. b 11111111 11110010 10001000 11000111 00001100 B 11111111 01001111 00010001 11100011 00110000 =cut

In reply to Bit order in bytes by geoffleach

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.