annotate e2gallerypro/e2upload/Backend/Assets/getid3/module.audio.bonk.php @ 8:1b77e8657088 judyates

[svn r9] saving for transference to cd
author rlm
date Fri, 19 Mar 2010 07:17:36 -0400
parents 3f6b44aa6b35
children
rev   line source
rlm@3 1 <?php
rlm@3 2 // +----------------------------------------------------------------------+
rlm@3 3 // | PHP version 5 |
rlm@3 4 // +----------------------------------------------------------------------+
rlm@3 5 // | Copyright (c) 2002-2006 James Heinrich, Allan Hansen |
rlm@3 6 // +----------------------------------------------------------------------+
rlm@3 7 // | This source file is subject to version 2 of the GPL license, |
rlm@3 8 // | that is bundled with this package in the file license.txt and is |
rlm@3 9 // | available through the world-wide-web at the following url: |
rlm@3 10 // | http://www.gnu.org/copyleft/gpl.html |
rlm@3 11 // +----------------------------------------------------------------------+
rlm@3 12 // | getID3() - http://getid3.sourceforge.net or http://www.getid3.org |
rlm@3 13 // +----------------------------------------------------------------------+
rlm@3 14 // | Authors: James Heinrich <infoØgetid3*org> |
rlm@3 15 // | Allan Hansen <ahØartemis*dk> |
rlm@3 16 // +----------------------------------------------------------------------+
rlm@3 17 // | module.audio.bonk.php |
rlm@3 18 // | Module for analyzing BONK audio files |
rlm@3 19 // | dependencies: module.tag.id3v2.php (optional) |
rlm@3 20 // +----------------------------------------------------------------------+
rlm@3 21 //
rlm@3 22 // $Id: module.audio.bonk.php,v 1.3 2006/11/02 10:48:01 ah Exp $
rlm@3 23
rlm@3 24
rlm@3 25
rlm@3 26 class getid3_bonk extends getid3_handler
rlm@3 27 {
rlm@3 28
rlm@3 29 public function Analyze() {
rlm@3 30
rlm@3 31 $getid3 = $this->getid3;
rlm@3 32
rlm@3 33 $getid3->info['bonk'] = array ();
rlm@3 34 $info_bonk = &$getid3->info['bonk'];
rlm@3 35
rlm@3 36 $info_bonk['dataoffset'] = $getid3->info['avdataoffset'];
rlm@3 37 $info_bonk['dataend'] = $getid3->info['avdataend'];
rlm@3 38
rlm@3 39
rlm@3 40 // Scan-from-end method, for v0.6 and higher
rlm@3 41 fseek($getid3->fp, $info_bonk['dataend'] - 8, SEEK_SET);
rlm@3 42 $possible_bonk_tag = fread($getid3->fp, 8);
rlm@3 43 while (getid3_bonk::BonkIsValidTagName(substr($possible_bonk_tag, 4, 4), true)) {
rlm@3 44 $bonk_tag_size = getid3_lib::LittleEndian2Int(substr($possible_bonk_tag, 0, 4));
rlm@3 45 fseek($getid3->fp, 0 - $bonk_tag_size, SEEK_CUR);
rlm@3 46 $bonk_tag_offset = ftell($getid3->fp);
rlm@3 47 $tag_header_test = fread($getid3->fp, 5);
rlm@3 48 if (($tag_header_test{0} != "\x00") || (substr($possible_bonk_tag, 4, 4) != strtolower(substr($possible_bonk_tag, 4, 4)))) {
rlm@3 49 throw new getid3_exception('Expecting "Ø'.strtoupper(substr($possible_bonk_tag, 4, 4)).'" at offset '.$bonk_tag_offset.', found "'.$tag_header_test.'"');
rlm@3 50 }
rlm@3 51 $bonk_tag_name = substr($tag_header_test, 1, 4);
rlm@3 52
rlm@3 53 $info_bonk[$bonk_tag_name]['size'] = $bonk_tag_size;
rlm@3 54 $info_bonk[$bonk_tag_name]['offset'] = $bonk_tag_offset;
rlm@3 55 $this->HandleBonkTags($bonk_tag_name);
rlm@3 56
rlm@3 57 $next_tag_end_offset = $bonk_tag_offset - 8;
rlm@3 58 if ($next_tag_end_offset < $info_bonk['dataoffset']) {
rlm@3 59 if (empty($getid3->info['audio']['encoder'])) {
rlm@3 60 $getid3->info['audio']['encoder'] = 'Extended BONK v0.9+';
rlm@3 61 }
rlm@3 62 return true;
rlm@3 63 }
rlm@3 64 fseek($getid3->fp, $next_tag_end_offset, SEEK_SET);
rlm@3 65 $possible_bonk_tag = fread($getid3->fp, 8);
rlm@3 66 }
rlm@3 67
rlm@3 68 // Seek-from-beginning method for v0.4 and v0.5
rlm@3 69 if (empty($info_bonk['BONK'])) {
rlm@3 70 fseek($getid3->fp, $info_bonk['dataoffset'], SEEK_SET);
rlm@3 71 do {
rlm@3 72 $tag_header_test = fread($getid3->fp, 5);
rlm@3 73 switch ($tag_header_test) {
rlm@3 74 case "\x00".'BONK':
rlm@3 75 if (empty($getid3->info['audio']['encoder'])) {
rlm@3 76 $getid3->info['audio']['encoder'] = 'BONK v0.4';
rlm@3 77 }
rlm@3 78 break;
rlm@3 79
rlm@3 80 case "\x00".'INFO':
rlm@3 81 $getid3->info['audio']['encoder'] = 'Extended BONK v0.5';
rlm@3 82 break;
rlm@3 83
rlm@3 84 default:
rlm@3 85 break 2;
rlm@3 86 }
rlm@3 87 $bonk_tag_name = substr($tag_header_test, 1, 4);
rlm@3 88 $info_bonk[$bonk_tag_name]['size'] = $info_bonk['dataend'] - $info_bonk['dataoffset'];
rlm@3 89 $info_bonk[$bonk_tag_name]['offset'] = $info_bonk['dataoffset'];
rlm@3 90 $this->HandleBonkTags($bonk_tag_name);
rlm@3 91
rlm@3 92 } while (true);
rlm@3 93 }
rlm@3 94
rlm@3 95
rlm@3 96 // Parse META block for v0.6 - v0.8
rlm@3 97 if (!@$info_bonk['INFO'] && isset($info_bonk['META']['tags']['info'])) {
rlm@3 98 fseek($getid3->fp, $info_bonk['META']['tags']['info'], SEEK_SET);
rlm@3 99 $tag_header_test = fread($getid3->fp, 5);
rlm@3 100 if ($tag_header_test == "\x00".'INFO') {
rlm@3 101 $getid3->info['audio']['encoder'] = 'Extended BONK v0.6 - v0.8';
rlm@3 102
rlm@3 103 $bonk_tag_name = substr($tag_header_test, 1, 4);
rlm@3 104 $info_bonk[$bonk_tag_name]['size'] = $info_bonk['dataend'] - $info_bonk['dataoffset'];
rlm@3 105 $info_bonk[$bonk_tag_name]['offset'] = $info_bonk['dataoffset'];
rlm@3 106 $this->HandleBonkTags($bonk_tag_name);
rlm@3 107 }
rlm@3 108 }
rlm@3 109
rlm@3 110 if (empty($getid3->info['audio']['encoder'])) {
rlm@3 111 $getid3->info['audio']['encoder'] = 'Extended BONK v0.9+';
rlm@3 112 }
rlm@3 113 if (empty($info_bonk['BONK'])) {
rlm@3 114 unset($getid3->info['bonk']);
rlm@3 115 }
rlm@3 116 return true;
rlm@3 117
rlm@3 118 }
rlm@3 119
rlm@3 120
rlm@3 121
rlm@3 122 private function HandleBonkTags(&$bonk_tag_name) {
rlm@3 123
rlm@3 124 // Shortcut to getid3 pointer
rlm@3 125 $getid3 = $this->getid3;
rlm@3 126 $info_audio = &$getid3->info['audio'];
rlm@3 127
rlm@3 128 switch ($bonk_tag_name) {
rlm@3 129
rlm@3 130 case 'BONK':
rlm@3 131 // shortcut
rlm@3 132 $info_bonk_BONK = &$getid3->info['bonk']['BONK'];
rlm@3 133
rlm@3 134 $bonk_data = "\x00".'BONK'.fread($getid3->fp, 17);
rlm@3 135
rlm@3 136 getid3_lib::ReadSequence('LittleEndian2Int', $info_bonk_BONK, $bonk_data, 5,
rlm@3 137 array (
rlm@3 138 'version' => 1,
rlm@3 139 'number_samples' => 4,
rlm@3 140 'sample_rate' => 4,
rlm@3 141 'channels' => 1,
rlm@3 142 'lossless' => 1,
rlm@3 143 'joint_stereo' => 1,
rlm@3 144 'number_taps' => 2,
rlm@3 145 'downsampling_ratio' => 1,
rlm@3 146 'samples_per_packet' => 2
rlm@3 147 )
rlm@3 148 );
rlm@3 149
rlm@3 150 $info_bonk_BONK['lossless'] = (bool)$info_bonk_BONK['lossless'];
rlm@3 151 $info_bonk_BONK['joint_stereo'] = (bool)$info_bonk_BONK['joint_stereo'];
rlm@3 152
rlm@3 153 $getid3->info['avdataoffset'] = $info_bonk_BONK['offset'] + 5 + 17;
rlm@3 154 $getid3->info['avdataend'] = $info_bonk_BONK['offset'] + $info_bonk_BONK['size'];
rlm@3 155
rlm@3 156 $getid3->info['fileformat'] = 'bonk';
rlm@3 157 $info_audio['dataformat'] = 'bonk';
rlm@3 158 $info_audio['bitrate_mode'] = 'vbr'; // assumed
rlm@3 159 $info_audio['channels'] = $info_bonk_BONK['channels'];
rlm@3 160 $info_audio['sample_rate'] = $info_bonk_BONK['sample_rate'];
rlm@3 161 $info_audio['channelmode'] = $info_bonk_BONK['joint_stereo'] ? 'joint stereo' : 'stereo';
rlm@3 162 $info_audio['lossless'] = $info_bonk_BONK['lossless'];
rlm@3 163 $info_audio['codec'] = 'bonk';
rlm@3 164
rlm@3 165 $getid3->info['playtime_seconds'] = $info_bonk_BONK['number_samples'] / ($info_bonk_BONK['sample_rate'] * $info_bonk_BONK['channels']);
rlm@3 166 if ($getid3->info['playtime_seconds'] > 0) {
rlm@3 167 $info_audio['bitrate'] = (($getid3->info['bonk']['dataend'] - $getid3->info['bonk']['dataoffset']) * 8) / $getid3->info['playtime_seconds'];
rlm@3 168 }
rlm@3 169 break;
rlm@3 170
rlm@3 171 case 'INFO':
rlm@3 172 // shortcut
rlm@3 173 $info_bonk_INFO = &$getid3->info['bonk']['INFO'];
rlm@3 174
rlm@3 175 $info_bonk_INFO['version'] = getid3_lib::LittleEndian2Int(fread($getid3->fp, 1));
rlm@3 176 $info_bonk_INFO['entries_count'] = 0;
rlm@3 177 $next_info_data_pair = fread($getid3->fp, 5);
rlm@3 178 if (!getid3_bonk::BonkIsValidTagName(substr($next_info_data_pair, 1, 4))) {
rlm@3 179 while (!feof($getid3->fp)) {
rlm@3 180 $next_info_data_pair = fread($getid3->fp, 5);
rlm@3 181 if (getid3_bonk::BonkIsValidTagName(substr($next_info_data_pair, 1, 4))) {
rlm@3 182 fseek($getid3->fp, -5, SEEK_CUR);
rlm@3 183 break;
rlm@3 184 }
rlm@3 185 $info_bonk_INFO['entries_count']++;
rlm@3 186 }
rlm@3 187 }
rlm@3 188 break;
rlm@3 189
rlm@3 190 case 'META':
rlm@3 191 $bonk_data = "\x00".'META'.fread($getid3->fp, $getid3->info['bonk']['META']['size'] - 5);
rlm@3 192 $getid3->info['bonk']['META']['version'] = getid3_lib::LittleEndian2Int(substr($bonk_data, 5, 1));
rlm@3 193
rlm@3 194 $meta_tag_entries = floor(((strlen($bonk_data) - 8) - 6) / 8); // BonkData - xxxxmeta - ØMETA
rlm@3 195 $offset = 6;
rlm@3 196 for ($i = 0; $i < $meta_tag_entries; $i++) {
rlm@3 197 $meta_entry_tag_name = substr($bonk_data, $offset, 4);
rlm@3 198 $offset += 4;
rlm@3 199 $meta_entry_tag_offset = getid3_lib::LittleEndian2Int(substr($bonk_data, $offset, 4));
rlm@3 200 $offset += 4;
rlm@3 201 $getid3->info['bonk']['META']['tags'][$meta_entry_tag_name] = $meta_entry_tag_offset;
rlm@3 202 }
rlm@3 203 break;
rlm@3 204
rlm@3 205 case ' ID3':
rlm@3 206 $info_audio['encoder'] = 'Extended BONK v0.9+';
rlm@3 207
rlm@3 208 // ID3v2 checking is optional
rlm@3 209 if (class_exists('getid3_id3v2')) {
rlm@3 210
rlm@3 211 $id3v2 = new getid3_id3v2($getid3);
rlm@3 212 $id3v2->option_starting_offset = $getid3->info['bonk'][' ID3']['offset'] + 2;
rlm@3 213 $getid3->info['bonk'][' ID3']['valid'] = $id3v2->Analyze();
rlm@3 214 }
rlm@3 215 break;
rlm@3 216
rlm@3 217 default:
rlm@3 218 $getid3->warning('Unexpected Bonk tag "'.$bonk_tag_name.'" at offset '.$getid3->info['bonk'][$bonk_tag_name]['offset']);
rlm@3 219 break;
rlm@3 220
rlm@3 221 }
rlm@3 222 }
rlm@3 223
rlm@3 224
rlm@3 225
rlm@3 226 public static function BonkIsValidTagName($possible_bonk_tag, $ignore_case=false) {
rlm@3 227
rlm@3 228 $ignore_case = $ignore_case ? 'i' : '';
rlm@3 229 return preg_match('/^(BONK|INFO| ID3|META)$/'.$ignore_case, $possible_bonk_tag);
rlm@3 230 }
rlm@3 231
rlm@3 232 }
rlm@3 233
rlm@3 234
rlm@3 235 ?>