<?php
+
/////////////////////////////////////////////////////////////////
/// getID3() by James Heinrich <info@getid3.org> //
-// available at http://getid3.sourceforge.net //
-// or http://www.getid3.org //
-// also https://github.com/JamesHeinrich/getID3 //
-/////////////////////////////////////////////////////////////////
-// See readme.txt for more details //
+// available at https://github.com/JamesHeinrich/getID3 //
+// or https://www.getid3.org //
+// or http://getid3.sourceforge.net //
+// see readme.txt for more details //
/////////////////////////////////////////////////////////////////
// //
// module.audio.flac.php //
{
const syncword = 'fLaC';
+ /**
+ * @return bool
+ */
public function Analyze() {
$info = &$this->getid3->info;
return $this->parseMETAdata();
}
+ /**
+ * @return bool
+ */
public function parseMETAdata() {
$info = &$this->getid3->info;
do {
$BlockOffset = $this->ftell();
$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);
$BlockType = ($LBFBT & 0x7F);
$BlockLength = getid3_lib::BigEndian2Int(substr($BlockHeader, 1, 3));
$BlockTypeText = self::metaBlockTypeLookup($BlockType);
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;
}
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');
break;
}
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['max_block_size'] = getid3_lib::BigEndian2Int(substr($BlockData, 2, 2));
$streaminfo['min_frame_size'] = getid3_lib::BigEndian2Int(substr($BlockData, 4, 3));
$streaminfo['bits_per_sample'] = getid3_lib::Bin2Dec(substr($SRCSBSS, 23, 5)) + 1;
$streaminfo['samples_stream'] = getid3_lib::Bin2Dec(substr($SRCSBSS, 28, 36));
- $streaminfo['audio_signature'] = substr($BlockData, 18, 16);
+ $streaminfo['audio_signature'] = substr($BlockData, 18, 16);
+
+ return $streaminfo;
+ }
+
+ /**
+ * @param string $BlockData
+ *
+ * @return bool
+ */
+ private function parseSTREAMINFO($BlockData) {
+ $info = &$this->getid3->info;
- if (!empty($streaminfo['sample_rate'])) {
+ $info['flac']['STREAMINFO'] = self::parseSTREAMINFOdata($BlockData);
+
+ if (!empty($info['flac']['STREAMINFO']['sample_rate'])) {
$info['audio']['bitrate_mode'] = 'vbr';
- $info['audio']['sample_rate'] = $streaminfo['sample_rate'];
- $info['audio']['channels'] = $streaminfo['channels'];
- $info['audio']['bits_per_sample'] = $streaminfo['bits_per_sample'];
- $info['playtime_seconds'] = $streaminfo['samples_stream'] / $streaminfo['sample_rate'];
+ $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'];
if ($info['playtime_seconds'] > 0) {
if (!$this->isDependencyFor('matroska')) {
$info['audio']['bitrate'] = (($info['avdataend'] - $info['avdataoffset']) * 8) / $info['playtime_seconds'];
return true;
}
+ /**
+ * @param string $BlockData
+ *
+ * @return bool
+ */
private function parseAPPLICATION($BlockData) {
$info = &$this->getid3->info;
return true;
}
+ /**
+ * @param string $BlockData
+ *
+ * @return bool
+ */
private function parseSEEKTABLE($BlockData) {
$info = &$this->getid3->info;
return true;
}
+ /**
+ * @param string $BlockData
+ *
+ * @return bool
+ */
private function parseVORBIS_COMMENT($BlockData) {
$info = &$this->getid3->info;
return true;
}
+ /**
+ * @param string $BlockData
+ *
+ * @return bool
+ */
private function parseCUESHEET($BlockData) {
$info = &$this->getid3->info;
$offset = 0;
}
/**
- * Parse METADATA_BLOCK_PICTURE flac structure and extract attachment
- * External usage: audio.ogg
- */
+ * Parse METADATA_BLOCK_PICTURE flac structure and extract attachment
+ * External usage: audio.ogg
+ *
+ * @return bool
+ */
public function parsePICTURE() {
$info = &$this->getid3->info;
return true;
}
+ /**
+ * @param int $blocktype
+ *
+ * @return string
+ */
public static function metaBlockTypeLookup($blocktype) {
static $lookup = array(
0 => 'STREAMINFO',
return (isset($lookup[$blocktype]) ? $lookup[$blocktype] : 'reserved');
}
+ /**
+ * @param int $applicationid
+ *
+ * @return string
+ */
public static function applicationIDLookup($applicationid) {
// http://flac.sourceforge.net/id.html
static $lookup = array(
return (isset($lookup[$applicationid]) ? $lookup[$applicationid] : 'reserved');
}
+ /**
+ * @param int $type_id
+ *
+ * @return string
+ */
public static function pictureTypeLookup($type_id) {
static $lookup = array (
0 => 'Other',