Edit File by line
/home/zeestwma/richards.../wp-inclu.../ID3
File: module.audio.mp3.php
if (($header[$SynchSeekOffset] == "\xFF") && ($header[($SynchSeekOffset + 1)] > "\xE0")) { // possible synch detected
[1500] Fix | Delete
if (++$SyncSeekAttempts >= $SyncSeekAttemptsMax) {
[1501] Fix | Delete
// https://github.com/JamesHeinrich/getID3/issues/286
[1502] Fix | Delete
// corrupt files claiming to be MP3, with a large number of 0xFF bytes near the beginning, can cause this loop to take a very long time
[1503] Fix | Delete
// should have escape condition to avoid spending too much time scanning a corrupt file
[1504] Fix | Delete
// if a synch's not found within the first 128k bytes, then give up
[1505] Fix | Delete
$this->error('Could not find valid MPEG audio synch after scanning '.$SyncSeekAttempts.' candidate offsets');
[1506] Fix | Delete
if (isset($info['audio']['bitrate'])) {
[1507] Fix | Delete
unset($info['audio']['bitrate']);
[1508] Fix | Delete
}
[1509] Fix | Delete
if (isset($info['mpeg']['audio'])) {
[1510] Fix | Delete
unset($info['mpeg']['audio']);
[1511] Fix | Delete
}
[1512] Fix | Delete
if (empty($info['mpeg'])) {
[1513] Fix | Delete
unset($info['mpeg']);
[1514] Fix | Delete
}
[1515] Fix | Delete
return false;
[1516] Fix | Delete
}
[1517] Fix | Delete
$FirstFrameAVDataOffset = null;
[1518] Fix | Delete
if (!isset($FirstFrameThisfileInfo) && !isset($info['mpeg']['audio'])) {
[1519] Fix | Delete
$FirstFrameThisfileInfo = $info;
[1520] Fix | Delete
$FirstFrameAVDataOffset = $avdataoffset + $SynchSeekOffset;
[1521] Fix | Delete
if (!$this->decodeMPEGaudioHeader($FirstFrameAVDataOffset, $FirstFrameThisfileInfo, false)) {
[1522] Fix | Delete
// if this is the first valid MPEG-audio frame, save it in case it's a VBR header frame and there's
[1523] Fix | Delete
// garbage between this frame and a valid sequence of MPEG-audio frames, to be restored below
[1524] Fix | Delete
unset($FirstFrameThisfileInfo);
[1525] Fix | Delete
}
[1526] Fix | Delete
}
[1527] Fix | Delete
[1528] Fix | Delete
$dummy = $info; // only overwrite real data if valid header found
[1529] Fix | Delete
if ($this->decodeMPEGaudioHeader($avdataoffset + $SynchSeekOffset, $dummy, true)) {
[1530] Fix | Delete
$info = $dummy;
[1531] Fix | Delete
$info['avdataoffset'] = $avdataoffset + $SynchSeekOffset;
[1532] Fix | Delete
switch (isset($info['fileformat']) ? $info['fileformat'] : '') {
[1533] Fix | Delete
case '':
[1534] Fix | Delete
case 'id3':
[1535] Fix | Delete
case 'ape':
[1536] Fix | Delete
case 'mp3':
[1537] Fix | Delete
$info['fileformat'] = 'mp3';
[1538] Fix | Delete
$info['audio']['dataformat'] = 'mp3';
[1539] Fix | Delete
break;
[1540] Fix | Delete
}
[1541] Fix | Delete
if (isset($FirstFrameThisfileInfo) && isset($FirstFrameThisfileInfo['mpeg']['audio']['bitrate_mode']) && ($FirstFrameThisfileInfo['mpeg']['audio']['bitrate_mode'] == 'vbr')) {
[1542] Fix | Delete
if (!(abs($info['audio']['bitrate'] - $FirstFrameThisfileInfo['audio']['bitrate']) <= 1)) {
[1543] Fix | Delete
// If there is garbage data between a valid VBR header frame and a sequence
[1544] Fix | Delete
// of valid MPEG-audio frames the VBR data is no longer discarded.
[1545] Fix | Delete
$info = $FirstFrameThisfileInfo;
[1546] Fix | Delete
$info['avdataoffset'] = $FirstFrameAVDataOffset;
[1547] Fix | Delete
$info['fileformat'] = 'mp3';
[1548] Fix | Delete
$info['audio']['dataformat'] = 'mp3';
[1549] Fix | Delete
$dummy = $info;
[1550] Fix | Delete
unset($dummy['mpeg']['audio']);
[1551] Fix | Delete
$GarbageOffsetStart = $FirstFrameAVDataOffset + $FirstFrameThisfileInfo['mpeg']['audio']['framelength'];
[1552] Fix | Delete
$GarbageOffsetEnd = $avdataoffset + $SynchSeekOffset;
[1553] Fix | Delete
if ($this->decodeMPEGaudioHeader($GarbageOffsetEnd, $dummy, true, true)) {
[1554] Fix | Delete
$info = $dummy;
[1555] Fix | Delete
$info['avdataoffset'] = $GarbageOffsetEnd;
[1556] Fix | Delete
$this->warning('apparently-valid VBR header not used because could not find '.$this->mp3_valid_check_frames.' consecutive MPEG-audio frames immediately after VBR header (garbage data for '.($GarbageOffsetEnd - $GarbageOffsetStart).' bytes between '.$GarbageOffsetStart.' and '.$GarbageOffsetEnd.'), but did find valid CBR stream starting at '.$GarbageOffsetEnd);
[1557] Fix | Delete
} else {
[1558] Fix | Delete
$this->warning('using data from VBR header even though could not find '.$this->mp3_valid_check_frames.' consecutive MPEG-audio frames immediately after VBR header (garbage data for '.($GarbageOffsetEnd - $GarbageOffsetStart).' bytes between '.$GarbageOffsetStart.' and '.$GarbageOffsetEnd.')');
[1559] Fix | Delete
}
[1560] Fix | Delete
}
[1561] Fix | Delete
}
[1562] Fix | Delete
if (isset($info['mpeg']['audio']['bitrate_mode']) && ($info['mpeg']['audio']['bitrate_mode'] == 'vbr') && !isset($info['mpeg']['audio']['VBR_method'])) {
[1563] Fix | Delete
// VBR file with no VBR header
[1564] Fix | Delete
$BitrateHistogram = true;
[1565] Fix | Delete
}
[1566] Fix | Delete
[1567] Fix | Delete
if ($BitrateHistogram) {
[1568] Fix | Delete
[1569] Fix | Delete
$info['mpeg']['audio']['stereo_distribution'] = array('stereo'=>0, 'joint stereo'=>0, 'dual channel'=>0, 'mono'=>0);
[1570] Fix | Delete
$info['mpeg']['audio']['version_distribution'] = array('1'=>0, '2'=>0, '2.5'=>0);
[1571] Fix | Delete
[1572] Fix | Delete
if ($info['mpeg']['audio']['version'] == '1') {
[1573] Fix | Delete
if ($info['mpeg']['audio']['layer'] == 3) {
[1574] Fix | Delete
$info['mpeg']['audio']['bitrate_distribution'] = array('free'=>0, 32000=>0, 40000=>0, 48000=>0, 56000=>0, 64000=>0, 80000=>0, 96000=>0, 112000=>0, 128000=>0, 160000=>0, 192000=>0, 224000=>0, 256000=>0, 320000=>0);
[1575] Fix | Delete
} elseif ($info['mpeg']['audio']['layer'] == 2) {
[1576] Fix | Delete
$info['mpeg']['audio']['bitrate_distribution'] = array('free'=>0, 32000=>0, 48000=>0, 56000=>0, 64000=>0, 80000=>0, 96000=>0, 112000=>0, 128000=>0, 160000=>0, 192000=>0, 224000=>0, 256000=>0, 320000=>0, 384000=>0);
[1577] Fix | Delete
} elseif ($info['mpeg']['audio']['layer'] == 1) {
[1578] Fix | Delete
$info['mpeg']['audio']['bitrate_distribution'] = array('free'=>0, 32000=>0, 64000=>0, 96000=>0, 128000=>0, 160000=>0, 192000=>0, 224000=>0, 256000=>0, 288000=>0, 320000=>0, 352000=>0, 384000=>0, 416000=>0, 448000=>0);
[1579] Fix | Delete
}
[1580] Fix | Delete
} elseif ($info['mpeg']['audio']['layer'] == 1) {
[1581] Fix | Delete
$info['mpeg']['audio']['bitrate_distribution'] = array('free'=>0, 32000=>0, 48000=>0, 56000=>0, 64000=>0, 80000=>0, 96000=>0, 112000=>0, 128000=>0, 144000=>0, 160000=>0, 176000=>0, 192000=>0, 224000=>0, 256000=>0);
[1582] Fix | Delete
} else {
[1583] Fix | Delete
$info['mpeg']['audio']['bitrate_distribution'] = array('free'=>0, 8000=>0, 16000=>0, 24000=>0, 32000=>0, 40000=>0, 48000=>0, 56000=>0, 64000=>0, 80000=>0, 96000=>0, 112000=>0, 128000=>0, 144000=>0, 160000=>0);
[1584] Fix | Delete
}
[1585] Fix | Delete
[1586] Fix | Delete
$dummy = array('error'=>$info['error'], 'warning'=>$info['warning'], 'avdataend'=>$info['avdataend'], 'avdataoffset'=>$info['avdataoffset']);
[1587] Fix | Delete
$synchstartoffset = $info['avdataoffset'];
[1588] Fix | Delete
$this->fseek($info['avdataoffset']);
[1589] Fix | Delete
[1590] Fix | Delete
// you can play with these numbers:
[1591] Fix | Delete
$max_frames_scan = 50000;
[1592] Fix | Delete
$max_scan_segments = 10;
[1593] Fix | Delete
[1594] Fix | Delete
// don't play with these numbers:
[1595] Fix | Delete
$FastMode = false;
[1596] Fix | Delete
$SynchErrorsFound = 0;
[1597] Fix | Delete
$frames_scanned = 0;
[1598] Fix | Delete
$this_scan_segment = 0;
[1599] Fix | Delete
$frames_scan_per_segment = ceil($max_frames_scan / $max_scan_segments);
[1600] Fix | Delete
$pct_data_scanned = 0;
[1601] Fix | Delete
for ($current_segment = 0; $current_segment < $max_scan_segments; $current_segment++) {
[1602] Fix | Delete
$frames_scanned_this_segment = 0;
[1603] Fix | Delete
$scan_start_offset = array();
[1604] Fix | Delete
if ($this->ftell() >= $info['avdataend']) {
[1605] Fix | Delete
break;
[1606] Fix | Delete
}
[1607] Fix | Delete
$scan_start_offset[$current_segment] = max($this->ftell(), $info['avdataoffset'] + round($current_segment * (($info['avdataend'] - $info['avdataoffset']) / $max_scan_segments)));
[1608] Fix | Delete
if ($current_segment > 0) {
[1609] Fix | Delete
$this->fseek($scan_start_offset[$current_segment]);
[1610] Fix | Delete
$buffer_4k = $this->fread(4096);
[1611] Fix | Delete
for ($j = 0; $j < (strlen($buffer_4k) - 4); $j++) {
[1612] Fix | Delete
if (($buffer_4k[$j] == "\xFF") && ($buffer_4k[($j + 1)] > "\xE0")) { // synch detected
[1613] Fix | Delete
if ($this->decodeMPEGaudioHeader($scan_start_offset[$current_segment] + $j, $dummy, false, false, $FastMode)) {
[1614] Fix | Delete
$calculated_next_offset = $scan_start_offset[$current_segment] + $j + $dummy['mpeg']['audio']['framelength'];
[1615] Fix | Delete
if ($this->decodeMPEGaudioHeader($calculated_next_offset, $dummy, false, false, $FastMode)) {
[1616] Fix | Delete
$scan_start_offset[$current_segment] += $j;
[1617] Fix | Delete
break;
[1618] Fix | Delete
}
[1619] Fix | Delete
}
[1620] Fix | Delete
}
[1621] Fix | Delete
}
[1622] Fix | Delete
}
[1623] Fix | Delete
$synchstartoffset = $scan_start_offset[$current_segment];
[1624] Fix | Delete
while (($synchstartoffset < $info['avdataend']) && $this->decodeMPEGaudioHeader($synchstartoffset, $dummy, false, false, $FastMode)) {
[1625] Fix | Delete
$FastMode = true;
[1626] Fix | Delete
$thisframebitrate = $MPEGaudioBitrateLookup[$MPEGaudioVersionLookup[$dummy['mpeg']['audio']['raw']['version']]][$MPEGaudioLayerLookup[$dummy['mpeg']['audio']['raw']['layer']]][$dummy['mpeg']['audio']['raw']['bitrate']];
[1627] Fix | Delete
[1628] Fix | Delete
if (empty($dummy['mpeg']['audio']['framelength'])) {
[1629] Fix | Delete
$SynchErrorsFound++;
[1630] Fix | Delete
$synchstartoffset++;
[1631] Fix | Delete
} else {
[1632] Fix | Delete
getid3_lib::safe_inc($info['mpeg']['audio']['bitrate_distribution'][$thisframebitrate]);
[1633] Fix | Delete
getid3_lib::safe_inc($info['mpeg']['audio']['stereo_distribution'][$dummy['mpeg']['audio']['channelmode']]);
[1634] Fix | Delete
getid3_lib::safe_inc($info['mpeg']['audio']['version_distribution'][$dummy['mpeg']['audio']['version']]);
[1635] Fix | Delete
$synchstartoffset += $dummy['mpeg']['audio']['framelength'];
[1636] Fix | Delete
}
[1637] Fix | Delete
$frames_scanned++;
[1638] Fix | Delete
if ($frames_scan_per_segment && (++$frames_scanned_this_segment >= $frames_scan_per_segment)) {
[1639] Fix | Delete
$this_pct_scanned = getid3_lib::SafeDiv($this->ftell() - $scan_start_offset[$current_segment], $info['avdataend'] - $info['avdataoffset']);
[1640] Fix | Delete
if (($current_segment == 0) && (($this_pct_scanned * $max_scan_segments) >= 1)) {
[1641] Fix | Delete
// file likely contains < $max_frames_scan, just scan as one segment
[1642] Fix | Delete
$max_scan_segments = 1;
[1643] Fix | Delete
$frames_scan_per_segment = $max_frames_scan;
[1644] Fix | Delete
} else {
[1645] Fix | Delete
$pct_data_scanned += $this_pct_scanned;
[1646] Fix | Delete
break;
[1647] Fix | Delete
}
[1648] Fix | Delete
}
[1649] Fix | Delete
}
[1650] Fix | Delete
}
[1651] Fix | Delete
if ($pct_data_scanned > 0) {
[1652] Fix | Delete
$this->warning('too many MPEG audio frames to scan, only scanned '.$frames_scanned.' frames in '.$max_scan_segments.' segments ('.number_format($pct_data_scanned * 100, 1).'% of file) and extrapolated distribution, playtime and bitrate may be incorrect.');
[1653] Fix | Delete
foreach ($info['mpeg']['audio'] as $key1 => $value1) {
[1654] Fix | Delete
if (!preg_match('#_distribution$#i', $key1)) {
[1655] Fix | Delete
continue;
[1656] Fix | Delete
}
[1657] Fix | Delete
foreach ($value1 as $key2 => $value2) {
[1658] Fix | Delete
$info['mpeg']['audio'][$key1][$key2] = round($value2 / $pct_data_scanned);
[1659] Fix | Delete
}
[1660] Fix | Delete
}
[1661] Fix | Delete
}
[1662] Fix | Delete
[1663] Fix | Delete
if ($SynchErrorsFound > 0) {
[1664] Fix | Delete
$this->warning('Found '.$SynchErrorsFound.' synch errors in histogram analysis');
[1665] Fix | Delete
//return false;
[1666] Fix | Delete
}
[1667] Fix | Delete
[1668] Fix | Delete
$bittotal = 0;
[1669] Fix | Delete
$framecounter = 0;
[1670] Fix | Delete
foreach ($info['mpeg']['audio']['bitrate_distribution'] as $bitratevalue => $bitratecount) {
[1671] Fix | Delete
$framecounter += $bitratecount;
[1672] Fix | Delete
if ($bitratevalue != 'free') {
[1673] Fix | Delete
$bittotal += ($bitratevalue * $bitratecount);
[1674] Fix | Delete
}
[1675] Fix | Delete
}
[1676] Fix | Delete
if ($framecounter == 0) {
[1677] Fix | Delete
$this->error('Corrupt MP3 file: framecounter == zero');
[1678] Fix | Delete
return false;
[1679] Fix | Delete
}
[1680] Fix | Delete
$info['mpeg']['audio']['frame_count'] = getid3_lib::CastAsInt($framecounter);
[1681] Fix | Delete
$info['mpeg']['audio']['bitrate'] = ($bittotal / $framecounter);
[1682] Fix | Delete
[1683] Fix | Delete
$info['audio']['bitrate'] = $info['mpeg']['audio']['bitrate'];
[1684] Fix | Delete
[1685] Fix | Delete
[1686] Fix | Delete
// Definitively set VBR vs CBR, even if the Xing/LAME/VBRI header says differently
[1687] Fix | Delete
$distinct_bitrates = 0;
[1688] Fix | Delete
foreach ($info['mpeg']['audio']['bitrate_distribution'] as $bitrate_value => $bitrate_count) {
[1689] Fix | Delete
if ($bitrate_count > 0) {
[1690] Fix | Delete
$distinct_bitrates++;
[1691] Fix | Delete
}
[1692] Fix | Delete
}
[1693] Fix | Delete
if ($distinct_bitrates > 1) {
[1694] Fix | Delete
$info['mpeg']['audio']['bitrate_mode'] = 'vbr';
[1695] Fix | Delete
} else {
[1696] Fix | Delete
$info['mpeg']['audio']['bitrate_mode'] = 'cbr';
[1697] Fix | Delete
}
[1698] Fix | Delete
$info['audio']['bitrate_mode'] = $info['mpeg']['audio']['bitrate_mode'];
[1699] Fix | Delete
[1700] Fix | Delete
}
[1701] Fix | Delete
[1702] Fix | Delete
break; // exit while()
[1703] Fix | Delete
}
[1704] Fix | Delete
}
[1705] Fix | Delete
[1706] Fix | Delete
$SynchSeekOffset++;
[1707] Fix | Delete
if (($avdataoffset + $SynchSeekOffset) >= $info['avdataend']) {
[1708] Fix | Delete
// end of file/data
[1709] Fix | Delete
[1710] Fix | Delete
if (empty($info['mpeg']['audio'])) {
[1711] Fix | Delete
[1712] Fix | Delete
$this->error('could not find valid MPEG synch before end of file');
[1713] Fix | Delete
if (isset($info['audio']['bitrate'])) {
[1714] Fix | Delete
unset($info['audio']['bitrate']);
[1715] Fix | Delete
}
[1716] Fix | Delete
if (isset($info['mpeg']['audio'])) {
[1717] Fix | Delete
unset($info['mpeg']['audio']);
[1718] Fix | Delete
}
[1719] Fix | Delete
if (isset($info['mpeg']) && (!is_array($info['mpeg']) || empty($info['mpeg']))) {
[1720] Fix | Delete
unset($info['mpeg']);
[1721] Fix | Delete
}
[1722] Fix | Delete
return false;
[1723] Fix | Delete
[1724] Fix | Delete
}
[1725] Fix | Delete
break;
[1726] Fix | Delete
}
[1727] Fix | Delete
[1728] Fix | Delete
}
[1729] Fix | Delete
$info['audio']['channels'] = $info['mpeg']['audio']['channels'];
[1730] Fix | Delete
if ($info['audio']['channels'] < 1) {
[1731] Fix | Delete
$this->error('Corrupt MP3 file: no channels');
[1732] Fix | Delete
return false;
[1733] Fix | Delete
}
[1734] Fix | Delete
$info['audio']['channelmode'] = $info['mpeg']['audio']['channelmode'];
[1735] Fix | Delete
$info['audio']['sample_rate'] = $info['mpeg']['audio']['sample_rate'];
[1736] Fix | Delete
return true;
[1737] Fix | Delete
}
[1738] Fix | Delete
[1739] Fix | Delete
/**
[1740] Fix | Delete
* @return array
[1741] Fix | Delete
*/
[1742] Fix | Delete
public static function MPEGaudioVersionArray() {
[1743] Fix | Delete
static $MPEGaudioVersion = array('2.5', false, '2', '1');
[1744] Fix | Delete
return $MPEGaudioVersion;
[1745] Fix | Delete
}
[1746] Fix | Delete
[1747] Fix | Delete
/**
[1748] Fix | Delete
* @return array
[1749] Fix | Delete
*/
[1750] Fix | Delete
public static function MPEGaudioLayerArray() {
[1751] Fix | Delete
static $MPEGaudioLayer = array(false, 3, 2, 1);
[1752] Fix | Delete
return $MPEGaudioLayer;
[1753] Fix | Delete
}
[1754] Fix | Delete
[1755] Fix | Delete
/**
[1756] Fix | Delete
* @return array
[1757] Fix | Delete
*/
[1758] Fix | Delete
public static function MPEGaudioBitrateArray() {
[1759] Fix | Delete
static $MPEGaudioBitrate;
[1760] Fix | Delete
if (empty($MPEGaudioBitrate)) {
[1761] Fix | Delete
$MPEGaudioBitrate = array (
[1762] Fix | Delete
'1' => array (1 => array('free', 32000, 64000, 96000, 128000, 160000, 192000, 224000, 256000, 288000, 320000, 352000, 384000, 416000, 448000),
[1763] Fix | Delete
2 => array('free', 32000, 48000, 56000, 64000, 80000, 96000, 112000, 128000, 160000, 192000, 224000, 256000, 320000, 384000),
[1764] Fix | Delete
3 => array('free', 32000, 40000, 48000, 56000, 64000, 80000, 96000, 112000, 128000, 160000, 192000, 224000, 256000, 320000)
[1765] Fix | Delete
),
[1766] Fix | Delete
[1767] Fix | Delete
'2' => array (1 => array('free', 32000, 48000, 56000, 64000, 80000, 96000, 112000, 128000, 144000, 160000, 176000, 192000, 224000, 256000),
[1768] Fix | Delete
2 => array('free', 8000, 16000, 24000, 32000, 40000, 48000, 56000, 64000, 80000, 96000, 112000, 128000, 144000, 160000),
[1769] Fix | Delete
)
[1770] Fix | Delete
);
[1771] Fix | Delete
$MPEGaudioBitrate['2'][3] = $MPEGaudioBitrate['2'][2];
[1772] Fix | Delete
$MPEGaudioBitrate['2.5'] = $MPEGaudioBitrate['2'];
[1773] Fix | Delete
}
[1774] Fix | Delete
return $MPEGaudioBitrate;
[1775] Fix | Delete
}
[1776] Fix | Delete
[1777] Fix | Delete
/**
[1778] Fix | Delete
* @return array
[1779] Fix | Delete
*/
[1780] Fix | Delete
public static function MPEGaudioFrequencyArray() {
[1781] Fix | Delete
static $MPEGaudioFrequency;
[1782] Fix | Delete
if (empty($MPEGaudioFrequency)) {
[1783] Fix | Delete
$MPEGaudioFrequency = array (
[1784] Fix | Delete
'1' => array(44100, 48000, 32000),
[1785] Fix | Delete
'2' => array(22050, 24000, 16000),
[1786] Fix | Delete
'2.5' => array(11025, 12000, 8000)
[1787] Fix | Delete
);
[1788] Fix | Delete
}
[1789] Fix | Delete
return $MPEGaudioFrequency;
[1790] Fix | Delete
}
[1791] Fix | Delete
[1792] Fix | Delete
/**
[1793] Fix | Delete
* @return array
[1794] Fix | Delete
*/
[1795] Fix | Delete
public static function MPEGaudioChannelModeArray() {
[1796] Fix | Delete
static $MPEGaudioChannelMode = array('stereo', 'joint stereo', 'dual channel', 'mono');
[1797] Fix | Delete
return $MPEGaudioChannelMode;
[1798] Fix | Delete
}
[1799] Fix | Delete
[1800] Fix | Delete
/**
[1801] Fix | Delete
* @return array
[1802] Fix | Delete
*/
[1803] Fix | Delete
public static function MPEGaudioModeExtensionArray() {
[1804] Fix | Delete
static $MPEGaudioModeExtension;
[1805] Fix | Delete
if (empty($MPEGaudioModeExtension)) {
[1806] Fix | Delete
$MPEGaudioModeExtension = array (
[1807] Fix | Delete
1 => array('4-31', '8-31', '12-31', '16-31'),
[1808] Fix | Delete
2 => array('4-31', '8-31', '12-31', '16-31'),
[1809] Fix | Delete
3 => array('', 'IS', 'MS', 'IS+MS')
[1810] Fix | Delete
);
[1811] Fix | Delete
}
[1812] Fix | Delete
return $MPEGaudioModeExtension;
[1813] Fix | Delete
}
[1814] Fix | Delete
[1815] Fix | Delete
/**
[1816] Fix | Delete
* @return array
[1817] Fix | Delete
*/
[1818] Fix | Delete
public static function MPEGaudioEmphasisArray() {
[1819] Fix | Delete
static $MPEGaudioEmphasis = array('none', '50/15ms', false, 'CCIT J.17');
[1820] Fix | Delete
return $MPEGaudioEmphasis;
[1821] Fix | Delete
}
[1822] Fix | Delete
[1823] Fix | Delete
/**
[1824] Fix | Delete
* @param string $head4
[1825] Fix | Delete
* @param bool $allowBitrate15
[1826] Fix | Delete
*
[1827] Fix | Delete
* @return bool
[1828] Fix | Delete
*/
[1829] Fix | Delete
public static function MPEGaudioHeaderBytesValid($head4, $allowBitrate15=false) {
[1830] Fix | Delete
return self::MPEGaudioHeaderValid(self::MPEGaudioHeaderDecode($head4), false, $allowBitrate15);
[1831] Fix | Delete
}
[1832] Fix | Delete
[1833] Fix | Delete
/**
[1834] Fix | Delete
* @param array $rawarray
[1835] Fix | Delete
* @param bool $echoerrors
[1836] Fix | Delete
* @param bool $allowBitrate15
[1837] Fix | Delete
*
[1838] Fix | Delete
* @return bool
[1839] Fix | Delete
*/
[1840] Fix | Delete
public static function MPEGaudioHeaderValid($rawarray, $echoerrors=false, $allowBitrate15=false) {
[1841] Fix | Delete
if (!isset($rawarray['synch']) || ($rawarray['synch'] & 0x0FFE) != 0x0FFE) {
[1842] Fix | Delete
return false;
[1843] Fix | Delete
}
[1844] Fix | Delete
[1845] Fix | Delete
static $MPEGaudioVersionLookup;
[1846] Fix | Delete
static $MPEGaudioLayerLookup;
[1847] Fix | Delete
static $MPEGaudioBitrateLookup;
[1848] Fix | Delete
static $MPEGaudioFrequencyLookup;
[1849] Fix | Delete
static $MPEGaudioChannelModeLookup;
[1850] Fix | Delete
static $MPEGaudioModeExtensionLookup;
[1851] Fix | Delete
static $MPEGaudioEmphasisLookup;
[1852] Fix | Delete
if (empty($MPEGaudioVersionLookup)) {
[1853] Fix | Delete
$MPEGaudioVersionLookup = self::MPEGaudioVersionArray();
[1854] Fix | Delete
$MPEGaudioLayerLookup = self::MPEGaudioLayerArray();
[1855] Fix | Delete
$MPEGaudioBitrateLookup = self::MPEGaudioBitrateArray();
[1856] Fix | Delete
$MPEGaudioFrequencyLookup = self::MPEGaudioFrequencyArray();
[1857] Fix | Delete
$MPEGaudioChannelModeLookup = self::MPEGaudioChannelModeArray();
[1858] Fix | Delete
$MPEGaudioModeExtensionLookup = self::MPEGaudioModeExtensionArray();
[1859] Fix | Delete
$MPEGaudioEmphasisLookup = self::MPEGaudioEmphasisArray();
[1860] Fix | Delete
}
[1861] Fix | Delete
[1862] Fix | Delete
if (isset($MPEGaudioVersionLookup[$rawarray['version']])) {
[1863] Fix | Delete
$decodedVersion = $MPEGaudioVersionLookup[$rawarray['version']];
[1864] Fix | Delete
} else {
[1865] Fix | Delete
echo ($echoerrors ? "\n".'invalid Version ('.$rawarray['version'].')' : '');
[1866] Fix | Delete
return false;
[1867] Fix | Delete
}
[1868] Fix | Delete
if (isset($MPEGaudioLayerLookup[$rawarray['layer']])) {
[1869] Fix | Delete
$decodedLayer = $MPEGaudioLayerLookup[$rawarray['layer']];
[1870] Fix | Delete
} else {
[1871] Fix | Delete
echo ($echoerrors ? "\n".'invalid Layer ('.$rawarray['layer'].')' : '');
[1872] Fix | Delete
return false;
[1873] Fix | Delete
}
[1874] Fix | Delete
if (!isset($MPEGaudioBitrateLookup[$decodedVersion][$decodedLayer][$rawarray['bitrate']])) {
[1875] Fix | Delete
echo ($echoerrors ? "\n".'invalid Bitrate ('.$rawarray['bitrate'].')' : '');
[1876] Fix | Delete
if ($rawarray['bitrate'] == 15) {
[1877] Fix | Delete
// known issue in LAME 3.90 - 3.93.1 where free-format has bitrate ID of 15 instead of 0
[1878] Fix | Delete
// let it go through here otherwise file will not be identified
[1879] Fix | Delete
if (!$allowBitrate15) {
[1880] Fix | Delete
return false;
[1881] Fix | Delete
}
[1882] Fix | Delete
} else {
[1883] Fix | Delete
return false;
[1884] Fix | Delete
}
[1885] Fix | Delete
}
[1886] Fix | Delete
if (!isset($MPEGaudioFrequencyLookup[$decodedVersion][$rawarray['sample_rate']])) {
[1887] Fix | Delete
echo ($echoerrors ? "\n".'invalid Frequency ('.$rawarray['sample_rate'].')' : '');
[1888] Fix | Delete
return false;
[1889] Fix | Delete
}
[1890] Fix | Delete
if (!isset($MPEGaudioChannelModeLookup[$rawarray['channelmode']])) {
[1891] Fix | Delete
echo ($echoerrors ? "\n".'invalid ChannelMode ('.$rawarray['channelmode'].')' : '');
[1892] Fix | Delete
return false;
[1893] Fix | Delete
}
[1894] Fix | Delete
if (!isset($MPEGaudioModeExtensionLookup[$decodedLayer][$rawarray['modeextension']])) {
[1895] Fix | Delete
echo ($echoerrors ? "\n".'invalid Mode Extension ('.$rawarray['modeextension'].')' : '');
[1896] Fix | Delete
return false;
[1897] Fix | Delete
}
[1898] Fix | Delete
if (!isset($MPEGaudioEmphasisLookup[$rawarray['emphasis']])) {
[1899] Fix | Delete
echo ($echoerrors ? "\n".'invalid Emphasis ('.$rawarray['emphasis'].')' : '');
[1900] Fix | Delete
return false;
[1901] Fix | Delete
}
[1902] Fix | Delete
// These are just either set or not set, you can't mess that up :)
[1903] Fix | Delete
// $rawarray['protection'];
[1904] Fix | Delete
// $rawarray['padding'];
[1905] Fix | Delete
// $rawarray['private'];
[1906] Fix | Delete
// $rawarray['copyright'];
[1907] Fix | Delete
// $rawarray['original'];
[1908] Fix | Delete
[1909] Fix | Delete
return true;
[1910] Fix | Delete
}
[1911] Fix | Delete
[1912] Fix | Delete
/**
[1913] Fix | Delete
* @param string $Header4Bytes
[1914] Fix | Delete
*
[1915] Fix | Delete
* @return array|false
[1916] Fix | Delete
*/
[1917] Fix | Delete
public static function MPEGaudioHeaderDecode($Header4Bytes) {
[1918] Fix | Delete
// AAAA AAAA AAAB BCCD EEEE FFGH IIJJ KLMM
[1919] Fix | Delete
// A - Frame sync (all bits set)
[1920] Fix | Delete
// B - MPEG Audio version ID
[1921] Fix | Delete
// C - Layer description
[1922] Fix | Delete
// D - Protection bit
[1923] Fix | Delete
// E - Bitrate index
[1924] Fix | Delete
// F - Sampling rate frequency index
[1925] Fix | Delete
// G - Padding bit
[1926] Fix | Delete
// H - Private bit
[1927] Fix | Delete
// I - Channel Mode
[1928] Fix | Delete
// J - Mode extension (Only if Joint stereo)
[1929] Fix | Delete
// K - Copyright
[1930] Fix | Delete
// L - Original
[1931] Fix | Delete
// M - Emphasis
[1932] Fix | Delete
[1933] Fix | Delete
if (strlen($Header4Bytes) != 4) {
[1934] Fix | Delete
return false;
[1935] Fix | Delete
}
[1936] Fix | Delete
[1937] Fix | Delete
$MPEGrawHeader = array();
[1938] Fix | Delete
$MPEGrawHeader['synch'] = (getid3_lib::BigEndian2Int(substr($Header4Bytes, 0, 2)) & 0xFFE0) >> 4;
[1939] Fix | Delete
$MPEGrawHeader['version'] = (ord($Header4Bytes[1]) & 0x18) >> 3; // BB
[1940] Fix | Delete
$MPEGrawHeader['layer'] = (ord($Header4Bytes[1]) & 0x06) >> 1; // CC
[1941] Fix | Delete
$MPEGrawHeader['protection'] = (ord($Header4Bytes[1]) & 0x01); // D
[1942] Fix | Delete
$MPEGrawHeader['bitrate'] = (ord($Header4Bytes[2]) & 0xF0) >> 4; // EEEE
[1943] Fix | Delete
$MPEGrawHeader['sample_rate'] = (ord($Header4Bytes[2]) & 0x0C) >> 2; // FF
[1944] Fix | Delete
$MPEGrawHeader['padding'] = (ord($Header4Bytes[2]) & 0x02) >> 1; // G
[1945] Fix | Delete
$MPEGrawHeader['private'] = (ord($Header4Bytes[2]) & 0x01); // H
[1946] Fix | Delete
$MPEGrawHeader['channelmode'] = (ord($Header4Bytes[3]) & 0xC0) >> 6; // II
[1947] Fix | Delete
$MPEGrawHeader['modeextension'] = (ord($Header4Bytes[3]) & 0x30) >> 4; // JJ
[1948] Fix | Delete
$MPEGrawHeader['copyright'] = (ord($Header4Bytes[3]) & 0x08) >> 3; // K
[1949] Fix | Delete
$MPEGrawHeader['original'] = (ord($Header4Bytes[3]) & 0x04) >> 2; // L
[1950] Fix | Delete
$MPEGrawHeader['emphasis'] = (ord($Header4Bytes[3]) & 0x03); // MM
[1951] Fix | Delete
[1952] Fix | Delete
return $MPEGrawHeader;
[1953] Fix | Delete
}
[1954] Fix | Delete
[1955] Fix | Delete
/**
[1956] Fix | Delete
* @param int|string $bitrate
[1957] Fix | Delete
* @param string $version
[1958] Fix | Delete
* @param string $layer
[1959] Fix | Delete
* @param bool $padding
[1960] Fix | Delete
* @param int $samplerate
[1961] Fix | Delete
*
[1962] Fix | Delete
* @return int|false
[1963] Fix | Delete
*/
[1964] Fix | Delete
public static function MPEGaudioFrameLength(&$bitrate, &$version, &$layer, $padding, &$samplerate) {
[1965] Fix | Delete
static $AudioFrameLengthCache = array();
[1966] Fix | Delete
[1967] Fix | Delete
if (!isset($AudioFrameLengthCache[$bitrate][$version][$layer][$padding][$samplerate])) {
[1968] Fix | Delete
$AudioFrameLengthCache[$bitrate][$version][$layer][$padding][$samplerate] = false;
[1969] Fix | Delete
if ($bitrate != 'free') {
[1970] Fix | Delete
[1971] Fix | Delete
if ($version == '1') {
[1972] Fix | Delete
[1973] Fix | Delete
if ($layer == '1') {
[1974] Fix | Delete
[1975] Fix | Delete
// For Layer I slot is 32 bits long
[1976] Fix | Delete
$FrameLengthCoefficient = 48;
[1977] Fix | Delete
$SlotLength = 4;
[1978] Fix | Delete
[1979] Fix | Delete
} else { // Layer 2 / 3
[1980] Fix | Delete
[1981] Fix | Delete
// for Layer 2 and Layer 3 slot is 8 bits long.
[1982] Fix | Delete
$FrameLengthCoefficient = 144;
[1983] Fix | Delete
$SlotLength = 1;
[1984] Fix | Delete
[1985] Fix | Delete
}
[1986] Fix | Delete
[1987] Fix | Delete
} else { // MPEG-2 / MPEG-2.5
[1988] Fix | Delete
[1989] Fix | Delete
if ($layer == '1') {
[1990] Fix | Delete
[1991] Fix | Delete
// For Layer I slot is 32 bits long
[1992] Fix | Delete
$FrameLengthCoefficient = 24;
[1993] Fix | Delete
$SlotLength = 4;
[1994] Fix | Delete
[1995] Fix | Delete
} elseif ($layer == '2') {
[1996] Fix | Delete
[1997] Fix | Delete
// for Layer 2 and Layer 3 slot is 8 bits long.
[1998] Fix | Delete
$FrameLengthCoefficient = 144;
[1999] Fix | Delete
It is recommended that you Edit text format, this type of Fix handles quite a lot in one request
Function