wp/wp-includes/ID3/module.audio.mp3.php
changeset 7 cf61fcea0001
parent 5 5e2f62d02dcd
child 16 a86126ab1dd4
equal deleted inserted replaced
6:490d5cc509ed 7:cf61fcea0001
    32 
    32 
    33 		$initialOffset = $info['avdataoffset'];
    33 		$initialOffset = $info['avdataoffset'];
    34 
    34 
    35 		if (!$this->getOnlyMPEGaudioInfo($info['avdataoffset'])) {
    35 		if (!$this->getOnlyMPEGaudioInfo($info['avdataoffset'])) {
    36 			if ($this->allow_bruteforce) {
    36 			if ($this->allow_bruteforce) {
    37 				$info['error'][] = 'Rescanning file in BruteForce mode';
    37 				$this->error('Rescanning file in BruteForce mode');
    38 				$this->getOnlyMPEGaudioInfoBruteForce($this->getid3->fp, $info);
    38 				$this->getOnlyMPEGaudioInfoBruteForce($this->getid3->fp, $info);
    39 			}
    39 			}
    40 		}
    40 		}
    41 
    41 
    42 
    42 
    70 					$CurrentDataLAMEversionString = 'LAME3.';
    70 					$CurrentDataLAMEversionString = 'LAME3.';
    71 
    71 
    72 				}
    72 				}
    73 
    73 
    74 			}
    74 			}
    75 			$info['warning'][] = $synchoffsetwarning;
    75 			$this->warning($synchoffsetwarning);
    76 
    76 
    77 		}
    77 		}
    78 
    78 
    79 		if (isset($info['mpeg']['audio']['LAME'])) {
    79 		if (isset($info['mpeg']['audio']['LAME'])) {
    80 			$info['audio']['codec'] = 'LAME';
    80 			$info['audio']['codec'] = 'LAME';
   132 				case 'mp3':
   132 				case 'mp3':
   133 					$info['fileformat'] = $info['audio']['dataformat'];
   133 					$info['fileformat'] = $info['audio']['dataformat'];
   134 					break;
   134 					break;
   135 
   135 
   136 				default:
   136 				default:
   137 					$info['warning'][] = 'Expecting [audio][dataformat] to be mp1/mp2/mp3 when fileformat == mp3, [audio][dataformat] actually "'.$info['audio']['dataformat'].'"';
   137 					$this->warning('Expecting [audio][dataformat] to be mp1/mp2/mp3 when fileformat == mp3, [audio][dataformat] actually "'.$info['audio']['dataformat'].'"');
   138 					break;
   138 					break;
   139 			}
   139 			}
   140 		}
   140 		}
   141 
   141 
   142 		if (empty($info['fileformat'])) {
   142 		if (empty($info['fileformat'])) {
   422 			$MPEGaudioModeExtensionLookup = self::MPEGaudioModeExtensionArray();
   422 			$MPEGaudioModeExtensionLookup = self::MPEGaudioModeExtensionArray();
   423 			$MPEGaudioEmphasisLookup      = self::MPEGaudioEmphasisArray();
   423 			$MPEGaudioEmphasisLookup      = self::MPEGaudioEmphasisArray();
   424 		}
   424 		}
   425 
   425 
   426 		if ($this->fseek($offset) != 0) {
   426 		if ($this->fseek($offset) != 0) {
   427 			$info['error'][] = 'decodeMPEGaudioHeader() failed to seek to next offset at '.$offset;
   427 			$this->error('decodeMPEGaudioHeader() failed to seek to next offset at '.$offset);
   428 			return false;
   428 			return false;
   429 		}
   429 		}
   430 		//$headerstring = $this->fread(1441); // worst-case max length = 32kHz @ 320kbps layer 3 = 1441 bytes/frame
   430 		//$headerstring = $this->fread(1441); // worst-case max length = 32kHz @ 320kbps layer 3 = 1441 bytes/frame
   431 		$headerstring = $this->fread(226); // LAME header at offset 36 + 190 bytes of Xing/LAME data
   431 		$headerstring = $this->fread(226); // LAME header at offset 36 + 190 bytes of Xing/LAME data
   432 
   432 
   435 		// where $aa..$aa is the four-byte mpeg-audio header (below)
   435 		// where $aa..$aa is the four-byte mpeg-audio header (below)
   436 		// $bb $bb is the optional 2-byte CRC
   436 		// $bb $bb is the optional 2-byte CRC
   437 		// and $cc... is the audio data
   437 		// and $cc... is the audio data
   438 
   438 
   439 		$head4 = substr($headerstring, 0, 4);
   439 		$head4 = substr($headerstring, 0, 4);
   440 
   440 		$head4_key = getid3_lib::PrintHexBytes($head4, true, false, false);
   441 		static $MPEGaudioHeaderDecodeCache = array();
   441 		static $MPEGaudioHeaderDecodeCache = array();
   442 		if (isset($MPEGaudioHeaderDecodeCache[$head4])) {
   442 		if (isset($MPEGaudioHeaderDecodeCache[$head4_key])) {
   443 			$MPEGheaderRawArray = $MPEGaudioHeaderDecodeCache[$head4];
   443 			$MPEGheaderRawArray = $MPEGaudioHeaderDecodeCache[$head4_key];
   444 		} else {
   444 		} else {
   445 			$MPEGheaderRawArray = self::MPEGaudioHeaderDecode($head4);
   445 			$MPEGheaderRawArray = self::MPEGaudioHeaderDecode($head4);
   446 			$MPEGaudioHeaderDecodeCache[$head4] = $MPEGheaderRawArray;
   446 			$MPEGaudioHeaderDecodeCache[$head4_key] = $MPEGheaderRawArray;
   447 		}
   447 		}
   448 
   448 
   449 		static $MPEGaudioHeaderValidCache = array();
   449 		static $MPEGaudioHeaderValidCache = array();
   450 		if (!isset($MPEGaudioHeaderValidCache[$head4])) { // Not in cache
   450 		if (!isset($MPEGaudioHeaderValidCache[$head4_key])) { // Not in cache
   451 			//$MPEGaudioHeaderValidCache[$head4] = self::MPEGaudioHeaderValid($MPEGheaderRawArray, false, true);  // allow badly-formatted freeformat (from LAME 3.90 - 3.93.1)
   451 			//$MPEGaudioHeaderValidCache[$head4_key] = self::MPEGaudioHeaderValid($MPEGheaderRawArray, false, true);  // allow badly-formatted freeformat (from LAME 3.90 - 3.93.1)
   452 			$MPEGaudioHeaderValidCache[$head4] = self::MPEGaudioHeaderValid($MPEGheaderRawArray, false, false);
   452 			$MPEGaudioHeaderValidCache[$head4_key] = self::MPEGaudioHeaderValid($MPEGheaderRawArray, false, false);
   453 		}
   453 		}
   454 
   454 
   455 		// shortcut
   455 		// shortcut
   456 		if (!isset($info['mpeg']['audio'])) {
   456 		if (!isset($info['mpeg']['audio'])) {
   457 			$info['mpeg']['audio'] = array();
   457 			$info['mpeg']['audio'] = array();
   458 		}
   458 		}
   459 		$thisfile_mpeg_audio = &$info['mpeg']['audio'];
   459 		$thisfile_mpeg_audio = &$info['mpeg']['audio'];
   460 
   460 
   461 
   461 
   462 		if ($MPEGaudioHeaderValidCache[$head4]) {
   462 		if ($MPEGaudioHeaderValidCache[$head4_key]) {
   463 			$thisfile_mpeg_audio['raw'] = $MPEGheaderRawArray;
   463 			$thisfile_mpeg_audio['raw'] = $MPEGheaderRawArray;
   464 		} else {
   464 		} else {
   465 			$info['error'][] = 'Invalid MPEG audio header ('.getid3_lib::PrintHexBytes($head4).') at offset '.$offset;
   465 			$this->error('Invalid MPEG audio header ('.getid3_lib::PrintHexBytes($head4).') at offset '.$offset);
   466 			return false;
   466 			return false;
   467 		}
   467 		}
   468 
   468 
   469 		if (!$FastMPEGheaderScan) {
   469 		if (!$FastMPEGheaderScan) {
   470 			$thisfile_mpeg_audio['version']       = $MPEGaudioVersionLookup[$thisfile_mpeg_audio['raw']['version']];
   470 			$thisfile_mpeg_audio['version']       = $MPEGaudioVersionLookup[$thisfile_mpeg_audio['raw']['version']];
   488 			}
   488 			}
   489 		}
   489 		}
   490 
   490 
   491 		if ($thisfile_mpeg_audio['raw']['bitrate'] == 15) {
   491 		if ($thisfile_mpeg_audio['raw']['bitrate'] == 15) {
   492 			// http://www.hydrogenaudio.org/?act=ST&f=16&t=9682&st=0
   492 			// http://www.hydrogenaudio.org/?act=ST&f=16&t=9682&st=0
   493 			$info['warning'][] = 'Invalid bitrate index (15), this is a known bug in free-format MP3s encoded by LAME v3.90 - 3.93.1';
   493 			$this->warning('Invalid bitrate index (15), this is a known bug in free-format MP3s encoded by LAME v3.90 - 3.93.1');
   494 			$thisfile_mpeg_audio['raw']['bitrate'] = 0;
   494 			$thisfile_mpeg_audio['raw']['bitrate'] = 0;
   495 		}
   495 		}
   496 		$thisfile_mpeg_audio['padding'] = (bool) $thisfile_mpeg_audio['raw']['padding'];
   496 		$thisfile_mpeg_audio['padding'] = (bool) $thisfile_mpeg_audio['raw']['padding'];
   497 		$thisfile_mpeg_audio['bitrate'] = $MPEGaudioBitrateLookup[$thisfile_mpeg_audio['version']][$thisfile_mpeg_audio['layer']][$thisfile_mpeg_audio['raw']['bitrate']];
   497 		$thisfile_mpeg_audio['bitrate'] = $MPEGaudioBitrateLookup[$thisfile_mpeg_audio['version']][$thisfile_mpeg_audio['layer']][$thisfile_mpeg_audio['raw']['bitrate']];
   498 
   498 
   510 
   510 
   511 				case 'mono':
   511 				case 'mono':
   512 					if (($thisfile_mpeg_audio['bitrate'] == 'free') || ($thisfile_mpeg_audio['bitrate'] <= 192000)) {
   512 					if (($thisfile_mpeg_audio['bitrate'] == 'free') || ($thisfile_mpeg_audio['bitrate'] <= 192000)) {
   513 						// these are ok
   513 						// these are ok
   514 					} else {
   514 					} else {
   515 						$info['error'][] = $thisfile_mpeg_audio['bitrate'].'kbps not allowed in Layer 2, '.$thisfile_mpeg_audio['channelmode'].'.';
   515 						$this->error($thisfile_mpeg_audio['bitrate'].'kbps not allowed in Layer 2, '.$thisfile_mpeg_audio['channelmode'].'.');
   516 						return false;
   516 						return false;
   517 					}
   517 					}
   518 					break;
   518 					break;
   519 
   519 
   520 				case 'stereo':
   520 				case 'stereo':
   521 				case 'joint stereo':
   521 				case 'joint stereo':
   522 				case 'dual channel':
   522 				case 'dual channel':
   523 					if (($thisfile_mpeg_audio['bitrate'] == 'free') || ($thisfile_mpeg_audio['bitrate'] == 64000) || ($thisfile_mpeg_audio['bitrate'] >= 96000)) {
   523 					if (($thisfile_mpeg_audio['bitrate'] == 'free') || ($thisfile_mpeg_audio['bitrate'] == 64000) || ($thisfile_mpeg_audio['bitrate'] >= 96000)) {
   524 						// these are ok
   524 						// these are ok
   525 					} else {
   525 					} else {
   526 						$info['error'][] = intval(round($thisfile_mpeg_audio['bitrate'] / 1000)).'kbps not allowed in Layer 2, '.$thisfile_mpeg_audio['channelmode'].'.';
   526 						$this->error(intval(round($thisfile_mpeg_audio['bitrate'] / 1000)).'kbps not allowed in Layer 2, '.$thisfile_mpeg_audio['channelmode'].'.');
   527 						return false;
   527 						return false;
   528 					}
   528 					}
   529 					break;
   529 					break;
   530 
   530 
   531 			}
   531 			}
   543 			$info['audio']['bitrate'] = $thisfile_mpeg_audio['bitrate'];
   543 			$info['audio']['bitrate'] = $thisfile_mpeg_audio['bitrate'];
   544 
   544 
   545 			if (isset($thisfile_mpeg_audio['framelength'])) {
   545 			if (isset($thisfile_mpeg_audio['framelength'])) {
   546 				$nextframetestoffset = $offset + $thisfile_mpeg_audio['framelength'];
   546 				$nextframetestoffset = $offset + $thisfile_mpeg_audio['framelength'];
   547 			} else {
   547 			} else {
   548 				$info['error'][] = 'Frame at offset('.$offset.') is has an invalid frame length.';
   548 				$this->error('Frame at offset('.$offset.') is has an invalid frame length.');
   549 				return false;
   549 				return false;
   550 			}
   550 			}
   551 
   551 
   552 		}
   552 		}
   553 
   553 
   646 				if ($thisfile_mpeg_audio['xing_flags']['bytes']) {
   646 				if ($thisfile_mpeg_audio['xing_flags']['bytes']) {
   647 					$thisfile_mpeg_audio['VBR_bytes']  = getid3_lib::BigEndian2Int(substr($headerstring, $VBRidOffset + 12, 4));
   647 					$thisfile_mpeg_audio['VBR_bytes']  = getid3_lib::BigEndian2Int(substr($headerstring, $VBRidOffset + 12, 4));
   648 				}
   648 				}
   649 
   649 
   650 				//if (($thisfile_mpeg_audio['bitrate'] == 'free') && !empty($thisfile_mpeg_audio['VBR_frames']) && !empty($thisfile_mpeg_audio['VBR_bytes'])) {
   650 				//if (($thisfile_mpeg_audio['bitrate'] == 'free') && !empty($thisfile_mpeg_audio['VBR_frames']) && !empty($thisfile_mpeg_audio['VBR_bytes'])) {
   651 				if (!empty($thisfile_mpeg_audio['VBR_frames']) && !empty($thisfile_mpeg_audio['VBR_bytes'])) {
   651 				//if (!empty($thisfile_mpeg_audio['VBR_frames']) && !empty($thisfile_mpeg_audio['VBR_bytes'])) {
   652 
   652 				if (!empty($thisfile_mpeg_audio['VBR_frames'])) {
   653 					$framelengthfloat = $thisfile_mpeg_audio['VBR_bytes'] / $thisfile_mpeg_audio['VBR_frames'];
   653 					$used_filesize  = 0;
       
   654 					if (!empty($thisfile_mpeg_audio['VBR_bytes'])) {
       
   655 						$used_filesize = $thisfile_mpeg_audio['VBR_bytes'];
       
   656 					} elseif (!empty($info['filesize'])) {
       
   657 						$used_filesize  = $info['filesize'];
       
   658 						$used_filesize -= intval(@$info['id3v2']['headerlength']);
       
   659 						$used_filesize -= (isset($info['id3v1']) ? 128 : 0);
       
   660 						$used_filesize -= (isset($info['tag_offset_end']) ? $info['tag_offset_end'] - $info['tag_offset_start'] : 0);
       
   661 						$this->warning('MP3.Xing header missing VBR_bytes, assuming MPEG audio portion of file is '.number_format($used_filesize).' bytes');
       
   662 					}
       
   663 
       
   664 					$framelengthfloat = $used_filesize / $thisfile_mpeg_audio['VBR_frames'];
   654 
   665 
   655 					if ($thisfile_mpeg_audio['layer'] == '1') {
   666 					if ($thisfile_mpeg_audio['layer'] == '1') {
   656 						// BitRate = (((FrameLengthInBytes / 4) - Padding) * SampleRate) / 12
   667 						// BitRate = (((FrameLengthInBytes / 4) - Padding) * SampleRate) / 12
   657 						//$info['audio']['bitrate'] = ((($framelengthfloat / 4) - intval($thisfile_mpeg_audio['padding'])) * $thisfile_mpeg_audio['sample_rate']) / 12;
   668 						//$info['audio']['bitrate'] = ((($framelengthfloat / 4) - intval($thisfile_mpeg_audio['padding'])) * $thisfile_mpeg_audio['sample_rate']) / 12;
   658 						$info['audio']['bitrate'] = ($framelengthfloat / 4) * $thisfile_mpeg_audio['sample_rate'] * (2 / $info['audio']['channels']) / 12;
   669 						$info['audio']['bitrate'] = ($framelengthfloat / 4) * $thisfile_mpeg_audio['sample_rate'] * (2 / $info['audio']['channels']) / 12;
   835 						$thisfile_mpeg_audio_lame_raw['surround_info'] = ($PresetSurroundBytes & 0x3800);
   846 						$thisfile_mpeg_audio_lame_raw['surround_info'] = ($PresetSurroundBytes & 0x3800);
   836 						$thisfile_mpeg_audio_lame['surround_info']     = self::LAMEsurroundInfoLookup($thisfile_mpeg_audio_lame_raw['surround_info']);
   847 						$thisfile_mpeg_audio_lame['surround_info']     = self::LAMEsurroundInfoLookup($thisfile_mpeg_audio_lame_raw['surround_info']);
   837 						$thisfile_mpeg_audio_lame['preset_used_id']    = ($PresetSurroundBytes & 0x07FF);
   848 						$thisfile_mpeg_audio_lame['preset_used_id']    = ($PresetSurroundBytes & 0x07FF);
   838 						$thisfile_mpeg_audio_lame['preset_used']       = self::LAMEpresetUsedLookup($thisfile_mpeg_audio_lame);
   849 						$thisfile_mpeg_audio_lame['preset_used']       = self::LAMEpresetUsedLookup($thisfile_mpeg_audio_lame);
   839 						if (!empty($thisfile_mpeg_audio_lame['preset_used_id']) && empty($thisfile_mpeg_audio_lame['preset_used'])) {
   850 						if (!empty($thisfile_mpeg_audio_lame['preset_used_id']) && empty($thisfile_mpeg_audio_lame['preset_used'])) {
   840 							$info['warning'][] = 'Unknown LAME preset used ('.$thisfile_mpeg_audio_lame['preset_used_id'].') - please report to info@getid3.org';
   851 							$this->warning('Unknown LAME preset used ('.$thisfile_mpeg_audio_lame['preset_used_id'].') - please report to info@getid3.org');
   841 						}
   852 						}
   842 						if (($thisfile_mpeg_audio_lame['short_version'] == 'LAME3.90.') && !empty($thisfile_mpeg_audio_lame['preset_used_id'])) {
   853 						if (($thisfile_mpeg_audio_lame['short_version'] == 'LAME3.90.') && !empty($thisfile_mpeg_audio_lame['preset_used_id'])) {
   843 							// this may change if 3.90.4 ever comes out
   854 							// this may change if 3.90.4 ever comes out
   844 							$thisfile_mpeg_audio_lame['short_version'] = 'LAME3.90.3';
   855 							$thisfile_mpeg_audio_lame['short_version'] = 'LAME3.90.3';
   845 						}
   856 						}
   879 					if ($this->RecursiveFrameScanning($offset, $nextframetestoffset, true)) {
   890 					if ($this->RecursiveFrameScanning($offset, $nextframetestoffset, true)) {
   880 						$recursivesearch = false;
   891 						$recursivesearch = false;
   881 						$thisfile_mpeg_audio['bitrate_mode'] = 'cbr';
   892 						$thisfile_mpeg_audio['bitrate_mode'] = 'cbr';
   882 					}
   893 					}
   883 					if ($thisfile_mpeg_audio['bitrate_mode'] == 'vbr') {
   894 					if ($thisfile_mpeg_audio['bitrate_mode'] == 'vbr') {
   884 						$info['warning'][] = 'VBR file with no VBR header. Bitrate values calculated from actual frame bitrates.';
   895 						$this->warning('VBR file with no VBR header. Bitrate values calculated from actual frame bitrates.');
   885 					}
   896 					}
   886 				}
   897 				}
   887 
   898 
   888 			}
   899 			}
   889 
   900 
   906 				//	$this->fseek($info['avdataend']);
   917 				//	$this->fseek($info['avdataend']);
   907 				//	$PossibleNullByte = $this->fread(1);
   918 				//	$PossibleNullByte = $this->fread(1);
   908 				//	$this->fseek($prenullbytefileoffset);
   919 				//	$this->fseek($prenullbytefileoffset);
   909 				//	if ($PossibleNullByte === "\x00") {
   920 				//	if ($PossibleNullByte === "\x00") {
   910 						$info['avdataend']--;
   921 						$info['avdataend']--;
   911 				//		$info['warning'][] = 'Extra null byte at end of MP3 data assumed to be RIFF padding and therefore ignored';
   922 				//		$this->warning('Extra null byte at end of MP3 data assumed to be RIFF padding and therefore ignored');
   912 				//	} else {
   923 				//	} else {
   913 				//		$info['warning'][] = 'Too much data in file: expecting '.$ExpectedNumberOfAudioBytes.' bytes of audio data, found '.($info['avdataend'] - $info['avdataoffset']).' ('.(($info['avdataend'] - $info['avdataoffset']) - $ExpectedNumberOfAudioBytes).' bytes too many)';
   924 				//		$this->warning('Too much data in file: expecting '.$ExpectedNumberOfAudioBytes.' bytes of audio data, found '.($info['avdataend'] - $info['avdataoffset']).' ('.(($info['avdataend'] - $info['avdataoffset']) - $ExpectedNumberOfAudioBytes).' bytes too many)');
   914 				//	}
   925 				//	}
   915 				} else {
   926 				} else {
   916 					$info['warning'][] = 'Too much data in file: expecting '.$ExpectedNumberOfAudioBytes.' bytes of audio data, found '.($info['avdataend'] - $info['avdataoffset']).' ('.(($info['avdataend'] - $info['avdataoffset']) - $ExpectedNumberOfAudioBytes).' bytes too many)';
   927 					$this->warning('Too much data in file: expecting '.$ExpectedNumberOfAudioBytes.' bytes of audio data, found '.($info['avdataend'] - $info['avdataoffset']).' ('.(($info['avdataend'] - $info['avdataoffset']) - $ExpectedNumberOfAudioBytes).' bytes too many)');
   917 				}
   928 				}
   918 			}
   929 			}
   919 		}
   930 		}
   920 
   931 
   921 		if (($thisfile_mpeg_audio['bitrate'] == 'free') && empty($info['audio']['bitrate'])) {
   932 		if (($thisfile_mpeg_audio['bitrate'] == 'free') && empty($info['audio']['bitrate'])) {
   929 					} else {
   940 					} else {
   930 						// Bitrate = ((FrameLengthInBytes - Padding) * SampleRate) / 144
   941 						// Bitrate = ((FrameLengthInBytes - Padding) * SampleRate) / 144
   931 						$info['audio']['bitrate'] = (($framebytelength - intval($thisfile_mpeg_audio['padding'])) * $thisfile_mpeg_audio['sample_rate']) / 144;
   942 						$info['audio']['bitrate'] = (($framebytelength - intval($thisfile_mpeg_audio['padding'])) * $thisfile_mpeg_audio['sample_rate']) / 144;
   932 					}
   943 					}
   933 				} else {
   944 				} else {
   934 					$info['error'][] = 'Error calculating frame length of free-format MP3 without Xing/LAME header';
   945 					$this->error('Error calculating frame length of free-format MP3 without Xing/LAME header');
   935 				}
   946 				}
   936 			}
   947 			}
   937 		}
   948 		}
   938 
   949 
   939 		if (isset($thisfile_mpeg_audio['VBR_frames']) ? $thisfile_mpeg_audio['VBR_frames'] : '') {
   950 		if (isset($thisfile_mpeg_audio['VBR_frames']) ? $thisfile_mpeg_audio['VBR_frames'] : '') {
   946 					} elseif ((($thisfile_mpeg_audio['version'] == '2') || ($thisfile_mpeg_audio['version'] == '2.5')) && ($thisfile_mpeg_audio['layer'] == 3)) {
   957 					} elseif ((($thisfile_mpeg_audio['version'] == '2') || ($thisfile_mpeg_audio['version'] == '2.5')) && ($thisfile_mpeg_audio['layer'] == 3)) {
   947 						$bytes_per_frame = 576;
   958 						$bytes_per_frame = 576;
   948 					}
   959 					}
   949 					$thisfile_mpeg_audio['VBR_bitrate'] = (isset($thisfile_mpeg_audio['VBR_bytes']) ? (($thisfile_mpeg_audio['VBR_bytes'] / $thisfile_mpeg_audio['VBR_frames']) * 8) * ($info['audio']['sample_rate'] / $bytes_per_frame) : 0);
   960 					$thisfile_mpeg_audio['VBR_bitrate'] = (isset($thisfile_mpeg_audio['VBR_bytes']) ? (($thisfile_mpeg_audio['VBR_bytes'] / $thisfile_mpeg_audio['VBR_frames']) * 8) * ($info['audio']['sample_rate'] / $bytes_per_frame) : 0);
   950 					if ($thisfile_mpeg_audio['VBR_bitrate'] > 0) {
   961 					if ($thisfile_mpeg_audio['VBR_bitrate'] > 0) {
   951 						$info['audio']['bitrate']         = $thisfile_mpeg_audio['VBR_bitrate'];
   962 						$info['audio']['bitrate']       = $thisfile_mpeg_audio['VBR_bitrate'];
   952 						$thisfile_mpeg_audio['bitrate'] = $thisfile_mpeg_audio['VBR_bitrate']; // to avoid confusion
   963 						$thisfile_mpeg_audio['bitrate'] = $thisfile_mpeg_audio['VBR_bitrate']; // to avoid confusion
   953 					}
   964 					}
   954 					break;
   965 					break;
   955 			}
   966 			}
   956 		}
   967 		}
  1072 		return true;
  1083 		return true;
  1073 	}
  1084 	}
  1074 
  1085 
  1075 	public function RecursiveFrameScanning(&$offset, &$nextframetestoffset, $ScanAsCBR) {
  1086 	public function RecursiveFrameScanning(&$offset, &$nextframetestoffset, $ScanAsCBR) {
  1076 		$info = &$this->getid3->info;
  1087 		$info = &$this->getid3->info;
  1077 		$firstframetestarray = array('error'=>'', 'warning'=>'', 'avdataend'=>$info['avdataend'], 'avdataoffset'=>$info['avdataoffset']);
  1088 		$firstframetestarray = array('error' => array(), 'warning'=> array(), 'avdataend' => $info['avdataend'], 'avdataoffset' => $info['avdataoffset']);
  1078 		$this->decodeMPEGaudioHeader($offset, $firstframetestarray, false);
  1089 		$this->decodeMPEGaudioHeader($offset, $firstframetestarray, false);
  1079 
  1090 
  1080 		for ($i = 0; $i < GETID3_MP3_VALID_CHECK_FRAMES; $i++) {
  1091 		for ($i = 0; $i < GETID3_MP3_VALID_CHECK_FRAMES; $i++) {
  1081 			// check next GETID3_MP3_VALID_CHECK_FRAMES frames for validity, to make sure we haven't run across a false synch
  1092 			// check next GETID3_MP3_VALID_CHECK_FRAMES frames for validity, to make sure we haven't run across a false synch
  1082 			if (($nextframetestoffset + 4) >= $info['avdataend']) {
  1093 			if (($nextframetestoffset + 4) >= $info['avdataend']) {
  1083 				// end of file
  1094 				// end of file
  1084 				return true;
  1095 				return true;
  1085 			}
  1096 			}
  1086 
  1097 
  1087 			$nextframetestarray = array('error'=>'', 'warning'=>'', 'avdataend'=>$info['avdataend'], 'avdataoffset'=>$info['avdataoffset']);
  1098 			$nextframetestarray = array('error' => array(), 'warning' => array(), 'avdataend' => $info['avdataend'], 'avdataoffset'=>$info['avdataoffset']);
  1088 			if ($this->decodeMPEGaudioHeader($nextframetestoffset, $nextframetestarray, false)) {
  1099 			if ($this->decodeMPEGaudioHeader($nextframetestoffset, $nextframetestarray, false)) {
  1089 				if ($ScanAsCBR) {
  1100 				if ($ScanAsCBR) {
  1090 					// force CBR mode, used for trying to pick out invalid audio streams with valid(?) VBR headers, or VBR streams with no VBR header
  1101 					// force CBR mode, used for trying to pick out invalid audio streams with valid(?) VBR headers, or VBR streams with no VBR header
  1091 					if (!isset($nextframetestarray['mpeg']['audio']['bitrate']) || !isset($firstframetestarray['mpeg']['audio']['bitrate']) || ($nextframetestarray['mpeg']['audio']['bitrate'] != $firstframetestarray['mpeg']['audio']['bitrate'])) {
  1102 					if (!isset($nextframetestarray['mpeg']['audio']['bitrate']) || !isset($firstframetestarray['mpeg']['audio']['bitrate']) || ($nextframetestarray['mpeg']['audio']['bitrate'] != $firstframetestarray['mpeg']['audio']['bitrate'])) {
  1092 						return false;
  1103 						return false;
  1096 
  1107 
  1097 				// next frame is OK, get ready to check the one after that
  1108 				// next frame is OK, get ready to check the one after that
  1098 				if (isset($nextframetestarray['mpeg']['audio']['framelength']) && ($nextframetestarray['mpeg']['audio']['framelength'] > 0)) {
  1109 				if (isset($nextframetestarray['mpeg']['audio']['framelength']) && ($nextframetestarray['mpeg']['audio']['framelength'] > 0)) {
  1099 					$nextframetestoffset += $nextframetestarray['mpeg']['audio']['framelength'];
  1110 					$nextframetestoffset += $nextframetestarray['mpeg']['audio']['framelength'];
  1100 				} else {
  1111 				} else {
  1101 					$info['error'][] = 'Frame at offset ('.$offset.') is has an invalid frame length.';
  1112 					$this->error('Frame at offset ('.$offset.') is has an invalid frame length.');
  1102 					return false;
  1113 					return false;
  1103 				}
  1114 				}
  1104 
  1115 
  1105 			} elseif (!empty($firstframetestarray['mpeg']['audio']['framelength']) && (($nextframetestoffset + $firstframetestarray['mpeg']['audio']['framelength']) > $info['avdataend'])) {
  1116 			} elseif (!empty($firstframetestarray['mpeg']['audio']['framelength']) && (($nextframetestoffset + $firstframetestarray['mpeg']['audio']['framelength']) > $info['avdataend'])) {
  1106 
  1117 
  1108 				return true;
  1119 				return true;
  1109 
  1120 
  1110 			} else {
  1121 			} else {
  1111 
  1122 
  1112 				// next frame is not valid, note the error and fail, so scanning can contiue for a valid frame sequence
  1123 				// next frame is not valid, note the error and fail, so scanning can contiue for a valid frame sequence
  1113 				$info['warning'][] = 'Frame at offset ('.$offset.') is valid, but the next one at ('.$nextframetestoffset.') is not.';
  1124 				$this->warning('Frame at offset ('.$offset.') is valid, but the next one at ('.$nextframetestoffset.') is not.');
  1114 
  1125 
  1115 				return false;
  1126 				return false;
  1116 			}
  1127 			}
  1117 		}
  1128 		}
  1118 		return true;
  1129 		return true;
  1151 			}
  1162 			}
  1152 			if (($framelength2 > 4) && ($framelength2 < $framelength1)) {
  1163 			if (($framelength2 > 4) && ($framelength2 < $framelength1)) {
  1153 				$framelength = $framelength2;
  1164 				$framelength = $framelength2;
  1154 			}
  1165 			}
  1155 			if (!$framelength) {
  1166 			if (!$framelength) {
  1156 				$info['error'][] = 'Cannot find next free-format synch pattern ('.getid3_lib::PrintHexBytes($SyncPattern1).' or '.getid3_lib::PrintHexBytes($SyncPattern2).') after offset '.$offset;
  1167 				$this->error('Cannot find next free-format synch pattern ('.getid3_lib::PrintHexBytes($SyncPattern1).' or '.getid3_lib::PrintHexBytes($SyncPattern2).') after offset '.$offset);
  1157 				return false;
  1168 				return false;
  1158 			} else {
  1169 			} else {
  1159 				$info['warning'][] = 'ModeExtension varies between first frame and other frames (known free-format issue in LAME 3.88)';
  1170 				$this->warning('ModeExtension varies between first frame and other frames (known free-format issue in LAME 3.88)');
  1160 				$info['audio']['codec']   = 'LAME';
  1171 				$info['audio']['codec']   = 'LAME';
  1161 				$info['audio']['encoder'] = 'LAME3.88';
  1172 				$info['audio']['encoder'] = 'LAME3.88';
  1162 				$SyncPattern1 = substr($SyncPattern1, 0, 3);
  1173 				$SyncPattern1 = substr($SyncPattern1, 0, 3);
  1163 				$SyncPattern2 = substr($SyncPattern2, 0, 3);
  1174 				$SyncPattern2 = substr($SyncPattern2, 0, 3);
  1164 			}
  1175 			}
  1181 				} elseif ((substr($NextSyncPattern, 2, strlen($SyncPattern1)) == $SyncPattern1) || (substr($NextSyncPattern, 2, strlen($SyncPattern2)) == $SyncPattern2)) {
  1192 				} elseif ((substr($NextSyncPattern, 2, strlen($SyncPattern1)) == $SyncPattern1) || (substr($NextSyncPattern, 2, strlen($SyncPattern2)) == $SyncPattern2)) {
  1182 					// ok - found one byte later than expected (last frame was padded, first frame wasn't)
  1193 					// ok - found one byte later than expected (last frame was padded, first frame wasn't)
  1183 					$ActualFrameLengthValues[] = ($framelength + 1);
  1194 					$ActualFrameLengthValues[] = ($framelength + 1);
  1184 					$nextoffset++;
  1195 					$nextoffset++;
  1185 				} else {
  1196 				} else {
  1186 					$info['error'][] = 'Did not find expected free-format sync pattern at offset '.$nextoffset;
  1197 					$this->error('Did not find expected free-format sync pattern at offset '.$nextoffset);
  1187 					return false;
  1198 					return false;
  1188 				}
  1199 				}
  1189 				$nextoffset += $framelength;
  1200 				$nextoffset += $framelength;
  1190 			}
  1201 			}
  1191 			if (count($ActualFrameLengthValues) > 0) {
  1202 			if (count($ActualFrameLengthValues) > 0) {
  1279 							getid3_lib::safe_inc($Distribution['version'][$LongMPEGversionLookup[$head4]]);
  1290 							getid3_lib::safe_inc($Distribution['version'][$LongMPEGversionLookup[$head4]]);
  1280 							getid3_lib::safe_inc($Distribution['padding'][intval($LongMPEGpaddingLookup[$head4])]);
  1291 							getid3_lib::safe_inc($Distribution['padding'][intval($LongMPEGpaddingLookup[$head4])]);
  1281 							getid3_lib::safe_inc($Distribution['frequency'][$LongMPEGfrequencyLookup[$head4]]);
  1292 							getid3_lib::safe_inc($Distribution['frequency'][$LongMPEGfrequencyLookup[$head4]]);
  1282 							if ($max_frames_scan && (++$frames_scanned >= $max_frames_scan)) {
  1293 							if ($max_frames_scan && (++$frames_scanned >= $max_frames_scan)) {
  1283 								$pct_data_scanned = ($this->ftell() - $info['avdataoffset']) / ($info['avdataend'] - $info['avdataoffset']);
  1294 								$pct_data_scanned = ($this->ftell() - $info['avdataoffset']) / ($info['avdataend'] - $info['avdataoffset']);
  1284 								$info['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.';
  1295 								$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.');
  1285 								foreach ($Distribution as $key1 => $value1) {
  1296 								foreach ($Distribution as $key1 => $value1) {
  1286 									foreach ($value1 as $key2 => $value2) {
  1297 									foreach ($value1 as $key2 => $value2) {
  1287 										$Distribution[$key1][$key2] = round($value2 / $pct_data_scanned);
  1298 										$Distribution[$key1][$key2] = round($value2 / $pct_data_scanned);
  1288 									}
  1299 									}
  1289 								}
  1300 								}
  1306 		$info['mpeg']['audio']['frequency_distribution'] = $Distribution['frequency'];
  1317 		$info['mpeg']['audio']['frequency_distribution'] = $Distribution['frequency'];
  1307 		$info['mpeg']['audio']['layer_distribution']     = $Distribution['layer'];
  1318 		$info['mpeg']['audio']['layer_distribution']     = $Distribution['layer'];
  1308 		$info['mpeg']['audio']['version_distribution']   = $Distribution['version'];
  1319 		$info['mpeg']['audio']['version_distribution']   = $Distribution['version'];
  1309 		$info['mpeg']['audio']['padding_distribution']   = $Distribution['padding'];
  1320 		$info['mpeg']['audio']['padding_distribution']   = $Distribution['padding'];
  1310 		if (count($Distribution['version']) > 1) {
  1321 		if (count($Distribution['version']) > 1) {
  1311 			$info['error'][] = 'Corrupt file - more than one MPEG version detected';
  1322 			$this->error('Corrupt file - more than one MPEG version detected');
  1312 		}
  1323 		}
  1313 		if (count($Distribution['layer']) > 1) {
  1324 		if (count($Distribution['layer']) > 1) {
  1314 			$info['error'][] = 'Corrupt file - more than one MPEG layer detected';
  1325 			$this->error('Corrupt file - more than one MPEG layer detected');
  1315 		}
  1326 		}
  1316 		if (count($Distribution['frequency']) > 1) {
  1327 		if (count($Distribution['frequency']) > 1) {
  1317 			$info['error'][] = 'Corrupt file - more than one MPEG sample rate detected';
  1328 			$this->error('Corrupt file - more than one MPEG sample rate detected');
  1318 		}
  1329 		}
  1319 
  1330 
  1320 
  1331 
  1321 		$bittotal = 0;
  1332 		$bittotal = 0;
  1322 		foreach ($Distribution['bitrate'] as $bitratevalue => $bitratecount) {
  1333 		foreach ($Distribution['bitrate'] as $bitratevalue => $bitratecount) {
  1324 				$bittotal += ($bitratevalue * $bitratecount);
  1335 				$bittotal += ($bitratevalue * $bitratecount);
  1325 			}
  1336 			}
  1326 		}
  1337 		}
  1327 		$info['mpeg']['audio']['frame_count']  = array_sum($Distribution['bitrate']);
  1338 		$info['mpeg']['audio']['frame_count']  = array_sum($Distribution['bitrate']);
  1328 		if ($info['mpeg']['audio']['frame_count'] == 0) {
  1339 		if ($info['mpeg']['audio']['frame_count'] == 0) {
  1329 			$info['error'][] = 'no MPEG audio frames found';
  1340 			$this->error('no MPEG audio frames found');
  1330 			return false;
  1341 			return false;
  1331 		}
  1342 		}
  1332 		$info['mpeg']['audio']['bitrate']      = ($bittotal / $info['mpeg']['audio']['frame_count']);
  1343 		$info['mpeg']['audio']['bitrate']      = ($bittotal / $info['mpeg']['audio']['frame_count']);
  1333 		$info['mpeg']['audio']['bitrate_mode'] = ((count($Distribution['bitrate']) > 0) ? 'vbr' : 'cbr');
  1344 		$info['mpeg']['audio']['bitrate_mode'] = ((count($Distribution['bitrate']) > 0) ? 'vbr' : 'cbr');
  1334 		$info['mpeg']['audio']['sample_rate']  = getid3_lib::array_max($Distribution['frequency'], true);
  1345 		$info['mpeg']['audio']['sample_rate']  = getid3_lib::array_max($Distribution['frequency'], true);
  1359 		}
  1370 		}
  1360 
  1371 
  1361 		$this->fseek($avdataoffset);
  1372 		$this->fseek($avdataoffset);
  1362 		$sync_seek_buffer_size = min(128 * 1024, $info['avdataend'] - $avdataoffset);
  1373 		$sync_seek_buffer_size = min(128 * 1024, $info['avdataend'] - $avdataoffset);
  1363 		if ($sync_seek_buffer_size <= 0) {
  1374 		if ($sync_seek_buffer_size <= 0) {
  1364 			$info['error'][] = 'Invalid $sync_seek_buffer_size at offset '.$avdataoffset;
  1375 			$this->error('Invalid $sync_seek_buffer_size at offset '.$avdataoffset);
  1365 			return false;
  1376 			return false;
  1366 		}
  1377 		}
  1367 		$header = $this->fread($sync_seek_buffer_size);
  1378 		$header = $this->fread($sync_seek_buffer_size);
  1368 		$sync_seek_buffer_size = strlen($header);
  1379 		$sync_seek_buffer_size = strlen($header);
  1369 		$SynchSeekOffset = 0;
  1380 		$SynchSeekOffset = 0;
  1370 		while ($SynchSeekOffset < $sync_seek_buffer_size) {
  1381 		while ($SynchSeekOffset < $sync_seek_buffer_size) {
  1371 			if ((($avdataoffset + $SynchSeekOffset)  < $info['avdataend']) && !feof($this->getid3->fp)) {
  1382 			if ((($avdataoffset + $SynchSeekOffset)  < $info['avdataend']) && !feof($this->getid3->fp)) {
  1372 
  1383 
  1373 				if ($SynchSeekOffset > $sync_seek_buffer_size) {
  1384 				if ($SynchSeekOffset > $sync_seek_buffer_size) {
  1374 					// if a synch's not found within the first 128k bytes, then give up
  1385 					// if a synch's not found within the first 128k bytes, then give up
  1375 					$info['error'][] = 'Could not find valid MPEG audio synch within the first '.round($sync_seek_buffer_size / 1024).'kB';
  1386 					$this->error('Could not find valid MPEG audio synch within the first '.round($sync_seek_buffer_size / 1024).'kB');
  1376 					if (isset($info['audio']['bitrate'])) {
  1387 					if (isset($info['audio']['bitrate'])) {
  1377 						unset($info['audio']['bitrate']);
  1388 						unset($info['audio']['bitrate']);
  1378 					}
  1389 					}
  1379 					if (isset($info['mpeg']['audio'])) {
  1390 					if (isset($info['mpeg']['audio'])) {
  1380 						unset($info['mpeg']['audio']);
  1391 						unset($info['mpeg']['audio']);
  1384 					}
  1395 					}
  1385 					return false;
  1396 					return false;
  1386 
  1397 
  1387 				} elseif (feof($this->getid3->fp)) {
  1398 				} elseif (feof($this->getid3->fp)) {
  1388 
  1399 
  1389 					$info['error'][] = 'Could not find valid MPEG audio synch before end of file';
  1400 					$this->error('Could not find valid MPEG audio synch before end of file');
  1390 					if (isset($info['audio']['bitrate'])) {
  1401 					if (isset($info['audio']['bitrate'])) {
  1391 						unset($info['audio']['bitrate']);
  1402 						unset($info['audio']['bitrate']);
  1392 					}
  1403 					}
  1393 					if (isset($info['mpeg']['audio'])) {
  1404 					if (isset($info['mpeg']['audio'])) {
  1394 						unset($info['mpeg']['audio']);
  1405 						unset($info['mpeg']['audio']);
  1399 					return false;
  1410 					return false;
  1400 				}
  1411 				}
  1401 			}
  1412 			}
  1402 
  1413 
  1403 			if (($SynchSeekOffset + 1) >= strlen($header)) {
  1414 			if (($SynchSeekOffset + 1) >= strlen($header)) {
  1404 				$info['error'][] = 'Could not find valid MPEG synch before end of file';
  1415 				$this->error('Could not find valid MPEG synch before end of file');
  1405 				return false;
  1416 				return false;
  1406 			}
  1417 			}
  1407 
  1418 
  1408 			if (($header{$SynchSeekOffset} == "\xFF") && ($header{($SynchSeekOffset + 1)} > "\xE0")) { // synch detected
  1419 			if (($header{$SynchSeekOffset} == "\xFF") && ($header{($SynchSeekOffset + 1)} > "\xE0")) { // synch detected
  1409 				if (!isset($FirstFrameThisfileInfo) && !isset($info['mpeg']['audio'])) {
  1420 				if (!isset($FirstFrameThisfileInfo) && !isset($info['mpeg']['audio'])) {
  1442 							$GarbageOffsetStart = $FirstFrameAVDataOffset + $FirstFrameThisfileInfo['mpeg']['audio']['framelength'];
  1453 							$GarbageOffsetStart = $FirstFrameAVDataOffset + $FirstFrameThisfileInfo['mpeg']['audio']['framelength'];
  1443 							$GarbageOffsetEnd   = $avdataoffset + $SynchSeekOffset;
  1454 							$GarbageOffsetEnd   = $avdataoffset + $SynchSeekOffset;
  1444 							if ($this->decodeMPEGaudioHeader($GarbageOffsetEnd, $dummy, true, true)) {
  1455 							if ($this->decodeMPEGaudioHeader($GarbageOffsetEnd, $dummy, true, true)) {
  1445 								$info = $dummy;
  1456 								$info = $dummy;
  1446 								$info['avdataoffset'] = $GarbageOffsetEnd;
  1457 								$info['avdataoffset'] = $GarbageOffsetEnd;
  1447 								$info['warning'][] = 'apparently-valid VBR header not used because could not find '.GETID3_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;
  1458 								$this->warning('apparently-valid VBR header not used because could not find '.GETID3_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);
  1448 							} else {
  1459 							} else {
  1449 								$info['warning'][] = 'using data from VBR header even though could not find '.GETID3_MP3_VALID_CHECK_FRAMES.' consecutive MPEG-audio frames immediately after VBR header (garbage data for '.($GarbageOffsetEnd - $GarbageOffsetStart).' bytes between '.$GarbageOffsetStart.' and '.$GarbageOffsetEnd.')';
  1460 								$this->warning('using data from VBR header even though could not find '.GETID3_MP3_VALID_CHECK_FRAMES.' consecutive MPEG-audio frames immediately after VBR header (garbage data for '.($GarbageOffsetEnd - $GarbageOffsetStart).' bytes between '.$GarbageOffsetStart.' and '.$GarbageOffsetEnd.')');
  1450 							}
  1461 							}
  1451 						}
  1462 						}
  1452 					}
  1463 					}
  1453 					if (isset($info['mpeg']['audio']['bitrate_mode']) && ($info['mpeg']['audio']['bitrate_mode'] == 'vbr') && !isset($info['mpeg']['audio']['VBR_method'])) {
  1464 					if (isset($info['mpeg']['audio']['bitrate_mode']) && ($info['mpeg']['audio']['bitrate_mode'] == 'vbr') && !isset($info['mpeg']['audio']['VBR_method'])) {
  1454 						// VBR file with no VBR header
  1465 						// VBR file with no VBR header
  1537 									}
  1548 									}
  1538 								}
  1549 								}
  1539 							}
  1550 							}
  1540 						}
  1551 						}
  1541 						if ($pct_data_scanned > 0) {
  1552 						if ($pct_data_scanned > 0) {
  1542 							$info['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.';
  1553 							$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.');
  1543 							foreach ($info['mpeg']['audio'] as $key1 => $value1) {
  1554 							foreach ($info['mpeg']['audio'] as $key1 => $value1) {
  1544 								if (!preg_match('#_distribution$#i', $key1)) {
  1555 								if (!preg_match('#_distribution$#i', $key1)) {
  1545 									continue;
  1556 									continue;
  1546 								}
  1557 								}
  1547 								foreach ($value1 as $key2 => $value2) {
  1558 								foreach ($value1 as $key2 => $value2) {
  1549 								}
  1560 								}
  1550 							}
  1561 							}
  1551 						}
  1562 						}
  1552 
  1563 
  1553 						if ($SynchErrorsFound > 0) {
  1564 						if ($SynchErrorsFound > 0) {
  1554 							$info['warning'][] = 'Found '.$SynchErrorsFound.' synch errors in histogram analysis';
  1565 							$this->warning('Found '.$SynchErrorsFound.' synch errors in histogram analysis');
  1555 							//return false;
  1566 							//return false;
  1556 						}
  1567 						}
  1557 
  1568 
  1558 						$bittotal     = 0;
  1569 						$bittotal     = 0;
  1559 						$framecounter = 0;
  1570 						$framecounter = 0;
  1562 							if ($bitratevalue != 'free') {
  1573 							if ($bitratevalue != 'free') {
  1563 								$bittotal += ($bitratevalue * $bitratecount);
  1574 								$bittotal += ($bitratevalue * $bitratecount);
  1564 							}
  1575 							}
  1565 						}
  1576 						}
  1566 						if ($framecounter == 0) {
  1577 						if ($framecounter == 0) {
  1567 							$info['error'][] = 'Corrupt MP3 file: framecounter == zero';
  1578 							$this->error('Corrupt MP3 file: framecounter == zero');
  1568 							return false;
  1579 							return false;
  1569 						}
  1580 						}
  1570 						$info['mpeg']['audio']['frame_count'] = getid3_lib::CastAsInt($framecounter);
  1581 						$info['mpeg']['audio']['frame_count'] = getid3_lib::CastAsInt($framecounter);
  1571 						$info['mpeg']['audio']['bitrate']     = ($bittotal / $framecounter);
  1582 						$info['mpeg']['audio']['bitrate']     = ($bittotal / $framecounter);
  1572 
  1583 
  1597 			if (($avdataoffset + $SynchSeekOffset) >= $info['avdataend']) {
  1608 			if (($avdataoffset + $SynchSeekOffset) >= $info['avdataend']) {
  1598 				// end of file/data
  1609 				// end of file/data
  1599 
  1610 
  1600 				if (empty($info['mpeg']['audio'])) {
  1611 				if (empty($info['mpeg']['audio'])) {
  1601 
  1612 
  1602 					$info['error'][] = 'could not find valid MPEG synch before end of file';
  1613 					$this->error('could not find valid MPEG synch before end of file');
  1603 					if (isset($info['audio']['bitrate'])) {
  1614 					if (isset($info['audio']['bitrate'])) {
  1604 						unset($info['audio']['bitrate']);
  1615 						unset($info['audio']['bitrate']);
  1605 					}
  1616 					}
  1606 					if (isset($info['mpeg']['audio'])) {
  1617 					if (isset($info['mpeg']['audio'])) {
  1607 						unset($info['mpeg']['audio']);
  1618 						unset($info['mpeg']['audio']);