File indexing completed on 2024-05-12 17:26:00

0001 <?php
0002 /////////////////////////////////////////////////////////////////
0003 /// getID3() by James Heinrich <info@getid3.org>               //
0004 //  available at http://getid3.sourceforge.net                 //
0005 //            or http://www.getid3.org                         //
0006 //          also https://github.com/JamesHeinrich/getID3       //
0007 /////////////////////////////////////////////////////////////////
0008 // See readme.txt for more details                             //
0009 /////////////////////////////////////////////////////////////////
0010 //                                                             //
0011 // module.audio.tta.php                                        //
0012 // module for analyzing TTA Audio files                        //
0013 // dependencies: NONE                                          //
0014 //                                                            ///
0015 /////////////////////////////////////////////////////////////////
0016 
0017 
0018 class getid3_tta extends getid3_handler
0019 {
0020 
0021   public function Analyze() {
0022     $info = &$this->getid3->info;
0023 
0024     $info['fileformat']            = 'tta';
0025     $info['audio']['dataformat']   = 'tta';
0026     $info['audio']['lossless']     = true;
0027     $info['audio']['bitrate_mode'] = 'vbr';
0028 
0029     $this->fseek($info['avdataoffset']);
0030     $ttaheader = $this->fread(26);
0031 
0032     $info['tta']['magic'] = substr($ttaheader, 0, 3);
0033     $magic = 'TTA';
0034     if ($info['tta']['magic'] != $magic) {
0035       $info['error'][] = 'Expecting "'.getid3_lib::PrintHexBytes($magic).'" at offset '.$info['avdataoffset'].', found "'.getid3_lib::PrintHexBytes($info['tta']['magic']).'"';
0036       unset($info['fileformat']);
0037       unset($info['audio']);
0038       unset($info['tta']);
0039       return false;
0040     }
0041 
0042     switch ($ttaheader{3}) {
0043       case "\x01": // TTA v1.x
0044       case "\x02": // TTA v1.x
0045       case "\x03": // TTA v1.x
0046         // "It was the demo-version of the TTA encoder. There is no released format with such header. TTA encoder v1 is not supported about a year."
0047         $info['tta']['major_version'] = 1;
0048         $info['avdataoffset'] += 16;
0049 
0050         $info['tta']['compression_level']   = ord($ttaheader{3});
0051         $info['tta']['channels']            = getid3_lib::LittleEndian2Int(substr($ttaheader,  4,  2));
0052         $info['tta']['bits_per_sample']     = getid3_lib::LittleEndian2Int(substr($ttaheader,  6,  2));
0053         $info['tta']['sample_rate']         = getid3_lib::LittleEndian2Int(substr($ttaheader,  8,  4));
0054         $info['tta']['samples_per_channel'] = getid3_lib::LittleEndian2Int(substr($ttaheader, 12,  4));
0055 
0056         $info['audio']['encoder_options']   = '-e'.$info['tta']['compression_level'];
0057         $info['playtime_seconds']           = $info['tta']['samples_per_channel'] / $info['tta']['sample_rate'];
0058         break;
0059 
0060       case '2': // TTA v2.x
0061         // "I have hurried to release the TTA 2.0 encoder. Format documentation is removed from our site. This format still in development. Please wait the TTA2 format, encoder v4."
0062         $info['tta']['major_version'] = 2;
0063         $info['avdataoffset'] += 20;
0064 
0065         $info['tta']['compression_level']   = getid3_lib::LittleEndian2Int(substr($ttaheader,  4,  2));
0066         $info['tta']['audio_format']        = getid3_lib::LittleEndian2Int(substr($ttaheader,  6,  2));
0067         $info['tta']['channels']            = getid3_lib::LittleEndian2Int(substr($ttaheader,  8,  2));
0068         $info['tta']['bits_per_sample']     = getid3_lib::LittleEndian2Int(substr($ttaheader, 10,  2));
0069         $info['tta']['sample_rate']         = getid3_lib::LittleEndian2Int(substr($ttaheader, 12,  4));
0070         $info['tta']['data_length']         = getid3_lib::LittleEndian2Int(substr($ttaheader, 16,  4));
0071 
0072         $info['audio']['encoder_options']   = '-e'.$info['tta']['compression_level'];
0073         $info['playtime_seconds']           = $info['tta']['data_length'] / $info['tta']['sample_rate'];
0074         break;
0075 
0076       case '1': // TTA v3.x
0077         // "This is a first stable release of the TTA format. It will be supported by the encoders v3 or higher."
0078         $info['tta']['major_version'] = 3;
0079         $info['avdataoffset'] += 26;
0080 
0081         $info['tta']['audio_format']        = getid3_lib::LittleEndian2Int(substr($ttaheader,  4,  2)); // getid3_riff::wFormatTagLookup()
0082         $info['tta']['channels']            = getid3_lib::LittleEndian2Int(substr($ttaheader,  6,  2));
0083         $info['tta']['bits_per_sample']     = getid3_lib::LittleEndian2Int(substr($ttaheader,  8,  2));
0084         $info['tta']['sample_rate']         = getid3_lib::LittleEndian2Int(substr($ttaheader, 10,  4));
0085         $info['tta']['data_length']         = getid3_lib::LittleEndian2Int(substr($ttaheader, 14,  4));
0086         $info['tta']['crc32_footer']        =                              substr($ttaheader, 18,  4);
0087         $info['tta']['seek_point']          = getid3_lib::LittleEndian2Int(substr($ttaheader, 22,  4));
0088 
0089         $info['playtime_seconds']           = $info['tta']['data_length'] / $info['tta']['sample_rate'];
0090         break;
0091 
0092       default:
0093         $info['error'][] = 'This version of getID3() ['.$this->getid3->version().'] only knows how to handle TTA v1 and v2 - it may not work correctly with this file which appears to be TTA v'.$ttaheader{3};
0094         return false;
0095         break;
0096     }
0097 
0098     $info['audio']['encoder']         = 'TTA v'.$info['tta']['major_version'];
0099     $info['audio']['bits_per_sample'] = $info['tta']['bits_per_sample'];
0100     $info['audio']['sample_rate']     = $info['tta']['sample_rate'];
0101     $info['audio']['channels']        = $info['tta']['channels'];
0102     $info['audio']['bitrate']         = (($info['avdataend'] - $info['avdataoffset']) * 8) / $info['playtime_seconds'];
0103 
0104     return true;
0105   }
0106 
0107 }