Ignore:
Timestamp:
Jul 7, 2009, 10:27:37 PM (15 years ago)
Author:
vdigital
Message:

Change: getid3 upgraded to -> 1.7.9

File:
1 edited

Legend:

Unmodified
Added
Removed
  • extensions/charlies_content/getid3/getid3/module.audio.la.php

    r3318 r3544  
    11<?php
    2 // +----------------------------------------------------------------------+
    3 // | PHP version 5                                                        |
    4 // +----------------------------------------------------------------------+
    5 // | Copyright (c) 2002-2006 James Heinrich, Allan Hansen                 |
    6 // +----------------------------------------------------------------------+
    7 // | This source file is subject to version 2 of the GPL license,         |
    8 // | that is bundled with this package in the file license.txt and is     |
    9 // | available through the world-wide-web at the following url:           |
    10 // | http://www.gnu.org/copyleft/gpl.html                                 |
    11 // +----------------------------------------------------------------------+
    12 // | getID3() - http://getid3.sourceforge.net or http://www.getid3.org    |
    13 // +----------------------------------------------------------------------+
    14 // | Authors: James Heinrich <infoØgetid3*org>                            |
    15 // |          Allan Hansen <ahØartemis*dk>                                |
    16 // +----------------------------------------------------------------------+
    17 // | module.audio.la.php                                                  |
    18 // | Module for analyzing LA udio files                                   |
    19 // | dependencies: module.audio-video.riff.php                            |
    20 // +----------------------------------------------------------------------+
    21 //
    22 // $Id$
    23 
    24        
    25        
    26 class getid3_la extends getid3_handler
     2/////////////////////////////////////////////////////////////////
     3/// getID3() by James Heinrich <info@getid3.org>               //
     4//  available at http://getid3.sourceforge.net                 //
     5//            or http://www.getid3.org                         //
     6/////////////////////////////////////////////////////////////////
     7// See readme.txt for more details                             //
     8/////////////////////////////////////////////////////////////////
     9//                                                             //
     10// module.audio.la.php                                         //
     11// module for analyzing LA audio files                         //
     12// dependencies: module.audio.riff.php                         //
     13//                                                            ///
     14/////////////////////////////////////////////////////////////////
     15
     16getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.riff.php', __FILE__, true);
     17
     18class getid3_la
    2719{
    2820
    29     public function Analyze() {
    30        
    31         $getid3 = $this->getid3;
    32        
    33         $getid3->include_module('audio-video.riff');
    34        
    35         fseek($getid3->fp, $getid3->info['avdataoffset'], SEEK_SET);
    36         $raw_data = fread($getid3->fp, getid3::FREAD_BUFFER_SIZE);
    37    
    38         $getid3->info['fileformat']          = 'la';
    39         $getid3->info['audio']['dataformat'] = 'la';
    40         $getid3->info['audio']['lossless']   = true;
    41 
    42         $getid3->info['la']['version_major'] = (int)$raw_data{2};
    43         $getid3->info['la']['version_minor'] = (int)$raw_data{3};
    44         $getid3->info['la']['version']       = (float)$getid3->info['la']['version_major'] + ($getid3->info['la']['version_minor'] / 10);
    45 
    46         $getid3->info['la']['uncompressed_size'] = getid3_lib::LittleEndian2Int(substr($raw_data, 4, 4));
    47        
    48         $wave_chunk = substr($raw_data, 8, 4);
    49         if ($wave_chunk !== 'WAVE') {
    50             throw new getid3_exception('Expected "WAVE" ('.getid3_lib::PrintHexBytes('WAVE').') at offset 8, found "'.$wave_chunk.'" ('.getid3_lib::PrintHexBytes($wave_chunk).') instead.');
    51         }
    52        
    53         $offset = 12;
    54 
    55         $getid3->info['la']['fmt_size'] = 24;
    56         if ($getid3->info['la']['version'] >= 0.3) {
    57 
    58             $getid3->info['la']['fmt_size']    = getid3_lib::LittleEndian2Int(substr($raw_data, $offset, 4));
    59             $getid3->info['la']['header_size'] = 49 + $getid3->info['la']['fmt_size'] - 24;
    60             $offset += 4;
    61 
    62         } else {
    63 
    64             // version 0.2 didn't support additional data blocks
    65             $getid3->info['la']['header_size'] = 41;
    66         }
    67 
    68         $fmt_chunk = substr($raw_data, $offset, 4);
    69         if ($fmt_chunk !== 'fmt ') {
    70             throw new getid3_exception('Expected "fmt " ('.getid3_lib::PrintHexBytes('fmt ').') at offset '.$offset.', found "'.$fmt_chunk.'" ('.getid3_lib::PrintHexBytes($fmt_chunk).') instead.');
    71         }
    72         $offset += 4;
    73        
    74         $fmt_size = getid3_lib::LittleEndian2Int(substr($raw_data, $offset, 4));
    75         $offset += 4;
    76 
    77         $getid3->info['la']['raw']['format'] = getid3_lib::LittleEndian2Int(substr($raw_data, $offset, 2));
    78         $offset += 2;
    79        
    80         getid3_lib::ReadSequence('LittleEndian2Int', $getid3->info['la'], $raw_data, $offset,
    81             array (
    82                 'channels'         => 2,
    83                 'sample_rate'      => 4,
    84                 'bytes_per_second' => 4,
    85                 'bytes_per_sample' => 2,
    86                 'bits_per_sample'  => 2,
    87                 'samples'          => 4
    88             )
    89         );
    90         $offset += 18;
    91        
    92         $getid3->info['la']['raw']['flags'] = getid3_lib::LittleEndian2Int($raw_data{$offset++});
    93        
    94         $getid3->info['la']['flags']['seekable']             = (bool)($getid3->info['la']['raw']['flags'] & 0x01);
    95         if ($getid3->info['la']['version'] >= 0.4) {
    96             $getid3->info['la']['flags']['high_compression'] = (bool)($getid3->info['la']['raw']['flags'] & 0x02);
    97         }
    98 
    99         $getid3->info['la']['original_crc'] = getid3_lib::LittleEndian2Int(substr($raw_data, $offset, 4));
    100         $offset += 4;
    101 
    102         // mikeØbevin*de
    103         // Basically, the blocksize/seekevery are 61440/19 in La0.4 and 73728/16
    104         // in earlier versions. A seekpoint is added every blocksize * seekevery
    105         // samples, so 4 * int(totalSamples / (blockSize * seekEvery)) should
    106         // give the number of bytes used for the seekpoints. Of course, if seeking
    107         // is disabled, there are no seekpoints stored.
    108        
    109         if ($getid3->info['la']['version'] >= 0.4) {
    110             $getid3->info['la']['blocksize'] = 61440;
    111             $getid3->info['la']['seekevery'] = 19;
    112         } else {
    113             $getid3->info['la']['blocksize'] = 73728;
    114             $getid3->info['la']['seekevery'] = 16;
    115         }
    116 
    117         $getid3->info['la']['seekpoint_count'] = 0;
    118         if ($getid3->info['la']['flags']['seekable']) {
    119             $getid3->info['la']['seekpoint_count'] = floor($getid3->info['la']['samples'] / ($getid3->info['la']['blocksize'] * $getid3->info['la']['seekevery']));
    120 
    121             for ($i = 0; $i < $getid3->info['la']['seekpoint_count']; $i++) {
    122                 $getid3->info['la']['seekpoints'][] = getid3_lib::LittleEndian2Int(substr($raw_data, $offset, 4));
    123                 $offset += 4;
    124             }
    125         }
    126 
    127         if ($getid3->info['la']['version'] >= 0.3) {
    128 
    129             // Following the main header information, the program outputs all of the
    130             // seekpoints. Following these is what I called the 'footer start',
    131             // i.e. the position immediately after the La audio data is finished.
    132        
    133             $getid3->info['la']['footerstart'] = getid3_lib::LittleEndian2Int(substr($raw_data, $offset, 4));
    134             $offset += 4;
    135 
    136             if ($getid3->info['la']['footerstart'] > $getid3->info['filesize']) {
    137                 $getid3->warning('FooterStart value points to offset '.$getid3->info['la']['footerstart'].' which is beyond end-of-file ('.$getid3->info['filesize'].')');
    138                 $getid3->info['la']['footerstart'] = $getid3->info['filesize'];
    139             }
    140 
    141         } else {
    142 
    143             // La v0.2 didn't have FooterStart value
    144             $getid3->info['la']['footerstart'] = $getid3->info['avdataend'];
    145 
    146         }
    147 
    148         if ($getid3->info['la']['footerstart'] < $getid3->info['avdataend']) {
    149        
    150             // Create riff header
    151             $riff_data = 'WAVE';
    152             if ($getid3->info['la']['version'] == 0.2) {
    153                 $riff_data .= substr($raw_data, 12, 24);
    154             } else {
    155                 $riff_data .= substr($raw_data, 16, 24);
    156             }
    157             if ($getid3->info['la']['footerstart'] < $getid3->info['avdataend']) {
    158                 fseek($getid3->fp, $getid3->info['la']['footerstart'], SEEK_SET);
    159                 $riff_data .= fread($getid3->fp, $getid3->info['avdataend'] - $getid3->info['la']['footerstart']);
    160             }
    161             $riff_data = 'RIFF'.getid3_lib::LittleEndian2String(strlen($riff_data), 4, false).$riff_data;
    162            
    163             // Clone getid3 - messing with offsets - better safe than sorry
    164             $clone = clone $getid3;
    165            
    166             // Analyze clone by string
    167             $riff = new getid3_riff($clone);
    168             $riff->AnalyzeString($riff_data);
    169            
    170             // Import from clone and destroy
    171             $getid3->info['riff']   = $clone->info['riff'];
    172             $getid3->warnings($clone->warnings());
    173             unset($clone);
    174         }
    175 
    176         // $getid3->info['avdataoffset'] should be zero to begin with, but just in case it's not, include the addition anyway
    177         $getid3->info['avdataend']    = $getid3->info['avdataoffset'] + $getid3->info['la']['footerstart'];
    178         $getid3->info['avdataoffset'] = $getid3->info['avdataoffset'] + $offset;
    179 
    180         $getid3->info['la']['compression_ratio']  = (float)(($getid3->info['avdataend'] - $getid3->info['avdataoffset']) / $getid3->info['la']['uncompressed_size']);
    181         $getid3->info['playtime_seconds']         = (float)($getid3->info['la']['samples'] / $getid3->info['la']['sample_rate']) / $getid3->info['la']['channels'];
    182 
    183         $getid3->info['audio']['bitrate']         = ($getid3->info['avdataend'] - $getid3->info['avdataoffset']) * 8 / $getid3->info['playtime_seconds'];
    184         $getid3->info['audio']['bits_per_sample'] = $getid3->info['la']['bits_per_sample'];
    185 
    186         $getid3->info['audio']['channels']        = $getid3->info['la']['channels'];
    187         $getid3->info['audio']['sample_rate']     = (int)$getid3->info['la']['sample_rate'];
    188         $getid3->info['audio']['encoder']         = 'LA v'.$getid3->info['la']['version'];
    189 
    190         return true;
    191     }
     21        function getid3_la(&$fd, &$ThisFileInfo) {
     22                $offset = 0;
     23                fseek($fd, $ThisFileInfo['avdataoffset'], SEEK_SET);
     24                $rawdata = fread($fd, GETID3_FREAD_BUFFER_SIZE);
     25
     26                switch (substr($rawdata, $offset, 4)) {
     27                        case 'LA02':
     28                        case 'LA03':
     29                        case 'LA04':
     30                                $ThisFileInfo['fileformat']          = 'la';
     31                                $ThisFileInfo['audio']['dataformat'] = 'la';
     32                                $ThisFileInfo['audio']['lossless']   = true;
     33
     34                                $ThisFileInfo['la']['version_major'] = (int) substr($rawdata, $offset + 2, 1);
     35                                $ThisFileInfo['la']['version_minor'] = (int) substr($rawdata, $offset + 3, 1);
     36                                $ThisFileInfo['la']['version']       = (float) $ThisFileInfo['la']['version_major'] + ($ThisFileInfo['la']['version_minor'] / 10);
     37                                $offset += 4;
     38
     39                                $ThisFileInfo['la']['uncompressed_size'] = getid3_lib::LittleEndian2Int(substr($rawdata, $offset, 4));
     40                                $offset += 4;
     41                                if ($ThisFileInfo['la']['uncompressed_size'] == 0) {
     42                                        $ThisFileInfo['error'][] = 'Corrupt LA file: uncompressed_size == zero';
     43                                        return false;
     44                                }
     45
     46                                $WAVEchunk = substr($rawdata, $offset, 4);
     47                                if ($WAVEchunk !== 'WAVE') {
     48                                        $ThisFileInfo['error'][] = 'Expected "WAVE" ('.getid3_lib::PrintHexBytes('WAVE').') at offset '.$offset.', found "'.$WAVEchunk.'" ('.getid3_lib::PrintHexBytes($WAVEchunk).') instead.';
     49                                        return false;
     50                                }
     51                                $offset += 4;
     52
     53                                $ThisFileInfo['la']['fmt_size'] = 24;
     54                                if ($ThisFileInfo['la']['version'] >= 0.3) {
     55
     56                                        $ThisFileInfo['la']['fmt_size']    = getid3_lib::LittleEndian2Int(substr($rawdata, $offset, 4));
     57                                        $ThisFileInfo['la']['header_size'] = 49 + $ThisFileInfo['la']['fmt_size'] - 24;
     58                                        $offset += 4;
     59
     60                                } else {
     61
     62                                        // version 0.2 didn't support additional data blocks
     63                                        $ThisFileInfo['la']['header_size'] = 41;
     64
     65                                }
     66
     67                                $fmt_chunk = substr($rawdata, $offset, 4);
     68                                if ($fmt_chunk !== 'fmt ') {
     69                                        $ThisFileInfo['error'][] = 'Expected "fmt " ('.getid3_lib::PrintHexBytes('fmt ').') at offset '.$offset.', found "'.$fmt_chunk.'" ('.getid3_lib::PrintHexBytes($fmt_chunk).') instead.';
     70                                        return false;
     71                                }
     72                                $offset += 4;
     73                                $fmt_size = getid3_lib::LittleEndian2Int(substr($rawdata, $offset, 4));
     74                                $offset += 4;
     75
     76                                $ThisFileInfo['la']['raw']['format']  = getid3_lib::LittleEndian2Int(substr($rawdata, $offset, 2));
     77                                $offset += 2;
     78
     79                                $ThisFileInfo['la']['channels']       = getid3_lib::LittleEndian2Int(substr($rawdata, $offset, 2));
     80                                $offset += 2;
     81                                if ($ThisFileInfo['la']['channels'] == 0) {
     82                                        $ThisFileInfo['error'][] = 'Corrupt LA file: channels == zero';
     83                                                return false;
     84                                }
     85
     86                                $ThisFileInfo['la']['sample_rate'] = getid3_lib::LittleEndian2Int(substr($rawdata, $offset, 4));
     87                                $offset += 4;
     88                                if ($ThisFileInfo['la']['sample_rate'] == 0) {
     89                                        $ThisFileInfo['error'][] = 'Corrupt LA file: sample_rate == zero';
     90                                                return false;
     91                                }
     92
     93                                $ThisFileInfo['la']['bytes_per_second']     = getid3_lib::LittleEndian2Int(substr($rawdata, $offset, 4));
     94                                $offset += 4;
     95                                $ThisFileInfo['la']['bytes_per_sample']     = getid3_lib::LittleEndian2Int(substr($rawdata, $offset, 2));
     96                                $offset += 2;
     97                                $ThisFileInfo['la']['bits_per_sample']      = getid3_lib::LittleEndian2Int(substr($rawdata, $offset, 2));
     98                                $offset += 2;
     99
     100                                $ThisFileInfo['la']['samples']              = getid3_lib::LittleEndian2Int(substr($rawdata, $offset, 4));
     101                                $offset += 4;
     102
     103                                $ThisFileInfo['la']['raw']['flags']         = getid3_lib::LittleEndian2Int(substr($rawdata, $offset, 1));
     104                                $offset += 1;
     105                                $ThisFileInfo['la']['flags']['seekable']             = (bool) ($ThisFileInfo['la']['raw']['flags'] & 0x01);
     106                                if ($ThisFileInfo['la']['version'] >= 0.4) {
     107                                        $ThisFileInfo['la']['flags']['high_compression'] = (bool) ($ThisFileInfo['la']['raw']['flags'] & 0x02);
     108                                }
     109
     110                                $ThisFileInfo['la']['original_crc']         = getid3_lib::LittleEndian2Int(substr($rawdata, $offset, 4));
     111                                $offset += 4;
     112
     113                                // mikeØbevin*de
     114                                // Basically, the blocksize/seekevery are 61440/19 in La0.4 and 73728/16
     115                                // in earlier versions. A seekpoint is added every blocksize * seekevery
     116                                // samples, so 4 * int(totalSamples / (blockSize * seekEvery)) should
     117                                // give the number of bytes used for the seekpoints. Of course, if seeking
     118                                // is disabled, there are no seekpoints stored.
     119                                if ($ThisFileInfo['la']['version'] >= 0.4) {
     120                                        $ThisFileInfo['la']['blocksize'] = 61440;
     121                                        $ThisFileInfo['la']['seekevery'] = 19;
     122                                } else {
     123                                        $ThisFileInfo['la']['blocksize'] = 73728;
     124                                        $ThisFileInfo['la']['seekevery'] = 16;
     125                                }
     126
     127                                $ThisFileInfo['la']['seekpoint_count'] = 0;
     128                                if ($ThisFileInfo['la']['flags']['seekable']) {
     129                                        $ThisFileInfo['la']['seekpoint_count'] = floor($ThisFileInfo['la']['samples'] / ($ThisFileInfo['la']['blocksize'] * $ThisFileInfo['la']['seekevery']));
     130
     131                                        for ($i = 0; $i < $ThisFileInfo['la']['seekpoint_count']; $i++) {
     132                                                $ThisFileInfo['la']['seekpoints'][] = getid3_lib::LittleEndian2Int(substr($rawdata, $offset, 4));
     133                                                $offset += 4;
     134                                        }
     135                                }
     136
     137                                if ($ThisFileInfo['la']['version'] >= 0.3) {
     138
     139                                        // Following the main header information, the program outputs all of the
     140                                        // seekpoints. Following these is what I called the 'footer start',
     141                                        // i.e. the position immediately after the La audio data is finished.
     142                                        $ThisFileInfo['la']['footerstart'] = getid3_lib::LittleEndian2Int(substr($rawdata, $offset, 4));
     143                                        $offset += 4;
     144
     145                                        if ($ThisFileInfo['la']['footerstart'] > $ThisFileInfo['filesize']) {
     146                                                $ThisFileInfo['warning'][] = 'FooterStart value points to offset '.$ThisFileInfo['la']['footerstart'].' which is beyond end-of-file ('.$ThisFileInfo['filesize'].')';
     147                                                $ThisFileInfo['la']['footerstart'] = $ThisFileInfo['filesize'];
     148                                        }
     149
     150                                } else {
     151
     152                                        // La v0.2 didn't have FooterStart value
     153                                        $ThisFileInfo['la']['footerstart'] = $ThisFileInfo['avdataend'];
     154
     155                                }
     156
     157                                if ($ThisFileInfo['la']['footerstart'] < $ThisFileInfo['avdataend']) {
     158                                        if ($RIFFtempfilename = tempnam('*', 'id3')) {
     159                                                if ($RIFF_fp = fopen($RIFFtempfilename, 'w+b')) {
     160                                                        $RIFFdata = 'WAVE';
     161                                                        if ($ThisFileInfo['la']['version'] == 0.2) {
     162                                                                $RIFFdata .= substr($rawdata, 12, 24);
     163                                                        } else {
     164                                                                $RIFFdata .= substr($rawdata, 16, 24);
     165                                                        }
     166                                                        if ($ThisFileInfo['la']['footerstart'] < $ThisFileInfo['avdataend']) {
     167                                                                fseek($fd, $ThisFileInfo['la']['footerstart'], SEEK_SET);
     168                                                                $RIFFdata .= fread($fd, $ThisFileInfo['avdataend'] - $ThisFileInfo['la']['footerstart']);
     169                                                        }
     170                                                        $RIFFdata = 'RIFF'.getid3_lib::LittleEndian2String(strlen($RIFFdata), 4, false).$RIFFdata;
     171                                                        fwrite($RIFF_fp, $RIFFdata, strlen($RIFFdata));
     172                                                        $dummy = $ThisFileInfo;
     173                                                        $dummy['filesize']     = strlen($RIFFdata);
     174                                                        $dummy['avdataoffset'] = 0;
     175                                                        $dummy['avdataend']    = $dummy['filesize'];
     176
     177                                                        $riff = new getid3_riff($RIFF_fp, $dummy);
     178                                                        if (empty($dummy['error'])) {
     179                                                                $ThisFileInfo['riff'] = $dummy['riff'];
     180                                                        } else {
     181                                                                $ThisFileInfo['warning'][] = 'Error parsing RIFF portion of La file: '.implode($dummy['error']);
     182                                                        }
     183                                                        unset($riff);
     184                                                        unset($dummy);
     185                                                        fclose($RIFF_fp);
     186                                                }
     187                                                unlink($RIFFtempfilename);
     188                                        }
     189                                }
     190
     191                                // $ThisFileInfo['avdataoffset'] should be zero to begin with, but just in case it's not, include the addition anyway
     192                                $ThisFileInfo['avdataend']    = $ThisFileInfo['avdataoffset'] + $ThisFileInfo['la']['footerstart'];
     193                                $ThisFileInfo['avdataoffset'] = $ThisFileInfo['avdataoffset'] + $offset;
     194
     195                                //$ThisFileInfo['la']['codec']                = RIFFwFormatTagLookup($ThisFileInfo['la']['raw']['format']);
     196                                $ThisFileInfo['la']['compression_ratio']    = (float) (($ThisFileInfo['avdataend'] - $ThisFileInfo['avdataoffset']) / $ThisFileInfo['la']['uncompressed_size']);
     197                                $ThisFileInfo['playtime_seconds']           = (float) ($ThisFileInfo['la']['samples'] / $ThisFileInfo['la']['sample_rate']) / $ThisFileInfo['la']['channels'];
     198                                if ($ThisFileInfo['playtime_seconds'] == 0) {
     199                                        $ThisFileInfo['error'][] = 'Corrupt LA file: playtime_seconds == zero';
     200                                        return false;
     201                                }
     202
     203                                $ThisFileInfo['audio']['bitrate']            = ($ThisFileInfo['avdataend'] - $ThisFileInfo['avdataoffset']) * 8 / $ThisFileInfo['playtime_seconds'];
     204                                //$ThisFileInfo['audio']['codec']              = $ThisFileInfo['la']['codec'];
     205                                $ThisFileInfo['audio']['bits_per_sample']    = $ThisFileInfo['la']['bits_per_sample'];
     206                                break;
     207
     208                        default:
     209                                if (substr($rawdata, $offset, 2) == 'LA') {
     210                                        $ThisFileInfo['error'][] = 'This version of getID3() (v'.GETID3_VERSION.') doesn\'t support LA version '.substr($rawdata, $offset + 2, 1).'.'.substr($rawdata, $offset + 3, 1).' which this appears to be - check http://getid3.sourceforge.net for updates.';
     211                                } else {
     212                                        $ThisFileInfo['error'][] = 'Not a LA (Lossless-Audio) file';
     213                                }
     214                                return false;
     215                                break;
     216                }
     217
     218                $ThisFileInfo['audio']['channels']    = $ThisFileInfo['la']['channels'];
     219                $ThisFileInfo['audio']['sample_rate'] = (int) $ThisFileInfo['la']['sample_rate'];
     220                $ThisFileInfo['audio']['encoder']     = 'LA v'.$ThisFileInfo['la']['version'];
     221
     222                return true;
     223        }
    192224
    193225}
Note: See TracChangeset for help on using the changeset viewer.