<?php
/////////////////////////////////////////////////////////////////
/// getID3() by James Heinrich <getid3@users.sourceforge.net> //
// available at http://getid3.sourceforge.net ///
/////////////////////////////////////////////////////////////////
// //
// getid3.frames.php - part of getID3() //
// See getid3.readme.txt for more details //
// //
/////////////////////////////////////////////////////////////////
function ID3v2FrameProcessing($frame_name, $frame_flags, &$MP3fileInfo) {
// define $frame_arrayindex once here (used for many frames), override or ignore as neccesary
$frame_arrayindex = count($MP3fileInfo['id3']['id3v2']["$frame_name"]); // 'data', 'datalength'
if (isset($MP3fileInfo['id3']['id3v2']["$frame_name"]['data'])) {
$frame_arrayindex--;
}
if (isset($MP3fileInfo['id3']['id3v2']["$frame_name"]['datalength'])) {
$frame_arrayindex--;
}
if (isset($MP3fileInfo['id3']['id3v2']["$frame_name"]['dataoffset'])) {
$frame_arrayindex--;
}
if (isset($MP3fileInfo['id3']['id3v2']["$frame_name"]['flags'])) {
$frame_arrayindex--;
}
if (isset($MP3fileInfo['id3']['id3v2']["$frame_name"]['timestampformat'])) {
$frame_arrayindex--;
}
if ($MP3fileInfo['id3']['id3v2']['majorversion'] >= 3) { // frame flags are not part of the ID3v2.2 standard
if ($MP3fileInfo['id3']['id3v2']['majorversion'] == 3) {
// Frame Header Flags
// %abc00000 %ijk00000
$MP3fileInfo['id3']['id3v2']["$frame_name"]['flags']['TagAlterPreservation'] = (bool) substr($frame_flags, 0, 1); // a - Tag alter preservation
$MP3fileInfo['id3']['id3v2']["$frame_name"]['flags']['FileAlterPreservation'] = (bool) substr($frame_flags, 1, 1); // b - File alter preservation
$MP3fileInfo['id3']['id3v2']["$frame_name"]['flags']['ReadOnly'] = (bool) substr($frame_flags, 2, 1); // c - Read only
$MP3fileInfo['id3']['id3v2']["$frame_name"]['flags']['compression'] = (bool) substr($frame_flags, 8, 1); // i - Compression
$MP3fileInfo['id3']['id3v2']["$frame_name"]['flags']['Encryption'] = (bool) substr($frame_flags, 9, 1); // j - Encryption
$MP3fileInfo['id3']['id3v2']["$frame_name"]['flags']['GroupingIdentity'] = (bool) substr($frame_flags, 10, 1); // k - Grouping identity
} else if ($MP3fileInfo['id3']['id3v2']['majorversion'] == 4) {
// Frame Header Flags
// %0abc0000 %0h00kmnp
$MP3fileInfo['id3']['id3v2']["$frame_name"]['flags']['TagAlterPreservation'] = (bool) substr($frame_flags, 1, 1); // a - Tag alter preservation
$MP3fileInfo['id3']['id3v2']["$frame_name"]['flags']['FileAlterPreservation'] = (bool) substr($frame_flags, 2, 1); // b - File alter preservation
$MP3fileInfo['id3']['id3v2']["$frame_name"]['flags']['ReadOnly'] = (bool) substr($frame_flags, 3, 1); // c - Read only
$MP3fileInfo['id3']['id3v2']["$frame_name"]['flags']['GroupingIdentity'] = (bool) substr($frame_flags, 9, 1); // h - Grouping identity
$MP3fileInfo['id3']['id3v2']["$frame_name"]['flags']['compression'] = (bool) substr($frame_flags, 12, 1); // k - Compression
$MP3fileInfo['id3']['id3v2']["$frame_name"]['flags']['Encryption'] = (bool) substr($frame_flags, 13, 1); // m - Encryption
$MP3fileInfo['id3']['id3v2']["$frame_name"]['flags']['Unsynchronisation'] = (bool) substr($frame_flags, 14, 1); // n - Unsynchronisation
$MP3fileInfo['id3']['id3v2']["$frame_name"]['flags']['DataLengthIndicator'] = (bool) substr($frame_flags, 15, 1); // p - Data length indicator
}
// Frame-level de-unsynchronization - ID3v2.4
if (isset($MP3fileInfo['id3']['id3v2']["$frame_name"]['flags']['Unsynchronisation'])) {
$MP3fileInfo['id3']['id3v2']["$frame_name"]['data'] = DeUnSynchronise($MP3fileInfo['id3']['id3v2']["$frame_name"]['data']);
}
// Frame-level de-compression
if (isset($MP3fileInfo['id3']['id3v2']["$frame_name"]['flags']['compression'])) {
// it's on the wishlist :)
}
}
if ((($MP3fileInfo['id3']['id3v2']['majorversion'] >= 3) && ($frame_name == 'UFID')) || // 4.1 UFID Unique file identifier
(($MP3fileInfo['id3']['id3v2']['majorversion'] == 2) && ($frame_name == 'UFI'))) { // 4.1 UFI Unique file identifier
// There may be more than one 'UFID' frame in a tag,
// but only one with the same 'Owner identifier'.
// <Header for 'Unique file identifier', ID: 'UFID'>
// Owner identifier <text string> $00
// Identifier <up to 64 bytes binary data>
$frame_terminatorpos = strpos($MP3fileInfo['id3']['id3v2']["$frame_name"]['data'], chr(0));
$frame_idstring = substr($MP3fileInfo['id3']['id3v2']["$frame_name"]['data'], 0, $frame_terminatorpos);
$MP3fileInfo['id3']['id3v2']["$frame_name"]["$frame_arrayindex"]['ownerid'] = $frame_idstring;
$MP3fileInfo['id3']['id3v2']["$frame_name"]["$frame_arrayindex"]['data'] = substr($MP3fileInfo['id3']['id3v2']["$frame_name"]['data'], $frame_terminatorpos + strlen(chr(0)));
if ($MP3fileInfo['id3']['id3v2']['majorversion'] >= 3) {
$MP3fileInfo['id3']['id3v2']["$frame_name"]["$frame_arrayindex"]['flags'] = $MP3fileInfo['id3']['id3v2']["$frame_name"]['flags'];
unset($MP3fileInfo['id3']['id3v2']["$frame_name"]['flags']);
}
$MP3fileInfo['id3']['id3v2']["$frame_name"]["$frame_arrayindex"]['framenamelong'] = FrameNameLongLookup($frame_name);
unset($MP3fileInfo['id3']['id3v2']["$frame_name"]['data']);
$MP3fileInfo['id3']['id3v2']["$frame_name"]["$frame_arrayindex"]['datalength'] = $MP3fileInfo['id3']['id3v2']["$frame_name"]['datalength'];
unset($MP3fileInfo['id3']['id3v2']["$frame_name"]['datalength']);
$MP3fileInfo['id3']['id3v2']["$frame_name"]["$frame_arrayindex"]['dataoffset'] = $MP3fileInfo['id3']['id3v2']["$frame_name"]['dataoffset'];
unset($MP3fileInfo['id3']['id3v2']["$frame_name"]['dataoffset']);
} else if ((($MP3fileInfo['id3']['id3v2']['majorversion'] >= 3) && ($frame_name == 'TXXX')) || // 4.2.2 TXXX User defined text information frame
(($MP3fileInfo['id3']['id3v2']['majorversion'] == 2) && ($frame_name == 'TXX'))) { // 4.2.2 TXX User defined text information frame
// There may be more than one 'TXXX' frame in each tag,
// but only one with the same description.
// <Header for 'User defined text information frame', ID: 'TXXX'>
// Text encoding $xx
// Description <text string according to encoding> $00 (00)
// Value <text string according to encoding>
$frame_offset = 0;
$frame_textencoding = ord(substr($MP3fileInfo['id3']['id3v2']["$frame_name"]['data'], $frame_offset++, 1));
$frame_terminatorpos = strpos($MP3fileInfo['id3']['id3v2']["$frame_name"]['data'], TextEncodingLookup('terminator', $frame_textencoding), $frame_offset);
if (ord(substr($MP3fileInfo['id3']['id3v2']["$frame_name"]['data'], $frame_terminatorpos + strlen(TextEncodingLookup('terminator', $frame_textencoding)), 1)) === 0) {
$frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00
}
$frame_description = substr($MP3fileInfo['id3']['id3v2']["$frame_name"]['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
if (ord($frame_description) === 0) {
$frame_description = '';
}
$MP3fileInfo['id3']['id3v2']["$frame_name"]["$frame_arrayindex"]['encodingid'] = $frame_textencoding;
$MP3fileInfo['id3']['id3v2']["$frame_name"]["$frame_arrayindex"]['encoding'] = TextEncodingLookup('encoding', $frame_textencoding);
if ($MP3fileInfo['id3']['id3v2']['majorversion'] >= 3) {
$MP3fileInfo['id3']['id3v2']["$frame_name"]["$frame_arrayindex"]['flags'] = $MP3fileInfo['id3']['id3v2']["$frame_name"]['flags'];
}
$MP3fileInfo['id3']['id3v2']["$frame_name"]["$frame_arrayindex"]['description'] = $frame_description;
if (!isset($MP3fileInfo['id3']['id3v2']["$frame_name"]["$frame_arrayindex"]['flags']['compression']) || ($MP3fileInfo['id3']['id3v2']["$frame_name"]["$frame_arrayindex"]['flags']['compression'] === FALSE)) {
$MP3fileInfo['id3']['id3v2']["$frame_name"]["$frame_arrayindex"]['asciidescription'] = RoughTranslateUnicodeToASCII($frame_description, $frame_textencoding);
}
$MP3fileInfo['id3']['id3v2']["$frame_name"]["$frame_arrayindex"]['data'] = substr($MP3fileInfo['id3']['id3v2']["$frame_name"]['data'], $frame_terminatorpos + strlen(TextEncodingLookup('terminator', $frame_textencoding)));
if (!isset($MP3fileInfo['id3']['id3v2']["$frame_name"]["$frame_arrayindex"]['flags']['compression']) || ($MP3fileInfo['id3']['id3v2']["$frame_name"]["$frame_arrayindex"]['flags']['compression'] === FALSE)) {
$MP3fileInfo['id3']['id3v2']["$frame_name"]["$frame_arrayindex"]['asciidata'] = RoughTranslateUnicodeToASCII($MP3fileInfo['id3']['id3v2']["$frame_name"]["$frame_arrayindex"]['data'], $frame_textencoding);
}
if ($MP3fileInfo['id3']['id3v2']['majorversion'] >= 3) {
unset($MP3fileInfo['id3']['id3v2']["$frame_name"]['flags']);
}
$MP3fileInfo['id3']['id3v2']["$frame_name"]["$frame_arrayindex"]['framenamelong'] = FrameNameLongLookup($frame_name);
unset($MP3fileInfo['id3']['id3v2']["$frame_name"]['data']);
$MP3fileInfo['id3']['id3v2']["$frame_name"]["$frame_arrayindex"]['datalength'] = $MP3fileInfo['id3']['id3v2']["$frame_name"]['datalength'];
unset($MP3fileInfo['id3']['id3v2']["$frame_name"]['datalength']);
$MP3fileInfo['id3']['id3v2']["$frame_name"]["$frame_arrayindex"]['dataoffset'] = $MP3fileInfo['id3']['id3v2']["$frame_name"]['dataoffset'];
unset($MP3fileInfo['id3']['id3v2']["$frame_name"]['dataoffset']);
} else if ($frame_name{0} == 'T') { // 4.2. T??[?] Text information frame
// There may only be one text information frame of its kind in an tag.
// <Header for 'Text information frame', ID: 'T000' - 'TZZZ',
// excluding 'TXXX' described in 4.2.6.>
// Text encoding $xx
// Information <text string(s) according to encoding>
$frame_offset = 0;
$frame_textencoding = ord(substr($MP3fileInfo['id3']['id3v2']["$frame_name"]['data'], $frame_offset++, 1));
// $MP3fileInfo['id3']['id3v2']["$frame_name"]['data'] = substr($MP3fileInfo['id3']['id3v2']["$frame_name"]['data'], $frame_offset);
// this one-line method should work, but as a safeguard against null-padded data, do it the safe way
$frame_terminatorpos = strpos($MP3fileInfo['id3']['id3v2']["$frame_name"]['data'], TextEncodingLookup('terminator', $frame_textencoding), $frame_offset);
if (ord(substr($MP3fileInfo['id3']['id3v2']["$frame_name"]['data'], $frame_terminatorpos + strlen(TextEncodingLookup('terminator', $frame_textencoding)), 1)) === 0) {
$frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00
}
if ($frame_terminatorpos) {
// there are null bytes after the data - this is not according to spec
// only use data up to first null byte
$MP3fileInfo['id3']['id3v2']["$frame_name"]['data'] = substr($MP3fileInfo['id3']['id3v2']["$frame_name"]['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
} else {
// no null bytes following data, just use all data
$MP3fileInfo['id3']['id3v2']["$frame_name"]['data'] = substr($MP3fileInfo['id3']['id3v2']["$frame_name"]['data'], $frame_offset);
}
if (!isset($MP3fileInfo['id3']['id3v2']["$frame_name"]['flags']['compression']) || !$MP3fileInfo['id3']['id3v2']["$frame_name"]['flags']['compression']) {
$MP3fileInfo['id3']['id3v2']["$frame_name"]['asciidata'] = RoughTranslateUnicodeToASCII($MP3fileInfo['id3']['id3v2']["$frame_name"]['data'], $frame_textencoding);
}
$MP3fileInfo['id3']['id3v2']["$frame_name"]['encodingid'] = $frame_textencoding;
$MP3fileInfo['id3']['id3v2']["$frame_name"]['encoding'] = TextEncodingLookup('encoding', $frame_textencoding);
$MP3fileInfo['id3']['id3v2']["$frame_name"]['framenamelong'] = FrameNameLongLookup($frame_name);
} else if ((($MP3fileInfo['id3']['id3v2']['majorversion'] >= 3) && ($frame_name == 'WXXX')) || // 4.3.2 WXXX User defined URL link frame
(($MP3fileInfo['id3']['id3v2']['majorversion'] == 2) && ($frame_name == 'WXX'))) { // 4.3.2 WXX User defined URL link frame
// There may be more than one 'WXXX' frame in each tag,
// but only one with the same description
// <Header for 'User defined URL link frame', ID: 'WXXX'>
// Text encoding $xx
// Description <text string according to encoding> $00 (00)
// URL <text string>
$frame_offset = 0;
$frame_textencoding = ord(substr($MP3fileInfo['id3']['id3v2']["$frame_name"]['data'], $frame_offset++, 1));
$frame_terminatorpos = strpos($MP3fileInfo['id3']['id3v2']["$frame_name"]['data'], TextEncodingLookup('terminator', $frame_textencoding), $frame_offset);
if (ord(substr($MP3fileInfo['id3']['id3v2']["$frame_name"]['data'], $frame_terminatorpos + strlen(TextEncodingLookup('terminator', $frame_textencoding)), 1)) === 0) {
$frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00
}
$frame_description = substr($MP3fileInfo['id3']['id3v2']["$frame_name"]['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
if (ord($frame_description) === 0) {
$frame_description = '';
}
$MP3fileInfo['id3']['id3v2']["$frame_name"]['data'] = substr($MP3fileInfo['id3']['id3v2']["$frame_name"]['data'], $frame_terminatorpos + strlen(TextEncodingLookup('terminator', $frame_textencoding)));
$frame_terminatorpos = strpos($MP3fileInfo['id3']['id3v2']["$frame_name"]['data'], TextEncodingLookup('terminator', $frame_textencoding));
if (ord(substr($MP3fileInfo['id3']['id3v2']["$frame_name"]['data'], $frame_terminatorpos + strlen(TextEncodingLookup('terminator', $frame_textencoding)), 1)) === 0) {
$frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00
}
if ($frame_terminatorpos) {
// there are null bytes after the data - this is not according to spec
// only use data up to first null byte
$frame_urldata = substr($MP3fileInfo['id3']['id3v2']["$frame_name"]['data'], 0, $frame_terminatorpos);
} else {
// no null bytes following data, just use all data
$frame_urldata = $MP3fileInfo['id3']['id3v2']["$frame_name"]['data'];
}
if ($MP3fileInfo['id3']['id3v2']['majorversion'] >= 3) {
$MP3fileInfo['id3']['id3v2']["$frame_name"]["$frame_arrayindex"]['flags'] = $MP3fileInfo['id3']['id3v2']["$frame_name"]['flags'];
unset($MP3fileInfo['id3']['id3v2']["$frame_name"]['flags']);
}
$MP3fileInfo['id3']['id3v2']["$frame_name"]["$frame_arrayindex"]['encodingid'] = $frame_textencoding;
$MP3fileInfo['id3']['id3v2']["$frame_name"]["$frame_arrayindex"]['encoding'] = TextEncodingLookup('encoding', $frame_textencoding);
$MP3fileInfo['id3']['id3v2']["$frame_name"]["$frame_arrayindex"]['url'] = $frame_urldata;
$MP3fileInfo['id3']['id3v2']["$frame_name"]["$frame_arrayindex"]['description'] = $frame_description;
if (!isset($MP3fileInfo['id3']['id3v2']["$frame_name"]["$frame_arrayindex"]['flags']['compression']) || ($MP3fileInfo['id3']['id3v2']["$frame_name"]["$frame_arrayindex"]['flags']['compression'] === FALSE)) {
$MP3fileInfo['id3']['id3v2']["$frame_name"]["$frame_arrayindex"]['asciidescription'] = RoughTranslateUnicodeToASCII($frame_description, $frame_textencoding);
}
$MP3fileInfo['id3']['id3v2']["$frame_name"]["$frame_arrayindex"]['framenamelong'] = FrameNameLongLookup($frame_name);
unset($MP3fileInfo['id3']['id3v2']["$frame_name"]['data']);
$MP3fileInfo['id3']['id3v2']["$frame_name"]["$frame_arrayindex"]['datalength'] = $MP3fileInfo['id3']['id3v2']["$frame_name"]['datalength'];
unset($MP3fileInfo['id3']['id3v2']["$frame_name"]['datalength']);
$MP3fileInfo['id3']['id3v2']["$frame_name"]["$frame_arrayindex"]['dataoffset'] = $MP3fileInfo['id3']['id3v2']["$frame_name"]['dataoffset'];
unset($MP3fileInfo['id3']['id3v2']["$frame_name"]['dataoffset']);
} else if ($frame_name{0} == 'W') { // 4.3. W??? URL link frames
// There may only be one URL link frame of its kind in a tag,
// except when stated otherwise in the frame description
// <Header for 'URL link frame', ID: 'W000' - 'WZZZ', excluding 'WXXX'
// described in 4.3.2.>
// URL <text string>
$MP3fileInfo['id3']['id3v2']["$frame_name"]["$frame_arrayindex"]['url'] = trim($MP3fileInfo['id3']['id3v2']["$frame_name"]['data']);
if ($MP3fileInfo['id3']['id3v2']['majorversion'] >= 3) {
$MP3fileInfo['id3']['id3v2']["$frame_name"]["$frame_arrayindex"]['flags'] = $MP3fileInfo['id3']['id3v2']["$frame_name"]['flags'];
unset($MP3fileInfo['id3']['id3v2']["$frame_name"]['flags']);
}
$MP3fileInfo['id3']['id3v2']["$frame_name"]["$frame_arrayindex"]['framenamelong'] = FrameNameLongLookup($frame_name);
unset($MP3fileInfo['id3']['id3v2']["$frame_name"]['data']);
$MP3fileInfo['id3']['id3v2']["$frame_name"]["$frame_arrayindex"]['datalength'] = $MP3fileInfo['id3']['id3v2']["$frame_name"]['datalength'];
unset($MP3fileInfo['id3']['id3v2']["$frame_name"]['datalength']);
$MP3fileInfo['id3']['id3v2']["$frame_name"]["$frame_arrayindex"]['dataoffset'] = $MP3fileInfo['id3']['id3v2']["$frame_name"]['dataoffset'];
unset($MP3fileInfo['id3']['id3v2']["$frame_name"]['dataoffset']);
} else if ((($MP3fileInfo['id3']['id3v2']['majorversion'] == 3) && ($frame_name == 'IPLS')) || // 4.4 IPLS Involved people list (ID3v2.3 only)
(($MP3fileInfo['id3']['id3v2']['majorversion'] == 2) && ($frame_name == 'IPL'))) { // 4.4 IPL Involved people list (ID3v2.2 only)
// There may only be one 'IPL' frame in each tag
// <Header for 'User defined URL link frame', ID: 'IPL'>
// Text encoding $xx
// People list strings <textstrings>
$frame_offset = 0;
$frame_textencoding = ord(substr($MP3fileInfo['id3']['id3v2']["$frame_name"]['data'], $frame_offset++, 1));
$MP3fileInfo['id3']['id3v2']["$frame_name"]['encodingid'] = $frame_textencoding;
$MP3fileInfo['id3']['id3v2']["$frame_name"]['encoding'] = TextEncodingLookup('encoding', $MP3fileInfo['id3']['id3v2']["$frame_name"]['encodingid']);
$MP3fileInfo['id3']['id3v2']["$frame_name"]['data'] = substr($MP3fileInfo['id3']['id3v2']["$frame_name"]['data'], $frame_offset);
$MP3fileInfo['id3']['id3v2']["$frame_name"]['asciidata'] = RoughTranslateUnicodeToASCII($MP3fileInfo['id3']['id3v2']["$frame_name"]['data'], $frame_textencoding);
$MP3fileInfo['id3']['id3v2']["$frame_name"]['framenamelong'] = FrameNameLongLookup($frame_name);
} else if ((($MP3fileInfo['id3']['id3v2']['majorversion'] >= 3) && ($frame_name == 'MCDI')) || // 4.4 MCDI Music CD identifier
(($MP3fileInfo['id3']['id3v2']['majorversion'] == 2) && ($frame_name == 'MCI'))) { // 4.5 MCI Music CD identifier
// There may only be one 'MCDI' frame in each tag
// <Header for 'Music CD identifier', ID: 'MCDI'>
// CD TOC <binary data>
$MP3fileInfo['id3']['id3v2']["$frame_name"]['framenamelong'] = FrameNameLongLookup($frame_name);
// no other special processing needed
} else if ((($MP3fileInfo['id3']['id3v2']['majorversion'] >= 3) && ($frame_name == 'ETCO')) || // 4.5 ETCO Event timing codes
(($MP3fileInfo['id3']['id3v2']['majorversion'] == 2) && ($frame_name == 'ETC'))) { // 4.6 ETC Event timing codes
// There may only be one 'ETCO' frame in each tag
// <Header for 'Event timing codes', ID: 'ETCO'>
// Time stamp format $xx
// Where time stamp format is:
// $01 (32-bit value) MPEG frames from beginning of file
// $02 (32-bit value) milliseconds from beginning of file
// Followed by a list of key events in the following format:
// Type of event $xx
// Time stamp $xx (xx ...)
// The 'Time stamp' is set to zero if directly at the beginning of the sound
// or after the previous event. All events MUST be sorted in chronological order.
$frame_offset = 0;
$MP3fileInfo['id3']['id3v2']["$frame_name"]['timestampformat'] = ord(substr($MP3fileInfo['id3']['id3v2']["$frame_name"]['data'], $frame_offset++, 1));
while ($frame_offset < strlen($MP3fileInfo['id3']['id3v2']["$frame_name"]['data'])) {
$MP3fileInfo['id3']['id3v2']["$frame_name"]["$frame_arrayindex"]['typeid'] = substr($MP3fileInfo['id3']['id3v2']["$frame_name"]['data'], $frame_offset++, 1);
$MP3fileInfo['id3']['id3v2']["$frame_name"]["$frame_arrayindex"]['type'] = ETCOEventLookup($MP3fileInfo['id3']['id3v2']["$frame_name"]["$frame_arrayindex"]['typeid']);
$MP3fileInfo['id3']['id3v2']["$frame_name"]["$frame_arrayindex"]['timestamp'] = BigEndian2Int(substr($MP3fileInfo['id3']['id3v2']["$frame_name"]['data'], $frame_offset, 4));
$frame_offset += 4;
}
if ($MP3fileInfo['id3']['id3v2']['majorversion'] >= 3) {
unset($MP3fileInfo['id3']['id3v2']["$frame_name"]['flags']);
}
$MP3fileInfo['id3']['id3v2']["$frame_name"]["$frame_arrayindex"]['framenamelong'] = FrameNameLongLookup($frame_name);
unset($MP3fileInfo['id3']['id3v2']["$frame_name"]['data']);
$MP3fileInfo['id3']['id3v2']["$frame_name"]["$frame_arrayindex"]['datalength'] = $MP3fileInfo['id3']['id3v2']["$frame_name"]['datalength'];
unset($MP3fileInfo['id3']['id3v2']["$frame_name"]['datalength']);
$MP3fileInfo['id3']['id3v2']["$frame_name"]["$frame_arrayindex"]['dataoffset'] = $MP3fileInfo['id3']['id3v2']["$frame_name"]['dataoffset'];
unset($MP3fileInfo['id3']['id3v2']["$frame_name"]['dataoffset']);
} else if ((($MP3fileInfo['id3']['id3v2']['majorversion'] >= 3) && ($frame_name == 'MLLT')) || // 4.6 MLLT MPEG location lookup table
(($MP3fileInfo['id3']['id3v2']['majorversion'] == 2) && ($frame_name == 'MLL'))) { // 4.7 MLL MPEG location lookup table
// There may only be one 'MLLT' frame in each tag
// <Header for 'Location lookup table', ID: 'MLLT'>
// MPEG frames between reference $xx xx
// Bytes between reference $xx xx xx
// Milliseconds between reference $xx xx xx
// Bits for bytes deviation $xx
// Bits for milliseconds dev. $xx
// Then for every reference the following data is included;
// Deviation in bytes %xxx....
// Deviation in milliseconds %xxx....
$frame_offset = 0;
$MP3fileInfo['id3']['id3v2']["$frame_name"]['framesbetweenreferences'] = BigEndian2Int(substr($MP3fileInfo['id3']['id3v2']["$frame_name"]['data'], 0, 2));
$MP3fileInfo['id3']['id3v2']["$frame_name"][<