Simple update
This commit is contained in:
parent
1f083faf60
commit
27bb2c55e9
223
bin/mp3scan
223
bin/mp3scan
@ -1,5 +1,7 @@
|
||||
#!/usr/bin/php
|
||||
<?php
|
||||
use wapmorgan\Mp3Info\Mp3Info;
|
||||
|
||||
$paths = [
|
||||
// as a root package or phar
|
||||
__DIR__.'/../vendor/autoload.php',
|
||||
@ -18,77 +20,178 @@ function init_composer(array $paths) {
|
||||
return false;
|
||||
}
|
||||
if (!init_composer($paths)) die('Run `composer install` firstly.'.PHP_EOL);
|
||||
|
||||
use wapmorgan\Mp3Info\Mp3Info;
|
||||
|
||||
$compare = class_exists('getID3');
|
||||
|
||||
if ($argc == 1)
|
||||
die('Specify file names to scan');
|
||||
|
||||
function formatTime($time) {
|
||||
return floor($time / 60).':'.str_pad(floor($time % 60), 2, 0, STR_PAD_LEFT);
|
||||
}
|
||||
class Mp3InfoConsoleRunner {
|
||||
|
||||
function substrIfLonger($string, $maxLength) {
|
||||
if (strlen($string) > $maxLength) {
|
||||
return substr($string, 0, $maxLength-3).'...';
|
||||
}
|
||||
return $string;
|
||||
}
|
||||
/** @var array */
|
||||
protected $widths = array(
|
||||
'filename' => 0.3,
|
||||
'duration' => 6,
|
||||
'bitRate' => 6,
|
||||
'sampleRate' => 6,
|
||||
'song' => 0.13,
|
||||
'artist' => 0.125,
|
||||
'track' => 5,
|
||||
'parseTime' => 4,
|
||||
);
|
||||
|
||||
function analyze($filename, &$total_duration, &$total_parse_time, $id3v2 = false) {
|
||||
if (!is_readable($filename)) return;
|
||||
try {
|
||||
$audio = new Mp3Info($filename, true);
|
||||
} catch (Exception $e) {
|
||||
var_dump($filename.': '.$e->getMessage());
|
||||
return null;
|
||||
}
|
||||
echo sprintf('%15s | %4s | %7s | %0.1fkHz | %-11s | %-10s | %5d | %.5f', substrIfLonger(basename($filename), 15), formatTime($audio->duration), $audio->isVbr ? 'vbr' : ($audio->bitRate / 1000).'kbps', ($audio->sampleRate / 1000), isset($audio->tags1['song']) ? substrIfLonger($audio->tags1['song'], 11) : null, isset($audio->tags1['artist']) ? substrIfLonger($audio->tags1['artist'], 10) : null, isset($audio->tags1['track']) ? substrIfLonger($audio->tags1['track'], 5) : null, $audio->_parsingTime).PHP_EOL;
|
||||
if ($id3v2 && !empty($audio->tags2)) {
|
||||
foreach ($audio->tags2 as $tag=>$value) {
|
||||
echo ' '.$tag.': ';
|
||||
if ($tag == 'COMM') {
|
||||
foreach ($value as $lang => $comment) {
|
||||
echo '['.$lang.'] '.$comment['short'].'; '.$comment['actual'].PHP_EOL;
|
||||
/** @var string */
|
||||
protected $songRowTempalte;
|
||||
|
||||
/** @var bool */
|
||||
protected $compareWithId3;
|
||||
|
||||
protected $totalDuration = 0;
|
||||
protected $totalParseTime = 0;
|
||||
protected $totalId3ParseTime = 0;
|
||||
|
||||
/**
|
||||
* @param array $fileNames
|
||||
*/
|
||||
public function run(array $fileNames)
|
||||
{
|
||||
$this->adjustOutputSize();
|
||||
$this->songRowTempalte = '%'.$this->widths['filename'].'s | %'.$this->widths['duration'].'s | %'.$this->widths['bitRate'].'s | %'.$this->widths['sampleRate'].'s | %'
|
||||
.$this->widths['song'].'s | %'.$this->widths['artist'].'s | %'.$this->widths['track'].'s | %'.$this->widths['parseTime'].'s';
|
||||
$this->compareWithId3 = class_exists('getID3');
|
||||
|
||||
echo sprintf($this->songRowTempalte, 'File name', 'dur.', 'bitrate', 'sample', 'song', 'artist', 'track',
|
||||
'time').PHP_EOL;
|
||||
|
||||
foreach ($fileNames as $arg) {
|
||||
if (is_dir($arg)) {
|
||||
foreach (glob(rtrim($arg, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.'*.mp3') as $f) {
|
||||
if (is_file($f)) {
|
||||
$this->analyze($f);
|
||||
if ($this->compareWithId3) $this->analyzeId3($f);
|
||||
}
|
||||
}
|
||||
} else
|
||||
echo $value.PHP_EOL;
|
||||
} else if (is_file($arg)) {
|
||||
$this->analyze($arg, true);
|
||||
if ($this->compareWithId3) $this->analyzeId3($arg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
echo sprintf('%42s | %34s', 'Total duration: '.self::formatTime($this->totalDuration), 'Total parsing time: '.round($this->totalParseTime, 5)).PHP_EOL;
|
||||
if ($this->compareWithId3)
|
||||
echo sprintf('%79s', 'Total getId3 parsing time: '.round($this->totalId3ParseTime, 5)).PHP_EOL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $time
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function formatTime($time) {
|
||||
return floor($time / 60).':'.str_pad(floor($time % 60), 2, 0, STR_PAD_LEFT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $string
|
||||
* @param $maxLength
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function substrIfLonger($string, $maxLength) {
|
||||
if (mb_strlen($string) > $maxLength) {
|
||||
return mb_substr($string, 0, $maxLength-3).'...';
|
||||
}
|
||||
return $string;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
protected function adjustOutputSize()
|
||||
{
|
||||
$terminal_width = \wapmorgan\TerminalInfo\TerminalInfo::getWidth();
|
||||
|
||||
foreach ($this->widths as $element => $width) {
|
||||
if ($width >= 1) {
|
||||
continue;
|
||||
}
|
||||
$this->widths[$element] = ceil($width * $terminal_width);
|
||||
}
|
||||
}
|
||||
$total_duration += $audio->duration;
|
||||
$total_parse_time += $audio->_parsingTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $filename
|
||||
* @param bool $id3v2
|
||||
*
|
||||
* @return null|void
|
||||
*/
|
||||
protected function analyze($filename, $id3v2 = false) {
|
||||
if (!is_readable($filename)) return;
|
||||
try {
|
||||
$audio = new Mp3Info($filename, true);
|
||||
} catch (Exception $e) {
|
||||
var_dump($filename.': '.$e->getMessage());
|
||||
return null;
|
||||
}
|
||||
|
||||
function analyzeId3($filename, &$total_parse_time) {
|
||||
static $ID3;
|
||||
if ($ID3 === null) $ID3 = new getID3();
|
||||
echo sprintf($this->songRowTempalte,
|
||||
self::convertToNativeEncoding(self::substrIfLonger(basename($filename), $this->widths['filename'])),
|
||||
self::formatTime($audio->duration),
|
||||
$audio->isVbr ? 'vbr' : ($audio->bitRate / 1000).'kbps',
|
||||
($audio->sampleRate / 1000),
|
||||
isset($audio->tags1['song']) ? self::substrIfLonger($audio->tags1['song'], 11) : null,
|
||||
isset($audio->tags1['artist']) ? self::substrIfLonger($audio->tags1['artist'], 10) : null,
|
||||
isset($audio->tags1['track']) ? self::substrIfLonger($audio->tags1['track'], 5) : null,
|
||||
$audio->_parsingTime)
|
||||
.PHP_EOL;
|
||||
|
||||
$t = microtime(true);
|
||||
$info = $ID3->analyze($filename);
|
||||
$parse_time = microtime(true) - $t;
|
||||
echo sprintf('%15s | %4s | %7s | %0.1fkHz | %-11s | %-10s | %.5f | %5d', substrIfLonger(basename($filename), 15), $info['playtime_string'], $info['audio']['bitrate_mode'] == 'vbr' ? 'vbr' : floor($info['audio']['bitrate'] / 1000).'kbps', ($info['audio']['sample_rate'] / 1000), isset($info['tags']['title']) ? substrIfLonger($info['tags']['title'], 11) : null, isset($info['tags']['artist']) ? substrIfLonger($info['tags']['artist'], 10) : null, null, $parse_time).PHP_EOL;
|
||||
$total_parse_time += $parse_time;
|
||||
if ($id3v2 && !empty($audio->tags2)) {
|
||||
foreach ($audio->tags2 as $tag=>$value) {
|
||||
echo ' '.$tag.': ';
|
||||
if ($tag == 'COMM') {
|
||||
foreach ($value as $lang => $comment) {
|
||||
echo '['.$lang.'] '.$comment['short'].'; '.$comment['actual'].PHP_EOL;
|
||||
}
|
||||
} else
|
||||
echo self::convertToNativeEncoding($value).PHP_EOL;
|
||||
}
|
||||
}
|
||||
$this->totalDuration += $audio->duration;
|
||||
$this->totalParseTime += $audio->_parsingTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $filename
|
||||
*/
|
||||
protected function analyzeId3($filename) {
|
||||
static $ID3;
|
||||
if ($ID3 === null) $ID3 = new getID3();
|
||||
|
||||
$t = microtime(true);
|
||||
$info = $ID3->analyze($filename);
|
||||
$parse_time = microtime(true) - $t;
|
||||
echo sprintf($this->songRowTempalte,
|
||||
self::substrIfLonger(basename($filename), $this->widths['filename']),
|
||||
$info['playtime_string'],
|
||||
$info['audio']['bitrate_mode'] == 'vbr' ? 'vbr' : floor($info['audio']['bitrate'] / 1000).'kbps',
|
||||
($info['audio']['sample_rate'] / 1000),
|
||||
isset($info['tags']['title']) ? self::substrIfLonger($info['tags']['title'], 11) : null,
|
||||
isset($info['tags']['artist']) ? self::substrIfLonger($info['tags']['artist'], 10) :
|
||||
null,
|
||||
null,
|
||||
$parse_time)
|
||||
.PHP_EOL;
|
||||
|
||||
$this->totalId3ParseTime += $parse_time;
|
||||
}
|
||||
|
||||
protected static function convertToNativeEncoding($string)
|
||||
{
|
||||
// if (strncasecmp(PHP_OS, 'win', 3) === 0)
|
||||
// return mb_convert_encoding($string, 'cp1251', 'utf-8');
|
||||
return $string;
|
||||
}
|
||||
}
|
||||
|
||||
array_shift($argv);
|
||||
echo sprintf('%15s | %4s | %7s | %7s | %11s | %10s | %5s | %4s', 'File name', 'dur.', 'bitrate', 'sample', 'song', 'artist', 'track',
|
||||
'time').PHP_EOL;
|
||||
$total_duration = $total_parse_time = $id3_parse_time = 0;
|
||||
foreach ($argv as $arg) {
|
||||
if (is_dir($arg)) {
|
||||
foreach (glob(rtrim($arg, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.'*.mp3') as $f) {
|
||||
if (is_file($f)) {
|
||||
analyze($f, $total_duration, $total_parse_time);
|
||||
if ($compare) analyzeId3($f, $id3_parse_time);
|
||||
}
|
||||
}
|
||||
} else if (is_file($arg)) {
|
||||
analyze($arg, $total_duration, $total_parse_time, true);
|
||||
if ($compare) analyzeId3($f, $id3_parse_time);
|
||||
}
|
||||
}
|
||||
echo sprintf('%42s | %34s', 'Total duration: '.formatTime($total_duration), 'Total parsing time: '.round($total_parse_time, 5)).PHP_EOL;
|
||||
if ($compare) echo sprintf('%79s', 'Total getId3 parsing time: '.round($id3_parse_time, 5)).PHP_EOL;
|
||||
$runner = new Mp3InfoConsoleRunner();
|
||||
$runner->run($argv);
|
||||
|
||||
|
@ -9,5 +9,11 @@
|
||||
"wapmorgan\\Mp3Info\\": "src/"
|
||||
}
|
||||
},
|
||||
"require": {
|
||||
"ext-mbstring": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
"wapmorgan/terminal-info": "dev-master"
|
||||
},
|
||||
"bin": ["bin/mp3scan"]
|
||||
}
|
||||
|
140
src/Mp3Info.php
140
src/Mp3Info.php
@ -1,6 +1,8 @@
|
||||
<?php
|
||||
namespace wapmorgan\Mp3Info;
|
||||
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* This class extracts information about an mpeg audio. (supported mpeg versions: MPEG-1, MPEG-2)
|
||||
* (supported mpeg audio layers: 1, 2, 3).
|
||||
@ -20,10 +22,12 @@ namespace wapmorgan\Mp3Info;
|
||||
* * {@link http://gabriel.mp3-tech.org/mp3infotag.html Xing, Info and Lame tags specifications}
|
||||
*/
|
||||
class Mp3Info {
|
||||
const TAG1_SYNC = "TAG";
|
||||
const TAG2_SYNC = "ID3";
|
||||
const VBR_SYNC = "Xing";
|
||||
const CBR_SYNC = "Info";
|
||||
const TAG1_SYNC = 'TAG';
|
||||
const TAG2_SYNC = 'ID3';
|
||||
const VBR_SYNC = 'Xing';
|
||||
const CBR_SYNC = 'Info';
|
||||
|
||||
const FRAME_SYNC = 0xffe0;
|
||||
|
||||
const META = 1;
|
||||
const TAGS = 2;
|
||||
@ -35,10 +39,10 @@ class Mp3Info {
|
||||
const LAYER_2 = 2;
|
||||
const LAYER_3 = 3;
|
||||
|
||||
const STEREO = "stereo";
|
||||
const JOINT_STEREO = "joint_stereo";
|
||||
const DUAL_MONO = "dual_mono";
|
||||
const MONO = "mono";
|
||||
const STEREO = 'stereo';
|
||||
const JOINT_STEREO = 'joint_stereo';
|
||||
const DUAL_MONO = 'dual_mono';
|
||||
const MONO = 'mono';
|
||||
|
||||
/**
|
||||
* Boolean trigger to enable / disable trace output
|
||||
@ -157,11 +161,17 @@ class Mp3Info {
|
||||
|
||||
/**
|
||||
* $mode is self::META, self::TAGS or their combination.
|
||||
*
|
||||
* @param string $filename
|
||||
* @param bool $parseTags
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function __construct($filename, $parseTags = false) {
|
||||
if (is_null(self::$_bitRateTable)) self::$_bitRateTable = require dirname(__FILE__).'/../data/bitRateTable.php';
|
||||
if (is_null(self::$_sampleRateTable)) self::$_sampleRateTable = require dirname(__FILE__).'/../data/sampleRateTable.php';
|
||||
if (self::$_bitRateTable === null)
|
||||
self::$_bitRateTable = require dirname(__FILE__).'/../data/bitRateTable.php';
|
||||
if (self::$_sampleRateTable === null)
|
||||
self::$_sampleRateTable = require dirname(__FILE__).'/../data/sampleRateTable.php';
|
||||
|
||||
if (!file_exists($filename))
|
||||
throw new \Exception("File ".$filename." is not present!");
|
||||
@ -183,7 +193,7 @@ class Mp3Info {
|
||||
*/
|
||||
private function parseAudio($filename, $fileSize, $mode) {
|
||||
$time = microtime(true);
|
||||
$fp = fopen($filename, "rb");
|
||||
$fp = fopen($filename, 'rb');
|
||||
|
||||
/** Size of audio data (exclude tags size)
|
||||
* @var int */
|
||||
@ -278,10 +288,10 @@ class Mp3Info {
|
||||
}
|
||||
|
||||
switch ($this->codecVersion.($this->channel == self::MONO ? 'mono' : 'stereo')) {
|
||||
case "1stereo": $offset = 36; break;
|
||||
case "1mono": $offset = 21; break;
|
||||
case "2stereo": $offset = 21; break;
|
||||
case "2mono": $offset = 13; break;
|
||||
case '1stereo': $offset = 36; break;
|
||||
case '1mono': $offset = 21; break;
|
||||
case '2stereo': $offset = 21; break;
|
||||
case '2mono': $offset = 13; break;
|
||||
}
|
||||
fseek($fp, $pos + $offset);
|
||||
if (fread($fp, 4) == self::VBR_SYNC) {
|
||||
@ -379,7 +389,7 @@ class Mp3Info {
|
||||
private function readId3v2Body($fp) {
|
||||
// read the rest of the id3v2 header
|
||||
$raw = fread($fp, 7);
|
||||
$data = unpack("cmajor_version/cminor_version/H*", $raw);
|
||||
$data = unpack('cmajor_version/cminor_version/H*', $raw);
|
||||
$this->id3v2MajorVersion = $data['major_version'];
|
||||
$this->id3v2MinorVersion = $data['minor_version'];
|
||||
$data = str_pad(base_convert($data[1], 16, 2), 40, 0, STR_PAD_LEFT);
|
||||
@ -436,7 +446,7 @@ class Mp3Info {
|
||||
break;
|
||||
}
|
||||
|
||||
$data = unpack("Nframe_size/H2flags", substr($raw, 4));
|
||||
$data = unpack('Nframe_size/H2flags', substr($raw, 4));
|
||||
$frame_size = $data['frame_size'];
|
||||
$flags = base_convert($data['flags'], 16, 2);
|
||||
$this->id3v2TagsFlags[$frame_id] = array(
|
||||
@ -455,24 +465,16 @@ class Mp3Info {
|
||||
|
||||
################# Text information frames
|
||||
case 'TALB': # Album/Movie/Show title
|
||||
$raw = fread($fp, $frame_size);
|
||||
// var_dump($raw);
|
||||
$data = unpack("C1encoding/A".($frame_size - 1)."information", $raw);
|
||||
if ((bool)($data['encoding'] == 0x00)) # ISO-8859-1
|
||||
$this->tags2[$frame_id] = mb_convert_encoding($data['information'], 'utf-8', 'iso-8859-1');
|
||||
else # utf-16
|
||||
$this->tags2[$frame_id] = mb_convert_encoding($data['information'], 'utf-8', 'utf-16');
|
||||
case 'TCON': # Content type
|
||||
case 'TYER': # Year
|
||||
case 'TXXX': # User defined text information frame
|
||||
case 'TRCK': # Track number/Position in set
|
||||
case 'TIT2': # Title/songname/content description
|
||||
case 'TPE1': # Lead performer(s)/Soloist(s)
|
||||
$this->tags2[$frame_id] = $this->handleTextFrame($frame_size, fread($fp, $frame_size));
|
||||
break;
|
||||
// case 'TBPM': # BPM (beats per minute)
|
||||
// case 'TCOM': # Composer
|
||||
case 'TCON': # Content type
|
||||
$raw = fread($fp, $frame_size);
|
||||
$data = unpack("C1encoding/A".($frame_size - 1)."information", $raw);
|
||||
if ((bool)($data['encoding'] == 0x00)) # ISO-8859-1
|
||||
$this->tags2[$frame_id] = mb_convert_encoding($data['information'], 'utf-8', 'iso-8859-1');
|
||||
else # utf-16
|
||||
$this->tags2[$frame_id] = mb_convert_encoding($data['information'], 'utf-8', 'utf-16');
|
||||
break;
|
||||
// case 'TCOP': # Copyright message
|
||||
// case 'TDAT': # Date
|
||||
// case 'TDLY': # Playlist delay
|
||||
@ -481,14 +483,6 @@ class Mp3Info {
|
||||
// case 'TFLT': # File type
|
||||
// case 'TIME': # Time
|
||||
// case 'TIT1': # Content group description
|
||||
case 'TIT2': # Title/songname/content description
|
||||
$raw = fread($fp, $frame_size);
|
||||
$data = unpack("C1encoding/A".($frame_size - 1)."information", $raw);
|
||||
if ((bool)($data['encoding'] == 0x00)) # ISO-8859-1
|
||||
$this->tags2[$frame_id] = mb_convert_encoding($data['information'], 'utf-8', 'iso-8859-1');
|
||||
else # utf-16
|
||||
$this->tags2[$frame_id] = mb_convert_encoding($data['information'], 'utf-8', 'utf-16');
|
||||
break;
|
||||
// case 'TIT3': # Subtitle/Description refinement
|
||||
// case 'TKEY': # Initial key
|
||||
// case 'TLAN': # Language(s)
|
||||
@ -500,49 +494,18 @@ class Mp3Info {
|
||||
// case 'TOPE': # Original artist(s)/performer(s)
|
||||
// case 'TORY': # Original release year
|
||||
// case 'TOWN': # File owner/licensee
|
||||
case 'TPE1': # Lead performer(s)/Soloist(s)
|
||||
$raw = fread($fp, $frame_size);
|
||||
$data = unpack("C1encoding/A".($frame_size - 1)."information", $raw);
|
||||
if ((bool)($data['encoding'] == 0x00)) # ISO-8859-1
|
||||
$this->tags2[$frame_id] = mb_convert_encoding($data['information'], 'utf-8', 'iso-8859-1');
|
||||
else # utf-16
|
||||
$this->tags2[$frame_id] = mb_convert_encoding($data['information'], 'utf-8', 'utf-16');
|
||||
break;
|
||||
// case 'TPE2': # Band/orchestra/accompaniment
|
||||
// case 'TPE3': # Conductor/performer refinement
|
||||
// case 'TPE4': # Interpreted, remixed, or otherwise modified by
|
||||
// case 'TPOS': # Part of a set
|
||||
// case 'TPUB': # Publisher
|
||||
case 'TRCK': # Track number/Position in set
|
||||
$raw = fread($fp, $frame_size);
|
||||
$data = unpack("C1encoding/A".($frame_size - 1)."information", $raw);
|
||||
if ((bool)($data['encoding'] == 0x00)) # ISO-8859-1
|
||||
$this->tags2[$frame_id] = mb_convert_encoding($data['information'], 'utf-8', 'iso-8859-1');
|
||||
else # utf-16
|
||||
$this->tags2[$frame_id] = mb_convert_encoding($data['information'], 'utf-8', 'utf-16');
|
||||
break;
|
||||
// case 'TRDA': # Recording dates
|
||||
// case 'TRSN': # Internet radio station name
|
||||
// case 'TRSO': # Internet radio station owner
|
||||
// case 'TSIZ': # Size
|
||||
// case 'TSRC': # ISRC (international standard recording code)
|
||||
// case 'TSSE': # Software/Hardware and settings used for encoding
|
||||
case 'TYER': # Year
|
||||
$raw = fread($fp, $frame_size);
|
||||
$data = unpack("C1encoding/A".($frame_size - 1)."information", $raw);
|
||||
if ((bool)($data['encoding'] == 0x00)) # ISO-8859-1
|
||||
$this->tags2[$frame_id] = mb_convert_encoding($data['information'], 'utf-8', 'iso-8859-1');
|
||||
else # utf-16
|
||||
$this->tags2[$frame_id] = mb_convert_encoding($data['information'], 'utf-8', 'utf-16');
|
||||
break;
|
||||
case 'TXXX': # User defined text information frame
|
||||
$raw = fread($fp, $frame_size);
|
||||
$data = unpack("C1encoding/A".($frame_size - 1)."information", $raw);
|
||||
if ((bool)($data['encoding'] == 0x00)) # ISO-8859-1
|
||||
$this->tags2[$frame_id] = mb_convert_encoding($data['information'], 'utf-8', 'iso-8859-1');
|
||||
else # utf-16
|
||||
$this->tags2[$frame_id] = mb_convert_encoding($data['information'], 'utf-8', 'utf-16');
|
||||
break;
|
||||
|
||||
################# Text information frames
|
||||
|
||||
################# URL link frames
|
||||
@ -583,7 +546,7 @@ class Mp3Info {
|
||||
case 'COMM': # Comments
|
||||
$dataEnd = ftell($fp) + $frame_size;
|
||||
$raw = fread($fp, 4);
|
||||
$data = unpack("C1encoding/A3language", $raw);
|
||||
$data = unpack('C1encoding/A3language', $raw);
|
||||
// read until \null character
|
||||
$short_description = null;
|
||||
$last_null = false;
|
||||
@ -622,8 +585,7 @@ class Mp3Info {
|
||||
// case 'GEOB': # General encapsulated object
|
||||
// break;
|
||||
case 'PCNT': # Play counter
|
||||
$raw = fread($fp, $frame_size);
|
||||
$data = unpack("L", $raw);
|
||||
$data = unpack('L', fread($fp, $frame_size));
|
||||
$this->tags2[$frame_id] = $data[1];
|
||||
break;
|
||||
// case 'POPM': # Popularimeter
|
||||
@ -657,15 +619,35 @@ class Mp3Info {
|
||||
|
||||
/**
|
||||
* Simple function that checks mpeg-audio correctness of given file.
|
||||
* Actually it checks that first 3 bytes of file is a id3v2 tag mark or that first 11 bits of file is a frame header sync mark.
|
||||
* To perform full test create an instance of Mp3Info with given file.
|
||||
* Actually it checks that first 3 bytes of file is a id3v2 tag mark or
|
||||
* that first 11 bits of file is a frame header sync mark. To perform full
|
||||
* test create an instance of Mp3Info with given file.
|
||||
*
|
||||
* @param string $filename File to be tested.
|
||||
*
|
||||
* @return boolean True if file is looks correct, False otherwise.
|
||||
* @throws \Exception
|
||||
*/
|
||||
static public function isValidAudio($filename) {
|
||||
if (!file_exists($filename))
|
||||
throw new Exception("File ".$filename." is not present!");
|
||||
throw new Exception('File '.$filename.' is not present!');
|
||||
$raw = file_get_contents($filename, false, null, 0, 3);
|
||||
return ($raw == self::TAG2_SYNC || substr(base_convert(implode(null, unpack('H*', $raw)), 16, 2), 0, 11) == self::FRAME_SYNC);
|
||||
return ($raw == self::TAG2_SYNC || (self::FRAME_SYNC == (unpack('n*', $raw)[1] & self::FRAME_SYNC)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $frameSize
|
||||
* @param $raw
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function handleTextFrame($frameSize, $raw)
|
||||
{
|
||||
$data = unpack('C1encoding/A' . ($frameSize - 1) . 'information', $raw);
|
||||
|
||||
if ($data['encoding'] == 0x00) # ISO-8859-1
|
||||
return mb_convert_encoding($data['information'], 'utf-8', 'iso-8859-1');
|
||||
else # utf-16
|
||||
return mb_convert_encoding($data['information'], 'utf-8', 'utf-16');
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user