geoffleach has asked for the wisdom of the Perl Monks concerning the following question:
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
|
---|
Replies are listed 'Best First'. | |
---|---|
Re: Bit order in bytes
by BrowserUk (Patriarch) on Dec 10, 2013 at 06:07 UTC | |
by syphilis (Archbishop) on Dec 10, 2013 at 12:08 UTC | |
by BrowserUk (Patriarch) on Dec 10, 2013 at 12:32 UTC | |
by syphilis (Archbishop) on Dec 10, 2013 at 13:38 UTC | |
by BrowserUk (Patriarch) on Dec 10, 2013 at 14:15 UTC | |
by hdb (Monsignor) on Dec 10, 2013 at 13:03 UTC | |
by BrowserUk (Patriarch) on Dec 10, 2013 at 13:10 UTC | |
by Anonymous Monk on Dec 11, 2013 at 00:36 UTC | |
by geoffleach (Scribe) on Dec 10, 2013 at 18:50 UTC | |
by BrowserUk (Patriarch) on Dec 10, 2013 at 20:30 UTC | |
Re: Bit order in bytes
by Anonymous Monk on Dec 10, 2013 at 15:32 UTC | |
by geoffleach (Scribe) on Dec 10, 2013 at 18:36 UTC |
Back to
Seekers of Perl Wisdom