wp/wp-includes/ID3/module.audio.mp3.php
changeset 21 48c4eec2b7e6
parent 19 3d72ae0968f4
equal deleted inserted replaced
20:7b1b88e27a20 21:48c4eec2b7e6
   313 		}
   313 		}
   314 		if (!empty($thisfile_mpeg_audio_lame['bitrate_min'])) {
   314 		if (!empty($thisfile_mpeg_audio_lame['bitrate_min'])) {
   315 			$encoder_options .= ' -b'.$thisfile_mpeg_audio_lame['bitrate_min'];
   315 			$encoder_options .= ' -b'.$thisfile_mpeg_audio_lame['bitrate_min'];
   316 		}
   316 		}
   317 
   317 
       
   318 		if (isset($thisfile_mpeg_audio['bitrate']) && $thisfile_mpeg_audio['bitrate'] === 'free') {
       
   319 			$encoder_options .= ' --freeformat';
       
   320 		}
       
   321 
   318 		if (!empty($thisfile_mpeg_audio_lame['encoding_flags']['nogap_prev']) || !empty($thisfile_mpeg_audio_lame['encoding_flags']['nogap_next'])) {
   322 		if (!empty($thisfile_mpeg_audio_lame['encoding_flags']['nogap_prev']) || !empty($thisfile_mpeg_audio_lame['encoding_flags']['nogap_next'])) {
   319 			$encoder_options .= ' --nogap';
   323 			$encoder_options .= ' --nogap';
   320 		}
   324 		}
   321 
   325 
   322 		if (!empty($thisfile_mpeg_audio_lame['lowpass_frequency'])) {
   326 		if (!empty($thisfile_mpeg_audio_lame['lowpass_frequency'])) {
   748 
   752 
   749 							// extra 11 chars are not part of version string when LAMEtag present
   753 							// extra 11 chars are not part of version string when LAMEtag present
   750 							unset($thisfile_mpeg_audio_lame['long_version']);
   754 							unset($thisfile_mpeg_audio_lame['long_version']);
   751 
   755 
   752 							// It the LAME tag was only introduced in LAME v3.90
   756 							// It the LAME tag was only introduced in LAME v3.90
   753 							// http://www.hydrogenaudio.org/?act=ST&f=15&t=9933
   757 							// https://wiki.hydrogenaud.io/index.php/LAME#VBR_header_and_LAME_tag
       
   758 							// https://hydrogenaud.io/index.php?topic=9933
   754 
   759 
   755 							// Offsets of various bytes in http://gabriel.mp3-tech.org/mp3infotag.html
   760 							// Offsets of various bytes in http://gabriel.mp3-tech.org/mp3infotag.html
   756 							// are assuming a 'Xing' identifier offset of 0x24, which is the case for
   761 							// are assuming a 'Xing' identifier offset of 0x24, which is the case for
   757 							// MPEG-1 non-mono, but not for other combinations
   762 							// MPEG-1 non-mono, but not for other combinations
   758 							$LAMEtagOffsetContant = $VBRidOffset - 0x24;
   763 							$LAMEtagOffsetContant = $VBRidOffset - 0x24;
   784 
   789 
   785 							// byte $A6  Lowpass filter value
   790 							// byte $A6  Lowpass filter value
   786 							$thisfile_mpeg_audio_lame['lowpass_frequency'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xA6, 1)) * 100;
   791 							$thisfile_mpeg_audio_lame['lowpass_frequency'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xA6, 1)) * 100;
   787 
   792 
   788 							// bytes $A7-$AE  Replay Gain
   793 							// bytes $A7-$AE  Replay Gain
   789 							// http://privatewww.essex.ac.uk/~djmrob/replaygain/rg_data_format.html
   794 							// https://web.archive.org/web/20021015212753/http://privatewww.essex.ac.uk/~djmrob/replaygain/rg_data_format.html
   790 							// bytes $A7-$AA : 32 bit floating point "Peak signal amplitude"
   795 							// bytes $A7-$AA : 32 bit floating point "Peak signal amplitude"
   791 							if ($thisfile_mpeg_audio_lame['short_version'] >= 'LAME3.94b') {
   796 							if ($thisfile_mpeg_audio_lame['short_version'] >= 'LAME3.94b') {
   792 								// LAME 3.94a16 and later - 9.23 fixed point
   797 								// LAME 3.94a16 and later - 9.23 fixed point
   793 								// ie 0x0059E2EE / (2^23) = 5890798 / 8388608 = 0.7022378444671630859375
   798 								// ie 0x0059E2EE / (2^23) = 5890798 / 8388608 = 0.7022378444671630859375
   794 								$thisfile_mpeg_audio_lame_RGAD['peak_amplitude'] = (float) ((getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xA7, 4))) / 8388608);
   799 								$thisfile_mpeg_audio_lame_RGAD['peak_amplitude'] = (float) ((getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xA7, 4))) / 8388608);
   912 							// bytes $BE-$BF  CRC-16 of Info Tag
   917 							// bytes $BE-$BF  CRC-16 of Info Tag
   913 							$thisfile_mpeg_audio_lame['lame_tag_crc'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xBE, 2));
   918 							$thisfile_mpeg_audio_lame['lame_tag_crc'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xBE, 2));
   914 
   919 
   915 
   920 
   916 							// LAME CBR
   921 							// LAME CBR
   917 							if ($thisfile_mpeg_audio_lame_raw['vbr_method'] == 1) {
   922 							if ($thisfile_mpeg_audio_lame_raw['vbr_method'] == 1 && $thisfile_mpeg_audio['bitrate'] !== 'free') {
   918 
   923 
   919 								$thisfile_mpeg_audio['bitrate_mode'] = 'cbr';
   924 								$thisfile_mpeg_audio['bitrate_mode'] = 'cbr';
   920 								$thisfile_mpeg_audio['bitrate'] = self::ClosestStandardMP3Bitrate($thisfile_mpeg_audio['bitrate']);
   925 								$thisfile_mpeg_audio['bitrate'] = self::ClosestStandardMP3Bitrate($thisfile_mpeg_audio['bitrate']);
   921 								$info['audio']['bitrate'] = $thisfile_mpeg_audio['bitrate'];
   926 								$info['audio']['bitrate'] = $thisfile_mpeg_audio['bitrate'];
   922 								//if (empty($thisfile_mpeg_audio['bitrate']) || (!empty($thisfile_mpeg_audio_lame['bitrate_min']) && ($thisfile_mpeg_audio_lame['bitrate_min'] != 255))) {
   927 								//if (empty($thisfile_mpeg_audio['bitrate']) || (!empty($thisfile_mpeg_audio_lame['bitrate_min']) && ($thisfile_mpeg_audio_lame['bitrate_min'] != 255))) {
  1167 				return true;
  1172 				return true;
  1168 			}
  1173 			}
  1169 
  1174 
  1170 			$nextframetestarray = array('error' => array(), 'warning' => array(), 'avdataend' => $info['avdataend'], 'avdataoffset'=>$info['avdataoffset']);
  1175 			$nextframetestarray = array('error' => array(), 'warning' => array(), 'avdataend' => $info['avdataend'], 'avdataoffset'=>$info['avdataoffset']);
  1171 			if ($this->decodeMPEGaudioHeader($nextframetestoffset, $nextframetestarray, false)) {
  1176 			if ($this->decodeMPEGaudioHeader($nextframetestoffset, $nextframetestarray, false)) {
       
  1177 				/** @phpstan-ignore-next-line */
  1172 				getid3_lib::safe_inc($info['mp3_validity_check_bitrates'][$nextframetestarray['mpeg']['audio']['bitrate']]);
  1178 				getid3_lib::safe_inc($info['mp3_validity_check_bitrates'][$nextframetestarray['mpeg']['audio']['bitrate']]);
  1173 				if ($ScanAsCBR) {
  1179 				if ($ScanAsCBR) {
  1174 					// force CBR mode, used for trying to pick out invalid audio streams with valid(?) VBR headers, or VBR streams with no VBR header
  1180 					// force CBR mode, used for trying to pick out invalid audio streams with valid(?) VBR headers, or VBR streams with no VBR header
  1175 					if (!isset($nextframetestarray['mpeg']['audio']['bitrate']) || !isset($firstframetestarray['mpeg']['audio']['bitrate']) || ($nextframetestarray['mpeg']['audio']['bitrate'] != $firstframetestarray['mpeg']['audio']['bitrate'])) {
  1181 					if (!isset($nextframetestarray['mpeg']['audio']['bitrate']) || !isset($firstframetestarray['mpeg']['audio']['bitrate']) || ($nextframetestarray['mpeg']['audio']['bitrate'] != $firstframetestarray['mpeg']['audio']['bitrate'])) {
  1176 						return false;
  1182 						return false;
  1372 							$Distribution['layer'][$LongMPEGlayerLookup[$head4]] = isset($Distribution['layer'][$LongMPEGlayerLookup[$head4]]) ? ++$Distribution['layer'][$LongMPEGlayerLookup[$head4]] : 1;
  1378 							$Distribution['layer'][$LongMPEGlayerLookup[$head4]] = isset($Distribution['layer'][$LongMPEGlayerLookup[$head4]]) ? ++$Distribution['layer'][$LongMPEGlayerLookup[$head4]] : 1;
  1373 							$Distribution['version'][$LongMPEGversionLookup[$head4]] = isset($Distribution['version'][$LongMPEGversionLookup[$head4]]) ? ++$Distribution['version'][$LongMPEGversionLookup[$head4]] : 1;
  1379 							$Distribution['version'][$LongMPEGversionLookup[$head4]] = isset($Distribution['version'][$LongMPEGversionLookup[$head4]]) ? ++$Distribution['version'][$LongMPEGversionLookup[$head4]] : 1;
  1374 							$Distribution['padding'][intval($LongMPEGpaddingLookup[$head4])] = isset($Distribution['padding'][intval($LongMPEGpaddingLookup[$head4])]) ? ++$Distribution['padding'][intval($LongMPEGpaddingLookup[$head4])] : 1;
  1380 							$Distribution['padding'][intval($LongMPEGpaddingLookup[$head4])] = isset($Distribution['padding'][intval($LongMPEGpaddingLookup[$head4])]) ? ++$Distribution['padding'][intval($LongMPEGpaddingLookup[$head4])] : 1;
  1375 							$Distribution['frequency'][$LongMPEGfrequencyLookup[$head4]] = isset($Distribution['frequency'][$LongMPEGfrequencyLookup[$head4]]) ? ++$Distribution['frequency'][$LongMPEGfrequencyLookup[$head4]] : 1;
  1381 							$Distribution['frequency'][$LongMPEGfrequencyLookup[$head4]] = isset($Distribution['frequency'][$LongMPEGfrequencyLookup[$head4]]) ? ++$Distribution['frequency'][$LongMPEGfrequencyLookup[$head4]] : 1;
  1376 							if (++$frames_scanned >= $max_frames_scan) {
  1382 							if (++$frames_scanned >= $max_frames_scan) {
  1377 								$pct_data_scanned = ($this->ftell() - $info['avdataoffset']) / ($info['avdataend'] - $info['avdataoffset']);
  1383 								$pct_data_scanned = getid3_lib::SafeDiv($this->ftell() - $info['avdataoffset'], $info['avdataend'] - $info['avdataoffset']);
  1378 								$this->warning('too many MPEG audio frames to scan, only scanned first '.$max_frames_scan.' frames ('.number_format($pct_data_scanned * 100, 1).'% of file) and extrapolated distribution, playtime and bitrate may be incorrect.');
  1384 								$this->warning('too many MPEG audio frames to scan, only scanned first '.$max_frames_scan.' frames ('.number_format($pct_data_scanned * 100, 1).'% of file) and extrapolated distribution, playtime and bitrate may be incorrect.');
  1379 								foreach ($Distribution as $key1 => $value1) {
  1385 								foreach ($Distribution as $key1 => $value1) {
  1380 									foreach ($value1 as $key2 => $value2) {
  1386 									foreach ($value1 as $key2 => $value2) {
  1381 										$Distribution[$key1][$key2] = round($value2 / $pct_data_scanned);
  1387 										$Distribution[$key1][$key2] = $pct_data_scanned ? round($value2 / $pct_data_scanned) : 1;
  1382 									}
  1388 									}
  1383 								}
  1389 								}
  1384 								break;
  1390 								break;
  1385 							}
  1391 							}
  1386 							continue;
  1392 							continue;
  1467 		$SynchSeekOffset = 0;
  1473 		$SynchSeekOffset = 0;
  1468 		$SyncSeekAttempts = 0;
  1474 		$SyncSeekAttempts = 0;
  1469 		$SyncSeekAttemptsMax = 1000;
  1475 		$SyncSeekAttemptsMax = 1000;
  1470 		$FirstFrameThisfileInfo = null;
  1476 		$FirstFrameThisfileInfo = null;
  1471 		while ($SynchSeekOffset < $sync_seek_buffer_size) {
  1477 		while ($SynchSeekOffset < $sync_seek_buffer_size) {
  1472 			if ((($avdataoffset + $SynchSeekOffset)  < $info['avdataend']) && !feof($this->getid3->fp)) {
  1478 			if ((($avdataoffset + $SynchSeekOffset)  < $info['avdataend']) && !$this->feof()) {
  1473 
  1479 
  1474 				if ($SynchSeekOffset > $sync_seek_buffer_size) {
  1480 				if ($SynchSeekOffset > $sync_seek_buffer_size) {
  1475 					// if a synch's not found within the first 128k bytes, then give up
  1481 					// if a synch's not found within the first 128k bytes, then give up
  1476 					$this->error('Could not find valid MPEG audio synch within the first '.round($sync_seek_buffer_size / 1024).'kB');
  1482 					$this->error('Could not find valid MPEG audio synch within the first '.round($sync_seek_buffer_size / 1024).'kB');
  1477 					if (isset($info['audio']['bitrate'])) {
  1483 					if (isset($info['audio']['bitrate'])) {
  1479 					}
  1485 					}
  1480 					if (isset($info['mpeg']['audio'])) {
  1486 					if (isset($info['mpeg']['audio'])) {
  1481 						unset($info['mpeg']['audio']);
  1487 						unset($info['mpeg']['audio']);
  1482 					}
  1488 					}
  1483 					if (empty($info['mpeg'])) {
  1489 					if (empty($info['mpeg'])) {
  1484 						unset($info['mpeg']);
       
  1485 					}
       
  1486 					return false;
       
  1487 
       
  1488 				} elseif (feof($this->getid3->fp)) {
       
  1489 
       
  1490 					$this->error('Could not find valid MPEG audio synch before end of file');
       
  1491 					if (isset($info['audio']['bitrate'])) {
       
  1492 						unset($info['audio']['bitrate']);
       
  1493 					}
       
  1494 					if (isset($info['mpeg']['audio'])) {
       
  1495 						unset($info['mpeg']['audio']);
       
  1496 					}
       
  1497 					if (isset($info['mpeg']) && (!is_array($info['mpeg']) || (count($info['mpeg']) == 0))) {
       
  1498 						unset($info['mpeg']);
  1490 						unset($info['mpeg']);
  1499 					}
  1491 					}
  1500 					return false;
  1492 					return false;
  1501 				}
  1493 				}
  1502 			}
  1494 			}
  1644 									getid3_lib::safe_inc($info['mpeg']['audio']['version_distribution'][$dummy['mpeg']['audio']['version']]);
  1636 									getid3_lib::safe_inc($info['mpeg']['audio']['version_distribution'][$dummy['mpeg']['audio']['version']]);
  1645 									$synchstartoffset += $dummy['mpeg']['audio']['framelength'];
  1637 									$synchstartoffset += $dummy['mpeg']['audio']['framelength'];
  1646 								}
  1638 								}
  1647 								$frames_scanned++;
  1639 								$frames_scanned++;
  1648 								if ($frames_scan_per_segment && (++$frames_scanned_this_segment >= $frames_scan_per_segment)) {
  1640 								if ($frames_scan_per_segment && (++$frames_scanned_this_segment >= $frames_scan_per_segment)) {
  1649 									$this_pct_scanned = ($this->ftell() - $scan_start_offset[$current_segment]) / ($info['avdataend'] - $info['avdataoffset']);
  1641 									$this_pct_scanned = getid3_lib::SafeDiv($this->ftell() - $scan_start_offset[$current_segment], $info['avdataend'] - $info['avdataoffset']);
  1650 									if (($current_segment == 0) && (($this_pct_scanned * $max_scan_segments) >= 1)) {
  1642 									if (($current_segment == 0) && (($this_pct_scanned * $max_scan_segments) >= 1)) {
  1651 										// file likely contains < $max_frames_scan, just scan as one segment
  1643 										// file likely contains < $max_frames_scan, just scan as one segment
  1652 										$max_scan_segments = 1;
  1644 										$max_scan_segments = 1;
  1653 										$frames_scan_per_segment = $max_frames_scan;
  1645 										$frames_scan_per_segment = $max_frames_scan;
  1654 									} else {
  1646 									} else {
  1735 				break;
  1727 				break;
  1736 			}
  1728 			}
  1737 
  1729 
  1738 		}
  1730 		}
  1739 		$info['audio']['channels']        = $info['mpeg']['audio']['channels'];
  1731 		$info['audio']['channels']        = $info['mpeg']['audio']['channels'];
       
  1732 		if ($info['audio']['channels'] < 1) {
       
  1733 			$this->error('Corrupt MP3 file: no channels');
       
  1734 			return false;
       
  1735 		}
  1740 		$info['audio']['channelmode']     = $info['mpeg']['audio']['channelmode'];
  1736 		$info['audio']['channelmode']     = $info['mpeg']['audio']['channelmode'];
  1741 		$info['audio']['sample_rate']     = $info['mpeg']['audio']['sample_rate'];
  1737 		$info['audio']['sample_rate']     = $info['mpeg']['audio']['sample_rate'];
  1742 		return true;
  1738 		return true;
  1743 	}
  1739 	}
  1744 
  1740