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.shorten.php |
|
rlm@3
|
18 // | Module for analyzing Shorten Audio files |
|
rlm@3
|
19 // | dependencies: module.audio-video.riff.php |
|
rlm@3
|
20 // +----------------------------------------------------------------------+
|
rlm@3
|
21 //
|
rlm@3
|
22 // $Id: module.audio.shorten.php,v 1.5 2006/12/03 19:28:18 ah Exp $
|
rlm@3
|
23
|
rlm@3
|
24
|
rlm@3
|
25
|
rlm@3
|
26 class getid3_shorten extends getid3_handler
|
rlm@3
|
27 {
|
rlm@3
|
28
|
rlm@3
|
29 public function __construct(getID3 $getid3) {
|
rlm@3
|
30
|
rlm@3
|
31 parent::__construct($getid3);
|
rlm@3
|
32
|
rlm@3
|
33 if ((bool)ini_get('safe_mode')) {
|
rlm@3
|
34 throw new getid3_exception('PHP running in Safe Mode - backtick operator not available, cannot analyze Shorten files.');
|
rlm@3
|
35 }
|
rlm@3
|
36
|
rlm@3
|
37 if (!`head --version`) {
|
rlm@3
|
38 throw new getid3_exception('head[.exe] binary not found in path. UNIX: typically /usr/bin. Windows: typically c:\windows\system32.');
|
rlm@3
|
39 }
|
rlm@3
|
40
|
rlm@3
|
41 if (!`shorten -l`) {
|
rlm@3
|
42 throw new getid3_exception('shorten[.exe] binary not found in path. UNIX: typically /usr/bin. Windows: typically c:\windows\system32.');
|
rlm@3
|
43 }
|
rlm@3
|
44 }
|
rlm@3
|
45
|
rlm@3
|
46
|
rlm@3
|
47 public function Analyze() {
|
rlm@3
|
48
|
rlm@3
|
49 $getid3 = $this->getid3;
|
rlm@3
|
50
|
rlm@3
|
51 $getid3->include_module('audio-video.riff');
|
rlm@3
|
52
|
rlm@3
|
53 fseek($getid3->fp, $getid3->info['avdataoffset'], SEEK_SET);
|
rlm@3
|
54
|
rlm@3
|
55 $shn_header = fread($getid3->fp, 8);
|
rlm@3
|
56
|
rlm@3
|
57 // Magic bytes: "ajkg"
|
rlm@3
|
58
|
rlm@3
|
59 $getid3->info['fileformat'] = 'shn';
|
rlm@3
|
60 $getid3->info['audio']['dataformat'] = 'shn';
|
rlm@3
|
61 $getid3->info['audio']['lossless'] = true;
|
rlm@3
|
62 $getid3->info['audio']['bitrate_mode'] = 'vbr';
|
rlm@3
|
63
|
rlm@3
|
64 $getid3->info['shn']['version'] = getid3_lib::LittleEndian2Int($shn_header{4});
|
rlm@3
|
65
|
rlm@3
|
66 fseek($getid3->fp, $getid3->info['avdataend'] - 12, SEEK_SET);
|
rlm@3
|
67
|
rlm@3
|
68 $seek_table_signature_test = fread($getid3->fp, 12);
|
rlm@3
|
69
|
rlm@3
|
70 $getid3->info['shn']['seektable']['present'] = (bool)(substr($seek_table_signature_test, 4, 8) == 'SHNAMPSK');
|
rlm@3
|
71 if ($getid3->info['shn']['seektable']['present']) {
|
rlm@3
|
72
|
rlm@3
|
73 $getid3->info['shn']['seektable']['length'] = getid3_lib::LittleEndian2Int(substr($seek_table_signature_test, 0, 4));
|
rlm@3
|
74 $getid3->info['shn']['seektable']['offset'] = $getid3->info['avdataend'] - $getid3->info['shn']['seektable']['length'];
|
rlm@3
|
75 fseek($getid3->fp, $getid3->info['shn']['seektable']['offset'], SEEK_SET);
|
rlm@3
|
76 $seek_table_magic = fread($getid3->fp, 4);
|
rlm@3
|
77
|
rlm@3
|
78 if ($seek_table_magic != 'SEEK') {
|
rlm@3
|
79
|
rlm@3
|
80 throw new getid3_exception('Expecting "SEEK" at offset '.$getid3->info['shn']['seektable']['offset'].', found "'.$seek_table_magic.'"');
|
rlm@3
|
81 }
|
rlm@3
|
82
|
rlm@3
|
83 $seek_table_data = fread($getid3->fp, $getid3->info['shn']['seektable']['length'] - 16);
|
rlm@3
|
84 $getid3->info['shn']['seektable']['entry_count'] = floor(strlen($seek_table_data) / 80);
|
rlm@3
|
85 }
|
rlm@3
|
86
|
rlm@3
|
87 $commandline = 'shorten -x '.escapeshellarg(realpath($getid3->filename)).' - | head -c 64';
|
rlm@3
|
88 $output = `$commandline`;
|
rlm@3
|
89
|
rlm@3
|
90 if (@$output && substr($output, 12, 4) == 'fmt ') {
|
rlm@3
|
91
|
rlm@3
|
92 $fmt_size = getid3_lib::LittleEndian2Int(substr($output, 16, 4));
|
rlm@3
|
93 $decoded_wav_format_ex = getid3_riff::RIFFparseWAVEFORMATex(substr($output, 20, $fmt_size));
|
rlm@3
|
94
|
rlm@3
|
95 $getid3->info['audio']['channels'] = $decoded_wav_format_ex['channels'];
|
rlm@3
|
96 $getid3->info['audio']['bits_per_sample'] = $decoded_wav_format_ex['bits_per_sample'];
|
rlm@3
|
97 $getid3->info['audio']['sample_rate'] = $decoded_wav_format_ex['sample_rate'];
|
rlm@3
|
98
|
rlm@3
|
99 if (substr($output, 20 + $fmt_size, 4) == 'data') {
|
rlm@3
|
100
|
rlm@3
|
101 $getid3->info['playtime_seconds'] = getid3_lib::LittleEndian2Int(substr($output, 20 + 4 + $fmt_size, 4)) / $decoded_wav_format_ex['raw']['nAvgBytesPerSec'];
|
rlm@3
|
102
|
rlm@3
|
103 } else {
|
rlm@3
|
104
|
rlm@3
|
105 throw new getid3_exception('shorten failed to decode DATA chunk to expected location, cannot determine playtime');
|
rlm@3
|
106 }
|
rlm@3
|
107
|
rlm@3
|
108 $getid3->info['audio']['bitrate'] = (($getid3->info['avdataend'] - $getid3->info['avdataoffset']) / $getid3->info['playtime_seconds']) * 8;
|
rlm@3
|
109
|
rlm@3
|
110 } else {
|
rlm@3
|
111
|
rlm@3
|
112 throw new getid3_exception('shorten failed to decode file to WAV for parsing');
|
rlm@3
|
113 return false;
|
rlm@3
|
114 }
|
rlm@3
|
115
|
rlm@3
|
116 return true;
|
rlm@3
|
117 }
|
rlm@3
|
118
|
rlm@3
|
119 }
|
rlm@3
|
120
|
rlm@3
|
121 ?> |