Annotation of /trunk/lib/getid3/module.audio.vqf.php
Parent Directory
|
Revision Log
Revision 2 - (view) (download)
| 1 : | andphe | 2 | <?php |
| 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.vqf.php // | ||
| 11 : | // module for analyzing VQF audio files // | ||
| 12 : | // dependencies: NONE // | ||
| 13 : | // /// | ||
| 14 : | ///////////////////////////////////////////////////////////////// | ||
| 15 : | // MOS Intruder Alerts | ||
| 16 : | defined( '_VALID_MOS' ) or die( 'Direct Access to this location is not allowed.' ); | ||
| 17 : | |||
| 18 : | class getid3_vqf | ||
| 19 : | { | ||
| 20 : | function getid3_vqf(&$fd, &$ThisFileInfo) { | ||
| 21 : | // based loosely on code from TTwinVQ by Jurgen Faul <jfaul�gmx*de> | ||
| 22 : | // http://jfaul.de/atl or http://j-faul.virtualave.net/atl/atl.html | ||
| 23 : | |||
| 24 : | $ThisFileInfo['fileformat'] = 'vqf'; | ||
| 25 : | $ThisFileInfo['audio']['dataformat'] = 'vqf'; | ||
| 26 : | $ThisFileInfo['audio']['bitrate_mode'] = 'cbr'; | ||
| 27 : | $ThisFileInfo['audio']['lossless'] = false; | ||
| 28 : | |||
| 29 : | // shortcut | ||
| 30 : | $ThisFileInfo['vqf']['raw'] = array(); | ||
| 31 : | $thisfile_vqf = &$ThisFileInfo['vqf']; | ||
| 32 : | $thisfile_vqf_raw = &$thisfile_vqf['raw']; | ||
| 33 : | |||
| 34 : | fseek($fd, $ThisFileInfo['avdataoffset'], SEEK_SET); | ||
| 35 : | $VQFheaderData = fread($fd, 16); | ||
| 36 : | |||
| 37 : | $offset = 0; | ||
| 38 : | $thisfile_vqf_raw['header_tag'] = substr($VQFheaderData, $offset, 4); | ||
| 39 : | if ($thisfile_vqf_raw['header_tag'] != 'TWIN') { | ||
| 40 : | $ThisFileInfo['error'][] = 'Expecting "TWIN" at offset '.$ThisFileInfo['avdataoffset'].', found "'.$thisfile_vqf_raw['header_tag'].'"'; | ||
| 41 : | unset($ThisFileInfo['vqf']); | ||
| 42 : | unset($ThisFileInfo['fileformat']); | ||
| 43 : | return false; | ||
| 44 : | } | ||
| 45 : | $offset += 4; | ||
| 46 : | $thisfile_vqf_raw['version'] = substr($VQFheaderData, $offset, 8); | ||
| 47 : | $offset += 8; | ||
| 48 : | $thisfile_vqf_raw['size'] = getid3_lib::BigEndian2Int(substr($VQFheaderData, $offset, 4)); | ||
| 49 : | $offset += 4; | ||
| 50 : | |||
| 51 : | while (ftell($fd) < $ThisFileInfo['avdataend']) { | ||
| 52 : | |||
| 53 : | $ChunkBaseOffset = ftell($fd); | ||
| 54 : | $chunkoffset = 0; | ||
| 55 : | $ChunkData = fread($fd, 8); | ||
| 56 : | $ChunkName = substr($ChunkData, $chunkoffset, 4); | ||
| 57 : | if ($ChunkName == 'DATA') { | ||
| 58 : | $ThisFileInfo['avdataoffset'] = $ChunkBaseOffset; | ||
| 59 : | break; | ||
| 60 : | } | ||
| 61 : | $chunkoffset += 4; | ||
| 62 : | $ChunkSize = getid3_lib::BigEndian2Int(substr($ChunkData, $chunkoffset, 4)); | ||
| 63 : | $chunkoffset += 4; | ||
| 64 : | if ($ChunkSize > ($ThisFileInfo['avdataend'] - ftell($fd))) { | ||
| 65 : | $ThisFileInfo['error'][] = 'Invalid chunk size ('.$ChunkSize.') for chunk "'.$ChunkName.'" at offset '.$ChunkBaseOffset; | ||
| 66 : | break; | ||
| 67 : | } | ||
| 68 : | if ($ChunkSize > 0) { | ||
| 69 : | $ChunkData .= fread($fd, $ChunkSize); | ||
| 70 : | } | ||
| 71 : | |||
| 72 : | switch ($ChunkName) { | ||
| 73 : | case 'COMM': | ||
| 74 : | // shortcut | ||
| 75 : | $thisfile_vqf['COMM'] = array(); | ||
| 76 : | $thisfile_vqf_COMM = &$thisfile_vqf['COMM']; | ||
| 77 : | |||
| 78 : | $thisfile_vqf_COMM['channel_mode'] = getid3_lib::BigEndian2Int(substr($ChunkData, $chunkoffset, 4)); | ||
| 79 : | $chunkoffset += 4; | ||
| 80 : | $thisfile_vqf_COMM['bitrate'] = getid3_lib::BigEndian2Int(substr($ChunkData, $chunkoffset, 4)); | ||
| 81 : | $chunkoffset += 4; | ||
| 82 : | $thisfile_vqf_COMM['sample_rate'] = getid3_lib::BigEndian2Int(substr($ChunkData, $chunkoffset, 4)); | ||
| 83 : | $chunkoffset += 4; | ||
| 84 : | $thisfile_vqf_COMM['security_level'] = getid3_lib::BigEndian2Int(substr($ChunkData, $chunkoffset, 4)); | ||
| 85 : | $chunkoffset += 4; | ||
| 86 : | |||
| 87 : | $ThisFileInfo['audio']['channels'] = $thisfile_vqf_COMM['channel_mode'] + 1; | ||
| 88 : | $ThisFileInfo['audio']['sample_rate'] = $this->VQFchannelFrequencyLookup($thisfile_vqf_COMM['sample_rate']); | ||
| 89 : | $ThisFileInfo['audio']['bitrate'] = $thisfile_vqf_COMM['bitrate'] * 1000; | ||
| 90 : | $ThisFileInfo['audio']['encoder_options'] = 'CBR' . ceil($ThisFileInfo['audio']['bitrate']/1000); | ||
| 91 : | |||
| 92 : | if ($ThisFileInfo['audio']['bitrate'] == 0) { | ||
| 93 : | $ThisFileInfo['error'][] = 'Corrupt VQF file: bitrate_audio == zero'; | ||
| 94 : | return false; | ||
| 95 : | } | ||
| 96 : | break; | ||
| 97 : | |||
| 98 : | case 'NAME': | ||
| 99 : | case 'AUTH': | ||
| 100 : | case '(c) ': | ||
| 101 : | case 'FILE': | ||
| 102 : | case 'COMT': | ||
| 103 : | case 'ALBM': | ||
| 104 : | $thisfile_vqf['comments'][$this->VQFcommentNiceNameLookup($ChunkName)][] = trim(substr($ChunkData, 8)); | ||
| 105 : | break; | ||
| 106 : | |||
| 107 : | case 'DSIZ': | ||
| 108 : | $thisfile_vqf['DSIZ'] = getid3_lib::BigEndian2Int(substr($ChunkData, 8, 4)); | ||
| 109 : | break; | ||
| 110 : | |||
| 111 : | default: | ||
| 112 : | $ThisFileInfo['warning'][] = 'Unhandled chunk type "'.$ChunkName.'" at offset '.$ChunkBaseOffset; | ||
| 113 : | break; | ||
| 114 : | } | ||
| 115 : | } | ||
| 116 : | |||
| 117 : | $ThisFileInfo['playtime_seconds'] = (($ThisFileInfo['avdataend'] - $ThisFileInfo['avdataoffset']) * 8) / $ThisFileInfo['audio']['bitrate']; | ||
| 118 : | |||
| 119 : | if (isset($thisfile_vqf['DSIZ']) && (($thisfile_vqf['DSIZ'] != ($ThisFileInfo['avdataend'] - $ThisFileInfo['avdataoffset'] - strlen('DATA'))))) { | ||
| 120 : | switch ($thisfile_vqf['DSIZ']) { | ||
| 121 : | case 0: | ||
| 122 : | case 1: | ||
| 123 : | $ThisFileInfo['warning'][] = 'Invalid DSIZ value "'.$thisfile_vqf['DSIZ'].'". This is known to happen with VQF files encoded by Ahead Nero, and seems to be its way of saying this is TwinVQF v'.($thisfile_vqf['DSIZ'] + 1).'.0'; | ||
| 124 : | $ThisFileInfo['audio']['encoder'] = 'Ahead Nero'; | ||
| 125 : | break; | ||
| 126 : | |||
| 127 : | default: | ||
| 128 : | $ThisFileInfo['warning'][] = 'Probable corrupted file - should be '.$thisfile_vqf['DSIZ'].' bytes, actually '.($ThisFileInfo['avdataend'] - $ThisFileInfo['avdataoffset'] - strlen('DATA')); | ||
| 129 : | break; | ||
| 130 : | } | ||
| 131 : | } | ||
| 132 : | |||
| 133 : | return true; | ||
| 134 : | } | ||
| 135 : | |||
| 136 : | function VQFchannelFrequencyLookup($frequencyid) { | ||
| 137 : | static $VQFchannelFrequencyLookup = array( | ||
| 138 : | 11 => 11025, | ||
| 139 : | 22 => 22050, | ||
| 140 : | 44 => 44100 | ||
| 141 : | ); | ||
| 142 : | return (isset($VQFchannelFrequencyLookup[$frequencyid]) ? $VQFchannelFrequencyLookup[$frequencyid] : $frequencyid * 1000); | ||
| 143 : | } | ||
| 144 : | |||
| 145 : | function VQFcommentNiceNameLookup($shortname) { | ||
| 146 : | static $VQFcommentNiceNameLookup = array( | ||
| 147 : | 'NAME' => 'title', | ||
| 148 : | 'AUTH' => 'artist', | ||
| 149 : | '(c) ' => 'copyright', | ||
| 150 : | 'FILE' => 'filename', | ||
| 151 : | 'COMT' => 'comment', | ||
| 152 : | 'ALBM' => 'album' | ||
| 153 : | ); | ||
| 154 : | return (isset($VQFcommentNiceNameLookup[$shortname]) ? $VQFcommentNiceNameLookup[$shortname] : $shortname); | ||
| 155 : | } | ||
| 156 : | |||
| 157 : | } | ||
| 158 : | |||
| 159 : | |||
| 160 : | ?> |
| ViewVC Help | |
| Powered by ViewVC 1.0.0 |
Web Hosting provided by Network Redux.

