Update getID3 library to fix issues with PHP7.4
Updates to trunk version that includes fixes for PHP7.4 Changelog: https://github.com/JamesHeinrich/getID3/compare/v1.9.14...00f3fbfd77e583099ca70a3cf0bc092e113d2b20 See: #47751,#47783. Fixes: #48040. Built from https://develop.svn.wordpress.org/trunk@46112 git-svn-id: http://core.svn.wordpress.org/trunk@45924 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
parent
b7fbf7d373
commit
1ed691f574
File diff suppressed because it is too large
Load Diff
|
@ -1,10 +1,9 @@
|
||||||
<?php
|
<?php
|
||||||
/////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////
|
||||||
/// getID3() by James Heinrich <info@getid3.org> //
|
/// getID3() by James Heinrich <info@getid3.org> //
|
||||||
// available at http://getid3.sourceforge.net //
|
// available at https://github.com/JamesHeinrich/getID3 //
|
||||||
// or http://www.getid3.org //
|
// or https://www.getid3.org //
|
||||||
// also https://github.com/JamesHeinrich/getID3 //
|
// or http://getid3.sourceforge.net //
|
||||||
/////////////////////////////////////////////////////////////////
|
|
||||||
// //
|
// //
|
||||||
// Please see readme.txt for more information //
|
// Please see readme.txt for more information //
|
||||||
// ///
|
// ///
|
||||||
|
@ -26,6 +25,14 @@ if (!defined('ENT_SUBSTITUTE')) { // PHP5.3 adds ENT_IGNORE, PHP5.4 adds ENT_SUB
|
||||||
define('ENT_SUBSTITUTE', (defined('ENT_IGNORE') ? ENT_IGNORE : 8));
|
define('ENT_SUBSTITUTE', (defined('ENT_IGNORE') ? ENT_IGNORE : 8));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
https://www.getid3.org/phpBB3/viewtopic.php?t=2114
|
||||||
|
If you are running into a the problem where filenames with special characters are being handled
|
||||||
|
incorrectly by external helper programs (e.g. metaflac), notably with the special characters removed,
|
||||||
|
and you are passing in the filename in UTF8 (typically via a HTML form), try uncommenting this line:
|
||||||
|
*/
|
||||||
|
//setlocale(LC_CTYPE, 'en_US.UTF-8');
|
||||||
|
|
||||||
// attempt to define temp dir as something flexible but reliable
|
// attempt to define temp dir as something flexible but reliable
|
||||||
$temp_dir = ini_get('upload_tmp_dir');
|
$temp_dir = ini_get('upload_tmp_dir');
|
||||||
if ($temp_dir && (!is_dir($temp_dir) || !is_readable($temp_dir))) {
|
if ($temp_dir && (!is_dir($temp_dir) || !is_readable($temp_dir))) {
|
||||||
|
@ -74,53 +81,190 @@ unset($open_basedir, $temp_dir);
|
||||||
|
|
||||||
class getID3
|
class getID3
|
||||||
{
|
{
|
||||||
// public: Settings
|
/*
|
||||||
public $encoding = 'UTF-8'; // CASE SENSITIVE! - i.e. (must be supported by iconv()). Examples: ISO-8859-1 UTF-8 UTF-16 UTF-16BE
|
* Settings
|
||||||
public $encoding_id3v1 = 'ISO-8859-1'; // Should always be 'ISO-8859-1', but some tags may be written in other encodings such as 'EUC-CN' or 'CP1252'
|
*/
|
||||||
|
|
||||||
// public: Optional tag checks - disable for speed.
|
/**
|
||||||
public $option_tag_id3v1 = true; // Read and process ID3v1 tags
|
* CASE SENSITIVE! - i.e. (must be supported by iconv()). Examples: ISO-8859-1 UTF-8 UTF-16 UTF-16BE
|
||||||
public $option_tag_id3v2 = true; // Read and process ID3v2 tags
|
*
|
||||||
public $option_tag_lyrics3 = true; // Read and process Lyrics3 tags
|
* @var string
|
||||||
public $option_tag_apetag = true; // Read and process APE tags
|
*/
|
||||||
public $option_tags_process = true; // Copy tags to root key 'tags' and encode to $this->encoding
|
public $encoding = 'UTF-8';
|
||||||
public $option_tags_html = true; // Copy tags to root key 'tags_html' properly translated from various encodings to HTML entities
|
|
||||||
|
|
||||||
// public: Optional tag/comment calucations
|
/**
|
||||||
public $option_extra_info = true; // Calculate additional info such as bitrate, channelmode etc
|
* Should always be 'ISO-8859-1', but some tags may be written in other encodings such as 'EUC-CN' or 'CP1252'
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $encoding_id3v1 = 'ISO-8859-1';
|
||||||
|
|
||||||
// public: Optional handling of embedded attachments (e.g. images)
|
/*
|
||||||
public $option_save_attachments = true; // defaults to true (ATTACHMENTS_INLINE) for backward compatibility
|
* Optional tag checks - disable for speed.
|
||||||
|
*/
|
||||||
|
|
||||||
// public: Optional calculations
|
/**
|
||||||
public $option_md5_data = false; // Get MD5 sum of data part - slow
|
* Read and process ID3v1 tags
|
||||||
public $option_md5_data_source = false; // Use MD5 of source file if availble - only FLAC and OptimFROG
|
*
|
||||||
public $option_sha1_data = false; // Get SHA1 sum of data part - slow
|
* @var bool
|
||||||
public $option_max_2gb_check = null; // Check whether file is larger than 2GB and thus not supported by 32-bit PHP (null: auto-detect based on PHP_INT_MAX)
|
*/
|
||||||
|
public $option_tag_id3v1 = true;
|
||||||
|
|
||||||
// public: Read buffer size in bytes
|
/**
|
||||||
|
* Read and process ID3v2 tags
|
||||||
|
*
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
public $option_tag_id3v2 = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read and process Lyrics3 tags
|
||||||
|
*
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
public $option_tag_lyrics3 = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read and process APE tags
|
||||||
|
*
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
public $option_tag_apetag = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy tags to root key 'tags' and encode to $this->encoding
|
||||||
|
*
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
public $option_tags_process = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy tags to root key 'tags_html' properly translated from various encodings to HTML entities
|
||||||
|
*
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
public $option_tags_html = true;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Optional tag/comment calculations
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate additional info such as bitrate, channelmode etc
|
||||||
|
*
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
public $option_extra_info = true;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Optional handling of embedded attachments (e.g. images)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defaults to true (ATTACHMENTS_INLINE) for backward compatibility
|
||||||
|
*
|
||||||
|
* @var bool|string
|
||||||
|
*/
|
||||||
|
public $option_save_attachments = true;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Optional calculations
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get MD5 sum of data part - slow
|
||||||
|
*
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
public $option_md5_data = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use MD5 of source file if availble - only FLAC and OptimFROG
|
||||||
|
*
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
public $option_md5_data_source = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get SHA1 sum of data part - slow
|
||||||
|
*
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
public $option_sha1_data = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check whether file is larger than 2GB and thus not supported by 32-bit PHP (null: auto-detect based on
|
||||||
|
* PHP_INT_MAX)
|
||||||
|
*
|
||||||
|
* @var bool|null
|
||||||
|
*/
|
||||||
|
public $option_max_2gb_check;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read buffer size in bytes
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
public $option_fread_buffer_size = 32768;
|
public $option_fread_buffer_size = 32768;
|
||||||
|
|
||||||
// Public variables
|
// Public variables
|
||||||
public $filename; // Filename of file being analysed.
|
|
||||||
public $fp; // Filepointer to file being analysed.
|
/**
|
||||||
public $info; // Result array.
|
* Filename of file being analysed.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $filename;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filepointer to file being analysed.
|
||||||
|
*
|
||||||
|
* @var resource
|
||||||
|
*/
|
||||||
|
public $fp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Result array.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
public $info;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
public $tempdir = GETID3_TEMP_DIR;
|
public $tempdir = GETID3_TEMP_DIR;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
public $memory_limit = 0;
|
public $memory_limit = 0;
|
||||||
|
|
||||||
// Protected variables
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
protected $startup_error = '';
|
protected $startup_error = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
protected $startup_warning = '';
|
protected $startup_warning = '';
|
||||||
|
|
||||||
const VERSION = '1.9.14-201706111222';
|
const VERSION = '1.9.17-201907240906';
|
||||||
const FREAD_BUFFER_SIZE = 32768;
|
const FREAD_BUFFER_SIZE = 32768;
|
||||||
|
|
||||||
const ATTACHMENTS_NONE = false;
|
const ATTACHMENTS_NONE = false;
|
||||||
const ATTACHMENTS_INLINE = true;
|
const ATTACHMENTS_INLINE = true;
|
||||||
|
|
||||||
// public: constructor
|
|
||||||
public function __construct() {
|
public function __construct() {
|
||||||
|
|
||||||
|
// Check for PHP version
|
||||||
|
$required_php_version = '5.3.0';
|
||||||
|
if (version_compare(PHP_VERSION, $required_php_version, '<')) {
|
||||||
|
$this->startup_error .= 'getID3() requires PHP v'.$required_php_version.' or higher - you are running v'.PHP_VERSION."\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Check memory
|
// Check memory
|
||||||
$this->memory_limit = ini_get('memory_limit');
|
$this->memory_limit = ini_get('memory_limit');
|
||||||
if (preg_match('#([0-9]+) ?M#i', $this->memory_limit, $matches)) {
|
if (preg_match('#([0-9]+) ?M#i', $this->memory_limit, $matches)) {
|
||||||
|
@ -176,7 +320,7 @@ class getID3
|
||||||
|
|
||||||
// Needed for Windows only:
|
// Needed for Windows only:
|
||||||
// Define locations of helper applications for Shorten, VorbisComment, MetaFLAC
|
// Define locations of helper applications for Shorten, VorbisComment, MetaFLAC
|
||||||
// as well as other helper functions such as head, tail, md5sum, etc
|
// as well as other helper functions such as head, etc
|
||||||
// This path cannot contain spaces, but the below code will attempt to get the
|
// This path cannot contain spaces, but the below code will attempt to get the
|
||||||
// 8.3-equivalent path automatically
|
// 8.3-equivalent path automatically
|
||||||
// IMPORTANT: This path must include the trailing slash
|
// IMPORTANT: This path must include the trailing slash
|
||||||
|
@ -219,20 +363,27 @@ class getID3
|
||||||
echo $this->startup_error;
|
echo $this->startup_error;
|
||||||
throw new getid3_exception($this->startup_error);
|
throw new getid3_exception($this->startup_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public function version() {
|
public function version() {
|
||||||
return self::VERSION;
|
return self::VERSION;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
public function fread_buffer_size() {
|
public function fread_buffer_size() {
|
||||||
return $this->option_fread_buffer_size;
|
return $this->option_fread_buffer_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
// public: setOption
|
* @param array $optArray
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
public function setOption($optArray) {
|
public function setOption($optArray) {
|
||||||
if (!is_array($optArray) || empty($optArray)) {
|
if (!is_array($optArray) || empty($optArray)) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -246,8 +397,15 @@ class getID3
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
public function openfile($filename, $filesize=null) {
|
* @param string $filename
|
||||||
|
* @param int $filesize
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*
|
||||||
|
* @throws getid3_exception
|
||||||
|
*/
|
||||||
|
public function openfile($filename, $filesize=null, $fp=null) {
|
||||||
try {
|
try {
|
||||||
if (!empty($this->startup_error)) {
|
if (!empty($this->startup_error)) {
|
||||||
throw new getid3_exception($this->startup_error);
|
throw new getid3_exception($this->startup_error);
|
||||||
|
@ -270,11 +428,13 @@ class getID3
|
||||||
}
|
}
|
||||||
|
|
||||||
$filename = str_replace('/', DIRECTORY_SEPARATOR, $filename);
|
$filename = str_replace('/', DIRECTORY_SEPARATOR, $filename);
|
||||||
$filename = preg_replace('#(?<!gs:)('.preg_quote(DIRECTORY_SEPARATOR).'{2,})#', DIRECTORY_SEPARATOR, $filename);
|
//$filename = preg_replace('#(?<!gs:)('.preg_quote(DIRECTORY_SEPARATOR).'{2,})#', DIRECTORY_SEPARATOR, $filename);
|
||||||
|
|
||||||
// open local file
|
// open local file
|
||||||
//if (is_readable($filename) && is_file($filename) && ($this->fp = fopen($filename, 'rb'))) { // see http://www.getid3.org/phpBB3/viewtopic.php?t=1720
|
//if (is_readable($filename) && is_file($filename) && ($this->fp = fopen($filename, 'rb'))) { // see https://www.getid3.org/phpBB3/viewtopic.php?t=1720
|
||||||
if ((is_readable($filename) || file_exists($filename)) && is_file($filename) && ($this->fp = fopen($filename, 'rb'))) {
|
if (($fp != null) && ((get_resource_type($fp) == 'file') || (get_resource_type($fp) == 'stream'))) {
|
||||||
|
$this->fp = $fp;
|
||||||
|
} elseif ((is_readable($filename) || file_exists($filename)) && is_file($filename) && ($this->fp = fopen($filename, 'rb'))) {
|
||||||
// great
|
// great
|
||||||
} else {
|
} else {
|
||||||
$errormessagelist = array();
|
$errormessagelist = array();
|
||||||
|
@ -331,10 +491,10 @@ class getID3
|
||||||
} elseif (getid3_lib::intValueSupported($real_filesize)) {
|
} elseif (getid3_lib::intValueSupported($real_filesize)) {
|
||||||
unset($this->info['filesize']);
|
unset($this->info['filesize']);
|
||||||
fclose($this->fp);
|
fclose($this->fp);
|
||||||
throw new getid3_exception('PHP seems to think the file is larger than '.round(PHP_INT_MAX / 1073741824).'GB, but filesystem reports it as '.number_format($real_filesize, 3).'GB, please report to info@getid3.org');
|
throw new getid3_exception('PHP seems to think the file is larger than '.round(PHP_INT_MAX / 1073741824).'GB, but filesystem reports it as '.number_format($real_filesize / 1073741824, 3).'GB, please report to info@getid3.org');
|
||||||
}
|
}
|
||||||
$this->info['filesize'] = $real_filesize;
|
$this->info['filesize'] = $real_filesize;
|
||||||
$this->warning('File is larger than '.round(PHP_INT_MAX / 1073741824).'GB (filesystem reports it as '.number_format($real_filesize, 3).'GB) and is not properly supported by PHP.');
|
$this->warning('File is larger than '.round(PHP_INT_MAX / 1073741824).'GB (filesystem reports it as '.number_format($real_filesize / 1073741824, 3).'GB) and is not properly supported by PHP.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -346,10 +506,18 @@ class getID3
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// public: analyze file
|
/**
|
||||||
public function analyze($filename, $filesize=null, $original_filename='') {
|
* analyze file
|
||||||
|
*
|
||||||
|
* @param string $filename
|
||||||
|
* @param int $filesize
|
||||||
|
* @param string $original_filename
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function analyze($filename, $filesize=null, $original_filename='', $fp=null) {
|
||||||
try {
|
try {
|
||||||
if (!$this->openfile($filename, $filesize)) {
|
if (!$this->openfile($filename, $filesize, $fp)) {
|
||||||
return $this->info;
|
return $this->info;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -383,8 +551,8 @@ class getID3
|
||||||
$header = fread($this->fp, 10);
|
$header = fread($this->fp, 10);
|
||||||
if ((substr($header, 0, 3) == 'ID3') && (strlen($header) == 10)) {
|
if ((substr($header, 0, 3) == 'ID3') && (strlen($header) == 10)) {
|
||||||
$this->info['id3v2']['header'] = true;
|
$this->info['id3v2']['header'] = true;
|
||||||
$this->info['id3v2']['majorversion'] = ord($header{3});
|
$this->info['id3v2']['majorversion'] = ord($header[3]);
|
||||||
$this->info['id3v2']['minorversion'] = ord($header{4});
|
$this->info['id3v2']['minorversion'] = ord($header[4]);
|
||||||
$this->info['avdataoffset'] += getid3_lib::BigEndian2Int(substr($header, 6, 4), 1) + 10; // length of ID3v2 tag in 10-byte header doesn't include 10-byte header length
|
$this->info['avdataoffset'] += getid3_lib::BigEndian2Int(substr($header, 6, 4), 1) + 10; // length of ID3v2 tag in 10-byte header doesn't include 10-byte header length
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -497,7 +665,13 @@ class getID3
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// private: error handling
|
/**
|
||||||
|
* Error handling.
|
||||||
|
*
|
||||||
|
* @param string $message
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
public function error($message) {
|
public function error($message) {
|
||||||
$this->CleanUp();
|
$this->CleanUp();
|
||||||
if (!isset($this->info['error'])) {
|
if (!isset($this->info['error'])) {
|
||||||
|
@ -508,14 +682,22 @@ class getID3
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// private: warning handling
|
/**
|
||||||
|
* Warning handling.
|
||||||
|
*
|
||||||
|
* @param string $message
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
public function warning($message) {
|
public function warning($message) {
|
||||||
$this->info['warning'][] = $message;
|
$this->info['warning'][] = $message;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// private: CleanUp
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
private function CleanUp() {
|
private function CleanUp() {
|
||||||
|
|
||||||
// remove possible empty keys
|
// remove possible empty keys
|
||||||
|
@ -562,8 +744,11 @@ class getID3
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
// return array containing information about all supported formats
|
* Return array containing information about all supported formats.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
public function GetFileFormatArray() {
|
public function GetFileFormatArray() {
|
||||||
static $format_info = array();
|
static $format_info = array();
|
||||||
if (empty($format_info)) {
|
if (empty($format_info)) {
|
||||||
|
@ -584,7 +769,7 @@ class getID3
|
||||||
'pattern' => '^ADIF',
|
'pattern' => '^ADIF',
|
||||||
'group' => 'audio',
|
'group' => 'audio',
|
||||||
'module' => 'aac',
|
'module' => 'aac',
|
||||||
'mime_type' => 'application/octet-stream',
|
'mime_type' => 'audio/aac',
|
||||||
'fail_ape' => 'WARNING',
|
'fail_ape' => 'WARNING',
|
||||||
),
|
),
|
||||||
|
|
||||||
|
@ -602,7 +787,7 @@ class getID3
|
||||||
'pattern' => '^\\xFF[\\xF0-\\xF1\\xF8-\\xF9]',
|
'pattern' => '^\\xFF[\\xF0-\\xF1\\xF8-\\xF9]',
|
||||||
'group' => 'audio',
|
'group' => 'audio',
|
||||||
'module' => 'aac',
|
'module' => 'aac',
|
||||||
'mime_type' => 'application/octet-stream',
|
'mime_type' => 'audio/aac',
|
||||||
'fail_ape' => 'WARNING',
|
'fail_ape' => 'WARNING',
|
||||||
),
|
),
|
||||||
|
|
||||||
|
@ -649,7 +834,7 @@ class getID3
|
||||||
|
|
||||||
// DSS - audio - Digital Speech Standard
|
// DSS - audio - Digital Speech Standard
|
||||||
'dss' => array(
|
'dss' => array(
|
||||||
'pattern' => '^[\\x02-\\x06]ds[s2]',
|
'pattern' => '^[\\x02-\\x08]ds[s2]',
|
||||||
'group' => 'audio',
|
'group' => 'audio',
|
||||||
'module' => 'dss',
|
'module' => 'dss',
|
||||||
'mime_type' => 'application/octet-stream',
|
'mime_type' => 'application/octet-stream',
|
||||||
|
@ -668,7 +853,7 @@ class getID3
|
||||||
'pattern' => '^fLaC',
|
'pattern' => '^fLaC',
|
||||||
'group' => 'audio',
|
'group' => 'audio',
|
||||||
'module' => 'flac',
|
'module' => 'flac',
|
||||||
'mime_type' => 'audio/x-flac',
|
'mime_type' => 'audio/flac',
|
||||||
),
|
),
|
||||||
|
|
||||||
// LA - audio - Lossless Audio (LA)
|
// LA - audio - Lossless Audio (LA)
|
||||||
|
@ -700,7 +885,7 @@ class getID3
|
||||||
'pattern' => '^MAC ',
|
'pattern' => '^MAC ',
|
||||||
'group' => 'audio',
|
'group' => 'audio',
|
||||||
'module' => 'monkey',
|
'module' => 'monkey',
|
||||||
'mime_type' => 'application/octet-stream',
|
'mime_type' => 'audio/x-monkeys-audio',
|
||||||
),
|
),
|
||||||
|
|
||||||
// has been known to produce false matches in random files (e.g. JPEGs), leave out until more precise matching available
|
// has been known to produce false matches in random files (e.g. JPEGs), leave out until more precise matching available
|
||||||
|
@ -889,7 +1074,7 @@ class getID3
|
||||||
'pattern' => '^(RIFF|SDSS|FORM)',
|
'pattern' => '^(RIFF|SDSS|FORM)',
|
||||||
'group' => 'audio-video',
|
'group' => 'audio-video',
|
||||||
'module' => 'riff',
|
'module' => 'riff',
|
||||||
'mime_type' => 'audio/x-wav',
|
'mime_type' => 'audio/wav',
|
||||||
'fail_ape' => 'WARNING',
|
'fail_ape' => 'WARNING',
|
||||||
),
|
),
|
||||||
|
|
||||||
|
@ -1053,7 +1238,7 @@ class getID3
|
||||||
'pattern' => '^\\x1F\\x8B\\x08',
|
'pattern' => '^\\x1F\\x8B\\x08',
|
||||||
'group' => 'archive',
|
'group' => 'archive',
|
||||||
'module' => 'gzip',
|
'module' => 'gzip',
|
||||||
'mime_type' => 'application/x-gzip',
|
'mime_type' => 'application/gzip',
|
||||||
'fail_id3' => 'ERROR',
|
'fail_id3' => 'ERROR',
|
||||||
'fail_ape' => 'ERROR',
|
'fail_ape' => 'ERROR',
|
||||||
),
|
),
|
||||||
|
@ -1068,6 +1253,16 @@ class getID3
|
||||||
'fail_ape' => 'ERROR',
|
'fail_ape' => 'ERROR',
|
||||||
),
|
),
|
||||||
|
|
||||||
|
// XZ - data - XZ compressed data
|
||||||
|
'xz' => array(
|
||||||
|
'pattern' => '^\\xFD7zXZ\\x00',
|
||||||
|
'group' => 'archive',
|
||||||
|
'module' => 'xz',
|
||||||
|
'mime_type' => 'application/x-xz',
|
||||||
|
'fail_id3' => 'ERROR',
|
||||||
|
'fail_ape' => 'ERROR',
|
||||||
|
),
|
||||||
|
|
||||||
|
|
||||||
// Misc other formats
|
// Misc other formats
|
||||||
|
|
||||||
|
@ -1115,8 +1310,12 @@ class getID3
|
||||||
return $format_info;
|
return $format_info;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $filedata
|
||||||
|
* @param string $filename
|
||||||
|
*
|
||||||
|
* @return mixed|false
|
||||||
|
*/
|
||||||
public function GetFileFormat(&$filedata, $filename='') {
|
public function GetFileFormat(&$filedata, $filename='') {
|
||||||
// this function will determine the format of a file based on usually
|
// this function will determine the format of a file based on usually
|
||||||
// the first 2-4 bytes of the file (8 bytes for PNG, 16 bytes for JPG,
|
// the first 2-4 bytes of the file (8 bytes for PNG, 16 bytes for JPG,
|
||||||
|
@ -1135,7 +1334,7 @@ class getID3
|
||||||
|
|
||||||
|
|
||||||
if (preg_match('#\\.mp[123a]$#i', $filename)) {
|
if (preg_match('#\\.mp[123a]$#i', $filename)) {
|
||||||
// Too many mp3 encoders on the market put gabage in front of mpeg files
|
// Too many mp3 encoders on the market put garbage in front of mpeg files
|
||||||
// use assume format on these if format detection failed
|
// use assume format on these if format detection failed
|
||||||
$GetFileFormatArray = $this->GetFileFormatArray();
|
$GetFileFormatArray = $this->GetFileFormatArray();
|
||||||
$info = $GetFileFormatArray['mp3'];
|
$info = $GetFileFormatArray['mp3'];
|
||||||
|
@ -1154,8 +1353,12 @@ class getID3
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
// converts array to $encoding charset from $this->encoding
|
* Converts array to $encoding charset from $this->encoding.
|
||||||
|
*
|
||||||
|
* @param array $array
|
||||||
|
* @param string $encoding
|
||||||
|
*/
|
||||||
public function CharConvert(&$array, $encoding) {
|
public function CharConvert(&$array, $encoding) {
|
||||||
|
|
||||||
// identical encoding - end here
|
// identical encoding - end here
|
||||||
|
@ -1178,7 +1381,9 @@ class getID3
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
public function HandleAllTags() {
|
public function HandleAllTags() {
|
||||||
|
|
||||||
// key name => array (tag name, character encoding)
|
// key name => array (tag name, character encoding)
|
||||||
|
@ -1233,6 +1438,7 @@ class getID3
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($tag_key == 'picture') {
|
if ($tag_key == 'picture') {
|
||||||
|
// pictures can take up a lot of space, and we don't need multiple copies of them; let there be a single copy in [comments][picture], and not elsewhere
|
||||||
unset($this->info[$comment_name]['comments'][$tag_key]);
|
unset($this->info[$comment_name]['comments'][$tag_key]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1246,6 +1452,11 @@ class getID3
|
||||||
|
|
||||||
if ($this->option_tags_html) {
|
if ($this->option_tags_html) {
|
||||||
foreach ($this->info['tags'][$tag_name] as $tag_key => $valuearray) {
|
foreach ($this->info['tags'][$tag_name] as $tag_key => $valuearray) {
|
||||||
|
if ($tag_key == 'picture') {
|
||||||
|
// Do not to try to convert binary picture data to HTML
|
||||||
|
// https://github.com/JamesHeinrich/getID3/issues/178
|
||||||
|
continue;
|
||||||
|
}
|
||||||
$this->info['tags_html'][$tag_name][$tag_key] = getid3_lib::recursiveMultiByteCharString2HTML($valuearray, $this->info[$comment_name]['encoding']);
|
$this->info['tags_html'][$tag_name][$tag_key] = getid3_lib::recursiveMultiByteCharString2HTML($valuearray, $this->info[$comment_name]['encoding']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1254,8 +1465,7 @@ class getID3
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// pictures can take up a lot of space, and we don't need multiple copies of them
|
// pictures can take up a lot of space, and we don't need multiple copies of them; let there be a single copy in [comments][picture], and not elsewhere
|
||||||
// let there be a single copy in [comments][picture], and not elsewhere
|
|
||||||
if (!empty($this->info['tags'])) {
|
if (!empty($this->info['tags'])) {
|
||||||
$unset_keys = array('tags', 'tags_html');
|
$unset_keys = array('tags', 'tags_html');
|
||||||
foreach ($this->info['tags'] as $tagtype => $tagarray) {
|
foreach ($this->info['tags'] as $tagtype => $tagarray) {
|
||||||
|
@ -1301,6 +1511,11 @@ class getID3
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $algorithm
|
||||||
|
*
|
||||||
|
* @return array|bool
|
||||||
|
*/
|
||||||
public function getHashdata($algorithm) {
|
public function getHashdata($algorithm) {
|
||||||
switch ($algorithm) {
|
switch ($algorithm) {
|
||||||
case 'md5':
|
case 'md5':
|
||||||
|
@ -1365,7 +1580,6 @@ class getID3
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
$commandline = 'vorbiscomment -w -c "'.$empty.'" "'.$file.'" "'.$temp.'" 2>&1';
|
|
||||||
$commandline = 'vorbiscomment -w -c '.escapeshellarg($empty).' '.escapeshellarg($file).' '.escapeshellarg($temp).' 2>&1';
|
$commandline = 'vorbiscomment -w -c '.escapeshellarg($empty).' '.escapeshellarg($file).' '.escapeshellarg($temp).' 2>&1';
|
||||||
$VorbisCommentError = `$commandline`;
|
$VorbisCommentError = `$commandline`;
|
||||||
|
|
||||||
|
@ -1424,7 +1638,6 @@ class getID3
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function ChannelsBitratePlaytimeCalculations() {
|
public function ChannelsBitratePlaytimeCalculations() {
|
||||||
|
|
||||||
// set channelmode on audio
|
// set channelmode on audio
|
||||||
|
@ -1489,7 +1702,9 @@ class getID3
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
public function CalculateCompressionRatioVideo() {
|
public function CalculateCompressionRatioVideo() {
|
||||||
if (empty($this->info['video'])) {
|
if (empty($this->info['video'])) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -1537,7 +1752,9 @@ class getID3
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
public function CalculateCompressionRatioAudio() {
|
public function CalculateCompressionRatioAudio() {
|
||||||
if (empty($this->info['audio']['bitrate']) || empty($this->info['audio']['channels']) || empty($this->info['audio']['sample_rate']) || !is_numeric($this->info['audio']['sample_rate'])) {
|
if (empty($this->info['audio']['bitrate']) || empty($this->info['audio']['channels']) || empty($this->info['audio']['sample_rate']) || !is_numeric($this->info['audio']['sample_rate'])) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -1554,11 +1771,13 @@ class getID3
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
public function CalculateReplayGain() {
|
public function CalculateReplayGain() {
|
||||||
if (isset($this->info['replay_gain'])) {
|
if (isset($this->info['replay_gain'])) {
|
||||||
if (!isset($this->info['replay_gain']['reference_volume'])) {
|
if (!isset($this->info['replay_gain']['reference_volume'])) {
|
||||||
$this->info['replay_gain']['reference_volume'] = (double) 89.0;
|
$this->info['replay_gain']['reference_volume'] = 89.0;
|
||||||
}
|
}
|
||||||
if (isset($this->info['replay_gain']['track']['adjustment'])) {
|
if (isset($this->info['replay_gain']['track']['adjustment'])) {
|
||||||
$this->info['replay_gain']['track']['volume'] = $this->info['replay_gain']['reference_volume'] - $this->info['replay_gain']['track']['adjustment'];
|
$this->info['replay_gain']['track']['volume'] = $this->info['replay_gain']['reference_volume'] - $this->info['replay_gain']['track']['adjustment'];
|
||||||
|
@ -1577,6 +1796,9 @@ class getID3
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
public function ProcessAudioStreams() {
|
public function ProcessAudioStreams() {
|
||||||
if (!empty($this->info['audio']['bitrate']) || !empty($this->info['audio']['channels']) || !empty($this->info['audio']['sample_rate'])) {
|
if (!empty($this->info['audio']['bitrate']) || !empty($this->info['audio']['channels']) || !empty($this->info['audio']['sample_rate'])) {
|
||||||
if (!isset($this->info['audio']['streams'])) {
|
if (!isset($this->info['audio']['streams'])) {
|
||||||
|
@ -1590,10 +1812,20 @@ class getID3
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string|bool
|
||||||
|
*/
|
||||||
public function getid3_tempnam() {
|
public function getid3_tempnam() {
|
||||||
return tempnam($this->tempdir, 'gI3');
|
return tempnam($this->tempdir, 'gI3');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $name
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*
|
||||||
|
* @throws getid3_exception
|
||||||
|
*/
|
||||||
public function include_module($name) {
|
public function include_module($name) {
|
||||||
//if (!file_exists($this->include_path.'module.'.$name.'.php')) {
|
//if (!file_exists($this->include_path.'module.'.$name.'.php')) {
|
||||||
if (!file_exists(GETID3_INCLUDEPATH.'module.'.$name.'.php')) {
|
if (!file_exists(GETID3_INCLUDEPATH.'module.'.$name.'.php')) {
|
||||||
|
@ -1603,35 +1835,70 @@ class getID3
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function is_writable ($filename) {
|
/**
|
||||||
$ret = is_writable($filename);
|
* @param string $filename
|
||||||
|
*
|
||||||
if (!$ret) {
|
* @return bool
|
||||||
$perms = fileperms($filename);
|
*/
|
||||||
$ret = ($perms & 0x0080) || ($perms & 0x0010) || ($perms & 0x0002);
|
public static function is_writable ($filename) {
|
||||||
}
|
$ret = is_writable($filename);
|
||||||
|
if (!$ret) {
|
||||||
return $ret;
|
$perms = fileperms($filename);
|
||||||
}
|
$ret = ($perms & 0x0080) || ($perms & 0x0010) || ($perms & 0x0002);
|
||||||
|
}
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
abstract class getid3_handler {
|
abstract class getid3_handler
|
||||||
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var getID3
|
* @var getID3
|
||||||
*/
|
*/
|
||||||
protected $getid3; // pointer
|
protected $getid3; // pointer
|
||||||
|
|
||||||
protected $data_string_flag = false; // analyzing filepointer or string
|
/**
|
||||||
protected $data_string = ''; // string to analyze
|
* Analyzing filepointer or string.
|
||||||
protected $data_string_position = 0; // seek position in string
|
*
|
||||||
protected $data_string_length = 0; // string length
|
* @var bool
|
||||||
|
*/
|
||||||
|
protected $data_string_flag = false;
|
||||||
|
|
||||||
private $dependency_to = null;
|
/**
|
||||||
|
* String to analyze.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $data_string = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Seek position in string.
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
protected $data_string_position = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* String length.
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
protected $data_string_length = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $dependency_to;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* getid3_handler constructor.
|
||||||
|
*
|
||||||
|
* @param getID3 $getid3
|
||||||
|
* @param string $call_module
|
||||||
|
*/
|
||||||
public function __construct(getID3 $getid3, $call_module=null) {
|
public function __construct(getID3 $getid3, $call_module=null) {
|
||||||
$this->getid3 = $getid3;
|
$this->getid3 = $getid3;
|
||||||
|
|
||||||
|
@ -1640,12 +1907,18 @@ abstract class getid3_handler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
// Analyze from file pointer
|
* Analyze from file pointer.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
abstract public function Analyze();
|
abstract public function Analyze();
|
||||||
|
|
||||||
|
/**
|
||||||
// Analyze from string instead
|
* Analyze from string instead.
|
||||||
|
*
|
||||||
|
* @param string $string
|
||||||
|
*/
|
||||||
public function AnalyzeString($string) {
|
public function AnalyzeString($string) {
|
||||||
// Enter string mode
|
// Enter string mode
|
||||||
$this->setStringMode($string);
|
$this->setStringMode($string);
|
||||||
|
@ -1671,12 +1944,18 @@ abstract class getid3_handler {
|
||||||
$this->data_string_flag = false;
|
$this->data_string_flag = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $string
|
||||||
|
*/
|
||||||
public function setStringMode($string) {
|
public function setStringMode($string) {
|
||||||
$this->data_string_flag = true;
|
$this->data_string_flag = true;
|
||||||
$this->data_string = $string;
|
$this->data_string = $string;
|
||||||
$this->data_string_length = strlen($string);
|
$this->data_string_length = strlen($string);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return int|bool
|
||||||
|
*/
|
||||||
protected function ftell() {
|
protected function ftell() {
|
||||||
if ($this->data_string_flag) {
|
if ($this->data_string_flag) {
|
||||||
return $this->data_string_position;
|
return $this->data_string_position;
|
||||||
|
@ -1684,6 +1963,13 @@ abstract class getid3_handler {
|
||||||
return ftell($this->getid3->fp);
|
return ftell($this->getid3->fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $bytes
|
||||||
|
*
|
||||||
|
* @return string|false
|
||||||
|
*
|
||||||
|
* @throws getid3_exception
|
||||||
|
*/
|
||||||
protected function fread($bytes) {
|
protected function fread($bytes) {
|
||||||
if ($this->data_string_flag) {
|
if ($this->data_string_flag) {
|
||||||
$this->data_string_position += $bytes;
|
$this->data_string_position += $bytes;
|
||||||
|
@ -1696,7 +1982,7 @@ abstract class getid3_handler {
|
||||||
|
|
||||||
//return fread($this->getid3->fp, $bytes);
|
//return fread($this->getid3->fp, $bytes);
|
||||||
/*
|
/*
|
||||||
* http://www.getid3.org/phpBB3/viewtopic.php?t=1930
|
* https://www.getid3.org/phpBB3/viewtopic.php?t=1930
|
||||||
* "I found out that the root cause for the problem was how getID3 uses the PHP system function fread().
|
* "I found out that the root cause for the problem was how getID3 uses the PHP system function fread().
|
||||||
* It seems to assume that fread() would always return as many bytes as were requested.
|
* It seems to assume that fread() would always return as many bytes as were requested.
|
||||||
* However, according the PHP manual (http://php.net/manual/en/function.fread.php), this is the case only with regular local files, but not e.g. with Linux pipes.
|
* However, according the PHP manual (http://php.net/manual/en/function.fread.php), this is the case only with regular local files, but not e.g. with Linux pipes.
|
||||||
|
@ -1704,6 +1990,10 @@ abstract class getid3_handler {
|
||||||
*/
|
*/
|
||||||
$contents = '';
|
$contents = '';
|
||||||
do {
|
do {
|
||||||
|
//if (($this->getid3->memory_limit > 0) && ($bytes > $this->getid3->memory_limit)) {
|
||||||
|
if (($this->getid3->memory_limit > 0) && (($bytes / $this->getid3->memory_limit) > 0.99)) { // enable a more-fuzzy match to prevent close misses generating errors like "PHP Fatal error: Allowed memory size of 33554432 bytes exhausted (tried to allocate 33554464 bytes)"
|
||||||
|
throw new getid3_exception('cannot fread('.$bytes.' from '.$this->ftell().') that is more than available PHP memory ('.$this->getid3->memory_limit.')', 10);
|
||||||
|
}
|
||||||
$part = fread($this->getid3->fp, $bytes);
|
$part = fread($this->getid3->fp, $bytes);
|
||||||
$partLength = strlen($part);
|
$partLength = strlen($part);
|
||||||
$bytes -= $partLength;
|
$bytes -= $partLength;
|
||||||
|
@ -1712,6 +2002,14 @@ abstract class getid3_handler {
|
||||||
return $contents;
|
return $contents;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $bytes
|
||||||
|
* @param int $whence
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*
|
||||||
|
* @throws getid3_exception
|
||||||
|
*/
|
||||||
protected function fseek($bytes, $whence=SEEK_SET) {
|
protected function fseek($bytes, $whence=SEEK_SET) {
|
||||||
if ($this->data_string_flag) {
|
if ($this->data_string_flag) {
|
||||||
switch ($whence) {
|
switch ($whence) {
|
||||||
|
@ -1742,6 +2040,9 @@ abstract class getid3_handler {
|
||||||
return fseek($this->getid3->fp, $bytes, $whence);
|
return fseek($this->getid3->fp, $bytes, $whence);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
protected function feof() {
|
protected function feof() {
|
||||||
if ($this->data_string_flag) {
|
if ($this->data_string_flag) {
|
||||||
return $this->data_string_position >= $this->data_string_length;
|
return $this->data_string_position >= $this->data_string_length;
|
||||||
|
@ -1749,24 +2050,53 @@ abstract class getid3_handler {
|
||||||
return feof($this->getid3->fp);
|
return feof($this->getid3->fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $module
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
final protected function isDependencyFor($module) {
|
final protected function isDependencyFor($module) {
|
||||||
return $this->dependency_to == $module;
|
return $this->dependency_to == $module;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $text
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
protected function error($text) {
|
protected function error($text) {
|
||||||
$this->getid3->info['error'][] = $text;
|
$this->getid3->info['error'][] = $text;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $text
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
protected function warning($text) {
|
protected function warning($text) {
|
||||||
return $this->getid3->warning($text);
|
return $this->getid3->warning($text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $text
|
||||||
|
*/
|
||||||
protected function notice($text) {
|
protected function notice($text) {
|
||||||
// does nothing for now
|
// does nothing for now
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $name
|
||||||
|
* @param int $offset
|
||||||
|
* @param int $length
|
||||||
|
* @param string $image_mime
|
||||||
|
*
|
||||||
|
* @return string|null
|
||||||
|
*
|
||||||
|
* @throws Exception
|
||||||
|
* @throws getid3_exception
|
||||||
|
*/
|
||||||
public function saveAttachment($name, $offset, $length, $image_mime=null) {
|
public function saveAttachment($name, $offset, $length, $image_mime=null) {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
|
@ -1820,6 +2150,9 @@ abstract class getid3_handler {
|
||||||
// close and remove dest file if created
|
// close and remove dest file if created
|
||||||
if (isset($fp_dest) && is_resource($fp_dest)) {
|
if (isset($fp_dest) && is_resource($fp_dest)) {
|
||||||
fclose($fp_dest);
|
fclose($fp_dest);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($dest) && file_exists($dest)) {
|
||||||
unlink($dest);
|
unlink($dest);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////
|
||||||
/// getID3() by James Heinrich <info@getid3.org> //
|
/// getID3() by James Heinrich <info@getid3.org> //
|
||||||
// available at http://getid3.sourceforge.net //
|
// available at http://getid3.sourceforge.net //
|
||||||
// or http://www.getid3.org //
|
// or https://www.getid3.org //
|
||||||
// also https://github.com/JamesHeinrich/getID3 //
|
// also https://github.com/JamesHeinrich/getID3 //
|
||||||
/////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@ -18,9 +18,9 @@ GNU GPL: https://gnu.org/licenses/gpl.html (v3)
|
||||||
|
|
||||||
GNU LGPL: https://gnu.org/licenses/lgpl.html (v3)
|
GNU LGPL: https://gnu.org/licenses/lgpl.html (v3)
|
||||||
|
|
||||||
Mozilla MPL: http://www.mozilla.org/MPL/2.0/ (v2)
|
Mozilla MPL: https://www.mozilla.org/MPL/2.0/ (v2)
|
||||||
|
|
||||||
getID3 Commercial License: http://getid3.org/#gCL (payment required)
|
getID3 Commercial License: https://www.getid3.org/#gCL (payment required)
|
||||||
|
|
||||||
*****************************************************************
|
*****************************************************************
|
||||||
*****************************************************************
|
*****************************************************************
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
<?php
|
<?php
|
||||||
/////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////
|
||||||
/// getID3() by James Heinrich <info@getid3.org> //
|
/// getID3() by James Heinrich <info@getid3.org> //
|
||||||
// available at http://getid3.sourceforge.net //
|
// available at https://github.com/JamesHeinrich/getID3 //
|
||||||
// or http://www.getid3.org //
|
// or https://www.getid3.org //
|
||||||
// also https://github.com/JamesHeinrich/getID3 //
|
// or http://getid3.sourceforge.net //
|
||||||
/////////////////////////////////////////////////////////////////
|
// see readme.txt for more details //
|
||||||
// See readme.txt for more details //
|
|
||||||
/////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////
|
||||||
// //
|
// //
|
||||||
// module.audio-video.asf.php //
|
// module.audio-video.asf.php //
|
||||||
|
@ -16,8 +15,11 @@
|
||||||
|
|
||||||
getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.riff.php', __FILE__, true);
|
getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.riff.php', __FILE__, true);
|
||||||
|
|
||||||
class getid3_asf extends getid3_handler {
|
class getid3_asf extends getid3_handler
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param getID3 $getid3
|
||||||
|
*/
|
||||||
public function __construct(getID3 $getid3) {
|
public function __construct(getID3 $getid3) {
|
||||||
parent::__construct($getid3); // extends getid3_handler::__construct()
|
parent::__construct($getid3); // extends getid3_handler::__construct()
|
||||||
|
|
||||||
|
@ -30,6 +32,9 @@ class getid3_asf extends getid3_handler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
public function Analyze() {
|
public function Analyze() {
|
||||||
$info = &$this->getid3->info;
|
$info = &$this->getid3->info;
|
||||||
|
|
||||||
|
@ -83,6 +88,8 @@ class getid3_asf extends getid3_handler {
|
||||||
$NextObjectOffset = $this->ftell();
|
$NextObjectOffset = $this->ftell();
|
||||||
$ASFHeaderData = $this->fread($thisfile_asf_headerobject['objectsize'] - 30);
|
$ASFHeaderData = $this->fread($thisfile_asf_headerobject['objectsize'] - 30);
|
||||||
$offset = 0;
|
$offset = 0;
|
||||||
|
$thisfile_asf_streambitratepropertiesobject = array();
|
||||||
|
$thisfile_asf_codeclistobject = array();
|
||||||
|
|
||||||
for ($HeaderObjectsCounter = 0; $HeaderObjectsCounter < $thisfile_asf_headerobject['headerobjects']; $HeaderObjectsCounter++) {
|
for ($HeaderObjectsCounter = 0; $HeaderObjectsCounter < $thisfile_asf_headerobject['headerobjects']; $HeaderObjectsCounter++) {
|
||||||
$NextObjectGUID = substr($ASFHeaderData, $offset, 16);
|
$NextObjectGUID = substr($ASFHeaderData, $offset, 16);
|
||||||
|
@ -790,17 +797,17 @@ class getid3_asf extends getid3_handler {
|
||||||
case 'wm/tracknumber':
|
case 'wm/tracknumber':
|
||||||
case 'tracknumber':
|
case 'tracknumber':
|
||||||
// be careful casting to int: casting unicode strings to int gives unexpected results (stops parsing at first non-numeric character)
|
// be careful casting to int: casting unicode strings to int gives unexpected results (stops parsing at first non-numeric character)
|
||||||
$thisfile_asf_comments['track'] = array($this->TrimTerm($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']));
|
$thisfile_asf_comments['track_number'] = array($this->TrimTerm($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']));
|
||||||
foreach ($thisfile_asf_comments['track'] as $key => $value) {
|
foreach ($thisfile_asf_comments['track_number'] as $key => $value) {
|
||||||
if (preg_match('/^[0-9\x00]+$/', $value)) {
|
if (preg_match('/^[0-9\x00]+$/', $value)) {
|
||||||
$thisfile_asf_comments['track'][$key] = intval(str_replace("\x00", '', $value));
|
$thisfile_asf_comments['track_number'][$key] = intval(str_replace("\x00", '', $value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'wm/track':
|
case 'wm/track':
|
||||||
if (empty($thisfile_asf_comments['track'])) {
|
if (empty($thisfile_asf_comments['track_number'])) {
|
||||||
$thisfile_asf_comments['track'] = array(1 + $this->TrimConvert($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']));
|
$thisfile_asf_comments['track_number'] = array(1 + $this->TrimConvert($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -970,18 +977,18 @@ class getid3_asf extends getid3_handler {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (isset($thisfile_asf_streambitrateproperties['bitrate_records_count'])) {
|
if (isset($thisfile_asf_streambitratepropertiesobject['bitrate_records_count'])) {
|
||||||
$ASFbitrateAudio = 0;
|
$ASFbitrateAudio = 0;
|
||||||
$ASFbitrateVideo = 0;
|
$ASFbitrateVideo = 0;
|
||||||
for ($BitrateRecordsCounter = 0; $BitrateRecordsCounter < $thisfile_asf_streambitrateproperties['bitrate_records_count']; $BitrateRecordsCounter++) {
|
for ($BitrateRecordsCounter = 0; $BitrateRecordsCounter < $thisfile_asf_streambitratepropertiesobject['bitrate_records_count']; $BitrateRecordsCounter++) {
|
||||||
if (isset($thisfile_asf_codeclistobject['codec_entries'][$BitrateRecordsCounter])) {
|
if (isset($thisfile_asf_codeclistobject['codec_entries'][$BitrateRecordsCounter])) {
|
||||||
switch ($thisfile_asf_codeclistobject['codec_entries'][$BitrateRecordsCounter]['type_raw']) {
|
switch ($thisfile_asf_codeclistobject['codec_entries'][$BitrateRecordsCounter]['type_raw']) {
|
||||||
case 1:
|
case 1:
|
||||||
$ASFbitrateVideo += $thisfile_asf_streambitrateproperties['bitrate_records'][$BitrateRecordsCounter]['bitrate'];
|
$ASFbitrateVideo += $thisfile_asf_streambitratepropertiesobject['bitrate_records'][$BitrateRecordsCounter]['bitrate'];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
$ASFbitrateAudio += $thisfile_asf_streambitrateproperties['bitrate_records'][$BitrateRecordsCounter]['bitrate'];
|
$ASFbitrateAudio += $thisfile_asf_streambitratepropertiesobject['bitrate_records'][$BitrateRecordsCounter]['bitrate'];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -1440,6 +1447,11 @@ class getid3_asf extends getid3_handler {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $CodecListType
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public static function codecListObjectTypeLookup($CodecListType) {
|
public static function codecListObjectTypeLookup($CodecListType) {
|
||||||
static $lookup = array(
|
static $lookup = array(
|
||||||
0x0001 => 'Video Codec',
|
0x0001 => 'Video Codec',
|
||||||
|
@ -1450,6 +1462,9 @@ class getid3_asf extends getid3_handler {
|
||||||
return (isset($lookup[$CodecListType]) ? $lookup[$CodecListType] : 'Invalid Codec Type');
|
return (isset($lookup[$CodecListType]) ? $lookup[$CodecListType] : 'Invalid Codec Type');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
public static function KnownGUIDs() {
|
public static function KnownGUIDs() {
|
||||||
static $GUIDarray = array(
|
static $GUIDarray = array(
|
||||||
'GETID3_ASF_Extended_Stream_Properties_Object' => '14E6A5CB-C672-4332-8399-A96952065B5A',
|
'GETID3_ASF_Extended_Stream_Properties_Object' => '14E6A5CB-C672-4332-8399-A96952065B5A',
|
||||||
|
@ -1564,6 +1579,11 @@ class getid3_asf extends getid3_handler {
|
||||||
return $GUIDarray;
|
return $GUIDarray;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $GUIDstring
|
||||||
|
*
|
||||||
|
* @return string|false
|
||||||
|
*/
|
||||||
public static function GUIDname($GUIDstring) {
|
public static function GUIDname($GUIDstring) {
|
||||||
static $GUIDarray = array();
|
static $GUIDarray = array();
|
||||||
if (empty($GUIDarray)) {
|
if (empty($GUIDarray)) {
|
||||||
|
@ -1572,6 +1592,11 @@ class getid3_asf extends getid3_handler {
|
||||||
return array_search($GUIDstring, $GUIDarray);
|
return array_search($GUIDstring, $GUIDarray);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $id
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public static function ASFIndexObjectIndexTypeLookup($id) {
|
public static function ASFIndexObjectIndexTypeLookup($id) {
|
||||||
static $ASFIndexObjectIndexTypeLookup = array();
|
static $ASFIndexObjectIndexTypeLookup = array();
|
||||||
if (empty($ASFIndexObjectIndexTypeLookup)) {
|
if (empty($ASFIndexObjectIndexTypeLookup)) {
|
||||||
|
@ -1582,6 +1607,11 @@ class getid3_asf extends getid3_handler {
|
||||||
return (isset($ASFIndexObjectIndexTypeLookup[$id]) ? $ASFIndexObjectIndexTypeLookup[$id] : 'invalid');
|
return (isset($ASFIndexObjectIndexTypeLookup[$id]) ? $ASFIndexObjectIndexTypeLookup[$id] : 'invalid');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $GUIDstring
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public static function GUIDtoBytestring($GUIDstring) {
|
public static function GUIDtoBytestring($GUIDstring) {
|
||||||
// Microsoft defines these 16-byte (128-bit) GUIDs in the strangest way:
|
// Microsoft defines these 16-byte (128-bit) GUIDs in the strangest way:
|
||||||
// first 4 bytes are in little-endian order
|
// first 4 bytes are in little-endian order
|
||||||
|
@ -1617,31 +1647,42 @@ class getid3_asf extends getid3_handler {
|
||||||
return $hexbytecharstring;
|
return $hexbytecharstring;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $Bytestring
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public static function BytestringToGUID($Bytestring) {
|
public static function BytestringToGUID($Bytestring) {
|
||||||
$GUIDstring = str_pad(dechex(ord($Bytestring{3})), 2, '0', STR_PAD_LEFT);
|
$GUIDstring = str_pad(dechex(ord($Bytestring[3])), 2, '0', STR_PAD_LEFT);
|
||||||
$GUIDstring .= str_pad(dechex(ord($Bytestring{2})), 2, '0', STR_PAD_LEFT);
|
$GUIDstring .= str_pad(dechex(ord($Bytestring[2])), 2, '0', STR_PAD_LEFT);
|
||||||
$GUIDstring .= str_pad(dechex(ord($Bytestring{1})), 2, '0', STR_PAD_LEFT);
|
$GUIDstring .= str_pad(dechex(ord($Bytestring[1])), 2, '0', STR_PAD_LEFT);
|
||||||
$GUIDstring .= str_pad(dechex(ord($Bytestring{0})), 2, '0', STR_PAD_LEFT);
|
$GUIDstring .= str_pad(dechex(ord($Bytestring[0])), 2, '0', STR_PAD_LEFT);
|
||||||
$GUIDstring .= '-';
|
$GUIDstring .= '-';
|
||||||
$GUIDstring .= str_pad(dechex(ord($Bytestring{5})), 2, '0', STR_PAD_LEFT);
|
$GUIDstring .= str_pad(dechex(ord($Bytestring[5])), 2, '0', STR_PAD_LEFT);
|
||||||
$GUIDstring .= str_pad(dechex(ord($Bytestring{4})), 2, '0', STR_PAD_LEFT);
|
$GUIDstring .= str_pad(dechex(ord($Bytestring[4])), 2, '0', STR_PAD_LEFT);
|
||||||
$GUIDstring .= '-';
|
$GUIDstring .= '-';
|
||||||
$GUIDstring .= str_pad(dechex(ord($Bytestring{7})), 2, '0', STR_PAD_LEFT);
|
$GUIDstring .= str_pad(dechex(ord($Bytestring[7])), 2, '0', STR_PAD_LEFT);
|
||||||
$GUIDstring .= str_pad(dechex(ord($Bytestring{6})), 2, '0', STR_PAD_LEFT);
|
$GUIDstring .= str_pad(dechex(ord($Bytestring[6])), 2, '0', STR_PAD_LEFT);
|
||||||
$GUIDstring .= '-';
|
$GUIDstring .= '-';
|
||||||
$GUIDstring .= str_pad(dechex(ord($Bytestring{8})), 2, '0', STR_PAD_LEFT);
|
$GUIDstring .= str_pad(dechex(ord($Bytestring[8])), 2, '0', STR_PAD_LEFT);
|
||||||
$GUIDstring .= str_pad(dechex(ord($Bytestring{9})), 2, '0', STR_PAD_LEFT);
|
$GUIDstring .= str_pad(dechex(ord($Bytestring[9])), 2, '0', STR_PAD_LEFT);
|
||||||
$GUIDstring .= '-';
|
$GUIDstring .= '-';
|
||||||
$GUIDstring .= str_pad(dechex(ord($Bytestring{10})), 2, '0', STR_PAD_LEFT);
|
$GUIDstring .= str_pad(dechex(ord($Bytestring[10])), 2, '0', STR_PAD_LEFT);
|
||||||
$GUIDstring .= str_pad(dechex(ord($Bytestring{11})), 2, '0', STR_PAD_LEFT);
|
$GUIDstring .= str_pad(dechex(ord($Bytestring[11])), 2, '0', STR_PAD_LEFT);
|
||||||
$GUIDstring .= str_pad(dechex(ord($Bytestring{12})), 2, '0', STR_PAD_LEFT);
|
$GUIDstring .= str_pad(dechex(ord($Bytestring[12])), 2, '0', STR_PAD_LEFT);
|
||||||
$GUIDstring .= str_pad(dechex(ord($Bytestring{13})), 2, '0', STR_PAD_LEFT);
|
$GUIDstring .= str_pad(dechex(ord($Bytestring[13])), 2, '0', STR_PAD_LEFT);
|
||||||
$GUIDstring .= str_pad(dechex(ord($Bytestring{14})), 2, '0', STR_PAD_LEFT);
|
$GUIDstring .= str_pad(dechex(ord($Bytestring[14])), 2, '0', STR_PAD_LEFT);
|
||||||
$GUIDstring .= str_pad(dechex(ord($Bytestring{15})), 2, '0', STR_PAD_LEFT);
|
$GUIDstring .= str_pad(dechex(ord($Bytestring[15])), 2, '0', STR_PAD_LEFT);
|
||||||
|
|
||||||
return strtoupper($GUIDstring);
|
return strtoupper($GUIDstring);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $FILETIME
|
||||||
|
* @param bool $round
|
||||||
|
*
|
||||||
|
* @return float|int
|
||||||
|
*/
|
||||||
public static function FILETIMEtoUNIXtime($FILETIME, $round=true) {
|
public static function FILETIMEtoUNIXtime($FILETIME, $round=true) {
|
||||||
// FILETIME is a 64-bit unsigned integer representing
|
// FILETIME is a 64-bit unsigned integer representing
|
||||||
// the number of 100-nanosecond intervals since January 1, 1601
|
// the number of 100-nanosecond intervals since January 1, 1601
|
||||||
|
@ -1653,6 +1694,11 @@ class getid3_asf extends getid3_handler {
|
||||||
return ($FILETIME - 116444736000000000) / 10000000;
|
return ($FILETIME - 116444736000000000) / 10000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $WMpictureType
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public static function WMpictureTypeLookup($WMpictureType) {
|
public static function WMpictureTypeLookup($WMpictureType) {
|
||||||
static $lookup = null;
|
static $lookup = null;
|
||||||
if ($lookup === null) {
|
if ($lookup === null) {
|
||||||
|
@ -1684,6 +1730,12 @@ class getid3_asf extends getid3_handler {
|
||||||
return (isset($lookup[$WMpictureType]) ? $lookup[$WMpictureType] : '');
|
return (isset($lookup[$WMpictureType]) ? $lookup[$WMpictureType] : '');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $asf_header_extension_object_data
|
||||||
|
* @param int $unhandled_sections
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
public function HeaderExtensionObjectDataParse(&$asf_header_extension_object_data, &$unhandled_sections) {
|
public function HeaderExtensionObjectDataParse(&$asf_header_extension_object_data, &$unhandled_sections) {
|
||||||
// http://msdn.microsoft.com/en-us/library/bb643323.aspx
|
// http://msdn.microsoft.com/en-us/library/bb643323.aspx
|
||||||
|
|
||||||
|
@ -1930,7 +1982,11 @@ class getid3_asf extends getid3_handler {
|
||||||
return $HeaderExtensionObjectParsed;
|
return $HeaderExtensionObjectParsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $id
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public static function metadataLibraryObjectDataTypeLookup($id) {
|
public static function metadataLibraryObjectDataTypeLookup($id) {
|
||||||
static $lookup = array(
|
static $lookup = array(
|
||||||
0x0000 => 'Unicode string', // The data consists of a sequence of Unicode characters
|
0x0000 => 'Unicode string', // The data consists of a sequence of Unicode characters
|
||||||
|
@ -1944,6 +2000,11 @@ class getid3_asf extends getid3_handler {
|
||||||
return (isset($lookup[$id]) ? $lookup[$id] : 'invalid');
|
return (isset($lookup[$id]) ? $lookup[$id] : 'invalid');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $data
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
public function ASF_WMpicture(&$data) {
|
public function ASF_WMpicture(&$data) {
|
||||||
//typedef struct _WMPicture{
|
//typedef struct _WMPicture{
|
||||||
// LPWSTR pwszMIMEType;
|
// LPWSTR pwszMIMEType;
|
||||||
|
@ -1994,14 +2055,24 @@ class getid3_asf extends getid3_handler {
|
||||||
return $WMpicture;
|
return $WMpicture;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
// Remove terminator 00 00 and convert UTF-16LE to Latin-1
|
* Remove terminator 00 00 and convert UTF-16LE to Latin-1.
|
||||||
|
*
|
||||||
|
* @param string $string
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public static function TrimConvert($string) {
|
public static function TrimConvert($string) {
|
||||||
return trim(getid3_lib::iconv_fallback('UTF-16LE', 'ISO-8859-1', self::TrimTerm($string)), ' ');
|
return trim(getid3_lib::iconv_fallback('UTF-16LE', 'ISO-8859-1', self::TrimTerm($string)), ' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
// Remove terminator 00 00
|
* Remove terminator 00 00.
|
||||||
|
*
|
||||||
|
* @param string $string
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public static function TrimTerm($string) {
|
public static function TrimTerm($string) {
|
||||||
// remove terminator, only if present (it should be, but...)
|
// remove terminator, only if present (it should be, but...)
|
||||||
if (substr($string, -2) === "\x00\x00") {
|
if (substr($string, -2) === "\x00\x00") {
|
||||||
|
|
|
@ -1,15 +1,22 @@
|
||||||
<?php
|
<?php
|
||||||
/////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////
|
||||||
/// getID3() by James Heinrich <info@getid3.org> //
|
/// getID3() by James Heinrich <info@getid3.org> //
|
||||||
// available at http://getid3.sourceforge.net //
|
// available at https://github.com/JamesHeinrich/getID3 //
|
||||||
// or http://www.getid3.org //
|
// or https://www.getid3.org //
|
||||||
// also https://github.com/JamesHeinrich/getID3 //
|
// or http://getid3.sourceforge.net //
|
||||||
|
// see readme.txt for more details //
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
// //
|
||||||
|
// module.audio-video.flv.php //
|
||||||
|
// module for analyzing Shockwave Flash Video files //
|
||||||
|
// dependencies: NONE //
|
||||||
|
// //
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
// //
|
// //
|
||||||
// FLV module by Seth Kaufman <sethØwhirl-i-gig*com> //
|
// FLV module by Seth Kaufman <sethØwhirl-i-gig*com> //
|
||||||
// //
|
// //
|
||||||
// * version 0.1 (26 June 2005) //
|
// * version 0.1 (26 June 2005) //
|
||||||
// //
|
// //
|
||||||
// //
|
|
||||||
// * version 0.1.1 (15 July 2005) //
|
// * version 0.1.1 (15 July 2005) //
|
||||||
// minor modifications by James Heinrich <info@getid3.org> //
|
// minor modifications by James Heinrich <info@getid3.org> //
|
||||||
// //
|
// //
|
||||||
|
@ -43,12 +50,6 @@
|
||||||
// handle GETID3_FLV_VIDEO_VP6FLV_ALPHA //
|
// handle GETID3_FLV_VIDEO_VP6FLV_ALPHA //
|
||||||
// improved AVCSequenceParameterSetReader::readData() //
|
// improved AVCSequenceParameterSetReader::readData() //
|
||||||
// by Xander Schouwerwou <schouwerwouØgmail*com> //
|
// by Xander Schouwerwou <schouwerwouØgmail*com> //
|
||||||
// //
|
|
||||||
/////////////////////////////////////////////////////////////////
|
|
||||||
// //
|
|
||||||
// module.audio-video.flv.php //
|
|
||||||
// module for analyzing Shockwave Flash Video files //
|
|
||||||
// dependencies: NONE //
|
|
||||||
// ///
|
// ///
|
||||||
/////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@ -73,12 +74,21 @@ define('H264_PROFILE_HIGH422', 122);
|
||||||
define('H264_PROFILE_HIGH444', 144);
|
define('H264_PROFILE_HIGH444', 144);
|
||||||
define('H264_PROFILE_HIGH444_PREDICTIVE', 244);
|
define('H264_PROFILE_HIGH444_PREDICTIVE', 244);
|
||||||
|
|
||||||
class getid3_flv extends getid3_handler {
|
class getid3_flv extends getid3_handler
|
||||||
|
{
|
||||||
const magic = 'FLV';
|
const magic = 'FLV';
|
||||||
|
|
||||||
public $max_frames = 100000; // break out of the loop if too many frames have been scanned; only scan this many if meta frame does not contain useful duration
|
/**
|
||||||
|
* Break out of the loop if too many frames have been scanned; only scan this
|
||||||
|
* many if meta frame does not contain useful duration.
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
public $max_frames = 100000;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
public function Analyze() {
|
public function Analyze() {
|
||||||
$info = &$this->getid3->info;
|
$info = &$this->getid3->info;
|
||||||
|
|
||||||
|
@ -332,7 +342,11 @@ class getid3_flv extends getid3_handler {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $id
|
||||||
|
*
|
||||||
|
* @return string|false
|
||||||
|
*/
|
||||||
public static function audioFormatLookup($id) {
|
public static function audioFormatLookup($id) {
|
||||||
static $lookup = array(
|
static $lookup = array(
|
||||||
0 => 'Linear PCM, platform endian',
|
0 => 'Linear PCM, platform endian',
|
||||||
|
@ -355,6 +369,11 @@ class getid3_flv extends getid3_handler {
|
||||||
return (isset($lookup[$id]) ? $lookup[$id] : false);
|
return (isset($lookup[$id]) ? $lookup[$id] : false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $id
|
||||||
|
*
|
||||||
|
* @return int|false
|
||||||
|
*/
|
||||||
public static function audioRateLookup($id) {
|
public static function audioRateLookup($id) {
|
||||||
static $lookup = array(
|
static $lookup = array(
|
||||||
0 => 5500,
|
0 => 5500,
|
||||||
|
@ -365,6 +384,11 @@ class getid3_flv extends getid3_handler {
|
||||||
return (isset($lookup[$id]) ? $lookup[$id] : false);
|
return (isset($lookup[$id]) ? $lookup[$id] : false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $id
|
||||||
|
*
|
||||||
|
* @return int|false
|
||||||
|
*/
|
||||||
public static function audioBitDepthLookup($id) {
|
public static function audioBitDepthLookup($id) {
|
||||||
static $lookup = array(
|
static $lookup = array(
|
||||||
0 => 8,
|
0 => 8,
|
||||||
|
@ -373,6 +397,11 @@ class getid3_flv extends getid3_handler {
|
||||||
return (isset($lookup[$id]) ? $lookup[$id] : false);
|
return (isset($lookup[$id]) ? $lookup[$id] : false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $id
|
||||||
|
*
|
||||||
|
* @return string|false
|
||||||
|
*/
|
||||||
public static function videoCodecLookup($id) {
|
public static function videoCodecLookup($id) {
|
||||||
static $lookup = array(
|
static $lookup = array(
|
||||||
GETID3_FLV_VIDEO_H263 => 'Sorenson H.263',
|
GETID3_FLV_VIDEO_H263 => 'Sorenson H.263',
|
||||||
|
@ -386,47 +415,84 @@ class getid3_flv extends getid3_handler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class AMFStream {
|
class AMFStream
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
public $bytes;
|
public $bytes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
public $pos;
|
public $pos;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $bytes
|
||||||
|
*/
|
||||||
public function __construct(&$bytes) {
|
public function __construct(&$bytes) {
|
||||||
$this->bytes =& $bytes;
|
$this->bytes =& $bytes;
|
||||||
$this->pos = 0;
|
$this->pos = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function readByte() {
|
/**
|
||||||
return getid3_lib::BigEndian2Int(substr($this->bytes, $this->pos++, 1));
|
* @return int
|
||||||
|
*/
|
||||||
|
public function readByte() { // 8-bit
|
||||||
|
return ord(substr($this->bytes, $this->pos++, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function readInt() {
|
/**
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function readInt() { // 16-bit
|
||||||
return ($this->readByte() << 8) + $this->readByte();
|
return ($this->readByte() << 8) + $this->readByte();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function readLong() {
|
/**
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function readLong() { // 32-bit
|
||||||
return ($this->readByte() << 24) + ($this->readByte() << 16) + ($this->readByte() << 8) + $this->readByte();
|
return ($this->readByte() << 24) + ($this->readByte() << 16) + ($this->readByte() << 8) + $this->readByte();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return float|false
|
||||||
|
*/
|
||||||
public function readDouble() {
|
public function readDouble() {
|
||||||
return getid3_lib::BigEndian2Float($this->read(8));
|
return getid3_lib::BigEndian2Float($this->read(8));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public function readUTF() {
|
public function readUTF() {
|
||||||
$length = $this->readInt();
|
$length = $this->readInt();
|
||||||
return $this->read($length);
|
return $this->read($length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public function readLongUTF() {
|
public function readLongUTF() {
|
||||||
$length = $this->readLong();
|
$length = $this->readLong();
|
||||||
return $this->read($length);
|
return $this->read($length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $length
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public function read($length) {
|
public function read($length) {
|
||||||
$val = substr($this->bytes, $this->pos, $length);
|
$val = substr($this->bytes, $this->pos, $length);
|
||||||
$this->pos += $length;
|
$this->pos += $length;
|
||||||
return $val;
|
return $val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
public function peekByte() {
|
public function peekByte() {
|
||||||
$pos = $this->pos;
|
$pos = $this->pos;
|
||||||
$val = $this->readByte();
|
$val = $this->readByte();
|
||||||
|
@ -434,6 +500,9 @@ class AMFStream {
|
||||||
return $val;
|
return $val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
public function peekInt() {
|
public function peekInt() {
|
||||||
$pos = $this->pos;
|
$pos = $this->pos;
|
||||||
$val = $this->readInt();
|
$val = $this->readInt();
|
||||||
|
@ -441,6 +510,9 @@ class AMFStream {
|
||||||
return $val;
|
return $val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
public function peekLong() {
|
public function peekLong() {
|
||||||
$pos = $this->pos;
|
$pos = $this->pos;
|
||||||
$val = $this->readLong();
|
$val = $this->readLong();
|
||||||
|
@ -448,6 +520,9 @@ class AMFStream {
|
||||||
return $val;
|
return $val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return float|false
|
||||||
|
*/
|
||||||
public function peekDouble() {
|
public function peekDouble() {
|
||||||
$pos = $this->pos;
|
$pos = $this->pos;
|
||||||
$val = $this->readDouble();
|
$val = $this->readDouble();
|
||||||
|
@ -455,6 +530,9 @@ class AMFStream {
|
||||||
return $val;
|
return $val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public function peekUTF() {
|
public function peekUTF() {
|
||||||
$pos = $this->pos;
|
$pos = $this->pos;
|
||||||
$val = $this->readUTF();
|
$val = $this->readUTF();
|
||||||
|
@ -462,6 +540,9 @@ class AMFStream {
|
||||||
return $val;
|
return $val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public function peekLongUTF() {
|
public function peekLongUTF() {
|
||||||
$pos = $this->pos;
|
$pos = $this->pos;
|
||||||
$val = $this->readLongUTF();
|
$val = $this->readLongUTF();
|
||||||
|
@ -470,13 +551,23 @@ class AMFStream {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class AMFReader {
|
class AMFReader
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var AMFStream
|
||||||
|
*/
|
||||||
public $stream;
|
public $stream;
|
||||||
|
|
||||||
public function __construct(&$stream) {
|
/**
|
||||||
$this->stream =& $stream;
|
* @param AMFStream $stream
|
||||||
|
*/
|
||||||
|
public function __construct(AMFStream $stream) {
|
||||||
|
$this->stream = $stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
public function readData() {
|
public function readData() {
|
||||||
$value = null;
|
$value = null;
|
||||||
|
|
||||||
|
@ -547,23 +638,36 @@ class AMFReader {
|
||||||
return $value;
|
return $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return float|false
|
||||||
|
*/
|
||||||
public function readDouble() {
|
public function readDouble() {
|
||||||
return $this->stream->readDouble();
|
return $this->stream->readDouble();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
public function readBoolean() {
|
public function readBoolean() {
|
||||||
return $this->stream->readByte() == 1;
|
return $this->stream->readByte() == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public function readString() {
|
public function readString() {
|
||||||
return $this->stream->readUTF();
|
return $this->stream->readUTF();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
public function readObject() {
|
public function readObject() {
|
||||||
// Get highest numerical index - ignored
|
// Get highest numerical index - ignored
|
||||||
// $highestIndex = $this->stream->readLong();
|
// $highestIndex = $this->stream->readLong();
|
||||||
|
|
||||||
$data = array();
|
$data = array();
|
||||||
|
$key = null;
|
||||||
|
|
||||||
while ($key = $this->stream->readUTF()) {
|
while ($key = $this->stream->readUTF()) {
|
||||||
$data[$key] = $this->readData();
|
$data[$key] = $this->readData();
|
||||||
|
@ -576,15 +680,19 @@ class AMFReader {
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
public function readMixedArray() {
|
public function readMixedArray() {
|
||||||
// Get highest numerical index - ignored
|
// Get highest numerical index - ignored
|
||||||
$highestIndex = $this->stream->readLong();
|
$highestIndex = $this->stream->readLong();
|
||||||
|
|
||||||
$data = array();
|
$data = array();
|
||||||
|
$key = null;
|
||||||
|
|
||||||
while ($key = $this->stream->readUTF()) {
|
while ($key = $this->stream->readUTF()) {
|
||||||
if (is_numeric($key)) {
|
if (is_numeric($key)) {
|
||||||
$key = (float) $key;
|
$key = (int) $key;
|
||||||
}
|
}
|
||||||
$data[$key] = $this->readData();
|
$data[$key] = $this->readData();
|
||||||
}
|
}
|
||||||
|
@ -597,6 +705,9 @@ class AMFReader {
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
public function readArray() {
|
public function readArray() {
|
||||||
$length = $this->stream->readLong();
|
$length = $this->stream->readLong();
|
||||||
$data = array();
|
$data = array();
|
||||||
|
@ -607,34 +718,61 @@ class AMFReader {
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return float|false
|
||||||
|
*/
|
||||||
public function readDate() {
|
public function readDate() {
|
||||||
$timestamp = $this->stream->readDouble();
|
$timestamp = $this->stream->readDouble();
|
||||||
$timezone = $this->stream->readInt();
|
$timezone = $this->stream->readInt();
|
||||||
return $timestamp;
|
return $timestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public function readLongString() {
|
public function readLongString() {
|
||||||
return $this->stream->readLongUTF();
|
return $this->stream->readLongUTF();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public function readXML() {
|
public function readXML() {
|
||||||
return $this->stream->readLongUTF();
|
return $this->stream->readLongUTF();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
public function readTypedObject() {
|
public function readTypedObject() {
|
||||||
$className = $this->stream->readUTF();
|
$className = $this->stream->readUTF();
|
||||||
return $this->readObject();
|
return $this->readObject();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class AVCSequenceParameterSetReader {
|
class AVCSequenceParameterSetReader
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
public $sps;
|
public $sps;
|
||||||
public $start = 0;
|
public $start = 0;
|
||||||
public $currentBytes = 0;
|
public $currentBytes = 0;
|
||||||
public $currentBits = 0;
|
public $currentBits = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
public $width;
|
public $width;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
public $height;
|
public $height;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $sps
|
||||||
|
*/
|
||||||
public function __construct($sps) {
|
public function __construct($sps) {
|
||||||
$this->sps = $sps;
|
$this->sps = $sps;
|
||||||
}
|
}
|
||||||
|
@ -691,18 +829,29 @@ class AVCSequenceParameterSetReader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $bits
|
||||||
|
*/
|
||||||
public function skipBits($bits) {
|
public function skipBits($bits) {
|
||||||
$newBits = $this->currentBits + $bits;
|
$newBits = $this->currentBits + $bits;
|
||||||
$this->currentBytes += (int)floor($newBits / 8);
|
$this->currentBytes += (int)floor($newBits / 8);
|
||||||
$this->currentBits = $newBits % 8;
|
$this->currentBits = $newBits % 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
public function getBit() {
|
public function getBit() {
|
||||||
$result = (getid3_lib::BigEndian2Int(substr($this->sps, $this->currentBytes, 1)) >> (7 - $this->currentBits)) & 0x01;
|
$result = (getid3_lib::BigEndian2Int(substr($this->sps, $this->currentBytes, 1)) >> (7 - $this->currentBits)) & 0x01;
|
||||||
$this->skipBits(1);
|
$this->skipBits(1);
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $bits
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
public function getBits($bits) {
|
public function getBits($bits) {
|
||||||
$result = 0;
|
$result = 0;
|
||||||
for ($i = 0; $i < $bits; $i++) {
|
for ($i = 0; $i < $bits; $i++) {
|
||||||
|
@ -711,6 +860,9 @@ class AVCSequenceParameterSetReader {
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
public function expGolombUe() {
|
public function expGolombUe() {
|
||||||
$significantBits = 0;
|
$significantBits = 0;
|
||||||
$bit = $this->getBit();
|
$bit = $this->getBit();
|
||||||
|
@ -726,6 +878,9 @@ class AVCSequenceParameterSetReader {
|
||||||
return (1 << $significantBits) + $this->getBits($significantBits) - 1;
|
return (1 << $significantBits) + $this->getBits($significantBits) - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
public function expGolombSe() {
|
public function expGolombSe() {
|
||||||
$result = $this->expGolombUe();
|
$result = $this->expGolombUe();
|
||||||
if (($result & 0x01) == 0) {
|
if (($result & 0x01) == 0) {
|
||||||
|
@ -735,10 +890,16 @@ class AVCSequenceParameterSetReader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
public function getWidth() {
|
public function getWidth() {
|
||||||
return $this->width;
|
return $this->width;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
public function getHeight() {
|
public function getHeight() {
|
||||||
return $this->height;
|
return $this->height;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////
|
||||||
/// getID3() by James Heinrich <info@getid3.org> //
|
/// getID3() by James Heinrich <info@getid3.org> //
|
||||||
// available at http://getid3.sourceforge.net //
|
// available at https://github.com/JamesHeinrich/getID3 //
|
||||||
// or http://www.getid3.org //
|
// or https://www.getid3.org //
|
||||||
// also https://github.com/JamesHeinrich/getID3 //
|
// or http://getid3.sourceforge.net //
|
||||||
/////////////////////////////////////////////////////////////////
|
// see readme.txt for more details //
|
||||||
// See readme.txt for more details //
|
|
||||||
/////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////
|
||||||
// //
|
// //
|
||||||
// module.audio-video.matriska.php //
|
// module.audio-video.matriska.php //
|
||||||
|
@ -72,7 +72,7 @@ define('EBML_ID_FILEREFERRAL', 0x0675); // [46][75] --
|
||||||
define('EBML_ID_FILEDESCRIPTION', 0x067E); // [46][7E] -- A human-friendly name for the attached file.
|
define('EBML_ID_FILEDESCRIPTION', 0x067E); // [46][7E] -- A human-friendly name for the attached file.
|
||||||
define('EBML_ID_FILEUID', 0x06AE); // [46][AE] -- Unique ID representing the file, as random as possible.
|
define('EBML_ID_FILEUID', 0x06AE); // [46][AE] -- Unique ID representing the file, as random as possible.
|
||||||
define('EBML_ID_CONTENTENCALGO', 0x07E1); // [47][E1] -- The encryption algorithm used. The value '0' means that the contents have not been encrypted but only signed. Predefined values:
|
define('EBML_ID_CONTENTENCALGO', 0x07E1); // [47][E1] -- The encryption algorithm used. The value '0' means that the contents have not been encrypted but only signed. Predefined values:
|
||||||
define('EBML_ID_CONTENTENCKEYID', 0x07E2); // [47][E2] -- For public key algorithms this is the ID of the public key the the data was encrypted with.
|
define('EBML_ID_CONTENTENCKEYID', 0x07E2); // [47][E2] -- For public key algorithms this is the ID of the public key the data was encrypted with.
|
||||||
define('EBML_ID_CONTENTSIGNATURE', 0x07E3); // [47][E3] -- A cryptographic signature of the contents.
|
define('EBML_ID_CONTENTSIGNATURE', 0x07E3); // [47][E3] -- A cryptographic signature of the contents.
|
||||||
define('EBML_ID_CONTENTSIGKEYID', 0x07E4); // [47][E4] -- This is the ID of the private key the data was signed with.
|
define('EBML_ID_CONTENTSIGKEYID', 0x07E4); // [47][E4] -- This is the ID of the private key the data was signed with.
|
||||||
define('EBML_ID_CONTENTSIGALGO', 0x07E5); // [47][E5] -- The algorithm used for the signature. A value of '0' means that the contents have not been signed but only encrypted. Predefined values:
|
define('EBML_ID_CONTENTSIGALGO', 0x07E5); // [47][E5] -- The algorithm used for the signature. A value of '0' means that the contents have not been signed but only encrypted. Predefined values:
|
||||||
|
@ -215,17 +215,33 @@ define('EBML_ID_CLUSTERREFERENCEVIRTUAL', 0x7D); // [FD] --
|
||||||
*/
|
*/
|
||||||
class getid3_matroska extends getid3_handler
|
class getid3_matroska extends getid3_handler
|
||||||
{
|
{
|
||||||
// public options
|
/**
|
||||||
public static $hide_clusters = true; // if true, do not return information about CLUSTER chunks, since there's a lot of them and they're not usually useful [default: TRUE]
|
* If true, do not return information about CLUSTER chunks, since there's a lot of them
|
||||||
public static $parse_whole_file = false; // true to parse the whole file, not only header [default: FALSE]
|
* and they're not usually useful [default: TRUE].
|
||||||
|
*
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
public static $hide_clusters = true;
|
||||||
|
|
||||||
// private parser settings/placeholders
|
/**
|
||||||
|
* True to parse the whole file, not only header [default: FALSE].
|
||||||
|
*
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
public static $parse_whole_file = false;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Private parser settings/placeholders.
|
||||||
|
*/
|
||||||
private $EBMLbuffer = '';
|
private $EBMLbuffer = '';
|
||||||
private $EBMLbuffer_offset = 0;
|
private $EBMLbuffer_offset = 0;
|
||||||
private $EBMLbuffer_length = 0;
|
private $EBMLbuffer_length = 0;
|
||||||
private $current_offset = 0;
|
private $current_offset = 0;
|
||||||
private $unuseful_elements = array(EBML_ID_CRC32, EBML_ID_VOID);
|
private $unuseful_elements = array(EBML_ID_CRC32, EBML_ID_VOID);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
public function Analyze()
|
public function Analyze()
|
||||||
{
|
{
|
||||||
$info = &$this->getid3->info;
|
$info = &$this->getid3->info;
|
||||||
|
@ -366,8 +382,8 @@ class getid3_matroska extends getid3_handler
|
||||||
if (!empty($getid3_temp->info[$header_data_key])) {
|
if (!empty($getid3_temp->info[$header_data_key])) {
|
||||||
$info['matroska']['track_codec_parsed'][$trackarray['TrackNumber']] = $getid3_temp->info[$header_data_key];
|
$info['matroska']['track_codec_parsed'][$trackarray['TrackNumber']] = $getid3_temp->info[$header_data_key];
|
||||||
if (isset($getid3_temp->info['audio']) && is_array($getid3_temp->info['audio'])) {
|
if (isset($getid3_temp->info['audio']) && is_array($getid3_temp->info['audio'])) {
|
||||||
foreach ($getid3_temp->info['audio'] as $key => $value) {
|
foreach ($getid3_temp->info['audio'] as $sub_key => $value) {
|
||||||
$track_info[$key] = $value;
|
$track_info[$sub_key] = $value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -421,8 +437,8 @@ class getid3_matroska extends getid3_handler
|
||||||
if (!empty($getid3_temp->info['ogg'])) {
|
if (!empty($getid3_temp->info['ogg'])) {
|
||||||
$info['matroska']['track_codec_parsed'][$trackarray['TrackNumber']] = $getid3_temp->info['ogg'];
|
$info['matroska']['track_codec_parsed'][$trackarray['TrackNumber']] = $getid3_temp->info['ogg'];
|
||||||
if (isset($getid3_temp->info['audio']) && is_array($getid3_temp->info['audio'])) {
|
if (isset($getid3_temp->info['audio']) && is_array($getid3_temp->info['audio'])) {
|
||||||
foreach ($getid3_temp->info['audio'] as $key => $value) {
|
foreach ($getid3_temp->info['audio'] as $sub_key => $value) {
|
||||||
$track_info[$key] = $value;
|
$track_info[$sub_key] = $value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -449,9 +465,9 @@ class getid3_matroska extends getid3_handler
|
||||||
getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.riff.php', __FILE__, true);
|
getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.riff.php', __FILE__, true);
|
||||||
|
|
||||||
$parsed = getid3_riff::parseWAVEFORMATex($trackarray['CodecPrivate']);
|
$parsed = getid3_riff::parseWAVEFORMATex($trackarray['CodecPrivate']);
|
||||||
foreach ($parsed as $key => $value) {
|
foreach ($parsed as $sub_key => $value) {
|
||||||
if ($key != 'raw') {
|
if ($sub_key != 'raw') {
|
||||||
$track_info[$key] = $value;
|
$track_info[$sub_key] = $value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$info['matroska']['track_codec_parsed'][$trackarray['TrackNumber']] = $parsed;
|
$info['matroska']['track_codec_parsed'][$trackarray['TrackNumber']] = $parsed;
|
||||||
|
@ -496,6 +512,9 @@ class getid3_matroska extends getid3_handler
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $info
|
||||||
|
*/
|
||||||
private function parseEBML(&$info) {
|
private function parseEBML(&$info) {
|
||||||
// http://www.matroska.org/technical/specs/index.html#EBMLBasics
|
// http://www.matroska.org/technical/specs/index.html#EBMLBasics
|
||||||
$this->current_offset = $info['avdataoffset'];
|
$this->current_offset = $info['avdataoffset'];
|
||||||
|
@ -1228,6 +1247,11 @@ class getid3_matroska extends getid3_handler
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $min_data
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
private function EnsureBufferHasEnoughData($min_data=1024) {
|
private function EnsureBufferHasEnoughData($min_data=1024) {
|
||||||
if (($this->current_offset - $this->EBMLbuffer_offset) >= ($this->EBMLbuffer_length - $min_data)) {
|
if (($this->current_offset - $this->EBMLbuffer_offset) >= ($this->EBMLbuffer_length - $min_data)) {
|
||||||
$read_bytes = max($min_data, $this->getid3->fread_buffer_size());
|
$read_bytes = max($min_data, $this->getid3->fread_buffer_size());
|
||||||
|
@ -1249,6 +1273,9 @@ class getid3_matroska extends getid3_handler
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return int|float|false
|
||||||
|
*/
|
||||||
private function readEBMLint() {
|
private function readEBMLint() {
|
||||||
$actual_offset = $this->current_offset - $this->EBMLbuffer_offset;
|
$actual_offset = $this->current_offset - $this->EBMLbuffer_offset;
|
||||||
|
|
||||||
|
@ -1281,6 +1308,12 @@ class getid3_matroska extends getid3_handler
|
||||||
return $int_value;
|
return $int_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $length
|
||||||
|
* @param bool $check_buffer
|
||||||
|
*
|
||||||
|
* @return string|false
|
||||||
|
*/
|
||||||
private function readEBMLelementData($length, $check_buffer=false) {
|
private function readEBMLelementData($length, $check_buffer=false) {
|
||||||
if ($check_buffer && !$this->EnsureBufferHasEnoughData($length)) {
|
if ($check_buffer && !$this->EnsureBufferHasEnoughData($length)) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -1290,6 +1323,13 @@ class getid3_matroska extends getid3_handler
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $element
|
||||||
|
* @param int $parent_end
|
||||||
|
* @param array|bool $get_data
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
private function getEBMLelement(&$element, $parent_end, $get_data=false) {
|
private function getEBMLelement(&$element, $parent_end, $get_data=false) {
|
||||||
if ($this->current_offset >= $parent_end) {
|
if ($this->current_offset >= $parent_end) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -1326,6 +1366,11 @@ class getid3_matroska extends getid3_handler
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $type
|
||||||
|
* @param int $line
|
||||||
|
* @param array $element
|
||||||
|
*/
|
||||||
private function unhandledElement($type, $line, $element) {
|
private function unhandledElement($type, $line, $element) {
|
||||||
// warn only about unknown and missed elements, not about unuseful
|
// warn only about unknown and missed elements, not about unuseful
|
||||||
if (!in_array($element['id'], $this->unuseful_elements)) {
|
if (!in_array($element['id'], $this->unuseful_elements)) {
|
||||||
|
@ -1338,6 +1383,11 @@ class getid3_matroska extends getid3_handler
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $SimpleTagArray
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
private function ExtractCommentsSimpleTag($SimpleTagArray) {
|
private function ExtractCommentsSimpleTag($SimpleTagArray) {
|
||||||
if (!empty($SimpleTagArray['SimpleTag'])) {
|
if (!empty($SimpleTagArray['SimpleTag'])) {
|
||||||
foreach ($SimpleTagArray['SimpleTag'] as $SimpleTagKey => $SimpleTagData) {
|
foreach ($SimpleTagArray['SimpleTag'] as $SimpleTagKey => $SimpleTagData) {
|
||||||
|
@ -1353,6 +1403,11 @@ class getid3_matroska extends getid3_handler
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $parent_end
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
private function HandleEMBLSimpleTag($parent_end) {
|
private function HandleEMBLSimpleTag($parent_end) {
|
||||||
$simpletag_entry = array();
|
$simpletag_entry = array();
|
||||||
|
|
||||||
|
@ -1383,6 +1438,13 @@ class getid3_matroska extends getid3_handler
|
||||||
return $simpletag_entry;
|
return $simpletag_entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $element
|
||||||
|
* @param int $block_type
|
||||||
|
* @param array $info
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
private function HandleEMBLClusterBlock($element, $block_type, &$info) {
|
private function HandleEMBLClusterBlock($element, $block_type, &$info) {
|
||||||
// http://www.matroska.org/technical/specs/index.html#block_structure
|
// http://www.matroska.org/technical/specs/index.html#block_structure
|
||||||
// http://www.matroska.org/technical/specs/index.html#simpleblock_structure
|
// http://www.matroska.org/technical/specs/index.html#simpleblock_structure
|
||||||
|
@ -1446,6 +1508,11 @@ class getid3_matroska extends getid3_handler
|
||||||
return $block_data;
|
return $block_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $EBMLstring
|
||||||
|
*
|
||||||
|
* @return int|float|false
|
||||||
|
*/
|
||||||
private static function EBML2Int($EBMLstring) {
|
private static function EBML2Int($EBMLstring) {
|
||||||
// http://matroska.org/specs/
|
// http://matroska.org/specs/
|
||||||
|
|
||||||
|
@ -1488,12 +1555,22 @@ class getid3_matroska extends getid3_handler
|
||||||
return getid3_lib::BigEndian2Int($EBMLstring);
|
return getid3_lib::BigEndian2Int($EBMLstring);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $EBMLdatestamp
|
||||||
|
*
|
||||||
|
* @return float
|
||||||
|
*/
|
||||||
private static function EBMLdate2unix($EBMLdatestamp) {
|
private static function EBMLdate2unix($EBMLdatestamp) {
|
||||||
// Date - signed 8 octets integer in nanoseconds with 0 indicating the precise beginning of the millennium (at 2001-01-01T00:00:00,000000000 UTC)
|
// Date - signed 8 octets integer in nanoseconds with 0 indicating the precise beginning of the millennium (at 2001-01-01T00:00:00,000000000 UTC)
|
||||||
// 978307200 == mktime(0, 0, 0, 1, 1, 2001) == January 1, 2001 12:00:00am UTC
|
// 978307200 == mktime(0, 0, 0, 1, 1, 2001) == January 1, 2001 12:00:00am UTC
|
||||||
return round(($EBMLdatestamp / 1000000000) + 978307200);
|
return round(($EBMLdatestamp / 1000000000) + 978307200);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $target_type
|
||||||
|
*
|
||||||
|
* @return string|int
|
||||||
|
*/
|
||||||
public static function TargetTypeValue($target_type) {
|
public static function TargetTypeValue($target_type) {
|
||||||
// http://www.matroska.org/technical/specs/tagging/index.html
|
// http://www.matroska.org/technical/specs/tagging/index.html
|
||||||
static $TargetTypeValue = array();
|
static $TargetTypeValue = array();
|
||||||
|
@ -1509,6 +1586,11 @@ class getid3_matroska extends getid3_handler
|
||||||
return (isset($TargetTypeValue[$target_type]) ? $TargetTypeValue[$target_type] : $target_type);
|
return (isset($TargetTypeValue[$target_type]) ? $TargetTypeValue[$target_type] : $target_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $lacingtype
|
||||||
|
*
|
||||||
|
* @return string|int
|
||||||
|
*/
|
||||||
public static function BlockLacingType($lacingtype) {
|
public static function BlockLacingType($lacingtype) {
|
||||||
// http://matroska.org/technical/specs/index.html#block_structure
|
// http://matroska.org/technical/specs/index.html#block_structure
|
||||||
static $BlockLacingType = array();
|
static $BlockLacingType = array();
|
||||||
|
@ -1521,6 +1603,11 @@ class getid3_matroska extends getid3_handler
|
||||||
return (isset($BlockLacingType[$lacingtype]) ? $BlockLacingType[$lacingtype] : $lacingtype);
|
return (isset($BlockLacingType[$lacingtype]) ? $BlockLacingType[$lacingtype] : $lacingtype);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $codecid
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public static function CodecIDtoCommonName($codecid) {
|
public static function CodecIDtoCommonName($codecid) {
|
||||||
// http://www.matroska.org/technical/specs/codecid/index.html
|
// http://www.matroska.org/technical/specs/codecid/index.html
|
||||||
static $CodecIDlist = array();
|
static $CodecIDlist = array();
|
||||||
|
@ -1557,6 +1644,11 @@ class getid3_matroska extends getid3_handler
|
||||||
return (isset($CodecIDlist[$codecid]) ? $CodecIDlist[$codecid] : $codecid);
|
return (isset($CodecIDlist[$codecid]) ? $CodecIDlist[$codecid] : $codecid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $value
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
private static function EBMLidName($value) {
|
private static function EBMLidName($value) {
|
||||||
static $EBMLidList = array();
|
static $EBMLidList = array();
|
||||||
if (empty($EBMLidList)) {
|
if (empty($EBMLidList)) {
|
||||||
|
@ -1755,6 +1847,11 @@ class getid3_matroska extends getid3_handler
|
||||||
return (isset($EBMLidList[$value]) ? $EBMLidList[$value] : dechex($value));
|
return (isset($EBMLidList[$value]) ? $EBMLidList[$value] : dechex($value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $value
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public static function displayUnit($value) {
|
public static function displayUnit($value) {
|
||||||
// http://www.matroska.org/technical/specs/index.html#DisplayUnit
|
// http://www.matroska.org/technical/specs/index.html#DisplayUnit
|
||||||
static $units = array(
|
static $units = array(
|
||||||
|
@ -1766,8 +1863,14 @@ class getid3_matroska extends getid3_handler
|
||||||
return (isset($units[$value]) ? $units[$value] : 'unknown');
|
return (isset($units[$value]) ? $units[$value] : 'unknown');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $streams
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
private static function getDefaultStreamInfo($streams)
|
private static function getDefaultStreamInfo($streams)
|
||||||
{
|
{
|
||||||
|
$stream = array();
|
||||||
foreach (array_reverse($streams) as $stream) {
|
foreach (array_reverse($streams) as $stream) {
|
||||||
if ($stream['default']) {
|
if ($stream['default']) {
|
||||||
break;
|
break;
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,11 +1,11 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////
|
||||||
/// getID3() by James Heinrich <info@getid3.org> //
|
/// getID3() by James Heinrich <info@getid3.org> //
|
||||||
// available at http://getid3.sourceforge.net //
|
// available at https://github.com/JamesHeinrich/getID3 //
|
||||||
// or http://www.getid3.org //
|
// or https://www.getid3.org //
|
||||||
// also https://github.com/JamesHeinrich/getID3 //
|
// or http://getid3.sourceforge.net //
|
||||||
/////////////////////////////////////////////////////////////////
|
// see readme.txt for more details //
|
||||||
// See readme.txt for more details //
|
|
||||||
/////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////
|
||||||
// //
|
// //
|
||||||
// module.audio-video.riff.php //
|
// module.audio-video.riff.php //
|
||||||
|
@ -27,10 +27,15 @@ getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.mp3.php', __FILE_
|
||||||
getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.ac3.php', __FILE__, true);
|
getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.ac3.php', __FILE__, true);
|
||||||
getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.dts.php', __FILE__, true);
|
getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.dts.php', __FILE__, true);
|
||||||
|
|
||||||
class getid3_riff extends getid3_handler {
|
class getid3_riff extends getid3_handler
|
||||||
|
{
|
||||||
protected $container = 'riff'; // default
|
protected $container = 'riff'; // default
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*
|
||||||
|
* @throws getid3_exception
|
||||||
|
*/
|
||||||
public function Analyze() {
|
public function Analyze() {
|
||||||
$info = &$this->getid3->info;
|
$info = &$this->getid3->info;
|
||||||
|
|
||||||
|
@ -46,6 +51,7 @@ class getid3_riff extends getid3_handler {
|
||||||
$thisfile_audio_dataformat = &$thisfile_audio['dataformat'];
|
$thisfile_audio_dataformat = &$thisfile_audio['dataformat'];
|
||||||
$thisfile_riff_audio = &$thisfile_riff['audio'];
|
$thisfile_riff_audio = &$thisfile_riff['audio'];
|
||||||
$thisfile_riff_video = &$thisfile_riff['video'];
|
$thisfile_riff_video = &$thisfile_riff['video'];
|
||||||
|
$thisfile_riff_WAVE = array();
|
||||||
|
|
||||||
$Original['avdataoffset'] = $info['avdataoffset'];
|
$Original['avdataoffset'] = $info['avdataoffset'];
|
||||||
$Original['avdataend'] = $info['avdataend'];
|
$Original['avdataend'] = $info['avdataend'];
|
||||||
|
@ -357,6 +363,7 @@ class getid3_riff extends getid3_handler {
|
||||||
}
|
}
|
||||||
$thisfile_riff_WAVE_cart_0['url'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 748, 1024));
|
$thisfile_riff_WAVE_cart_0['url'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 748, 1024));
|
||||||
$thisfile_riff_WAVE_cart_0['tag_text'] = explode("\r\n", trim(substr($thisfile_riff_WAVE_cart_0['data'], 1772)));
|
$thisfile_riff_WAVE_cart_0['tag_text'] = explode("\r\n", trim(substr($thisfile_riff_WAVE_cart_0['data'], 1772)));
|
||||||
|
$thisfile_riff['comments']['tag_text'][] = substr($thisfile_riff_WAVE_cart_0['data'], 1772);
|
||||||
|
|
||||||
$thisfile_riff['comments']['artist'][] = $thisfile_riff_WAVE_cart_0['artist'];
|
$thisfile_riff['comments']['artist'][] = $thisfile_riff_WAVE_cart_0['artist'];
|
||||||
$thisfile_riff['comments']['title'][] = $thisfile_riff_WAVE_cart_0['title'];
|
$thisfile_riff['comments']['title'][] = $thisfile_riff_WAVE_cart_0['title'];
|
||||||
|
@ -405,7 +412,6 @@ class getid3_riff extends getid3_handler {
|
||||||
'tracktitle'=>'title',
|
'tracktitle'=>'title',
|
||||||
'category' =>'genre',
|
'category' =>'genre',
|
||||||
'cdtitle' =>'album',
|
'cdtitle' =>'album',
|
||||||
'tracktitle'=>'title',
|
|
||||||
);
|
);
|
||||||
foreach ($tagmapping as $fromkey => $tokey) {
|
foreach ($tagmapping as $fromkey => $tokey) {
|
||||||
if (isset($thisfile_riff_WAVE_SNDM_0['parsed'][$fromkey])) {
|
if (isset($thisfile_riff_WAVE_SNDM_0['parsed'][$fromkey])) {
|
||||||
|
@ -613,6 +619,8 @@ class getid3_riff extends getid3_handler {
|
||||||
$thisfile_video['bitrate_mode'] = 'vbr'; // maybe not, but probably
|
$thisfile_video['bitrate_mode'] = 'vbr'; // maybe not, but probably
|
||||||
$thisfile_video['dataformat'] = 'avi';
|
$thisfile_video['dataformat'] = 'avi';
|
||||||
|
|
||||||
|
$thisfile_riff_video_current = array();
|
||||||
|
|
||||||
if (isset($thisfile_riff[$RIFFsubtype]['movi']['offset'])) {
|
if (isset($thisfile_riff[$RIFFsubtype]['movi']['offset'])) {
|
||||||
$info['avdataoffset'] = $thisfile_riff[$RIFFsubtype]['movi']['offset'] + 8;
|
$info['avdataoffset'] = $thisfile_riff[$RIFFsubtype]['movi']['offset'] + 8;
|
||||||
if (isset($thisfile_riff['AVIX'])) {
|
if (isset($thisfile_riff['AVIX'])) {
|
||||||
|
@ -695,12 +703,13 @@ class getid3_riff extends getid3_handler {
|
||||||
'capturedfile' => 0x00010000,
|
'capturedfile' => 0x00010000,
|
||||||
'copyrighted' => 0x00020010,
|
'copyrighted' => 0x00020010,
|
||||||
);
|
);
|
||||||
foreach ($flags as $flag => $value) {
|
foreach ($flags as $flag => $value) {
|
||||||
$thisfile_riff_raw_avih['flags'][$flag] = (bool) ($thisfile_riff_raw_avih['dwFlags'] & $value);
|
$thisfile_riff_raw_avih['flags'][$flag] = (bool) ($thisfile_riff_raw_avih['dwFlags'] & $value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// shortcut
|
// shortcut
|
||||||
$thisfile_riff_video[$streamindex] = array();
|
$thisfile_riff_video[$streamindex] = array();
|
||||||
|
/** @var array $thisfile_riff_video_current */
|
||||||
$thisfile_riff_video_current = &$thisfile_riff_video[$streamindex];
|
$thisfile_riff_video_current = &$thisfile_riff_video[$streamindex];
|
||||||
|
|
||||||
if ($thisfile_riff_raw_avih['dwWidth'] > 0) {
|
if ($thisfile_riff_raw_avih['dwWidth'] > 0) {
|
||||||
|
@ -867,7 +876,7 @@ class getid3_riff extends getid3_handler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc'])) {
|
if (isset($thisfile_riff_raw_strf_strhfccType_streamindex) && isset($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc'])) {
|
||||||
|
|
||||||
$thisfile_video['fourcc'] = $thisfile_riff_raw_strf_strhfccType_streamindex['fourcc'];
|
$thisfile_video['fourcc'] = $thisfile_riff_raw_strf_strhfccType_streamindex['fourcc'];
|
||||||
if (self::fourccLookup($thisfile_video['fourcc'])) {
|
if (self::fourccLookup($thisfile_video['fourcc'])) {
|
||||||
|
@ -914,7 +923,7 @@ class getid3_riff extends getid3_handler {
|
||||||
// http://en.wikipedia.org/wiki/CD-DA
|
// http://en.wikipedia.org/wiki/CD-DA
|
||||||
case 'CDDA':
|
case 'CDDA':
|
||||||
$info['fileformat'] = 'cda';
|
$info['fileformat'] = 'cda';
|
||||||
unset($info['mime_type']);
|
unset($info['mime_type']);
|
||||||
|
|
||||||
$thisfile_audio_dataformat = 'cda';
|
$thisfile_audio_dataformat = 'cda';
|
||||||
|
|
||||||
|
@ -934,7 +943,7 @@ class getid3_riff extends getid3_handler {
|
||||||
|
|
||||||
$thisfile_riff_CDDA_fmt_0['start_offset_seconds'] = (float) $thisfile_riff_CDDA_fmt_0['start_offset_frame'] / 75;
|
$thisfile_riff_CDDA_fmt_0['start_offset_seconds'] = (float) $thisfile_riff_CDDA_fmt_0['start_offset_frame'] / 75;
|
||||||
$thisfile_riff_CDDA_fmt_0['playtime_seconds'] = (float) $thisfile_riff_CDDA_fmt_0['playtime_frames'] / 75;
|
$thisfile_riff_CDDA_fmt_0['playtime_seconds'] = (float) $thisfile_riff_CDDA_fmt_0['playtime_frames'] / 75;
|
||||||
$info['comments']['track'] = $thisfile_riff_CDDA_fmt_0['track_num'];
|
$info['comments']['track_number'] = $thisfile_riff_CDDA_fmt_0['track_num'];
|
||||||
$info['playtime_seconds'] = $thisfile_riff_CDDA_fmt_0['playtime_seconds'];
|
$info['playtime_seconds'] = $thisfile_riff_CDDA_fmt_0['playtime_seconds'];
|
||||||
|
|
||||||
// hardcoded data for CD-audio
|
// hardcoded data for CD-audio
|
||||||
|
@ -947,7 +956,7 @@ class getid3_riff extends getid3_handler {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// http://en.wikipedia.org/wiki/AIFF
|
// http://en.wikipedia.org/wiki/AIFF
|
||||||
case 'AIFF':
|
case 'AIFF':
|
||||||
case 'AIFC':
|
case 'AIFC':
|
||||||
$info['fileformat'] = 'aiff';
|
$info['fileformat'] = 'aiff';
|
||||||
|
@ -1057,7 +1066,7 @@ class getid3_riff extends getid3_handler {
|
||||||
if (isset($thisfile_riff[$RIFFsubtype]['ID3 '])) {
|
if (isset($thisfile_riff[$RIFFsubtype]['ID3 '])) {
|
||||||
getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.tag.id3v2.php', __FILE__, true);
|
getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.tag.id3v2.php', __FILE__, true);
|
||||||
$getid3_temp = new getID3();
|
$getid3_temp = new getID3();
|
||||||
$getid3_temp->openfile($this->getid3->filename);
|
$getid3_temp->openfile($this->getid3->filename, null, $this->getid3->fp);
|
||||||
$getid3_id3v2 = new getid3_id3v2($getid3_temp);
|
$getid3_id3v2 = new getid3_id3v2($getid3_temp);
|
||||||
$getid3_id3v2->StartingOffset = $thisfile_riff[$RIFFsubtype]['ID3 '][0]['offset'] + 8;
|
$getid3_id3v2->StartingOffset = $thisfile_riff[$RIFFsubtype]['ID3 '][0]['offset'] + 8;
|
||||||
if ($thisfile_riff[$RIFFsubtype]['ID3 '][0]['valid'] = $getid3_id3v2->Analyze()) {
|
if ($thisfile_riff[$RIFFsubtype]['ID3 '][0]['valid'] = $getid3_id3v2->Analyze()) {
|
||||||
|
@ -1077,6 +1086,7 @@ class getid3_riff extends getid3_handler {
|
||||||
$thisfile_audio_dataformat = '8svx';
|
$thisfile_audio_dataformat = '8svx';
|
||||||
$thisfile_audio['bits_per_sample'] = 8;
|
$thisfile_audio['bits_per_sample'] = 8;
|
||||||
$thisfile_audio['channels'] = 1; // overridden below, if need be
|
$thisfile_audio['channels'] = 1; // overridden below, if need be
|
||||||
|
$ActualBitsPerSample = 0;
|
||||||
|
|
||||||
if (isset($thisfile_riff[$RIFFsubtype]['BODY'][0]['offset'])) {
|
if (isset($thisfile_riff[$RIFFsubtype]['BODY'][0]['offset'])) {
|
||||||
$info['avdataoffset'] = $thisfile_riff[$RIFFsubtype]['BODY'][0]['offset'] + 8;
|
$info['avdataoffset'] = $thisfile_riff[$RIFFsubtype]['BODY'][0]['offset'] + 8;
|
||||||
|
@ -1114,7 +1124,7 @@ class getid3_riff extends getid3_handler {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
$this->warning('Unexpected sCompression value in 8SVX.VHDR chunk - expecting 0 or 1, found "'.sCompression.'"');
|
$this->warning('Unexpected sCompression value in 8SVX.VHDR chunk - expecting 0 or 1, found "'.$thisfile_riff_RIFFsubtype_VHDR_0['sCompression'].'"');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1159,7 +1169,7 @@ class getid3_riff extends getid3_handler {
|
||||||
getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.mpeg.php', __FILE__, true);
|
getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.mpeg.php', __FILE__, true);
|
||||||
|
|
||||||
$getid3_temp = new getID3();
|
$getid3_temp = new getID3();
|
||||||
$getid3_temp->openfile($this->getid3->filename);
|
$getid3_temp->openfile($this->getid3->filename, null, $this->getid3->fp);
|
||||||
$getid3_mpeg = new getid3_mpeg($getid3_temp);
|
$getid3_mpeg = new getid3_mpeg($getid3_temp);
|
||||||
$getid3_mpeg->Analyze();
|
$getid3_mpeg->Analyze();
|
||||||
if (empty($getid3_temp->info['error'])) {
|
if (empty($getid3_temp->info['error'])) {
|
||||||
|
@ -1245,7 +1255,7 @@ class getid3_riff extends getid3_handler {
|
||||||
getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.tag.id3v2.php', __FILE__, true);
|
getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.tag.id3v2.php', __FILE__, true);
|
||||||
|
|
||||||
$getid3_temp = new getID3();
|
$getid3_temp = new getID3();
|
||||||
$getid3_temp->openfile($this->getid3->filename);
|
$getid3_temp->openfile($this->getid3->filename, null, $this->getid3->fp);
|
||||||
$getid3_id3v2 = new getid3_id3v2($getid3_temp);
|
$getid3_id3v2 = new getid3_id3v2($getid3_temp);
|
||||||
$getid3_id3v2->StartingOffset = $thisfile_riff[$RIFFsubtype]['id3 '][0]['offset'] + 8;
|
$getid3_id3v2->StartingOffset = $thisfile_riff[$RIFFsubtype]['id3 '][0]['offset'] + 8;
|
||||||
if ($thisfile_riff[$RIFFsubtype]['id3 '][0]['valid'] = $getid3_id3v2->Analyze()) {
|
if ($thisfile_riff[$RIFFsubtype]['id3 '][0]['valid'] = $getid3_id3v2->Analyze()) {
|
||||||
|
@ -1372,6 +1382,15 @@ class getid3_riff extends getid3_handler {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $startoffset
|
||||||
|
* @param int $maxoffset
|
||||||
|
*
|
||||||
|
* @return array|false
|
||||||
|
*
|
||||||
|
* @throws Exception
|
||||||
|
* @throws getid3_exception
|
||||||
|
*/
|
||||||
public function ParseRIFFAMV($startoffset, $maxoffset) {
|
public function ParseRIFFAMV($startoffset, $maxoffset) {
|
||||||
// AMV files are RIFF-AVI files with parts of the spec deliberately broken, such as chunk size fields hardcoded to zero (because players known in hardware that these fields are always a certain size
|
// AMV files are RIFF-AVI files with parts of the spec deliberately broken, such as chunk size fields hardcoded to zero (because players known in hardware that these fields are always a certain size
|
||||||
|
|
||||||
|
@ -1480,7 +1499,13 @@ class getid3_riff extends getid3_handler {
|
||||||
return $RIFFchunk;
|
return $RIFFchunk;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $startoffset
|
||||||
|
* @param int $maxoffset
|
||||||
|
*
|
||||||
|
* @return array|false
|
||||||
|
* @throws getid3_exception
|
||||||
|
*/
|
||||||
public function ParseRIFF($startoffset, $maxoffset) {
|
public function ParseRIFF($startoffset, $maxoffset) {
|
||||||
$info = &$this->getid3->info;
|
$info = &$this->getid3->info;
|
||||||
|
|
||||||
|
@ -1529,7 +1554,7 @@ class getid3_riff extends getid3_handler {
|
||||||
// MP3
|
// MP3
|
||||||
if (getid3_mp3::MPEGaudioHeaderBytesValid($FirstFourBytes)) {
|
if (getid3_mp3::MPEGaudioHeaderBytesValid($FirstFourBytes)) {
|
||||||
$getid3_temp = new getID3();
|
$getid3_temp = new getID3();
|
||||||
$getid3_temp->openfile($this->getid3->filename);
|
$getid3_temp->openfile($this->getid3->filename, null, $this->getid3->fp);
|
||||||
$getid3_temp->info['avdataoffset'] = $this->ftell() - 4;
|
$getid3_temp->info['avdataoffset'] = $this->ftell() - 4;
|
||||||
$getid3_temp->info['avdataend'] = $this->ftell() + $AudioChunkSize;
|
$getid3_temp->info['avdataend'] = $this->ftell() + $AudioChunkSize;
|
||||||
$getid3_mp3 = new getid3_mp3($getid3_temp, __CLASS__);
|
$getid3_mp3 = new getid3_mp3($getid3_temp, __CLASS__);
|
||||||
|
@ -1551,7 +1576,7 @@ class getid3_riff extends getid3_handler {
|
||||||
|
|
||||||
// AC3
|
// AC3
|
||||||
$getid3_temp = new getID3();
|
$getid3_temp = new getID3();
|
||||||
$getid3_temp->openfile($this->getid3->filename);
|
$getid3_temp->openfile($this->getid3->filename, null, $this->getid3->fp);
|
||||||
$getid3_temp->info['avdataoffset'] = $this->ftell() - 4;
|
$getid3_temp->info['avdataoffset'] = $this->ftell() - 4;
|
||||||
$getid3_temp->info['avdataend'] = $this->ftell() + $AudioChunkSize;
|
$getid3_temp->info['avdataend'] = $this->ftell() + $AudioChunkSize;
|
||||||
$getid3_ac3 = new getid3_ac3($getid3_temp);
|
$getid3_ac3 = new getid3_ac3($getid3_temp);
|
||||||
|
@ -1612,7 +1637,7 @@ class getid3_riff extends getid3_handler {
|
||||||
// Probably is MP3 data
|
// Probably is MP3 data
|
||||||
if (getid3_mp3::MPEGaudioHeaderBytesValid(substr($testData, 0, 4))) {
|
if (getid3_mp3::MPEGaudioHeaderBytesValid(substr($testData, 0, 4))) {
|
||||||
$getid3_temp = new getID3();
|
$getid3_temp = new getID3();
|
||||||
$getid3_temp->openfile($this->getid3->filename);
|
$getid3_temp->openfile($this->getid3->filename, null, $this->getid3->fp);
|
||||||
$getid3_temp->info['avdataoffset'] = $info['avdataoffset'];
|
$getid3_temp->info['avdataoffset'] = $info['avdataoffset'];
|
||||||
$getid3_temp->info['avdataend'] = $info['avdataend'];
|
$getid3_temp->info['avdataend'] = $info['avdataend'];
|
||||||
$getid3_mp3 = new getid3_mp3($getid3_temp, __CLASS__);
|
$getid3_mp3 = new getid3_mp3($getid3_temp, __CLASS__);
|
||||||
|
@ -1629,7 +1654,7 @@ class getid3_riff extends getid3_handler {
|
||||||
// This is probably AC-3 data
|
// This is probably AC-3 data
|
||||||
$getid3_temp = new getID3();
|
$getid3_temp = new getID3();
|
||||||
if ($isRegularAC3) {
|
if ($isRegularAC3) {
|
||||||
$getid3_temp->openfile($this->getid3->filename);
|
$getid3_temp->openfile($this->getid3->filename, null, $this->getid3->fp);
|
||||||
$getid3_temp->info['avdataoffset'] = $info['avdataoffset'];
|
$getid3_temp->info['avdataoffset'] = $info['avdataoffset'];
|
||||||
$getid3_temp->info['avdataend'] = $info['avdataend'];
|
$getid3_temp->info['avdataend'] = $info['avdataend'];
|
||||||
}
|
}
|
||||||
|
@ -1663,7 +1688,7 @@ class getid3_riff extends getid3_handler {
|
||||||
|
|
||||||
// This is probably DTS data
|
// This is probably DTS data
|
||||||
$getid3_temp = new getID3();
|
$getid3_temp = new getID3();
|
||||||
$getid3_temp->openfile($this->getid3->filename);
|
$getid3_temp->openfile($this->getid3->filename, null, $this->getid3->fp);
|
||||||
$getid3_temp->info['avdataoffset'] = $info['avdataoffset'];
|
$getid3_temp->info['avdataoffset'] = $info['avdataoffset'];
|
||||||
$getid3_dts = new getid3_dts($getid3_temp);
|
$getid3_dts = new getid3_dts($getid3_temp);
|
||||||
$getid3_dts->Analyze();
|
$getid3_dts->Analyze();
|
||||||
|
@ -1731,8 +1756,77 @@ class getid3_riff extends getid3_handler {
|
||||||
// $info['divxtag']['comments'] = self::ParseDIVXTAG($this->fread($chunksize));
|
// $info['divxtag']['comments'] = self::ParseDIVXTAG($this->fread($chunksize));
|
||||||
// break;
|
// break;
|
||||||
|
|
||||||
|
case 'scot':
|
||||||
|
// https://cmsdk.com/node-js/adding-scot-chunk-to-wav-file.html
|
||||||
|
$RIFFchunk[$chunkname][$thisindex]['data'] = $this->fread($chunksize);
|
||||||
|
$RIFFchunk[$chunkname][$thisindex]['parsed']['alter'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 0, 1);
|
||||||
|
$RIFFchunk[$chunkname][$thisindex]['parsed']['attrib'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 1, 1);
|
||||||
|
$RIFFchunk[$chunkname][$thisindex]['parsed']['artnum'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 2, 2));
|
||||||
|
$RIFFchunk[$chunkname][$thisindex]['parsed']['title'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 4, 43); // "name" in other documentation
|
||||||
|
$RIFFchunk[$chunkname][$thisindex]['parsed']['copy'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 47, 4);
|
||||||
|
$RIFFchunk[$chunkname][$thisindex]['parsed']['padd'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 51, 1);
|
||||||
|
$RIFFchunk[$chunkname][$thisindex]['parsed']['asclen'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 52, 5);
|
||||||
|
$RIFFchunk[$chunkname][$thisindex]['parsed']['startseconds'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 57, 2));
|
||||||
|
$RIFFchunk[$chunkname][$thisindex]['parsed']['starthundredths'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 59, 2));
|
||||||
|
$RIFFchunk[$chunkname][$thisindex]['parsed']['endseconds'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 61, 2));
|
||||||
|
$RIFFchunk[$chunkname][$thisindex]['parsed']['endhundreths'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 63, 2));
|
||||||
|
$RIFFchunk[$chunkname][$thisindex]['parsed']['sdate'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 65, 6);
|
||||||
|
$RIFFchunk[$chunkname][$thisindex]['parsed']['kdate'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 71, 6);
|
||||||
|
$RIFFchunk[$chunkname][$thisindex]['parsed']['start_hr'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 77, 1);
|
||||||
|
$RIFFchunk[$chunkname][$thisindex]['parsed']['kill_hr'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 78, 1);
|
||||||
|
$RIFFchunk[$chunkname][$thisindex]['parsed']['digital'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 79, 1);
|
||||||
|
$RIFFchunk[$chunkname][$thisindex]['parsed']['sample_rate'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 80, 2));
|
||||||
|
$RIFFchunk[$chunkname][$thisindex]['parsed']['stereo'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 82, 1);
|
||||||
|
$RIFFchunk[$chunkname][$thisindex]['parsed']['compress'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 83, 1);
|
||||||
|
$RIFFchunk[$chunkname][$thisindex]['parsed']['eomstrt'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 84, 4));
|
||||||
|
$RIFFchunk[$chunkname][$thisindex]['parsed']['eomlen'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 88, 2));
|
||||||
|
$RIFFchunk[$chunkname][$thisindex]['parsed']['attrib2'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 90, 4));
|
||||||
|
$RIFFchunk[$chunkname][$thisindex]['parsed']['future1'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 94, 12);
|
||||||
|
$RIFFchunk[$chunkname][$thisindex]['parsed']['catfontcolor'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 106, 4));
|
||||||
|
$RIFFchunk[$chunkname][$thisindex]['parsed']['catcolor'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 110, 4));
|
||||||
|
$RIFFchunk[$chunkname][$thisindex]['parsed']['segeompos'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 114, 4));
|
||||||
|
$RIFFchunk[$chunkname][$thisindex]['parsed']['vt_startsecs'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 118, 2));
|
||||||
|
$RIFFchunk[$chunkname][$thisindex]['parsed']['vt_starthunds'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 120, 2));
|
||||||
|
$RIFFchunk[$chunkname][$thisindex]['parsed']['priorcat'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 122, 3);
|
||||||
|
$RIFFchunk[$chunkname][$thisindex]['parsed']['priorcopy'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 125, 4);
|
||||||
|
$RIFFchunk[$chunkname][$thisindex]['parsed']['priorpadd'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 129, 1);
|
||||||
|
$RIFFchunk[$chunkname][$thisindex]['parsed']['postcat'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 130, 3);
|
||||||
|
$RIFFchunk[$chunkname][$thisindex]['parsed']['postcopy'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 133, 4);
|
||||||
|
$RIFFchunk[$chunkname][$thisindex]['parsed']['postpadd'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 137, 1);
|
||||||
|
$RIFFchunk[$chunkname][$thisindex]['parsed']['hrcanplay'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 138, 21);
|
||||||
|
$RIFFchunk[$chunkname][$thisindex]['parsed']['future2'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 159, 108);
|
||||||
|
$RIFFchunk[$chunkname][$thisindex]['parsed']['artist'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 267, 34);
|
||||||
|
$RIFFchunk[$chunkname][$thisindex]['parsed']['comment'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 301, 34); // "trivia" in other documentation
|
||||||
|
$RIFFchunk[$chunkname][$thisindex]['parsed']['intro'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 335, 2);
|
||||||
|
$RIFFchunk[$chunkname][$thisindex]['parsed']['end'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 337, 1);
|
||||||
|
$RIFFchunk[$chunkname][$thisindex]['parsed']['year'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 338, 4);
|
||||||
|
$RIFFchunk[$chunkname][$thisindex]['parsed']['obsolete2'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 342, 1);
|
||||||
|
$RIFFchunk[$chunkname][$thisindex]['parsed']['rec_hr'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 343, 1);
|
||||||
|
$RIFFchunk[$chunkname][$thisindex]['parsed']['rdate'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 344, 6);
|
||||||
|
$RIFFchunk[$chunkname][$thisindex]['parsed']['mpeg_bitrate'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 350, 2));
|
||||||
|
$RIFFchunk[$chunkname][$thisindex]['parsed']['pitch'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 352, 2));
|
||||||
|
$RIFFchunk[$chunkname][$thisindex]['parsed']['playlevel'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 354, 2));
|
||||||
|
$RIFFchunk[$chunkname][$thisindex]['parsed']['lenvalid'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 356, 1);
|
||||||
|
$RIFFchunk[$chunkname][$thisindex]['parsed']['filelength'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 357, 4));
|
||||||
|
$RIFFchunk[$chunkname][$thisindex]['parsed']['newplaylevel'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 361, 2));
|
||||||
|
$RIFFchunk[$chunkname][$thisindex]['parsed']['chopsize'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 363, 4));
|
||||||
|
$RIFFchunk[$chunkname][$thisindex]['parsed']['vteomovr'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 367, 4));
|
||||||
|
$RIFFchunk[$chunkname][$thisindex]['parsed']['desiredlen'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 371, 4));
|
||||||
|
$RIFFchunk[$chunkname][$thisindex]['parsed']['triggers'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 375, 4));
|
||||||
|
$RIFFchunk[$chunkname][$thisindex]['parsed']['fillout'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 379, 33);
|
||||||
|
|
||||||
|
foreach (array('title', 'artist', 'comment') as $key) {
|
||||||
|
if (trim($RIFFchunk[$chunkname][$thisindex]['parsed'][$key])) {
|
||||||
|
$info['riff']['comments'][$key] = array($RIFFchunk[$chunkname][$thisindex]['parsed'][$key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($RIFFchunk[$chunkname][$thisindex]['parsed']['filelength'] && !empty($info['filesize']) && ($RIFFchunk[$chunkname][$thisindex]['parsed']['filelength'] != $info['filesize'])) {
|
||||||
|
$this->warning('RIFF.WAVE.scot.filelength ('.$RIFFchunk[$chunkname][$thisindex]['parsed']['filelength'].') different from actual filesize ('.$info['filesize'].')');
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (!empty($LISTchunkParent) && (($RIFFchunk[$chunkname][$thisindex]['offset'] + $RIFFchunk[$chunkname][$thisindex]['size']) <= $LISTchunkMaxOffset)) {
|
if (!empty($LISTchunkParent) && isset($LISTchunkMaxOffset) && (($RIFFchunk[$chunkname][$thisindex]['offset'] + $RIFFchunk[$chunkname][$thisindex]['size']) <= $LISTchunkMaxOffset)) {
|
||||||
$RIFFchunk[$LISTchunkParent][$chunkname][$thisindex]['offset'] = $RIFFchunk[$chunkname][$thisindex]['offset'];
|
$RIFFchunk[$LISTchunkParent][$chunkname][$thisindex]['offset'] = $RIFFchunk[$chunkname][$thisindex]['offset'];
|
||||||
$RIFFchunk[$LISTchunkParent][$chunkname][$thisindex]['size'] = $RIFFchunk[$chunkname][$thisindex]['size'];
|
$RIFFchunk[$LISTchunkParent][$chunkname][$thisindex]['size'] = $RIFFchunk[$chunkname][$thisindex]['size'];
|
||||||
unset($RIFFchunk[$chunkname][$thisindex]['offset']);
|
unset($RIFFchunk[$chunkname][$thisindex]['offset']);
|
||||||
|
@ -1767,6 +1861,11 @@ class getid3_riff extends getid3_handler {
|
||||||
return $RIFFchunk;
|
return $RIFFchunk;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $RIFFdata
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
public function ParseRIFFdata(&$RIFFdata) {
|
public function ParseRIFFdata(&$RIFFdata) {
|
||||||
$info = &$this->getid3->info;
|
$info = &$this->getid3->info;
|
||||||
if ($RIFFdata) {
|
if ($RIFFdata) {
|
||||||
|
@ -1804,6 +1903,12 @@ class getid3_riff extends getid3_handler {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $RIFFinfoArray
|
||||||
|
* @param array $CommentsTargetArray
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
public static function parseComments(&$RIFFinfoArray, &$CommentsTargetArray) {
|
public static function parseComments(&$RIFFinfoArray, &$CommentsTargetArray) {
|
||||||
$RIFFinfoKeyLookup = array(
|
$RIFFinfoKeyLookup = array(
|
||||||
'IARL'=>'archivallocation',
|
'IARL'=>'archivallocation',
|
||||||
|
@ -1863,8 +1968,14 @@ class getid3_riff extends getid3_handler {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $WaveFormatExData
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
public static function parseWAVEFORMATex($WaveFormatExData) {
|
public static function parseWAVEFORMATex($WaveFormatExData) {
|
||||||
// shortcut
|
// shortcut
|
||||||
|
$WaveFormatEx = array();
|
||||||
$WaveFormatEx['raw'] = array();
|
$WaveFormatEx['raw'] = array();
|
||||||
$WaveFormatEx_raw = &$WaveFormatEx['raw'];
|
$WaveFormatEx_raw = &$WaveFormatEx['raw'];
|
||||||
|
|
||||||
|
@ -1888,6 +1999,11 @@ class getid3_riff extends getid3_handler {
|
||||||
return $WaveFormatEx;
|
return $WaveFormatEx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $WavPackChunkData
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
public function parseWavPackHeader($WavPackChunkData) {
|
public function parseWavPackHeader($WavPackChunkData) {
|
||||||
// typedef struct {
|
// typedef struct {
|
||||||
// char ckID [4];
|
// char ckID [4];
|
||||||
|
@ -1949,6 +2065,12 @@ class getid3_riff extends getid3_handler {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $BITMAPINFOHEADER
|
||||||
|
* @param bool $littleEndian
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
public static function ParseBITMAPINFOHEADER($BITMAPINFOHEADER, $littleEndian=true) {
|
public static function ParseBITMAPINFOHEADER($BITMAPINFOHEADER, $littleEndian=true) {
|
||||||
|
|
||||||
$parsed['biSize'] = substr($BITMAPINFOHEADER, 0, 4); // number of bytes required by the BITMAPINFOHEADER structure
|
$parsed['biSize'] = substr($BITMAPINFOHEADER, 0, 4); // number of bytes required by the BITMAPINFOHEADER structure
|
||||||
|
@ -1968,6 +2090,12 @@ class getid3_riff extends getid3_handler {
|
||||||
return $parsed;
|
return $parsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $DIVXTAG
|
||||||
|
* @param bool $raw
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
public static function ParseDIVXTAG($DIVXTAG, $raw=false) {
|
public static function ParseDIVXTAG($DIVXTAG, $raw=false) {
|
||||||
// structure from "IDivX" source, Form1.frm, by "Greg Frazier of Daemonic Software Group", email: gfrazier@icestorm.net, web: http://dsg.cjb.net/
|
// structure from "IDivX" source, Form1.frm, by "Greg Frazier of Daemonic Software Group", email: gfrazier@icestorm.net, web: http://dsg.cjb.net/
|
||||||
// source available at http://files.divx-digest.com/download/c663efe7ef8ad2e90bf4af4d3ea6188a/on0SWN2r/edit/IDivX.zip
|
// source available at http://files.divx-digest.com/download/c663efe7ef8ad2e90bf4af4d3ea6188a/on0SWN2r/edit/IDivX.zip
|
||||||
|
@ -2014,6 +2142,7 @@ class getid3_riff extends getid3_handler {
|
||||||
5 => 'NC-17',
|
5 => 'NC-17',
|
||||||
);
|
);
|
||||||
|
|
||||||
|
$parsed = array();
|
||||||
$parsed['title'] = trim(substr($DIVXTAG, 0, 32));
|
$parsed['title'] = trim(substr($DIVXTAG, 0, 32));
|
||||||
$parsed['artist'] = trim(substr($DIVXTAG, 32, 28));
|
$parsed['artist'] = trim(substr($DIVXTAG, 32, 28));
|
||||||
$parsed['year'] = intval(trim(substr($DIVXTAG, 60, 4)));
|
$parsed['year'] = intval(trim(substr($DIVXTAG, 60, 4)));
|
||||||
|
@ -2029,8 +2158,8 @@ class getid3_riff extends getid3_handler {
|
||||||
if (!$raw) {
|
if (!$raw) {
|
||||||
unset($parsed['genre_id'], $parsed['rating_id']);
|
unset($parsed['genre_id'], $parsed['rating_id']);
|
||||||
foreach ($parsed as $key => $value) {
|
foreach ($parsed as $key => $value) {
|
||||||
if (!$value === '') {
|
if (empty($value)) {
|
||||||
unset($parsed['key']);
|
unset($parsed[$key]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2042,6 +2171,11 @@ class getid3_riff extends getid3_handler {
|
||||||
return $parsed;
|
return $parsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $tagshortname
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public static function waveSNDMtagLookup($tagshortname) {
|
public static function waveSNDMtagLookup($tagshortname) {
|
||||||
$begin = __LINE__;
|
$begin = __LINE__;
|
||||||
|
|
||||||
|
@ -2065,6 +2199,11 @@ class getid3_riff extends getid3_handler {
|
||||||
return getid3_lib::EmbeddedLookup($tagshortname, $begin, __LINE__, __FILE__, 'riff-sndm');
|
return getid3_lib::EmbeddedLookup($tagshortname, $begin, __LINE__, __FILE__, 'riff-sndm');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $wFormatTag
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public static function wFormatTagLookup($wFormatTag) {
|
public static function wFormatTagLookup($wFormatTag) {
|
||||||
|
|
||||||
$begin = __LINE__;
|
$begin = __LINE__;
|
||||||
|
@ -2234,6 +2373,11 @@ class getid3_riff extends getid3_handler {
|
||||||
return getid3_lib::EmbeddedLookup('0x'.str_pad(strtoupper(dechex($wFormatTag)), 4, '0', STR_PAD_LEFT), $begin, __LINE__, __FILE__, 'riff-wFormatTag');
|
return getid3_lib::EmbeddedLookup('0x'.str_pad(strtoupper(dechex($wFormatTag)), 4, '0', STR_PAD_LEFT), $begin, __LINE__, __FILE__, 'riff-wFormatTag');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $fourcc
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public static function fourccLookup($fourcc) {
|
public static function fourccLookup($fourcc) {
|
||||||
|
|
||||||
$begin = __LINE__;
|
$begin = __LINE__;
|
||||||
|
@ -2628,6 +2772,12 @@ class getid3_riff extends getid3_handler {
|
||||||
return getid3_lib::EmbeddedLookup($fourcc, $begin, __LINE__, __FILE__, 'riff-fourcc');
|
return getid3_lib::EmbeddedLookup($fourcc, $begin, __LINE__, __FILE__, 'riff-fourcc');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $byteword
|
||||||
|
* @param bool $signed
|
||||||
|
*
|
||||||
|
* @return int|float|false
|
||||||
|
*/
|
||||||
private function EitherEndian2Int($byteword, $signed=false) {
|
private function EitherEndian2Int($byteword, $signed=false) {
|
||||||
if ($this->container == 'riff') {
|
if ($this->container == 'riff') {
|
||||||
return getid3_lib::LittleEndian2Int($byteword, $signed);
|
return getid3_lib::LittleEndian2Int($byteword, $signed);
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////
|
||||||
/// getID3() by James Heinrich <info@getid3.org> //
|
/// getID3() by James Heinrich <info@getid3.org> //
|
||||||
// available at http://getid3.sourceforge.net //
|
// available at https://github.com/JamesHeinrich/getID3 //
|
||||||
// or http://www.getid3.org //
|
// or https://www.getid3.org //
|
||||||
// also https://github.com/JamesHeinrich/getID3 //
|
// or http://getid3.sourceforge.net //
|
||||||
/////////////////////////////////////////////////////////////////
|
// see readme.txt for more details //
|
||||||
// See readme.txt for more details //
|
|
||||||
/////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////
|
||||||
// //
|
// //
|
||||||
// module.audio.ac3.php //
|
// module.audio.ac3.php //
|
||||||
|
@ -17,11 +17,21 @@
|
||||||
|
|
||||||
class getid3_ac3 extends getid3_handler
|
class getid3_ac3 extends getid3_handler
|
||||||
{
|
{
|
||||||
private $AC3header = array();
|
/**
|
||||||
private $BSIoffset = 0;
|
* @var array
|
||||||
|
*/
|
||||||
|
private $AC3header = array();
|
||||||
|
|
||||||
const syncword = 0x0B77;
|
/**
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
private $BSIoffset = 0;
|
||||||
|
|
||||||
|
const syncword = 0x0B77;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
public function Analyze() {
|
public function Analyze() {
|
||||||
$info = &$this->getid3->info;
|
$info = &$this->getid3->info;
|
||||||
|
|
||||||
|
@ -187,7 +197,7 @@ class getid3_ac3 extends getid3_handler
|
||||||
} elseif ($thisfile_ac3_raw_bsi['bsid'] <= 16) { // E-AC3
|
} elseif ($thisfile_ac3_raw_bsi['bsid'] <= 16) { // E-AC3
|
||||||
|
|
||||||
|
|
||||||
$this->error('E-AC3 parsing is incomplete and experimental in this version of getID3 ('.$this->getid3->version().'). Notably the bitrate calculations are wrong -- value might (or not) be correct, but it is not calculated correctly. Email info@getid3.org if you know how to calculate EAC3 bitrate correctly.');
|
$this->error('E-AC3 parsing is incomplete and experimental in this version of getID3 ('.$this->getid3->version().'). Notably the bitrate calculations are wrong -- value might (or not) be correct, but it is not calculated correctly. Email info@getid3.org if you know how to calculate EAC3 bitrate correctly.');
|
||||||
$info['audio']['dataformat'] = 'eac3';
|
$info['audio']['dataformat'] = 'eac3';
|
||||||
|
|
||||||
$thisfile_ac3_raw_bsi['strmtyp'] = $this->readHeaderBSI(2);
|
$thisfile_ac3_raw_bsi['strmtyp'] = $this->readHeaderBSI(2);
|
||||||
|
@ -412,7 +422,7 @@ $this->error('E-AC3 parsing is incomplete and experimental in this version of ge
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
$this->error('Bit stream identification is version '.$thisfile_ac3_raw_bsi['bsid'].', but getID3() only understands up to version 16. Please submit a support ticket with a sample file.');
|
$this->error('Bit stream identification is version '.$thisfile_ac3_raw_bsi['bsid'].', but getID3() only understands up to version 16. Please submit a support ticket with a sample file.');
|
||||||
unset($info['ac3']);
|
unset($info['ac3']);
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -431,15 +441,17 @@ $this->error('E-AC3 parsing is incomplete and experimental in this version of ge
|
||||||
$thisfile_ac3['frame_length'] = self::frameSizeLookup($thisfile_ac3_raw_bsi['frmsizecod'], $thisfile_ac3_raw_bsi['fscod']);
|
$thisfile_ac3['frame_length'] = self::frameSizeLookup($thisfile_ac3_raw_bsi['frmsizecod'], $thisfile_ac3_raw_bsi['fscod']);
|
||||||
$thisfile_ac3['bitrate'] = self::bitrateLookup($thisfile_ac3_raw_bsi['frmsizecod']);
|
$thisfile_ac3['bitrate'] = self::bitrateLookup($thisfile_ac3_raw_bsi['frmsizecod']);
|
||||||
} elseif (!empty($thisfile_ac3_raw_bsi['frmsiz'])) {
|
} elseif (!empty($thisfile_ac3_raw_bsi['frmsiz'])) {
|
||||||
// this isn't right, but it's (usually) close, roughly 5% less than it should be.
|
// this isn't right, but it's (usually) close, roughly 5% less than it should be.
|
||||||
// but WHERE is the actual bitrate value stored in EAC3?? email info@getid3.org if you know!
|
// but WHERE is the actual bitrate value stored in EAC3?? email info@getid3.org if you know!
|
||||||
$thisfile_ac3['bitrate'] = ($thisfile_ac3_raw_bsi['frmsiz'] + 1) * 16 * 30; // The frmsiz field shall contain a value one less than the overall size of the coded syncframe in 16-bit words. That is, this field may assume a value ranging from 0 to 2047, and these values correspond to syncframe sizes ranging from 1 to 2048.
|
$thisfile_ac3['bitrate'] = ($thisfile_ac3_raw_bsi['frmsiz'] + 1) * 16 * 30; // The frmsiz field shall contain a value one less than the overall size of the coded syncframe in 16-bit words. That is, this field may assume a value ranging from 0 to 2047, and these values correspond to syncframe sizes ranging from 1 to 2048.
|
||||||
// kludge-fix to make it approximately the expected value, still not "right":
|
// kludge-fix to make it approximately the expected value, still not "right":
|
||||||
$thisfile_ac3['bitrate'] = round(($thisfile_ac3['bitrate'] * 1.05) / 16000) * 16000;
|
$thisfile_ac3['bitrate'] = round(($thisfile_ac3['bitrate'] * 1.05) / 16000) * 16000;
|
||||||
}
|
}
|
||||||
$info['audio']['bitrate'] = $thisfile_ac3['bitrate'];
|
$info['audio']['bitrate'] = $thisfile_ac3['bitrate'];
|
||||||
|
|
||||||
$thisfile_ac3['service_type'] = self::serviceTypeLookup($thisfile_ac3_raw_bsi['bsmod'], $thisfile_ac3_raw_bsi['acmod']);
|
if (isset($thisfile_ac3_raw_bsi['bsmod']) && isset($thisfile_ac3_raw_bsi['acmod'])) {
|
||||||
|
$thisfile_ac3['service_type'] = self::serviceTypeLookup($thisfile_ac3_raw_bsi['bsmod'], $thisfile_ac3_raw_bsi['acmod']);
|
||||||
|
}
|
||||||
$ac3_coding_mode = self::audioCodingModeLookup($thisfile_ac3_raw_bsi['acmod']);
|
$ac3_coding_mode = self::audioCodingModeLookup($thisfile_ac3_raw_bsi['acmod']);
|
||||||
foreach($ac3_coding_mode as $key => $value) {
|
foreach($ac3_coding_mode as $key => $value) {
|
||||||
$thisfile_ac3[$key] = $value;
|
$thisfile_ac3[$key] = $value;
|
||||||
|
@ -470,6 +482,11 @@ $thisfile_ac3['bitrate'] = round(($thisfile_ac3['bitrate'] * 1.05) / 16000) * 16
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $length
|
||||||
|
*
|
||||||
|
* @return float|int
|
||||||
|
*/
|
||||||
private function readHeaderBSI($length) {
|
private function readHeaderBSI($length) {
|
||||||
$data = substr($this->AC3header['bsi'], $this->BSIoffset, $length);
|
$data = substr($this->AC3header['bsi'], $this->BSIoffset, $length);
|
||||||
$this->BSIoffset += $length;
|
$this->BSIoffset += $length;
|
||||||
|
@ -477,6 +494,11 @@ $thisfile_ac3['bitrate'] = round(($thisfile_ac3['bitrate'] * 1.05) / 16000) * 16
|
||||||
return bindec($data);
|
return bindec($data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $fscod
|
||||||
|
*
|
||||||
|
* @return int|string|false
|
||||||
|
*/
|
||||||
public static function sampleRateCodeLookup($fscod) {
|
public static function sampleRateCodeLookup($fscod) {
|
||||||
static $sampleRateCodeLookup = array(
|
static $sampleRateCodeLookup = array(
|
||||||
0 => 48000,
|
0 => 48000,
|
||||||
|
@ -487,6 +509,11 @@ $thisfile_ac3['bitrate'] = round(($thisfile_ac3['bitrate'] * 1.05) / 16000) * 16
|
||||||
return (isset($sampleRateCodeLookup[$fscod]) ? $sampleRateCodeLookup[$fscod] : false);
|
return (isset($sampleRateCodeLookup[$fscod]) ? $sampleRateCodeLookup[$fscod] : false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $fscod2
|
||||||
|
*
|
||||||
|
* @return int|string|false
|
||||||
|
*/
|
||||||
public static function sampleRateCodeLookup2($fscod2) {
|
public static function sampleRateCodeLookup2($fscod2) {
|
||||||
static $sampleRateCodeLookup2 = array(
|
static $sampleRateCodeLookup2 = array(
|
||||||
0 => 24000,
|
0 => 24000,
|
||||||
|
@ -497,6 +524,12 @@ $thisfile_ac3['bitrate'] = round(($thisfile_ac3['bitrate'] * 1.05) / 16000) * 16
|
||||||
return (isset($sampleRateCodeLookup2[$fscod2]) ? $sampleRateCodeLookup2[$fscod2] : false);
|
return (isset($sampleRateCodeLookup2[$fscod2]) ? $sampleRateCodeLookup2[$fscod2] : false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $bsmod
|
||||||
|
* @param int $acmod
|
||||||
|
*
|
||||||
|
* @return string|false
|
||||||
|
*/
|
||||||
public static function serviceTypeLookup($bsmod, $acmod) {
|
public static function serviceTypeLookup($bsmod, $acmod) {
|
||||||
static $serviceTypeLookup = array();
|
static $serviceTypeLookup = array();
|
||||||
if (empty($serviceTypeLookup)) {
|
if (empty($serviceTypeLookup)) {
|
||||||
|
@ -518,6 +551,11 @@ $thisfile_ac3['bitrate'] = round(($thisfile_ac3['bitrate'] * 1.05) / 16000) * 16
|
||||||
return (isset($serviceTypeLookup[$bsmod][$acmod]) ? $serviceTypeLookup[$bsmod][$acmod] : false);
|
return (isset($serviceTypeLookup[$bsmod][$acmod]) ? $serviceTypeLookup[$bsmod][$acmod] : false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $acmod
|
||||||
|
*
|
||||||
|
* @return array|false
|
||||||
|
*/
|
||||||
public static function audioCodingModeLookup($acmod) {
|
public static function audioCodingModeLookup($acmod) {
|
||||||
// array(channel configuration, # channels (not incl LFE), channel order)
|
// array(channel configuration, # channels (not incl LFE), channel order)
|
||||||
static $audioCodingModeLookup = array (
|
static $audioCodingModeLookup = array (
|
||||||
|
@ -533,6 +571,11 @@ $thisfile_ac3['bitrate'] = round(($thisfile_ac3['bitrate'] * 1.05) / 16000) * 16
|
||||||
return (isset($audioCodingModeLookup[$acmod]) ? $audioCodingModeLookup[$acmod] : false);
|
return (isset($audioCodingModeLookup[$acmod]) ? $audioCodingModeLookup[$acmod] : false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $cmixlev
|
||||||
|
*
|
||||||
|
* @return int|float|string|false
|
||||||
|
*/
|
||||||
public static function centerMixLevelLookup($cmixlev) {
|
public static function centerMixLevelLookup($cmixlev) {
|
||||||
static $centerMixLevelLookup;
|
static $centerMixLevelLookup;
|
||||||
if (empty($centerMixLevelLookup)) {
|
if (empty($centerMixLevelLookup)) {
|
||||||
|
@ -546,6 +589,11 @@ $thisfile_ac3['bitrate'] = round(($thisfile_ac3['bitrate'] * 1.05) / 16000) * 16
|
||||||
return (isset($centerMixLevelLookup[$cmixlev]) ? $centerMixLevelLookup[$cmixlev] : false);
|
return (isset($centerMixLevelLookup[$cmixlev]) ? $centerMixLevelLookup[$cmixlev] : false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $surmixlev
|
||||||
|
*
|
||||||
|
* @return int|float|string|false
|
||||||
|
*/
|
||||||
public static function surroundMixLevelLookup($surmixlev) {
|
public static function surroundMixLevelLookup($surmixlev) {
|
||||||
static $surroundMixLevelLookup;
|
static $surroundMixLevelLookup;
|
||||||
if (empty($surroundMixLevelLookup)) {
|
if (empty($surroundMixLevelLookup)) {
|
||||||
|
@ -559,6 +607,11 @@ $thisfile_ac3['bitrate'] = round(($thisfile_ac3['bitrate'] * 1.05) / 16000) * 16
|
||||||
return (isset($surroundMixLevelLookup[$surmixlev]) ? $surroundMixLevelLookup[$surmixlev] : false);
|
return (isset($surroundMixLevelLookup[$surmixlev]) ? $surroundMixLevelLookup[$surmixlev] : false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $dsurmod
|
||||||
|
*
|
||||||
|
* @return string|false
|
||||||
|
*/
|
||||||
public static function dolbySurroundModeLookup($dsurmod) {
|
public static function dolbySurroundModeLookup($dsurmod) {
|
||||||
static $dolbySurroundModeLookup = array(
|
static $dolbySurroundModeLookup = array(
|
||||||
0 => 'not indicated',
|
0 => 'not indicated',
|
||||||
|
@ -569,12 +622,18 @@ $thisfile_ac3['bitrate'] = round(($thisfile_ac3['bitrate'] * 1.05) / 16000) * 16
|
||||||
return (isset($dolbySurroundModeLookup[$dsurmod]) ? $dolbySurroundModeLookup[$dsurmod] : false);
|
return (isset($dolbySurroundModeLookup[$dsurmod]) ? $dolbySurroundModeLookup[$dsurmod] : false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $acmod
|
||||||
|
* @param bool $lfeon
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
public static function channelsEnabledLookup($acmod, $lfeon) {
|
public static function channelsEnabledLookup($acmod, $lfeon) {
|
||||||
$lookup = array(
|
$lookup = array(
|
||||||
'ch1'=>(bool) ($acmod == 0),
|
'ch1'=>($acmod == 0),
|
||||||
'ch2'=>(bool) ($acmod == 0),
|
'ch2'=>($acmod == 0),
|
||||||
'left'=>(bool) ($acmod > 1),
|
'left'=>($acmod > 1),
|
||||||
'right'=>(bool) ($acmod > 1),
|
'right'=>($acmod > 1),
|
||||||
'center'=>(bool) ($acmod & 0x01),
|
'center'=>(bool) ($acmod & 0x01),
|
||||||
'surround_mono'=>false,
|
'surround_mono'=>false,
|
||||||
'surround_left'=>false,
|
'surround_left'=>false,
|
||||||
|
@ -594,6 +653,11 @@ $thisfile_ac3['bitrate'] = round(($thisfile_ac3['bitrate'] * 1.05) / 16000) * 16
|
||||||
return $lookup;
|
return $lookup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $compre
|
||||||
|
*
|
||||||
|
* @return float|int
|
||||||
|
*/
|
||||||
public static function heavyCompression($compre) {
|
public static function heavyCompression($compre) {
|
||||||
// The first four bits indicate gain changes in 6.02dB increments which can be
|
// The first four bits indicate gain changes in 6.02dB increments which can be
|
||||||
// implemented with an arithmetic shift operation. The following four bits
|
// implemented with an arithmetic shift operation. The following four bits
|
||||||
|
@ -623,7 +687,7 @@ $thisfile_ac3['bitrate'] = round(($thisfile_ac3['bitrate'] * 1.05) / 16000) * 16
|
||||||
// -8 -42.14 dB
|
// -8 -42.14 dB
|
||||||
|
|
||||||
$fourbit = str_pad(decbin(($compre & 0xF0) >> 4), 4, '0', STR_PAD_LEFT);
|
$fourbit = str_pad(decbin(($compre & 0xF0) >> 4), 4, '0', STR_PAD_LEFT);
|
||||||
if ($fourbit{0} == '1') {
|
if ($fourbit[0] == '1') {
|
||||||
$log_gain = -8 + bindec(substr($fourbit, 1));
|
$log_gain = -8 + bindec(substr($fourbit, 1));
|
||||||
} else {
|
} else {
|
||||||
$log_gain = bindec(substr($fourbit, 1));
|
$log_gain = bindec(substr($fourbit, 1));
|
||||||
|
@ -644,6 +708,11 @@ $thisfile_ac3['bitrate'] = round(($thisfile_ac3['bitrate'] * 1.05) / 16000) * 16
|
||||||
return $log_gain - $lin_gain;
|
return $log_gain - $lin_gain;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $roomtyp
|
||||||
|
*
|
||||||
|
* @return string|false
|
||||||
|
*/
|
||||||
public static function roomTypeLookup($roomtyp) {
|
public static function roomTypeLookup($roomtyp) {
|
||||||
static $roomTypeLookup = array(
|
static $roomTypeLookup = array(
|
||||||
0 => 'not indicated',
|
0 => 'not indicated',
|
||||||
|
@ -654,6 +723,12 @@ $thisfile_ac3['bitrate'] = round(($thisfile_ac3['bitrate'] * 1.05) / 16000) * 16
|
||||||
return (isset($roomTypeLookup[$roomtyp]) ? $roomTypeLookup[$roomtyp] : false);
|
return (isset($roomTypeLookup[$roomtyp]) ? $roomTypeLookup[$roomtyp] : false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $frmsizecod
|
||||||
|
* @param int $fscod
|
||||||
|
*
|
||||||
|
* @return int|false
|
||||||
|
*/
|
||||||
public static function frameSizeLookup($frmsizecod, $fscod) {
|
public static function frameSizeLookup($frmsizecod, $fscod) {
|
||||||
// LSB is whether padding is used or not
|
// LSB is whether padding is used or not
|
||||||
$padding = (bool) ($frmsizecod & 0x01);
|
$padding = (bool) ($frmsizecod & 0x01);
|
||||||
|
@ -683,13 +758,20 @@ $thisfile_ac3['bitrate'] = round(($thisfile_ac3['bitrate'] * 1.05) / 16000) * 16
|
||||||
18 => array(2560, 2786, 3840) // 640 kbps
|
18 => array(2560, 2786, 3840) // 640 kbps
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
$paddingBytes = 0;
|
||||||
if (($fscod == 1) && $padding) {
|
if (($fscod == 1) && $padding) {
|
||||||
// frame lengths are padded by 1 word (16 bits) at 44100
|
// frame lengths are padded by 1 word (16 bits) at 44100
|
||||||
$frameSizeLookup[$frmsizecod] += 2;
|
// (fscode==1) means 44100Hz (see sampleRateCodeLookup)
|
||||||
|
$paddingBytes = 2;
|
||||||
}
|
}
|
||||||
return (isset($frameSizeLookup[$framesizeid][$fscod]) ? $frameSizeLookup[$framesizeid][$fscod] : false);
|
return (isset($frameSizeLookup[$framesizeid][$fscod]) ? $frameSizeLookup[$framesizeid][$fscod] + $paddingBytes : false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $frmsizecod
|
||||||
|
*
|
||||||
|
* @return int|false
|
||||||
|
*/
|
||||||
public static function bitrateLookup($frmsizecod) {
|
public static function bitrateLookup($frmsizecod) {
|
||||||
// LSB is whether padding is used or not
|
// LSB is whether padding is used or not
|
||||||
$padding = (bool) ($frmsizecod & 0x01);
|
$padding = (bool) ($frmsizecod & 0x01);
|
||||||
|
@ -719,6 +801,11 @@ $thisfile_ac3['bitrate'] = round(($thisfile_ac3['bitrate'] * 1.05) / 16000) * 16
|
||||||
return (isset($bitrateLookup[$framesizeid]) ? $bitrateLookup[$framesizeid] : false);
|
return (isset($bitrateLookup[$framesizeid]) ? $bitrateLookup[$framesizeid] : false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $numblkscod
|
||||||
|
*
|
||||||
|
* @return int|false
|
||||||
|
*/
|
||||||
public static function blocksPerSyncFrame($numblkscod) {
|
public static function blocksPerSyncFrame($numblkscod) {
|
||||||
static $blocksPerSyncFrameLookup = array(
|
static $blocksPerSyncFrameLookup = array(
|
||||||
0 => 1,
|
0 => 1,
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////
|
||||||
/// getID3() by James Heinrich <info@getid3.org> //
|
/// getID3() by James Heinrich <info@getid3.org> //
|
||||||
// available at http://getid3.sourceforge.net //
|
// available at https://github.com/JamesHeinrich/getID3 //
|
||||||
// or http://www.getid3.org //
|
// or https://www.getid3.org //
|
||||||
// also https://github.com/JamesHeinrich/getID3 //
|
// or http://getid3.sourceforge.net //
|
||||||
/////////////////////////////////////////////////////////////////
|
// see readme.txt for more details //
|
||||||
// See readme.txt for more details //
|
|
||||||
/////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////
|
||||||
// //
|
// //
|
||||||
// module.audio.dts.php //
|
// module.audio.dts.php //
|
||||||
|
@ -21,21 +21,27 @@
|
||||||
class getid3_dts extends getid3_handler
|
class getid3_dts extends getid3_handler
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Default DTS syncword used in native .cpt or .dts formats
|
* Default DTS syncword used in native .cpt or .dts formats.
|
||||||
*/
|
*/
|
||||||
const syncword = "\x7F\xFE\x80\x01";
|
const syncword = "\x7F\xFE\x80\x01";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
private $readBinDataOffset = 0;
|
private $readBinDataOffset = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Possible syncwords indicating bitstream encoding
|
* Possible syncwords indicating bitstream encoding.
|
||||||
*/
|
*/
|
||||||
public static $syncwords = array(
|
public static $syncwords = array(
|
||||||
0 => "\x7F\xFE\x80\x01", // raw big-endian
|
0 => "\x7F\xFE\x80\x01", // raw big-endian
|
||||||
1 => "\xFE\x7F\x01\x80", // raw little-endian
|
1 => "\xFE\x7F\x01\x80", // raw little-endian
|
||||||
2 => "\x1F\xFF\xE8\x00", // 14-bit big-endian
|
2 => "\x1F\xFF\xE8\x00", // 14-bit big-endian
|
||||||
3 => "\xFF\x1F\x00\xE8"); // 14-bit little-endian
|
3 => "\xFF\x1F\x00\xE8"); // 14-bit little-endian
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
public function Analyze() {
|
public function Analyze() {
|
||||||
$info = &$this->getid3->info;
|
$info = &$this->getid3->info;
|
||||||
$info['fileformat'] = 'dts';
|
$info['fileformat'] = 'dts';
|
||||||
|
@ -45,18 +51,18 @@ class getid3_dts extends getid3_handler
|
||||||
|
|
||||||
// check syncword
|
// check syncword
|
||||||
$sync = substr($DTSheader, 0, 4);
|
$sync = substr($DTSheader, 0, 4);
|
||||||
if (($encoding = array_search($sync, self::$syncwords)) !== false) {
|
if (($encoding = array_search($sync, self::$syncwords)) !== false) {
|
||||||
|
|
||||||
$info['dts']['raw']['magic'] = $sync;
|
$info['dts']['raw']['magic'] = $sync;
|
||||||
$this->readBinDataOffset = 32;
|
$this->readBinDataOffset = 32;
|
||||||
|
|
||||||
} elseif ($this->isDependencyFor('matroska')) {
|
} elseif ($this->isDependencyFor('matroska')) {
|
||||||
|
|
||||||
// Matroska contains DTS without syncword encoded as raw big-endian format
|
// Matroska contains DTS without syncword encoded as raw big-endian format
|
||||||
$encoding = 0;
|
$encoding = 0;
|
||||||
$this->readBinDataOffset = 0;
|
$this->readBinDataOffset = 0;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
unset($info['fileformat']);
|
unset($info['fileformat']);
|
||||||
return $this->error('Expecting "'.implode('| ', array_map('getid3_lib::PrintHexBytes', self::$syncwords)).'" at offset '.$info['avdataoffset'].', found "'.getid3_lib::PrintHexBytes($sync).'"');
|
return $this->error('Expecting "'.implode('| ', array_map('getid3_lib::PrintHexBytes', self::$syncwords)).'" at offset '.$info['avdataoffset'].', found "'.getid3_lib::PrintHexBytes($sync).'"');
|
||||||
|
@ -139,6 +145,12 @@ class getid3_dts extends getid3_handler
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $bin
|
||||||
|
* @param int $length
|
||||||
|
*
|
||||||
|
* @return float|int
|
||||||
|
*/
|
||||||
private function readBinData($bin, $length) {
|
private function readBinData($bin, $length) {
|
||||||
$data = substr($bin, $this->readBinDataOffset, $length);
|
$data = substr($bin, $this->readBinDataOffset, $length);
|
||||||
$this->readBinDataOffset += $length;
|
$this->readBinDataOffset += $length;
|
||||||
|
@ -146,6 +158,11 @@ class getid3_dts extends getid3_handler
|
||||||
return bindec($data);
|
return bindec($data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $index
|
||||||
|
*
|
||||||
|
* @return int|string|false
|
||||||
|
*/
|
||||||
public static function bitrateLookup($index) {
|
public static function bitrateLookup($index) {
|
||||||
static $lookup = array(
|
static $lookup = array(
|
||||||
0 => 32000,
|
0 => 32000,
|
||||||
|
@ -184,6 +201,11 @@ class getid3_dts extends getid3_handler
|
||||||
return (isset($lookup[$index]) ? $lookup[$index] : false);
|
return (isset($lookup[$index]) ? $lookup[$index] : false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $index
|
||||||
|
*
|
||||||
|
* @return int|string|false
|
||||||
|
*/
|
||||||
public static function sampleRateLookup($index) {
|
public static function sampleRateLookup($index) {
|
||||||
static $lookup = array(
|
static $lookup = array(
|
||||||
0 => 'invalid',
|
0 => 'invalid',
|
||||||
|
@ -206,6 +228,11 @@ class getid3_dts extends getid3_handler
|
||||||
return (isset($lookup[$index]) ? $lookup[$index] : false);
|
return (isset($lookup[$index]) ? $lookup[$index] : false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $index
|
||||||
|
*
|
||||||
|
* @return int|false
|
||||||
|
*/
|
||||||
public static function bitPerSampleLookup($index) {
|
public static function bitPerSampleLookup($index) {
|
||||||
static $lookup = array(
|
static $lookup = array(
|
||||||
0 => 16,
|
0 => 16,
|
||||||
|
@ -216,6 +243,11 @@ class getid3_dts extends getid3_handler
|
||||||
return (isset($lookup[$index]) ? $lookup[$index] : false);
|
return (isset($lookup[$index]) ? $lookup[$index] : false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $index
|
||||||
|
*
|
||||||
|
* @return int|false
|
||||||
|
*/
|
||||||
public static function numChannelsLookup($index) {
|
public static function numChannelsLookup($index) {
|
||||||
switch ($index) {
|
switch ($index) {
|
||||||
case 0:
|
case 0:
|
||||||
|
@ -254,6 +286,11 @@ class getid3_dts extends getid3_handler
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $index
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public static function channelArrangementLookup($index) {
|
public static function channelArrangementLookup($index) {
|
||||||
static $lookup = array(
|
static $lookup = array(
|
||||||
0 => 'A',
|
0 => 'A',
|
||||||
|
@ -276,6 +313,12 @@ class getid3_dts extends getid3_handler
|
||||||
return (isset($lookup[$index]) ? $lookup[$index] : 'user-defined');
|
return (isset($lookup[$index]) ? $lookup[$index] : 'user-defined');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $index
|
||||||
|
* @param int $version
|
||||||
|
*
|
||||||
|
* @return int|false
|
||||||
|
*/
|
||||||
public static function dialogNormalization($index, $version) {
|
public static function dialogNormalization($index, $version) {
|
||||||
switch ($version) {
|
switch ($version) {
|
||||||
case 7:
|
case 7:
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////
|
||||||
/// getID3() by James Heinrich <info@getid3.org> //
|
/// getID3() by James Heinrich <info@getid3.org> //
|
||||||
// available at http://getid3.sourceforge.net //
|
// available at https://github.com/JamesHeinrich/getID3 //
|
||||||
// or http://www.getid3.org //
|
// or https://www.getid3.org //
|
||||||
// also https://github.com/JamesHeinrich/getID3 //
|
// or http://getid3.sourceforge.net //
|
||||||
/////////////////////////////////////////////////////////////////
|
// see readme.txt for more details //
|
||||||
// See readme.txt for more details //
|
|
||||||
/////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////
|
||||||
// //
|
// //
|
||||||
// module.audio.flac.php //
|
// module.audio.flac.php //
|
||||||
|
@ -24,6 +24,9 @@ class getid3_flac extends getid3_handler
|
||||||
{
|
{
|
||||||
const syncword = 'fLaC';
|
const syncword = 'fLaC';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
public function Analyze() {
|
public function Analyze() {
|
||||||
$info = &$this->getid3->info;
|
$info = &$this->getid3->info;
|
||||||
|
|
||||||
|
@ -41,22 +44,30 @@ class getid3_flac extends getid3_handler
|
||||||
return $this->parseMETAdata();
|
return $this->parseMETAdata();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
public function parseMETAdata() {
|
public function parseMETAdata() {
|
||||||
$info = &$this->getid3->info;
|
$info = &$this->getid3->info;
|
||||||
do {
|
do {
|
||||||
$BlockOffset = $this->ftell();
|
$BlockOffset = $this->ftell();
|
||||||
$BlockHeader = $this->fread(4);
|
$BlockHeader = $this->fread(4);
|
||||||
$LBFBT = getid3_lib::BigEndian2Int(substr($BlockHeader, 0, 1));
|
$LBFBT = getid3_lib::BigEndian2Int(substr($BlockHeader, 0, 1)); // LBFBT = LastBlockFlag + BlockType
|
||||||
$LastBlockFlag = (bool) ($LBFBT & 0x80);
|
$LastBlockFlag = (bool) ($LBFBT & 0x80);
|
||||||
$BlockType = ($LBFBT & 0x7F);
|
$BlockType = ($LBFBT & 0x7F);
|
||||||
$BlockLength = getid3_lib::BigEndian2Int(substr($BlockHeader, 1, 3));
|
$BlockLength = getid3_lib::BigEndian2Int(substr($BlockHeader, 1, 3));
|
||||||
$BlockTypeText = self::metaBlockTypeLookup($BlockType);
|
$BlockTypeText = self::metaBlockTypeLookup($BlockType);
|
||||||
|
|
||||||
if (($BlockOffset + 4 + $BlockLength) > $info['avdataend']) {
|
if (($BlockOffset + 4 + $BlockLength) > $info['avdataend']) {
|
||||||
$this->error('METADATA_BLOCK_HEADER.BLOCK_TYPE ('.$BlockTypeText.') at offset '.$BlockOffset.' extends beyond end of file');
|
$this->warning('METADATA_BLOCK_HEADER.BLOCK_TYPE ('.$BlockTypeText.') at offset '.$BlockOffset.' extends beyond end of file');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if ($BlockLength < 1) {
|
if ($BlockLength < 1) {
|
||||||
|
if ($BlockTypeText != 'reserved') {
|
||||||
|
// probably supposed to be zero-length
|
||||||
|
$this->warning('METADATA_BLOCK_HEADER.BLOCK_LENGTH ('.$BlockTypeText.') at offset '.$BlockOffset.' is zero bytes');
|
||||||
|
continue;
|
||||||
|
}
|
||||||
$this->error('METADATA_BLOCK_HEADER.BLOCK_LENGTH ('.$BlockLength.') at offset '.$BlockOffset.' is invalid');
|
$this->error('METADATA_BLOCK_HEADER.BLOCK_LENGTH ('.$BlockLength.') at offset '.$BlockOffset.' is invalid');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -167,7 +178,7 @@ class getid3_flac extends getid3_handler
|
||||||
if (isset($info['flac']['STREAMINFO']['audio_signature'])) {
|
if (isset($info['flac']['STREAMINFO']['audio_signature'])) {
|
||||||
|
|
||||||
if ($info['flac']['STREAMINFO']['audio_signature'] === str_repeat("\x00", 16)) {
|
if ($info['flac']['STREAMINFO']['audio_signature'] === str_repeat("\x00", 16)) {
|
||||||
$this->warning('FLAC STREAMINFO.audio_signature is null (known issue with libOggFLAC)');
|
$this->warning('FLAC STREAMINFO.audio_signature is null (known issue with libOggFLAC)');
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$info['md5_data_source'] = '';
|
$info['md5_data_source'] = '';
|
||||||
|
@ -194,12 +205,14 @@ class getid3_flac extends getid3_handler
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function parseSTREAMINFO($BlockData) {
|
|
||||||
$info = &$this->getid3->info;
|
|
||||||
|
|
||||||
$info['flac']['STREAMINFO'] = array();
|
|
||||||
$streaminfo = &$info['flac']['STREAMINFO'];
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $BlockData
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public static function parseSTREAMINFOdata($BlockData) {
|
||||||
|
$streaminfo = array();
|
||||||
$streaminfo['min_block_size'] = getid3_lib::BigEndian2Int(substr($BlockData, 0, 2));
|
$streaminfo['min_block_size'] = getid3_lib::BigEndian2Int(substr($BlockData, 0, 2));
|
||||||
$streaminfo['max_block_size'] = getid3_lib::BigEndian2Int(substr($BlockData, 2, 2));
|
$streaminfo['max_block_size'] = getid3_lib::BigEndian2Int(substr($BlockData, 2, 2));
|
||||||
$streaminfo['min_frame_size'] = getid3_lib::BigEndian2Int(substr($BlockData, 4, 3));
|
$streaminfo['min_frame_size'] = getid3_lib::BigEndian2Int(substr($BlockData, 4, 3));
|
||||||
|
@ -211,15 +224,28 @@ class getid3_flac extends getid3_handler
|
||||||
$streaminfo['bits_per_sample'] = getid3_lib::Bin2Dec(substr($SRCSBSS, 23, 5)) + 1;
|
$streaminfo['bits_per_sample'] = getid3_lib::Bin2Dec(substr($SRCSBSS, 23, 5)) + 1;
|
||||||
$streaminfo['samples_stream'] = getid3_lib::Bin2Dec(substr($SRCSBSS, 28, 36));
|
$streaminfo['samples_stream'] = getid3_lib::Bin2Dec(substr($SRCSBSS, 28, 36));
|
||||||
|
|
||||||
$streaminfo['audio_signature'] = substr($BlockData, 18, 16);
|
$streaminfo['audio_signature'] = substr($BlockData, 18, 16);
|
||||||
|
|
||||||
if (!empty($streaminfo['sample_rate'])) {
|
return $streaminfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $BlockData
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function parseSTREAMINFO($BlockData) {
|
||||||
|
$info = &$this->getid3->info;
|
||||||
|
|
||||||
|
$info['flac']['STREAMINFO'] = self::parseSTREAMINFOdata($BlockData);
|
||||||
|
|
||||||
|
if (!empty($info['flac']['STREAMINFO']['sample_rate'])) {
|
||||||
|
|
||||||
$info['audio']['bitrate_mode'] = 'vbr';
|
$info['audio']['bitrate_mode'] = 'vbr';
|
||||||
$info['audio']['sample_rate'] = $streaminfo['sample_rate'];
|
$info['audio']['sample_rate'] = $info['flac']['STREAMINFO']['sample_rate'];
|
||||||
$info['audio']['channels'] = $streaminfo['channels'];
|
$info['audio']['channels'] = $info['flac']['STREAMINFO']['channels'];
|
||||||
$info['audio']['bits_per_sample'] = $streaminfo['bits_per_sample'];
|
$info['audio']['bits_per_sample'] = $info['flac']['STREAMINFO']['bits_per_sample'];
|
||||||
$info['playtime_seconds'] = $streaminfo['samples_stream'] / $streaminfo['sample_rate'];
|
$info['playtime_seconds'] = $info['flac']['STREAMINFO']['samples_stream'] / $info['flac']['STREAMINFO']['sample_rate'];
|
||||||
if ($info['playtime_seconds'] > 0) {
|
if ($info['playtime_seconds'] > 0) {
|
||||||
if (!$this->isDependencyFor('matroska')) {
|
if (!$this->isDependencyFor('matroska')) {
|
||||||
$info['audio']['bitrate'] = (($info['avdataend'] - $info['avdataoffset']) * 8) / $info['playtime_seconds'];
|
$info['audio']['bitrate'] = (($info['avdataend'] - $info['avdataoffset']) * 8) / $info['playtime_seconds'];
|
||||||
|
@ -236,6 +262,11 @@ class getid3_flac extends getid3_handler
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $BlockData
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
private function parseAPPLICATION($BlockData) {
|
private function parseAPPLICATION($BlockData) {
|
||||||
$info = &$this->getid3->info;
|
$info = &$this->getid3->info;
|
||||||
|
|
||||||
|
@ -246,6 +277,11 @@ class getid3_flac extends getid3_handler
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $BlockData
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
private function parseSEEKTABLE($BlockData) {
|
private function parseSEEKTABLE($BlockData) {
|
||||||
$info = &$this->getid3->info;
|
$info = &$this->getid3->info;
|
||||||
|
|
||||||
|
@ -275,6 +311,11 @@ class getid3_flac extends getid3_handler
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $BlockData
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
private function parseVORBIS_COMMENT($BlockData) {
|
private function parseVORBIS_COMMENT($BlockData) {
|
||||||
$info = &$this->getid3->info;
|
$info = &$this->getid3->info;
|
||||||
|
|
||||||
|
@ -294,6 +335,11 @@ class getid3_flac extends getid3_handler
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $BlockData
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
private function parseCUESHEET($BlockData) {
|
private function parseCUESHEET($BlockData) {
|
||||||
$info = &$this->getid3->info;
|
$info = &$this->getid3->info;
|
||||||
$offset = 0;
|
$offset = 0;
|
||||||
|
@ -346,9 +392,11 @@ class getid3_flac extends getid3_handler
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse METADATA_BLOCK_PICTURE flac structure and extract attachment
|
* Parse METADATA_BLOCK_PICTURE flac structure and extract attachment
|
||||||
* External usage: audio.ogg
|
* External usage: audio.ogg
|
||||||
*/
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
public function parsePICTURE() {
|
public function parsePICTURE() {
|
||||||
$info = &$this->getid3->info;
|
$info = &$this->getid3->info;
|
||||||
|
|
||||||
|
@ -380,6 +428,11 @@ class getid3_flac extends getid3_handler
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $blocktype
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public static function metaBlockTypeLookup($blocktype) {
|
public static function metaBlockTypeLookup($blocktype) {
|
||||||
static $lookup = array(
|
static $lookup = array(
|
||||||
0 => 'STREAMINFO',
|
0 => 'STREAMINFO',
|
||||||
|
@ -393,6 +446,11 @@ class getid3_flac extends getid3_handler
|
||||||
return (isset($lookup[$blocktype]) ? $lookup[$blocktype] : 'reserved');
|
return (isset($lookup[$blocktype]) ? $lookup[$blocktype] : 'reserved');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $applicationid
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public static function applicationIDLookup($applicationid) {
|
public static function applicationIDLookup($applicationid) {
|
||||||
// http://flac.sourceforge.net/id.html
|
// http://flac.sourceforge.net/id.html
|
||||||
static $lookup = array(
|
static $lookup = array(
|
||||||
|
@ -423,6 +481,11 @@ class getid3_flac extends getid3_handler
|
||||||
return (isset($lookup[$applicationid]) ? $lookup[$applicationid] : 'reserved');
|
return (isset($lookup[$applicationid]) ? $lookup[$applicationid] : 'reserved');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $type_id
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public static function pictureTypeLookup($type_id) {
|
public static function pictureTypeLookup($type_id) {
|
||||||
static $lookup = array (
|
static $lookup = array (
|
||||||
0 => 'Other',
|
0 => 'Other',
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////
|
||||||
/// getID3() by James Heinrich <info@getid3.org> //
|
/// getID3() by James Heinrich <info@getid3.org> //
|
||||||
// available at http://getid3.sourceforge.net //
|
// available at https://github.com/JamesHeinrich/getID3 //
|
||||||
// or http://www.getid3.org //
|
// or https://www.getid3.org //
|
||||||
// also https://github.com/JamesHeinrich/getID3 //
|
// or http://getid3.sourceforge.net //
|
||||||
/////////////////////////////////////////////////////////////////
|
// see readme.txt for more details //
|
||||||
// See readme.txt for more details //
|
|
||||||
/////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////
|
||||||
// //
|
// //
|
||||||
// module.audio.mp3.php //
|
// module.audio.mp3.php //
|
||||||
|
@ -24,9 +24,17 @@ define('GETID3_MP3_VALID_CHECK_FRAMES', 35);
|
||||||
|
|
||||||
class getid3_mp3 extends getid3_handler
|
class getid3_mp3 extends getid3_handler
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Forces getID3() to scan the file byte-by-byte and log all the valid audio frame headers - extremely slow,
|
||||||
|
* unrecommended, but may provide data from otherwise-unusable files.
|
||||||
|
*
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
public $allow_bruteforce = false;
|
||||||
|
|
||||||
public $allow_bruteforce = false; // forces getID3() to scan the file byte-by-byte and log all the valid audio frame headers - extremely slow, unrecommended, but may provide data from otherwise-unusuable files
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
public function Analyze() {
|
public function Analyze() {
|
||||||
$info = &$this->getid3->info;
|
$info = &$this->getid3->info;
|
||||||
|
|
||||||
|
@ -35,7 +43,7 @@ class getid3_mp3 extends getid3_handler
|
||||||
if (!$this->getOnlyMPEGaudioInfo($info['avdataoffset'])) {
|
if (!$this->getOnlyMPEGaudioInfo($info['avdataoffset'])) {
|
||||||
if ($this->allow_bruteforce) {
|
if ($this->allow_bruteforce) {
|
||||||
$this->error('Rescanning file in BruteForce mode');
|
$this->error('Rescanning file in BruteForce mode');
|
||||||
$this->getOnlyMPEGaudioInfoBruteForce($this->getid3->fp, $info);
|
$this->getOnlyMPEGaudioInfoBruteForce();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,7 +160,11 @@ class getid3_mp3 extends getid3_handler
|
||||||
|
|
||||||
// Calculate playtime
|
// Calculate playtime
|
||||||
if (!isset($info['playtime_seconds']) && isset($info['audio']['bitrate']) && ($info['audio']['bitrate'] > 0)) {
|
if (!isset($info['playtime_seconds']) && isset($info['audio']['bitrate']) && ($info['audio']['bitrate'] > 0)) {
|
||||||
$info['playtime_seconds'] = ($info['avdataend'] - $info['avdataoffset']) * 8 / $info['audio']['bitrate'];
|
// https://github.com/JamesHeinrich/getID3/issues/161
|
||||||
|
// VBR header frame contains ~0.026s of silent audio data, but is not actually part of the original encoding and should be ignored
|
||||||
|
$xingVBRheaderFrameLength = ((isset($info['mpeg']['audio']['VBR_frames']) && isset($info['mpeg']['audio']['framelength'])) ? $info['mpeg']['audio']['framelength'] : 0);
|
||||||
|
|
||||||
|
$info['playtime_seconds'] = ($info['avdataend'] - $info['avdataoffset'] - $xingVBRheaderFrameLength) * 8 / $info['audio']['bitrate'];
|
||||||
}
|
}
|
||||||
|
|
||||||
$info['audio']['encoder_options'] = $this->GuessEncoderOptions();
|
$info['audio']['encoder_options'] = $this->GuessEncoderOptions();
|
||||||
|
@ -160,10 +172,14 @@ class getid3_mp3 extends getid3_handler
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public function GuessEncoderOptions() {
|
public function GuessEncoderOptions() {
|
||||||
// shortcuts
|
// shortcuts
|
||||||
$info = &$this->getid3->info;
|
$info = &$this->getid3->info;
|
||||||
|
$thisfile_mpeg_audio = array();
|
||||||
|
$thisfile_mpeg_audio_lame = array();
|
||||||
if (!empty($info['mpeg']['audio'])) {
|
if (!empty($info['mpeg']['audio'])) {
|
||||||
$thisfile_mpeg_audio = &$info['mpeg']['audio'];
|
$thisfile_mpeg_audio = &$info['mpeg']['audio'];
|
||||||
if (!empty($thisfile_mpeg_audio['LAME'])) {
|
if (!empty($thisfile_mpeg_audio['LAME'])) {
|
||||||
|
@ -178,7 +194,7 @@ class getid3_mp3 extends getid3_handler
|
||||||
|
|
||||||
$encoder_options = 'VBR q'.$thisfile_mpeg_audio['VBR_quality'];
|
$encoder_options = 'VBR q'.$thisfile_mpeg_audio['VBR_quality'];
|
||||||
|
|
||||||
} elseif (!empty($thisfile_mpeg_audio_lame['preset_used']) && (!in_array($thisfile_mpeg_audio_lame['preset_used_id'], $NamedPresetBitrates))) {
|
} elseif (!empty($thisfile_mpeg_audio_lame['preset_used']) && isset($thisfile_mpeg_audio_lame['preset_used_id']) && (!in_array($thisfile_mpeg_audio_lame['preset_used_id'], $NamedPresetBitrates))) {
|
||||||
|
|
||||||
$encoder_options = $thisfile_mpeg_audio_lame['preset_used'];
|
$encoder_options = $thisfile_mpeg_audio_lame['preset_used'];
|
||||||
|
|
||||||
|
@ -404,7 +420,15 @@ class getid3_mp3 extends getid3_handler
|
||||||
return $encoder_options;
|
return $encoder_options;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $offset
|
||||||
|
* @param array $info
|
||||||
|
* @param bool $recursivesearch
|
||||||
|
* @param bool $ScanAsCBR
|
||||||
|
* @param bool $FastMPEGheaderScan
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
public function decodeMPEGaudioHeader($offset, &$info, $recursivesearch=true, $ScanAsCBR=false, $FastMPEGheaderScan=false) {
|
public function decodeMPEGaudioHeader($offset, &$info, $recursivesearch=true, $ScanAsCBR=false, $FastMPEGheaderScan=false) {
|
||||||
static $MPEGaudioVersionLookup;
|
static $MPEGaudioVersionLookup;
|
||||||
static $MPEGaudioLayerLookup;
|
static $MPEGaudioLayerLookup;
|
||||||
|
@ -458,7 +482,6 @@ class getid3_mp3 extends getid3_handler
|
||||||
}
|
}
|
||||||
$thisfile_mpeg_audio = &$info['mpeg']['audio'];
|
$thisfile_mpeg_audio = &$info['mpeg']['audio'];
|
||||||
|
|
||||||
|
|
||||||
if ($MPEGaudioHeaderValidCache[$head4_key]) {
|
if ($MPEGaudioHeaderValidCache[$head4_key]) {
|
||||||
$thisfile_mpeg_audio['raw'] = $MPEGheaderRawArray;
|
$thisfile_mpeg_audio['raw'] = $MPEGheaderRawArray;
|
||||||
} else {
|
} else {
|
||||||
|
@ -562,7 +585,7 @@ class getid3_mp3 extends getid3_handler
|
||||||
|
|
||||||
$thisfile_mpeg_audio['bitrate_mode'] = 'vbr';
|
$thisfile_mpeg_audio['bitrate_mode'] = 'vbr';
|
||||||
$thisfile_mpeg_audio['VBR_method'] = 'Fraunhofer';
|
$thisfile_mpeg_audio['VBR_method'] = 'Fraunhofer';
|
||||||
$info['audio']['codec'] = 'Fraunhofer';
|
$info['audio']['codec'] = 'Fraunhofer';
|
||||||
|
|
||||||
$SideInfoData = substr($headerstring, 4 + 2, 32);
|
$SideInfoData = substr($headerstring, 4 + 2, 32);
|
||||||
|
|
||||||
|
@ -655,7 +678,7 @@ class getid3_mp3 extends getid3_handler
|
||||||
$used_filesize = $thisfile_mpeg_audio['VBR_bytes'];
|
$used_filesize = $thisfile_mpeg_audio['VBR_bytes'];
|
||||||
} elseif (!empty($info['filesize'])) {
|
} elseif (!empty($info['filesize'])) {
|
||||||
$used_filesize = $info['filesize'];
|
$used_filesize = $info['filesize'];
|
||||||
$used_filesize -= intval(@$info['id3v2']['headerlength']);
|
$used_filesize -= (isset($info['id3v2']['headerlength']) ? intval($info['id3v2']['headerlength']) : 0);
|
||||||
$used_filesize -= (isset($info['id3v1']) ? 128 : 0);
|
$used_filesize -= (isset($info['id3v1']) ? 128 : 0);
|
||||||
$used_filesize -= (isset($info['tag_offset_end']) ? $info['tag_offset_end'] - $info['tag_offset_start'] : 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');
|
$this->warning('MP3.Xing header missing VBR_bytes, assuming MPEG audio portion of file is '.number_format($used_filesize).' bytes');
|
||||||
|
@ -678,7 +701,7 @@ class getid3_mp3 extends getid3_handler
|
||||||
if ($thisfile_mpeg_audio['xing_flags']['toc']) {
|
if ($thisfile_mpeg_audio['xing_flags']['toc']) {
|
||||||
$LAMEtocData = substr($headerstring, $VBRidOffset + 16, 100);
|
$LAMEtocData = substr($headerstring, $VBRidOffset + 16, 100);
|
||||||
for ($i = 0; $i < 100; $i++) {
|
for ($i = 0; $i < 100; $i++) {
|
||||||
$thisfile_mpeg_audio['toc'][$i] = ord($LAMEtocData{$i});
|
$thisfile_mpeg_audio['toc'][$i] = ord($LAMEtocData[$i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($thisfile_mpeg_audio['xing_flags']['vbr_scale']) {
|
if ($thisfile_mpeg_audio['xing_flags']['vbr_scale']) {
|
||||||
|
@ -1083,6 +1106,13 @@ class getid3_mp3 extends getid3_handler
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $offset
|
||||||
|
* @param int $nextframetestoffset
|
||||||
|
* @param bool $ScanAsCBR
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
public function RecursiveFrameScanning(&$offset, &$nextframetestoffset, $ScanAsCBR) {
|
public function RecursiveFrameScanning(&$offset, &$nextframetestoffset, $ScanAsCBR) {
|
||||||
$info = &$this->getid3->info;
|
$info = &$this->getid3->info;
|
||||||
$firstframetestarray = array('error' => array(), 'warning'=> array(), 'avdataend' => $info['avdataend'], 'avdataoffset' => $info['avdataoffset']);
|
$firstframetestarray = array('error' => array(), 'warning'=> array(), 'avdataend' => $info['avdataend'], 'avdataoffset' => $info['avdataoffset']);
|
||||||
|
@ -1129,6 +1159,12 @@ class getid3_mp3 extends getid3_handler
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $offset
|
||||||
|
* @param bool $deepscan
|
||||||
|
*
|
||||||
|
* @return int|false
|
||||||
|
*/
|
||||||
public function FreeFormatFrameLength($offset, $deepscan=false) {
|
public function FreeFormatFrameLength($offset, $deepscan=false) {
|
||||||
$info = &$this->getid3->info;
|
$info = &$this->getid3->info;
|
||||||
|
|
||||||
|
@ -1137,9 +1173,9 @@ class getid3_mp3 extends getid3_handler
|
||||||
|
|
||||||
$SyncPattern1 = substr($MPEGaudioData, 0, 4);
|
$SyncPattern1 = substr($MPEGaudioData, 0, 4);
|
||||||
// may be different pattern due to padding
|
// may be different pattern due to padding
|
||||||
$SyncPattern2 = $SyncPattern1{0}.$SyncPattern1{1}.chr(ord($SyncPattern1{2}) | 0x02).$SyncPattern1{3};
|
$SyncPattern2 = $SyncPattern1[0].$SyncPattern1[1].chr(ord($SyncPattern1[2]) | 0x02).$SyncPattern1[3];
|
||||||
if ($SyncPattern2 === $SyncPattern1) {
|
if ($SyncPattern2 === $SyncPattern1) {
|
||||||
$SyncPattern2 = $SyncPattern1{0}.$SyncPattern1{1}.chr(ord($SyncPattern1{2}) & 0xFD).$SyncPattern1{3};
|
$SyncPattern2 = $SyncPattern1[0].$SyncPattern1[1].chr(ord($SyncPattern1[2]) & 0xFD).$SyncPattern1[3];
|
||||||
}
|
}
|
||||||
|
|
||||||
$framelength = false;
|
$framelength = false;
|
||||||
|
@ -1206,6 +1242,9 @@ class getid3_mp3 extends getid3_handler
|
||||||
return $framelength;
|
return $framelength;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
public function getOnlyMPEGaudioInfoBruteForce() {
|
public function getOnlyMPEGaudioInfoBruteForce() {
|
||||||
$MPEGaudioHeaderDecodeCache = array();
|
$MPEGaudioHeaderDecodeCache = array();
|
||||||
$MPEGaudioHeaderValidCache = array();
|
$MPEGaudioHeaderValidCache = array();
|
||||||
|
@ -1241,9 +1280,9 @@ class getid3_mp3 extends getid3_handler
|
||||||
if (strlen($head4) < 4) {
|
if (strlen($head4) < 4) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if ($head4{0} != "\xFF") {
|
if ($head4[0] != "\xFF") {
|
||||||
for ($i = 1; $i < 4; $i++) {
|
for ($i = 1; $i < 4; $i++) {
|
||||||
if ($head4{$i} == "\xFF") {
|
if ($head4[$i] == "\xFF") {
|
||||||
$this->fseek($i - 4, SEEK_CUR);
|
$this->fseek($i - 4, SEEK_CUR);
|
||||||
continue 2;
|
continue 2;
|
||||||
}
|
}
|
||||||
|
@ -1275,7 +1314,7 @@ class getid3_mp3 extends getid3_handler
|
||||||
$WhereWeWere = $this->ftell();
|
$WhereWeWere = $this->ftell();
|
||||||
$this->fseek($MPEGaudioHeaderLengthCache[$head4] - 4, SEEK_CUR);
|
$this->fseek($MPEGaudioHeaderLengthCache[$head4] - 4, SEEK_CUR);
|
||||||
$next4 = $this->fread(4);
|
$next4 = $this->fread(4);
|
||||||
if ($next4{0} == "\xFF") {
|
if ($next4[0] == "\xFF") {
|
||||||
if (!isset($MPEGaudioHeaderDecodeCache[$next4])) {
|
if (!isset($MPEGaudioHeaderDecodeCache[$next4])) {
|
||||||
$MPEGaudioHeaderDecodeCache[$next4] = self::MPEGaudioHeaderDecode($next4);
|
$MPEGaudioHeaderDecodeCache[$next4] = self::MPEGaudioHeaderDecode($next4);
|
||||||
}
|
}
|
||||||
|
@ -1353,7 +1392,12 @@ class getid3_mp3 extends getid3_handler
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $avdataoffset
|
||||||
|
* @param bool $BitrateHistogram
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
public function getOnlyMPEGaudioInfo($avdataoffset, $BitrateHistogram=false) {
|
public function getOnlyMPEGaudioInfo($avdataoffset, $BitrateHistogram=false) {
|
||||||
// looks for synch, decodes MPEG audio header
|
// looks for synch, decodes MPEG audio header
|
||||||
|
|
||||||
|
@ -1363,10 +1407,9 @@ class getid3_mp3 extends getid3_handler
|
||||||
static $MPEGaudioLayerLookup;
|
static $MPEGaudioLayerLookup;
|
||||||
static $MPEGaudioBitrateLookup;
|
static $MPEGaudioBitrateLookup;
|
||||||
if (empty($MPEGaudioVersionLookup)) {
|
if (empty($MPEGaudioVersionLookup)) {
|
||||||
$MPEGaudioVersionLookup = self::MPEGaudioVersionArray();
|
$MPEGaudioVersionLookup = self::MPEGaudioVersionArray();
|
||||||
$MPEGaudioLayerLookup = self::MPEGaudioLayerArray();
|
$MPEGaudioLayerLookup = self::MPEGaudioLayerArray();
|
||||||
$MPEGaudioBitrateLookup = self::MPEGaudioBitrateArray();
|
$MPEGaudioBitrateLookup = self::MPEGaudioBitrateArray();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->fseek($avdataoffset);
|
$this->fseek($avdataoffset);
|
||||||
|
@ -1416,7 +1459,8 @@ class getid3_mp3 extends getid3_handler
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (($header{$SynchSeekOffset} == "\xFF") && ($header{($SynchSeekOffset + 1)} > "\xE0")) { // synch detected
|
if (($header[$SynchSeekOffset] == "\xFF") && ($header[($SynchSeekOffset + 1)] > "\xE0")) { // synch detected
|
||||||
|
$FirstFrameAVDataOffset = null;
|
||||||
if (!isset($FirstFrameThisfileInfo) && !isset($info['mpeg']['audio'])) {
|
if (!isset($FirstFrameThisfileInfo) && !isset($info['mpeg']['audio'])) {
|
||||||
$FirstFrameThisfileInfo = $info;
|
$FirstFrameThisfileInfo = $info;
|
||||||
$FirstFrameAVDataOffset = $avdataoffset + $SynchSeekOffset;
|
$FirstFrameAVDataOffset = $avdataoffset + $SynchSeekOffset;
|
||||||
|
@ -1440,7 +1484,7 @@ class getid3_mp3 extends getid3_handler
|
||||||
$info['audio']['dataformat'] = 'mp3';
|
$info['audio']['dataformat'] = 'mp3';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (isset($FirstFrameThisfileInfo['mpeg']['audio']['bitrate_mode']) && ($FirstFrameThisfileInfo['mpeg']['audio']['bitrate_mode'] == 'vbr')) {
|
if (isset($FirstFrameThisfileInfo) && isset($FirstFrameThisfileInfo['mpeg']['audio']['bitrate_mode']) && ($FirstFrameThisfileInfo['mpeg']['audio']['bitrate_mode'] == 'vbr')) {
|
||||||
if (!(abs($info['audio']['bitrate'] - $FirstFrameThisfileInfo['audio']['bitrate']) <= 1)) {
|
if (!(abs($info['audio']['bitrate'] - $FirstFrameThisfileInfo['audio']['bitrate']) <= 1)) {
|
||||||
// If there is garbage data between a valid VBR header frame and a sequence
|
// If there is garbage data between a valid VBR header frame and a sequence
|
||||||
// of valid MPEG-audio frames the VBR data is no longer discarded.
|
// of valid MPEG-audio frames the VBR data is no longer discarded.
|
||||||
|
@ -1510,7 +1554,7 @@ class getid3_mp3 extends getid3_handler
|
||||||
$this->fseek($scan_start_offset[$current_segment]);
|
$this->fseek($scan_start_offset[$current_segment]);
|
||||||
$buffer_4k = $this->fread(4096);
|
$buffer_4k = $this->fread(4096);
|
||||||
for ($j = 0; $j < (strlen($buffer_4k) - 4); $j++) {
|
for ($j = 0; $j < (strlen($buffer_4k) - 4); $j++) {
|
||||||
if (($buffer_4k{$j} == "\xFF") && ($buffer_4k{($j + 1)} > "\xE0")) { // synch detected
|
if (($buffer_4k[$j] == "\xFF") && ($buffer_4k[($j + 1)] > "\xE0")) { // synch detected
|
||||||
if ($this->decodeMPEGaudioHeader($scan_start_offset[$current_segment] + $j, $dummy, false, false, $FastMode)) {
|
if ($this->decodeMPEGaudioHeader($scan_start_offset[$current_segment] + $j, $dummy, false, false, $FastMode)) {
|
||||||
$calculated_next_offset = $scan_start_offset[$current_segment] + $j + $dummy['mpeg']['audio']['framelength'];
|
$calculated_next_offset = $scan_start_offset[$current_segment] + $j + $dummy['mpeg']['audio']['framelength'];
|
||||||
if ($this->decodeMPEGaudioHeader($calculated_next_offset, $dummy, false, false, $FastMode)) {
|
if ($this->decodeMPEGaudioHeader($calculated_next_offset, $dummy, false, false, $FastMode)) {
|
||||||
|
@ -1522,7 +1566,7 @@ class getid3_mp3 extends getid3_handler
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$synchstartoffset = $scan_start_offset[$current_segment];
|
$synchstartoffset = $scan_start_offset[$current_segment];
|
||||||
while ($this->decodeMPEGaudioHeader($synchstartoffset, $dummy, false, false, $FastMode)) {
|
while (($synchstartoffset < $info['avdataend']) && $this->decodeMPEGaudioHeader($synchstartoffset, $dummy, false, false, $FastMode)) {
|
||||||
$FastMode = true;
|
$FastMode = true;
|
||||||
$thisframebitrate = $MPEGaudioBitrateLookup[$MPEGaudioVersionLookup[$dummy['mpeg']['audio']['raw']['version']]][$MPEGaudioLayerLookup[$dummy['mpeg']['audio']['raw']['layer']]][$dummy['mpeg']['audio']['raw']['bitrate']];
|
$thisframebitrate = $MPEGaudioBitrateLookup[$MPEGaudioVersionLookup[$dummy['mpeg']['audio']['raw']['version']]][$MPEGaudioLayerLookup[$dummy['mpeg']['audio']['raw']['layer']]][$dummy['mpeg']['audio']['raw']['bitrate']];
|
||||||
|
|
||||||
|
@ -1633,17 +1677,25 @@ class getid3_mp3 extends getid3_handler
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
public static function MPEGaudioVersionArray() {
|
public static function MPEGaudioVersionArray() {
|
||||||
static $MPEGaudioVersion = array('2.5', false, '2', '1');
|
static $MPEGaudioVersion = array('2.5', false, '2', '1');
|
||||||
return $MPEGaudioVersion;
|
return $MPEGaudioVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
public static function MPEGaudioLayerArray() {
|
public static function MPEGaudioLayerArray() {
|
||||||
static $MPEGaudioLayer = array(false, 3, 2, 1);
|
static $MPEGaudioLayer = array(false, 3, 2, 1);
|
||||||
return $MPEGaudioLayer;
|
return $MPEGaudioLayer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
public static function MPEGaudioBitrateArray() {
|
public static function MPEGaudioBitrateArray() {
|
||||||
static $MPEGaudioBitrate;
|
static $MPEGaudioBitrate;
|
||||||
if (empty($MPEGaudioBitrate)) {
|
if (empty($MPEGaudioBitrate)) {
|
||||||
|
@ -1663,6 +1715,9 @@ class getid3_mp3 extends getid3_handler
|
||||||
return $MPEGaudioBitrate;
|
return $MPEGaudioBitrate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
public static function MPEGaudioFrequencyArray() {
|
public static function MPEGaudioFrequencyArray() {
|
||||||
static $MPEGaudioFrequency;
|
static $MPEGaudioFrequency;
|
||||||
if (empty($MPEGaudioFrequency)) {
|
if (empty($MPEGaudioFrequency)) {
|
||||||
|
@ -1675,11 +1730,17 @@ class getid3_mp3 extends getid3_handler
|
||||||
return $MPEGaudioFrequency;
|
return $MPEGaudioFrequency;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
public static function MPEGaudioChannelModeArray() {
|
public static function MPEGaudioChannelModeArray() {
|
||||||
static $MPEGaudioChannelMode = array('stereo', 'joint stereo', 'dual channel', 'mono');
|
static $MPEGaudioChannelMode = array('stereo', 'joint stereo', 'dual channel', 'mono');
|
||||||
return $MPEGaudioChannelMode;
|
return $MPEGaudioChannelMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
public static function MPEGaudioModeExtensionArray() {
|
public static function MPEGaudioModeExtensionArray() {
|
||||||
static $MPEGaudioModeExtension;
|
static $MPEGaudioModeExtension;
|
||||||
if (empty($MPEGaudioModeExtension)) {
|
if (empty($MPEGaudioModeExtension)) {
|
||||||
|
@ -1692,15 +1753,31 @@ class getid3_mp3 extends getid3_handler
|
||||||
return $MPEGaudioModeExtension;
|
return $MPEGaudioModeExtension;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
public static function MPEGaudioEmphasisArray() {
|
public static function MPEGaudioEmphasisArray() {
|
||||||
static $MPEGaudioEmphasis = array('none', '50/15ms', false, 'CCIT J.17');
|
static $MPEGaudioEmphasis = array('none', '50/15ms', false, 'CCIT J.17');
|
||||||
return $MPEGaudioEmphasis;
|
return $MPEGaudioEmphasis;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $head4
|
||||||
|
* @param bool $allowBitrate15
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
public static function MPEGaudioHeaderBytesValid($head4, $allowBitrate15=false) {
|
public static function MPEGaudioHeaderBytesValid($head4, $allowBitrate15=false) {
|
||||||
return self::MPEGaudioHeaderValid(self::MPEGaudioHeaderDecode($head4), false, $allowBitrate15);
|
return self::MPEGaudioHeaderValid(self::MPEGaudioHeaderDecode($head4), false, $allowBitrate15);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $rawarray
|
||||||
|
* @param bool $echoerrors
|
||||||
|
* @param bool $allowBitrate15
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
public static function MPEGaudioHeaderValid($rawarray, $echoerrors=false, $allowBitrate15=false) {
|
public static function MPEGaudioHeaderValid($rawarray, $echoerrors=false, $allowBitrate15=false) {
|
||||||
if (($rawarray['synch'] & 0x0FFE) != 0x0FFE) {
|
if (($rawarray['synch'] & 0x0FFE) != 0x0FFE) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -1773,6 +1850,11 @@ class getid3_mp3 extends getid3_handler
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $Header4Bytes
|
||||||
|
*
|
||||||
|
* @return array|false
|
||||||
|
*/
|
||||||
public static function MPEGaudioHeaderDecode($Header4Bytes) {
|
public static function MPEGaudioHeaderDecode($Header4Bytes) {
|
||||||
// AAAA AAAA AAAB BCCD EEEE FFGH IIJJ KLMM
|
// AAAA AAAA AAAB BCCD EEEE FFGH IIJJ KLMM
|
||||||
// A - Frame sync (all bits set)
|
// A - Frame sync (all bits set)
|
||||||
|
@ -1794,22 +1876,31 @@ class getid3_mp3 extends getid3_handler
|
||||||
}
|
}
|
||||||
|
|
||||||
$MPEGrawHeader['synch'] = (getid3_lib::BigEndian2Int(substr($Header4Bytes, 0, 2)) & 0xFFE0) >> 4;
|
$MPEGrawHeader['synch'] = (getid3_lib::BigEndian2Int(substr($Header4Bytes, 0, 2)) & 0xFFE0) >> 4;
|
||||||
$MPEGrawHeader['version'] = (ord($Header4Bytes{1}) & 0x18) >> 3; // BB
|
$MPEGrawHeader['version'] = (ord($Header4Bytes[1]) & 0x18) >> 3; // BB
|
||||||
$MPEGrawHeader['layer'] = (ord($Header4Bytes{1}) & 0x06) >> 1; // CC
|
$MPEGrawHeader['layer'] = (ord($Header4Bytes[1]) & 0x06) >> 1; // CC
|
||||||
$MPEGrawHeader['protection'] = (ord($Header4Bytes{1}) & 0x01); // D
|
$MPEGrawHeader['protection'] = (ord($Header4Bytes[1]) & 0x01); // D
|
||||||
$MPEGrawHeader['bitrate'] = (ord($Header4Bytes{2}) & 0xF0) >> 4; // EEEE
|
$MPEGrawHeader['bitrate'] = (ord($Header4Bytes[2]) & 0xF0) >> 4; // EEEE
|
||||||
$MPEGrawHeader['sample_rate'] = (ord($Header4Bytes{2}) & 0x0C) >> 2; // FF
|
$MPEGrawHeader['sample_rate'] = (ord($Header4Bytes[2]) & 0x0C) >> 2; // FF
|
||||||
$MPEGrawHeader['padding'] = (ord($Header4Bytes{2}) & 0x02) >> 1; // G
|
$MPEGrawHeader['padding'] = (ord($Header4Bytes[2]) & 0x02) >> 1; // G
|
||||||
$MPEGrawHeader['private'] = (ord($Header4Bytes{2}) & 0x01); // H
|
$MPEGrawHeader['private'] = (ord($Header4Bytes[2]) & 0x01); // H
|
||||||
$MPEGrawHeader['channelmode'] = (ord($Header4Bytes{3}) & 0xC0) >> 6; // II
|
$MPEGrawHeader['channelmode'] = (ord($Header4Bytes[3]) & 0xC0) >> 6; // II
|
||||||
$MPEGrawHeader['modeextension'] = (ord($Header4Bytes{3}) & 0x30) >> 4; // JJ
|
$MPEGrawHeader['modeextension'] = (ord($Header4Bytes[3]) & 0x30) >> 4; // JJ
|
||||||
$MPEGrawHeader['copyright'] = (ord($Header4Bytes{3}) & 0x08) >> 3; // K
|
$MPEGrawHeader['copyright'] = (ord($Header4Bytes[3]) & 0x08) >> 3; // K
|
||||||
$MPEGrawHeader['original'] = (ord($Header4Bytes{3}) & 0x04) >> 2; // L
|
$MPEGrawHeader['original'] = (ord($Header4Bytes[3]) & 0x04) >> 2; // L
|
||||||
$MPEGrawHeader['emphasis'] = (ord($Header4Bytes{3}) & 0x03); // MM
|
$MPEGrawHeader['emphasis'] = (ord($Header4Bytes[3]) & 0x03); // MM
|
||||||
|
|
||||||
return $MPEGrawHeader;
|
return $MPEGrawHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int|string $bitrate
|
||||||
|
* @param string $version
|
||||||
|
* @param string $layer
|
||||||
|
* @param bool $padding
|
||||||
|
* @param int $samplerate
|
||||||
|
*
|
||||||
|
* @return int|false
|
||||||
|
*/
|
||||||
public static function MPEGaudioFrameLength(&$bitrate, &$version, &$layer, $padding, &$samplerate) {
|
public static function MPEGaudioFrameLength(&$bitrate, &$version, &$layer, $padding, &$samplerate) {
|
||||||
static $AudioFrameLengthCache = array();
|
static $AudioFrameLengthCache = array();
|
||||||
|
|
||||||
|
@ -1871,6 +1962,11 @@ class getid3_mp3 extends getid3_handler
|
||||||
return $AudioFrameLengthCache[$bitrate][$version][$layer][$padding][$samplerate];
|
return $AudioFrameLengthCache[$bitrate][$version][$layer][$padding][$samplerate];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param float|int $bit_rate
|
||||||
|
*
|
||||||
|
* @return int|float|string
|
||||||
|
*/
|
||||||
public static function ClosestStandardMP3Bitrate($bit_rate) {
|
public static function ClosestStandardMP3Bitrate($bit_rate) {
|
||||||
static $standard_bit_rates = array (320000, 256000, 224000, 192000, 160000, 128000, 112000, 96000, 80000, 64000, 56000, 48000, 40000, 32000, 24000, 16000, 8000);
|
static $standard_bit_rates = array (320000, 256000, 224000, 192000, 160000, 128000, 112000, 96000, 80000, 64000, 56000, 48000, 40000, 32000, 24000, 16000, 8000);
|
||||||
static $bit_rate_table = array (0=>'-');
|
static $bit_rate_table = array (0=>'-');
|
||||||
|
@ -1891,10 +1987,16 @@ class getid3_mp3 extends getid3_handler
|
||||||
return $bit_rate_table[$round_bit_rate];
|
return $bit_rate_table[$round_bit_rate];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $version
|
||||||
|
* @param string $channelmode
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
public static function XingVBRidOffset($version, $channelmode) {
|
public static function XingVBRidOffset($version, $channelmode) {
|
||||||
static $XingVBRidOffsetCache = array();
|
static $XingVBRidOffsetCache = array();
|
||||||
if (empty($XingVBRidOffset)) {
|
if (empty($XingVBRidOffsetCache)) {
|
||||||
$XingVBRidOffset = array (
|
$XingVBRidOffsetCache = array (
|
||||||
'1' => array ('mono' => 0x15, // 4 + 17 = 21
|
'1' => array ('mono' => 0x15, // 4 + 17 = 21
|
||||||
'stereo' => 0x24, // 4 + 32 = 36
|
'stereo' => 0x24, // 4 + 32 = 36
|
||||||
'joint stereo' => 0x24,
|
'joint stereo' => 0x24,
|
||||||
|
@ -1914,9 +2016,14 @@ class getid3_mp3 extends getid3_handler
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return $XingVBRidOffset[$version][$channelmode];
|
return $XingVBRidOffsetCache[$version][$channelmode];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $VBRmethodID
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public static function LAMEvbrMethodLookup($VBRmethodID) {
|
public static function LAMEvbrMethodLookup($VBRmethodID) {
|
||||||
static $LAMEvbrMethodLookup = array(
|
static $LAMEvbrMethodLookup = array(
|
||||||
0x00 => 'unknown',
|
0x00 => 'unknown',
|
||||||
|
@ -1933,6 +2040,11 @@ class getid3_mp3 extends getid3_handler
|
||||||
return (isset($LAMEvbrMethodLookup[$VBRmethodID]) ? $LAMEvbrMethodLookup[$VBRmethodID] : '');
|
return (isset($LAMEvbrMethodLookup[$VBRmethodID]) ? $LAMEvbrMethodLookup[$VBRmethodID] : '');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $StereoModeID
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public static function LAMEmiscStereoModeLookup($StereoModeID) {
|
public static function LAMEmiscStereoModeLookup($StereoModeID) {
|
||||||
static $LAMEmiscStereoModeLookup = array(
|
static $LAMEmiscStereoModeLookup = array(
|
||||||
0 => 'mono',
|
0 => 'mono',
|
||||||
|
@ -1947,6 +2059,11 @@ class getid3_mp3 extends getid3_handler
|
||||||
return (isset($LAMEmiscStereoModeLookup[$StereoModeID]) ? $LAMEmiscStereoModeLookup[$StereoModeID] : '');
|
return (isset($LAMEmiscStereoModeLookup[$StereoModeID]) ? $LAMEmiscStereoModeLookup[$StereoModeID] : '');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $SourceSampleFrequencyID
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public static function LAMEmiscSourceSampleFrequencyLookup($SourceSampleFrequencyID) {
|
public static function LAMEmiscSourceSampleFrequencyLookup($SourceSampleFrequencyID) {
|
||||||
static $LAMEmiscSourceSampleFrequencyLookup = array(
|
static $LAMEmiscSourceSampleFrequencyLookup = array(
|
||||||
0 => '<= 32 kHz',
|
0 => '<= 32 kHz',
|
||||||
|
@ -1957,6 +2074,11 @@ class getid3_mp3 extends getid3_handler
|
||||||
return (isset($LAMEmiscSourceSampleFrequencyLookup[$SourceSampleFrequencyID]) ? $LAMEmiscSourceSampleFrequencyLookup[$SourceSampleFrequencyID] : '');
|
return (isset($LAMEmiscSourceSampleFrequencyLookup[$SourceSampleFrequencyID]) ? $LAMEmiscSourceSampleFrequencyLookup[$SourceSampleFrequencyID] : '');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $SurroundInfoID
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public static function LAMEsurroundInfoLookup($SurroundInfoID) {
|
public static function LAMEsurroundInfoLookup($SurroundInfoID) {
|
||||||
static $LAMEsurroundInfoLookup = array(
|
static $LAMEsurroundInfoLookup = array(
|
||||||
0 => 'no surround info',
|
0 => 'no surround info',
|
||||||
|
@ -1967,6 +2089,11 @@ class getid3_mp3 extends getid3_handler
|
||||||
return (isset($LAMEsurroundInfoLookup[$SurroundInfoID]) ? $LAMEsurroundInfoLookup[$SurroundInfoID] : 'reserved');
|
return (isset($LAMEsurroundInfoLookup[$SurroundInfoID]) ? $LAMEsurroundInfoLookup[$SurroundInfoID] : 'reserved');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $LAMEtag
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public static function LAMEpresetUsedLookup($LAMEtag) {
|
public static function LAMEpresetUsedLookup($LAMEtag) {
|
||||||
|
|
||||||
if ($LAMEtag['preset_used_id'] == 0) {
|
if ($LAMEtag['preset_used_id'] == 0) {
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////
|
||||||
/// getID3() by James Heinrich <info@getid3.org> //
|
/// getID3() by James Heinrich <info@getid3.org> //
|
||||||
// available at http://getid3.sourceforge.net //
|
// available at https://github.com/JamesHeinrich/getID3 //
|
||||||
// or http://www.getid3.org //
|
// or https://www.getid3.org //
|
||||||
// also https://github.com/JamesHeinrich/getID3 //
|
// or http://getid3.sourceforge.net //
|
||||||
/////////////////////////////////////////////////////////////////
|
// see readme.txt for more details //
|
||||||
// See readme.txt for more details //
|
|
||||||
/////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////
|
||||||
// //
|
// //
|
||||||
// module.audio.ogg.php //
|
// module.audio.ogg.php //
|
||||||
|
@ -18,7 +18,11 @@ getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.flac.php', __FILE
|
||||||
|
|
||||||
class getid3_ogg extends getid3_handler
|
class getid3_ogg extends getid3_handler
|
||||||
{
|
{
|
||||||
// http://xiph.org/vorbis/doc/Vorbis_I_spec.html
|
/**
|
||||||
|
* @link http://xiph.org/vorbis/doc/Vorbis_I_spec.html
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
public function Analyze() {
|
public function Analyze() {
|
||||||
$info = &$this->getid3->info;
|
$info = &$this->getid3->info;
|
||||||
|
|
||||||
|
@ -65,7 +69,7 @@ class getid3_ogg extends getid3_handler
|
||||||
|
|
||||||
} elseif (substr($filedata, 0, 8) == 'OpusHead') {
|
} elseif (substr($filedata, 0, 8) == 'OpusHead') {
|
||||||
|
|
||||||
if( $this->ParseOpusPageHeader($filedata, $filedataoffset, $oggpageinfo) == false ) {
|
if ($this->ParseOpusPageHeader($filedata, $filedataoffset, $oggpageinfo) === false) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,7 +183,7 @@ class getid3_ogg extends getid3_handler
|
||||||
if ($info['ogg']['pageheader']['theora']['pixel_aspect_denominator'] > 0) {
|
if ($info['ogg']['pageheader']['theora']['pixel_aspect_denominator'] > 0) {
|
||||||
$info['video']['pixel_aspect_ratio'] = (float) $info['ogg']['pageheader']['theora']['pixel_aspect_numerator'] / $info['ogg']['pageheader']['theora']['pixel_aspect_denominator'];
|
$info['video']['pixel_aspect_ratio'] = (float) $info['ogg']['pageheader']['theora']['pixel_aspect_numerator'] / $info['ogg']['pageheader']['theora']['pixel_aspect_denominator'];
|
||||||
}
|
}
|
||||||
$this->warning('Ogg Theora (v3) not fully supported in this version of getID3 ['.$this->getid3->version().'] -- bitrate, playtime and all audio data are currently unavailable');
|
$this->warning('Ogg Theora (v3) not fully supported in this version of getID3 ['.$this->getid3->version().'] -- bitrate, playtime and all audio data are currently unavailable');
|
||||||
|
|
||||||
|
|
||||||
} elseif (substr($filedata, 0, 8) == "fishead\x00") {
|
} elseif (substr($filedata, 0, 8) == "fishead\x00") {
|
||||||
|
@ -259,9 +263,34 @@ $this->warning('Ogg Theora (v3) not fully supported in this version of getID3 ['
|
||||||
$this->error('Ogg Skeleton not correctly handled in this version of getID3 ['.$this->getid3->version().']');
|
$this->error('Ogg Skeleton not correctly handled in this version of getID3 ['.$this->getid3->version().']');
|
||||||
//return false;
|
//return false;
|
||||||
|
|
||||||
|
} elseif (substr($filedata, 0, 5) == "\x7F".'FLAC') {
|
||||||
|
// https://xiph.org/flac/ogg_mapping.html
|
||||||
|
|
||||||
|
$info['audio']['dataformat'] = 'flac';
|
||||||
|
$info['audio']['bitrate_mode'] = 'vbr';
|
||||||
|
$info['audio']['lossless'] = true;
|
||||||
|
|
||||||
|
$info['ogg']['flac']['header']['version_major'] = ord(substr($filedata, 5, 1));
|
||||||
|
$info['ogg']['flac']['header']['version_minor'] = ord(substr($filedata, 6, 1));
|
||||||
|
$info['ogg']['flac']['header']['header_packets'] = getid3_lib::BigEndian2Int(substr($filedata, 7, 2)) + 1; // "A two-byte, big-endian binary number signifying the number of header (non-audio) packets, not including this one. This number may be zero (0x0000) to signify 'unknown' but be aware that some decoders may not be able to handle such streams."
|
||||||
|
$info['ogg']['flac']['header']['magic'] = substr($filedata, 9, 4);
|
||||||
|
if ($info['ogg']['flac']['header']['magic'] != 'fLaC') {
|
||||||
|
$this->error('Ogg-FLAC expecting "fLaC", found "'.$info['ogg']['flac']['header']['magic'].'" ('.trim(getid3_lib::PrintHexBytes($info['ogg']['flac']['header']['magic'])).')');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$info['ogg']['flac']['header']['STREAMINFO_bytes'] = getid3_lib::BigEndian2Int(substr($filedata, 13, 4));
|
||||||
|
$info['flac']['STREAMINFO'] = getid3_flac::parseSTREAMINFOdata(substr($filedata, 17, 34));
|
||||||
|
if (!empty($info['flac']['STREAMINFO']['sample_rate'])) {
|
||||||
|
$info['audio']['bitrate_mode'] = 'vbr';
|
||||||
|
$info['audio']['sample_rate'] = $info['flac']['STREAMINFO']['sample_rate'];
|
||||||
|
$info['audio']['channels'] = $info['flac']['STREAMINFO']['channels'];
|
||||||
|
$info['audio']['bits_per_sample'] = $info['flac']['STREAMINFO']['bits_per_sample'];
|
||||||
|
$info['playtime_seconds'] = $info['flac']['STREAMINFO']['samples_stream'] / $info['flac']['STREAMINFO']['sample_rate'];
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
$this->error('Expecting either "Speex ", "OpusHead" or "vorbis" identifier strings, found "'.substr($filedata, 0, 8).'"');
|
$this->error('Expecting one of "vorbis", "Speex", "OpusHead", "vorbis", "fishhead", "theora", "fLaC" identifier strings, found "'.substr($filedata, 0, 8).'"');
|
||||||
unset($info['ogg']);
|
unset($info['ogg']);
|
||||||
unset($info['mime_type']);
|
unset($info['mime_type']);
|
||||||
return false;
|
return false;
|
||||||
|
@ -378,6 +407,13 @@ $this->warning('Ogg Theora (v3) not fully supported in this version of getID3 ['
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $filedata
|
||||||
|
* @param int $filedataoffset
|
||||||
|
* @param array $oggpageinfo
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
public function ParseVorbisPageHeader(&$filedata, &$filedataoffset, &$oggpageinfo) {
|
public function ParseVorbisPageHeader(&$filedata, &$filedataoffset, &$oggpageinfo) {
|
||||||
$info = &$this->getid3->info;
|
$info = &$this->getid3->info;
|
||||||
$info['audio']['dataformat'] = 'vorbis';
|
$info['audio']['dataformat'] = 'vorbis';
|
||||||
|
@ -426,7 +462,15 @@ $this->warning('Ogg Theora (v3) not fully supported in this version of getID3 ['
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// http://tools.ietf.org/html/draft-ietf-codec-oggopus-03
|
/**
|
||||||
|
* @link http://tools.ietf.org/html/draft-ietf-codec-oggopus-03
|
||||||
|
*
|
||||||
|
* @param string $filedata
|
||||||
|
* @param int $filedataoffset
|
||||||
|
* @param array $oggpageinfo
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
public function ParseOpusPageHeader(&$filedata, &$filedataoffset, &$oggpageinfo) {
|
public function ParseOpusPageHeader(&$filedata, &$filedataoffset, &$oggpageinfo) {
|
||||||
$info = &$this->getid3->info;
|
$info = &$this->getid3->info;
|
||||||
$info['audio']['dataformat'] = 'opus';
|
$info['audio']['dataformat'] = 'opus';
|
||||||
|
@ -458,7 +502,7 @@ $this->warning('Ogg Theora (v3) not fully supported in this version of getID3 ['
|
||||||
$info['ogg']['pageheader']['opus']['pre_skip'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 2));
|
$info['ogg']['pageheader']['opus']['pre_skip'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 2));
|
||||||
$filedataoffset += 2;
|
$filedataoffset += 2;
|
||||||
|
|
||||||
$info['ogg']['pageheader']['opus']['sample_rate'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
|
$info['ogg']['pageheader']['opus']['input_sample_rate'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
|
||||||
$filedataoffset += 4;
|
$filedataoffset += 4;
|
||||||
|
|
||||||
//$info['ogg']['pageheader']['opus']['output_gain'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 2));
|
//$info['ogg']['pageheader']['opus']['output_gain'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 2));
|
||||||
|
@ -467,16 +511,19 @@ $this->warning('Ogg Theora (v3) not fully supported in this version of getID3 ['
|
||||||
//$info['ogg']['pageheader']['opus']['channel_mapping_family'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 1));
|
//$info['ogg']['pageheader']['opus']['channel_mapping_family'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 1));
|
||||||
//$filedataoffset += 1;
|
//$filedataoffset += 1;
|
||||||
|
|
||||||
$info['opus']['opus_version'] = $info['ogg']['pageheader']['opus']['version'];
|
$info['opus']['opus_version'] = $info['ogg']['pageheader']['opus']['version'];
|
||||||
$info['opus']['sample_rate'] = $info['ogg']['pageheader']['opus']['sample_rate'];
|
$info['opus']['sample_rate_input'] = $info['ogg']['pageheader']['opus']['input_sample_rate'];
|
||||||
$info['opus']['out_channel_count'] = $info['ogg']['pageheader']['opus']['out_channel_count'];
|
$info['opus']['out_channel_count'] = $info['ogg']['pageheader']['opus']['out_channel_count'];
|
||||||
|
|
||||||
$info['audio']['channels'] = $info['opus']['out_channel_count'];
|
$info['audio']['channels'] = $info['opus']['out_channel_count'];
|
||||||
$info['audio']['sample_rate'] = $info['opus']['sample_rate'];
|
$info['audio']['sample_rate_input'] = $info['opus']['sample_rate_input'];
|
||||||
|
$info['audio']['sample_rate'] = 48000; // "All Opus audio is coded at 48 kHz, and should also be decoded at 48 kHz for playback (unless the target hardware does not support this sampling rate). However, this field may be used to resample the audio back to the original sampling rate, for example, when saving the output to a file." -- https://mf4.xiph.org/jenkins/view/opus/job/opusfile-unix/ws/doc/html/structOpusHead.html
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array|false
|
||||||
|
*/
|
||||||
public function ParseOggPageHeader() {
|
public function ParseOggPageHeader() {
|
||||||
// http://xiph.org/ogg/vorbis/doc/framing.html
|
// http://xiph.org/ogg/vorbis/doc/framing.html
|
||||||
$oggheader['page_start_offset'] = $this->ftell(); // where we started from in the file
|
$oggheader['page_start_offset'] = $this->ftell(); // where we started from in the file
|
||||||
|
@ -489,7 +536,7 @@ $this->warning('Ogg Theora (v3) not fully supported in this version of getID3 ['
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if ((($filedataoffset + 28) > strlen($filedata)) || (strlen($filedata) < 28)) {
|
if ((($filedataoffset + 28) > strlen($filedata)) || (strlen($filedata) < 28)) {
|
||||||
if ($this->feof() || (($filedata .= $this->fread($this->getid3->fread_buffer_size())) === false)) {
|
if ($this->feof() || (($filedata .= $this->fread($this->getid3->fread_buffer_size())) === '')) {
|
||||||
// get some more data, unless eof, in which case fail
|
// get some more data, unless eof, in which case fail
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -528,13 +575,19 @@ $this->warning('Ogg Theora (v3) not fully supported in this version of getID3 ['
|
||||||
return $oggheader;
|
return $oggheader;
|
||||||
}
|
}
|
||||||
|
|
||||||
// http://xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-810005
|
/**
|
||||||
|
* @link http://xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-810005
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
public function ParseVorbisComments() {
|
public function ParseVorbisComments() {
|
||||||
$info = &$this->getid3->info;
|
$info = &$this->getid3->info;
|
||||||
|
|
||||||
$OriginalOffset = $this->ftell();
|
$OriginalOffset = $this->ftell();
|
||||||
|
$commentdata = null;
|
||||||
$commentdataoffset = 0;
|
$commentdataoffset = 0;
|
||||||
$VorbisCommentPage = 1;
|
$VorbisCommentPage = 1;
|
||||||
|
$CommentStartOffset = 0;
|
||||||
|
|
||||||
switch ($info['audio']['dataformat']) {
|
switch ($info['audio']['dataformat']) {
|
||||||
case 'vorbis':
|
case 'vorbis':
|
||||||
|
@ -765,6 +818,11 @@ $this->warning('Ogg Theora (v3) not fully supported in this version of getID3 ['
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $mode
|
||||||
|
*
|
||||||
|
* @return string|null
|
||||||
|
*/
|
||||||
public static function SpeexBandModeLookup($mode) {
|
public static function SpeexBandModeLookup($mode) {
|
||||||
static $SpeexBandModeLookup = array();
|
static $SpeexBandModeLookup = array();
|
||||||
if (empty($SpeexBandModeLookup)) {
|
if (empty($SpeexBandModeLookup)) {
|
||||||
|
@ -775,8 +833,14 @@ $this->warning('Ogg Theora (v3) not fully supported in this version of getID3 ['
|
||||||
return (isset($SpeexBandModeLookup[$mode]) ? $SpeexBandModeLookup[$mode] : null);
|
return (isset($SpeexBandModeLookup[$mode]) ? $SpeexBandModeLookup[$mode] : null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $OggInfoArray
|
||||||
|
* @param int $SegmentNumber
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
public static function OggPageSegmentLength($OggInfoArray, $SegmentNumber=1) {
|
public static function OggPageSegmentLength($OggInfoArray, $SegmentNumber=1) {
|
||||||
|
$segmentlength = 0;
|
||||||
for ($i = 0; $i < $SegmentNumber; $i++) {
|
for ($i = 0; $i < $SegmentNumber; $i++) {
|
||||||
$segmentlength = 0;
|
$segmentlength = 0;
|
||||||
foreach ($OggInfoArray['segment_table'] as $key => $value) {
|
foreach ($OggInfoArray['segment_table'] as $key => $value) {
|
||||||
|
@ -789,7 +853,11 @@ $this->warning('Ogg Theora (v3) not fully supported in this version of getID3 ['
|
||||||
return $segmentlength;
|
return $segmentlength;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $nominal_bitrate
|
||||||
|
*
|
||||||
|
* @return float
|
||||||
|
*/
|
||||||
public static function get_quality_from_nominal_bitrate($nominal_bitrate) {
|
public static function get_quality_from_nominal_bitrate($nominal_bitrate) {
|
||||||
|
|
||||||
// decrease precision
|
// decrease precision
|
||||||
|
@ -813,6 +881,11 @@ $this->warning('Ogg Theora (v3) not fully supported in this version of getID3 ['
|
||||||
return round($qval, 1); // 5 or 4.9
|
return round($qval, 1); // 5 or 4.9
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $colorspace_id
|
||||||
|
*
|
||||||
|
* @return string|null
|
||||||
|
*/
|
||||||
public static function TheoraColorSpace($colorspace_id) {
|
public static function TheoraColorSpace($colorspace_id) {
|
||||||
// http://www.theora.org/doc/Theora.pdf (table 6.3)
|
// http://www.theora.org/doc/Theora.pdf (table 6.3)
|
||||||
static $TheoraColorSpaceLookup = array();
|
static $TheoraColorSpaceLookup = array();
|
||||||
|
@ -825,6 +898,11 @@ $this->warning('Ogg Theora (v3) not fully supported in this version of getID3 ['
|
||||||
return (isset($TheoraColorSpaceLookup[$colorspace_id]) ? $TheoraColorSpaceLookup[$colorspace_id] : null);
|
return (isset($TheoraColorSpaceLookup[$colorspace_id]) ? $TheoraColorSpaceLookup[$colorspace_id] : null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $pixelformat_id
|
||||||
|
*
|
||||||
|
* @return string|null
|
||||||
|
*/
|
||||||
public static function TheoraPixelFormat($pixelformat_id) {
|
public static function TheoraPixelFormat($pixelformat_id) {
|
||||||
// http://www.theora.org/doc/Theora.pdf (table 6.4)
|
// http://www.theora.org/doc/Theora.pdf (table 6.4)
|
||||||
static $TheoraPixelFormatLookup = array();
|
static $TheoraPixelFormatLookup = array();
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////
|
||||||
/// getID3() by James Heinrich <info@getid3.org> //
|
/// getID3() by James Heinrich <info@getid3.org> //
|
||||||
// available at http://getid3.sourceforge.net //
|
// available at https://github.com/JamesHeinrich/getID3 //
|
||||||
// or http://www.getid3.org //
|
// or https://www.getid3.org //
|
||||||
// also https://github.com/JamesHeinrich/getID3 //
|
// or http://getid3.sourceforge.net //
|
||||||
/////////////////////////////////////////////////////////////////
|
// see readme.txt for more details //
|
||||||
// See readme.txt for more details //
|
|
||||||
/////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////
|
||||||
// //
|
// //
|
||||||
// module.tag.apetag.php //
|
// module.tag.apetag.php //
|
||||||
|
@ -16,9 +16,21 @@
|
||||||
|
|
||||||
class getid3_apetag extends getid3_handler
|
class getid3_apetag extends getid3_handler
|
||||||
{
|
{
|
||||||
public $inline_attachments = true; // true: return full data for all attachments; false: return no data for all attachments; integer: return data for attachments <= than this; string: save as file to this directory
|
/**
|
||||||
|
* true: return full data for all attachments;
|
||||||
|
* false: return no data for all attachments;
|
||||||
|
* integer: return data for attachments <= than this;
|
||||||
|
* string: save as file to this directory.
|
||||||
|
*
|
||||||
|
* @var int|bool|string
|
||||||
|
*/
|
||||||
|
public $inline_attachments = true;
|
||||||
|
|
||||||
public $overrideendoffset = 0;
|
public $overrideendoffset = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
public function Analyze() {
|
public function Analyze() {
|
||||||
$info = &$this->getid3->info;
|
$info = &$this->getid3->info;
|
||||||
|
|
||||||
|
@ -150,8 +162,8 @@ class getid3_apetag extends getid3_handler
|
||||||
switch (strtolower($item_key)) {
|
switch (strtolower($item_key)) {
|
||||||
// http://wiki.hydrogenaud.io/index.php?title=ReplayGain#MP3Gain
|
// http://wiki.hydrogenaud.io/index.php?title=ReplayGain#MP3Gain
|
||||||
case 'replaygain_track_gain':
|
case 'replaygain_track_gain':
|
||||||
if (preg_match('#^[\\-\\+][0-9\\.,]{8}$#', $thisfile_ape_items_current['data'][0])) {
|
if (preg_match('#^([\\-\\+][0-9\\.,]{8})( dB)?$#', $thisfile_ape_items_current['data'][0], $matches)) {
|
||||||
$thisfile_replaygain['track']['adjustment'] = (float) str_replace(',', '.', $thisfile_ape_items_current['data'][0]); // float casting will see "0,95" as zero!
|
$thisfile_replaygain['track']['adjustment'] = (float) str_replace(',', '.', $matches[1]); // float casting will see "0,95" as zero!
|
||||||
$thisfile_replaygain['track']['originator'] = 'unspecified';
|
$thisfile_replaygain['track']['originator'] = 'unspecified';
|
||||||
} else {
|
} else {
|
||||||
$this->warning('MP3gainTrackGain value in APEtag appears invalid: "'.$thisfile_ape_items_current['data'][0].'"');
|
$this->warning('MP3gainTrackGain value in APEtag appears invalid: "'.$thisfile_ape_items_current['data'][0].'"');
|
||||||
|
@ -159,8 +171,8 @@ class getid3_apetag extends getid3_handler
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'replaygain_track_peak':
|
case 'replaygain_track_peak':
|
||||||
if (preg_match('#^[0-9\\.,]{8}$#', $thisfile_ape_items_current['data'][0])) {
|
if (preg_match('#^([0-9\\.,]{8})$#', $thisfile_ape_items_current['data'][0], $matches)) {
|
||||||
$thisfile_replaygain['track']['peak'] = (float) str_replace(',', '.', $thisfile_ape_items_current['data'][0]); // float casting will see "0,95" as zero!
|
$thisfile_replaygain['track']['peak'] = (float) str_replace(',', '.', $matches[1]); // float casting will see "0,95" as zero!
|
||||||
$thisfile_replaygain['track']['originator'] = 'unspecified';
|
$thisfile_replaygain['track']['originator'] = 'unspecified';
|
||||||
if ($thisfile_replaygain['track']['peak'] <= 0) {
|
if ($thisfile_replaygain['track']['peak'] <= 0) {
|
||||||
$this->warning('ReplayGain Track peak from APEtag appears invalid: '.$thisfile_replaygain['track']['peak'].' (original value = "'.$thisfile_ape_items_current['data'][0].'")');
|
$this->warning('ReplayGain Track peak from APEtag appears invalid: '.$thisfile_replaygain['track']['peak'].' (original value = "'.$thisfile_ape_items_current['data'][0].'")');
|
||||||
|
@ -171,8 +183,8 @@ class getid3_apetag extends getid3_handler
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'replaygain_album_gain':
|
case 'replaygain_album_gain':
|
||||||
if (preg_match('#^[\\-\\+][0-9\\.,]{8}$#', $thisfile_ape_items_current['data'][0])) {
|
if (preg_match('#^([\\-\\+][0-9\\.,]{8})( dB)?$#', $thisfile_ape_items_current['data'][0], $matches)) {
|
||||||
$thisfile_replaygain['album']['adjustment'] = (float) str_replace(',', '.', $thisfile_ape_items_current['data'][0]); // float casting will see "0,95" as zero!
|
$thisfile_replaygain['album']['adjustment'] = (float) str_replace(',', '.', $matches[1]); // float casting will see "0,95" as zero!
|
||||||
$thisfile_replaygain['album']['originator'] = 'unspecified';
|
$thisfile_replaygain['album']['originator'] = 'unspecified';
|
||||||
} else {
|
} else {
|
||||||
$this->warning('MP3gainAlbumGain value in APEtag appears invalid: "'.$thisfile_ape_items_current['data'][0].'"');
|
$this->warning('MP3gainAlbumGain value in APEtag appears invalid: "'.$thisfile_ape_items_current['data'][0].'"');
|
||||||
|
@ -180,8 +192,8 @@ class getid3_apetag extends getid3_handler
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'replaygain_album_peak':
|
case 'replaygain_album_peak':
|
||||||
if (preg_match('#^[0-9\\.,]{8}$#', $thisfile_ape_items_current['data'][0])) {
|
if (preg_match('#^([0-9\\.,]{8})$#', $thisfile_ape_items_current['data'][0], $matches)) {
|
||||||
$thisfile_replaygain['album']['peak'] = (float) str_replace(',', '.', $thisfile_ape_items_current['data'][0]); // float casting will see "0,95" as zero!
|
$thisfile_replaygain['album']['peak'] = (float) str_replace(',', '.', $matches[1]); // float casting will see "0,95" as zero!
|
||||||
$thisfile_replaygain['album']['originator'] = 'unspecified';
|
$thisfile_replaygain['album']['originator'] = 'unspecified';
|
||||||
if ($thisfile_replaygain['album']['peak'] <= 0) {
|
if ($thisfile_replaygain['album']['peak'] <= 0) {
|
||||||
$this->warning('ReplayGain Album peak from APEtag appears invalid: '.$thisfile_replaygain['album']['peak'].' (original value = "'.$thisfile_ape_items_current['data'][0].'")');
|
$this->warning('ReplayGain Album peak from APEtag appears invalid: '.$thisfile_replaygain['album']['peak'].' (original value = "'.$thisfile_ape_items_current['data'][0].'")');
|
||||||
|
@ -225,7 +237,7 @@ class getid3_apetag extends getid3_handler
|
||||||
case 'tracknumber':
|
case 'tracknumber':
|
||||||
if (is_array($thisfile_ape_items_current['data'])) {
|
if (is_array($thisfile_ape_items_current['data'])) {
|
||||||
foreach ($thisfile_ape_items_current['data'] as $comment) {
|
foreach ($thisfile_ape_items_current['data'] as $comment) {
|
||||||
$thisfile_ape['comments']['track'][] = $comment;
|
$thisfile_ape['comments']['track_number'][] = $comment;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -335,6 +347,11 @@ class getid3_apetag extends getid3_handler
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $APEheaderFooterData
|
||||||
|
*
|
||||||
|
* @return array|false
|
||||||
|
*/
|
||||||
public function parseAPEheaderFooter($APEheaderFooterData) {
|
public function parseAPEheaderFooter($APEheaderFooterData) {
|
||||||
// http://www.uni-jena.de/~pfk/mpp/sv8/apeheader.html
|
// http://www.uni-jena.de/~pfk/mpp/sv8/apeheader.html
|
||||||
|
|
||||||
|
@ -359,6 +376,11 @@ class getid3_apetag extends getid3_handler
|
||||||
return $headerfooterinfo;
|
return $headerfooterinfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $rawflagint
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
public function parseAPEtagFlags($rawflagint) {
|
public function parseAPEtagFlags($rawflagint) {
|
||||||
// "Note: APE Tags 1.0 do not use any of the APE Tag flags.
|
// "Note: APE Tags 1.0 do not use any of the APE Tag flags.
|
||||||
// All are set to zero on creation and ignored on reading."
|
// All are set to zero on creation and ignored on reading."
|
||||||
|
@ -374,6 +396,11 @@ class getid3_apetag extends getid3_handler
|
||||||
return $flags;
|
return $flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $contenttypeid
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public function APEcontentTypeFlagLookup($contenttypeid) {
|
public function APEcontentTypeFlagLookup($contenttypeid) {
|
||||||
static $APEcontentTypeFlagLookup = array(
|
static $APEcontentTypeFlagLookup = array(
|
||||||
0 => 'utf-8',
|
0 => 'utf-8',
|
||||||
|
@ -384,6 +411,11 @@ class getid3_apetag extends getid3_handler
|
||||||
return (isset($APEcontentTypeFlagLookup[$contenttypeid]) ? $APEcontentTypeFlagLookup[$contenttypeid] : 'invalid');
|
return (isset($APEcontentTypeFlagLookup[$contenttypeid]) ? $APEcontentTypeFlagLookup[$contenttypeid] : 'invalid');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $itemkey
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
public function APEtagItemIsUTF8Lookup($itemkey) {
|
public function APEtagItemIsUTF8Lookup($itemkey) {
|
||||||
static $APEtagItemIsUTF8Lookup = array(
|
static $APEtagItemIsUTF8Lookup = array(
|
||||||
'title',
|
'title',
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////
|
||||||
/// getID3() by James Heinrich <info@getid3.org> //
|
/// getID3() by James Heinrich <info@getid3.org> //
|
||||||
// available at http://getid3.sourceforge.net //
|
// available at https://github.com/JamesHeinrich/getID3 //
|
||||||
// or http://www.getid3.org //
|
// or https://www.getid3.org //
|
||||||
// also https://github.com/JamesHeinrich/getID3 //
|
// or http://getid3.sourceforge.net //
|
||||||
/////////////////////////////////////////////////////////////////
|
// see readme.txt for more details //
|
||||||
// See readme.txt for more details //
|
|
||||||
/////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////
|
||||||
// //
|
// //
|
||||||
// module.tag.id3v1.php //
|
// module.tag.id3v1.php //
|
||||||
|
@ -17,7 +17,9 @@
|
||||||
|
|
||||||
class getid3_id3v1 extends getid3_handler
|
class getid3_id3v1 extends getid3_handler
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
public function Analyze() {
|
public function Analyze() {
|
||||||
$info = &$this->getid3->info;
|
$info = &$this->getid3->info;
|
||||||
|
|
||||||
|
@ -43,9 +45,9 @@ class getid3_id3v1 extends getid3_handler
|
||||||
|
|
||||||
// If second-last byte of comment field is null and last byte of comment field is non-null
|
// If second-last byte of comment field is null and last byte of comment field is non-null
|
||||||
// then this is ID3v1.1 and the comment field is 28 bytes long and the 30th byte is the track number
|
// then this is ID3v1.1 and the comment field is 28 bytes long and the 30th byte is the track number
|
||||||
if (($id3v1tag{125} === "\x00") && ($id3v1tag{126} !== "\x00")) {
|
if (($id3v1tag[125] === "\x00") && ($id3v1tag[126] !== "\x00")) {
|
||||||
$ParsedID3v1['track'] = ord(substr($ParsedID3v1['comment'], 29, 1));
|
$ParsedID3v1['track_number'] = ord(substr($ParsedID3v1['comment'], 29, 1));
|
||||||
$ParsedID3v1['comment'] = substr($ParsedID3v1['comment'], 0, 28);
|
$ParsedID3v1['comment'] = substr($ParsedID3v1['comment'], 0, 28);
|
||||||
}
|
}
|
||||||
$ParsedID3v1['comment'] = $this->cutfield($ParsedID3v1['comment']);
|
$ParsedID3v1['comment'] = $this->cutfield($ParsedID3v1['comment']);
|
||||||
|
|
||||||
|
@ -66,7 +68,7 @@ class getid3_id3v1 extends getid3_handler
|
||||||
$ID3v1encoding = 'ISO-8859-1';
|
$ID3v1encoding = 'ISO-8859-1';
|
||||||
foreach ($ParsedID3v1['comments'] as $tag_key => $valuearray) {
|
foreach ($ParsedID3v1['comments'] as $tag_key => $valuearray) {
|
||||||
foreach ($valuearray as $key => $value) {
|
foreach ($valuearray as $key => $value) {
|
||||||
if (preg_match('#^[\\x00-\\x40\\xA8\\B8\\x80-\\xFF]+$#', $value)) {
|
if (preg_match('#^[\\x00-\\x40\\xA8\\xB8\\x80-\\xFF]+$#', $value)) {
|
||||||
foreach (array('Windows-1251', 'KOI8-R') as $id3v1_bad_encoding) {
|
foreach (array('Windows-1251', 'KOI8-R') as $id3v1_bad_encoding) {
|
||||||
if (function_exists('mb_convert_encoding') && @mb_convert_encoding($value, $id3v1_bad_encoding, $id3v1_bad_encoding) === $value) {
|
if (function_exists('mb_convert_encoding') && @mb_convert_encoding($value, $id3v1_bad_encoding, $id3v1_bad_encoding) === $value) {
|
||||||
$ID3v1encoding = $id3v1_bad_encoding;
|
$ID3v1encoding = $id3v1_bad_encoding;
|
||||||
|
@ -89,7 +91,7 @@ class getid3_id3v1 extends getid3_handler
|
||||||
$ParsedID3v1['year'],
|
$ParsedID3v1['year'],
|
||||||
(isset($ParsedID3v1['genre']) ? $this->LookupGenreID($ParsedID3v1['genre']) : false),
|
(isset($ParsedID3v1['genre']) ? $this->LookupGenreID($ParsedID3v1['genre']) : false),
|
||||||
$ParsedID3v1['comment'],
|
$ParsedID3v1['comment'],
|
||||||
(!empty($ParsedID3v1['track']) ? $ParsedID3v1['track'] : ''));
|
(!empty($ParsedID3v1['track_number']) ? $ParsedID3v1['track_number'] : ''));
|
||||||
$ParsedID3v1['padding_valid'] = true;
|
$ParsedID3v1['padding_valid'] = true;
|
||||||
if ($id3v1tag !== $GoodFormatID3v1tag) {
|
if ($id3v1tag !== $GoodFormatID3v1tag) {
|
||||||
$ParsedID3v1['padding_valid'] = false;
|
$ParsedID3v1['padding_valid'] = false;
|
||||||
|
@ -124,10 +126,20 @@ class getid3_id3v1 extends getid3_handler
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $str
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public static function cutfield($str) {
|
public static function cutfield($str) {
|
||||||
return trim(substr($str, 0, strcspn($str, "\x00")));
|
return trim(substr($str, 0, strcspn($str, "\x00")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param bool $allowSCMPXextended
|
||||||
|
*
|
||||||
|
* @return string[]
|
||||||
|
*/
|
||||||
public static function ArrayOfGenres($allowSCMPXextended=false) {
|
public static function ArrayOfGenres($allowSCMPXextended=false) {
|
||||||
static $GenreLookup = array(
|
static $GenreLookup = array(
|
||||||
0 => 'Blues',
|
0 => 'Blues',
|
||||||
|
@ -312,6 +324,12 @@ class getid3_id3v1 extends getid3_handler
|
||||||
return ($allowSCMPXextended ? $GenreLookupSCMPX : $GenreLookup);
|
return ($allowSCMPXextended ? $GenreLookupSCMPX : $GenreLookup);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $genreid
|
||||||
|
* @param bool $allowSCMPXextended
|
||||||
|
*
|
||||||
|
* @return string|false
|
||||||
|
*/
|
||||||
public static function LookupGenreName($genreid, $allowSCMPXextended=true) {
|
public static function LookupGenreName($genreid, $allowSCMPXextended=true) {
|
||||||
switch ($genreid) {
|
switch ($genreid) {
|
||||||
case 'RX':
|
case 'RX':
|
||||||
|
@ -328,6 +346,12 @@ class getid3_id3v1 extends getid3_handler
|
||||||
return (isset($GenreLookup[$genreid]) ? $GenreLookup[$genreid] : false);
|
return (isset($GenreLookup[$genreid]) ? $GenreLookup[$genreid] : false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $genre
|
||||||
|
* @param bool $allowSCMPXextended
|
||||||
|
*
|
||||||
|
* @return string|false
|
||||||
|
*/
|
||||||
public static function LookupGenreID($genre, $allowSCMPXextended=false) {
|
public static function LookupGenreID($genre, $allowSCMPXextended=false) {
|
||||||
$GenreLookup = self::ArrayOfGenres($allowSCMPXextended);
|
$GenreLookup = self::ArrayOfGenres($allowSCMPXextended);
|
||||||
$LowerCaseNoSpaceSearchTerm = strtolower(str_replace(' ', '', $genre));
|
$LowerCaseNoSpaceSearchTerm = strtolower(str_replace(' ', '', $genre));
|
||||||
|
@ -339,6 +363,11 @@ class getid3_id3v1 extends getid3_handler
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $OriginalGenre
|
||||||
|
*
|
||||||
|
* @return string|false
|
||||||
|
*/
|
||||||
public static function StandardiseID3v1GenreName($OriginalGenre) {
|
public static function StandardiseID3v1GenreName($OriginalGenre) {
|
||||||
if (($GenreID = self::LookupGenreID($OriginalGenre)) !== false) {
|
if (($GenreID = self::LookupGenreID($OriginalGenre)) !== false) {
|
||||||
return self::LookupGenreName($GenreID);
|
return self::LookupGenreName($GenreID);
|
||||||
|
@ -346,6 +375,17 @@ class getid3_id3v1 extends getid3_handler
|
||||||
return $OriginalGenre;
|
return $OriginalGenre;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $title
|
||||||
|
* @param string $artist
|
||||||
|
* @param string $album
|
||||||
|
* @param string $year
|
||||||
|
* @param int $genreid
|
||||||
|
* @param string $comment
|
||||||
|
* @param int|string $track
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public static function GenerateID3v1Tag($title, $artist, $album, $year, $genreid, $comment, $track='') {
|
public static function GenerateID3v1Tag($title, $artist, $album, $year, $genreid, $comment, $track='') {
|
||||||
$ID3v1Tag = 'TAG';
|
$ID3v1Tag = 'TAG';
|
||||||
$ID3v1Tag .= str_pad(trim(substr($title, 0, 30)), 30, "\x00", STR_PAD_RIGHT);
|
$ID3v1Tag .= str_pad(trim(substr($title, 0, 30)), 30, "\x00", STR_PAD_RIGHT);
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////
|
||||||
/// getID3() by James Heinrich <info@getid3.org> //
|
/// getID3() by James Heinrich <info@getid3.org> //
|
||||||
// available at http://getid3.sourceforge.net //
|
// available at https://github.com/JamesHeinrich/getID3 //
|
||||||
// or http://www.getid3.org //
|
// or https://www.getid3.org //
|
||||||
// also https://github.com/JamesHeinrich/getID3 //
|
// or http://getid3.sourceforge.net //
|
||||||
/////////////////////////////////////////////////////////////////
|
// see readme.txt for more details //
|
||||||
// See readme.txt for more details //
|
|
||||||
/////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////
|
||||||
/// //
|
/// //
|
||||||
// module.tag.id3v2.php //
|
// module.tag.id3v2.php //
|
||||||
|
@ -20,6 +20,9 @@ class getid3_id3v2 extends getid3_handler
|
||||||
{
|
{
|
||||||
public $StartingOffset = 0;
|
public $StartingOffset = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
public function Analyze() {
|
public function Analyze() {
|
||||||
$info = &$this->getid3->info;
|
$info = &$this->getid3->info;
|
||||||
|
|
||||||
|
@ -56,8 +59,8 @@ class getid3_id3v2 extends getid3_handler
|
||||||
$header = $this->fread(10);
|
$header = $this->fread(10);
|
||||||
if (substr($header, 0, 3) == 'ID3' && strlen($header) == 10) {
|
if (substr($header, 0, 3) == 'ID3' && strlen($header) == 10) {
|
||||||
|
|
||||||
$thisfile_id3v2['majorversion'] = ord($header{3});
|
$thisfile_id3v2['majorversion'] = ord($header[3]);
|
||||||
$thisfile_id3v2['minorversion'] = ord($header{4});
|
$thisfile_id3v2['minorversion'] = ord($header[4]);
|
||||||
|
|
||||||
// shortcut
|
// shortcut
|
||||||
$id3v2_majorversion = &$thisfile_id3v2['majorversion'];
|
$id3v2_majorversion = &$thisfile_id3v2['majorversion'];
|
||||||
|
@ -76,7 +79,7 @@ class getid3_id3v2 extends getid3_handler
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$id3_flags = ord($header{5});
|
$id3_flags = ord($header[5]);
|
||||||
switch ($id3v2_majorversion) {
|
switch ($id3v2_majorversion) {
|
||||||
case 2:
|
case 2:
|
||||||
// %ab000000 in v2.2
|
// %ab000000 in v2.2
|
||||||
|
@ -257,7 +260,7 @@ class getid3_id3v2 extends getid3_handler
|
||||||
$thisfile_id3v2['padding']['length'] = strlen($framedata);
|
$thisfile_id3v2['padding']['length'] = strlen($framedata);
|
||||||
$thisfile_id3v2['padding']['valid'] = true;
|
$thisfile_id3v2['padding']['valid'] = true;
|
||||||
for ($i = 0; $i < $thisfile_id3v2['padding']['length']; $i++) {
|
for ($i = 0; $i < $thisfile_id3v2['padding']['length']; $i++) {
|
||||||
if ($framedata{$i} != "\x00") {
|
if ($framedata[$i] != "\x00") {
|
||||||
$thisfile_id3v2['padding']['valid'] = false;
|
$thisfile_id3v2['padding']['valid'] = false;
|
||||||
$thisfile_id3v2['padding']['errorpos'] = $thisfile_id3v2['padding']['start'] + $i;
|
$thisfile_id3v2['padding']['errorpos'] = $thisfile_id3v2['padding']['start'] + $i;
|
||||||
$this->warning('Invalid ID3v2 padding found at offset '.$thisfile_id3v2['padding']['errorpos'].' (the remaining '.($thisfile_id3v2['padding']['length'] - $i).' bytes are considered invalid)');
|
$this->warning('Invalid ID3v2 padding found at offset '.$thisfile_id3v2['padding']['errorpos'].' (the remaining '.($thisfile_id3v2['padding']['length'] - $i).' bytes are considered invalid)');
|
||||||
|
@ -266,6 +269,10 @@ class getid3_id3v2 extends getid3_handler
|
||||||
}
|
}
|
||||||
break; // skip rest of ID3v2 header
|
break; // skip rest of ID3v2 header
|
||||||
}
|
}
|
||||||
|
$frame_header = null;
|
||||||
|
$frame_name = null;
|
||||||
|
$frame_size = null;
|
||||||
|
$frame_flags = null;
|
||||||
if ($id3v2_majorversion == 2) {
|
if ($id3v2_majorversion == 2) {
|
||||||
// Frame ID $xx xx xx (three characters)
|
// Frame ID $xx xx xx (three characters)
|
||||||
// Size $xx xx xx (24-bit integer)
|
// Size $xx xx xx (24-bit integer)
|
||||||
|
@ -319,7 +326,7 @@ class getid3_id3v2 extends getid3_handler
|
||||||
|
|
||||||
$len = strlen($framedata);
|
$len = strlen($framedata);
|
||||||
for ($i = 0; $i < $len; $i++) {
|
for ($i = 0; $i < $len; $i++) {
|
||||||
if ($framedata{$i} != "\x00") {
|
if ($framedata[$i] != "\x00") {
|
||||||
$thisfile_id3v2['padding']['valid'] = false;
|
$thisfile_id3v2['padding']['valid'] = false;
|
||||||
$thisfile_id3v2['padding']['errorpos'] = $thisfile_id3v2['padding']['start'] + $i;
|
$thisfile_id3v2['padding']['errorpos'] = $thisfile_id3v2['padding']['start'] + $i;
|
||||||
$this->warning('Invalid ID3v2 padding found at offset '.$thisfile_id3v2['padding']['errorpos'].' (the remaining '.($thisfile_id3v2['padding']['length'] - $i).' bytes are considered invalid)');
|
$this->warning('Invalid ID3v2 padding found at offset '.$thisfile_id3v2['padding']['errorpos'].' (the remaining '.($thisfile_id3v2['padding']['length'] - $i).' bytes are considered invalid)');
|
||||||
|
@ -427,11 +434,11 @@ class getid3_id3v2 extends getid3_handler
|
||||||
$footer = $this->fread(10);
|
$footer = $this->fread(10);
|
||||||
if (substr($footer, 0, 3) == '3DI') {
|
if (substr($footer, 0, 3) == '3DI') {
|
||||||
$thisfile_id3v2['footer'] = true;
|
$thisfile_id3v2['footer'] = true;
|
||||||
$thisfile_id3v2['majorversion_footer'] = ord($footer{3});
|
$thisfile_id3v2['majorversion_footer'] = ord($footer[3]);
|
||||||
$thisfile_id3v2['minorversion_footer'] = ord($footer{4});
|
$thisfile_id3v2['minorversion_footer'] = ord($footer[4]);
|
||||||
}
|
}
|
||||||
if ($thisfile_id3v2['majorversion_footer'] <= 4) {
|
if ($thisfile_id3v2['majorversion_footer'] <= 4) {
|
||||||
$id3_flags = ord(substr($footer{5}));
|
$id3_flags = ord($footer[5]);
|
||||||
$thisfile_id3v2_flags['unsynch_footer'] = (bool) ($id3_flags & 0x80);
|
$thisfile_id3v2_flags['unsynch_footer'] = (bool) ($id3_flags & 0x80);
|
||||||
$thisfile_id3v2_flags['extfoot_footer'] = (bool) ($id3_flags & 0x40);
|
$thisfile_id3v2_flags['extfoot_footer'] = (bool) ($id3_flags & 0x40);
|
||||||
$thisfile_id3v2_flags['experim_footer'] = (bool) ($id3_flags & 0x20);
|
$thisfile_id3v2_flags['experim_footer'] = (bool) ($id3_flags & 0x20);
|
||||||
|
@ -452,10 +459,10 @@ class getid3_id3v2 extends getid3_handler
|
||||||
unset($key, $value, $genres, $genre);
|
unset($key, $value, $genres, $genre);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($thisfile_id3v2['comments']['track'])) {
|
if (isset($thisfile_id3v2['comments']['track_number'])) {
|
||||||
foreach ($thisfile_id3v2['comments']['track'] as $key => $value) {
|
foreach ($thisfile_id3v2['comments']['track_number'] as $key => $value) {
|
||||||
if (strstr($value, '/')) {
|
if (strstr($value, '/')) {
|
||||||
list($thisfile_id3v2['comments']['tracknum'][$key], $thisfile_id3v2['comments']['totaltracks'][$key]) = explode('/', $thisfile_id3v2['comments']['track'][$key]);
|
list($thisfile_id3v2['comments']['track_number'][$key], $thisfile_id3v2['comments']['totaltracks'][$key]) = explode('/', $thisfile_id3v2['comments']['track_number'][$key]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -498,7 +505,11 @@ class getid3_id3v2 extends getid3_handler
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $genrestring
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
public function ParseID3v2GenreString($genrestring) {
|
public function ParseID3v2GenreString($genrestring) {
|
||||||
// Parse genres into arrays of genreName and genreID
|
// Parse genres into arrays of genreName and genreID
|
||||||
// ID3v2.2.x, ID3v2.3.x: '(21)' or '(4)Eurodisco' or '(51)(39)' or '(55)((I think...)'
|
// ID3v2.2.x, ID3v2.3.x: '(21)' or '(4)Eurodisco' or '(51)(39)' or '(55)((I think...)'
|
||||||
|
@ -530,7 +541,7 @@ class getid3_id3v2 extends getid3_handler
|
||||||
foreach ($genre_elements as $element) {
|
foreach ($genre_elements as $element) {
|
||||||
$element = trim($element);
|
$element = trim($element);
|
||||||
if ($element) {
|
if ($element) {
|
||||||
if (preg_match('#^[0-9]{1,3}#', $element)) {
|
if (preg_match('#^[0-9]{1,3}$#', $element)) {
|
||||||
$clean_genres[] = getid3_id3v1::LookupGenreName($element);
|
$clean_genres[] = getid3_id3v1::LookupGenreName($element);
|
||||||
} else {
|
} else {
|
||||||
$clean_genres[] = str_replace('((', '(', $element);
|
$clean_genres[] = str_replace('((', '(', $element);
|
||||||
|
@ -540,7 +551,11 @@ class getid3_id3v2 extends getid3_handler
|
||||||
return $clean_genres;
|
return $clean_genres;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $parsedFrame
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
public function ParseID3v2Frame(&$parsedFrame) {
|
public function ParseID3v2Frame(&$parsedFrame) {
|
||||||
|
|
||||||
// shortcuts
|
// shortcuts
|
||||||
|
@ -657,16 +672,14 @@ class getid3_id3v2 extends getid3_handler
|
||||||
if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator), 1)) === 0) {
|
if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator), 1)) === 0) {
|
||||||
$frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00
|
$frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00
|
||||||
}
|
}
|
||||||
$frame_description = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
|
$parsedFrame['description'] = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
|
||||||
if (in_array($frame_description, array("\x00", "\x00\x00", "\xFF\xFE", "\xFE\xFF"))) {
|
$parsedFrame['description'] = $this->MakeUTF16emptyStringEmpty($parsedFrame['description']);
|
||||||
// if description only contains a BOM or terminator then make it blank
|
|
||||||
$frame_description = '';
|
|
||||||
}
|
|
||||||
$parsedFrame['encodingid'] = $frame_textencoding;
|
$parsedFrame['encodingid'] = $frame_textencoding;
|
||||||
$parsedFrame['encoding'] = $this->TextEncodingNameLookup($frame_textencoding);
|
$parsedFrame['encoding'] = $this->TextEncodingNameLookup($frame_textencoding);
|
||||||
|
|
||||||
$parsedFrame['description'] = trim(getid3_lib::iconv_fallback($parsedFrame['encoding'], $info['id3v2']['encoding'], $frame_description));
|
$parsedFrame['description'] = trim(getid3_lib::iconv_fallback($parsedFrame['encoding'], $info['id3v2']['encoding'], $parsedFrame['description']));
|
||||||
$parsedFrame['data'] = substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator));
|
$parsedFrame['data'] = substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator));
|
||||||
|
$parsedFrame['data'] = $this->RemoveStringTerminator($parsedFrame['data'], $frame_textencoding_terminator);
|
||||||
if (!empty($parsedFrame['framenameshort']) && !empty($parsedFrame['data'])) {
|
if (!empty($parsedFrame['framenameshort']) && !empty($parsedFrame['data'])) {
|
||||||
$commentkey = ($parsedFrame['description'] ? $parsedFrame['description'] : (isset($info['id3v2']['comments'][$parsedFrame['framenameshort']]) ? count($info['id3v2']['comments'][$parsedFrame['framenameshort']]) : 0));
|
$commentkey = ($parsedFrame['description'] ? $parsedFrame['description'] : (isset($info['id3v2']['comments'][$parsedFrame['framenameshort']]) ? count($info['id3v2']['comments'][$parsedFrame['framenameshort']]) : 0));
|
||||||
if (!isset($info['id3v2']['comments'][$parsedFrame['framenameshort']]) || !array_key_exists($commentkey, $info['id3v2']['comments'][$parsedFrame['framenameshort']])) {
|
if (!isset($info['id3v2']['comments'][$parsedFrame['framenameshort']]) || !array_key_exists($commentkey, $info['id3v2']['comments'][$parsedFrame['framenameshort']])) {
|
||||||
|
@ -678,7 +691,7 @@ class getid3_id3v2 extends getid3_handler
|
||||||
//unset($parsedFrame['data']); do not unset, may be needed elsewhere, e.g. for replaygain
|
//unset($parsedFrame['data']); do not unset, may be needed elsewhere, e.g. for replaygain
|
||||||
|
|
||||||
|
|
||||||
} elseif ($parsedFrame['frame_name']{0} == 'T') { // 4.2. T??[?] Text information frame
|
} elseif ($parsedFrame['frame_name'][0] == 'T') { // 4.2. T??[?] Text information frame
|
||||||
// There may only be one text information frame of its kind in an tag.
|
// There may only be one text information frame of its kind in an tag.
|
||||||
// <Header for 'Text information frame', ID: 'T000' - 'TZZZ',
|
// <Header for 'Text information frame', ID: 'T000' - 'TZZZ',
|
||||||
// excluding 'TXXX' described in 4.2.6.>
|
// excluding 'TXXX' described in 4.2.6.>
|
||||||
|
@ -692,10 +705,10 @@ class getid3_id3v2 extends getid3_handler
|
||||||
}
|
}
|
||||||
|
|
||||||
$parsedFrame['data'] = (string) substr($parsedFrame['data'], $frame_offset);
|
$parsedFrame['data'] = (string) substr($parsedFrame['data'], $frame_offset);
|
||||||
|
$parsedFrame['data'] = $this->RemoveStringTerminator($parsedFrame['data'], $this->TextEncodingTerminatorLookup($frame_textencoding));
|
||||||
|
|
||||||
$parsedFrame['encodingid'] = $frame_textencoding;
|
$parsedFrame['encodingid'] = $frame_textencoding;
|
||||||
$parsedFrame['encoding'] = $this->TextEncodingNameLookup($frame_textencoding);
|
$parsedFrame['encoding'] = $this->TextEncodingNameLookup($frame_textencoding);
|
||||||
|
|
||||||
if (!empty($parsedFrame['framenameshort']) && !empty($parsedFrame['data'])) {
|
if (!empty($parsedFrame['framenameshort']) && !empty($parsedFrame['data'])) {
|
||||||
// ID3v2.3 specs say that TPE1 (and others) can contain multiple artist values separated with /
|
// ID3v2.3 specs say that TPE1 (and others) can contain multiple artist values separated with /
|
||||||
// This of course breaks when an artist name contains slash character, e.g. "AC/DC"
|
// This of course breaks when an artist name contains slash character, e.g. "AC/DC"
|
||||||
|
@ -751,47 +764,29 @@ class getid3_id3v2 extends getid3_handler
|
||||||
if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator), 1)) === 0) {
|
if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator), 1)) === 0) {
|
||||||
$frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00
|
$frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00
|
||||||
}
|
}
|
||||||
$frame_description = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
|
|
||||||
if (in_array($frame_description, array("\x00", "\x00\x00", "\xFF\xFE", "\xFE\xFF"))) {
|
|
||||||
// if description only contains a BOM or terminator then make it blank
|
|
||||||
$frame_description = '';
|
|
||||||
}
|
|
||||||
$parsedFrame['data'] = substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator));
|
|
||||||
|
|
||||||
$frame_terminatorpos = strpos($parsedFrame['data'], $frame_textencoding_terminator);
|
|
||||||
if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator), 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 = (string) substr($parsedFrame['data'], 0, $frame_terminatorpos);
|
|
||||||
} else {
|
|
||||||
// no null bytes following data, just use all data
|
|
||||||
$frame_urldata = (string) $parsedFrame['data'];
|
|
||||||
}
|
|
||||||
|
|
||||||
$parsedFrame['encodingid'] = $frame_textencoding;
|
$parsedFrame['encodingid'] = $frame_textencoding;
|
||||||
$parsedFrame['encoding'] = $this->TextEncodingNameLookup($frame_textencoding);
|
$parsedFrame['encoding'] = $this->TextEncodingNameLookup($frame_textencoding);
|
||||||
|
$parsedFrame['description'] = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset); // according to the frame text encoding
|
||||||
|
$parsedFrame['url'] = substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator)); // always ISO-8859-1
|
||||||
|
$parsedFrame['description'] = $this->RemoveStringTerminator($parsedFrame['description'], $frame_textencoding_terminator);
|
||||||
|
$parsedFrame['description'] = $this->MakeUTF16emptyStringEmpty($parsedFrame['description']);
|
||||||
|
|
||||||
$parsedFrame['url'] = $frame_urldata;
|
|
||||||
$parsedFrame['description'] = $frame_description;
|
|
||||||
if (!empty($parsedFrame['framenameshort']) && $parsedFrame['url']) {
|
if (!empty($parsedFrame['framenameshort']) && $parsedFrame['url']) {
|
||||||
$info['id3v2']['comments'][$parsedFrame['framenameshort']][] = getid3_lib::iconv_fallback($parsedFrame['encoding'], $info['id3v2']['encoding'], $parsedFrame['url']);
|
$info['id3v2']['comments'][$parsedFrame['framenameshort']][] = getid3_lib::iconv_fallback('ISO-8859-1', $info['id3v2']['encoding'], $parsedFrame['url']);
|
||||||
}
|
}
|
||||||
unset($parsedFrame['data']);
|
unset($parsedFrame['data']);
|
||||||
|
|
||||||
|
|
||||||
} elseif ($parsedFrame['frame_name']{0} == 'W') { // 4.3. W??? URL link frames
|
} elseif ($parsedFrame['frame_name'][0] == 'W') { // 4.3. W??? URL link frames
|
||||||
// There may only be one URL link frame of its kind in a tag,
|
// There may only be one URL link frame of its kind in a tag,
|
||||||
// except when stated otherwise in the frame description
|
// except when stated otherwise in the frame description
|
||||||
// <Header for 'URL link frame', ID: 'W000' - 'WZZZ', excluding 'WXXX'
|
// <Header for 'URL link frame', ID: 'W000' - 'WZZZ', excluding 'WXXX'
|
||||||
// described in 4.3.2.>
|
// described in 4.3.2.>
|
||||||
// URL <text string>
|
// URL <text string>
|
||||||
|
|
||||||
$parsedFrame['url'] = trim($parsedFrame['data']);
|
$parsedFrame['url'] = trim($parsedFrame['data']); // always ISO-8859-1
|
||||||
if (!empty($parsedFrame['framenameshort']) && $parsedFrame['url']) {
|
if (!empty($parsedFrame['framenameshort']) && $parsedFrame['url']) {
|
||||||
$info['id3v2']['comments'][$parsedFrame['framenameshort']][] = $parsedFrame['url'];
|
$info['id3v2']['comments'][$parsedFrame['framenameshort']][] = getid3_lib::iconv_fallback('ISO-8859-1', $info['id3v2']['encoding'], $parsedFrame['url']);
|
||||||
}
|
}
|
||||||
unset($parsedFrame['data']);
|
unset($parsedFrame['data']);
|
||||||
|
|
||||||
|
@ -813,7 +808,7 @@ class getid3_id3v2 extends getid3_handler
|
||||||
$parsedFrame['encoding'] = $this->TextEncodingNameLookup($parsedFrame['encodingid']);
|
$parsedFrame['encoding'] = $this->TextEncodingNameLookup($parsedFrame['encodingid']);
|
||||||
$parsedFrame['data_raw'] = (string) substr($parsedFrame['data'], $frame_offset);
|
$parsedFrame['data_raw'] = (string) substr($parsedFrame['data'], $frame_offset);
|
||||||
|
|
||||||
// http://www.getid3.org/phpBB3/viewtopic.php?t=1369
|
// https://www.getid3.org/phpBB3/viewtopic.php?t=1369
|
||||||
// "this tag typically contains null terminated strings, which are associated in pairs"
|
// "this tag typically contains null terminated strings, which are associated in pairs"
|
||||||
// "there are users that use the tag incorrectly"
|
// "there are users that use the tag incorrectly"
|
||||||
$IPLS_parts = array();
|
$IPLS_parts = array();
|
||||||
|
@ -933,6 +928,7 @@ class getid3_id3v2 extends getid3_handler
|
||||||
$parsedFrame['bitsforbytesdeviation'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], 8, 1));
|
$parsedFrame['bitsforbytesdeviation'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], 8, 1));
|
||||||
$parsedFrame['bitsformsdeviation'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], 9, 1));
|
$parsedFrame['bitsformsdeviation'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], 9, 1));
|
||||||
$parsedFrame['data'] = substr($parsedFrame['data'], 10);
|
$parsedFrame['data'] = substr($parsedFrame['data'], 10);
|
||||||
|
$deviationbitstream = '';
|
||||||
while ($frame_offset < strlen($parsedFrame['data'])) {
|
while ($frame_offset < strlen($parsedFrame['data'])) {
|
||||||
$deviationbitstream .= getid3_lib::BigEndian2Bin(substr($parsedFrame['data'], $frame_offset++, 1));
|
$deviationbitstream .= getid3_lib::BigEndian2Bin(substr($parsedFrame['data'], $frame_offset++, 1));
|
||||||
}
|
}
|
||||||
|
@ -994,19 +990,16 @@ class getid3_id3v2 extends getid3_handler
|
||||||
if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator), 1)) === 0) {
|
if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator), 1)) === 0) {
|
||||||
$frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00
|
$frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00
|
||||||
}
|
}
|
||||||
$frame_description = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
|
$parsedFrame['description'] = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
|
||||||
if (in_array($frame_description, array("\x00", "\x00\x00", "\xFF\xFE", "\xFE\xFF"))) {
|
$parsedFrame['description'] = $this->MakeUTF16emptyStringEmpty($parsedFrame['description']);
|
||||||
// if description only contains a BOM or terminator then make it blank
|
|
||||||
$frame_description = '';
|
|
||||||
}
|
|
||||||
$parsedFrame['data'] = substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator));
|
$parsedFrame['data'] = substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator));
|
||||||
|
$parsedFrame['data'] = $this->RemoveStringTerminator($parsedFrame['data'], $frame_textencoding_terminator);
|
||||||
|
|
||||||
$parsedFrame['encodingid'] = $frame_textencoding;
|
$parsedFrame['encodingid'] = $frame_textencoding;
|
||||||
$parsedFrame['encoding'] = $this->TextEncodingNameLookup($frame_textencoding);
|
$parsedFrame['encoding'] = $this->TextEncodingNameLookup($frame_textencoding);
|
||||||
|
|
||||||
$parsedFrame['language'] = $frame_language;
|
$parsedFrame['language'] = $frame_language;
|
||||||
$parsedFrame['languagename'] = $this->LanguageLookup($frame_language, false);
|
$parsedFrame['languagename'] = $this->LanguageLookup($frame_language, false);
|
||||||
$parsedFrame['description'] = $frame_description;
|
|
||||||
if (!empty($parsedFrame['framenameshort']) && !empty($parsedFrame['data'])) {
|
if (!empty($parsedFrame['framenameshort']) && !empty($parsedFrame['data'])) {
|
||||||
$info['id3v2']['comments'][$parsedFrame['framenameshort']][] = getid3_lib::iconv_fallback($parsedFrame['encoding'], $info['id3v2']['encoding'], $parsedFrame['data']);
|
$info['id3v2']['comments'][$parsedFrame['framenameshort']][] = getid3_lib::iconv_fallback($parsedFrame['encoding'], $info['id3v2']['encoding'], $parsedFrame['data']);
|
||||||
}
|
}
|
||||||
|
@ -1061,7 +1054,7 @@ class getid3_id3v2 extends getid3_handler
|
||||||
$parsedFrame['lyrics'][$timestampindex]['data'] = substr($frame_remainingdata, $frame_offset, $frame_terminatorpos - $frame_offset);
|
$parsedFrame['lyrics'][$timestampindex]['data'] = substr($frame_remainingdata, $frame_offset, $frame_terminatorpos - $frame_offset);
|
||||||
|
|
||||||
$frame_remainingdata = substr($frame_remainingdata, $frame_terminatorpos + strlen($frame_textencoding_terminator));
|
$frame_remainingdata = substr($frame_remainingdata, $frame_terminatorpos + strlen($frame_textencoding_terminator));
|
||||||
if (($timestampindex == 0) && (ord($frame_remainingdata{0}) != 0)) {
|
if (($timestampindex == 0) && (ord($frame_remainingdata[0]) != 0)) {
|
||||||
// timestamp probably omitted for first data item
|
// timestamp probably omitted for first data item
|
||||||
} else {
|
} else {
|
||||||
$parsedFrame['lyrics'][$timestampindex]['timestamp'] = getid3_lib::BigEndian2Int(substr($frame_remainingdata, 0, 4));
|
$parsedFrame['lyrics'][$timestampindex]['timestamp'] = getid3_lib::BigEndian2Int(substr($frame_remainingdata, 0, 4));
|
||||||
|
@ -1102,19 +1095,16 @@ class getid3_id3v2 extends getid3_handler
|
||||||
if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator), 1)) === 0) {
|
if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator), 1)) === 0) {
|
||||||
$frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00
|
$frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00
|
||||||
}
|
}
|
||||||
$frame_description = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
|
$parsedFrame['description'] = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
|
||||||
if (in_array($frame_description, array("\x00", "\x00\x00", "\xFF\xFE", "\xFE\xFF"))) {
|
$parsedFrame['description'] = $this->MakeUTF16emptyStringEmpty($parsedFrame['description']);
|
||||||
// if description only contains a BOM or terminator then make it blank
|
|
||||||
$frame_description = '';
|
|
||||||
}
|
|
||||||
$frame_text = (string) substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator));
|
$frame_text = (string) substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator));
|
||||||
|
$frame_text = $this->RemoveStringTerminator($frame_text, $frame_textencoding_terminator);
|
||||||
|
|
||||||
$parsedFrame['encodingid'] = $frame_textencoding;
|
$parsedFrame['encodingid'] = $frame_textencoding;
|
||||||
$parsedFrame['encoding'] = $this->TextEncodingNameLookup($frame_textencoding);
|
$parsedFrame['encoding'] = $this->TextEncodingNameLookup($frame_textencoding);
|
||||||
|
|
||||||
$parsedFrame['language'] = $frame_language;
|
$parsedFrame['language'] = $frame_language;
|
||||||
$parsedFrame['languagename'] = $this->LanguageLookup($frame_language, false);
|
$parsedFrame['languagename'] = $this->LanguageLookup($frame_language, false);
|
||||||
$parsedFrame['description'] = $frame_description;
|
|
||||||
$parsedFrame['data'] = $frame_text;
|
$parsedFrame['data'] = $frame_text;
|
||||||
if (!empty($parsedFrame['framenameshort']) && !empty($parsedFrame['data'])) {
|
if (!empty($parsedFrame['framenameshort']) && !empty($parsedFrame['data'])) {
|
||||||
$commentkey = ($parsedFrame['description'] ? $parsedFrame['description'] : (!empty($info['id3v2']['comments'][$parsedFrame['framenameshort']]) ? count($info['id3v2']['comments'][$parsedFrame['framenameshort']]) : 0));
|
$commentkey = ($parsedFrame['description'] ? $parsedFrame['description'] : (!empty($info['id3v2']['comments'][$parsedFrame['framenameshort']]) ? count($info['id3v2']['comments'][$parsedFrame['framenameshort']]) : 0));
|
||||||
|
@ -1407,30 +1397,26 @@ class getid3_id3v2 extends getid3_handler
|
||||||
if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator), 1)) === 0) {
|
if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator), 1)) === 0) {
|
||||||
$frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00
|
$frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00
|
||||||
}
|
}
|
||||||
$frame_description = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
|
$parsedFrame['description'] = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
|
||||||
if (in_array($frame_description, array("\x00", "\x00\x00", "\xFF\xFE", "\xFE\xFF"))) {
|
$parsedFrame['description'] = $this->MakeUTF16emptyStringEmpty($parsedFrame['description']);
|
||||||
// if description only contains a BOM or terminator then make it blank
|
$parsedFrame['encodingid'] = $frame_textencoding;
|
||||||
$frame_description = '';
|
$parsedFrame['encoding'] = $this->TextEncodingNameLookup($frame_textencoding);
|
||||||
}
|
|
||||||
$parsedFrame['encodingid'] = $frame_textencoding;
|
|
||||||
$parsedFrame['encoding'] = $this->TextEncodingNameLookup($frame_textencoding);
|
|
||||||
|
|
||||||
if ($id3v2_majorversion == 2) {
|
if ($id3v2_majorversion == 2) {
|
||||||
$parsedFrame['imagetype'] = $frame_imagetype;
|
$parsedFrame['imagetype'] = isset($frame_imagetype) ? $frame_imagetype : null;
|
||||||
} else {
|
} else {
|
||||||
$parsedFrame['mime'] = $frame_mimetype;
|
$parsedFrame['mime'] = isset($frame_mimetype) ? $frame_mimetype : null;
|
||||||
}
|
}
|
||||||
$parsedFrame['picturetypeid'] = $frame_picturetype;
|
$parsedFrame['picturetypeid'] = $frame_picturetype;
|
||||||
$parsedFrame['picturetype'] = $this->APICPictureTypeLookup($frame_picturetype);
|
$parsedFrame['picturetype'] = $this->APICPictureTypeLookup($frame_picturetype);
|
||||||
$parsedFrame['description'] = $frame_description;
|
$parsedFrame['data'] = substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator));
|
||||||
$parsedFrame['data'] = substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator));
|
$parsedFrame['datalength'] = strlen($parsedFrame['data']);
|
||||||
$parsedFrame['datalength'] = strlen($parsedFrame['data']);
|
|
||||||
|
|
||||||
$parsedFrame['image_mime'] = '';
|
$parsedFrame['image_mime'] = '';
|
||||||
$imageinfo = array();
|
$imageinfo = array();
|
||||||
if ($imagechunkcheck = getid3_lib::GetDataImageSize($parsedFrame['data'], $imageinfo)) {
|
if ($imagechunkcheck = getid3_lib::GetDataImageSize($parsedFrame['data'], $imageinfo)) {
|
||||||
if (($imagechunkcheck[2] >= 1) && ($imagechunkcheck[2] <= 3)) {
|
if (($imagechunkcheck[2] >= 1) && ($imagechunkcheck[2] <= 3)) {
|
||||||
$parsedFrame['image_mime'] = 'image/'.getid3_lib::ImageTypesLookup($imagechunkcheck[2]);
|
$parsedFrame['image_mime'] = image_type_to_mime_type($imagechunkcheck[2]);
|
||||||
if ($imagechunkcheck[0]) {
|
if ($imagechunkcheck[0]) {
|
||||||
$parsedFrame['image_width'] = $imagechunkcheck[0];
|
$parsedFrame['image_width'] = $imagechunkcheck[0];
|
||||||
}
|
}
|
||||||
|
@ -1446,6 +1432,7 @@ class getid3_id3v2 extends getid3_handler
|
||||||
unset($parsedFrame['data']);
|
unset($parsedFrame['data']);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
$dir = '';
|
||||||
if ($this->getid3->option_save_attachments === true) {
|
if ($this->getid3->option_save_attachments === true) {
|
||||||
// great
|
// great
|
||||||
/*
|
/*
|
||||||
|
@ -1533,11 +1520,8 @@ class getid3_id3v2 extends getid3_handler
|
||||||
if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator), 1)) === 0) {
|
if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator), 1)) === 0) {
|
||||||
$frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00
|
$frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00
|
||||||
}
|
}
|
||||||
$frame_description = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
|
$parsedFrame['description'] = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
|
||||||
if (in_array($frame_description, array("\x00", "\x00\x00", "\xFF\xFE", "\xFE\xFF"))) {
|
$parsedFrame['description'] = $this->MakeUTF16emptyStringEmpty($parsedFrame['description']);
|
||||||
// if description only contains a BOM or terminator then make it blank
|
|
||||||
$frame_description = '';
|
|
||||||
}
|
|
||||||
$frame_offset = $frame_terminatorpos + strlen($frame_textencoding_terminator);
|
$frame_offset = $frame_terminatorpos + strlen($frame_textencoding_terminator);
|
||||||
|
|
||||||
$parsedFrame['objectdata'] = (string) substr($parsedFrame['data'], $frame_offset);
|
$parsedFrame['objectdata'] = (string) substr($parsedFrame['data'], $frame_offset);
|
||||||
|
@ -1546,7 +1530,6 @@ class getid3_id3v2 extends getid3_handler
|
||||||
|
|
||||||
$parsedFrame['mime'] = $frame_mimetype;
|
$parsedFrame['mime'] = $frame_mimetype;
|
||||||
$parsedFrame['filename'] = $frame_filename;
|
$parsedFrame['filename'] = $frame_filename;
|
||||||
$parsedFrame['description'] = $frame_description;
|
|
||||||
unset($parsedFrame['data']);
|
unset($parsedFrame['data']);
|
||||||
|
|
||||||
|
|
||||||
|
@ -1616,16 +1599,12 @@ class getid3_id3v2 extends getid3_handler
|
||||||
$frame_offset = $frame_terminatorpos + strlen("\x00");
|
$frame_offset = $frame_terminatorpos + strlen("\x00");
|
||||||
|
|
||||||
$frame_terminatorpos = strpos($parsedFrame['data'], "\x00", $frame_offset);
|
$frame_terminatorpos = strpos($parsedFrame['data'], "\x00", $frame_offset);
|
||||||
$frame_description = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
|
$parsedFrame['description'] = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
|
||||||
if (in_array($frame_description, array("\x00", "\x00\x00", "\xFF\xFE", "\xFE\xFF"))) {
|
$parsedFrame['description'] = $this->MakeUTF16emptyStringEmpty($parsedFrame['description']);
|
||||||
// if description only contains a BOM or terminator then make it blank
|
|
||||||
$frame_description = '';
|
|
||||||
}
|
|
||||||
$frame_offset = $frame_terminatorpos + strlen("\x00");
|
$frame_offset = $frame_terminatorpos + strlen("\x00");
|
||||||
|
|
||||||
$parsedFrame['ownerid'] = $frame_ownerid;
|
$parsedFrame['ownerid'] = $frame_ownerid;
|
||||||
$parsedFrame['data'] = (string) substr($parsedFrame['data'], $frame_offset);
|
$parsedFrame['data'] = (string) substr($parsedFrame['data'], $frame_offset);
|
||||||
$parsedFrame['description'] = $frame_description;
|
|
||||||
unset($parsedFrame['data']);
|
unset($parsedFrame['data']);
|
||||||
|
|
||||||
|
|
||||||
|
@ -1721,7 +1700,8 @@ class getid3_id3v2 extends getid3_handler
|
||||||
$parsedFrame['encodingid'] = $frame_textencoding;
|
$parsedFrame['encodingid'] = $frame_textencoding;
|
||||||
$parsedFrame['encoding'] = $this->TextEncodingNameLookup($frame_textencoding);
|
$parsedFrame['encoding'] = $this->TextEncodingNameLookup($frame_textencoding);
|
||||||
|
|
||||||
$parsedFrame['data'] = (string) substr($parsedFrame['data'], $frame_offset);
|
$parsedFrame['data'] = (string) substr($parsedFrame['data'], $frame_offset);
|
||||||
|
$parsedFrame['data'] = $this->RemoveStringTerminator($parsedFrame['data'], $this->TextEncodingTerminatorLookup($frame_textencoding));
|
||||||
if (!empty($parsedFrame['framenameshort']) && !empty($parsedFrame['data'])) {
|
if (!empty($parsedFrame['framenameshort']) && !empty($parsedFrame['data'])) {
|
||||||
$info['id3v2']['comments'][$parsedFrame['framenameshort']][] = getid3_lib::iconv_fallback($parsedFrame['encoding'], $info['id3v2']['encoding'], $parsedFrame['data']);
|
$info['id3v2']['comments'][$parsedFrame['framenameshort']][] = getid3_lib::iconv_fallback($parsedFrame['encoding'], $info['id3v2']['encoding'], $parsedFrame['data']);
|
||||||
}
|
}
|
||||||
|
@ -1759,6 +1739,7 @@ class getid3_id3v2 extends getid3_handler
|
||||||
$frame_offset += 8;
|
$frame_offset += 8;
|
||||||
|
|
||||||
$parsedFrame['seller'] = (string) substr($parsedFrame['data'], $frame_offset);
|
$parsedFrame['seller'] = (string) substr($parsedFrame['data'], $frame_offset);
|
||||||
|
$parsedFrame['seller'] = $this->RemoveStringTerminator($parsedFrame['seller'], $this->TextEncodingTerminatorLookup($frame_textencoding));
|
||||||
unset($parsedFrame['data']);
|
unset($parsedFrame['data']);
|
||||||
|
|
||||||
|
|
||||||
|
@ -1817,11 +1798,8 @@ class getid3_id3v2 extends getid3_handler
|
||||||
if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator), 1)) === 0) {
|
if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator), 1)) === 0) {
|
||||||
$frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00
|
$frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00
|
||||||
}
|
}
|
||||||
$frame_description = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
|
$parsedFrame['description'] = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
|
||||||
if (in_array($frame_description, array("\x00", "\x00\x00", "\xFF\xFE", "\xFE\xFF"))) {
|
$parsedFrame['description'] = $this->MakeUTF16emptyStringEmpty($parsedFrame['description']);
|
||||||
// if description only contains a BOM or terminator then make it blank
|
|
||||||
$frame_description = '';
|
|
||||||
}
|
|
||||||
$frame_offset = $frame_terminatorpos + strlen($frame_textencoding_terminator);
|
$frame_offset = $frame_terminatorpos + strlen($frame_textencoding_terminator);
|
||||||
|
|
||||||
$frame_terminatorpos = strpos($parsedFrame['data'], "\x00", $frame_offset);
|
$frame_terminatorpos = strpos($parsedFrame['data'], "\x00", $frame_offset);
|
||||||
|
@ -1838,7 +1816,6 @@ class getid3_id3v2 extends getid3_handler
|
||||||
$parsedFrame['receivedasid'] = $frame_receivedasid;
|
$parsedFrame['receivedasid'] = $frame_receivedasid;
|
||||||
$parsedFrame['receivedas'] = $this->COMRReceivedAsLookup($frame_receivedasid);
|
$parsedFrame['receivedas'] = $this->COMRReceivedAsLookup($frame_receivedasid);
|
||||||
$parsedFrame['sellername'] = $frame_sellername;
|
$parsedFrame['sellername'] = $frame_sellername;
|
||||||
$parsedFrame['description'] = $frame_description;
|
|
||||||
$parsedFrame['mime'] = $frame_mimetype;
|
$parsedFrame['mime'] = $frame_mimetype;
|
||||||
$parsedFrame['logo'] = $frame_sellerlogo;
|
$parsedFrame['logo'] = $frame_sellerlogo;
|
||||||
unset($parsedFrame['data']);
|
unset($parsedFrame['data']);
|
||||||
|
@ -2002,9 +1979,9 @@ class getid3_id3v2 extends getid3_handler
|
||||||
// Element ID <text string> $00
|
// Element ID <text string> $00
|
||||||
// Start time $xx xx xx xx
|
// Start time $xx xx xx xx
|
||||||
// End time $xx xx xx xx
|
// End time $xx xx xx xx
|
||||||
// Start offset $xx xx xx xx
|
// Start offset $xx xx xx xx
|
||||||
// End offset $xx xx xx xx
|
// End offset $xx xx xx xx
|
||||||
// <Optional embedded sub-frames>
|
// <Optional embedded sub-frames>
|
||||||
|
|
||||||
$frame_offset = 0;
|
$frame_offset = 0;
|
||||||
@list($parsedFrame['element_id']) = explode("\x00", $parsedFrame['data'], 2);
|
@list($parsedFrame['element_id']) = explode("\x00", $parsedFrame['data'], 2);
|
||||||
|
@ -2045,7 +2022,7 @@ class getid3_id3v2 extends getid3_handler
|
||||||
$subframe['encodingid'] = ord(substr($subframe_rawdata, 0, 1));
|
$subframe['encodingid'] = ord(substr($subframe_rawdata, 0, 1));
|
||||||
$subframe['text'] = substr($subframe_rawdata, 1);
|
$subframe['text'] = substr($subframe_rawdata, 1);
|
||||||
$subframe['encoding'] = $this->TextEncodingNameLookup($subframe['encodingid']);
|
$subframe['encoding'] = $this->TextEncodingNameLookup($subframe['encodingid']);
|
||||||
$encoding_converted_text = trim(getid3_lib::iconv_fallback($subframe['encoding'], $info['encoding'], $subframe['text']));;
|
$encoding_converted_text = trim(getid3_lib::iconv_fallback($subframe['encoding'], $info['encoding'], $subframe['text']));
|
||||||
switch (substr($encoding_converted_text, 0, 2)) {
|
switch (substr($encoding_converted_text, 0, 2)) {
|
||||||
case "\xFF\xFE":
|
case "\xFF\xFE":
|
||||||
case "\xFE\xFF":
|
case "\xFE\xFF":
|
||||||
|
@ -2065,22 +2042,51 @@ class getid3_id3v2 extends getid3_handler
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (($subframe['name'] == 'TIT2') || ($subframe['name'] == 'TIT3')) {
|
switch ($subframe['name']) {
|
||||||
if ($subframe['name'] == 'TIT2') {
|
case 'TIT2':
|
||||||
$parsedFrame['chapter_name'] = $encoding_converted_text;
|
$parsedFrame['chapter_name'] = $encoding_converted_text;
|
||||||
} elseif ($subframe['name'] == 'TIT3') {
|
$parsedFrame['subframes'][] = $subframe;
|
||||||
|
break;
|
||||||
|
case 'TIT3':
|
||||||
$parsedFrame['chapter_description'] = $encoding_converted_text;
|
$parsedFrame['chapter_description'] = $encoding_converted_text;
|
||||||
}
|
$parsedFrame['subframes'][] = $subframe;
|
||||||
$parsedFrame['subframes'][] = $subframe;
|
break;
|
||||||
} else {
|
case 'WXXX':
|
||||||
$this->warning('ID3v2.CHAP subframe "'.$subframe['name'].'" not handled (only TIT2 and TIT3)');
|
list($subframe['chapter_url_description'], $subframe['chapter_url']) = explode("\x00", $encoding_converted_text, 2);
|
||||||
|
$parsedFrame['chapter_url'][$subframe['chapter_url_description']] = $subframe['chapter_url'];
|
||||||
|
$parsedFrame['subframes'][] = $subframe;
|
||||||
|
break;
|
||||||
|
case 'APIC':
|
||||||
|
if (preg_match('#^([^\\x00]+)*\\x00(.)([^\\x00]+)*\\x00(.+)$#s', $subframe['text'], $matches)) {
|
||||||
|
list($dummy, $subframe_apic_mime, $subframe_apic_picturetype, $subframe_apic_description, $subframe_apic_picturedata) = $matches;
|
||||||
|
$subframe['image_mime'] = trim(getid3_lib::iconv_fallback($subframe['encoding'], $info['encoding'], $subframe_apic_mime));
|
||||||
|
$subframe['picture_type'] = $this->APICPictureTypeLookup($subframe_apic_picturetype);
|
||||||
|
$subframe['description'] = trim(getid3_lib::iconv_fallback($subframe['encoding'], $info['encoding'], $subframe_apic_description));
|
||||||
|
if (strlen($this->TextEncodingTerminatorLookup($subframe['encoding'])) == 2) {
|
||||||
|
// the null terminator between "description" and "picture data" could be either 1 byte (ISO-8859-1, UTF-8) or two bytes (UTF-16)
|
||||||
|
// the above regex assumes one byte, if it's actually two then strip the second one here
|
||||||
|
$subframe_apic_picturedata = substr($subframe_apic_picturedata, 1);
|
||||||
|
}
|
||||||
|
$subframe['data'] = $subframe_apic_picturedata;
|
||||||
|
unset($dummy, $subframe_apic_mime, $subframe_apic_picturetype, $subframe_apic_description, $subframe_apic_picturedata);
|
||||||
|
unset($subframe['text'], $parsedFrame['text']);
|
||||||
|
$parsedFrame['subframes'][] = $subframe;
|
||||||
|
$parsedFrame['picture_present'] = true;
|
||||||
|
} else {
|
||||||
|
$this->warning('ID3v2.CHAP subframe #'.(count($parsedFrame['subframes']) + 1).' "'.$subframe['name'].'" not in expected format');
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$this->warning('ID3v2.CHAP subframe "'.$subframe['name'].'" not handled (supported: TIT2, TIT3, WXXX, APIC)');
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
unset($subframe_rawdata, $subframe, $encoding_converted_text);
|
unset($subframe_rawdata, $subframe, $encoding_converted_text);
|
||||||
|
unset($parsedFrame['data']); // debatable whether this this be here, without it the returned structure may contain a large amount of duplicate data if chapters contain APIC
|
||||||
}
|
}
|
||||||
|
|
||||||
$id3v2_chapter_entry = array();
|
$id3v2_chapter_entry = array();
|
||||||
foreach (array('id', 'time_begin', 'time_end', 'offset_begin', 'offset_end', 'chapter_name', 'chapter_description') as $id3v2_chapter_key) {
|
foreach (array('id', 'time_begin', 'time_end', 'offset_begin', 'offset_end', 'chapter_name', 'chapter_description', 'chapter_url', 'picture_present') as $id3v2_chapter_key) {
|
||||||
if (isset($parsedFrame[$id3v2_chapter_key])) {
|
if (isset($parsedFrame[$id3v2_chapter_key])) {
|
||||||
$id3v2_chapter_entry[$id3v2_chapter_key] = $parsedFrame[$id3v2_chapter_key];
|
$id3v2_chapter_entry[$id3v2_chapter_key] = $parsedFrame[$id3v2_chapter_key];
|
||||||
}
|
}
|
||||||
|
@ -2099,7 +2105,7 @@ class getid3_id3v2 extends getid3_handler
|
||||||
// CTOC flags %xx
|
// CTOC flags %xx
|
||||||
// Entry count $xx
|
// Entry count $xx
|
||||||
// Child Element ID <string>$00 /* zero or more child CHAP or CTOC entries */
|
// Child Element ID <string>$00 /* zero or more child CHAP or CTOC entries */
|
||||||
// <Optional embedded sub-frames>
|
// <Optional embedded sub-frames>
|
||||||
|
|
||||||
$frame_offset = 0;
|
$frame_offset = 0;
|
||||||
@list($parsedFrame['element_id']) = explode("\x00", $parsedFrame['data'], 2);
|
@list($parsedFrame['element_id']) = explode("\x00", $parsedFrame['data'], 2);
|
||||||
|
@ -2181,11 +2187,20 @@ class getid3_id3v2 extends getid3_handler
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $data
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public function DeUnsynchronise($data) {
|
public function DeUnsynchronise($data) {
|
||||||
return str_replace("\xFF\x00", "\xFF", $data);
|
return str_replace("\xFF\x00", "\xFF", $data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $index
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public function LookupExtendedHeaderRestrictionsTagSizeLimits($index) {
|
public function LookupExtendedHeaderRestrictionsTagSizeLimits($index) {
|
||||||
static $LookupExtendedHeaderRestrictionsTagSizeLimits = array(
|
static $LookupExtendedHeaderRestrictionsTagSizeLimits = array(
|
||||||
0x00 => 'No more than 128 frames and 1 MB total tag size',
|
0x00 => 'No more than 128 frames and 1 MB total tag size',
|
||||||
|
@ -2196,6 +2211,11 @@ class getid3_id3v2 extends getid3_handler
|
||||||
return (isset($LookupExtendedHeaderRestrictionsTagSizeLimits[$index]) ? $LookupExtendedHeaderRestrictionsTagSizeLimits[$index] : '');
|
return (isset($LookupExtendedHeaderRestrictionsTagSizeLimits[$index]) ? $LookupExtendedHeaderRestrictionsTagSizeLimits[$index] : '');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $index
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public function LookupExtendedHeaderRestrictionsTextEncodings($index) {
|
public function LookupExtendedHeaderRestrictionsTextEncodings($index) {
|
||||||
static $LookupExtendedHeaderRestrictionsTextEncodings = array(
|
static $LookupExtendedHeaderRestrictionsTextEncodings = array(
|
||||||
0x00 => 'No restrictions',
|
0x00 => 'No restrictions',
|
||||||
|
@ -2204,6 +2224,11 @@ class getid3_id3v2 extends getid3_handler
|
||||||
return (isset($LookupExtendedHeaderRestrictionsTextEncodings[$index]) ? $LookupExtendedHeaderRestrictionsTextEncodings[$index] : '');
|
return (isset($LookupExtendedHeaderRestrictionsTextEncodings[$index]) ? $LookupExtendedHeaderRestrictionsTextEncodings[$index] : '');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $index
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public function LookupExtendedHeaderRestrictionsTextFieldSize($index) {
|
public function LookupExtendedHeaderRestrictionsTextFieldSize($index) {
|
||||||
static $LookupExtendedHeaderRestrictionsTextFieldSize = array(
|
static $LookupExtendedHeaderRestrictionsTextFieldSize = array(
|
||||||
0x00 => 'No restrictions',
|
0x00 => 'No restrictions',
|
||||||
|
@ -2214,6 +2239,11 @@ class getid3_id3v2 extends getid3_handler
|
||||||
return (isset($LookupExtendedHeaderRestrictionsTextFieldSize[$index]) ? $LookupExtendedHeaderRestrictionsTextFieldSize[$index] : '');
|
return (isset($LookupExtendedHeaderRestrictionsTextFieldSize[$index]) ? $LookupExtendedHeaderRestrictionsTextFieldSize[$index] : '');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $index
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public function LookupExtendedHeaderRestrictionsImageEncoding($index) {
|
public function LookupExtendedHeaderRestrictionsImageEncoding($index) {
|
||||||
static $LookupExtendedHeaderRestrictionsImageEncoding = array(
|
static $LookupExtendedHeaderRestrictionsImageEncoding = array(
|
||||||
0x00 => 'No restrictions',
|
0x00 => 'No restrictions',
|
||||||
|
@ -2222,6 +2252,11 @@ class getid3_id3v2 extends getid3_handler
|
||||||
return (isset($LookupExtendedHeaderRestrictionsImageEncoding[$index]) ? $LookupExtendedHeaderRestrictionsImageEncoding[$index] : '');
|
return (isset($LookupExtendedHeaderRestrictionsImageEncoding[$index]) ? $LookupExtendedHeaderRestrictionsImageEncoding[$index] : '');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $index
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public function LookupExtendedHeaderRestrictionsImageSizeSize($index) {
|
public function LookupExtendedHeaderRestrictionsImageSizeSize($index) {
|
||||||
static $LookupExtendedHeaderRestrictionsImageSizeSize = array(
|
static $LookupExtendedHeaderRestrictionsImageSizeSize = array(
|
||||||
0x00 => 'No restrictions',
|
0x00 => 'No restrictions',
|
||||||
|
@ -2232,6 +2267,11 @@ class getid3_id3v2 extends getid3_handler
|
||||||
return (isset($LookupExtendedHeaderRestrictionsImageSizeSize[$index]) ? $LookupExtendedHeaderRestrictionsImageSizeSize[$index] : '');
|
return (isset($LookupExtendedHeaderRestrictionsImageSizeSize[$index]) ? $LookupExtendedHeaderRestrictionsImageSizeSize[$index] : '');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $currencyid
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public function LookupCurrencyUnits($currencyid) {
|
public function LookupCurrencyUnits($currencyid) {
|
||||||
|
|
||||||
$begin = __LINE__;
|
$begin = __LINE__;
|
||||||
|
@ -2428,7 +2468,11 @@ class getid3_id3v2 extends getid3_handler
|
||||||
return getid3_lib::EmbeddedLookup($currencyid, $begin, __LINE__, __FILE__, 'id3v2-currency-units');
|
return getid3_lib::EmbeddedLookup($currencyid, $begin, __LINE__, __FILE__, 'id3v2-currency-units');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $currencyid
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public function LookupCurrencyCountry($currencyid) {
|
public function LookupCurrencyCountry($currencyid) {
|
||||||
|
|
||||||
$begin = __LINE__;
|
$begin = __LINE__;
|
||||||
|
@ -2624,8 +2668,12 @@ class getid3_id3v2 extends getid3_handler
|
||||||
return getid3_lib::EmbeddedLookup($currencyid, $begin, __LINE__, __FILE__, 'id3v2-currency-country');
|
return getid3_lib::EmbeddedLookup($currencyid, $begin, __LINE__, __FILE__, 'id3v2-currency-country');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $languagecode
|
||||||
|
* @param bool $casesensitive
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public static function LanguageLookup($languagecode, $casesensitive=false) {
|
public static function LanguageLookup($languagecode, $casesensitive=false) {
|
||||||
|
|
||||||
if (!$casesensitive) {
|
if (!$casesensitive) {
|
||||||
|
@ -3081,7 +3129,11 @@ class getid3_id3v2 extends getid3_handler
|
||||||
return getid3_lib::EmbeddedLookup($languagecode, $begin, __LINE__, __FILE__, 'id3v2-languagecode');
|
return getid3_lib::EmbeddedLookup($languagecode, $begin, __LINE__, __FILE__, 'id3v2-languagecode');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $index
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public static function ETCOEventLookup($index) {
|
public static function ETCOEventLookup($index) {
|
||||||
if (($index >= 0x17) && ($index <= 0xDF)) {
|
if (($index >= 0x17) && ($index <= 0xDF)) {
|
||||||
return 'reserved for future use';
|
return 'reserved for future use';
|
||||||
|
@ -3125,6 +3177,11 @@ class getid3_id3v2 extends getid3_handler
|
||||||
return (isset($EventLookup[$index]) ? $EventLookup[$index] : '');
|
return (isset($EventLookup[$index]) ? $EventLookup[$index] : '');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $index
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public static function SYTLContentTypeLookup($index) {
|
public static function SYTLContentTypeLookup($index) {
|
||||||
static $SYTLContentTypeLookup = array(
|
static $SYTLContentTypeLookup = array(
|
||||||
0x00 => 'other',
|
0x00 => 'other',
|
||||||
|
@ -3141,6 +3198,12 @@ class getid3_id3v2 extends getid3_handler
|
||||||
return (isset($SYTLContentTypeLookup[$index]) ? $SYTLContentTypeLookup[$index] : '');
|
return (isset($SYTLContentTypeLookup[$index]) ? $SYTLContentTypeLookup[$index] : '');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $index
|
||||||
|
* @param bool $returnarray
|
||||||
|
*
|
||||||
|
* @return array|string
|
||||||
|
*/
|
||||||
public static function APICPictureTypeLookup($index, $returnarray=false) {
|
public static function APICPictureTypeLookup($index, $returnarray=false) {
|
||||||
static $APICPictureTypeLookup = array(
|
static $APICPictureTypeLookup = array(
|
||||||
0x00 => 'Other',
|
0x00 => 'Other',
|
||||||
|
@ -3171,6 +3234,11 @@ class getid3_id3v2 extends getid3_handler
|
||||||
return (isset($APICPictureTypeLookup[$index]) ? $APICPictureTypeLookup[$index] : '');
|
return (isset($APICPictureTypeLookup[$index]) ? $APICPictureTypeLookup[$index] : '');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $index
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public static function COMRReceivedAsLookup($index) {
|
public static function COMRReceivedAsLookup($index) {
|
||||||
static $COMRReceivedAsLookup = array(
|
static $COMRReceivedAsLookup = array(
|
||||||
0x00 => 'Other',
|
0x00 => 'Other',
|
||||||
|
@ -3187,6 +3255,11 @@ class getid3_id3v2 extends getid3_handler
|
||||||
return (isset($COMRReceivedAsLookup[$index]) ? $COMRReceivedAsLookup[$index] : '');
|
return (isset($COMRReceivedAsLookup[$index]) ? $COMRReceivedAsLookup[$index] : '');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $index
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public static function RVA2ChannelTypeLookup($index) {
|
public static function RVA2ChannelTypeLookup($index) {
|
||||||
static $RVA2ChannelTypeLookup = array(
|
static $RVA2ChannelTypeLookup = array(
|
||||||
0x00 => 'Other',
|
0x00 => 'Other',
|
||||||
|
@ -3203,6 +3276,11 @@ class getid3_id3v2 extends getid3_handler
|
||||||
return (isset($RVA2ChannelTypeLookup[$index]) ? $RVA2ChannelTypeLookup[$index] : '');
|
return (isset($RVA2ChannelTypeLookup[$index]) ? $RVA2ChannelTypeLookup[$index] : '');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $framename
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public static function FrameNameLongLookup($framename) {
|
public static function FrameNameLongLookup($framename) {
|
||||||
|
|
||||||
$begin = __LINE__;
|
$begin = __LINE__;
|
||||||
|
@ -3354,7 +3432,7 @@ class getid3_id3v2 extends getid3_handler
|
||||||
TYER Year
|
TYER Year
|
||||||
UFI Unique file identifier
|
UFI Unique file identifier
|
||||||
UFID Unique file identifier
|
UFID Unique file identifier
|
||||||
ULT Unsychronised lyric/text transcription
|
ULT Unsynchronised lyric/text transcription
|
||||||
USER Terms of use
|
USER Terms of use
|
||||||
USLT Unsynchronised lyric/text transcription
|
USLT Unsynchronised lyric/text transcription
|
||||||
WAF Official audio file webpage
|
WAF Official audio file webpage
|
||||||
|
@ -3386,7 +3464,11 @@ class getid3_id3v2 extends getid3_handler
|
||||||
// from http://privatewww.essex.ac.uk/~djmrob/replaygain/file_format_id3v2.html
|
// from http://privatewww.essex.ac.uk/~djmrob/replaygain/file_format_id3v2.html
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $framename
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public static function FrameNameShortLookup($framename) {
|
public static function FrameNameShortLookup($framename) {
|
||||||
|
|
||||||
$begin = __LINE__;
|
$begin = __LINE__;
|
||||||
|
@ -3538,7 +3620,7 @@ class getid3_id3v2 extends getid3_handler
|
||||||
TYER year
|
TYER year
|
||||||
UFI unique_file_identifier
|
UFI unique_file_identifier
|
||||||
UFID unique_file_identifier
|
UFID unique_file_identifier
|
||||||
ULT unsychronised_lyric
|
ULT unsynchronised_lyric
|
||||||
USER terms_of_use
|
USER terms_of_use
|
||||||
USLT unsynchronised_lyric
|
USLT unsynchronised_lyric
|
||||||
WAF url_file
|
WAF url_file
|
||||||
|
@ -3566,6 +3648,11 @@ class getid3_id3v2 extends getid3_handler
|
||||||
return getid3_lib::EmbeddedLookup($framename, $begin, __LINE__, __FILE__, 'id3v2-framename_short');
|
return getid3_lib::EmbeddedLookup($framename, $begin, __LINE__, __FILE__, 'id3v2-framename_short');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $encoding
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public static function TextEncodingTerminatorLookup($encoding) {
|
public static function TextEncodingTerminatorLookup($encoding) {
|
||||||
// http://www.id3.org/id3v2.4.0-structure.txt
|
// http://www.id3.org/id3v2.4.0-structure.txt
|
||||||
// Frames that allow different types of text encoding contains a text encoding description byte. Possible encodings:
|
// Frames that allow different types of text encoding contains a text encoding description byte. Possible encodings:
|
||||||
|
@ -3579,6 +3666,11 @@ class getid3_id3v2 extends getid3_handler
|
||||||
return (isset($TextEncodingTerminatorLookup[$encoding]) ? $TextEncodingTerminatorLookup[$encoding] : "\x00");
|
return (isset($TextEncodingTerminatorLookup[$encoding]) ? $TextEncodingTerminatorLookup[$encoding] : "\x00");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $encoding
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public static function TextEncodingNameLookup($encoding) {
|
public static function TextEncodingNameLookup($encoding) {
|
||||||
// http://www.id3.org/id3v2.4.0-structure.txt
|
// http://www.id3.org/id3v2.4.0-structure.txt
|
||||||
// Frames that allow different types of text encoding contains a text encoding description byte. Possible encodings:
|
// Frames that allow different types of text encoding contains a text encoding description byte. Possible encodings:
|
||||||
|
@ -3592,6 +3684,41 @@ class getid3_id3v2 extends getid3_handler
|
||||||
return (isset($TextEncodingNameLookup[$encoding]) ? $TextEncodingNameLookup[$encoding] : 'ISO-8859-1');
|
return (isset($TextEncodingNameLookup[$encoding]) ? $TextEncodingNameLookup[$encoding] : 'ISO-8859-1');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $string
|
||||||
|
* @param string $terminator
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function RemoveStringTerminator($string, $terminator) {
|
||||||
|
// Null terminator at end of comment string is somewhat ambiguous in the specification, may or may not be implemented by various taggers. Remove terminator only if present.
|
||||||
|
// https://github.com/JamesHeinrich/getID3/issues/121
|
||||||
|
// https://community.mp3tag.de/t/x-trailing-nulls-in-id3v2-comments/19227
|
||||||
|
if (substr($string, -strlen($terminator), strlen($terminator)) === $terminator) {
|
||||||
|
$string = substr($string, 0, -strlen($terminator));
|
||||||
|
}
|
||||||
|
return $string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $string
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function MakeUTF16emptyStringEmpty($string) {
|
||||||
|
if (in_array($string, array("\x00", "\x00\x00", "\xFF\xFE", "\xFE\xFF"))) {
|
||||||
|
// if string only contains a BOM or terminator then make it actually an empty string
|
||||||
|
$string = '';
|
||||||
|
}
|
||||||
|
return $string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $framename
|
||||||
|
* @param int $id3v2majorversion
|
||||||
|
*
|
||||||
|
* @return bool|int
|
||||||
|
*/
|
||||||
public static function IsValidID3v2FrameName($framename, $id3v2majorversion) {
|
public static function IsValidID3v2FrameName($framename, $id3v2majorversion) {
|
||||||
switch ($id3v2majorversion) {
|
switch ($id3v2majorversion) {
|
||||||
case 2:
|
case 2:
|
||||||
|
@ -3606,12 +3733,19 @@ class getid3_id3v2 extends getid3_handler
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $numberstring
|
||||||
|
* @param bool $allowdecimal
|
||||||
|
* @param bool $allownegative
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
public static function IsANumber($numberstring, $allowdecimal=false, $allownegative=false) {
|
public static function IsANumber($numberstring, $allowdecimal=false, $allownegative=false) {
|
||||||
for ($i = 0; $i < strlen($numberstring); $i++) {
|
for ($i = 0; $i < strlen($numberstring); $i++) {
|
||||||
if ((chr($numberstring{$i}) < chr('0')) || (chr($numberstring{$i}) > chr('9'))) {
|
if ((chr($numberstring[$i]) < chr('0')) || (chr($numberstring[$i]) > chr('9'))) {
|
||||||
if (($numberstring{$i} == '.') && $allowdecimal) {
|
if (($numberstring[$i] == '.') && $allowdecimal) {
|
||||||
// allowed
|
// allowed
|
||||||
} elseif (($numberstring{$i} == '-') && $allownegative && ($i == 0)) {
|
} elseif (($numberstring[$i] == '-') && $allownegative && ($i == 0)) {
|
||||||
// allowed
|
// allowed
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
|
@ -3621,6 +3755,11 @@ class getid3_id3v2 extends getid3_handler
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $datestamp
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
public static function IsValidDateStampString($datestamp) {
|
public static function IsValidDateStampString($datestamp) {
|
||||||
if (strlen($datestamp) != 8) {
|
if (strlen($datestamp) != 8) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -3649,10 +3788,20 @@ class getid3_id3v2 extends getid3_handler
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $majorversion
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
public static function ID3v2HeaderLength($majorversion) {
|
public static function ID3v2HeaderLength($majorversion) {
|
||||||
return (($majorversion == 2) ? 6 : 10);
|
return (($majorversion == 2) ? 6 : 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $frame_name
|
||||||
|
*
|
||||||
|
* @return string|false
|
||||||
|
*/
|
||||||
public static function ID3v22iTunesBrokenFrameName($frame_name) {
|
public static function ID3v22iTunesBrokenFrameName($frame_name) {
|
||||||
// iTunes (multiple versions) has been known to write ID3v2.3 style frames
|
// iTunes (multiple versions) has been known to write ID3v2.3 style frames
|
||||||
// but use ID3v2.2 frame names, right-padded using either [space] or [null]
|
// but use ID3v2.2 frame names, right-padded using either [space] or [null]
|
||||||
|
@ -3739,3 +3888,4 @@ class getid3_id3v2 extends getid3_handler
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////
|
||||||
/// getID3() by James Heinrich <info@getid3.org> //
|
/// getID3() by James Heinrich <info@getid3.org> //
|
||||||
// available at http://getid3.sourceforge.net //
|
// available at https://github.com/JamesHeinrich/getID3 //
|
||||||
// or http://www.getid3.org //
|
// or https://www.getid3.org //
|
||||||
// also https://github.com/JamesHeinrich/getID3 //
|
// or http://getid3.sourceforge.net //
|
||||||
/////////////////////////////////////////////////////////////////
|
// see readme.txt for more details //
|
||||||
// See readme.txt for more details //
|
|
||||||
/////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////
|
||||||
/// //
|
/// //
|
||||||
// module.tag.lyrics3.php //
|
// module.tag.lyrics3.php //
|
||||||
|
@ -17,7 +17,9 @@
|
||||||
|
|
||||||
class getid3_lyrics3 extends getid3_handler
|
class getid3_lyrics3 extends getid3_handler
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
public function Analyze() {
|
public function Analyze() {
|
||||||
$info = &$this->getid3->info;
|
$info = &$this->getid3->info;
|
||||||
|
|
||||||
|
@ -61,7 +63,7 @@ class getid3_lyrics3 extends getid3_handler
|
||||||
|
|
||||||
// Lyrics3v2, no ID3v1, no APE
|
// Lyrics3v2, no ID3v1, no APE
|
||||||
|
|
||||||
$lyrics3size = strrev(substr(strrev($lyrics3_id3v1), 9, 6)) + 6 + strlen('LYRICS200'); // LSZ = lyrics + 'LYRICSBEGIN'; add 6-byte size field; add 'LYRICS200'
|
$lyrics3size = (int) strrev(substr(strrev($lyrics3_id3v1), 9, 6)) + 6 + strlen('LYRICS200'); // LSZ = lyrics + 'LYRICSBEGIN'; add 6-byte size field; add 'LYRICS200'
|
||||||
$lyrics3offset = $info['filesize'] - $lyrics3size;
|
$lyrics3offset = $info['filesize'] - $lyrics3size;
|
||||||
$lyrics3version = 2;
|
$lyrics3version = 2;
|
||||||
|
|
||||||
|
@ -96,7 +98,7 @@ class getid3_lyrics3 extends getid3_handler
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($lyrics3offset)) {
|
if (isset($lyrics3offset) && isset($lyrics3version) && isset($lyrics3size)) {
|
||||||
$info['avdataend'] = $lyrics3offset;
|
$info['avdataend'] = $lyrics3offset;
|
||||||
$this->getLyrics3Data($lyrics3offset, $lyrics3version, $lyrics3size);
|
$this->getLyrics3Data($lyrics3offset, $lyrics3version, $lyrics3size);
|
||||||
|
|
||||||
|
@ -126,6 +128,13 @@ class getid3_lyrics3 extends getid3_handler
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $endoffset
|
||||||
|
* @param int $version
|
||||||
|
* @param int $length
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
public function getLyrics3Data($endoffset, $version, $length) {
|
public function getLyrics3Data($endoffset, $version, $length) {
|
||||||
// http://www.volweb.cz/str/tags.htm
|
// http://www.volweb.cz/str/tags.htm
|
||||||
|
|
||||||
|
@ -142,6 +151,8 @@ class getid3_lyrics3 extends getid3_handler
|
||||||
}
|
}
|
||||||
$rawdata = $this->fread($length);
|
$rawdata = $this->fread($length);
|
||||||
|
|
||||||
|
$ParsedLyrics3 = array();
|
||||||
|
|
||||||
$ParsedLyrics3['raw']['lyrics3version'] = $version;
|
$ParsedLyrics3['raw']['lyrics3version'] = $version;
|
||||||
$ParsedLyrics3['raw']['lyrics3tagsize'] = $length;
|
$ParsedLyrics3['raw']['lyrics3tagsize'] = $length;
|
||||||
$ParsedLyrics3['tag_offset_start'] = $endoffset;
|
$ParsedLyrics3['tag_offset_start'] = $endoffset;
|
||||||
|
@ -250,6 +261,11 @@ class getid3_lyrics3 extends getid3_handler
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $rawtimestamp
|
||||||
|
*
|
||||||
|
* @return int|false
|
||||||
|
*/
|
||||||
public function Lyrics3Timestamp2Seconds($rawtimestamp) {
|
public function Lyrics3Timestamp2Seconds($rawtimestamp) {
|
||||||
if (preg_match('#^\\[([0-9]{2}):([0-9]{2})\\]$#', $rawtimestamp, $regs)) {
|
if (preg_match('#^\\[([0-9]{2}):([0-9]{2})\\]$#', $rawtimestamp, $regs)) {
|
||||||
return (int) (($regs[1] * 60) + $regs[2]);
|
return (int) (($regs[1] * 60) + $regs[2]);
|
||||||
|
@ -257,8 +273,14 @@ class getid3_lyrics3 extends getid3_handler
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $Lyrics3data
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
public function Lyrics3LyricsTimestampParse(&$Lyrics3data) {
|
public function Lyrics3LyricsTimestampParse(&$Lyrics3data) {
|
||||||
$lyricsarray = explode("\r\n", $Lyrics3data['raw']['LYR']);
|
$lyricsarray = explode("\r\n", $Lyrics3data['raw']['LYR']);
|
||||||
|
$notimestamplyricsarray = array();
|
||||||
foreach ($lyricsarray as $key => $lyricline) {
|
foreach ($lyricsarray as $key => $lyricline) {
|
||||||
$regs = array();
|
$regs = array();
|
||||||
unset($thislinetimestamps);
|
unset($thislinetimestamps);
|
||||||
|
@ -287,6 +309,11 @@ class getid3_lyrics3 extends getid3_handler
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $char
|
||||||
|
*
|
||||||
|
* @return bool|null
|
||||||
|
*/
|
||||||
public function IntString2Bool($char) {
|
public function IntString2Bool($char) {
|
||||||
if ($char == '1') {
|
if ($char == '1') {
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////
|
||||||
/// getID3() by James Heinrich <info@getid3.org> //
|
/// getID3() by James Heinrich <info@getid3.org> //
|
||||||
// available at http://getid3.sourceforge.net //
|
// available at http://getid3.sourceforge.net //
|
||||||
// or http://www.getid3.org //
|
// or https://www.getid3.org //
|
||||||
// also https://github.com/JamesHeinrich/getID3 //
|
// also https://github.com/JamesHeinrich/getID3 //
|
||||||
/////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@ -18,9 +18,9 @@ GNU GPL: https://gnu.org/licenses/gpl.html (v3)
|
||||||
|
|
||||||
GNU LGPL: https://gnu.org/licenses/lgpl.html (v3)
|
GNU LGPL: https://gnu.org/licenses/lgpl.html (v3)
|
||||||
|
|
||||||
Mozilla MPL: http://www.mozilla.org/MPL/2.0/ (v2)
|
Mozilla MPL: https://www.mozilla.org/MPL/2.0/ (v2)
|
||||||
|
|
||||||
getID3 Commercial License: http://getid3.org/#gCL (payment required)
|
getID3 Commercial License: https://www.getid3.org/#gCL (payment required)
|
||||||
|
|
||||||
*****************************************************************
|
*****************************************************************
|
||||||
*****************************************************************
|
*****************************************************************
|
||||||
|
@ -28,10 +28,10 @@ Copies of each of the above licenses are included in the 'licenses'
|
||||||
directory of the getID3 distribution.
|
directory of the getID3 distribution.
|
||||||
|
|
||||||
|
|
||||||
+---------------------------------------------+
|
+----------------------------------------------+
|
||||||
| If you want to donate, there is a link on |
|
| If you want to donate, there is a link on |
|
||||||
| http://www.getid3.org for PayPal donations. |
|
| https://www.getid3.org for PayPal donations. |
|
||||||
+---------------------------------------------+
|
+----------------------------------------------+
|
||||||
|
|
||||||
|
|
||||||
Quick Start
|
Quick Start
|
||||||
|
@ -77,7 +77,7 @@ Reads & parses (to varying degrees):
|
||||||
¤ audio-lossy:
|
¤ audio-lossy:
|
||||||
* MP3/MP2/MP1
|
* MP3/MP2/MP1
|
||||||
* MPC / Musepack
|
* MPC / Musepack
|
||||||
* Ogg (Vorbis, OggFLAC, Speex)
|
* Ogg (Vorbis, OggFLAC, Speex, Opus)
|
||||||
* AAC / MP4
|
* AAC / MP4
|
||||||
* AC3
|
* AC3
|
||||||
* DTS
|
* DTS
|
||||||
|
@ -145,9 +145,10 @@ Writes:
|
||||||
Requirements
|
Requirements
|
||||||
===========================================================================
|
===========================================================================
|
||||||
|
|
||||||
* PHP 4.2.0 up to 5.2.x for getID3() 1.7.x (and earlier)
|
* PHP 4.2.0 up to 5.2.x for getID3() 1.7.x (and earlier)
|
||||||
* PHP 5.0.5 (or higher) for getID3() 1.8.x (and up)
|
* PHP 5.0.5 (or higher) for getID3() 1.8.x (and up)
|
||||||
* PHP 5.0.5 (or higher) for getID3() 2.0.x (and up)
|
* PHP 5.3.0 (or higher) for getID3() 1.9.17 (and up)
|
||||||
|
* PHP 5.3.0 (or higher) for getID3() 2.0.x (and up)
|
||||||
* at least 4MB memory for PHP. 8MB or more is highly recommended.
|
* at least 4MB memory for PHP. 8MB or more is highly recommended.
|
||||||
12MB is required with all modules loaded.
|
12MB is required with all modules loaded.
|
||||||
|
|
||||||
|
@ -177,24 +178,32 @@ like this:
|
||||||
// Copy remote file locally to scan with getID3()
|
// Copy remote file locally to scan with getID3()
|
||||||
$remotefilename = 'http://www.example.com/filename.mp3';
|
$remotefilename = 'http://www.example.com/filename.mp3';
|
||||||
if ($fp_remote = fopen($remotefilename, 'rb')) {
|
if ($fp_remote = fopen($remotefilename, 'rb')) {
|
||||||
$localtempfilename = tempnam('/tmp', 'getID3');
|
$localtempfilename = tempnam('/tmp', 'getID3');
|
||||||
if ($fp_local = fopen($localtempfilename, 'wb')) {
|
if ($fp_local = fopen($localtempfilename, 'wb')) {
|
||||||
while ($buffer = fread($fp_remote, 8192)) {
|
while ($buffer = fread($fp_remote, 32768)) {
|
||||||
fwrite($fp_local, $buffer);
|
fwrite($fp_local, $buffer);
|
||||||
}
|
}
|
||||||
fclose($fp_local);
|
fclose($fp_local);
|
||||||
|
|
||||||
|
$remote_headers = array_change_key_case(get_headers($remotefilename, 1), CASE_LOWER);
|
||||||
|
$remote_filesize = (isset($remote_headers['content-length']) ? (is_array($remote_headers['content-length']) ? $remote_headers['content-length'][count($remote_headers['content-length']) - 1] : $remote_headers['content-length']) : null);
|
||||||
|
|
||||||
// Initialize getID3 engine
|
// Initialize getID3 engine
|
||||||
$getID3 = new getID3;
|
$getID3 = new getID3;
|
||||||
|
|
||||||
$ThisFileInfo = $getID3->analyze($filename);
|
$ThisFileInfo = $getID3->analyze($localtempfilename, $remote_filesize, basename($remotefilename));
|
||||||
|
|
||||||
// Delete temporary file
|
// Delete temporary file
|
||||||
unlink($localtempfilename);
|
unlink($localtempfilename);
|
||||||
}
|
}
|
||||||
fclose($fp_remote);
|
fclose($fp_remote);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Note: since v1.9.9-20150212 it is possible a second and third parameter
|
||||||
|
to $getID3->analyze(), for original filesize and original filename
|
||||||
|
respectively. This permits you to download only a portion of a large remote
|
||||||
|
file but get accurate playtime estimates, assuming the format only requires
|
||||||
|
the beginning of the file for correct format analysis.
|
||||||
|
|
||||||
See /demos/demo.write.php for how to write tags.
|
See /demos/demo.write.php for how to write tags.
|
||||||
|
|
||||||
|
@ -292,7 +301,7 @@ could essentially write it today with a one-line function:
|
||||||
|
|
||||||
Future Plans
|
Future Plans
|
||||||
===========================================================================
|
===========================================================================
|
||||||
http://www.getid3.org/phpBB3/viewforum.php?f=7
|
https://www.getid3.org/phpBB3/viewforum.php?f=7
|
||||||
|
|
||||||
* Better support for MP4 container format
|
* Better support for MP4 container format
|
||||||
* Scan for appended ID3v2 tag at end of file per ID3v2.4 specs (Section 5.0)
|
* Scan for appended ID3v2 tag at end of file per ID3v2.4 specs (Section 5.0)
|
||||||
|
@ -334,11 +343,11 @@ http://www.getid3.org/phpBB3/viewforum.php?f=7
|
||||||
* Optional scan-through-frames for AVI verification
|
* Optional scan-through-frames for AVI verification
|
||||||
(thanks rockcohenØmassive-interactive*nl)
|
(thanks rockcohenØmassive-interactive*nl)
|
||||||
* Support for TTF (thanks infoØbutterflyx*com)
|
* Support for TTF (thanks infoØbutterflyx*com)
|
||||||
* Support for DSS (http://www.getid3.org/phpBB3/viewtopic.php?t=171)
|
* Support for DSS (https://www.getid3.org/phpBB3/viewtopic.php?t=171)
|
||||||
* Support for SMAF (http://smaf-yamaha.com/what/demo.html)
|
* Support for SMAF (http://smaf-yamaha.com/what/demo.html)
|
||||||
http://www.getid3.org/phpBB3/viewtopic.php?t=182
|
https://www.getid3.org/phpBB3/viewtopic.php?t=182
|
||||||
* Support for AMR (http://www.getid3.org/phpBB3/viewtopic.php?t=195)
|
* Support for AMR (https://www.getid3.org/phpBB3/viewtopic.php?t=195)
|
||||||
* Support for 3gpp (http://www.getid3.org/phpBB3/viewtopic.php?t=195)
|
* Support for 3gpp (https://www.getid3.org/phpBB3/viewtopic.php?t=195)
|
||||||
* Support for ID4 (http://www.wackysoft.cjb.net grizlyY2KØhotmail*com)
|
* Support for ID4 (http://www.wackysoft.cjb.net grizlyY2KØhotmail*com)
|
||||||
* Parse XML data returned in Ogg comments
|
* Parse XML data returned in Ogg comments
|
||||||
* Parse XML data from Quicktime SMIL metafiles (klausrathØmac*com)
|
* Parse XML data from Quicktime SMIL metafiles (klausrathØmac*com)
|
||||||
|
@ -374,7 +383,7 @@ http://www.getid3.org/phpBB3/viewforum.php?f=7
|
||||||
|
|
||||||
Known Bugs/Issues in getID3() that may be fixed eventually
|
Known Bugs/Issues in getID3() that may be fixed eventually
|
||||||
===========================================================================
|
===========================================================================
|
||||||
http://www.getid3.org/phpBB3/viewtopic.php?t=25
|
https://www.getid3.org/phpBB3/viewtopic.php?t=25
|
||||||
|
|
||||||
* Cannot determine bitrate for MPEG video with VBR video data
|
* Cannot determine bitrate for MPEG video with VBR video data
|
||||||
(need documentation)
|
(need documentation)
|
||||||
|
@ -400,7 +409,7 @@ http://www.getid3.org/phpBB3/viewtopic.php?t=25
|
||||||
|
|
||||||
Known Bugs/Issues in getID3() that cannot be fixed
|
Known Bugs/Issues in getID3() that cannot be fixed
|
||||||
--------------------------------------------------
|
--------------------------------------------------
|
||||||
http://www.getid3.org/phpBB3/viewtopic.php?t=25
|
https://www.getid3.org/phpBB3/viewtopic.php?t=25
|
||||||
|
|
||||||
* 32-bit PHP installations only:
|
* 32-bit PHP installations only:
|
||||||
Files larger than 2GB cannot always be parsed fully by getID3()
|
Files larger than 2GB cannot always be parsed fully by getID3()
|
||||||
|
@ -430,8 +439,15 @@ http://www.getid3.org/phpBB3/viewtopic.php?t=25
|
||||||
|
|
||||||
Known Bugs/Issues in other programs
|
Known Bugs/Issues in other programs
|
||||||
-----------------------------------
|
-----------------------------------
|
||||||
http://www.getid3.org/phpBB3/viewtopic.php?t=25
|
https://www.getid3.org/phpBB3/viewtopic.php?t=25
|
||||||
|
|
||||||
|
* MusicBrainz Picard (at least up to v1.3.2) writes multiple
|
||||||
|
ID3v2.3 genres in non-standard forward-slash separated text
|
||||||
|
rather than parenthesis-numeric+refinement style per the ID3v2.3
|
||||||
|
specs. Tags written in ID3v2.4 mode are written correctly.
|
||||||
|
(detected and worked around by getID3())
|
||||||
|
* PZ TagEditor v4.53.408 has been known to insert ID3v2.3 frames
|
||||||
|
into an existing ID3v2.2 tag which, of course, breaks things
|
||||||
* Windows Media Player (up to v11) and iTunes (up to v10+) do
|
* Windows Media Player (up to v11) and iTunes (up to v10+) do
|
||||||
not correctly handle ID3v2.3 tags with UTF-16BE+BOM
|
not correctly handle ID3v2.3 tags with UTF-16BE+BOM
|
||||||
encoding (they assume the data is UTF-16LE+BOM and either
|
encoding (they assume the data is UTF-16LE+BOM and either
|
||||||
|
@ -451,6 +467,11 @@ http://www.getid3.org/phpBB3/viewtopic.php?t=25
|
||||||
written just "value" (detected by getID3())
|
written just "value" (detected by getID3())
|
||||||
* Oggenc 0.9-rc3 flags the encoded file as ABR whether it's
|
* Oggenc 0.9-rc3 flags the encoded file as ABR whether it's
|
||||||
actually ABR or VBR.
|
actually ABR or VBR.
|
||||||
|
* iTunes (versions "v7.0.0.70" is known-guilty, probably
|
||||||
|
other versions are too) writes ID3v2.3 comment tags using an
|
||||||
|
ID3v2.2 frame name (3-bytes) null-padded to 4 bytes which is
|
||||||
|
not valid for ID3v2.3+
|
||||||
|
(detected by getID3() since 1.9.12-201603221746)
|
||||||
* iTunes (versions "X v2.0.3", "v3.0.1" are known-guilty, probably
|
* iTunes (versions "X v2.0.3", "v3.0.1" are known-guilty, probably
|
||||||
other versions are too) writes ID3v2.3 comment tags using a
|
other versions are too) writes ID3v2.3 comment tags using a
|
||||||
frame name 'COM ' which is not valid for ID3v2.3+ (it's an
|
frame name 'COM ' which is not valid for ID3v2.3+ (it's an
|
||||||
|
@ -601,4 +622,6 @@ Reference material:
|
||||||
* http://cpansearch.perl.org/src/RGIBSON/Audio-DSS-0.02/lib/Audio/DSS.pm
|
* http://cpansearch.perl.org/src/RGIBSON/Audio-DSS-0.02/lib/Audio/DSS.pm
|
||||||
* http://trac.musepack.net/trac/wiki/SV8Specification
|
* http://trac.musepack.net/trac/wiki/SV8Specification
|
||||||
* http://wyday.com/cuesharp/specification.php
|
* http://wyday.com/cuesharp/specification.php
|
||||||
* http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html
|
* http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html
|
||||||
|
* http://www.codeproject.com/Articles/8295/MPEG-Audio-Frame-Header
|
||||||
|
* http://dsd-guide.com/sites/default/files/white-papers/DSFFileFormatSpec_E.pdf
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
*
|
*
|
||||||
* @global string $wp_version
|
* @global string $wp_version
|
||||||
*/
|
*/
|
||||||
$wp_version = '5.3-alpha-46111';
|
$wp_version = '5.3-alpha-46112';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.
|
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.
|
||||||
|
|
Loading…
Reference in New Issue