wp/wp-includes/ID3/module.audio.mp3.php
changeset 7 cf61fcea0001
parent 5 5e2f62d02dcd
child 16 a86126ab1dd4
--- a/wp/wp-includes/ID3/module.audio.mp3.php	Tue Jun 09 11:14:17 2015 +0000
+++ b/wp/wp-includes/ID3/module.audio.mp3.php	Mon Oct 14 17:39:30 2019 +0200
@@ -34,7 +34,7 @@
 
 		if (!$this->getOnlyMPEGaudioInfo($info['avdataoffset'])) {
 			if ($this->allow_bruteforce) {
-				$info['error'][] = 'Rescanning file in BruteForce mode';
+				$this->error('Rescanning file in BruteForce mode');
 				$this->getOnlyMPEGaudioInfoBruteForce($this->getid3->fp, $info);
 			}
 		}
@@ -72,7 +72,7 @@
 				}
 
 			}
-			$info['warning'][] = $synchoffsetwarning;
+			$this->warning($synchoffsetwarning);
 
 		}
 
@@ -134,7 +134,7 @@
 					break;
 
 				default:
-					$info['warning'][] = 'Expecting [audio][dataformat] to be mp1/mp2/mp3 when fileformat == mp3, [audio][dataformat] actually "'.$info['audio']['dataformat'].'"';
+					$this->warning('Expecting [audio][dataformat] to be mp1/mp2/mp3 when fileformat == mp3, [audio][dataformat] actually "'.$info['audio']['dataformat'].'"');
 					break;
 			}
 		}
@@ -424,7 +424,7 @@
 		}
 
 		if ($this->fseek($offset) != 0) {
-			$info['error'][] = 'decodeMPEGaudioHeader() failed to seek to next offset at '.$offset;
+			$this->error('decodeMPEGaudioHeader() failed to seek to next offset at '.$offset);
 			return false;
 		}
 		//$headerstring = $this->fread(1441); // worst-case max length = 32kHz @ 320kbps layer 3 = 1441 bytes/frame
@@ -437,19 +437,19 @@
 		// and $cc... is the audio data
 
 		$head4 = substr($headerstring, 0, 4);
-
+		$head4_key = getid3_lib::PrintHexBytes($head4, true, false, false);
 		static $MPEGaudioHeaderDecodeCache = array();
-		if (isset($MPEGaudioHeaderDecodeCache[$head4])) {
-			$MPEGheaderRawArray = $MPEGaudioHeaderDecodeCache[$head4];
+		if (isset($MPEGaudioHeaderDecodeCache[$head4_key])) {
+			$MPEGheaderRawArray = $MPEGaudioHeaderDecodeCache[$head4_key];
 		} else {
 			$MPEGheaderRawArray = self::MPEGaudioHeaderDecode($head4);
-			$MPEGaudioHeaderDecodeCache[$head4] = $MPEGheaderRawArray;
+			$MPEGaudioHeaderDecodeCache[$head4_key] = $MPEGheaderRawArray;
 		}
 
 		static $MPEGaudioHeaderValidCache = array();
-		if (!isset($MPEGaudioHeaderValidCache[$head4])) { // Not in cache
-			//$MPEGaudioHeaderValidCache[$head4] = self::MPEGaudioHeaderValid($MPEGheaderRawArray, false, true);  // allow badly-formatted freeformat (from LAME 3.90 - 3.93.1)
-			$MPEGaudioHeaderValidCache[$head4] = self::MPEGaudioHeaderValid($MPEGheaderRawArray, false, false);
+		if (!isset($MPEGaudioHeaderValidCache[$head4_key])) { // Not in cache
+			//$MPEGaudioHeaderValidCache[$head4_key] = self::MPEGaudioHeaderValid($MPEGheaderRawArray, false, true);  // allow badly-formatted freeformat (from LAME 3.90 - 3.93.1)
+			$MPEGaudioHeaderValidCache[$head4_key] = self::MPEGaudioHeaderValid($MPEGheaderRawArray, false, false);
 		}
 
 		// shortcut
@@ -459,10 +459,10 @@
 		$thisfile_mpeg_audio = &$info['mpeg']['audio'];
 
 
-		if ($MPEGaudioHeaderValidCache[$head4]) {
+		if ($MPEGaudioHeaderValidCache[$head4_key]) {
 			$thisfile_mpeg_audio['raw'] = $MPEGheaderRawArray;
 		} else {
-			$info['error'][] = 'Invalid MPEG audio header ('.getid3_lib::PrintHexBytes($head4).') at offset '.$offset;
+			$this->error('Invalid MPEG audio header ('.getid3_lib::PrintHexBytes($head4).') at offset '.$offset);
 			return false;
 		}
 
@@ -490,7 +490,7 @@
 
 		if ($thisfile_mpeg_audio['raw']['bitrate'] == 15) {
 			// http://www.hydrogenaudio.org/?act=ST&f=16&t=9682&st=0
-			$info['warning'][] = 'Invalid bitrate index (15), this is a known bug in free-format MP3s encoded by LAME v3.90 - 3.93.1';
+			$this->warning('Invalid bitrate index (15), this is a known bug in free-format MP3s encoded by LAME v3.90 - 3.93.1');
 			$thisfile_mpeg_audio['raw']['bitrate'] = 0;
 		}
 		$thisfile_mpeg_audio['padding'] = (bool) $thisfile_mpeg_audio['raw']['padding'];
@@ -512,7 +512,7 @@
 					if (($thisfile_mpeg_audio['bitrate'] == 'free') || ($thisfile_mpeg_audio['bitrate'] <= 192000)) {
 						// these are ok
 					} else {
-						$info['error'][] = $thisfile_mpeg_audio['bitrate'].'kbps not allowed in Layer 2, '.$thisfile_mpeg_audio['channelmode'].'.';
+						$this->error($thisfile_mpeg_audio['bitrate'].'kbps not allowed in Layer 2, '.$thisfile_mpeg_audio['channelmode'].'.');
 						return false;
 					}
 					break;
@@ -523,7 +523,7 @@
 					if (($thisfile_mpeg_audio['bitrate'] == 'free') || ($thisfile_mpeg_audio['bitrate'] == 64000) || ($thisfile_mpeg_audio['bitrate'] >= 96000)) {
 						// these are ok
 					} else {
-						$info['error'][] = intval(round($thisfile_mpeg_audio['bitrate'] / 1000)).'kbps not allowed in Layer 2, '.$thisfile_mpeg_audio['channelmode'].'.';
+						$this->error(intval(round($thisfile_mpeg_audio['bitrate'] / 1000)).'kbps not allowed in Layer 2, '.$thisfile_mpeg_audio['channelmode'].'.');
 						return false;
 					}
 					break;
@@ -545,7 +545,7 @@
 			if (isset($thisfile_mpeg_audio['framelength'])) {
 				$nextframetestoffset = $offset + $thisfile_mpeg_audio['framelength'];
 			} else {
-				$info['error'][] = 'Frame at offset('.$offset.') is has an invalid frame length.';
+				$this->error('Frame at offset('.$offset.') is has an invalid frame length.');
 				return false;
 			}
 
@@ -648,9 +648,20 @@
 				}
 
 				//if (($thisfile_mpeg_audio['bitrate'] == 'free') && !empty($thisfile_mpeg_audio['VBR_frames']) && !empty($thisfile_mpeg_audio['VBR_bytes'])) {
-				if (!empty($thisfile_mpeg_audio['VBR_frames']) && !empty($thisfile_mpeg_audio['VBR_bytes'])) {
+				//if (!empty($thisfile_mpeg_audio['VBR_frames']) && !empty($thisfile_mpeg_audio['VBR_bytes'])) {
+				if (!empty($thisfile_mpeg_audio['VBR_frames'])) {
+					$used_filesize  = 0;
+					if (!empty($thisfile_mpeg_audio['VBR_bytes'])) {
+						$used_filesize = $thisfile_mpeg_audio['VBR_bytes'];
+					} elseif (!empty($info['filesize'])) {
+						$used_filesize  = $info['filesize'];
+						$used_filesize -= intval(@$info['id3v2']['headerlength']);
+						$used_filesize -= (isset($info['id3v1']) ? 128 : 0);
+						$used_filesize -= (isset($info['tag_offset_end']) ? $info['tag_offset_end'] - $info['tag_offset_start'] : 0);
+						$this->warning('MP3.Xing header missing VBR_bytes, assuming MPEG audio portion of file is '.number_format($used_filesize).' bytes');
+					}
 
-					$framelengthfloat = $thisfile_mpeg_audio['VBR_bytes'] / $thisfile_mpeg_audio['VBR_frames'];
+					$framelengthfloat = $used_filesize / $thisfile_mpeg_audio['VBR_frames'];
 
 					if ($thisfile_mpeg_audio['layer'] == '1') {
 						// BitRate = (((FrameLengthInBytes / 4) - Padding) * SampleRate) / 12
@@ -837,7 +848,7 @@
 						$thisfile_mpeg_audio_lame['preset_used_id']    = ($PresetSurroundBytes & 0x07FF);
 						$thisfile_mpeg_audio_lame['preset_used']       = self::LAMEpresetUsedLookup($thisfile_mpeg_audio_lame);
 						if (!empty($thisfile_mpeg_audio_lame['preset_used_id']) && empty($thisfile_mpeg_audio_lame['preset_used'])) {
-							$info['warning'][] = 'Unknown LAME preset used ('.$thisfile_mpeg_audio_lame['preset_used_id'].') - please report to info@getid3.org';
+							$this->warning('Unknown LAME preset used ('.$thisfile_mpeg_audio_lame['preset_used_id'].') - please report to info@getid3.org');
 						}
 						if (($thisfile_mpeg_audio_lame['short_version'] == 'LAME3.90.') && !empty($thisfile_mpeg_audio_lame['preset_used_id'])) {
 							// this may change if 3.90.4 ever comes out
@@ -881,7 +892,7 @@
 						$thisfile_mpeg_audio['bitrate_mode'] = 'cbr';
 					}
 					if ($thisfile_mpeg_audio['bitrate_mode'] == 'vbr') {
-						$info['warning'][] = 'VBR file with no VBR header. Bitrate values calculated from actual frame bitrates.';
+						$this->warning('VBR file with no VBR header. Bitrate values calculated from actual frame bitrates.');
 					}
 				}
 
@@ -908,12 +919,12 @@
 				//	$this->fseek($prenullbytefileoffset);
 				//	if ($PossibleNullByte === "\x00") {
 						$info['avdataend']--;
-				//		$info['warning'][] = 'Extra null byte at end of MP3 data assumed to be RIFF padding and therefore ignored';
+				//		$this->warning('Extra null byte at end of MP3 data assumed to be RIFF padding and therefore ignored');
 				//	} else {
-				//		$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)';
+				//		$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)');
 				//	}
 				} else {
-					$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)';
+					$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)');
 				}
 			}
 		}
@@ -931,7 +942,7 @@
 						$info['audio']['bitrate'] = (($framebytelength - intval($thisfile_mpeg_audio['padding'])) * $thisfile_mpeg_audio['sample_rate']) / 144;
 					}
 				} else {
-					$info['error'][] = 'Error calculating frame length of free-format MP3 without Xing/LAME header';
+					$this->error('Error calculating frame length of free-format MP3 without Xing/LAME header');
 				}
 			}
 		}
@@ -948,7 +959,7 @@
 					}
 					$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);
 					if ($thisfile_mpeg_audio['VBR_bitrate'] > 0) {
-						$info['audio']['bitrate']         = $thisfile_mpeg_audio['VBR_bitrate'];
+						$info['audio']['bitrate']       = $thisfile_mpeg_audio['VBR_bitrate'];
 						$thisfile_mpeg_audio['bitrate'] = $thisfile_mpeg_audio['VBR_bitrate']; // to avoid confusion
 					}
 					break;
@@ -1074,7 +1085,7 @@
 
 	public function RecursiveFrameScanning(&$offset, &$nextframetestoffset, $ScanAsCBR) {
 		$info = &$this->getid3->info;
-		$firstframetestarray = array('error'=>'', 'warning'=>'', 'avdataend'=>$info['avdataend'], 'avdataoffset'=>$info['avdataoffset']);
+		$firstframetestarray = array('error' => array(), 'warning'=> array(), 'avdataend' => $info['avdataend'], 'avdataoffset' => $info['avdataoffset']);
 		$this->decodeMPEGaudioHeader($offset, $firstframetestarray, false);
 
 		for ($i = 0; $i < GETID3_MP3_VALID_CHECK_FRAMES; $i++) {
@@ -1084,7 +1095,7 @@
 				return true;
 			}
 
-			$nextframetestarray = array('error'=>'', 'warning'=>'', 'avdataend'=>$info['avdataend'], 'avdataoffset'=>$info['avdataoffset']);
+			$nextframetestarray = array('error' => array(), 'warning' => array(), 'avdataend' => $info['avdataend'], 'avdataoffset'=>$info['avdataoffset']);
 			if ($this->decodeMPEGaudioHeader($nextframetestoffset, $nextframetestarray, false)) {
 				if ($ScanAsCBR) {
 					// force CBR mode, used for trying to pick out invalid audio streams with valid(?) VBR headers, or VBR streams with no VBR header
@@ -1098,7 +1109,7 @@
 				if (isset($nextframetestarray['mpeg']['audio']['framelength']) && ($nextframetestarray['mpeg']['audio']['framelength'] > 0)) {
 					$nextframetestoffset += $nextframetestarray['mpeg']['audio']['framelength'];
 				} else {
-					$info['error'][] = 'Frame at offset ('.$offset.') is has an invalid frame length.';
+					$this->error('Frame at offset ('.$offset.') is has an invalid frame length.');
 					return false;
 				}
 
@@ -1110,7 +1121,7 @@
 			} else {
 
 				// next frame is not valid, note the error and fail, so scanning can contiue for a valid frame sequence
-				$info['warning'][] = 'Frame at offset ('.$offset.') is valid, but the next one at ('.$nextframetestoffset.') is not.';
+				$this->warning('Frame at offset ('.$offset.') is valid, but the next one at ('.$nextframetestoffset.') is not.');
 
 				return false;
 			}
@@ -1153,10 +1164,10 @@
 				$framelength = $framelength2;
 			}
 			if (!$framelength) {
-				$info['error'][] = 'Cannot find next free-format synch pattern ('.getid3_lib::PrintHexBytes($SyncPattern1).' or '.getid3_lib::PrintHexBytes($SyncPattern2).') after offset '.$offset;
+				$this->error('Cannot find next free-format synch pattern ('.getid3_lib::PrintHexBytes($SyncPattern1).' or '.getid3_lib::PrintHexBytes($SyncPattern2).') after offset '.$offset);
 				return false;
 			} else {
-				$info['warning'][] = 'ModeExtension varies between first frame and other frames (known free-format issue in LAME 3.88)';
+				$this->warning('ModeExtension varies between first frame and other frames (known free-format issue in LAME 3.88)');
 				$info['audio']['codec']   = 'LAME';
 				$info['audio']['encoder'] = 'LAME3.88';
 				$SyncPattern1 = substr($SyncPattern1, 0, 3);
@@ -1183,7 +1194,7 @@
 					$ActualFrameLengthValues[] = ($framelength + 1);
 					$nextoffset++;
 				} else {
-					$info['error'][] = 'Did not find expected free-format sync pattern at offset '.$nextoffset;
+					$this->error('Did not find expected free-format sync pattern at offset '.$nextoffset);
 					return false;
 				}
 				$nextoffset += $framelength;
@@ -1281,7 +1292,7 @@
 							getid3_lib::safe_inc($Distribution['frequency'][$LongMPEGfrequencyLookup[$head4]]);
 							if ($max_frames_scan && (++$frames_scanned >= $max_frames_scan)) {
 								$pct_data_scanned = ($this->ftell() - $info['avdataoffset']) / ($info['avdataend'] - $info['avdataoffset']);
-								$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.';
+								$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.');
 								foreach ($Distribution as $key1 => $value1) {
 									foreach ($value1 as $key2 => $value2) {
 										$Distribution[$key1][$key2] = round($value2 / $pct_data_scanned);
@@ -1308,13 +1319,13 @@
 		$info['mpeg']['audio']['version_distribution']   = $Distribution['version'];
 		$info['mpeg']['audio']['padding_distribution']   = $Distribution['padding'];
 		if (count($Distribution['version']) > 1) {
-			$info['error'][] = 'Corrupt file - more than one MPEG version detected';
+			$this->error('Corrupt file - more than one MPEG version detected');
 		}
 		if (count($Distribution['layer']) > 1) {
-			$info['error'][] = 'Corrupt file - more than one MPEG layer detected';
+			$this->error('Corrupt file - more than one MPEG layer detected');
 		}
 		if (count($Distribution['frequency']) > 1) {
-			$info['error'][] = 'Corrupt file - more than one MPEG sample rate detected';
+			$this->error('Corrupt file - more than one MPEG sample rate detected');
 		}
 
 
@@ -1326,7 +1337,7 @@
 		}
 		$info['mpeg']['audio']['frame_count']  = array_sum($Distribution['bitrate']);
 		if ($info['mpeg']['audio']['frame_count'] == 0) {
-			$info['error'][] = 'no MPEG audio frames found';
+			$this->error('no MPEG audio frames found');
 			return false;
 		}
 		$info['mpeg']['audio']['bitrate']      = ($bittotal / $info['mpeg']['audio']['frame_count']);
@@ -1361,7 +1372,7 @@
 		$this->fseek($avdataoffset);
 		$sync_seek_buffer_size = min(128 * 1024, $info['avdataend'] - $avdataoffset);
 		if ($sync_seek_buffer_size <= 0) {
-			$info['error'][] = 'Invalid $sync_seek_buffer_size at offset '.$avdataoffset;
+			$this->error('Invalid $sync_seek_buffer_size at offset '.$avdataoffset);
 			return false;
 		}
 		$header = $this->fread($sync_seek_buffer_size);
@@ -1372,7 +1383,7 @@
 
 				if ($SynchSeekOffset > $sync_seek_buffer_size) {
 					// if a synch's not found within the first 128k bytes, then give up
-					$info['error'][] = 'Could not find valid MPEG audio synch within the first '.round($sync_seek_buffer_size / 1024).'kB';
+					$this->error('Could not find valid MPEG audio synch within the first '.round($sync_seek_buffer_size / 1024).'kB');
 					if (isset($info['audio']['bitrate'])) {
 						unset($info['audio']['bitrate']);
 					}
@@ -1386,7 +1397,7 @@
 
 				} elseif (feof($this->getid3->fp)) {
 
-					$info['error'][] = 'Could not find valid MPEG audio synch before end of file';
+					$this->error('Could not find valid MPEG audio synch before end of file');
 					if (isset($info['audio']['bitrate'])) {
 						unset($info['audio']['bitrate']);
 					}
@@ -1401,7 +1412,7 @@
 			}
 
 			if (($SynchSeekOffset + 1) >= strlen($header)) {
-				$info['error'][] = 'Could not find valid MPEG synch before end of file';
+				$this->error('Could not find valid MPEG synch before end of file');
 				return false;
 			}
 
@@ -1444,9 +1455,9 @@
 							if ($this->decodeMPEGaudioHeader($GarbageOffsetEnd, $dummy, true, true)) {
 								$info = $dummy;
 								$info['avdataoffset'] = $GarbageOffsetEnd;
-								$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;
+								$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);
 							} else {
-								$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.')';
+								$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.')');
 							}
 						}
 					}
@@ -1539,7 +1550,7 @@
 							}
 						}
 						if ($pct_data_scanned > 0) {
-							$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.';
+							$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.');
 							foreach ($info['mpeg']['audio'] as $key1 => $value1) {
 								if (!preg_match('#_distribution$#i', $key1)) {
 									continue;
@@ -1551,7 +1562,7 @@
 						}
 
 						if ($SynchErrorsFound > 0) {
-							$info['warning'][] = 'Found '.$SynchErrorsFound.' synch errors in histogram analysis';
+							$this->warning('Found '.$SynchErrorsFound.' synch errors in histogram analysis');
 							//return false;
 						}
 
@@ -1564,7 +1575,7 @@
 							}
 						}
 						if ($framecounter == 0) {
-							$info['error'][] = 'Corrupt MP3 file: framecounter == zero';
+							$this->error('Corrupt MP3 file: framecounter == zero');
 							return false;
 						}
 						$info['mpeg']['audio']['frame_count'] = getid3_lib::CastAsInt($framecounter);
@@ -1599,7 +1610,7 @@
 
 				if (empty($info['mpeg']['audio'])) {
 
-					$info['error'][] = 'could not find valid MPEG synch before end of file';
+					$this->error('could not find valid MPEG synch before end of file');
 					if (isset($info['audio']['bitrate'])) {
 						unset($info['audio']['bitrate']);
 					}
@@ -2009,4 +2020,4 @@
 		return (isset($LAMEpresetUsedLookup[$LAMEtag['preset_used_id']]) ? $LAMEpresetUsedLookup[$LAMEtag['preset_used_id']] : 'new/unknown preset: '.$LAMEtag['preset_used_id'].' - report to info@getid3.org');
 	}
 
-}
\ No newline at end of file
+}