ILIAS  release_5-2 Revision v5.2.25-18-g3f80b828510
Shorten.php
Go to the documentation of this file.
1 <?php
2 
3 namespace GetId3\Module\Audio;
4 
9 
12 // available at http://getid3.sourceforge.net //
13 // or http://www.getid3.org //
15 // See readme.txt for more details //
17 // //
18 // module.audio.shorten.php //
19 // module for analyzing Shorten Audio files //
20 // dependencies: NONE //
21 // ///
23 
31 class Shorten extends BaseHandler
32 {
33 
39  public function analyze()
40  {
41  $info = &$this->getid3->info;
42 
43  fseek($this->getid3->fp, $info['avdataoffset'], SEEK_SET);
44 
45  $ShortenHeader = fread($this->getid3->fp, 8);
46  $magic = 'ajkg';
47  if (substr($ShortenHeader, 0, 4) != $magic) {
48  $info['error'][] = 'Expecting "'.Helper::PrintHexBytes($magic).'" at offset '.$info['avdataoffset'].', found "'.Helper::PrintHexBytes(substr($ShortenHeader, 0, 4)).'"';
49 
50  return false;
51  }
52  $info['fileformat'] = 'shn';
53  $info['audio']['dataformat'] = 'shn';
54  $info['audio']['lossless'] = true;
55  $info['audio']['bitrate_mode'] = 'vbr';
56 
57  $info['shn']['version'] = Helper::LittleEndian2Int(substr($ShortenHeader, 4, 1));
58 
59  fseek($this->getid3->fp, $info['avdataend'] - 12, SEEK_SET);
60  $SeekTableSignatureTest = fread($this->getid3->fp, 12);
61  $info['shn']['seektable']['present'] = (bool) (substr($SeekTableSignatureTest, 4, 8) == 'SHNAMPSK');
62  if ($info['shn']['seektable']['present']) {
63  $info['shn']['seektable']['length'] = Helper::LittleEndian2Int(substr($SeekTableSignatureTest, 0, 4));
64  $info['shn']['seektable']['offset'] = $info['avdataend'] - $info['shn']['seektable']['length'];
65  fseek($this->getid3->fp, $info['shn']['seektable']['offset'], SEEK_SET);
66  $SeekTableMagic = fread($this->getid3->fp, 4);
67  $magic = 'SEEK';
68  if ($SeekTableMagic != $magic) {
69 
70  $info['error'][] = 'Expecting "'.Helper::PrintHexBytes($magic).'" at offset '.$info['shn']['seektable']['offset'].', found "'.Helper::PrintHexBytes($SeekTableMagic).'"';
71 
72  return false;
73 
74  } else {
75 
76  // typedef struct tag_TSeekEntry
77  // {
78  // unsigned long SampleNumber;
79  // unsigned long SHNFileByteOffset;
80  // unsigned long SHNLastBufferReadPosition;
81  // unsigned short SHNByteGet;
82  // unsigned short SHNBufferOffset;
83  // unsigned short SHNFileBitOffset;
84  // unsigned long SHNGBuffer;
85  // unsigned short SHNBitShift;
86  // long CBuf0[3];
87  // long CBuf1[3];
88  // long Offset0[4];
89  // long Offset1[4];
90  // }TSeekEntry;
91 
92  $SeekTableData = fread($this->getid3->fp, $info['shn']['seektable']['length'] - 16);
93  $info['shn']['seektable']['entry_count'] = floor(strlen($SeekTableData) / 80);
94  //$info['shn']['seektable']['entries'] = array();
95  //$SeekTableOffset = 0;
96  //for ($i = 0; $i < $info['shn']['seektable']['entry_count']; $i++) {
97  // $SeekTableEntry['sample_number'] = GetId3_lib::LittleEndian2Int(substr($SeekTableData, $SeekTableOffset, 4));
98  // $SeekTableOffset += 4;
99  // $SeekTableEntry['shn_file_byte_offset'] = GetId3_lib::LittleEndian2Int(substr($SeekTableData, $SeekTableOffset, 4));
100  // $SeekTableOffset += 4;
101  // $SeekTableEntry['shn_last_buffer_read_position'] = GetId3_lib::LittleEndian2Int(substr($SeekTableData, $SeekTableOffset, 4));
102  // $SeekTableOffset += 4;
103  // $SeekTableEntry['shn_byte_get'] = GetId3_lib::LittleEndian2Int(substr($SeekTableData, $SeekTableOffset, 2));
104  // $SeekTableOffset += 2;
105  // $SeekTableEntry['shn_buffer_offset'] = GetId3_lib::LittleEndian2Int(substr($SeekTableData, $SeekTableOffset, 2));
106  // $SeekTableOffset += 2;
107  // $SeekTableEntry['shn_file_bit_offset'] = GetId3_lib::LittleEndian2Int(substr($SeekTableData, $SeekTableOffset, 2));
108  // $SeekTableOffset += 2;
109  // $SeekTableEntry['shn_gbuffer'] = GetId3_lib::LittleEndian2Int(substr($SeekTableData, $SeekTableOffset, 4));
110  // $SeekTableOffset += 4;
111  // $SeekTableEntry['shn_bit_shift'] = GetId3_lib::LittleEndian2Int(substr($SeekTableData, $SeekTableOffset, 2));
112  // $SeekTableOffset += 2;
113  // for ($j = 0; $j < 3; $j++) {
114  // $SeekTableEntry['cbuf0'][$j] = GetId3_lib::LittleEndian2Int(substr($SeekTableData, $SeekTableOffset, 4));
115  // $SeekTableOffset += 4;
116  // }
117  // for ($j = 0; $j < 3; $j++) {
118  // $SeekTableEntry['cbuf1'][$j] = GetId3_lib::LittleEndian2Int(substr($SeekTableData, $SeekTableOffset, 4));
119  // $SeekTableOffset += 4;
120  // }
121  // for ($j = 0; $j < 4; $j++) {
122  // $SeekTableEntry['offset0'][$j] = GetId3_lib::LittleEndian2Int(substr($SeekTableData, $SeekTableOffset, 4));
123  // $SeekTableOffset += 4;
124  // }
125  // for ($j = 0; $j < 4; $j++) {
126  // $SeekTableEntry['offset1'][$j] = GetId3_lib::LittleEndian2Int(substr($SeekTableData, $SeekTableOffset, 4));
127  // $SeekTableOffset += 4;
128  // }
129  //
130  // $info['shn']['seektable']['entries'][] = $SeekTableEntry;
131  //}
132 
133  }
134 
135  }
136 
137  if (preg_match('#(1|ON)#i', ini_get('safe_mode'))) {
138  $info['error'][] = 'PHP running in Safe Mode - backtick operator not available, cannot run shntool to analyze Shorten files';
139 
140  return false;
141  }
142 
144 
145  $RequiredFiles = array('shorten.exe', 'cygwin1.dll', 'head.exe');
146  foreach ($RequiredFiles as $required_file) {
147  if (!is_readable(GetId3Core::getHelperAppsDir().$required_file)) {
148  $info['error'][] = GetId3Core::getHelperAppsDir().$required_file.' does not exist';
149 
150  return false;
151  }
152  }
153  $commandline = GetId3Core::getHelperAppsDir().'shorten.exe -x "'.$info['filenamepath'].'" - | '.GetId3Core::getHelperAppsDir().'head.exe -c 64';
154  $commandline = str_replace('/', '\\', $commandline);
155 
156  } else {
157 
158  static $shorten_present;
159  if (!isset($shorten_present)) {
160  $shorten_present = file_exists('/usr/local/bin/shorten') || `which shorten`;
161  }
162  if (!$shorten_present) {
163  $info['error'][] = 'shorten binary was not found in path or /usr/local/bin';
164 
165  return false;
166  }
167  $commandline = (file_exists('/usr/local/bin/shorten') ? '/usr/local/bin/' : '' ) . 'shorten -x '.escapeshellarg($info['filenamepath']).' - | head -c 64';
168 
169  }
170 
171  $output = `$commandline`;
172 
173  if (!empty($output) && (substr($output, 12, 4) == 'fmt ')) {
174 
175  $fmt_size = Helper::LittleEndian2Int(substr($output, 16, 4));
176  $DecodedWAVFORMATEX = Riff::RIFFparseWAVEFORMATex(substr($output, 20, $fmt_size));
177  $info['audio']['channels'] = $DecodedWAVFORMATEX['channels'];
178  $info['audio']['bits_per_sample'] = $DecodedWAVFORMATEX['bits_per_sample'];
179  $info['audio']['sample_rate'] = $DecodedWAVFORMATEX['sample_rate'];
180 
181  if (substr($output, 20 + $fmt_size, 4) == 'data') {
182 
183  $info['playtime_seconds'] = Helper::LittleEndian2Int(substr($output, 20 + 4 + $fmt_size, 4)) / $DecodedWAVFORMATEX['raw']['nAvgBytesPerSec'];
184 
185  } else {
186 
187  $info['error'][] = 'shorten failed to decode DATA chunk to expected location, cannot determine playtime';
188 
189  return false;
190 
191  }
192 
193  $info['audio']['bitrate'] = (($info['avdataend'] - $info['avdataoffset']) / $info['playtime_seconds']) * 8;
194 
195  } else {
196 
197  $info['error'][] = 'shorten failed to decode file to WAV for parsing';
198 
199  return false;
200 
201  }
202 
203  return true;
204  }
205 }
analyze()
type $shorten_present
Definition: Shorten.php:39
static PrintHexBytes($string, $hex=true, $spaces=true, $htmlencoding='UTF-8')
Definition: Helper.php:36
GetId3() by James Heinrich info@getid3.org //.
Definition: BaseHandler.php:25
GetId3() by James Heinrich info@getid3.org //.
Definition: Shorten.php:31
static RIFFparseWAVEFORMATex($WaveFormatExData)
Definition: Riff.php:1707
fseek($bytes, $whence=SEEK_SET)
if(!is_dir( $entity_dir)) exit("Fatal Error ([A-Za-z0-9]+)\+" &#(? foreach( $entity_files as $file) $output
$info
Definition: example_052.php:80
static environmentIsWindows()
Create styles array
The data for the language used.
static LittleEndian2Int($byteword, $signed=false)
Definition: Helper.php:413
static getHelperAppsDir()
Definition: GetId3Core.php:186