Blame view

sources/3rdparty/getid3/module.audio.dts.php 10.2 KB
03e52840d   Kload   Init
1
2
3
4
5
6
7
8
9
10
11
12
13
14
  <?php
  /////////////////////////////////////////////////////////////////
  /// getID3() by James Heinrich <info@getid3.org>               //
  //  available at http://getid3.sourceforge.net                 //
  //            or http://www.getid3.org                         //
  /////////////////////////////////////////////////////////////////
  // See readme.txt for more details                             //
  /////////////////////////////////////////////////////////////////
  //                                                             //
  // module.audio.dts.php                                        //
  // module for analyzing DTS Audio files                        //
  // dependencies: NONE                                          //
  //                                                             //
  /////////////////////////////////////////////////////////////////
31b7f2792   Kload   Upgrade to ownclo...
15
16
17
  /**
  * @tutorial http://wiki.multimedia.cx/index.php?title=DTS
  */
03e52840d   Kload   Init
18
19
  class getid3_dts extends getid3_handler
  {
31b7f2792   Kload   Upgrade to ownclo...
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
  	/**
  	* Default DTS syncword used in native .cpt or .dts formats
  	*/
      const syncword = "\x7F\xFE\x80\x01";
  
  	private $readBinDataOffset = 0;
  
      /**
      * Possible syncwords indicating bitstream encoding
      */
      public static $syncwords = array(
      	0 => "\x7F\xFE\x80\x01",  // raw big-endian
      	1 => "\xFE\x7F\x01\x80",  // raw little-endian
      	2 => "\x1F\xFF\xE8\x00",  // 14-bit big-endian
      	3 => "\xFF\x1F\x00\xE8"); // 14-bit little-endian
03e52840d   Kload   Init
35
36
37
  
  	public function Analyze() {
  		$info = &$this->getid3->info;
31b7f2792   Kload   Upgrade to ownclo...
38
  		$info['fileformat'] = 'dts';
03e52840d   Kload   Init
39

31b7f2792   Kload   Upgrade to ownclo...
40
41
  		$this->fseek($info['avdataoffset']);
  		$DTSheader = $this->fread(20); // we only need 2 words magic + 6 words frame header, but these words may be normal 16-bit words OR 14-bit words with 2 highest bits set to zero, so 8 words can be either 8*16/8 = 16 bytes OR 8*16*(16/14)/8 = 18.3 bytes
03e52840d   Kload   Init
42

31b7f2792   Kload   Upgrade to ownclo...
43
44
45
46
47
48
49
50
51
52
53
54
55
56
  		// check syncword
  		$sync = substr($DTSheader, 0, 4);
          if (($encoding = array_search($sync, self::$syncwords)) !== false) {
  
          	$info['dts']['raw']['magic'] = $sync;
  			$this->readBinDataOffset = 32;
  
          } elseif ($this->isDependencyFor('matroska')) {
  
  			// Matroska contains DTS without syncword encoded as raw big-endian format
  			$encoding = 0;
  			$this->readBinDataOffset = 0;
  
          } else {
03e52840d   Kload   Init
57

31b7f2792   Kload   Upgrade to ownclo...
58
59
  			unset($info['fileformat']);
  			return $this->error('Expecting "'.implode('| ', array_map('getid3_lib::PrintHexBytes', self::$syncwords)).'" at offset '.$info['avdataoffset'].', found "'.getid3_lib::PrintHexBytes($sync).'"');
03e52840d   Kload   Init
60

03e52840d   Kload   Init
61
  		}
31b7f2792   Kload   Upgrade to ownclo...
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
  		// decode header
  		$fhBS = '';
  		for ($word_offset = 0; $word_offset <= strlen($DTSheader); $word_offset += 2) {
  			switch ($encoding) {
  				case 0: // raw big-endian
  					$fhBS .=        getid3_lib::BigEndian2Bin(       substr($DTSheader, $word_offset, 2) );
  					break;
  				case 1: // raw little-endian
  					$fhBS .=        getid3_lib::BigEndian2Bin(strrev(substr($DTSheader, $word_offset, 2)));
  					break;
  				case 2: // 14-bit big-endian
  					$fhBS .= substr(getid3_lib::BigEndian2Bin(       substr($DTSheader, $word_offset, 2) ), 2, 14);
  					break;
  				case 3: // 14-bit little-endian
  					$fhBS .= substr(getid3_lib::BigEndian2Bin(strrev(substr($DTSheader, $word_offset, 2))), 2, 14);
  					break;
  			}
  		}
  
  		$info['dts']['raw']['frame_type']             =        $this->readBinData($fhBS,  1);
  		$info['dts']['raw']['deficit_samples']        =        $this->readBinData($fhBS,  5);
  		$info['dts']['flags']['crc_present']          = (bool) $this->readBinData($fhBS,  1);
  		$info['dts']['raw']['pcm_sample_blocks']      =        $this->readBinData($fhBS,  7);
  		$info['dts']['raw']['frame_byte_size']        =        $this->readBinData($fhBS, 14);
  		$info['dts']['raw']['channel_arrangement']    =        $this->readBinData($fhBS,  6);
  		$info['dts']['raw']['sample_frequency']       =        $this->readBinData($fhBS,  4);
  		$info['dts']['raw']['bitrate']                =        $this->readBinData($fhBS,  5);
  		$info['dts']['flags']['embedded_downmix']     = (bool) $this->readBinData($fhBS,  1);
  		$info['dts']['flags']['dynamicrange']         = (bool) $this->readBinData($fhBS,  1);
  		$info['dts']['flags']['timestamp']            = (bool) $this->readBinData($fhBS,  1);
  		$info['dts']['flags']['auxdata']              = (bool) $this->readBinData($fhBS,  1);
  		$info['dts']['flags']['hdcd']                 = (bool) $this->readBinData($fhBS,  1);
  		$info['dts']['raw']['extension_audio']        =        $this->readBinData($fhBS,  3);
  		$info['dts']['flags']['extended_coding']      = (bool) $this->readBinData($fhBS,  1);
  		$info['dts']['flags']['audio_sync_insertion'] = (bool) $this->readBinData($fhBS,  1);
  		$info['dts']['raw']['lfe_effects']            =        $this->readBinData($fhBS,  2);
  		$info['dts']['flags']['predictor_history']    = (bool) $this->readBinData($fhBS,  1);
03e52840d   Kload   Init
99
  		if ($info['dts']['flags']['crc_present']) {
31b7f2792   Kload   Upgrade to ownclo...
100
  			$info['dts']['raw']['crc16']              =        $this->readBinData($fhBS, 16);
03e52840d   Kload   Init
101
  		}
31b7f2792   Kload   Upgrade to ownclo...
102
103
104
105
106
107
108
109
110
111
112
113
114
115
  		$info['dts']['flags']['mri_perfect_reconst']  = (bool) $this->readBinData($fhBS,  1);
  		$info['dts']['raw']['encoder_soft_version']   =        $this->readBinData($fhBS,  4);
  		$info['dts']['raw']['copy_history']           =        $this->readBinData($fhBS,  2);
  		$info['dts']['raw']['bits_per_sample']        =        $this->readBinData($fhBS,  2);
  		$info['dts']['flags']['surround_es']          = (bool) $this->readBinData($fhBS,  1);
  		$info['dts']['flags']['front_sum_diff']       = (bool) $this->readBinData($fhBS,  1);
  		$info['dts']['flags']['surround_sum_diff']    = (bool) $this->readBinData($fhBS,  1);
  		$info['dts']['raw']['dialog_normalization']   =        $this->readBinData($fhBS,  4);
  
  
  		$info['dts']['bitrate']              = self::bitrateLookup($info['dts']['raw']['bitrate']);
  		$info['dts']['bits_per_sample']      = self::bitPerSampleLookup($info['dts']['raw']['bits_per_sample']);
  		$info['dts']['sample_rate']          = self::sampleRateLookup($info['dts']['raw']['sample_frequency']);
  		$info['dts']['dialog_normalization'] = self::dialogNormalization($info['dts']['raw']['dialog_normalization'], $info['dts']['raw']['encoder_soft_version']);
03e52840d   Kload   Init
116
117
  		$info['dts']['flags']['lossless']    = (($info['dts']['raw']['bitrate'] == 31) ? true  : false);
  		$info['dts']['bitrate_mode']         = (($info['dts']['raw']['bitrate'] == 30) ? 'vbr' : 'cbr');
31b7f2792   Kload   Upgrade to ownclo...
118
119
  		$info['dts']['channels']             = self::numChannelsLookup($info['dts']['raw']['channel_arrangement']);
  		$info['dts']['channel_arrangement']  = self::channelArrangementLookup($info['dts']['raw']['channel_arrangement']);
03e52840d   Kload   Init
120
121
122
123
124
125
126
127
  
  		$info['audio']['dataformat']          = 'dts';
  		$info['audio']['lossless']            = $info['dts']['flags']['lossless'];
  		$info['audio']['bitrate_mode']        = $info['dts']['bitrate_mode'];
  		$info['audio']['bits_per_sample']     = $info['dts']['bits_per_sample'];
  		$info['audio']['sample_rate']         = $info['dts']['sample_rate'];
  		$info['audio']['channels']            = $info['dts']['channels'];
  		$info['audio']['bitrate']             = $info['dts']['bitrate'];
31b7f2792   Kload   Upgrade to ownclo...
128
  		if (isset($info['avdataend']) && !empty($info['dts']['bitrate']) && is_numeric($info['dts']['bitrate'])) {
03e52840d   Kload   Init
129
  			$info['playtime_seconds']         = ($info['avdataend'] - $info['avdataoffset']) / ($info['dts']['bitrate'] / 8);
31b7f2792   Kload   Upgrade to ownclo...
130
131
132
133
  			if (($encoding == 2) || ($encoding == 3)) {
  				// 14-bit data packed into 16-bit words, so the playtime is wrong because only (14/16) of the bytes in the data portion of the file are used at the specified bitrate
  				$info['playtime_seconds'] *= (14 / 16);
  			}
03e52840d   Kload   Init
134
  		}
03e52840d   Kload   Init
135
136
  		return true;
  	}
31b7f2792   Kload   Upgrade to ownclo...
137
138
139
  	private function readBinData($bin, $length) {
  		$data = substr($bin, $this->readBinDataOffset, $length);
  		$this->readBinDataOffset += $length;
03e52840d   Kload   Init
140
141
  		return bindec($data);
  	}
31b7f2792   Kload   Upgrade to ownclo...
142
143
  	public static function bitrateLookup($index) {
  		static $lookup = array(
03e52840d   Kload   Init
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
  			0  => 32000,
  			1  => 56000,
  			2  => 64000,
  			3  => 96000,
  			4  => 112000,
  			5  => 128000,
  			6  => 192000,
  			7  => 224000,
  			8  => 256000,
  			9  => 320000,
  			10 => 384000,
  			11 => 448000,
  			12 => 512000,
  			13 => 576000,
  			14 => 640000,
  			15 => 768000,
  			16 => 960000,
  			17 => 1024000,
  			18 => 1152000,
  			19 => 1280000,
  			20 => 1344000,
  			21 => 1408000,
  			22 => 1411200,
  			23 => 1472000,
  			24 => 1536000,
  			25 => 1920000,
  			26 => 2048000,
  			27 => 3072000,
  			28 => 3840000,
  			29 => 'open',
  			30 => 'variable',
31b7f2792   Kload   Upgrade to ownclo...
175
  			31 => 'lossless',
03e52840d   Kload   Init
176
  		);
31b7f2792   Kload   Upgrade to ownclo...
177
  		return (isset($lookup[$index]) ? $lookup[$index] : false);
03e52840d   Kload   Init
178
  	}
31b7f2792   Kload   Upgrade to ownclo...
179
180
  	public static function sampleRateLookup($index) {
  		static $lookup = array(
03e52840d   Kload   Init
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
  			0  => 'invalid',
  			1  => 8000,
  			2  => 16000,
  			3  => 32000,
  			4  => 'invalid',
  			5  => 'invalid',
  			6  => 11025,
  			7  => 22050,
  			8  => 44100,
  			9  => 'invalid',
  			10 => 'invalid',
  			11 => 12000,
  			12 => 24000,
  			13 => 48000,
  			14 => 'invalid',
31b7f2792   Kload   Upgrade to ownclo...
196
  			15 => 'invalid',
03e52840d   Kload   Init
197
  		);
31b7f2792   Kload   Upgrade to ownclo...
198
  		return (isset($lookup[$index]) ? $lookup[$index] : false);
03e52840d   Kload   Init
199
  	}
31b7f2792   Kload   Upgrade to ownclo...
200
201
  	public static function bitPerSampleLookup($index) {
  		static $lookup = array(
03e52840d   Kload   Init
202
203
204
205
206
  			0  => 16,
  			1  => 20,
  			2  => 24,
  			3  => 24,
  		);
31b7f2792   Kload   Upgrade to ownclo...
207
  		return (isset($lookup[$index]) ? $lookup[$index] : false);
03e52840d   Kload   Init
208
  	}
31b7f2792   Kload   Upgrade to ownclo...
209
  	public static function numChannelsLookup($index) {
03e52840d   Kload   Init
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
  		switch ($index) {
  			case 0:
  				return 1;
  				break;
  			case 1:
  			case 2:
  			case 3:
  			case 4:
  				return 2;
  				break;
  			case 5:
  			case 6:
  				return 3;
  				break;
  			case 7:
  			case 8:
  				return 4;
  				break;
  			case 9:
  				return 5;
  				break;
  			case 10:
  			case 11:
  			case 12:
  				return 6;
  				break;
  			case 13:
  				return 7;
  				break;
  			case 14:
  			case 15:
  				return 8;
  				break;
  		}
  		return false;
  	}
31b7f2792   Kload   Upgrade to ownclo...
246
247
  	public static function channelArrangementLookup($index) {
  		static $lookup = array(
03e52840d   Kload   Init
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
  			0  => 'A',
  			1  => 'A + B (dual mono)',
  			2  => 'L + R (stereo)',
  			3  => '(L+R) + (L-R) (sum-difference)',
  			4  => 'LT + RT (left and right total)',
  			5  => 'C + L + R',
  			6  => 'L + R + S',
  			7  => 'C + L + R + S',
  			8  => 'L + R + SL + SR',
  			9  => 'C + L + R + SL + SR',
  			10 => 'CL + CR + L + R + SL + SR',
  			11 => 'C + L + R+ LR + RR + OV',
  			12 => 'CF + CR + LF + RF + LR + RR',
  			13 => 'CL + C + CR + L + R + SL + SR',
  			14 => 'CL + CR + L + R + SL1 + SL2 + SR1 + SR2',
  			15 => 'CL + C+ CR + L + R + SL + S + SR',
  		);
31b7f2792   Kload   Upgrade to ownclo...
265
  		return (isset($lookup[$index]) ? $lookup[$index] : 'user-defined');
03e52840d   Kload   Init
266
  	}
31b7f2792   Kload   Upgrade to ownclo...
267
  	public static function dialogNormalization($index, $version) {
03e52840d   Kload   Init
268
269
270
271
272
273
274
275
276
277
278
279
  		switch ($version) {
  			case 7:
  				return 0 - $index;
  				break;
  			case 6:
  				return 0 - 16 - $index;
  				break;
  		}
  		return false;
  	}
  
  }