Edit File by line
/home/barbar84/public_h.../wp-inclu.../ID3
File: module.audio.ac3.php
<?php
[0] Fix | Delete
[1] Fix | Delete
/////////////////////////////////////////////////////////////////
[2] Fix | Delete
/// getID3() by James Heinrich <info@getid3.org> //
[3] Fix | Delete
// available at https://github.com/JamesHeinrich/getID3 //
[4] Fix | Delete
// or https://www.getid3.org //
[5] Fix | Delete
// or http://getid3.sourceforge.net //
[6] Fix | Delete
// see readme.txt for more details //
[7] Fix | Delete
/////////////////////////////////////////////////////////////////
[8] Fix | Delete
// //
[9] Fix | Delete
// module.audio.ac3.php //
[10] Fix | Delete
// module for analyzing AC-3 (aka Dolby Digital) audio files //
[11] Fix | Delete
// dependencies: NONE //
[12] Fix | Delete
// ///
[13] Fix | Delete
/////////////////////////////////////////////////////////////////
[14] Fix | Delete
[15] Fix | Delete
if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
[16] Fix | Delete
exit;
[17] Fix | Delete
}
[18] Fix | Delete
[19] Fix | Delete
class getid3_ac3 extends getid3_handler
[20] Fix | Delete
{
[21] Fix | Delete
/**
[22] Fix | Delete
* @var array
[23] Fix | Delete
*/
[24] Fix | Delete
private $AC3header = array();
[25] Fix | Delete
[26] Fix | Delete
/**
[27] Fix | Delete
* @var int
[28] Fix | Delete
*/
[29] Fix | Delete
private $BSIoffset = 0;
[30] Fix | Delete
[31] Fix | Delete
const syncword = 0x0B77;
[32] Fix | Delete
[33] Fix | Delete
/**
[34] Fix | Delete
* @return bool
[35] Fix | Delete
*/
[36] Fix | Delete
public function Analyze() {
[37] Fix | Delete
$info = &$this->getid3->info;
[38] Fix | Delete
[39] Fix | Delete
///AH
[40] Fix | Delete
$info['ac3']['raw']['bsi'] = array();
[41] Fix | Delete
$thisfile_ac3 = &$info['ac3'];
[42] Fix | Delete
$thisfile_ac3_raw = &$thisfile_ac3['raw'];
[43] Fix | Delete
$thisfile_ac3_raw_bsi = &$thisfile_ac3_raw['bsi'];
[44] Fix | Delete
[45] Fix | Delete
[46] Fix | Delete
// http://www.atsc.org/standards/a_52a.pdf
[47] Fix | Delete
[48] Fix | Delete
$info['fileformat'] = 'ac3';
[49] Fix | Delete
[50] Fix | Delete
// An AC-3 serial coded audio bit stream is made up of a sequence of synchronization frames
[51] Fix | Delete
// Each synchronization frame contains 6 coded audio blocks (AB), each of which represent 256
[52] Fix | Delete
// new audio samples per channel. A synchronization information (SI) header at the beginning
[53] Fix | Delete
// of each frame contains information needed to acquire and maintain synchronization. A
[54] Fix | Delete
// bit stream information (BSI) header follows SI, and contains parameters describing the coded
[55] Fix | Delete
// audio service. The coded audio blocks may be followed by an auxiliary data (Aux) field. At the
[56] Fix | Delete
// end of each frame is an error check field that includes a CRC word for error detection. An
[57] Fix | Delete
// additional CRC word is located in the SI header, the use of which, by a decoder, is optional.
[58] Fix | Delete
//
[59] Fix | Delete
// syncinfo() | bsi() | AB0 | AB1 | AB2 | AB3 | AB4 | AB5 | Aux | CRC
[60] Fix | Delete
[61] Fix | Delete
// syncinfo() {
[62] Fix | Delete
// syncword 16
[63] Fix | Delete
// crc1 16
[64] Fix | Delete
// fscod 2
[65] Fix | Delete
// frmsizecod 6
[66] Fix | Delete
// } /* end of syncinfo */
[67] Fix | Delete
[68] Fix | Delete
$this->fseek($info['avdataoffset']);
[69] Fix | Delete
$tempAC3header = $this->fread(100); // should be enough to cover all data, there are some variable-length fields...?
[70] Fix | Delete
$this->AC3header['syncinfo'] = getid3_lib::BigEndian2Int(substr($tempAC3header, 0, 2));
[71] Fix | Delete
$this->AC3header['bsi'] = getid3_lib::BigEndian2Bin(substr($tempAC3header, 2));
[72] Fix | Delete
$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
[73] Fix | Delete
unset($tempAC3header);
[74] Fix | Delete
[75] Fix | Delete
if ($this->AC3header['syncinfo'] !== self::syncword) {
[76] Fix | Delete
if (!$this->isDependencyFor('matroska')) {
[77] Fix | Delete
unset($info['fileformat'], $info['ac3']);
[78] Fix | Delete
return $this->error('Expecting "'.dechex(self::syncword).'" at offset '.$info['avdataoffset'].', found "'.dechex($this->AC3header['syncinfo']).'"');
[79] Fix | Delete
}
[80] Fix | Delete
}
[81] Fix | Delete
[82] Fix | Delete
$info['audio']['dataformat'] = 'ac3';
[83] Fix | Delete
$info['audio']['bitrate_mode'] = 'cbr';
[84] Fix | Delete
$info['audio']['lossless'] = false;
[85] Fix | Delete
[86] Fix | Delete
if ($thisfile_ac3_raw_bsi['bsid'] <= 8) {
[87] Fix | Delete
[88] Fix | Delete
$thisfile_ac3_raw_bsi['crc1'] = getid3_lib::Bin2Dec($this->readHeaderBSI(16));
[89] Fix | Delete
$thisfile_ac3_raw_bsi['fscod'] = $this->readHeaderBSI(2); // 5.4.1.3
[90] Fix | Delete
$thisfile_ac3_raw_bsi['frmsizecod'] = $this->readHeaderBSI(6); // 5.4.1.4
[91] Fix | Delete
if ($thisfile_ac3_raw_bsi['frmsizecod'] > 37) { // binary: 100101 - see Table 5.18 Frame Size Code Table (1 word = 16 bits)
[92] Fix | Delete
$this->warning('Unexpected ac3.bsi.frmsizecod value: '.$thisfile_ac3_raw_bsi['frmsizecod'].', bitrate not set correctly');
[93] Fix | Delete
}
[94] Fix | Delete
[95] Fix | Delete
$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
[96] Fix | Delete
$thisfile_ac3_raw_bsi['bsmod'] = $this->readHeaderBSI(3);
[97] Fix | Delete
$thisfile_ac3_raw_bsi['acmod'] = $this->readHeaderBSI(3);
[98] Fix | Delete
[99] Fix | Delete
if ($thisfile_ac3_raw_bsi['acmod'] & 0x01) {
[100] Fix | Delete
// If the lsb of acmod is a 1, center channel is in use and cmixlev follows in the bit stream.
[101] Fix | Delete
$thisfile_ac3_raw_bsi['cmixlev'] = $this->readHeaderBSI(2);
[102] Fix | Delete
$thisfile_ac3['center_mix_level'] = self::centerMixLevelLookup($thisfile_ac3_raw_bsi['cmixlev']);
[103] Fix | Delete
}
[104] Fix | Delete
[105] Fix | Delete
if ($thisfile_ac3_raw_bsi['acmod'] & 0x04) {
[106] Fix | Delete
// If the msb of acmod is a 1, surround channels are in use and surmixlev follows in the bit stream.
[107] Fix | Delete
$thisfile_ac3_raw_bsi['surmixlev'] = $this->readHeaderBSI(2);
[108] Fix | Delete
$thisfile_ac3['surround_mix_level'] = self::surroundMixLevelLookup($thisfile_ac3_raw_bsi['surmixlev']);
[109] Fix | Delete
}
[110] Fix | Delete
[111] Fix | Delete
if ($thisfile_ac3_raw_bsi['acmod'] == 0x02) {
[112] Fix | Delete
// When operating in the two channel mode, this 2-bit code indicates whether or not the program has been encoded in Dolby Surround.
[113] Fix | Delete
$thisfile_ac3_raw_bsi['dsurmod'] = $this->readHeaderBSI(2);
[114] Fix | Delete
$thisfile_ac3['dolby_surround_mode'] = self::dolbySurroundModeLookup($thisfile_ac3_raw_bsi['dsurmod']);
[115] Fix | Delete
}
[116] Fix | Delete
[117] Fix | Delete
$thisfile_ac3_raw_bsi['flags']['lfeon'] = (bool) $this->readHeaderBSI(1);
[118] Fix | Delete
[119] Fix | Delete
// This indicates how far the average dialogue level is below digital 100 percent. Valid values are 1-31.
[120] Fix | Delete
// 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.
[121] Fix | Delete
$thisfile_ac3_raw_bsi['dialnorm'] = $this->readHeaderBSI(5); // 5.4.2.8 dialnorm: Dialogue Normalization, 5 Bits
[122] Fix | Delete
[123] Fix | Delete
$thisfile_ac3_raw_bsi['flags']['compr'] = (bool) $this->readHeaderBSI(1); // 5.4.2.9 compre: Compression Gain Word Exists, 1 Bit
[124] Fix | Delete
if ($thisfile_ac3_raw_bsi['flags']['compr']) {
[125] Fix | Delete
$thisfile_ac3_raw_bsi['compr'] = $this->readHeaderBSI(8); // 5.4.2.10 compr: Compression Gain Word, 8 Bits
[126] Fix | Delete
$thisfile_ac3['heavy_compression'] = self::heavyCompression($thisfile_ac3_raw_bsi['compr']);
[127] Fix | Delete
}
[128] Fix | Delete
[129] Fix | Delete
$thisfile_ac3_raw_bsi['flags']['langcod'] = (bool) $this->readHeaderBSI(1); // 5.4.2.11 langcode: Language Code Exists, 1 Bit
[130] Fix | Delete
if ($thisfile_ac3_raw_bsi['flags']['langcod']) {
[131] Fix | Delete
$thisfile_ac3_raw_bsi['langcod'] = $this->readHeaderBSI(8); // 5.4.2.12 langcod: Language Code, 8 Bits
[132] Fix | Delete
}
[133] Fix | Delete
[134] Fix | Delete
$thisfile_ac3_raw_bsi['flags']['audprodinfo'] = (bool) $this->readHeaderBSI(1); // 5.4.2.13 audprodie: Audio Production Information Exists, 1 Bit
[135] Fix | Delete
if ($thisfile_ac3_raw_bsi['flags']['audprodinfo']) {
[136] Fix | Delete
$thisfile_ac3_raw_bsi['mixlevel'] = $this->readHeaderBSI(5); // 5.4.2.14 mixlevel: Mixing Level, 5 Bits
[137] Fix | Delete
$thisfile_ac3_raw_bsi['roomtyp'] = $this->readHeaderBSI(2); // 5.4.2.15 roomtyp: Room Type, 2 Bits
[138] Fix | Delete
[139] Fix | Delete
$thisfile_ac3['mixing_level'] = (80 + $thisfile_ac3_raw_bsi['mixlevel']).'dB';
[140] Fix | Delete
$thisfile_ac3['room_type'] = self::roomTypeLookup($thisfile_ac3_raw_bsi['roomtyp']);
[141] Fix | Delete
}
[142] Fix | Delete
[143] Fix | Delete
[144] Fix | Delete
$thisfile_ac3_raw_bsi['dialnorm2'] = $this->readHeaderBSI(5); // 5.4.2.16 dialnorm2: Dialogue Normalization, ch2, 5 Bits
[145] Fix | Delete
$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.
[146] Fix | Delete
[147] Fix | Delete
$thisfile_ac3_raw_bsi['flags']['compr2'] = (bool) $this->readHeaderBSI(1); // 5.4.2.17 compr2e: Compression Gain Word Exists, ch2, 1 Bit
[148] Fix | Delete
if ($thisfile_ac3_raw_bsi['flags']['compr2']) {
[149] Fix | Delete
$thisfile_ac3_raw_bsi['compr2'] = $this->readHeaderBSI(8); // 5.4.2.18 compr2: Compression Gain Word, ch2, 8 Bits
[150] Fix | Delete
$thisfile_ac3['heavy_compression2'] = self::heavyCompression($thisfile_ac3_raw_bsi['compr2']);
[151] Fix | Delete
}
[152] Fix | Delete
[153] Fix | Delete
$thisfile_ac3_raw_bsi['flags']['langcod2'] = (bool) $this->readHeaderBSI(1); // 5.4.2.19 langcod2e: Language Code Exists, ch2, 1 Bit
[154] Fix | Delete
if ($thisfile_ac3_raw_bsi['flags']['langcod2']) {
[155] Fix | Delete
$thisfile_ac3_raw_bsi['langcod2'] = $this->readHeaderBSI(8); // 5.4.2.20 langcod2: Language Code, ch2, 8 Bits
[156] Fix | Delete
}
[157] Fix | Delete
[158] Fix | Delete
$thisfile_ac3_raw_bsi['flags']['audprodinfo2'] = (bool) $this->readHeaderBSI(1); // 5.4.2.21 audprodi2e: Audio Production Information Exists, ch2, 1 Bit
[159] Fix | Delete
if ($thisfile_ac3_raw_bsi['flags']['audprodinfo2']) {
[160] Fix | Delete
$thisfile_ac3_raw_bsi['mixlevel2'] = $this->readHeaderBSI(5); // 5.4.2.22 mixlevel2: Mixing Level, ch2, 5 Bits
[161] Fix | Delete
$thisfile_ac3_raw_bsi['roomtyp2'] = $this->readHeaderBSI(2); // 5.4.2.23 roomtyp2: Room Type, ch2, 2 Bits
[162] Fix | Delete
[163] Fix | Delete
$thisfile_ac3['mixing_level2'] = (80 + $thisfile_ac3_raw_bsi['mixlevel2']).'dB';
[164] Fix | Delete
$thisfile_ac3['room_type2'] = self::roomTypeLookup($thisfile_ac3_raw_bsi['roomtyp2']);
[165] Fix | Delete
}
[166] Fix | Delete
[167] Fix | Delete
$thisfile_ac3_raw_bsi['copyright'] = (bool) $this->readHeaderBSI(1); // 5.4.2.24 copyrightb: Copyright Bit, 1 Bit
[168] Fix | Delete
[169] Fix | Delete
$thisfile_ac3_raw_bsi['original'] = (bool) $this->readHeaderBSI(1); // 5.4.2.25 origbs: Original Bit Stream, 1 Bit
[170] Fix | Delete
[171] Fix | Delete
$thisfile_ac3_raw_bsi['flags']['timecod1'] = $this->readHeaderBSI(2); // 5.4.2.26 timecod1e, timcode2e: Time Code (first and second) Halves Exist, 2 Bits
[172] Fix | Delete
if ($thisfile_ac3_raw_bsi['flags']['timecod1'] & 0x01) {
[173] Fix | Delete
$thisfile_ac3_raw_bsi['timecod1'] = $this->readHeaderBSI(14); // 5.4.2.27 timecod1: Time code first half, 14 bits
[174] Fix | Delete
$thisfile_ac3['timecode1'] = 0;
[175] Fix | Delete
$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
[176] Fix | Delete
$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
[177] Fix | Delete
$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)
[178] Fix | Delete
}
[179] Fix | Delete
if ($thisfile_ac3_raw_bsi['flags']['timecod1'] & 0x02) {
[180] Fix | Delete
$thisfile_ac3_raw_bsi['timecod2'] = $this->readHeaderBSI(14); // 5.4.2.28 timecod2: Time code second half, 14 bits
[181] Fix | Delete
$thisfile_ac3['timecode2'] = 0;
[182] Fix | Delete
$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)
[183] Fix | Delete
$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)
[184] Fix | Delete
$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
[185] Fix | Delete
}
[186] Fix | Delete
[187] Fix | Delete
$thisfile_ac3_raw_bsi['flags']['addbsi'] = (bool) $this->readHeaderBSI(1);
[188] Fix | Delete
if ($thisfile_ac3_raw_bsi['flags']['addbsi']) {
[189] Fix | Delete
$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.
[190] Fix | Delete
[191] Fix | Delete
$this->AC3header['bsi'] .= getid3_lib::BigEndian2Bin($this->fread($thisfile_ac3_raw_bsi['addbsi_length']));
[192] Fix | Delete
[193] Fix | Delete
$thisfile_ac3_raw_bsi['addbsi_data'] = substr($this->AC3header['bsi'], $this->BSIoffset, $thisfile_ac3_raw_bsi['addbsi_length'] * 8);
[194] Fix | Delete
$this->BSIoffset += $thisfile_ac3_raw_bsi['addbsi_length'] * 8;
[195] Fix | Delete
}
[196] Fix | Delete
[197] Fix | Delete
[198] Fix | Delete
} elseif ($thisfile_ac3_raw_bsi['bsid'] <= 16) { // E-AC3
[199] Fix | Delete
[200] Fix | Delete
[201] Fix | Delete
$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.');
[202] Fix | Delete
$info['audio']['dataformat'] = 'eac3';
[203] Fix | Delete
[204] Fix | Delete
$thisfile_ac3_raw_bsi['strmtyp'] = $this->readHeaderBSI(2);
[205] Fix | Delete
$thisfile_ac3_raw_bsi['substreamid'] = $this->readHeaderBSI(3);
[206] Fix | Delete
$thisfile_ac3_raw_bsi['frmsiz'] = $this->readHeaderBSI(11);
[207] Fix | Delete
$thisfile_ac3_raw_bsi['fscod'] = $this->readHeaderBSI(2);
[208] Fix | Delete
if ($thisfile_ac3_raw_bsi['fscod'] == 3) {
[209] Fix | Delete
$thisfile_ac3_raw_bsi['fscod2'] = $this->readHeaderBSI(2);
[210] Fix | Delete
$thisfile_ac3_raw_bsi['numblkscod'] = 3; // six blocks per syncframe
[211] Fix | Delete
} else {
[212] Fix | Delete
$thisfile_ac3_raw_bsi['numblkscod'] = $this->readHeaderBSI(2);
[213] Fix | Delete
}
[214] Fix | Delete
$thisfile_ac3['bsi']['blocks_per_sync_frame'] = self::blocksPerSyncFrame($thisfile_ac3_raw_bsi['numblkscod']);
[215] Fix | Delete
$thisfile_ac3_raw_bsi['acmod'] = $this->readHeaderBSI(3);
[216] Fix | Delete
$thisfile_ac3_raw_bsi['flags']['lfeon'] = (bool) $this->readHeaderBSI(1);
[217] Fix | Delete
$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
[218] Fix | Delete
$thisfile_ac3_raw_bsi['dialnorm'] = $this->readHeaderBSI(5);
[219] Fix | Delete
$thisfile_ac3_raw_bsi['flags']['compr'] = (bool) $this->readHeaderBSI(1);
[220] Fix | Delete
if ($thisfile_ac3_raw_bsi['flags']['compr']) {
[221] Fix | Delete
$thisfile_ac3_raw_bsi['compr'] = $this->readHeaderBSI(8);
[222] Fix | Delete
}
[223] Fix | Delete
if ($thisfile_ac3_raw_bsi['acmod'] == 0) { // if 1+1 mode (dual mono, so some items need a second value)
[224] Fix | Delete
$thisfile_ac3_raw_bsi['dialnorm2'] = $this->readHeaderBSI(5);
[225] Fix | Delete
$thisfile_ac3_raw_bsi['flags']['compr2'] = (bool) $this->readHeaderBSI(1);
[226] Fix | Delete
if ($thisfile_ac3_raw_bsi['flags']['compr2']) {
[227] Fix | Delete
$thisfile_ac3_raw_bsi['compr2'] = $this->readHeaderBSI(8);
[228] Fix | Delete
}
[229] Fix | Delete
}
[230] Fix | Delete
if ($thisfile_ac3_raw_bsi['strmtyp'] == 1) { // if dependent stream
[231] Fix | Delete
$thisfile_ac3_raw_bsi['flags']['chanmap'] = (bool) $this->readHeaderBSI(1);
[232] Fix | Delete
if ($thisfile_ac3_raw_bsi['flags']['chanmap']) {
[233] Fix | Delete
$thisfile_ac3_raw_bsi['chanmap'] = $this->readHeaderBSI(8);
[234] Fix | Delete
}
[235] Fix | Delete
}
[236] Fix | Delete
$thisfile_ac3_raw_bsi['flags']['mixmdat'] = (bool) $this->readHeaderBSI(1);
[237] Fix | Delete
if ($thisfile_ac3_raw_bsi['flags']['mixmdat']) { // Mixing metadata
[238] Fix | Delete
if ($thisfile_ac3_raw_bsi['acmod'] > 2) { // if more than 2 channels
[239] Fix | Delete
$thisfile_ac3_raw_bsi['dmixmod'] = $this->readHeaderBSI(2);
[240] Fix | Delete
}
[241] Fix | Delete
if (($thisfile_ac3_raw_bsi['acmod'] & 0x01) && ($thisfile_ac3_raw_bsi['acmod'] > 2)) { // if three front channels exist
[242] Fix | Delete
$thisfile_ac3_raw_bsi['ltrtcmixlev'] = $this->readHeaderBSI(3);
[243] Fix | Delete
$thisfile_ac3_raw_bsi['lorocmixlev'] = $this->readHeaderBSI(3);
[244] Fix | Delete
}
[245] Fix | Delete
if ($thisfile_ac3_raw_bsi['acmod'] & 0x04) { // if a surround channel exists
[246] Fix | Delete
$thisfile_ac3_raw_bsi['ltrtsurmixlev'] = $this->readHeaderBSI(3);
[247] Fix | Delete
$thisfile_ac3_raw_bsi['lorosurmixlev'] = $this->readHeaderBSI(3);
[248] Fix | Delete
}
[249] Fix | Delete
if ($thisfile_ac3_raw_bsi['flags']['lfeon']) { // if the LFE channel exists
[250] Fix | Delete
$thisfile_ac3_raw_bsi['flags']['lfemixlevcod'] = (bool) $this->readHeaderBSI(1);
[251] Fix | Delete
if ($thisfile_ac3_raw_bsi['flags']['lfemixlevcod']) {
[252] Fix | Delete
$thisfile_ac3_raw_bsi['lfemixlevcod'] = $this->readHeaderBSI(5);
[253] Fix | Delete
}
[254] Fix | Delete
}
[255] Fix | Delete
if ($thisfile_ac3_raw_bsi['strmtyp'] == 0) { // if independent stream
[256] Fix | Delete
$thisfile_ac3_raw_bsi['flags']['pgmscl'] = (bool) $this->readHeaderBSI(1);
[257] Fix | Delete
if ($thisfile_ac3_raw_bsi['flags']['pgmscl']) {
[258] Fix | Delete
$thisfile_ac3_raw_bsi['pgmscl'] = $this->readHeaderBSI(6);
[259] Fix | Delete
}
[260] Fix | Delete
if ($thisfile_ac3_raw_bsi['acmod'] == 0) { // if 1+1 mode (dual mono, so some items need a second value)
[261] Fix | Delete
$thisfile_ac3_raw_bsi['flags']['pgmscl2'] = (bool) $this->readHeaderBSI(1);
[262] Fix | Delete
if ($thisfile_ac3_raw_bsi['flags']['pgmscl2']) {
[263] Fix | Delete
$thisfile_ac3_raw_bsi['pgmscl2'] = $this->readHeaderBSI(6);
[264] Fix | Delete
}
[265] Fix | Delete
}
[266] Fix | Delete
$thisfile_ac3_raw_bsi['flags']['extpgmscl'] = (bool) $this->readHeaderBSI(1);
[267] Fix | Delete
if ($thisfile_ac3_raw_bsi['flags']['extpgmscl']) {
[268] Fix | Delete
$thisfile_ac3_raw_bsi['extpgmscl'] = $this->readHeaderBSI(6);
[269] Fix | Delete
}
[270] Fix | Delete
$thisfile_ac3_raw_bsi['mixdef'] = $this->readHeaderBSI(2);
[271] Fix | Delete
if ($thisfile_ac3_raw_bsi['mixdef'] == 1) { // mixing option 2
[272] Fix | Delete
$thisfile_ac3_raw_bsi['premixcmpsel'] = (bool) $this->readHeaderBSI(1);
[273] Fix | Delete
$thisfile_ac3_raw_bsi['drcsrc'] = (bool) $this->readHeaderBSI(1);
[274] Fix | Delete
$thisfile_ac3_raw_bsi['premixcmpscl'] = $this->readHeaderBSI(3);
[275] Fix | Delete
} elseif ($thisfile_ac3_raw_bsi['mixdef'] == 2) { // mixing option 3
[276] Fix | Delete
$thisfile_ac3_raw_bsi['mixdata'] = $this->readHeaderBSI(12);
[277] Fix | Delete
} elseif ($thisfile_ac3_raw_bsi['mixdef'] == 3) { // mixing option 4
[278] Fix | Delete
$mixdefbitsread = 0;
[279] Fix | Delete
$thisfile_ac3_raw_bsi['mixdeflen'] = $this->readHeaderBSI(5); $mixdefbitsread += 5;
[280] Fix | Delete
$thisfile_ac3_raw_bsi['flags']['mixdata2'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
[281] Fix | Delete
if ($thisfile_ac3_raw_bsi['flags']['mixdata2']) {
[282] Fix | Delete
$thisfile_ac3_raw_bsi['premixcmpsel'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
[283] Fix | Delete
$thisfile_ac3_raw_bsi['drcsrc'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
[284] Fix | Delete
$thisfile_ac3_raw_bsi['premixcmpscl'] = $this->readHeaderBSI(3); $mixdefbitsread += 3;
[285] Fix | Delete
$thisfile_ac3_raw_bsi['flags']['extpgmlscl'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
[286] Fix | Delete
if ($thisfile_ac3_raw_bsi['flags']['extpgmlscl']) {
[287] Fix | Delete
$thisfile_ac3_raw_bsi['extpgmlscl'] = $this->readHeaderBSI(4); $mixdefbitsread += 4;
[288] Fix | Delete
}
[289] Fix | Delete
$thisfile_ac3_raw_bsi['flags']['extpgmcscl'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
[290] Fix | Delete
if ($thisfile_ac3_raw_bsi['flags']['extpgmcscl']) {
[291] Fix | Delete
$thisfile_ac3_raw_bsi['extpgmcscl'] = $this->readHeaderBSI(4); $mixdefbitsread += 4;
[292] Fix | Delete
}
[293] Fix | Delete
$thisfile_ac3_raw_bsi['flags']['extpgmrscl'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
[294] Fix | Delete
if ($thisfile_ac3_raw_bsi['flags']['extpgmrscl']) {
[295] Fix | Delete
$thisfile_ac3_raw_bsi['extpgmrscl'] = $this->readHeaderBSI(4);
[296] Fix | Delete
}
[297] Fix | Delete
$thisfile_ac3_raw_bsi['flags']['extpgmlsscl'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
[298] Fix | Delete
if ($thisfile_ac3_raw_bsi['flags']['extpgmlsscl']) {
[299] Fix | Delete
$thisfile_ac3_raw_bsi['extpgmlsscl'] = $this->readHeaderBSI(4); $mixdefbitsread += 4;
[300] Fix | Delete
}
[301] Fix | Delete
$thisfile_ac3_raw_bsi['flags']['extpgmrsscl'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
[302] Fix | Delete
if ($thisfile_ac3_raw_bsi['flags']['extpgmrsscl']) {
[303] Fix | Delete
$thisfile_ac3_raw_bsi['extpgmrsscl'] = $this->readHeaderBSI(4); $mixdefbitsread += 4;
[304] Fix | Delete
}
[305] Fix | Delete
$thisfile_ac3_raw_bsi['flags']['extpgmlfescl'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
[306] Fix | Delete
if ($thisfile_ac3_raw_bsi['flags']['extpgmlfescl']) {
[307] Fix | Delete
$thisfile_ac3_raw_bsi['extpgmlfescl'] = $this->readHeaderBSI(4); $mixdefbitsread += 4;
[308] Fix | Delete
}
[309] Fix | Delete
$thisfile_ac3_raw_bsi['flags']['dmixscl'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
[310] Fix | Delete
if ($thisfile_ac3_raw_bsi['flags']['dmixscl']) {
[311] Fix | Delete
$thisfile_ac3_raw_bsi['dmixscl'] = $this->readHeaderBSI(4); $mixdefbitsread += 4;
[312] Fix | Delete
}
[313] Fix | Delete
$thisfile_ac3_raw_bsi['flags']['addch'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
[314] Fix | Delete
if ($thisfile_ac3_raw_bsi['flags']['addch']) {
[315] Fix | Delete
$thisfile_ac3_raw_bsi['flags']['extpgmaux1scl'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
[316] Fix | Delete
if ($thisfile_ac3_raw_bsi['flags']['extpgmaux1scl']) {
[317] Fix | Delete
$thisfile_ac3_raw_bsi['extpgmaux1scl'] = $this->readHeaderBSI(4); $mixdefbitsread += 4;
[318] Fix | Delete
}
[319] Fix | Delete
$thisfile_ac3_raw_bsi['flags']['extpgmaux2scl'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
[320] Fix | Delete
if ($thisfile_ac3_raw_bsi['flags']['extpgmaux2scl']) {
[321] Fix | Delete
$thisfile_ac3_raw_bsi['extpgmaux2scl'] = $this->readHeaderBSI(4); $mixdefbitsread += 4;
[322] Fix | Delete
}
[323] Fix | Delete
}
[324] Fix | Delete
}
[325] Fix | Delete
$thisfile_ac3_raw_bsi['flags']['mixdata3'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
[326] Fix | Delete
if ($thisfile_ac3_raw_bsi['flags']['mixdata3']) {
[327] Fix | Delete
$thisfile_ac3_raw_bsi['spchdat'] = $this->readHeaderBSI(5); $mixdefbitsread += 5;
[328] Fix | Delete
$thisfile_ac3_raw_bsi['flags']['addspchdat'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
[329] Fix | Delete
if ($thisfile_ac3_raw_bsi['flags']['addspchdat']) {
[330] Fix | Delete
$thisfile_ac3_raw_bsi['spchdat1'] = $this->readHeaderBSI(5); $mixdefbitsread += 5;
[331] Fix | Delete
$thisfile_ac3_raw_bsi['spchan1att'] = $this->readHeaderBSI(2); $mixdefbitsread += 2;
[332] Fix | Delete
$thisfile_ac3_raw_bsi['flags']['addspchdat1'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
[333] Fix | Delete
if ($thisfile_ac3_raw_bsi['flags']['addspchdat1']) {
[334] Fix | Delete
$thisfile_ac3_raw_bsi['spchdat2'] = $this->readHeaderBSI(5); $mixdefbitsread += 5;
[335] Fix | Delete
$thisfile_ac3_raw_bsi['spchan2att'] = $this->readHeaderBSI(3); $mixdefbitsread += 3;
[336] Fix | Delete
}
[337] Fix | Delete
}
[338] Fix | Delete
}
[339] Fix | Delete
$mixdata_bits = (8 * ($thisfile_ac3_raw_bsi['mixdeflen'] + 2)) - $mixdefbitsread;
[340] Fix | Delete
$mixdata_fill = (($mixdata_bits % 8) ? 8 - ($mixdata_bits % 8) : 0);
[341] Fix | Delete
$thisfile_ac3_raw_bsi['mixdata'] = $this->readHeaderBSI($mixdata_bits);
[342] Fix | Delete
$thisfile_ac3_raw_bsi['mixdatafill'] = $this->readHeaderBSI($mixdata_fill);
[343] Fix | Delete
unset($mixdefbitsread, $mixdata_bits, $mixdata_fill);
[344] Fix | Delete
}
[345] Fix | Delete
if ($thisfile_ac3_raw_bsi['acmod'] < 2) { // if mono or dual mono source
[346] Fix | Delete
$thisfile_ac3_raw_bsi['flags']['paninfo'] = (bool) $this->readHeaderBSI(1);
[347] Fix | Delete
if ($thisfile_ac3_raw_bsi['flags']['paninfo']) {
[348] Fix | Delete
$thisfile_ac3_raw_bsi['panmean'] = $this->readHeaderBSI(8);
[349] Fix | Delete
$thisfile_ac3_raw_bsi['paninfo'] = $this->readHeaderBSI(6);
[350] Fix | Delete
}
[351] Fix | Delete
if ($thisfile_ac3_raw_bsi['acmod'] == 0) { // if 1+1 mode (dual mono, so some items need a second value)
[352] Fix | Delete
$thisfile_ac3_raw_bsi['flags']['paninfo2'] = (bool) $this->readHeaderBSI(1);
[353] Fix | Delete
if ($thisfile_ac3_raw_bsi['flags']['paninfo2']) {
[354] Fix | Delete
$thisfile_ac3_raw_bsi['panmean2'] = $this->readHeaderBSI(8);
[355] Fix | Delete
$thisfile_ac3_raw_bsi['paninfo2'] = $this->readHeaderBSI(6);
[356] Fix | Delete
}
[357] Fix | Delete
}
[358] Fix | Delete
}
[359] Fix | Delete
$thisfile_ac3_raw_bsi['flags']['frmmixcfginfo'] = (bool) $this->readHeaderBSI(1);
[360] Fix | Delete
if ($thisfile_ac3_raw_bsi['flags']['frmmixcfginfo']) { // mixing configuration information
[361] Fix | Delete
if ($thisfile_ac3_raw_bsi['numblkscod'] == 0) {
[362] Fix | Delete
$thisfile_ac3_raw_bsi['blkmixcfginfo'][0] = $this->readHeaderBSI(5);
[363] Fix | Delete
} else {
[364] Fix | Delete
for ($blk = 0; $blk < $thisfile_ac3_raw_bsi['numblkscod']; $blk++) {
[365] Fix | Delete
$thisfile_ac3_raw_bsi['flags']['blkmixcfginfo'.$blk] = (bool) $this->readHeaderBSI(1);
[366] Fix | Delete
if ($thisfile_ac3_raw_bsi['flags']['blkmixcfginfo'.$blk]) { // mixing configuration information
[367] Fix | Delete
$thisfile_ac3_raw_bsi['blkmixcfginfo'][$blk] = $this->readHeaderBSI(5);
[368] Fix | Delete
}
[369] Fix | Delete
}
[370] Fix | Delete
}
[371] Fix | Delete
}
[372] Fix | Delete
}
[373] Fix | Delete
}
[374] Fix | Delete
$thisfile_ac3_raw_bsi['flags']['infomdat'] = (bool) $this->readHeaderBSI(1);
[375] Fix | Delete
if ($thisfile_ac3_raw_bsi['flags']['infomdat']) { // Informational metadata
[376] Fix | Delete
$thisfile_ac3_raw_bsi['bsmod'] = $this->readHeaderBSI(3);
[377] Fix | Delete
$thisfile_ac3_raw_bsi['flags']['copyrightb'] = (bool) $this->readHeaderBSI(1);
[378] Fix | Delete
$thisfile_ac3_raw_bsi['flags']['origbs'] = (bool) $this->readHeaderBSI(1);
[379] Fix | Delete
if ($thisfile_ac3_raw_bsi['acmod'] == 2) { // if in 2/0 mode
[380] Fix | Delete
$thisfile_ac3_raw_bsi['dsurmod'] = $this->readHeaderBSI(2);
[381] Fix | Delete
$thisfile_ac3_raw_bsi['dheadphonmod'] = $this->readHeaderBSI(2);
[382] Fix | Delete
}
[383] Fix | Delete
if ($thisfile_ac3_raw_bsi['acmod'] >= 6) { // if both surround channels exist
[384] Fix | Delete
$thisfile_ac3_raw_bsi['dsurexmod'] = $this->readHeaderBSI(2);
[385] Fix | Delete
}
[386] Fix | Delete
$thisfile_ac3_raw_bsi['flags']['audprodi'] = (bool) $this->readHeaderBSI(1);
[387] Fix | Delete
if ($thisfile_ac3_raw_bsi['flags']['audprodi']) {
[388] Fix | Delete
$thisfile_ac3_raw_bsi['mixlevel'] = $this->readHeaderBSI(5);
[389] Fix | Delete
$thisfile_ac3_raw_bsi['roomtyp'] = $this->readHeaderBSI(2);
[390] Fix | Delete
$thisfile_ac3_raw_bsi['flags']['adconvtyp'] = (bool) $this->readHeaderBSI(1);
[391] Fix | Delete
}
[392] Fix | Delete
if ($thisfile_ac3_raw_bsi['acmod'] == 0) { // if 1+1 mode (dual mono, so some items need a second value)
[393] Fix | Delete
$thisfile_ac3_raw_bsi['flags']['audprodi2'] = (bool) $this->readHeaderBSI(1);
[394] Fix | Delete
if ($thisfile_ac3_raw_bsi['flags']['audprodi2']) {
[395] Fix | Delete
$thisfile_ac3_raw_bsi['mixlevel2'] = $this->readHeaderBSI(5);
[396] Fix | Delete
$thisfile_ac3_raw_bsi['roomtyp2'] = $this->readHeaderBSI(2);
[397] Fix | Delete
$thisfile_ac3_raw_bsi['flags']['adconvtyp2'] = (bool) $this->readHeaderBSI(1);
[398] Fix | Delete
}
[399] Fix | Delete
}
[400] Fix | Delete
if ($thisfile_ac3_raw_bsi['fscod'] < 3) { // if not half sample rate
[401] Fix | Delete
$thisfile_ac3_raw_bsi['flags']['sourcefscod'] = (bool) $this->readHeaderBSI(1);
[402] Fix | Delete
}
[403] Fix | Delete
}
[404] Fix | Delete
if (($thisfile_ac3_raw_bsi['strmtyp'] == 0) && ($thisfile_ac3_raw_bsi['numblkscod'] != 3)) { // if both surround channels exist
[405] Fix | Delete
$thisfile_ac3_raw_bsi['flags']['convsync'] = (bool) $this->readHeaderBSI(1);
[406] Fix | Delete
}
[407] Fix | Delete
if ($thisfile_ac3_raw_bsi['strmtyp'] == 2) { // if bit stream converted from AC-3
[408] Fix | Delete
if ($thisfile_ac3_raw_bsi['numblkscod'] != 3) { // 6 blocks per syncframe
[409] Fix | Delete
$thisfile_ac3_raw_bsi['flags']['blkid'] = 1;
[410] Fix | Delete
} else {
[411] Fix | Delete
$thisfile_ac3_raw_bsi['flags']['blkid'] = (bool) $this->readHeaderBSI(1);
[412] Fix | Delete
}
[413] Fix | Delete
if ($thisfile_ac3_raw_bsi['flags']['blkid']) {
[414] Fix | Delete
$thisfile_ac3_raw_bsi['frmsizecod'] = $this->readHeaderBSI(6);
[415] Fix | Delete
}
[416] Fix | Delete
}
[417] Fix | Delete
$thisfile_ac3_raw_bsi['flags']['addbsi'] = (bool) $this->readHeaderBSI(1);
[418] Fix | Delete
if ($thisfile_ac3_raw_bsi['flags']['addbsi']) {
[419] Fix | Delete
$thisfile_ac3_raw_bsi['addbsil'] = $this->readHeaderBSI(6);
[420] Fix | Delete
$thisfile_ac3_raw_bsi['addbsi'] = $this->readHeaderBSI(($thisfile_ac3_raw_bsi['addbsil'] + 1) * 8);
[421] Fix | Delete
}
[422] Fix | Delete
[423] Fix | Delete
} else {
[424] Fix | Delete
[425] Fix | Delete
$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.');
[426] Fix | Delete
unset($info['ac3']);
[427] Fix | Delete
return false;
[428] Fix | Delete
[429] Fix | Delete
}
[430] Fix | Delete
[431] Fix | Delete
if (isset($thisfile_ac3_raw_bsi['fscod2'])) {
[432] Fix | Delete
$thisfile_ac3['sample_rate'] = self::sampleRateCodeLookup2($thisfile_ac3_raw_bsi['fscod2']);
[433] Fix | Delete
} else {
[434] Fix | Delete
$thisfile_ac3['sample_rate'] = self::sampleRateCodeLookup($thisfile_ac3_raw_bsi['fscod']);
[435] Fix | Delete
}
[436] Fix | Delete
if ($thisfile_ac3_raw_bsi['fscod'] <= 3) {
[437] Fix | Delete
$info['audio']['sample_rate'] = $thisfile_ac3['sample_rate'];
[438] Fix | Delete
} else {
[439] Fix | Delete
$this->warning('Unexpected ac3.bsi.fscod value: '.$thisfile_ac3_raw_bsi['fscod']);
[440] Fix | Delete
}
[441] Fix | Delete
if (isset($thisfile_ac3_raw_bsi['frmsizecod'])) {
[442] Fix | Delete
$thisfile_ac3['frame_length'] = self::frameSizeLookup($thisfile_ac3_raw_bsi['frmsizecod'], $thisfile_ac3_raw_bsi['fscod']);
[443] Fix | Delete
$thisfile_ac3['bitrate'] = self::bitrateLookup($thisfile_ac3_raw_bsi['frmsizecod']);
[444] Fix | Delete
} elseif (!empty($thisfile_ac3_raw_bsi['frmsiz'])) {
[445] Fix | Delete
// this isn't right, but it's (usually) close, roughly 5% less than it should be.
[446] Fix | Delete
// but WHERE is the actual bitrate value stored in EAC3?? email info@getid3.org if you know!
[447] Fix | Delete
$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.
[448] Fix | Delete
// kludge-fix to make it approximately the expected value, still not "right":
[449] Fix | Delete
$thisfile_ac3['bitrate'] = round(($thisfile_ac3['bitrate'] * 1.05) / 16000) * 16000;
[450] Fix | Delete
}
[451] Fix | Delete
$info['audio']['bitrate'] = $thisfile_ac3['bitrate'];
[452] Fix | Delete
[453] Fix | Delete
if (isset($thisfile_ac3_raw_bsi['bsmod']) && isset($thisfile_ac3_raw_bsi['acmod'])) {
[454] Fix | Delete
$thisfile_ac3['service_type'] = self::serviceTypeLookup($thisfile_ac3_raw_bsi['bsmod'], $thisfile_ac3_raw_bsi['acmod']);
[455] Fix | Delete
}
[456] Fix | Delete
$ac3_coding_mode = self::audioCodingModeLookup($thisfile_ac3_raw_bsi['acmod']);
[457] Fix | Delete
foreach($ac3_coding_mode as $key => $value) {
[458] Fix | Delete
$thisfile_ac3[$key] = $value;
[459] Fix | Delete
}
[460] Fix | Delete
switch ($thisfile_ac3_raw_bsi['acmod']) {
[461] Fix | Delete
case 0:
[462] Fix | Delete
case 1:
[463] Fix | Delete
$info['audio']['channelmode'] = 'mono';
[464] Fix | Delete
break;
[465] Fix | Delete
case 3:
[466] Fix | Delete
case 4:
[467] Fix | Delete
$info['audio']['channelmode'] = 'stereo';
[468] Fix | Delete
break;
[469] Fix | Delete
default:
[470] Fix | Delete
$info['audio']['channelmode'] = 'surround';
[471] Fix | Delete
break;
[472] Fix | Delete
}
[473] Fix | Delete
$info['audio']['channels'] = $thisfile_ac3['num_channels'];
[474] Fix | Delete
[475] Fix | Delete
$thisfile_ac3['lfe_enabled'] = $thisfile_ac3_raw_bsi['flags']['lfeon'];
[476] Fix | Delete
if ($thisfile_ac3_raw_bsi['flags']['lfeon']) {
[477] Fix | Delete
$info['audio']['channels'] .= '.1';
[478] Fix | Delete
}
[479] Fix | Delete
[480] Fix | Delete
$thisfile_ac3['channels_enabled'] = self::channelsEnabledLookup($thisfile_ac3_raw_bsi['acmod'], $thisfile_ac3_raw_bsi['flags']['lfeon']);
[481] Fix | Delete
$thisfile_ac3['dialogue_normalization'] = '-'.$thisfile_ac3_raw_bsi['dialnorm'].'dB';
[482] Fix | Delete
[483] Fix | Delete
return true;
[484] Fix | Delete
}
[485] Fix | Delete
[486] Fix | Delete
/**
[487] Fix | Delete
* @param int $length
[488] Fix | Delete
*
[489] Fix | Delete
* @return int
[490] Fix | Delete
*/
[491] Fix | Delete
private function readHeaderBSI($length) {
[492] Fix | Delete
$data = substr($this->AC3header['bsi'], $this->BSIoffset, $length);
[493] Fix | Delete
$this->BSIoffset += $length;
[494] Fix | Delete
[495] Fix | Delete
return bindec($data);
[496] Fix | Delete
}
[497] Fix | Delete
[498] Fix | Delete
/**
[499] Fix | Delete
12
It is recommended that you Edit text format, this type of Fix handles quite a lot in one request
Function