run:R W Run
54.21 KB
2026-03-11 16:18:51
R W Run
79.05 KB
2026-03-11 16:18:51
R W Run
1.36 KB
2026-03-11 16:18:51
R W Run
133.61 KB
2026-03-11 16:18:51
R W Run
26.5 KB
2026-03-11 16:18:51
R W Run
104.64 KB
2026-03-11 16:18:51
R W Run
164.97 KB
2026-03-11 16:18:51
R W Run
136.53 KB
2026-03-11 16:18:51
R W Run
38.46 KB
2026-03-11 16:18:51
R W Run
10.63 KB
2026-03-11 16:18:51
R W Run
19.23 KB
2026-03-11 16:18:51
R W Run
104.5 KB
2026-03-11 16:18:51
R W Run
42.74 KB
2026-03-11 16:18:51
R W Run
18.63 KB
2026-03-11 16:18:51
R W Run
14.7 KB
2026-03-11 16:18:51
R W Run
151.2 KB
2026-03-11 16:18:51
R W Run
11.75 KB
2026-03-11 16:18:51
R W Run
25.71 KB
2026-03-11 16:18:51
R W Run
error_log
📄module.audio.ac3.php
1<?php
2
3/////////////////////////////////////////////////////////////////
4/// getID3() by James Heinrich <info@getid3.org> //
5// available at https://github.com/JamesHeinrich/getID3 //
6// or https://www.getid3.org //
7// or http://getid3.sourceforge.net //
8// see readme.txt for more details //
9/////////////////////////////////////////////////////////////////
10// //
11// module.audio.ac3.php //
12// module for analyzing AC-3 (aka Dolby Digital) audio files //
13// dependencies: NONE //
14// ///
15/////////////////////////////////////////////////////////////////
16
17if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
18 exit;
19}
20
21class getid3_ac3 extends getid3_handler
22{
23 /**
24 * @var array
25 */
26 private $AC3header = array();
27
28 /**
29 * @var int
30 */
31 private $BSIoffset = 0;
32
33 const syncword = 0x0B77;
34
35 /**
36 * @return bool
37 */
38 public function Analyze() {
39 $info = &$this->getid3->info;
40
41 ///AH
42 $info['ac3']['raw']['bsi'] = array();
43 $thisfile_ac3 = &$info['ac3'];
44 $thisfile_ac3_raw = &$thisfile_ac3['raw'];
45 $thisfile_ac3_raw_bsi = &$thisfile_ac3_raw['bsi'];
46
47
48 // http://www.atsc.org/standards/a_52a.pdf
49
50 $info['fileformat'] = 'ac3';
51
52 // An AC-3 serial coded audio bit stream is made up of a sequence of synchronization frames
53 // Each synchronization frame contains 6 coded audio blocks (AB), each of which represent 256
54 // new audio samples per channel. A synchronization information (SI) header at the beginning
55 // of each frame contains information needed to acquire and maintain synchronization. A
56 // bit stream information (BSI) header follows SI, and contains parameters describing the coded
57 // audio service. The coded audio blocks may be followed by an auxiliary data (Aux) field. At the
58 // end of each frame is an error check field that includes a CRC word for error detection. An
59 // additional CRC word is located in the SI header, the use of which, by a decoder, is optional.
60 //
61 // syncinfo() | bsi() | AB0 | AB1 | AB2 | AB3 | AB4 | AB5 | Aux | CRC
62
63 // syncinfo() {
64 // syncword 16
65 // crc1 16
66 // fscod 2
67 // frmsizecod 6
68 // } /* end of syncinfo */
69
70 $this->fseek($info['avdataoffset']);
71 $tempAC3header = $this->fread(100); // should be enough to cover all data, there are some variable-length fields...?
72 $this->AC3header['syncinfo'] = getid3_lib::BigEndian2Int(substr($tempAC3header, 0, 2));
73 $this->AC3header['bsi'] = getid3_lib::BigEndian2Bin(substr($tempAC3header, 2));
74 $thisfile_ac3_raw_bsi['bsid'] = (getid3_lib::LittleEndian2Int(substr($tempAC3header, 5, 1)) & 0xF8) >> 3; // AC3 and E-AC3 put the "bsid" version identifier in the same place, but unfortnately the 4 bytes between the syncword and the version identifier are interpreted differently, so grab it here so the following code structure can make sense
75 unset($tempAC3header);
76
77 if ($this->AC3header['syncinfo'] !== self::syncword) {
78 if (!$this->isDependencyFor('matroska')) {
79 unset($info['fileformat'], $info['ac3']);
80 return $this->error('Expecting "'.dechex(self::syncword).'" at offset '.$info['avdataoffset'].', found "'.dechex($this->AC3header['syncinfo']).'"');
81 }
82 }
83
84 $info['audio']['dataformat'] = 'ac3';
85 $info['audio']['bitrate_mode'] = 'cbr';
86 $info['audio']['lossless'] = false;
87
88 if ($thisfile_ac3_raw_bsi['bsid'] <= 8) {
89
90 $thisfile_ac3_raw_bsi['crc1'] = getid3_lib::Bin2Dec($this->readHeaderBSI(16));
91 $thisfile_ac3_raw_bsi['fscod'] = $this->readHeaderBSI(2); // 5.4.1.3
92 $thisfile_ac3_raw_bsi['frmsizecod'] = $this->readHeaderBSI(6); // 5.4.1.4
93 if ($thisfile_ac3_raw_bsi['frmsizecod'] > 37) { // binary: 100101 - see Table 5.18 Frame Size Code Table (1 word = 16 bits)
94 $this->warning('Unexpected ac3.bsi.frmsizecod value: '.$thisfile_ac3_raw_bsi['frmsizecod'].', bitrate not set correctly');
95 }
96
97 $thisfile_ac3_raw_bsi['bsid'] = $this->readHeaderBSI(5); // we already know this from pre-parsing the version identifier, but re-read it to let the bitstream flow as intended
98 $thisfile_ac3_raw_bsi['bsmod'] = $this->readHeaderBSI(3);
99 $thisfile_ac3_raw_bsi['acmod'] = $this->readHeaderBSI(3);
100
101 if ($thisfile_ac3_raw_bsi['acmod'] & 0x01) {
102 // If the lsb of acmod is a 1, center channel is in use and cmixlev follows in the bit stream.
103 $thisfile_ac3_raw_bsi['cmixlev'] = $this->readHeaderBSI(2);
104 $thisfile_ac3['center_mix_level'] = self::centerMixLevelLookup($thisfile_ac3_raw_bsi['cmixlev']);
105 }
106
107 if ($thisfile_ac3_raw_bsi['acmod'] & 0x04) {
108 // If the msb of acmod is a 1, surround channels are in use and surmixlev follows in the bit stream.
109 $thisfile_ac3_raw_bsi['surmixlev'] = $this->readHeaderBSI(2);
110 $thisfile_ac3['surround_mix_level'] = self::surroundMixLevelLookup($thisfile_ac3_raw_bsi['surmixlev']);
111 }
112
113 if ($thisfile_ac3_raw_bsi['acmod'] == 0x02) {
114 // When operating in the two channel mode, this 2-bit code indicates whether or not the program has been encoded in Dolby Surround.
115 $thisfile_ac3_raw_bsi['dsurmod'] = $this->readHeaderBSI(2);
116 $thisfile_ac3['dolby_surround_mode'] = self::dolbySurroundModeLookup($thisfile_ac3_raw_bsi['dsurmod']);
117 }
118
119 $thisfile_ac3_raw_bsi['flags']['lfeon'] = (bool) $this->readHeaderBSI(1);
120
121 // This indicates how far the average dialogue level is below digital 100 percent. Valid values are 1-31.
122 // The value of 0 is reserved. The values of 1 to 31 are interpreted as -1 dB to -31 dB with respect to digital 100 percent.
123 $thisfile_ac3_raw_bsi['dialnorm'] = $this->readHeaderBSI(5); // 5.4.2.8 dialnorm: Dialogue Normalization, 5 Bits
124
125 $thisfile_ac3_raw_bsi['flags']['compr'] = (bool) $this->readHeaderBSI(1); // 5.4.2.9 compre: Compression Gain Word Exists, 1 Bit
126 if ($thisfile_ac3_raw_bsi['flags']['compr']) {
127 $thisfile_ac3_raw_bsi['compr'] = $this->readHeaderBSI(8); // 5.4.2.10 compr: Compression Gain Word, 8 Bits
128 $thisfile_ac3['heavy_compression'] = self::heavyCompression($thisfile_ac3_raw_bsi['compr']);
129 }
130
131 $thisfile_ac3_raw_bsi['flags']['langcod'] = (bool) $this->readHeaderBSI(1); // 5.4.2.11 langcode: Language Code Exists, 1 Bit
132 if ($thisfile_ac3_raw_bsi['flags']['langcod']) {
133 $thisfile_ac3_raw_bsi['langcod'] = $this->readHeaderBSI(8); // 5.4.2.12 langcod: Language Code, 8 Bits
134 }
135
136 $thisfile_ac3_raw_bsi['flags']['audprodinfo'] = (bool) $this->readHeaderBSI(1); // 5.4.2.13 audprodie: Audio Production Information Exists, 1 Bit
137 if ($thisfile_ac3_raw_bsi['flags']['audprodinfo']) {
138 $thisfile_ac3_raw_bsi['mixlevel'] = $this->readHeaderBSI(5); // 5.4.2.14 mixlevel: Mixing Level, 5 Bits
139 $thisfile_ac3_raw_bsi['roomtyp'] = $this->readHeaderBSI(2); // 5.4.2.15 roomtyp: Room Type, 2 Bits
140
141 $thisfile_ac3['mixing_level'] = (80 + $thisfile_ac3_raw_bsi['mixlevel']).'dB';
142 $thisfile_ac3['room_type'] = self::roomTypeLookup($thisfile_ac3_raw_bsi['roomtyp']);
143 }
144
145
146 $thisfile_ac3_raw_bsi['dialnorm2'] = $this->readHeaderBSI(5); // 5.4.2.16 dialnorm2: Dialogue Normalization, ch2, 5 Bits
147 $thisfile_ac3['dialogue_normalization2'] = '-'.$thisfile_ac3_raw_bsi['dialnorm2'].'dB'; // This indicates how far the average dialogue level is below digital 100 percent. Valid values are 1-31. The value of 0 is reserved. The values of 1 to 31 are interpreted as -1 dB to -31 dB with respect to digital 100 percent.
148
149 $thisfile_ac3_raw_bsi['flags']['compr2'] = (bool) $this->readHeaderBSI(1); // 5.4.2.17 compr2e: Compression Gain Word Exists, ch2, 1 Bit
150 if ($thisfile_ac3_raw_bsi['flags']['compr2']) {
151 $thisfile_ac3_raw_bsi['compr2'] = $this->readHeaderBSI(8); // 5.4.2.18 compr2: Compression Gain Word, ch2, 8 Bits
152 $thisfile_ac3['heavy_compression2'] = self::heavyCompression($thisfile_ac3_raw_bsi['compr2']);
153 }
154
155 $thisfile_ac3_raw_bsi['flags']['langcod2'] = (bool) $this->readHeaderBSI(1); // 5.4.2.19 langcod2e: Language Code Exists, ch2, 1 Bit
156 if ($thisfile_ac3_raw_bsi['flags']['langcod2']) {
157 $thisfile_ac3_raw_bsi['langcod2'] = $this->readHeaderBSI(8); // 5.4.2.20 langcod2: Language Code, ch2, 8 Bits
158 }
159
160 $thisfile_ac3_raw_bsi['flags']['audprodinfo2'] = (bool) $this->readHeaderBSI(1); // 5.4.2.21 audprodi2e: Audio Production Information Exists, ch2, 1 Bit
161 if ($thisfile_ac3_raw_bsi['flags']['audprodinfo2']) {
162 $thisfile_ac3_raw_bsi['mixlevel2'] = $this->readHeaderBSI(5); // 5.4.2.22 mixlevel2: Mixing Level, ch2, 5 Bits
163 $thisfile_ac3_raw_bsi['roomtyp2'] = $this->readHeaderBSI(2); // 5.4.2.23 roomtyp2: Room Type, ch2, 2 Bits
164
165 $thisfile_ac3['mixing_level2'] = (80 + $thisfile_ac3_raw_bsi['mixlevel2']).'dB';
166 $thisfile_ac3['room_type2'] = self::roomTypeLookup($thisfile_ac3_raw_bsi['roomtyp2']);
167 }
168
169 $thisfile_ac3_raw_bsi['copyright'] = (bool) $this->readHeaderBSI(1); // 5.4.2.24 copyrightb: Copyright Bit, 1 Bit
170
171 $thisfile_ac3_raw_bsi['original'] = (bool) $this->readHeaderBSI(1); // 5.4.2.25 origbs: Original Bit Stream, 1 Bit
172
173 $thisfile_ac3_raw_bsi['flags']['timecod1'] = $this->readHeaderBSI(2); // 5.4.2.26 timecod1e, timcode2e: Time Code (first and second) Halves Exist, 2 Bits
174 if ($thisfile_ac3_raw_bsi['flags']['timecod1'] & 0x01) {
175 $thisfile_ac3_raw_bsi['timecod1'] = $this->readHeaderBSI(14); // 5.4.2.27 timecod1: Time code first half, 14 bits
176 $thisfile_ac3['timecode1'] = 0;
177 $thisfile_ac3['timecode1'] += (($thisfile_ac3_raw_bsi['timecod1'] & 0x3E00) >> 9) * 3600; // The first 5 bits of this 14-bit field represent the time in hours, with valid values of 0�23
178 $thisfile_ac3['timecode1'] += (($thisfile_ac3_raw_bsi['timecod1'] & 0x01F8) >> 3) * 60; // The next 6 bits represent the time in minutes, with valid values of 0�59
179 $thisfile_ac3['timecode1'] += (($thisfile_ac3_raw_bsi['timecod1'] & 0x0003) >> 0) * 8; // The final 3 bits represents the time in 8 second increments, with valid values of 0�7 (representing 0, 8, 16, ... 56 seconds)
180 }
181 if ($thisfile_ac3_raw_bsi['flags']['timecod1'] & 0x02) {
182 $thisfile_ac3_raw_bsi['timecod2'] = $this->readHeaderBSI(14); // 5.4.2.28 timecod2: Time code second half, 14 bits
183 $thisfile_ac3['timecode2'] = 0;
184 $thisfile_ac3['timecode2'] += (($thisfile_ac3_raw_bsi['timecod2'] & 0x3800) >> 11) * 1; // The first 3 bits of this 14-bit field represent the time in seconds, with valid values from 0�7 (representing 0-7 seconds)
185 $thisfile_ac3['timecode2'] += (($thisfile_ac3_raw_bsi['timecod2'] & 0x07C0) >> 6) * (1 / 30); // The next 5 bits represents the time in frames, with valid values from 0�29 (one frame = 1/30th of a second)
186 $thisfile_ac3['timecode2'] += (($thisfile_ac3_raw_bsi['timecod2'] & 0x003F) >> 0) * ((1 / 30) / 60); // The final 6 bits represents fractions of 1/64 of a frame, with valid values from 0�63
187 }
188
189 $thisfile_ac3_raw_bsi['flags']['addbsi'] = (bool) $this->readHeaderBSI(1);
190 if ($thisfile_ac3_raw_bsi['flags']['addbsi']) {
191 $thisfile_ac3_raw_bsi['addbsi_length'] = $this->readHeaderBSI(6) + 1; // This 6-bit code, which exists only if addbside is a 1, indicates the length in bytes of additional bit stream information. The valid range of addbsil is 0�63, indicating 1�64 additional bytes, respectively.
192
193 $this->AC3header['bsi'] .= getid3_lib::BigEndian2Bin($this->fread($thisfile_ac3_raw_bsi['addbsi_length']));
194
195 $thisfile_ac3_raw_bsi['addbsi_data'] = substr($this->AC3header['bsi'], $this->BSIoffset, $thisfile_ac3_raw_bsi['addbsi_length'] * 8);
196 $this->BSIoffset += $thisfile_ac3_raw_bsi['addbsi_length'] * 8;
197 }
198
199
200 } elseif ($thisfile_ac3_raw_bsi['bsid'] <= 16) { // E-AC3
201
202
203 $this->error('E-AC3 parsing is incomplete and experimental in this version of getID3 ('.$this->getid3->version().'). Notably the bitrate calculations are wrong -- value might (or not) be correct, but it is not calculated correctly. Email info@getid3.org if you know how to calculate EAC3 bitrate correctly.');
204 $info['audio']['dataformat'] = 'eac3';
205
206 $thisfile_ac3_raw_bsi['strmtyp'] = $this->readHeaderBSI(2);
207 $thisfile_ac3_raw_bsi['substreamid'] = $this->readHeaderBSI(3);
208 $thisfile_ac3_raw_bsi['frmsiz'] = $this->readHeaderBSI(11);
209 $thisfile_ac3_raw_bsi['fscod'] = $this->readHeaderBSI(2);
210 if ($thisfile_ac3_raw_bsi['fscod'] == 3) {
211 $thisfile_ac3_raw_bsi['fscod2'] = $this->readHeaderBSI(2);
212 $thisfile_ac3_raw_bsi['numblkscod'] = 3; // six blocks per syncframe
213 } else {
214 $thisfile_ac3_raw_bsi['numblkscod'] = $this->readHeaderBSI(2);
215 }
216 $thisfile_ac3['bsi']['blocks_per_sync_frame'] = self::blocksPerSyncFrame($thisfile_ac3_raw_bsi['numblkscod']);
217 $thisfile_ac3_raw_bsi['acmod'] = $this->readHeaderBSI(3);
218 $thisfile_ac3_raw_bsi['flags']['lfeon'] = (bool) $this->readHeaderBSI(1);
219 $thisfile_ac3_raw_bsi['bsid'] = $this->readHeaderBSI(5); // we already know this from pre-parsing the version identifier, but re-read it to let the bitstream flow as intended
220 $thisfile_ac3_raw_bsi['dialnorm'] = $this->readHeaderBSI(5);
221 $thisfile_ac3_raw_bsi['flags']['compr'] = (bool) $this->readHeaderBSI(1);
222 if ($thisfile_ac3_raw_bsi['flags']['compr']) {
223 $thisfile_ac3_raw_bsi['compr'] = $this->readHeaderBSI(8);
224 }
225 if ($thisfile_ac3_raw_bsi['acmod'] == 0) { // if 1+1 mode (dual mono, so some items need a second value)
226 $thisfile_ac3_raw_bsi['dialnorm2'] = $this->readHeaderBSI(5);
227 $thisfile_ac3_raw_bsi['flags']['compr2'] = (bool) $this->readHeaderBSI(1);
228 if ($thisfile_ac3_raw_bsi['flags']['compr2']) {
229 $thisfile_ac3_raw_bsi['compr2'] = $this->readHeaderBSI(8);
230 }
231 }
232 if ($thisfile_ac3_raw_bsi['strmtyp'] == 1) { // if dependent stream
233 $thisfile_ac3_raw_bsi['flags']['chanmap'] = (bool) $this->readHeaderBSI(1);
234 if ($thisfile_ac3_raw_bsi['flags']['chanmap']) {
235 $thisfile_ac3_raw_bsi['chanmap'] = $this->readHeaderBSI(8);
236 }
237 }
238 $thisfile_ac3_raw_bsi['flags']['mixmdat'] = (bool) $this->readHeaderBSI(1);
239 if ($thisfile_ac3_raw_bsi['flags']['mixmdat']) { // Mixing metadata
240 if ($thisfile_ac3_raw_bsi['acmod'] > 2) { // if more than 2 channels
241 $thisfile_ac3_raw_bsi['dmixmod'] = $this->readHeaderBSI(2);
242 }
243 if (($thisfile_ac3_raw_bsi['acmod'] & 0x01) && ($thisfile_ac3_raw_bsi['acmod'] > 2)) { // if three front channels exist
244 $thisfile_ac3_raw_bsi['ltrtcmixlev'] = $this->readHeaderBSI(3);
245 $thisfile_ac3_raw_bsi['lorocmixlev'] = $this->readHeaderBSI(3);
246 }
247 if ($thisfile_ac3_raw_bsi['acmod'] & 0x04) { // if a surround channel exists
248 $thisfile_ac3_raw_bsi['ltrtsurmixlev'] = $this->readHeaderBSI(3);
249 $thisfile_ac3_raw_bsi['lorosurmixlev'] = $this->readHeaderBSI(3);
250 }
251 if ($thisfile_ac3_raw_bsi['flags']['lfeon']) { // if the LFE channel exists
252 $thisfile_ac3_raw_bsi['flags']['lfemixlevcod'] = (bool) $this->readHeaderBSI(1);
253 if ($thisfile_ac3_raw_bsi['flags']['lfemixlevcod']) {
254 $thisfile_ac3_raw_bsi['lfemixlevcod'] = $this->readHeaderBSI(5);
255 }
256 }
257 if ($thisfile_ac3_raw_bsi['strmtyp'] == 0) { // if independent stream
258 $thisfile_ac3_raw_bsi['flags']['pgmscl'] = (bool) $this->readHeaderBSI(1);
259 if ($thisfile_ac3_raw_bsi['flags']['pgmscl']) {
260 $thisfile_ac3_raw_bsi['pgmscl'] = $this->readHeaderBSI(6);
261 }
262 if ($thisfile_ac3_raw_bsi['acmod'] == 0) { // if 1+1 mode (dual mono, so some items need a second value)
263 $thisfile_ac3_raw_bsi['flags']['pgmscl2'] = (bool) $this->readHeaderBSI(1);
264 if ($thisfile_ac3_raw_bsi['flags']['pgmscl2']) {
265 $thisfile_ac3_raw_bsi['pgmscl2'] = $this->readHeaderBSI(6);
266 }
267 }
268 $thisfile_ac3_raw_bsi['flags']['extpgmscl'] = (bool) $this->readHeaderBSI(1);
269 if ($thisfile_ac3_raw_bsi['flags']['extpgmscl']) {
270 $thisfile_ac3_raw_bsi['extpgmscl'] = $this->readHeaderBSI(6);
271 }
272 $thisfile_ac3_raw_bsi['mixdef'] = $this->readHeaderBSI(2);
273 if ($thisfile_ac3_raw_bsi['mixdef'] == 1) { // mixing option 2
274 $thisfile_ac3_raw_bsi['premixcmpsel'] = (bool) $this->readHeaderBSI(1);
275 $thisfile_ac3_raw_bsi['drcsrc'] = (bool) $this->readHeaderBSI(1);
276 $thisfile_ac3_raw_bsi['premixcmpscl'] = $this->readHeaderBSI(3);
277 } elseif ($thisfile_ac3_raw_bsi['mixdef'] == 2) { // mixing option 3
278 $thisfile_ac3_raw_bsi['mixdata'] = $this->readHeaderBSI(12);
279 } elseif ($thisfile_ac3_raw_bsi['mixdef'] == 3) { // mixing option 4
280 $mixdefbitsread = 0;
281 $thisfile_ac3_raw_bsi['mixdeflen'] = $this->readHeaderBSI(5); $mixdefbitsread += 5;
282 $thisfile_ac3_raw_bsi['flags']['mixdata2'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
283 if ($thisfile_ac3_raw_bsi['flags']['mixdata2']) {
284 $thisfile_ac3_raw_bsi['premixcmpsel'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
285 $thisfile_ac3_raw_bsi['drcsrc'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
286 $thisfile_ac3_raw_bsi['premixcmpscl'] = $this->readHeaderBSI(3); $mixdefbitsread += 3;
287 $thisfile_ac3_raw_bsi['flags']['extpgmlscl'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
288 if ($thisfile_ac3_raw_bsi['flags']['extpgmlscl']) {
289 $thisfile_ac3_raw_bsi['extpgmlscl'] = $this->readHeaderBSI(4); $mixdefbitsread += 4;
290 }
291 $thisfile_ac3_raw_bsi['flags']['extpgmcscl'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
292 if ($thisfile_ac3_raw_bsi['flags']['extpgmcscl']) {
293 $thisfile_ac3_raw_bsi['extpgmcscl'] = $this->readHeaderBSI(4); $mixdefbitsread += 4;
294 }
295 $thisfile_ac3_raw_bsi['flags']['extpgmrscl'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
296 if ($thisfile_ac3_raw_bsi['flags']['extpgmrscl']) {
297 $thisfile_ac3_raw_bsi['extpgmrscl'] = $this->readHeaderBSI(4);
298 }
299 $thisfile_ac3_raw_bsi['flags']['extpgmlsscl'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
300 if ($thisfile_ac3_raw_bsi['flags']['extpgmlsscl']) {
301 $thisfile_ac3_raw_bsi['extpgmlsscl'] = $this->readHeaderBSI(4); $mixdefbitsread += 4;
302 }
303 $thisfile_ac3_raw_bsi['flags']['extpgmrsscl'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
304 if ($thisfile_ac3_raw_bsi['flags']['extpgmrsscl']) {
305 $thisfile_ac3_raw_bsi['extpgmrsscl'] = $this->readHeaderBSI(4); $mixdefbitsread += 4;
306 }
307 $thisfile_ac3_raw_bsi['flags']['extpgmlfescl'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
308 if ($thisfile_ac3_raw_bsi['flags']['extpgmlfescl']) {
309 $thisfile_ac3_raw_bsi['extpgmlfescl'] = $this->readHeaderBSI(4); $mixdefbitsread += 4;
310 }
311 $thisfile_ac3_raw_bsi['flags']['dmixscl'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
312 if ($thisfile_ac3_raw_bsi['flags']['dmixscl']) {
313 $thisfile_ac3_raw_bsi['dmixscl'] = $this->readHeaderBSI(4); $mixdefbitsread += 4;
314 }
315 $thisfile_ac3_raw_bsi['flags']['addch'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
316 if ($thisfile_ac3_raw_bsi['flags']['addch']) {
317 $thisfile_ac3_raw_bsi['flags']['extpgmaux1scl'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
318 if ($thisfile_ac3_raw_bsi['flags']['extpgmaux1scl']) {
319 $thisfile_ac3_raw_bsi['extpgmaux1scl'] = $this->readHeaderBSI(4); $mixdefbitsread += 4;
320 }
321 $thisfile_ac3_raw_bsi['flags']['extpgmaux2scl'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
322 if ($thisfile_ac3_raw_bsi['flags']['extpgmaux2scl']) {
323 $thisfile_ac3_raw_bsi['extpgmaux2scl'] = $this->readHeaderBSI(4); $mixdefbitsread += 4;
324 }
325 }
326 }
327 $thisfile_ac3_raw_bsi['flags']['mixdata3'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
328 if ($thisfile_ac3_raw_bsi['flags']['mixdata3']) {
329 $thisfile_ac3_raw_bsi['spchdat'] = $this->readHeaderBSI(5); $mixdefbitsread += 5;
330 $thisfile_ac3_raw_bsi['flags']['addspchdat'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
331 if ($thisfile_ac3_raw_bsi['flags']['addspchdat']) {
332 $thisfile_ac3_raw_bsi['spchdat1'] = $this->readHeaderBSI(5); $mixdefbitsread += 5;
333 $thisfile_ac3_raw_bsi['spchan1att'] = $this->readHeaderBSI(2); $mixdefbitsread += 2;
334 $thisfile_ac3_raw_bsi['flags']['addspchdat1'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
335 if ($thisfile_ac3_raw_bsi['flags']['addspchdat1']) {
336 $thisfile_ac3_raw_bsi['spchdat2'] = $this->readHeaderBSI(5); $mixdefbitsread += 5;
337 $thisfile_ac3_raw_bsi['spchan2att'] = $this->readHeaderBSI(3); $mixdefbitsread += 3;
338 }
339 }
340 }
341 $mixdata_bits = (8 * ($thisfile_ac3_raw_bsi['mixdeflen'] + 2)) - $mixdefbitsread;
342 $mixdata_fill = (($mixdata_bits % 8) ? 8 - ($mixdata_bits % 8) : 0);
343 $thisfile_ac3_raw_bsi['mixdata'] = $this->readHeaderBSI($mixdata_bits);
344 $thisfile_ac3_raw_bsi['mixdatafill'] = $this->readHeaderBSI($mixdata_fill);
345 unset($mixdefbitsread, $mixdata_bits, $mixdata_fill);
346 }
347 if ($thisfile_ac3_raw_bsi['acmod'] < 2) { // if mono or dual mono source
348 $thisfile_ac3_raw_bsi['flags']['paninfo'] = (bool) $this->readHeaderBSI(1);
349 if ($thisfile_ac3_raw_bsi['flags']['paninfo']) {
350 $thisfile_ac3_raw_bsi['panmean'] = $this->readHeaderBSI(8);
351 $thisfile_ac3_raw_bsi['paninfo'] = $this->readHeaderBSI(6);
352 }
353 if ($thisfile_ac3_raw_bsi['acmod'] == 0) { // if 1+1 mode (dual mono, so some items need a second value)
354 $thisfile_ac3_raw_bsi['flags']['paninfo2'] = (bool) $this->readHeaderBSI(1);
355 if ($thisfile_ac3_raw_bsi['flags']['paninfo2']) {
356 $thisfile_ac3_raw_bsi['panmean2'] = $this->readHeaderBSI(8);
357 $thisfile_ac3_raw_bsi['paninfo2'] = $this->readHeaderBSI(6);
358 }
359 }
360 }
361 $thisfile_ac3_raw_bsi['flags']['frmmixcfginfo'] = (bool) $this->readHeaderBSI(1);
362 if ($thisfile_ac3_raw_bsi['flags']['frmmixcfginfo']) { // mixing configuration information
363 if ($thisfile_ac3_raw_bsi['numblkscod'] == 0) {
364 $thisfile_ac3_raw_bsi['blkmixcfginfo'][0] = $this->readHeaderBSI(5);
365 } else {
366 for ($blk = 0; $blk < $thisfile_ac3_raw_bsi['numblkscod']; $blk++) {
367 $thisfile_ac3_raw_bsi['flags']['blkmixcfginfo'.$blk] = (bool) $this->readHeaderBSI(1);
368 if ($thisfile_ac3_raw_bsi['flags']['blkmixcfginfo'.$blk]) { // mixing configuration information
369 $thisfile_ac3_raw_bsi['blkmixcfginfo'][$blk] = $this->readHeaderBSI(5);
370 }
371 }
372 }
373 }
374 }
375 }
376 $thisfile_ac3_raw_bsi['flags']['infomdat'] = (bool) $this->readHeaderBSI(1);
377 if ($thisfile_ac3_raw_bsi['flags']['infomdat']) { // Informational metadata
378 $thisfile_ac3_raw_bsi['bsmod'] = $this->readHeaderBSI(3);
379 $thisfile_ac3_raw_bsi['flags']['copyrightb'] = (bool) $this->readHeaderBSI(1);
380 $thisfile_ac3_raw_bsi['flags']['origbs'] = (bool) $this->readHeaderBSI(1);
381 if ($thisfile_ac3_raw_bsi['acmod'] == 2) { // if in 2/0 mode
382 $thisfile_ac3_raw_bsi['dsurmod'] = $this->readHeaderBSI(2);
383 $thisfile_ac3_raw_bsi['dheadphonmod'] = $this->readHeaderBSI(2);
384 }
385 if ($thisfile_ac3_raw_bsi['acmod'] >= 6) { // if both surround channels exist
386 $thisfile_ac3_raw_bsi['dsurexmod'] = $this->readHeaderBSI(2);
387 }
388 $thisfile_ac3_raw_bsi['flags']['audprodi'] = (bool) $this->readHeaderBSI(1);
389 if ($thisfile_ac3_raw_bsi['flags']['audprodi']) {
390 $thisfile_ac3_raw_bsi['mixlevel'] = $this->readHeaderBSI(5);
391 $thisfile_ac3_raw_bsi['roomtyp'] = $this->readHeaderBSI(2);
392 $thisfile_ac3_raw_bsi['flags']['adconvtyp'] = (bool) $this->readHeaderBSI(1);
393 }
394 if ($thisfile_ac3_raw_bsi['acmod'] == 0) { // if 1+1 mode (dual mono, so some items need a second value)
395 $thisfile_ac3_raw_bsi['flags']['audprodi2'] = (bool) $this->readHeaderBSI(1);
396 if ($thisfile_ac3_raw_bsi['flags']['audprodi2']) {
397 $thisfile_ac3_raw_bsi['mixlevel2'] = $this->readHeaderBSI(5);
398 $thisfile_ac3_raw_bsi['roomtyp2'] = $this->readHeaderBSI(2);
399 $thisfile_ac3_raw_bsi['flags']['adconvtyp2'] = (bool) $this->readHeaderBSI(1);
400 }
401 }
402 if ($thisfile_ac3_raw_bsi['fscod'] < 3) { // if not half sample rate
403 $thisfile_ac3_raw_bsi['flags']['sourcefscod'] = (bool) $this->readHeaderBSI(1);
404 }
405 }
406 if (($thisfile_ac3_raw_bsi['strmtyp'] == 0) && ($thisfile_ac3_raw_bsi['numblkscod'] != 3)) { // if both surround channels exist
407 $thisfile_ac3_raw_bsi['flags']['convsync'] = (bool) $this->readHeaderBSI(1);
408 }
409 if ($thisfile_ac3_raw_bsi['strmtyp'] == 2) { // if bit stream converted from AC-3
410 if ($thisfile_ac3_raw_bsi['numblkscod'] != 3) { // 6 blocks per syncframe
411 $thisfile_ac3_raw_bsi['flags']['blkid'] = 1;
412 } else {
413 $thisfile_ac3_raw_bsi['flags']['blkid'] = (bool) $this->readHeaderBSI(1);
414 }
415 if ($thisfile_ac3_raw_bsi['flags']['blkid']) {
416 $thisfile_ac3_raw_bsi['frmsizecod'] = $this->readHeaderBSI(6);
417 }
418 }
419 $thisfile_ac3_raw_bsi['flags']['addbsi'] = (bool) $this->readHeaderBSI(1);
420 if ($thisfile_ac3_raw_bsi['flags']['addbsi']) {
421 $thisfile_ac3_raw_bsi['addbsil'] = $this->readHeaderBSI(6);
422 $thisfile_ac3_raw_bsi['addbsi'] = $this->readHeaderBSI(($thisfile_ac3_raw_bsi['addbsil'] + 1) * 8);
423 }
424
425 } else {
426
427 $this->error('Bit stream identification is version '.$thisfile_ac3_raw_bsi['bsid'].', but getID3() only understands up to version 16. Please submit a support ticket with a sample file.');
428 unset($info['ac3']);
429 return false;
430
431 }
432
433 if (isset($thisfile_ac3_raw_bsi['fscod2'])) {
434 $thisfile_ac3['sample_rate'] = self::sampleRateCodeLookup2($thisfile_ac3_raw_bsi['fscod2']);
435 } else {
436 $thisfile_ac3['sample_rate'] = self::sampleRateCodeLookup($thisfile_ac3_raw_bsi['fscod']);
437 }
438 if ($thisfile_ac3_raw_bsi['fscod'] <= 3) {
439 $info['audio']['sample_rate'] = $thisfile_ac3['sample_rate'];
440 } else {
441 $this->warning('Unexpected ac3.bsi.fscod value: '.$thisfile_ac3_raw_bsi['fscod']);
442 }
443 if (isset($thisfile_ac3_raw_bsi['frmsizecod'])) {
444 $thisfile_ac3['frame_length'] = self::frameSizeLookup($thisfile_ac3_raw_bsi['frmsizecod'], $thisfile_ac3_raw_bsi['fscod']);
445 $thisfile_ac3['bitrate'] = self::bitrateLookup($thisfile_ac3_raw_bsi['frmsizecod']);
446 } elseif (!empty($thisfile_ac3_raw_bsi['frmsiz'])) {
447 // this isn't right, but it's (usually) close, roughly 5% less than it should be.
448 // but WHERE is the actual bitrate value stored in EAC3?? email info@getid3.org if you know!
449 $thisfile_ac3['bitrate'] = ($thisfile_ac3_raw_bsi['frmsiz'] + 1) * 16 * 30; // The frmsiz field shall contain a value one less than the overall size of the coded syncframe in 16-bit words. That is, this field may assume a value ranging from 0 to 2047, and these values correspond to syncframe sizes ranging from 1 to 2048.
450 // kludge-fix to make it approximately the expected value, still not "right":
451 $thisfile_ac3['bitrate'] = round(($thisfile_ac3['bitrate'] * 1.05) / 16000) * 16000;
452 }
453 $info['audio']['bitrate'] = $thisfile_ac3['bitrate'];
454
455 if (isset($thisfile_ac3_raw_bsi['bsmod']) && isset($thisfile_ac3_raw_bsi['acmod'])) {
456 $thisfile_ac3['service_type'] = self::serviceTypeLookup($thisfile_ac3_raw_bsi['bsmod'], $thisfile_ac3_raw_bsi['acmod']);
457 }
458 $ac3_coding_mode = self::audioCodingModeLookup($thisfile_ac3_raw_bsi['acmod']);
459 foreach($ac3_coding_mode as $key => $value) {
460 $thisfile_ac3[$key] = $value;
461 }
462 switch ($thisfile_ac3_raw_bsi['acmod']) {
463 case 0:
464 case 1:
465 $info['audio']['channelmode'] = 'mono';
466 break;
467 case 3:
468 case 4:
469 $info['audio']['channelmode'] = 'stereo';
470 break;
471 default:
472 $info['audio']['channelmode'] = 'surround';
473 break;
474 }
475 $info['audio']['channels'] = $thisfile_ac3['num_channels'];
476
477 $thisfile_ac3['lfe_enabled'] = $thisfile_ac3_raw_bsi['flags']['lfeon'];
478 if ($thisfile_ac3_raw_bsi['flags']['lfeon']) {
479 $info['audio']['channels'] .= '.1';
480 }
481
482 $thisfile_ac3['channels_enabled'] = self::channelsEnabledLookup($thisfile_ac3_raw_bsi['acmod'], $thisfile_ac3_raw_bsi['flags']['lfeon']);
483 $thisfile_ac3['dialogue_normalization'] = '-'.$thisfile_ac3_raw_bsi['dialnorm'].'dB';
484
485 return true;
486 }
487
488 /**
489 * @param int $length
490 *
491 * @return int
492 */
493 private function readHeaderBSI($length) {
494 $data = substr($this->AC3header['bsi'], $this->BSIoffset, $length);
495 $this->BSIoffset += $length;
496
497 return bindec($data);
498 }
499
500 /**
501 * @param int $fscod
502 *
503 * @return int|string|false
504 */
505 public static function sampleRateCodeLookup($fscod) {
506 static $sampleRateCodeLookup = array(
507 0 => 48000,
508 1 => 44100,
509 2 => 32000,
510 3 => 'reserved' // If the reserved code is indicated, the decoder should not attempt to decode audio and should mute.
511 );
512 return (isset($sampleRateCodeLookup[$fscod]) ? $sampleRateCodeLookup[$fscod] : false);
513 }
514
515 /**
516 * @param int $fscod2
517 *
518 * @return int|string|false
519 */
520 public static function sampleRateCodeLookup2($fscod2) {
521 static $sampleRateCodeLookup2 = array(
522 0 => 24000,
523 1 => 22050,
524 2 => 16000,
525 3 => 'reserved' // If the reserved code is indicated, the decoder should not attempt to decode audio and should mute.
526 );
527 return (isset($sampleRateCodeLookup2[$fscod2]) ? $sampleRateCodeLookup2[$fscod2] : false);
528 }
529
530 /**
531 * @param int $bsmod
532 * @param int $acmod
533 *
534 * @return string|false
535 */
536 public static function serviceTypeLookup($bsmod, $acmod) {
537 static $serviceTypeLookup = array();
538 if (empty($serviceTypeLookup)) {
539 for ($i = 0; $i <= 7; $i++) {
540 $serviceTypeLookup[0][$i] = 'main audio service: complete main (CM)';
541 $serviceTypeLookup[1][$i] = 'main audio service: music and effects (ME)';
542 $serviceTypeLookup[2][$i] = 'associated service: visually impaired (VI)';
543 $serviceTypeLookup[3][$i] = 'associated service: hearing impaired (HI)';
544 $serviceTypeLookup[4][$i] = 'associated service: dialogue (D)';
545 $serviceTypeLookup[5][$i] = 'associated service: commentary (C)';
546 $serviceTypeLookup[6][$i] = 'associated service: emergency (E)';
547 }
548
549 $serviceTypeLookup[7][1] = 'associated service: voice over (VO)';
550 for ($i = 2; $i <= 7; $i++) {
551 $serviceTypeLookup[7][$i] = 'main audio service: karaoke';
552 }
553 }
554 return (isset($serviceTypeLookup[$bsmod][$acmod]) ? $serviceTypeLookup[$bsmod][$acmod] : false);
555 }
556
557 /**
558 * @param int $acmod
559 *
560 * @return array|false
561 */
562 public static function audioCodingModeLookup($acmod) {
563 // array(channel configuration, # channels (not incl LFE), channel order)
564 static $audioCodingModeLookup = array (
565 0 => array('channel_config'=>'1+1', 'num_channels'=>2, 'channel_order'=>'Ch1,Ch2'),
566 1 => array('channel_config'=>'1/0', 'num_channels'=>1, 'channel_order'=>'C'),
567 2 => array('channel_config'=>'2/0', 'num_channels'=>2, 'channel_order'=>'L,R'),
568 3 => array('channel_config'=>'3/0', 'num_channels'=>3, 'channel_order'=>'L,C,R'),
569 4 => array('channel_config'=>'2/1', 'num_channels'=>3, 'channel_order'=>'L,R,S'),
570 5 => array('channel_config'=>'3/1', 'num_channels'=>4, 'channel_order'=>'L,C,R,S'),
571 6 => array('channel_config'=>'2/2', 'num_channels'=>4, 'channel_order'=>'L,R,SL,SR'),
572 7 => array('channel_config'=>'3/2', 'num_channels'=>5, 'channel_order'=>'L,C,R,SL,SR'),
573 );
574 return (isset($audioCodingModeLookup[$acmod]) ? $audioCodingModeLookup[$acmod] : false);
575 }
576
577 /**
578 * @param int $cmixlev
579 *
580 * @return int|float|string|false
581 */
582 public static function centerMixLevelLookup($cmixlev) {
583 static $centerMixLevelLookup;
584 if (empty($centerMixLevelLookup)) {
585 $centerMixLevelLookup = array(
586 0 => pow(2, -3.0 / 6), // 0.707 (-3.0 dB)
587 1 => pow(2, -4.5 / 6), // 0.595 (-4.5 dB)
588 2 => pow(2, -6.0 / 6), // 0.500 (-6.0 dB)
589 3 => 'reserved'
590 );
591 }
592 return (isset($centerMixLevelLookup[$cmixlev]) ? $centerMixLevelLookup[$cmixlev] : false);
593 }
594
595 /**
596 * @param int $surmixlev
597 *
598 * @return int|float|string|false
599 */
600 public static function surroundMixLevelLookup($surmixlev) {
601 static $surroundMixLevelLookup;
602 if (empty($surroundMixLevelLookup)) {
603 $surroundMixLevelLookup = array(
604 0 => pow(2, -3.0 / 6),
605 1 => pow(2, -6.0 / 6),
606 2 => 0,
607 3 => 'reserved'
608 );
609 }
610 return (isset($surroundMixLevelLookup[$surmixlev]) ? $surroundMixLevelLookup[$surmixlev] : false);
611 }
612
613 /**
614 * @param int $dsurmod
615 *
616 * @return string|false
617 */
618 public static function dolbySurroundModeLookup($dsurmod) {
619 static $dolbySurroundModeLookup = array(
620 0 => 'not indicated',
621 1 => 'Not Dolby Surround encoded',
622 2 => 'Dolby Surround encoded',
623 3 => 'reserved'
624 );
625 return (isset($dolbySurroundModeLookup[$dsurmod]) ? $dolbySurroundModeLookup[$dsurmod] : false);
626 }
627
628 /**
629 * @param int $acmod
630 * @param bool $lfeon
631 *
632 * @return array
633 */
634 public static function channelsEnabledLookup($acmod, $lfeon) {
635 $lookup = array(
636 'ch1'=>($acmod == 0),
637 'ch2'=>($acmod == 0),
638 'left'=>($acmod > 1),
639 'right'=>($acmod > 1),
640 'center'=>(bool) ($acmod & 0x01),
641 'surround_mono'=>false,
642 'surround_left'=>false,
643 'surround_right'=>false,
644 'lfe'=>$lfeon);
645 switch ($acmod) {
646 case 4:
647 case 5:
648 $lookup['surround_mono'] = true;
649 break;
650 case 6:
651 case 7:
652 $lookup['surround_left'] = true;
653 $lookup['surround_right'] = true;
654 break;
655 }
656 return $lookup;
657 }
658
659 /**
660 * @param int $compre
661 *
662 * @return float|int
663 */
664 public static function heavyCompression($compre) {
665 // The first four bits indicate gain changes in 6.02dB increments which can be
666 // implemented with an arithmetic shift operation. The following four bits
667 // indicate linear gain changes, and require a 5-bit multiply.
668 // We will represent the two 4-bit fields of compr as follows:
669 // X0 X1 X2 X3 . Y4 Y5 Y6 Y7
670 // The meaning of the X values is most simply described by considering X to represent a 4-bit
671 // signed integer with values from -8 to +7. The gain indicated by X is then (X + 1) * 6.02 dB. The
672 // following table shows this in detail.
673
674 // Meaning of 4 msb of compr
675 // 7 +48.16 dB
676 // 6 +42.14 dB
677 // 5 +36.12 dB
678 // 4 +30.10 dB
679 // 3 +24.08 dB
680 // 2 +18.06 dB
681 // 1 +12.04 dB
682 // 0 +6.02 dB
683 // -1 0 dB
684 // -2 -6.02 dB
685 // -3 -12.04 dB
686 // -4 -18.06 dB
687 // -5 -24.08 dB
688 // -6 -30.10 dB
689 // -7 -36.12 dB
690 // -8 -42.14 dB
691
692 $fourbit = str_pad(decbin(($compre & 0xF0) >> 4), 4, '0', STR_PAD_LEFT);
693 if ($fourbit[0] == '1') {
694 $log_gain = -8 + bindec(substr($fourbit, 1));
695 } else {
696 $log_gain = bindec(substr($fourbit, 1));
697 }
698 $log_gain = ($log_gain + 1) * getid3_lib::RGADamplitude2dB(2);
699
700 // The value of Y is a linear representation of a gain change of up to -6 dB. Y is considered to
701 // be an unsigned fractional integer, with a leading value of 1, or: 0.1 Y4 Y5 Y6 Y7 (base 2). Y can
702 // represent values between 0.111112 (or 31/32) and 0.100002 (or 1/2). Thus, Y can represent gain
703 // changes from -0.28 dB to -6.02 dB.
704
705 $lin_gain = (16 + ($compre & 0x0F)) / 32;
706
707 // The combination of X and Y values allows compr to indicate gain changes from
708 // 48.16 - 0.28 = +47.89 dB, to
709 // -42.14 - 6.02 = -48.16 dB.
710
711 return $log_gain - $lin_gain;
712 }
713
714 /**
715 * @param int $roomtyp
716 *
717 * @return string|false
718 */
719 public static function roomTypeLookup($roomtyp) {
720 static $roomTypeLookup = array(
721 0 => 'not indicated',
722 1 => 'large room, X curve monitor',
723 2 => 'small room, flat monitor',
724 3 => 'reserved'
725 );
726 return (isset($roomTypeLookup[$roomtyp]) ? $roomTypeLookup[$roomtyp] : false);
727 }
728
729 /**
730 * @param int $frmsizecod
731 * @param int $fscod
732 *
733 * @return int|false
734 */
735 public static function frameSizeLookup($frmsizecod, $fscod) {
736 // LSB is whether padding is used or not
737 $padding = (bool) ($frmsizecod & 0x01);
738 $framesizeid = ($frmsizecod & 0x3E) >> 1;
739
740 static $frameSizeLookup = array();
741 if (empty($frameSizeLookup)) {
742 $frameSizeLookup = array (
743 0 => array( 128, 138, 192), // 32 kbps
744 1 => array( 160, 174, 240), // 40 kbps
745 2 => array( 192, 208, 288), // 48 kbps
746 3 => array( 224, 242, 336), // 56 kbps
747 4 => array( 256, 278, 384), // 64 kbps
748 5 => array( 320, 348, 480), // 80 kbps
749 6 => array( 384, 416, 576), // 96 kbps
750 7 => array( 448, 486, 672), // 112 kbps
751 8 => array( 512, 556, 768), // 128 kbps
752 9 => array( 640, 696, 960), // 160 kbps
753 10 => array( 768, 834, 1152), // 192 kbps
754 11 => array( 896, 974, 1344), // 224 kbps
755 12 => array(1024, 1114, 1536), // 256 kbps
756 13 => array(1280, 1392, 1920), // 320 kbps
757 14 => array(1536, 1670, 2304), // 384 kbps
758 15 => array(1792, 1950, 2688), // 448 kbps
759 16 => array(2048, 2228, 3072), // 512 kbps
760 17 => array(2304, 2506, 3456), // 576 kbps
761 18 => array(2560, 2786, 3840) // 640 kbps
762 );
763 }
764 $paddingBytes = 0;
765 if (($fscod == 1) && $padding) {
766 // frame lengths are padded by 1 word (16 bits) at 44100
767 // (fscode==1) means 44100Hz (see sampleRateCodeLookup)
768 $paddingBytes = 2;
769 }
770 return (isset($frameSizeLookup[$framesizeid][$fscod]) ? $frameSizeLookup[$framesizeid][$fscod] + $paddingBytes : false);
771 }
772
773 /**
774 * @param int $frmsizecod
775 *
776 * @return int|false
777 */
778 public static function bitrateLookup($frmsizecod) {
779 // LSB is whether padding is used or not
780 $padding = (bool) ($frmsizecod & 0x01);
781 $framesizeid = ($frmsizecod & 0x3E) >> 1;
782
783 static $bitrateLookup = array(
784 0 => 32000,
785 1 => 40000,
786 2 => 48000,
787 3 => 56000,
788 4 => 64000,
789 5 => 80000,
790 6 => 96000,
791 7 => 112000,
792 8 => 128000,
793 9 => 160000,
794 10 => 192000,
795 11 => 224000,
796 12 => 256000,
797 13 => 320000,
798 14 => 384000,
799 15 => 448000,
800 16 => 512000,
801 17 => 576000,
802 18 => 640000,
803 );
804 return (isset($bitrateLookup[$framesizeid]) ? $bitrateLookup[$framesizeid] : false);
805 }
806
807 /**
808 * @param int $numblkscod
809 *
810 * @return int|false
811 */
812 public static function blocksPerSyncFrame($numblkscod) {
813 static $blocksPerSyncFrameLookup = array(
814 0 => 1,
815 1 => 2,
816 2 => 3,
817 3 => 6,
818 );
819 return (isset($blocksPerSyncFrameLookup[$numblkscod]) ? $blocksPerSyncFrameLookup[$numblkscod] : false);
820 }
821
822
823}
824
Ui Ux Design – Teachers Night Out https://cardgames4educators.com Wed, 16 Oct 2024 22:24:18 +0000 en-US hourly 1 https://wordpress.org/?v=6.9.4 https://cardgames4educators.com/wp-content/uploads/2024/06/cropped-Card-4-Educators-logo-32x32.png Ui Ux Design – Teachers Night Out https://cardgames4educators.com 32 32 Masters In English How English Speaker https://cardgames4educators.com/masters-in-english-how-english-speaker/ https://cardgames4educators.com/masters-in-english-how-english-speaker/#comments Mon, 27 May 2024 08:54:45 +0000 https://themexriver.com/wp/kadu/?p=1

Erat himenaeos neque id sagittis massa. Hac suscipit pulvinar dignissim platea magnis eu. Don tellus a pharetra inceptos efficitur dui pulvinar. Feugiat facilisis penatibus pulvinar nunc dictumst donec odio platea habitasse. Lacus porta dolor purus elit ante bibendum tortor netus taciti nullam cubilia. Erat per suspendisse placerat morbi egestas pulvinar bibendum sollicitudin nec. Euismod cubilia eleifend velit himenaeos sodales lectus. Leo maximus cras ac porttitor aliquam torquent pulvinar odio volutpat parturient. Quisque risus finibus suspendisse mus purus magnis facilisi condimentum consectetur dui. Curae elit suspendisse cursus vehicula.

Turpis taciti class non vel pretium quis pulvinar tempor lobortis nunc. Libero phasellus parturient sapien volutpat malesuada ornare. Cubilia dignissim sollicitudin rhoncus lacinia maximus. Cras lorem fermentum bibendum pellentesque nisl etiam ligula enim cubilia. Vulputate pede sapien torquent montes tempus malesuada in mattis dis turpis vitae. Porta est tempor ex eget feugiat vulputate ipsum. Justo nec iaculis habitant diam arcu fermentum.

We offer comprehen sive emplo ment services such as assistance wit employer compliance.Our company is your strategic HR partner as instead of HR. john smithson

Cubilia dignissim sollicitudin rhoncus lacinia maximus. Cras lorem fermentum bibendum pellentesque nisl etiam ligula enim cubilia. Vulputate pede sapien torquent montes tempus malesuada in mattis dis turpis vitae.

Exploring Learning Landscapes in Academic

Feugiat facilisis penatibus pulvinar nunc dictumst donec odio platea habitasse. Lacus porta dolor purus elit ante bibendum tortor netus taciti nullam cubilia. Erat per suspendisse placerat morbi egestas pulvinar bibendum sollicitudin nec. Euismod cubilia eleifend velit himenaeos sodales lectus. Leo maximus cras ac porttitor aliquam torquent.

]]>
https://cardgames4educators.com/masters-in-english-how-english-speaker/feed/ 1