download this file: class.ogg.php view text/plain: class.ogg.php file encoding: UTF-8 [goback]
<?php
##
## getID3() by James Heinrich <info@getid3.org>
## available at http://getid3.sourceforge.net
##    or http://www.getid3.org
##
## getid3.ogg.php - part of getID3()
## See getid3.readme.txt for more details
##
## renew 'class.ogg.php' file
## author  : san2(at)linuxchannel.net
## url     : http://linuxchannel.net/
## changes :
##    - 2003.05.27
##

## ogg file header infomation
##
class ogg
{
  var 
$file    '';    // ogg file
  
var $error    '';    // for error debugging
  
var $bitrate    0;
  var 
$filesize    0;
  var 
$crc    false;    // Frames are crc protected?
  
var $frequency0;        // Frequency
  
var $padding    false;    // Frames padded
  
var $private    false;    // Private bit set?
  
var $mode    '';        // Mode (Stereo etc)
  
var $length    '';    // length of mp3 format hh:ss
  
var $lengths    0;    // length of mp3 in seconds
  
var $tmp    = array('Unknown','Mono','Stereo',''=>'Unknown');

  
## initial function
  ##
  
function ogg($debug=0)
  {
    
define('FREAD_BUFFER_SIZE',16384);
  }

  function 
gettag($file)
  {
    
$info = array();
    
$info['ogg'] = array();
    
$info['audio'] = array();

    
$this->file $file;

     if(!
$fd = @fopen($this->file,'rb'))
    {
        
$this->error 'Unable to open : '.$this->file;
        return;
    }

    
$info $this->getoggheaderfilepointer($fd);
    @
fclose($fd);

    
//$this->info = $info;

    ## $info['ogg'] copy to $this;
    ##
    
$this->array2this($info['ogg']);
    unset(
$info['ogg']);

    
## $info['audio'] copy to $this;
    ##
    
$this->array2this($info['audio']);
    unset(
$info['audio']);

    
## $info copy to $this;
    ##
    
$this->array2this($info);
    unset(
$info);

    
$this->filesize $this->hsize($this->filesize);
    
$this->mode $this->tmp[$this->channels];

    if(
$this->samplerate$this->frequency $this->samplerate .'Hz';

    if(
$this->bitrate round($this->bitrate))
    {
        
$s = (float)((($this->avdataend-$this->avdataoffset)*8)/$this->bitrate);

        
$this->length sprintf('%02d:%02d',floor($s/60),floor($s-(floor($s/60)*60)));
        
$this->lengths = (int)$s;
        
$this->bitrate = (int)($this->bitrate/1024).'Kbps';
    }
  }

  function 
hsize($bfsize$sub=0)
  {
    
$bytes number_format($bfsize).' Bytes';

    if(
$bfsize 1024) return $bytes;
    else if(
$bfsize 1048576$bfsize number_format(round($bfsize/1024)).' KB';
    else if(
$bfsize 1073741827$bfsize number_format($bfsize/1048576,1).'MB';
    else 
$bfsize number_format($bfsize/1073741827,1).' GB';

    if(
$sub$bfsize .= "($bytes)";
  
    return 
$bfsize;
  }

  function 
array2this($array)
  {
    if(!
is_array($array)) return;

    foreach(
$array AS $k=>$v)
    { 
$this->$k $v; }
  }

  function 
getOggHeaderFilepointer(&$fd)
  {
    
$ThisFileInfo = array();
    
$ThisFileInfo['avdataoffset'] = 0;

    
fseek($fd,0,SEEK_END); // end to file pinter
    
$ThisFileInfo['avdataend'] = $ThisFileInfo['filesize'] = ftell($fd); // for 2^32 over

    // Page 1 - Stream Header
    //fseek($fd, $ThisFileInfo['avdataoffset'], SEEK_SET);
    
rewind($fd);

    if(!
$oggpageinfo $this->ParseOggPageHeader($fd))
    {
        
$ThisFileInfo['error'] .= "\n".'not Ogg file';
        return 
$ThisFileInfo;
    }

    
$ThisFileInfo['fileformat'] = 'ogg';
    
$ThisFileInfo['ogg']['pageheader'][$oggpageinfo['page_seqno']] = $oggpageinfo;

    if(
ftell($fd) >= FREAD_BUFFER_SIZE)
    {
        
$ThisFileInfo['error'] .= "\n".'Could not find start of Ogg page in the first '.
            
FREAD_BUFFER_SIZE.' bytes (this might not be an Ogg-Vorbis file?)';
        unset(
$ThisFileInfo['fileformat']);
        unset(
$ThisFileInfo['ogg']);

        return 
$ThisFileInfo;
    }

    
$filedata fread($fd$oggpageinfo['page_length']);
    
$filedataoffset 0;

    if(
substr($filedata04) == 'fLaC')
    {
        
$ThisFileInfo['audio']['dataformat']   = 'flac';
        
$ThisFileInfo['audio']['bitrate_mode'] = 'vbr';
        
$ThisFileInfo['audio']['lossless']     = true;

    }

    else if(
substr($filedata16) == 'vorbis')
    {
        
$ThisFileInfo['audio']['dataformat'] = 'vorbis';
        
$ThisFileInfo['audio']['lossless']   = false;

        
$ThisFileInfo['ogg']['pageheader'][$oggpageinfo['page_seqno']]['packet_type']
            = 
$this->LittleEndian2Int(substr($filedata$filedataoffset1));
        
$filedataoffset += 1;
        
$ThisFileInfo['ogg']['pageheader'][$oggpageinfo['page_seqno']]['stream_type']
            = 
substr($filedata$filedataoffset6); // hard-coded to 'vorbis'
        
$filedataoffset += 6;
        
$ThisFileInfo['ogg']['bitstreamversion']
            = 
$this->LittleEndian2Int(substr($filedata$filedataoffset4));
        
$filedataoffset += 4;
        
$ThisFileInfo['ogg']['numberofchannels']
            = 
$this->LittleEndian2Int(substr($filedata$filedataoffset1));
        
$filedataoffset += 1;
        
$ThisFileInfo['audio']['channels']
            = 
$ThisFileInfo['ogg']['numberofchannels'];
        
$ThisFileInfo['ogg']['samplerate']
            = 
$this->LittleEndian2Int(substr($filedata$filedataoffset4));
        
$filedataoffset += 4;

        if(
$ThisFileInfo['ogg']['samplerate'] == 0)
        {
            
$ThisFileInfo['error'] .= "\n".'Corrupt Ogg file: sample rate == zero';
            return 
$ThisFileInfo;
        }

        
$ThisFileInfo['audio']['sample_rate'] = $ThisFileInfo['ogg']['samplerate'];
        
$ThisFileInfo['ogg']['samples'] = 0// filled in later
        
$ThisFileInfo['ogg']['bitrate_average']  = 0// filled in later
        
$ThisFileInfo['ogg']['bitrate_max']
            = 
$this->LittleEndian2Int(substr($filedata,  $filedataoffset4));
        
$filedataoffset += 4;
        
$ThisFileInfo['ogg']['bitrate_nominal'
            = 
$this->LittleEndian2Int(substr($filedata$filedataoffset4));
        
$filedataoffset += 4;
        
$ThisFileInfo['ogg']['bitrate_min']
            = 
$this->LittleEndian2Int(substr($filedata$filedataoffset4));
        
$filedataoffset += 4;
        
$ThisFileInfo['ogg']['blocksize_small']
            = 
pow(2,  $this->LittleEndian2Int(substr($filedata$filedataoffset1)) & 0x0F);
        
$ThisFileInfo['ogg']['blocksize_large']  = pow(2, ($this->LittleEndian2Int(substr($filedata$filedataoffset1)) & 0xF0) >> 4);
        
$ThisFileInfo['ogg']['stop_bit']
            = 
$this->LittleEndian2Int(substr($filedata$filedataoffset1)); // must be 1, marks end of packet

        
$ThisFileInfo['audio']['bitrate_mode'] = 'vbr'// overridden if actually abr

        
if($ThisFileInfo['ogg']['bitrate_max'] == 0xFFFFFFFF)
        {
            unset(
$ThisFileInfo['ogg']['bitrate_max']);
            
$ThisFileInfo['audio']['bitrate_mode'] = 'abr';
        }
        if(
$ThisFileInfo['ogg']['bitrate_nominal'] == 0xFFFFFFFF)
        {
            unset(
$ThisFileInfo['ogg']['bitrate_nominal']);
        }
        if(
$ThisFileInfo['ogg']['bitrate_min'] == 0xFFFFFFFF)
        {
            unset(
$ThisFileInfo['ogg']['bitrate_min']);
            
$ThisFileInfo['audio']['bitrate_mode'] = 'abr';
        }

    }

    
// http://www.speex.org/manual/node10.html
    //
    
else if(substr($filedata08) == 'Speex   ')
    {
        
$ThisFileInfo['audio']['dataformat'] = 'speex';
        
$ThisFileInfo['mime_type'] = 'audio/speex';
        
$ThisFileInfo['audio']['bitrate_mode'] = 'abr';
        
$ThisFileInfo['audio']['lossless'] = false;

        
$ThisFileInfo['ogg']['pageheader'][$oggpageinfo['page_seqno']]['speex_string']
            = 
substr($filedata$filedataoffset8); // hard-coded to 'Speex   '
        
$filedataoffset += 8;
        
$ThisFileInfo['ogg']['pageheader'][$oggpageinfo['page_seqno']]['speex_version']
            = 
substr($filedata$filedataoffset20);
        
$filedataoffset += 20;
        
$ThisFileInfo['ogg']['pageheader'][$oggpageinfo['page_seqno']]['speex_version_id']
            = 
$this->LittleEndian2Int(substr($filedata$filedataoffset4));
        
$filedataoffset += 4;
        
$ThisFileInfo['ogg']['pageheader'][$oggpageinfo['page_seqno']]['header_size']
            = 
$this->LittleEndian2Int(substr($filedata$filedataoffset4));
        
$filedataoffset += 4;
        
$ThisFileInfo['ogg']['pageheader'][$oggpageinfo['page_seqno']]['rate']
            = 
$this->LittleEndian2Int(substr($filedata$filedataoffset4));
        
$filedataoffset += 4;
        
$ThisFileInfo['ogg']['pageheader'][$oggpageinfo['page_seqno']]['mode']
            = 
$this->LittleEndian2Int(substr($filedata$filedataoffset4));
        
$filedataoffset += 4;
        
$ThisFileInfo['ogg']['pageheader'][$oggpageinfo['page_seqno']]['mode_bitstream_version']
            = 
$this->LittleEndian2Int(substr($filedata$filedataoffset4));
        
$filedataoffset += 4;
        
$ThisFileInfo['ogg']['pageheader'][$oggpageinfo['page_seqno']]['nb_channels']
            = 
$this->LittleEndian2Int(substr($filedata$filedataoffset4));
        
$filedataoffset += 4;
        
$ThisFileInfo['ogg']['pageheader'][$oggpageinfo['page_seqno']]['bitrate']
            = 
$this->LittleEndian2Int(substr($filedata$filedataoffset4));
        
$filedataoffset += 4;
        
$ThisFileInfo['ogg']['pageheader'][$oggpageinfo['page_seqno']]['framesize']
            = 
$this->LittleEndian2Int(substr($filedata$filedataoffset4));
        
$filedataoffset += 4;
        
$ThisFileInfo['ogg']['pageheader'][$oggpageinfo['page_seqno']]['vbr']
            = 
$this->LittleEndian2Int(substr($filedata$filedataoffset4));
        
$filedataoffset += 4;
        
$ThisFileInfo['ogg']['pageheader'][$oggpageinfo['page_seqno']]['frames_per_packet']
            = 
$this->LittleEndian2Int(substr($filedata$filedataoffset4));
        
$filedataoffset += 4;
        
$ThisFileInfo['ogg']['pageheader'][$oggpageinfo['page_seqno']]['extra_headers']
            = 
$this->LittleEndian2Int(substr($filedata$filedataoffset4));
        
$filedataoffset += 4;
        
$ThisFileInfo['ogg']['pageheader'][$oggpageinfo['page_seqno']]['reserved1']
            = 
$this->LittleEndian2Int(substr($filedata$filedataoffset4));
        
$filedataoffset += 4;
        
$ThisFileInfo['ogg']['pageheader'][$oggpageinfo['page_seqno']]['reserved2']
            = 
$this->LittleEndian2Int(substr($filedata$filedataoffset4));
        
$filedataoffset += 4;

        
$ThisFileInfo['speex']['speex_version']
            = 
trim($ThisFileInfo['ogg']['pageheader'][$oggpageinfo['page_seqno']]['speex_version']);
        
$ThisFileInfo['speex']['sample_rate']
            = 
$ThisFileInfo['ogg']['pageheader'][$oggpageinfo['page_seqno']]['rate'];
        
$ThisFileInfo['speex']['channels']
            = 
$ThisFileInfo['ogg']['pageheader'][$oggpageinfo['page_seqno']]['nb_channels'];
        
$ThisFileInfo['speex']['vbr']
            = (bool) 
$ThisFileInfo['ogg']['pageheader'][$oggpageinfo['page_seqno']]['vbr'];
        
$ThisFileInfo['speex']['band_type']
            = 
$this->SpeexBandModeLookup($ThisFileInfo['ogg']['pageheader'][$oggpageinfo['page_seqno']]['mode']);

        
$ThisFileInfo['audio']['sample_rate']
            = 
$ThisFileInfo['speex']['sample_rate'];
        
$ThisFileInfo['audio']['channels']
            = 
$ThisFileInfo['speex']['channels'];

        if(
$ThisFileInfo['speex']['vbr'])
        { 
$ThisFileInfo['audio']['bitrate_mode'] = 'vbr'; }
    }

    else
    {
        
$ThisFileInfo['error'] .=
            
"\n".'Expecting either "Speex   " or '.
            
'"vorbis" identifier strings, found neither';
        unset(
$ThisFileInfo['ogg']);
        unset(
$ThisFileInfo['mime_type']);
        return 
$ThisFileInfo;
    }

    
// Last Page - Number of Samples

    
fseek($fdmax($ThisFileInfo['avdataend'] - FREAD_BUFFER_SIZE0), SEEK_SET);
    
$LastChunkOfOgg strrev(fread($fdFREAD_BUFFER_SIZE));

    if(
$LastOggSpostion strpos($LastChunkOfOgg'SggO'))
    {
        
fseek($fd$ThisFileInfo['avdataend'] - ($LastOggSpostion strlen('SggO')), SEEK_SET);
        
$ThisFileInfo['avdataend'] = ftell($fd);
        
$ThisFileInfo['ogg']['pageheader']['eos'] = $this->ParseOggPageHeader($fd);
        
$ThisFileInfo['ogg']['samples']
            = 
$ThisFileInfo['ogg']['pageheader']['eos']['pcm_abs_position'];

        if(
$ThisFileInfo['ogg']['samples'] == 0)
        {
            
$ThisFileInfo['error'] .= "\n".'Corrupt Ogg file: eos.number of samples == zero';
            return 
$ThisFileInfo;
        }

        
$ThisFileInfo['ogg']['bitrate_average']
            = ((
$ThisFileInfo['avdataend'] - $ThisFileInfo['avdataoffset']) * 8)
            / (
$ThisFileInfo['ogg']['samples'] / $ThisFileInfo['audio']['sample_rate']);
    }

    if(isset(
$ThisFileInfo['ogg']['bitrate_average'])
        && (
$ThisFileInfo['ogg']['bitrate_average'] > 0))
    {
        
$ThisFileInfo['audio']['bitrate'] = $ThisFileInfo['ogg']['bitrate_average'];
    }

    else if(isset(
$ThisFileInfo['ogg']['bitrate_nominal'])
        && (
$ThisFileInfo['ogg']['bitrate_nominal'] > 0))
    {
        
$ThisFileInfo['audio']['bitrate'] = $ThisFileInfo['ogg']['bitrate_nominal'];
    }
    else if(isset(
$ThisFileInfo['ogg']['bitrate_min'])
        && isset(
$ThisFileInfo['ogg']['bitrate_max']))
    {
        
$ThisFileInfo['audio']['bitrate']
            = (
$ThisFileInfo['ogg']['bitrate_min'] + $ThisFileInfo['ogg']['bitrate_max']) / 2;
    }

    
/***
    if (isset($ThisFileInfo['audio']['bitrate']) && !isset($ThisFileInfo['playtime_seconds'])) {
        if ($ThisFileInfo['audio']['bitrate'] == 0) {
            $ThisFileInfo['error'] .= "\n".'Corrupt Ogg file: bitrate_audio == zero';
            return false;
        }
    }
    ***/

    //$ThisFileInfo['playtime_seconds']
    //    = (float) ((($ThisFileInfo['avdataend'] - $ThisFileInfo['avdataoffset']) * 8) / $ThisFileInfo['audio']['bitrate']);

    
if(isset($ThisFileInfo['ogg']['vendor']))
    {
        
$ThisFileInfo['audio']['encoder']
            = 
preg_replace('/^Encoded with /'''$ThisFileInfo['ogg']['vendor']);
    }

    return 
$ThisFileInfo;
  }


  
// http://xiph.org/ogg/vorbis/doc/framing.html
  //
  
function ParseOggPageHeader(&$fd)
  {
    
$oggheader['page_start_offset'] = ftell($fd); // where we started from in the file

    
$filedata fread($fdFREAD_BUFFER_SIZE);
    
$filedataoffset 0;
    while((
substr($filedata$filedataoffset++, 4) != 'OggS'))
    {
        if((
ftell($fd) - $oggheader['page_start_offset']) >= FREAD_BUFFER_SIZE) {
            
// should be found before here
            
return false;
        }
        if(((
$filedataoffset 28) > strlen($filedata)) || (strlen($filedata) < 28)) {
            if (
feof($fd) || (($filedata .= fread($fdFREAD_BUFFER_SIZE)) === false)) {
                
// get some more data, unless eof, in which case fail
                
return false;
            }
        }
    }

    
$filedataoffset += strlen('OggS') - 1// page, delimited by 'OggS'

    
$oggheader['stream_structver'
        = 
$this->LittleEndian2Int(substr($filedata$filedataoffset1));
    
$filedataoffset += 1;
    
$oggheader['flags_raw']
        = 
$this->LittleEndian2Int(substr($filedata$filedataoffset1));
    
$filedataoffset += 1;
    
$oggheader['flags']['fresh']
        = (bool) (
$oggheader['flags_raw'] & 0x01); // fresh packet
    
$oggheader['flags']['bos']
        = (bool) (
$oggheader['flags_raw'] & 0x02); // first page of logical bitstream (bos)
    
$oggheader['flags']['eos']
        = (bool) (
$oggheader['flags_raw'] & 0x04); // last page of logical bitstream (eos)
    
$oggheader['pcm_abs_position']
        = 
$this->LittleEndian2Int(substr($filedata$filedataoffset8));
    
$filedataoffset += 8;
    
$oggheader['stream_serialno']
        = 
$this->LittleEndian2Int(substr($filedata$filedataoffset4));
    
$filedataoffset += 4;
    
$oggheader['page_seqno']
        = 
$this->LittleEndian2Int(substr($filedata$filedataoffset4));
    
$filedataoffset += 4;
    
$oggheader['page_checksum']
        = 
$this->LittleEndian2Int(substr($filedata$filedataoffset4));
    
$filedataoffset += 4;
    
$oggheader['page_segments']
        = 
$this->LittleEndian2Int(substr($filedata$filedataoffset1));
    
$filedataoffset += 1;
    
$oggheader['page_length'] = 0;

    for(
$i=0$i<$oggheader['page_segments']; $i++)
    {
        
$oggheader['segment_table'][$i]
            = 
$this->LittleEndian2Int(substr($filedata,$filedataoffset,1));
        
$filedataoffset += 1;
        
$oggheader['page_length'] += $oggheader['segment_table'][$i];
    }

    
$oggheader['header_end_offset'] = $oggheader['page_start_offset']+$filedataoffset;
    
$oggheader['page_end_offset']   = $oggheader['header_end_offset']+$oggheader['page_length'];
    
fseek($fd$oggheader['header_end_offset'], SEEK_SET);

    return 
$oggheader;
  }

  function 
SpeexBandModeLookup($mode)
  {
    static 
$SpeexBandModeLookup = array();
    if(empty(
$SpeexBandModeLookup))
    {
        
$SpeexBandModeLookup[0] = 'narrow';
        
$SpeexBandModeLookup[1] = 'wide';
        
$SpeexBandModeLookup[2] = 'ultra-wide';
    }

    return (isset(
$SpeexBandModeLookup[$mode]) ? $SpeexBandModeLookup[$mode] : null);
  }

  function 
OggPageSegmentLength($OggInfoArray$SegmentNumber=1)
  {
    for(
$i=0$i<$SegmentNumber$i++)
    {
        
$segmentlength 0;
        foreach (
$OggInfoArray['segment_table'] AS $key => $value)
        {
            
$segmentlength += $value;
            if (
$value 255) break;
        }
    }

    return 
$segmentlength;
  }

  function 
DecimalBinary2Float($binarynumerator)
  {
    
$numerator BinDec($binarynumerator);
    
$denominator BinDec(str_repeat('1'strlen($binarynumerator)));

    return (
$numerator $denominator);
  }

  function 
LittleEndian2Float($byteword)
  {
    return 
$this->BigEndian2Float(strrev($byteword));
  }

  
// ANSI/IEEE Standard 754-1985, Standard for Binary Floating Point Arithmetic
  // http://www.psc.edu/general/software/packages/ieee/ieee.html
  // http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/ieee.html
  //
  
function BigEndian2Float($byteword)
  {
    
$bitword $this->BigEndian2Bin($byteword);
    
$signbit $bitword{0};

    switch(
strlen($byteword) * 8)
    {
        case 
32:
            
$exponentbits 8;
            
$fractionbits 23;
            break;
        case 
64:
            
$exponentbits 11;
            
$fractionbits 52;
            break;
        case 
80:
            
$exponentbits 16;
            
$fractionbits 64;
            break;
        default:
            return 
false;
            break;
    }

    
$exponentstring substr($bitword1$exponentbits 1);
    
$fractionstring substr($bitword$exponentbits$fractionbits);
    
$exponent BinDec($exponentstring);
    
$fraction BinDec($fractionstring);

    if((
$exponentbits == 16) && ($fractionbits == 64))
    {
        
// 80-bit
        // As used in Apple AIFF for sample_rate
        // A bit of a hack, but it works ;)
        
return pow(2, ($exponent  16382)) * $this->DecimalBinary2Float($fractionstring);
    }

    if((
$exponent == (pow(2$exponentbits) - 1)) && ($fraction != 0))
    {
        
// Not a Number
        
$floatvalue false;
    }

    else if((
$exponent == (pow(2$exponentbits) - 1)) && ($fraction == 0))
    {
        if (
$signbit == '1') {
            
$floatvalue '-infinity';
        } else {
            
$floatvalue '+infinity';
        }
    }

    else if((
$exponent == 0) && ($fraction == 0))
    {
        if (
$signbit == '1') {
            
$floatvalue = -0;
        } else {
            
$floatvalue 0;
        }
        
$floatvalue = ($signbit : -0);
    }

    else if((
$exponent == 0) && ($fraction != 0))
    {
        
// These are 'unnormalized' values
        
$floatvalue pow(2, (-* (pow(2$exponentbits 1) - 2)))
            * 
$this->DecimalBinary2Float($fractionstring);
        if (
$signbit == '1') {
            
$floatvalue *= -1;
        }
    }

    else if(
$exponent != 0)
    {
        
$floatvalue pow(2, ($exponent - (pow(2$exponentbits 1) - 1)))
            * (
$this->DecimalBinary2Float($fractionstring));
        if (
$signbit == '1') {
            
$floatvalue *= -1;
        }
    }

    return (float) 
$floatvalue;
  }

  
// truncates a floating-point number at the decimal point
  // returns int (if possible, otherwise float)
  //
  
function trunc($floatnumber)
  {
    if (
$floatnumber >= 1)
    {
        
$truncatednumber floor($floatnumber);
    }
    else if(
$floatnumber <= -1)
    {
        
$truncatednumber ceil($floatnumber);
    }
    else {
        
$truncatednumber 0;
    }

    if(
$truncatednumber <= pow(230))
    {
        
$truncatednumber = (int) $truncatednumber;
    }

    return 
$truncatednumber;
  }

  function 
CastAsInt($floatnum)
  {
    
// convert to float if not already
    
$floatnum = (float) $floatnum;

    
// convert a float to type int, only if possible
    
if($this->trunc($floatnum) == $floatnum)
    {
        
// it's not floating point
        
if($floatnum <= pow(230))
        {
            
// it's within int range
            
$floatnum = (int) $floatnum;
        }
    }

    return 
$floatnum;
  }

  function 
BigEndian2Int($byteword$synchsafe=false$signed=false)
  {
    
$intvalue 0;
    
$bytewordlen strlen($byteword);

    for(
$i=0$i<$bytewordlen$i++)
    {
        
// disregard MSB, effectively 7-bit bytes
        
if($synchsafe)
        {
            
$intvalue $intvalue
                
| (ord($byteword{$i})&0x7F)
                << ((
$bytewordlen-1-$i)*7);
        } else
        {
            
$intvalue += ord($byteword{$i})
                * 
pow(256,($bytewordlen-1-$i));
        }
    }

    if(
$signed && !$synchsafe)
    {
        
// synchsafe ints are not allowed to be signed
        
switch($bytewordlen)
        {
            case 
1:
            case 
2:
            case 
3:
            case 
4:
                
$signmaskbit 0x80 << (8*($bytewordlen-1));
                if(
$intvalue $signmaskbit)
                { 
$intvalue 0-($intvalue&($signmaskbit-1)); }
                break;
            default:
                
//die('ERROR: Cannot have signed integers '.
                //    'larger than 32-bits in BigEndian2Int()');
                
return;
                break;
        }
    }

    return 
$this->CastAsInt($intvalue);
  }

  function 
LittleEndian2Int($byteword$signed=false)
  {
    return 
$this->BigEndian2Int(strrev($byteword), false$signed);
  }

  function 
BigEndian2Bin($byteword)
  {
    
$binvalue '';
    
$bytewordlen strlen($byteword);

    for(
$i=0$i<$bytewordlen$i++)
    {
        
$binvalue .= str_pad(
            
decbin(ord($byteword{$i})),8,'0',STR_PAD_LEFT
            
);
    }

    return 
$binvalue;
  }

  function 
BigEndian2String($number$minbytes=1$synchsafe=false$signed=false)
  {
    if(
$number 0) return false;

    
$maskbyte = (($synchsafe || $signed) ? 0x7F 0xFF);
    
$intstring '';

    if(
$signed)
    {
        if(
$minbytes 4)
        {
            
//die('ERROR: Cannot have signed integers '.
            //    'larger than 32-bits in BigEndian2String()');
            
return;
        }
        
$number $number & (0x80 << (* ($minbytes 1)));
    }

    while(
$number != 0)
    {
        
$quotient = ($number / ($maskbyte 1));
        
$intstring chr(ceil(
                (
$quotient-floor($quotient))*$maskbyte
                
)).$intstring;
        
$number floor($quotient);
    }

    return 
str_pad($intstring$minbyteschr(0), STR_PAD_LEFT);
  }

  function 
LittleEndian2String($number$minbytes=1$synchsafe=false)
  {
    
$intstring '';
    while(
$number 0)
    {
        if (
$synchsafe) {
            
$intstring $intstring.chr($number 127);
            
$number >>= 7;
        } else {
            
$intstring $intstring.chr($number 255);
            
$number >>= 8;
        }
    }

    return 
str_pad($intstring$minbyteschr(0), STR_PAD_RIGHT);
  }
// end of class

?>