28                $info = &$this->getid3->info;
 
   31                $StreamMarker = $this->
fread(4);
 
   32                if ($StreamMarker != self::syncword) {
 
   35                $info[
'fileformat']            = 
'flac';
 
   36                $info[
'audio'][
'dataformat']   = 
'flac';
 
   37                $info[
'audio'][
'bitrate_mode'] = 
'vbr';
 
   38                $info[
'audio'][
'lossless']     = 
true;
 
   45                $info = &$this->getid3->info;
 
   47                        $BlockOffset   = $this->
ftell();
 
   48                        $BlockHeader   = $this->
fread(4);
 
   50                        $LastBlockFlag = (bool) ($LBFBT & 0x80);
 
   51                        $BlockType     =        ($LBFBT & 0x7F);
 
   55                        if (($BlockOffset + 4 + $BlockLength) > 
$info[
'avdataend']) {
 
   56                                $this->
error(
'METADATA_BLOCK_HEADER.BLOCK_TYPE ('.$BlockTypeText.
') at offset '.$BlockOffset.
' extends beyond end of file');
 
   59                        if ($BlockLength < 1) {
 
   60                                $this->
error(
'METADATA_BLOCK_HEADER.BLOCK_LENGTH ('.$BlockLength.
') at offset '.$BlockOffset.
' is invalid');
 
   64                        $info[
'flac'][$BlockTypeText][
'raw'] = array();
 
   65                        $BlockTypeText_raw = &
$info[
'flac'][$BlockTypeText][
'raw'];
 
   67                        $BlockTypeText_raw[
'offset']          = $BlockOffset;
 
   68                        $BlockTypeText_raw[
'last_meta_block'] = $LastBlockFlag;
 
   69                        $BlockTypeText_raw[
'block_type']      = $BlockType;
 
   70                        $BlockTypeText_raw[
'block_type_text'] = $BlockTypeText;
 
   71                        $BlockTypeText_raw[
'block_length']    = $BlockLength;
 
   72                        if ($BlockTypeText_raw[
'block_type'] != 0x06) { 
 
   73                                $BlockTypeText_raw[
'block_data']  = $this->
fread($BlockLength);
 
   76                        switch ($BlockTypeText) {
 
   84                                        unset(
$info[
'flac'][
'PADDING']); 
 
   99                                case 'VORBIS_COMMENT': 
 
  106                                        if (!$this->
parseCUESHEET($BlockTypeText_raw[
'block_data'])) {
 
  118                                        $this->
warning(
'Unhandled METADATA_BLOCK_HEADER.BLOCK_TYPE ('.$BlockType.
') at offset '.$BlockOffset);
 
  121                        unset(
$info[
'flac'][$BlockTypeText][
'raw']);
 
  124                while ($LastBlockFlag === 
false);
 
  127                if (!empty(
$info[
'flac'][
'VORBIS_COMMENT'][
'comments'])) {
 
  128                        $info[
'flac'][
'comments'] = 
$info[
'flac'][
'VORBIS_COMMENT'][
'comments'];
 
  130                if (!empty(
$info[
'flac'][
'VORBIS_COMMENT'][
'vendor'])) {
 
  131                        $info[
'audio'][
'encoder'] = str_replace(
'reference ', 
'', 
$info[
'flac'][
'VORBIS_COMMENT'][
'vendor']);
 
  136                        foreach (
$info[
'flac'][
'PICTURE'] as $entry) {
 
  137                                if (!empty($entry[
'data'])) {
 
  138                                        if (!isset(
$info[
'flac'][
'comments'][
'picture'])) {
 
  139                                                $info[
'flac'][
'comments'][
'picture'] = array();
 
  141                                        $comments_picture_data = array();
 
  142                                        foreach (array(
'data', 
'image_mime', 
'image_width', 
'image_height', 
'imagetype', 
'picturetype', 
'description', 
'datalength') as $picture_key) {
 
  143                                                if (isset($entry[$picture_key])) {
 
  144                                                        $comments_picture_data[$picture_key] = $entry[$picture_key];
 
  147                                        $info[
'flac'][
'comments'][
'picture'][] = $comments_picture_data;
 
  148                                        unset($comments_picture_data);
 
  153                if (isset(
$info[
'flac'][
'STREAMINFO'])) {
 
  155                                $info[
'flac'][
'compressed_audio_bytes'] = 
$info[
'avdataend'] - 
$info[
'avdataoffset'];
 
  157                        $info[
'flac'][
'uncompressed_audio_bytes'] = 
$info[
'flac'][
'STREAMINFO'][
'samples_stream'] * 
$info[
'flac'][
'STREAMINFO'][
'channels'] * (
$info[
'flac'][
'STREAMINFO'][
'bits_per_sample'] / 8);
 
  158                        if (
$info[
'flac'][
'uncompressed_audio_bytes'] == 0) {
 
  159                                return $this->
error(
'Corrupt FLAC file: uncompressed_audio_bytes == zero');
 
  161                        if (!empty(
$info[
'flac'][
'compressed_audio_bytes'])) {
 
  162                                $info[
'flac'][
'compression_ratio'] = 
$info[
'flac'][
'compressed_audio_bytes'] / 
$info[
'flac'][
'uncompressed_audio_bytes'];
 
  167                if (isset(
$info[
'flac'][
'STREAMINFO'][
'audio_signature'])) {
 
  169                        if (
$info[
'flac'][
'STREAMINFO'][
'audio_signature'] === str_repeat(
"\x00", 16)) {
 
  170                $this->
warning(
'FLAC STREAMINFO.audio_signature is null (known issue with libOggFLAC)');
 
  173                                $info[
'md5_data_source'] = 
'';
 
  174                                $md5 = 
$info[
'flac'][
'STREAMINFO'][
'audio_signature'];
 
  175                                for (
$i = 0; 
$i < strlen($md5); 
$i++) {
 
  176                                        $info[
'md5_data_source'] .= str_pad(dechex(ord($md5[
$i])), 2, 
'00', STR_PAD_LEFT);
 
  178                                if (!preg_match(
'/^[0-9a-f]{32}$/', 
$info[
'md5_data_source'])) {
 
  179                                        unset(
$info[
'md5_data_source']);
 
  184                if (isset(
$info[
'flac'][
'STREAMINFO'][
'bits_per_sample'])) {
 
  185                        $info[
'audio'][
'bits_per_sample'] = 
$info[
'flac'][
'STREAMINFO'][
'bits_per_sample'];
 
  186                        if (
$info[
'audio'][
'bits_per_sample'] == 8) {
 
  190                                $this->
warning(
'FLAC calculates MD5 data strangely on 8-bit audio, so the stored md5_data_source value will not match the decoded WAV file');
 
  198                $info = &$this->getid3->info;
 
  200                $info[
'flac'][
'STREAMINFO'] = array();
 
  201                $streaminfo = &
$info[
'flac'][
'STREAMINFO'];
 
  214                $streaminfo[
'audio_signature'] = substr($BlockData, 18, 16);
 
  216                if (!empty($streaminfo[
'sample_rate'])) {
 
  218                        $info[
'audio'][
'bitrate_mode']    = 
'vbr';
 
  219                        $info[
'audio'][
'sample_rate']     = $streaminfo[
'sample_rate'];
 
  220                        $info[
'audio'][
'channels']        = $streaminfo[
'channels'];
 
  221                        $info[
'audio'][
'bits_per_sample'] = $streaminfo[
'bits_per_sample'];
 
  222                        $info[
'playtime_seconds']         = $streaminfo[
'samples_stream'] / $streaminfo[
'sample_rate'];
 
  223                        if (
$info[
'playtime_seconds'] > 0) {
 
  225                                        $info[
'audio'][
'bitrate'] = ((
$info[
'avdataend'] - 
$info[
'avdataoffset']) * 8) / 
$info[
'playtime_seconds'];
 
  228                                        $this->
warning(
'Cannot determine audio bitrate because total stream size is unknown');
 
  233                        return $this->
error(
'Corrupt METAdata block: STREAMINFO');
 
  240                $info = &$this->getid3->info;
 
  244                $info[
'flac'][
'APPLICATION'][$ApplicationID][
'data'] = substr($BlockData, 4);
 
  250                $info = &$this->getid3->info;
 
  253                $BlockLength = strlen($BlockData);
 
  254                $placeholderpattern = str_repeat(
"\xFF", 8);
 
  255                while ($offset < $BlockLength) {
 
  256                        $SampleNumberString = substr($BlockData, $offset, 8);
 
  258                        if ($SampleNumberString == $placeholderpattern) {
 
  279                $info = &$this->getid3->info;
 
  283                        $getid3_ogg->setStringMode($this->data_string);
 
  285                $getid3_ogg->ParseVorbisComments();
 
  286                if (isset(
$info[
'ogg'])) {
 
  287                        unset(
$info[
'ogg'][
'comments_raw']);
 
  288                        $info[
'flac'][
'VORBIS_COMMENT'] = 
$info[
'ogg'];
 
  298                $info = &$this->getid3->info;
 
  300                $info[
'flac'][
'CUESHEET'][
'media_catalog_number'] =                              trim(substr($BlockData, $offset, 128), 
"\0");
 
  312                for ($track = 0; $track < 
$info[
'flac'][
'CUESHEET'][
'number_tracks']; $track++) {
 
  318                        $info[
'flac'][
'CUESHEET'][
'tracks'][$TrackNumber][
'sample_offset']         = $TrackSampleOffset;
 
  320                        $info[
'flac'][
'CUESHEET'][
'tracks'][$TrackNumber][
'isrc']                  =                           substr($BlockData, $offset, 12);
 
  325                        $info[
'flac'][
'CUESHEET'][
'tracks'][$TrackNumber][
'flags'][
'is_audio']     = (bool) ($TrackFlagsRaw & 0x80);
 
  326                        $info[
'flac'][
'CUESHEET'][
'tracks'][$TrackNumber][
'flags'][
'pre_emphasis'] = (bool) ($TrackFlagsRaw & 0x40);
 
  341                                $info[
'flac'][
'CUESHEET'][
'tracks'][$TrackNumber][
'indexes'][$IndexNumber] = $IndexSampleOffset;
 
  353                $info = &$this->getid3->info;
 
  360                        $picture[
'description'] = $this->
fread($descr_length);
 
  368                if ($picture[
'image_mime'] == 
'-->') {
 
  369                        $picture[
'data'] = $this->
fread($picture[
'datalength']);
 
  372                                str_replace(
'/', 
'_', $picture[
'picturetype']).
'_'.$this->
ftell(),
 
  374                                $picture[
'datalength'],
 
  375                                $picture[
'image_mime']);
 
  378                $info[
'flac'][
'PICTURE'][] = $picture;
 
  384                static $lookup = array(
 
  389                        4 => 
'VORBIS_COMMENT',
 
  393                return (isset($lookup[$blocktype]) ? $lookup[$blocktype] : 
'reserved');
 
  398                static $lookup = array(
 
  399                        0x41544348 => 
'FlacFile',                                                                           
 
  400                        0x42534F4C => 
'beSolo',                                                                             
 
  401                        0x42554753 => 
'Bugs Player',                                                                        
 
  402                        0x43756573 => 
'GoldWave cue points (specification)',                                                
 
  403                        0x46696361 => 
'CUE Splitter',                                                                       
 
  404                        0x46746F6C => 
'flac-tools',                                                                         
 
  405                        0x4D4F5442 => 
'MOTB MetaCzar',                                                                      
 
  406                        0x4D505345 => 
'MP3 Stream Editor',                                                                  
 
  407                        0x4D754D4C => 
'MusicML: Music Metadata Language',                                                   
 
  408                        0x52494646 => 
'Sound Devices RIFF chunk storage',                                                   
 
  409                        0x5346464C => 
'Sound Font FLAC',                                                                    
 
  410                        0x534F4E59 => 
'Sony Creative Software',                                                             
 
  411                        0x5351455A => 
'flacsqueeze',                                                                        
 
  412                        0x54745776 => 
'TwistedWave',                                                                        
 
  413                        0x55495453 => 
'UITS Embedding tools',                                                               
 
  414                        0x61696666 => 
'FLAC AIFF chunk storage',                                                            
 
  415                        0x696D6167 => 
'flac-image application for storing arbitrary files in APPLICATION metadata blocks',  
 
  416                        0x7065656D => 
'Parseable Embedded Extensible Metadata (specification)',                             
 
  417                        0x71667374 => 
'QFLAC Studio',                                                                       
 
  418                        0x72696666 => 
'FLAC RIFF chunk storage',                                                            
 
  419                        0x74756E65 => 
'TagTuner',                                                                           
 
  420                        0x78626174 => 
'XBAT',                                                                               
 
  421                        0x786D6364 => 
'xmcd',                                                                               
 
  423                return (isset($lookup[$applicationid]) ? $lookup[$applicationid] : 
'reserved');
 
  427                static $lookup = array (
 
  429                         1 => 
'32x32 pixels \'file icon\' (PNG only)',
 
  430                         2 => 
'Other file icon',
 
  431                         3 => 
'Cover (front)',
 
  434                         6 => 
'Media (e.g. label side of CD)',
 
  435                         7 => 
'Lead artist/lead performer/soloist',
 
  436                         8 => 
'Artist/performer',
 
  438                        10 => 
'Band/Orchestra',
 
  440                        12 => 
'Lyricist/text writer',
 
  441                        13 => 
'Recording Location',
 
  442                        14 => 
'During recording',
 
  443                        15 => 
'During performance',
 
  444                        16 => 
'Movie/video screen capture',
 
  445                        17 => 
'A bright coloured fish',
 
  446                        18 => 
'Illustration',
 
  447                        19 => 
'Band/artist logotype',
 
  448                        20 => 
'Publisher/Studio logotype',
 
  450                return (isset($lookup[$type_id]) ? $lookup[$type_id] : 
'reserved');
 
An exception for terminatinating execution or to throw for unit testing.
@tutorial http://flac.sourceforge.net/format.html
parseAPPLICATION($BlockData)
parseSTREAMINFO($BlockData)
parseSEEKTABLE($BlockData)
static pictureTypeLookup($type_id)
static metaBlockTypeLookup($blocktype)
parseVORBIS_COMMENT($BlockData)
static applicationIDLookup($applicationid)
parseCUESHEET($BlockData)
parsePICTURE()
Parse METADATA_BLOCK_PICTURE flac structure and extract attachment External usage: audio....
saveAttachment($name, $offset, $length, $image_mime=null)
fseek($bytes, $whence=SEEK_SET)
static PrintHexBytes($string, $hex=true, $spaces=true, $htmlencoding='UTF-8')
static safe_inc(&$variable, $increment=1)
static BigEndian2Bin($byteword)
static Bin2Dec($binstring, $signed=false)
static IncludeDependency($filename, $sourcefile, $DieOnFailure=false)
static BigEndian2Int($byteword, $synchsafe=false, $signed=false)