Add read support for FLAC metadata blocks
git-svn-id: http://php-reader.googlecode.com/svn/trunk@241 51a70ab9-7547-0410-9469-37e369ee0574
This commit is contained in:
245
src/Zend/Media/Flac.php
Normal file
245
src/Zend/Media/Flac.php
Normal file
@@ -0,0 +1,245 @@
|
||||
<?php
|
||||
/**
|
||||
* Zend Framework
|
||||
*
|
||||
* LICENSE
|
||||
*
|
||||
* This source file is subject to the new BSD license that is bundled
|
||||
* with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* http://framework.zend.com/license/new-bsd
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@zend.com so we can send you a copy immediately.
|
||||
*
|
||||
* @category Zend
|
||||
* @package Zend_Media
|
||||
* @subpackage FLAC
|
||||
* @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
/**#@+ @ignore */
|
||||
require_once 'Zend/Io/Reader.php';
|
||||
/**#@-*/
|
||||
|
||||
/**
|
||||
* This class represents a file FLAC file format as described in {@link http://flac.sourceforge.net/format.html}. FLAC
|
||||
* stands for Free Lossless Audio Codec, an audio format similar to MP3, but lossless, meaning that audio is compressed
|
||||
* in FLAC without any loss in quality. This is similar to how Zip works, except with FLAC you will get much better
|
||||
* compression because it is designed specifically for audio, and you can play back compressed FLAC files in your
|
||||
* favorite player (or your car or home stereo, see supported devices) just like you would an MP3 file.
|
||||
*
|
||||
* FLAC stands out as the fastest and most widely supported lossless audio codec, and the only one that at once is
|
||||
* non-proprietary, is unencumbered by patents, has an open-source reference implementation, has a well documented
|
||||
* format and API, and has several other independent implementations.
|
||||
*
|
||||
* @category Zend
|
||||
* @package Zend_Media
|
||||
* @subpackage FLAC
|
||||
* @author Sven Vollbehr <sven@vollbehr.eu>
|
||||
* @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
final class Zend_Media_Flac
|
||||
{
|
||||
/** The streaminfo metadata block */
|
||||
const STREAMINFO = 0;
|
||||
|
||||
/** The padding metadata block */
|
||||
const PADDING = 1;
|
||||
|
||||
/** The application metadata block */
|
||||
const APPLICATION = 2;
|
||||
|
||||
/** The seektable metadata block */
|
||||
const SEEKTABLE = 3;
|
||||
|
||||
/** The vorbis comment metadata block */
|
||||
const VORBIS_COMMENT = 4;
|
||||
|
||||
/** The cuesheet metadata block */
|
||||
const CUESHEET = 5;
|
||||
|
||||
/** The picture metadata block */
|
||||
const PICTURE = 6;
|
||||
|
||||
/** @var Zend_Io_Reader */
|
||||
private $_reader;
|
||||
|
||||
/** @var Array */
|
||||
private $_metadataBlocks = array();
|
||||
|
||||
/** @var string */
|
||||
private $_filename = null;
|
||||
|
||||
/**
|
||||
* Constructs the class with given filename.
|
||||
*
|
||||
* @param string|resource|Zend_Io_Reader $filename The path to the file,
|
||||
* file descriptor of an opened file, or a {@link Zend_Io_Reader} instance.
|
||||
* @throws Zend_Io_Exception if an error occur in stream handling.
|
||||
* @throws Zend_Media_Flac_Exception if an error occurs in vorbis bitstream reading.
|
||||
*/
|
||||
public function __construct($filename)
|
||||
{
|
||||
if ($filename instanceof Zend_Io_Reader) {
|
||||
$this->_reader = &$filename;
|
||||
} else {
|
||||
$this->_filename = $filename;
|
||||
require_once('Zend/Io/FileReader.php');
|
||||
try {
|
||||
$this->_reader = new Zend_Io_FileReader($filename);
|
||||
} catch (Zend_Io_Exception $e) {
|
||||
$this->_reader = null;
|
||||
require_once 'Zend/Media/Flac/Exception.php';
|
||||
throw new Zend_Media_Flac_Exception($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
$capturePattern = $this->_reader->read(4);
|
||||
if ($capturePattern != 'fLaC') {
|
||||
require_once 'Zend/Media/Flac/Exception.php';
|
||||
throw new Zend_Media_Flac_Exception('Not a valid FLAC bitstream');
|
||||
}
|
||||
|
||||
while (true) {
|
||||
$offset = $this->_reader->getOffset();
|
||||
$last = ($tmp = $this->_reader->readUInt8()) >> 7 & 0x1;
|
||||
$type = $tmp & 0x7f;
|
||||
$size = $this->_reader->readUInt24BE();
|
||||
|
||||
$this->_reader->setOffset($offset);
|
||||
switch ($type) {
|
||||
case self::STREAMINFO: // 0
|
||||
require_once 'Zend/Media/Flac/MetadataBlock/Streaminfo.php';
|
||||
$this->_metadataBlocks[] = new Zend_Media_Flac_MetadataBlock_Streaminfo($this->_reader);
|
||||
break;
|
||||
case self::PADDING: // 1
|
||||
require_once 'Zend/Media/Flac/MetadataBlock/Padding.php';
|
||||
$this->_metadataBlocks[] = new Zend_Media_Flac_MetadataBlock_Padding($this->_reader);
|
||||
break;
|
||||
case self::APPLICATION: // 2
|
||||
require_once 'Zend/Media/Flac/MetadataBlock/Application.php';
|
||||
$this->_metadataBlocks[] = new Zend_Media_Flac_MetadataBlock_Application($this->_reader);
|
||||
break;
|
||||
case self::SEEKTABLE: // 3
|
||||
require_once 'Zend/Media/Flac/MetadataBlock/Seektable.php';
|
||||
$this->_metadataBlocks[] = new Zend_Media_Flac_MetadataBlock_Seektable($this->_reader);
|
||||
break;
|
||||
case self::VORBIS_COMMENT: // 4
|
||||
require_once 'Zend/Media/Flac/MetadataBlock/VorbisComment.php';
|
||||
$this->_metadataBlocks[] = new Zend_Media_Flac_MetadataBlock_VorbisComment($this->_reader);
|
||||
break;
|
||||
case self::CUESHEET: // 5
|
||||
require_once 'Zend/Media/Flac/MetadataBlock/Cuesheet.php';
|
||||
$this->_metadataBlocks[] = new Zend_Media_Flac_MetadataBlock_Cuesheet($this->_reader);
|
||||
break;
|
||||
case self::PICTURE: // 6
|
||||
require_once 'Zend/Media/Flac/MetadataBlock/Picture.php';
|
||||
$this->_metadataBlocks[] = new Zend_Media_Flac_MetadataBlock_Picture($this->_reader);
|
||||
break;
|
||||
default:
|
||||
// break intentionally omitted
|
||||
}
|
||||
$this->_reader->setOffset($offset + 4 /* header */ + $size);
|
||||
|
||||
// Jump off the loop if we reached the end of metadata blocks
|
||||
if ($last === 1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the given metadata block is there. Returns <var>true</var> if one ore more frames are present,
|
||||
* <var>false</var> otherwise.
|
||||
*
|
||||
* @param string $type The metadata block type.
|
||||
* @return boolean
|
||||
*/
|
||||
public function hasMetadataBlock($type)
|
||||
{
|
||||
$metadataBlockCount = count($this->_metadataBlocks);
|
||||
for ($i = 0; $i < $metadataBlockCount; $i++) {
|
||||
if ($this->_metadataBlocks[$i]->getType() === $type) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all the metadata blocks as an associate array.
|
||||
*
|
||||
* @return Array
|
||||
*/
|
||||
public function getMetadataBlocks()
|
||||
{
|
||||
return $this->_metadataBlocks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of metadata blocks frames matching the given type or an empty array if no metadata blocks
|
||||
* matched the type.
|
||||
*
|
||||
* Please note that one may also use the shorthand $obj->type to access the first metadata block with the given
|
||||
* type.
|
||||
*
|
||||
* @param string $type The metadata block type.
|
||||
* @return Array
|
||||
*/
|
||||
public function getMetadataBlocksByType($type)
|
||||
{
|
||||
$matches = array();
|
||||
$metadataBlockCount = count($this->_metadataBlocks);
|
||||
for ($i = 0; $i < $metadataBlockCount; $i++) {
|
||||
if ($this->_metadataBlocks[$i]->getType() === $type) {
|
||||
$matches[] = $this->_metadataBlocks[$i];
|
||||
}
|
||||
}
|
||||
return $matches;
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic function so that $obj->value will work.
|
||||
*
|
||||
* @param string $name The field name.
|
||||
* @return mixed
|
||||
*/
|
||||
public function __get($name)
|
||||
{
|
||||
if (method_exists($this, 'get' . ucfirst($name))) {
|
||||
return call_user_func
|
||||
(array($this, 'get' . ucfirst($name)));
|
||||
}
|
||||
if (defined($constant = 'self::' . strtoupper(preg_replace('/(?<=[a-z])[A-Z]/', '_$0', $name)))) {
|
||||
$metadataBlocks = $this->getMetadataBlocksByType(constant($constant));
|
||||
if (isset($metadataBlocks[0])) {
|
||||
return $metadataBlocks[0];
|
||||
}
|
||||
}
|
||||
require_once 'Zend/Media/Flac/Exception.php';
|
||||
throw new Zend_Media_Flac_Exception('Unknown metadata block or field: ' . $name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic function so that assignments with $obj->value will work.
|
||||
*
|
||||
* @param string $name The field name.
|
||||
* @param string $value The field value.
|
||||
* @return mixed
|
||||
*/
|
||||
public function __set($name, $value)
|
||||
{
|
||||
if (method_exists($this, 'set' . ucfirst(strtolower($name)))) {
|
||||
call_user_func
|
||||
(array($this, 'set' . ucfirst(strtolower($name))), $value);
|
||||
} else {
|
||||
require_once('Zend/Media/Flac/Exception.php');
|
||||
throw new Zend_Media_Flac_Exception('Unknown field: ' . $name);
|
||||
}
|
||||
}
|
||||
}
|
||||
40
src/Zend/Media/Flac/Exception.php
Normal file
40
src/Zend/Media/Flac/Exception.php
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
/**
|
||||
* Zend Framework
|
||||
*
|
||||
* LICENSE
|
||||
*
|
||||
* This source file is subject to the new BSD license that is bundled
|
||||
* with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* http://framework.zend.com/license/new-bsd
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@zend.com so we can send you a copy immediately.
|
||||
*
|
||||
* @category Zend
|
||||
* @package Zend_Media
|
||||
* @subpackage FLAC
|
||||
* @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
/**#@+ @ignore */
|
||||
require_once 'Zend/Media/Exception.php';
|
||||
/**#@-*/
|
||||
|
||||
/**
|
||||
* The Zend_Media_Flac_Exception is thrown whenever an error occurs within the {@link Zend_Media_Flac} family of
|
||||
* classes.
|
||||
*
|
||||
* @category Zend
|
||||
* @package Zend_Media
|
||||
* @subpackage FLAC
|
||||
* @author Sven Vollbehr <sven@vollbehr.eu>
|
||||
* @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
class Zend_Media_Flac_Exception extends Zend_Media_Exception
|
||||
{}
|
||||
173
src/Zend/Media/Flac/MetadataBlock.php
Normal file
173
src/Zend/Media/Flac/MetadataBlock.php
Normal file
@@ -0,0 +1,173 @@
|
||||
<?php
|
||||
/**
|
||||
* Zend Framework
|
||||
*
|
||||
* LICENSE
|
||||
*
|
||||
* This source file is subject to the new BSD license that is bundled
|
||||
* with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* http://framework.zend.com/license/new-bsd
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@zend.com so we can send you a copy immediately.
|
||||
*
|
||||
* @category Zend
|
||||
* @package Zend_Media
|
||||
* @subpackage FLAC
|
||||
* @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
/**
|
||||
* This class represents a FLAC metadata block. FLAC specifies a metadata system, which allows arbitrary information
|
||||
* about the stream to be included at the beginning of the stream. FLAC contains a mandatory metadata block (called the
|
||||
* STREAMINFO block), and any number of other metadata blocks, listed below. After metadata blocks follows the audio
|
||||
* frames.
|
||||
*
|
||||
* FLAC supports up to 128 kinds of metadata blocks; currently the following are defined:
|
||||
* o STREAMINFO
|
||||
* This block has information about the whole stream, like sample rate, number of channels, total number of samples,
|
||||
* etc. It must be present as the first metadata block in the stream. Other metadata blocks may follow, and ones
|
||||
* that the decoder doesn't understand, it will skip.
|
||||
* o APPLICATION
|
||||
* This block is for use by third-party applications. The only mandatory field is a 32-bit identifier. This ID is
|
||||
* granted upon request to an application by the FLAC maintainers. The remainder is of the block is defined by the
|
||||
* registered application. Visit the registration page if you would like to register an ID for your application with
|
||||
* FLAC.
|
||||
* o PADDING
|
||||
* This block allows for an arbitrary amount of padding. The contents of a PADDING block have no meaning. This block
|
||||
* is useful when it is known that metadata will be edited after encoding; the user can instruct the encoder to
|
||||
* reserve a PADDING block of sufficient size so that when metadata is added, it will simply overwrite the padding
|
||||
* (which is relatively quick) instead of having to insert it into the right place in the existing file (which would
|
||||
* normally require rewriting the entire file).
|
||||
* o SEEKTABLE
|
||||
* This is an optional block for storing seek points. It is possible to seek to any given sample in a FLAC stream
|
||||
* without a seek table, but the delay can be unpredictable since the bitrate may vary widely within a stream. By
|
||||
* adding seek points to a stream, this delay can be significantly reduced. Each seek point takes 18 bytes, so 1%
|
||||
* resolution within a stream adds less than 2k. There can be only one SEEKTABLE in a stream, but the table can have
|
||||
* any number of seek points. There is also a special 'placeholder' seekpoint which will be ignored by decoders but
|
||||
* which can be used to reserve space for future seek point insertion.
|
||||
* o VORBIS_COMMENT
|
||||
* This block is for storing a list of human-readable name/value pairs. Values are encoded using UTF-8. It is an
|
||||
* implementation of the Vorbis comment specification (without the framing bit). This is the only officially
|
||||
* supported tagging mechanism in FLAC. There may be only one VORBIS_COMMENT block in a stream. In some external
|
||||
* documentation, Vorbis comments are called FLAC tags to lessen confusion.
|
||||
* o CUESHEET
|
||||
* This block is for storing various information that can be used in a cue sheet. It supports track and index points,
|
||||
* compatible with Red Book CD digital audio discs, as well as other CD-DA metadata such as media catalog number and
|
||||
* track ISRCs. The CUESHEET block is especially useful for backing up CD-DA discs, but it can be used as a general
|
||||
* purpose cueing mechanism for playback.
|
||||
* o PICTURE
|
||||
* This block is for storing pictures associated with the file, most commonly cover art from CDs. There may be more
|
||||
* than one PICTURE block in a file. The picture format is similar to the APIC frame in ID3v2. The PICTURE block has
|
||||
* a type, MIME type, and UTF-8 description like ID3v2, and supports external linking via URL (though this is
|
||||
* discouraged). The differences are that there is no uniqueness constraint on the description field, and the MIME
|
||||
* type is mandatory. The FLAC PICTURE block also includes the resolution, color depth, and palette size so that the
|
||||
* client can search for a suitable picture without having to scan them all.
|
||||
*
|
||||
* @category Zend
|
||||
* @package Zend_Media
|
||||
* @subpackage FLAC
|
||||
* @author Sven Vollbehr <sven@vollbehr.eu>
|
||||
* @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
abstract class Zend_Media_Flac_MetadataBlock
|
||||
{
|
||||
/**
|
||||
* The reader object.
|
||||
*
|
||||
* @var Zend_Io_Reader
|
||||
*/
|
||||
protected $_reader;
|
||||
|
||||
/** @var integer */
|
||||
private $_last;
|
||||
|
||||
/** @var integer */
|
||||
private $_type;
|
||||
|
||||
/** @var integer */
|
||||
private $_size;
|
||||
|
||||
/**
|
||||
* Constructs the class with given parameters and reads object related data
|
||||
* from the Flac bitstream.
|
||||
*
|
||||
* @param Zend_Io_Reader $reader The reader object.
|
||||
*/
|
||||
public function __construct($reader)
|
||||
{
|
||||
$this->_reader = $reader;
|
||||
|
||||
$this->_last = ($tmp = $this->_reader->readUInt8()) >> 7 & 0x1;
|
||||
$this->_type = $tmp & 0x7f;
|
||||
$this->_size = $this->_reader->readUInt24BE();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the metadata block type. The type is one of the following.
|
||||
*
|
||||
* o 0: STREAMINFO
|
||||
* o 1: PADDING
|
||||
* o 2: APPLICATION
|
||||
* o 3: SEEKTABLE
|
||||
* o 4: VORBIS_COMMENT
|
||||
* o 5: CUESHEET
|
||||
* o 6: PICTURE
|
||||
* o 7-126: reserved
|
||||
* o 127: invalid, to avoid confusion with a frame sync code
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function getType()
|
||||
{
|
||||
return $this->_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the metadata block length without the header, in bytes.
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function getSize()
|
||||
{
|
||||
return $this->_size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic function so that $obj->value will work.
|
||||
*
|
||||
* @param string $name The field name.
|
||||
* @return mixed
|
||||
*/
|
||||
public function __get($name)
|
||||
{
|
||||
if (method_exists($this, 'get' . ucfirst($name))) {
|
||||
return call_user_func(array($this, 'get' . ucfirst($name)));
|
||||
} else {
|
||||
require_once 'Zend/Media/Flac/Exception.php';
|
||||
throw new Zend_Media_Flac_Exception('Unknown field: ' . $name);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic function so that assignments with $obj->value will work.
|
||||
*
|
||||
* @param string $name The field name.
|
||||
* @param string $value The field value.
|
||||
* @return mixed
|
||||
*/
|
||||
public function __set($name, $value)
|
||||
{
|
||||
if (method_exists($this, 'set' . ucfirst($name))) {
|
||||
call_user_func(array($this, 'set' . ucfirst($name)), $value);
|
||||
} else {
|
||||
require_once 'Zend/Media/Flac/Exception.php';
|
||||
throw new Zend_Media_Flac_Exception('Unknown field: ' . $name);
|
||||
}
|
||||
}
|
||||
}
|
||||
77
src/Zend/Media/Flac/MetadataBlock/Application.php
Normal file
77
src/Zend/Media/Flac/MetadataBlock/Application.php
Normal file
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
/**
|
||||
* Zend Framework
|
||||
*
|
||||
* LICENSE
|
||||
*
|
||||
* This source file is subject to the new BSD license that is bundled
|
||||
* with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* http://framework.zend.com/license/new-bsd
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@zend.com so we can send you a copy immediately.
|
||||
*
|
||||
* @category Zend
|
||||
* @package Zend_Media
|
||||
* @subpackage FLAC
|
||||
* @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
/**#@+ @ignore */
|
||||
require_once 'Zend/Media/Flac/MetadataBlock.php';
|
||||
/**#@-*/
|
||||
|
||||
/**
|
||||
* This class represents the application metadata block. This block is for use by third-party applications. The only
|
||||
* mandatory field is a 32-bit identifier. This ID is granted upon request to an application by the FLAC maintainers.
|
||||
* The remainder is of the block is defined by the registered application. Visit the registration page if you would like
|
||||
* to register an ID for your application with FLAC.
|
||||
*
|
||||
* Applications can be registered at {@link http://flac.sourceforge.net/id.html}.
|
||||
*
|
||||
* @category Zend
|
||||
* @package Zend_Media
|
||||
* @subpackage FLAC
|
||||
* @author Sven Vollbehr <sven@vollbehr.eu>
|
||||
* @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
final class Zend_Media_Flac_MetadataBlock_Application extends Zend_Media_Flac_MetadataBlock
|
||||
{
|
||||
/**
|
||||
* Constructs the class with given parameters and parses object related data.
|
||||
*
|
||||
* @param Zend_Io_Reader $reader The reader object.
|
||||
*/
|
||||
public function __construct($reader)
|
||||
{
|
||||
parent::__construct($reader);
|
||||
|
||||
$this->_identifier = $this->_reader->readUInt32BE();
|
||||
$this->_data = $this->_reader->read($this->getSize() - 4);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the application identifier.
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function getIdentifier()
|
||||
{
|
||||
return $this->_identifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the application data.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getData()
|
||||
{
|
||||
return $this->_data;
|
||||
}
|
||||
}
|
||||
189
src/Zend/Media/Flac/MetadataBlock/Cuesheet.php
Normal file
189
src/Zend/Media/Flac/MetadataBlock/Cuesheet.php
Normal file
@@ -0,0 +1,189 @@
|
||||
<?php
|
||||
/**
|
||||
* Zend Framework
|
||||
*
|
||||
* LICENSE
|
||||
*
|
||||
* This source file is subject to the new BSD license that is bundled
|
||||
* with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* http://framework.zend.com/license/new-bsd
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@zend.com so we can send you a copy immediately.
|
||||
*
|
||||
* @category Zend
|
||||
* @package Zend_Media
|
||||
* @subpackage FLAC
|
||||
* @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
/**#@+ @ignore */
|
||||
require_once 'Zend/Media/Flac/MetadataBlock.php';
|
||||
/**#@-*/
|
||||
|
||||
/**
|
||||
* This class represents the cuesheet metadata block. This block is for storing various information that can be used in
|
||||
* a cue sheet. It supports track and index points, compatible with Red Book CD digital audio discs, as well as other
|
||||
* CD-DA metadata such as media catalog number and track ISRCs. The CUESHEET block is especially useful for backing up
|
||||
* CD-DA discs, but it can be used as a general purpose cueing mechanism for playback.
|
||||
*
|
||||
* @category Zend
|
||||
* @package Zend_Media
|
||||
* @subpackage FLAC
|
||||
* @author Sven Vollbehr <sven@vollbehr.eu>
|
||||
* @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
final class Zend_Media_Flac_MetadataBlock_Cuesheet extends Zend_Media_Flac_MetadataBlock
|
||||
{
|
||||
/** @var string */
|
||||
private $_catalogNumber;
|
||||
|
||||
/** @var integer */
|
||||
private $_leadinSamples;
|
||||
|
||||
/** @var boolean */
|
||||
private $_compactDisc;
|
||||
|
||||
/** @var Array */
|
||||
private $_tracks;
|
||||
|
||||
/**
|
||||
* Constructs the class with given parameters and parses object related data.
|
||||
*
|
||||
* @param Zend_Io_Reader $reader The reader object.
|
||||
*/
|
||||
public function __construct($reader)
|
||||
{
|
||||
parent::__construct($reader);
|
||||
|
||||
$this->_catalogNumber = rtrim($this->_reader->read(128), "\x00");
|
||||
$this->_leadinSamples = $this->_reader->readInt64BE();
|
||||
$this->_compactDisc = ($this->_reader->readUInt8() >> 7) & 0x1;
|
||||
$this->_reader->skip(258);
|
||||
$tracksLength = $this->_reader->readUInt8();
|
||||
for ($i = 0; $i < $tracksLength; $i++) {
|
||||
$this->_tracks[$i] = array(
|
||||
'offset' => $this->_reader->readInt64BE(),
|
||||
'number' => $this->_reader->readUInt8(),
|
||||
'isrc' => rtrim($this->_reader->read(12), "\x00"),
|
||||
'type' => (($tmp = $this->_reader->readUInt8()) >> 7 ) & 0x1,
|
||||
'pre-emphasis' => (($tmp) >> 6 ) & 0x1,
|
||||
'index' => array());
|
||||
$this->_reader->skip(13);
|
||||
$indexPointsLength = $this->_reader->readUInt8();
|
||||
for ($j = 0; $j < $indexPointsLength; $j++) {
|
||||
$this->_tracks[$i]['index'][$j] = array(
|
||||
'offset' => $this->_reader->readInt64BE(),
|
||||
'number' => $this->_reader->readUInt8()
|
||||
);
|
||||
$this->_reader->skip(3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the media catalog number, in ASCII printable characters 0x20-0x7e. In general, the media catalog number
|
||||
* may be 0 to 128 bytes long; any unused characters should be right-padded with NUL characters. For CD-DA, this is
|
||||
* a thirteen digit number, followed by 115 NUL bytes.minimum block size (in samples) used in the stream.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getCatalogNumber()
|
||||
{
|
||||
return $this->_catalogNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of lead-in samples. This field has meaning only for CD-DA cuesheets; for other uses it should
|
||||
* be 0. For CD-DA, the lead-in is the TRACK 00 area where the table of contents is stored; more precisely, it is
|
||||
* the number of samples from the first sample of the media to the first sample of the first index point of the
|
||||
* first track. According to the Red Book, the lead-in must be silence and CD grabbing software does not usually
|
||||
* store it; additionally, the lead-in must be at least two seconds but may be longer. For these reasons the
|
||||
* lead-in length is stored here so that the absolute position of the first track can be computed. Note that the
|
||||
* lead-in stored here is the number of samples up to the first index point of the first track, not necessarily to
|
||||
* INDEX 01 of the first track; even the first track may have INDEX 00 data.
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function getLeadinSamples()
|
||||
{
|
||||
return $this->_leadinSamples;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the minimum frame size (in bytes) used in the stream. May be 0 to imply the value is not known.
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function getMinimumFrameSize()
|
||||
{
|
||||
return $this->_minimumFrameSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the maximum frame size (in bytes) used in the stream. May be 0 to imply the value is not known.
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function getMaximumFrameSize()
|
||||
{
|
||||
return $this->_maximumFrameSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns sample rate in Hz. The maximum sample rate is limited by the structure of frame headers to 655350Hz.
|
||||
* Also, a value of 0 is invalid.
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function getSampleRate()
|
||||
{
|
||||
return $this->_sampleRate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the CUESHEET corresponds to a Compact Disc or not.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function getCompactDisk()
|
||||
{
|
||||
return $this->_compactDisk == 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of values. Each entry is an array containing the following keys.
|
||||
* o offset -- Track offset in samples, relative to the beginning of the FLAC audio stream. It is the offset to
|
||||
* the first index point of the track. (Note how this differs from CD-DA, where the track's offset in the TOC
|
||||
* is that of the track's INDEX 01 even if there is an INDEX 00.) For CD-DA, the offset must be evenly divisible
|
||||
* by 588 samples (588 samples = 44100 samples/sec * 1/75th of a sec).
|
||||
* o number -- Track number. A track number of 0 is not allowed to avoid conflicting with the CD-DA spec, which
|
||||
* reserves this for the lead-in. For CD-DA the number must be 1-99, or 170 for the lead-out; for non-CD-DA,
|
||||
* the track number must for 255 for the lead-out. It is not required but encouraged to start with track 1 and
|
||||
* increase sequentially. Track numbers must be unique within a CUESHEET.
|
||||
* o isrc -- Track ISRC. This is a 12-digit alphanumeric code or an empty string to denote absence of an ISRC.
|
||||
* o type -- The track type: 0 for audio, 1 for non-audio. This corresponds to the CD-DA Q-channel control bit 3.
|
||||
* o pre-emphasis -- The pre-emphasis flag: 0 for no pre-emphasis, 1 for pre-emphasis. This corresponds to the
|
||||
* CD-DA Q-channel control bit 5.
|
||||
* o index -- An array of track index points. There must be at least one index in every track in a CUESHEET except
|
||||
* for the lead-out track, which must have zero. For CD-DA, this number may be no more than 100. Each entry is
|
||||
* an array containing the following keys.
|
||||
* o offset -- Offset in samples, relative to the track offset, of the index point. For CD-DA, the offset must
|
||||
* be evenly divisible by 588 samples (588 samples = 44100 samples/sec * 1/75th of a sec). Note that the
|
||||
* offset is from the beginning of the track, not the beginning of the audio data.
|
||||
* o number -- The index point number. For CD-DA, an index number of 0 corresponds to the track pre-gap. The
|
||||
* first index in a track must have a number of 0 or 1, and subsequently, index numbers must increase by 1.
|
||||
* Index numbers must be unique within a track.
|
||||
*
|
||||
* @return Array
|
||||
*/
|
||||
public function getTracks()
|
||||
{
|
||||
return $this->_tracks;
|
||||
}
|
||||
}
|
||||
53
src/Zend/Media/Flac/MetadataBlock/Padding.php
Normal file
53
src/Zend/Media/Flac/MetadataBlock/Padding.php
Normal file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
/**
|
||||
* Zend Framework
|
||||
*
|
||||
* LICENSE
|
||||
*
|
||||
* This source file is subject to the new BSD license that is bundled
|
||||
* with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* http://framework.zend.com/license/new-bsd
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@zend.com so we can send you a copy immediately.
|
||||
*
|
||||
* @category Zend
|
||||
* @package Zend_Media
|
||||
* @subpackage FLAC
|
||||
* @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
/**#@+ @ignore */
|
||||
require_once 'Zend/Media/Flac/MetadataBlock.php';
|
||||
/**#@-*/
|
||||
|
||||
/**
|
||||
* This class represents the padding metadata block. This block allows for an arbitrary amount of padding. The contents
|
||||
* of a PADDING block have no meaning. This block is useful when it is known that metadata will be edited after
|
||||
* encoding; the user can instruct the encoder to reserve a PADDING block of sufficient size so that when metadata is
|
||||
* added, it will simply overwrite the padding (which is relatively quick) instead of having to insert it into the right
|
||||
* place in the existing file (which would normally require rewriting the entire file).
|
||||
*
|
||||
* @category Zend
|
||||
* @package Zend_Media
|
||||
* @subpackage FLAC
|
||||
* @author Sven Vollbehr <sven@vollbehr.eu>
|
||||
* @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
final class Zend_Media_Flac_MetadataBlock_Padding extends Zend_Media_Flac_MetadataBlock
|
||||
{
|
||||
/**
|
||||
* Constructs the class with given parameters and parses object related data.
|
||||
*
|
||||
* @param Zend_Io_Reader $reader The reader object.
|
||||
*/
|
||||
public function __construct($reader)
|
||||
{
|
||||
parent::__construct($reader);
|
||||
}
|
||||
}
|
||||
199
src/Zend/Media/Flac/MetadataBlock/Picture.php
Normal file
199
src/Zend/Media/Flac/MetadataBlock/Picture.php
Normal file
@@ -0,0 +1,199 @@
|
||||
<?php
|
||||
/**
|
||||
* Zend Framework
|
||||
*
|
||||
* LICENSE
|
||||
*
|
||||
* This source file is subject to the new BSD license that is bundled
|
||||
* with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* http://framework.zend.com/license/new-bsd
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@zend.com so we can send you a copy immediately.
|
||||
*
|
||||
* @category Zend
|
||||
* @package Zend_Media
|
||||
* @subpackage FLAC
|
||||
* @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
/**#@+ @ignore */
|
||||
require_once 'Zend/Media/Flac/MetadataBlock.php';
|
||||
/**#@-*/
|
||||
|
||||
/**
|
||||
* This class represents the picture metadata block. This block is for storing pictures associated with the file, most
|
||||
* commonly cover art from CDs. There may be more than one PICTURE block in a file. The picture format is similar to the
|
||||
* {@link Zend_Media_Id3v2_Frame_Apic APIC} frame in {@link Zend_Media_Id3v2 ID3v2}. The PICTURE block has a type,
|
||||
* MIME type, and UTF-8 description like {@link Zend_Media_Id3v2 ID3v2}, and supports external linking via URL (though
|
||||
* this is discouraged). The differences are that there is no uniqueness constraint on the description field, and the
|
||||
* MIME type is mandatory. The FLAC PICTURE block also includes the resolution, color depth, and palette size so that
|
||||
* the client can search for a suitable picture without having to scan them all.
|
||||
*
|
||||
* @category Zend
|
||||
* @package Zend_Media
|
||||
* @subpackage FLAC
|
||||
* @author Sven Vollbehr <sven@vollbehr.eu>
|
||||
* @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
final class Zend_Media_Flac_MetadataBlock_Picture extends Zend_Media_Flac_MetadataBlock
|
||||
{
|
||||
/**
|
||||
* The list of picture types.
|
||||
*
|
||||
* @var Array
|
||||
*/
|
||||
public static $types = array
|
||||
('Other', '32x32 pixels file icon (PNG only)', 'Other file icon',
|
||||
'Cover (front)', 'Cover (back)', 'Leaflet page',
|
||||
'Media (e.g. label side of CD)', 'Lead artist/lead performer/soloist',
|
||||
'Artist/performer', 'Conductor', 'Band/Orchestra', 'Composer',
|
||||
'Lyricist/text writer', 'Recording Location', 'During recording',
|
||||
'During performance', 'Movie/video screen capture',
|
||||
'A bright coloured fish', 'Illustration', 'Band/artist logotype',
|
||||
'Publisher/Studio logotype');
|
||||
|
||||
/** @var integer */
|
||||
private $_type;
|
||||
|
||||
/** @var string */
|
||||
private $_mimeType;
|
||||
|
||||
/** @var string */
|
||||
private $_description;
|
||||
|
||||
/** @var integer */
|
||||
private $_width;
|
||||
|
||||
/** @var integer */
|
||||
private $_height;
|
||||
|
||||
/** @var integer */
|
||||
private $_colorDepth;
|
||||
|
||||
/** @var integer */
|
||||
private $_numberOfColors;
|
||||
|
||||
/** @var integer */
|
||||
private $_dataSize;
|
||||
|
||||
/** @var string */
|
||||
private $_data;
|
||||
|
||||
/**
|
||||
* Constructs the class with given parameters and parses object related data.
|
||||
*
|
||||
* @todo There is the possibility to put only a link to the picture file by
|
||||
* using the MIME type '-->' and having a complete URL instead of picture
|
||||
* data. Support for such needs design considerations.
|
||||
* @param Zend_Io_Reader $reader The reader object.
|
||||
*/
|
||||
public function __construct($reader)
|
||||
{
|
||||
parent::__construct($reader);
|
||||
|
||||
$this->_type = $this->_reader->readUInt32BE();
|
||||
$this->_mimeType = $this->_reader->read($this->_reader->readUInt32BE());
|
||||
$this->_description = $this->_reader->read($this->_reader->readUInt32BE());
|
||||
$this->_width = $this->_reader->readUInt32BE();
|
||||
$this->_height = $this->_reader->readUInt32BE();
|
||||
$this->_colorDepth = $this->_reader->readUInt32BE();
|
||||
$this->_numberOfColors = $this->_reader->readUInt32BE();
|
||||
$this->_data = $this->_reader->read($this->_dataSize = $this->_reader->readUInt32BE());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the picture type.
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function getPictureType()
|
||||
{
|
||||
return $this->_pictureType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the MIME type.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getMimeType()
|
||||
{
|
||||
return $this->_mimeType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the picture description.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDescription()
|
||||
{
|
||||
return $this->_description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the picture width.
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function getWidth()
|
||||
{
|
||||
return $this->_width;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the picture height.
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function getHeight()
|
||||
{
|
||||
return $this->_height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the color depth of the picture in bits-per-pixel.
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function getColorDepth()
|
||||
{
|
||||
return $this->_colorDepth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of colors used for indexed-color pictures, or 0 for non-indexed pictures.
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function getNumberOfColors()
|
||||
{
|
||||
return $this->_numberOfColors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the picture data size.
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function getDataSize()
|
||||
{
|
||||
return $this->_dataSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the picture data.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getData()
|
||||
{
|
||||
return $this->_data;
|
||||
}
|
||||
}
|
||||
82
src/Zend/Media/Flac/MetadataBlock/Seektable.php
Normal file
82
src/Zend/Media/Flac/MetadataBlock/Seektable.php
Normal file
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
/**
|
||||
* Zend Framework
|
||||
*
|
||||
* LICENSE
|
||||
*
|
||||
* This source file is subject to the new BSD license that is bundled
|
||||
* with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* http://framework.zend.com/license/new-bsd
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@zend.com so we can send you a copy immediately.
|
||||
*
|
||||
* @category Zend
|
||||
* @package Zend_Media
|
||||
* @subpackage FLAC
|
||||
* @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
/**#@+ @ignore */
|
||||
require_once 'Zend/Media/Flac/MetadataBlock.php';
|
||||
/**#@-*/
|
||||
|
||||
/**
|
||||
* This class represents the seektable metadata block. This is an optional block for storing seek points. It is possible
|
||||
* to seek to any given sample in a FLAC stream without a seek table, but the delay can be unpredictable since the
|
||||
* bitrate may vary widely within a stream. By adding seek points to a stream, this delay can be significantly reduced.
|
||||
* Each seek point takes 18 bytes, so 1% resolution within a stream adds less than 2k. There can be only one SEEKTABLE
|
||||
* in a stream, but the table can have any number of seek points. There is also a special 'placeholder' seekpoint which
|
||||
* will be ignored by decoders but which can be used to reserve space for future seek point insertion.
|
||||
*
|
||||
* @category Zend
|
||||
* @package Zend_Media
|
||||
* @subpackage FLAC
|
||||
* @author Sven Vollbehr <sven@vollbehr.eu>
|
||||
* @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
final class Zend_Media_Flac_MetadataBlock_Seektable extends Zend_Media_Flac_MetadataBlock
|
||||
{
|
||||
/** @var Array */
|
||||
private $_seekpoints = array();
|
||||
|
||||
/**
|
||||
* Constructs the class with given parameters and parses object related data.
|
||||
*
|
||||
* @param Zend_Io_Reader $reader The reader object.
|
||||
*/
|
||||
public function __construct($reader)
|
||||
{
|
||||
parent::__construct($reader);
|
||||
|
||||
$seekpointCount = $this->getSize() / 18;
|
||||
for ($i = 0; $i < $seekpointCount; $i++) {
|
||||
$this->_seekpoints[] = array(
|
||||
'sampleNumber' => $this->_reader->readInt64BE(),
|
||||
'offset' => $this->_reader->readInt64BE(),
|
||||
'numberOfSamples' => $this->_reader->readUInt16BE()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the seekpoint table. The array consists of items having three keys.
|
||||
*
|
||||
* o sampleNumber -- Sample number of first sample in the target frame, or 0xFFFFFFFFFFFFFFFF for a
|
||||
* placeholder point.
|
||||
* o offset -- Offset (in bytes) from the first byte of the first frame header to the first byte of the
|
||||
* target frame's header.
|
||||
* o numberOfSamples -- Number of samples in the target frame.
|
||||
*
|
||||
* @return Array
|
||||
*/
|
||||
public function getSeekpoints()
|
||||
{
|
||||
return $this->_seekpoints;
|
||||
}
|
||||
}
|
||||
185
src/Zend/Media/Flac/MetadataBlock/Streaminfo.php
Normal file
185
src/Zend/Media/Flac/MetadataBlock/Streaminfo.php
Normal file
@@ -0,0 +1,185 @@
|
||||
<?php
|
||||
/**
|
||||
* Zend Framework
|
||||
*
|
||||
* LICENSE
|
||||
*
|
||||
* This source file is subject to the new BSD license that is bundled
|
||||
* with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* http://framework.zend.com/license/new-bsd
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@zend.com so we can send you a copy immediately.
|
||||
*
|
||||
* @category Zend
|
||||
* @package Zend_Media
|
||||
* @subpackage FLAC
|
||||
* @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
/**#@+ @ignore */
|
||||
require_once 'Zend/Media/Flac/MetadataBlock.php';
|
||||
require_once 'Zend/Bit/Twiddling.php';
|
||||
/**#@-*/
|
||||
|
||||
/**
|
||||
* This class represents the streaminfo metadata block. This block has information about the whole stream, like sample
|
||||
* rate, number of channels, total number of samples, etc. It must be present as the first metadata block in the stream.
|
||||
* Other metadata blocks may follow, and ones that the decoder doesn't understand, it will skip.
|
||||
*
|
||||
* @category Zend
|
||||
* @package Zend_Media
|
||||
* @subpackage FLAC
|
||||
* @author Sven Vollbehr <sven@vollbehr.eu>
|
||||
* @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
final class Zend_Media_Flac_MetadataBlock_Streaminfo extends Zend_Media_Flac_MetadataBlock
|
||||
{
|
||||
/** @var integer */
|
||||
private $_minimumBlockSize;
|
||||
|
||||
/** @var integer */
|
||||
private $_maximumBlockSize;
|
||||
|
||||
/** @var integer */
|
||||
private $_minimumFrameSize;
|
||||
|
||||
/** @var integer */
|
||||
private $_maximumFrameSize;
|
||||
|
||||
/** @var integer */
|
||||
private $_sampleRate;
|
||||
|
||||
/** @var integer */
|
||||
private $_numberOfChannels;
|
||||
|
||||
/** @var integer */
|
||||
private $_bitsPerSample;
|
||||
|
||||
/** @var integer */
|
||||
private $_numberOfSamples;
|
||||
|
||||
/** @var string */
|
||||
private $_md5Signature;
|
||||
|
||||
/**
|
||||
* Constructs the class with given parameters and parses object related data.
|
||||
*
|
||||
* @param Zend_Io_Reader $reader The reader object.
|
||||
*/
|
||||
public function __construct($reader)
|
||||
{
|
||||
parent::__construct($reader);
|
||||
|
||||
$this->_minimumBlockSize = $this->_reader->readUInt16BE();
|
||||
$this->_maximumBlockSize = $this->_reader->readUInt16BE();
|
||||
$this->_minimumFrameSize = $this->_reader->readUInt24BE();
|
||||
$this->_maximumFrameSize = $this->_reader->readUInt24BE();
|
||||
$this->_sampleRate = Zend_Bit_Twiddling::getValue(($tmp = $this->_reader->readUInt32BE()), 12, 31);
|
||||
$this->_numberOfChannels = Zend_Bit_Twiddling::getValue($tmp, 9, 11) + 1;
|
||||
$this->_bitsPerSample = Zend_Bit_Twiddling::getValue($tmp, 4, 8) + 1;
|
||||
$this->_numberOfSamples = (Zend_Bit_Twiddling::getValue($tmp, 0, 3) << 32) | $this->_reader->readUInt32BE();
|
||||
$this->_md5Signature = bin2hex($this->_reader->read(16));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the minimum block size (in samples) used in the stream.
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function getMinimumBlockSize()
|
||||
{
|
||||
return $this->_minimumBlockSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the maximum block size (in samples) used in the stream. (Minimum blocksize == maximum blocksize) implies
|
||||
* a fixed-blocksize stream.
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function getMaximumBlockSize()
|
||||
{
|
||||
return $this->_maximumBlockSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the minimum frame size (in bytes) used in the stream. May be 0 to imply the value is not known.
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function getMinimumFrameSize()
|
||||
{
|
||||
return $this->_minimumFrameSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the maximum frame size (in bytes) used in the stream. May be 0 to imply the value is not known.
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function getMaximumFrameSize()
|
||||
{
|
||||
return $this->_maximumFrameSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns sample rate in Hz. The maximum sample rate is limited by the structure of frame headers to 655350Hz.
|
||||
* Also, a value of 0 is invalid.
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function getSampleRate()
|
||||
{
|
||||
return $this->_sampleRate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns number of channels. FLAC supports from 1 to 8 channels.
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function getNumberOfChannels()
|
||||
{
|
||||
return $this->_numberOfChannels;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns bits per sample. FLAC supports from 4 to 32 bits per sample. Currently the reference encoder and
|
||||
* decoders only support up to 24 bits per sample.
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function getBitsPerSample()
|
||||
{
|
||||
return $this->_bitsPerSample;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns total samples in stream. 'Samples' means inter-channel sample, i.e. one second of 44.1Khz audio will
|
||||
* have 44100 samples regardless of the number of channels. A value of zero here means the number of total samples
|
||||
* is unknown.
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function getNumberOfSamples()
|
||||
{
|
||||
return $this->_numberOfSamples;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns MD5 signature of the unencoded audio data. This allows the decoder to determine if an error exists in
|
||||
* the audio data even when the error does not result in an invalid bitstream.
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function getMd5Signature()
|
||||
{
|
||||
return $this->_md5Signature;
|
||||
}
|
||||
}
|
||||
155
src/Zend/Media/Flac/MetadataBlock/VorbisComment.php
Normal file
155
src/Zend/Media/Flac/MetadataBlock/VorbisComment.php
Normal file
@@ -0,0 +1,155 @@
|
||||
<?php
|
||||
/**
|
||||
* Zend Framework
|
||||
*
|
||||
* LICENSE
|
||||
*
|
||||
* This source file is subject to the new BSD license that is bundled
|
||||
* with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* http://framework.zend.com/license/new-bsd
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@zend.com so we can send you a copy immediately.
|
||||
*
|
||||
* @category Zend
|
||||
* @package Zend_Media
|
||||
* @subpackage FLAC
|
||||
* @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
/**#@+ @ignore */
|
||||
require_once 'Zend/Media/Flac/MetadataBlock.php';
|
||||
require_once 'Zend/Media/Vorbis/Header/Comment.php';
|
||||
/**#@-*/
|
||||
|
||||
/**
|
||||
* This class represents the vorbis comments metadata block. This block is for storing a list of human-readable
|
||||
* name/value pairs. This is the only officially supported tagging mechanism in FLAC. There may be only one
|
||||
* VORBIS_COMMENT block in a stream. In some external documentation, Vorbis comments are called FLAC tags to lessen
|
||||
* confusion.
|
||||
*
|
||||
* This class parses the vorbis comments using the {@link Zend_Media_Vorbis_Header_Comment} class. Any of its method
|
||||
* or fields can be used in the context of this class.
|
||||
*
|
||||
* @category Zend
|
||||
* @package Zend_Media
|
||||
* @subpackage FLAC
|
||||
* @author Sven Vollbehr <sven@vollbehr.eu>
|
||||
* @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
final class Zend_Media_Flac_MetadataBlock_VorbisComment extends Zend_Media_Flac_MetadataBlock
|
||||
{
|
||||
/** @var Zend_Media_Vorbis_Header_Comment */
|
||||
private $_impl;
|
||||
|
||||
/**
|
||||
* Constructs the class with given parameters and parses object related data using the vorbis comment implementation
|
||||
* class {@link Zend_Media_Vorbis_Header_Comment}.
|
||||
*
|
||||
* @param Zend_Io_Reader $reader The reader object.
|
||||
*/
|
||||
public function __construct($reader)
|
||||
{
|
||||
parent::__construct($reader);
|
||||
$this->_impl = new Zend_Media_Vorbis_Header_Comment($this->_reader, array('vorbisContext' => false));
|
||||
}
|
||||
|
||||
/**
|
||||
* Forward all calls to the vorbis comment implementation class {@link Zend_Media_Vorbis_Header_Comment}.
|
||||
*
|
||||
* @param string $name The method name.
|
||||
* @param Array $arguments The method arguments.
|
||||
* @return mixed
|
||||
*/
|
||||
public function __call($name, $arguments)
|
||||
{
|
||||
if (method_exists($this, $name)) {
|
||||
return $this->$name($arguments);
|
||||
}
|
||||
try {
|
||||
return $this->_impl->$name($arguments);
|
||||
} catch (Zend_Media_Vorbis_Exception $e) {
|
||||
require_once 'Zend/Media/Flac/Exception.php';
|
||||
throw new Zend_Media_Flac_Exception($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Forward all calls to the vorbis comment implementation class {@link Zend_Media_Vorbis_Header_Comment}.
|
||||
*
|
||||
* @param string $name The field name.
|
||||
* @return mixed
|
||||
*/
|
||||
public function __get($name)
|
||||
{
|
||||
if (method_exists($this, 'get' . ucfirst($name))) {
|
||||
return call_user_func(array($this, 'get' . ucfirst($name)));
|
||||
}
|
||||
if (method_exists($this->_impl, 'get' . ucfirst($name))) {
|
||||
return call_user_func(array($this->_impl, 'get' . ucfirst($name)));
|
||||
}
|
||||
try {
|
||||
return $this->_impl->__get($name);
|
||||
} catch (Zend_Media_Vorbis_Exception $e) {
|
||||
require_once 'Zend/Media/Flac/Exception.php';
|
||||
throw new Zend_Media_Flac_Exception($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Forward all calls to the vorbis comment implementation class {@link Zend_Media_Vorbis_Header_Comment}.
|
||||
*
|
||||
* @param string $name The field name.
|
||||
* @param string $name The field value.
|
||||
* @return mixed
|
||||
*/
|
||||
public function __set($name, $value)
|
||||
{
|
||||
if (method_exists($this, 'set' . ucfirst($name))) {
|
||||
call_user_func(array($this, 'set' . ucfirst($name)), $value);
|
||||
} else {
|
||||
try {
|
||||
return $this->_impl->__set($name, $value);
|
||||
} catch (Zend_Media_Vorbis_Exception $e) {
|
||||
require_once 'Zend/Media/Flac/Exception.php';
|
||||
throw new Zend_Media_Flac_Exception($e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Forward all calls to the vorbis comment implementation class {@link Zend_Media_Vorbis_Header_Comment}.
|
||||
*
|
||||
* @param string $name The field name.
|
||||
* @return boolean
|
||||
*/
|
||||
public function __isset($name)
|
||||
{
|
||||
try {
|
||||
return $this->_impl->__isset($name);
|
||||
} catch (Zend_Media_Vorbis_Exception $e) {
|
||||
require_once 'Zend/Media/Flac/Exception.php';
|
||||
throw new Zend_Media_Flac_Exception($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Forward all calls to the vorbis comment implementation class {@link Zend_Media_Vorbis_Header_Comment}.
|
||||
*
|
||||
* @param string $name The field name.
|
||||
*/
|
||||
public function __unset($name)
|
||||
{
|
||||
try {
|
||||
$this->_impl->__unset($name);
|
||||
} catch (Zend_Media_Vorbis_Exception $e) {
|
||||
require_once 'Zend/Media/Flac/Exception.php';
|
||||
throw new Zend_Media_Flac_Exception($e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -84,7 +84,7 @@ final class Zend_Media_Id3_Frame_Apic extends Zend_Media_Id3_Frame
|
||||
*
|
||||
* @todo There is the possibility to put only a link to the image file by
|
||||
* using the MIME type '-->' and having a complete URL instead of picture
|
||||
* data. Support for such needs design considerations.
|
||||
* data. Support for such needs further design considerations.
|
||||
* @param Zend_Io_Reader $reader The reader object.
|
||||
* @param Array $options The options array.
|
||||
*/
|
||||
|
||||
@@ -62,17 +62,26 @@ final class Zend_Media_Vorbis_Header_Comment extends Zend_Media_Vorbis_Header
|
||||
private $_comments;
|
||||
|
||||
/** @var integer */
|
||||
private $_framingFlag;
|
||||
private $_framingFlag = 1;
|
||||
|
||||
/**
|
||||
* Constructs the class with given parameters.
|
||||
* Constructs the class with given parameters and reads object related data from the bitstream.
|
||||
*
|
||||
* The following options are currently recognized:
|
||||
* o vorbisContext -- Indicates whether to expect comments to be in the context of a vorbis bitstream or not. This
|
||||
* option can be used to parse vorbis comments in another formats, eg FLAC, that do not use for example the
|
||||
* framing flags. Defaults to true.
|
||||
*
|
||||
* @param Zend_Io_Reader $reader The reader object.
|
||||
* @param Array $options Array of options.
|
||||
*/
|
||||
public function __construct($reader)
|
||||
public function __construct($reader, $options = array())
|
||||
{
|
||||
parent::__construct($reader);
|
||||
|
||||
if (!isset($options['vorbisContext']) || $options['vorbisContext']) {
|
||||
parent::__construct($reader);
|
||||
} else {
|
||||
$this->_reader = $reader;
|
||||
}
|
||||
$this->_vendor = $this->_reader->read($this->_reader->readUInt32LE());
|
||||
$userCommentListLength = $this->_reader->readUInt32LE();
|
||||
for ($i = 0; $i < $userCommentListLength; $i++) {
|
||||
@@ -82,12 +91,24 @@ final class Zend_Media_Vorbis_Header_Comment extends Zend_Media_Vorbis_Header
|
||||
}
|
||||
$this->_comments[strtoupper($name)][] = $value;
|
||||
}
|
||||
$this->_framingFlag = $this->_reader->readUInt8() & 0x1;
|
||||
if ($this->_framingFlag == 0) {
|
||||
require_once 'Zend/Media/Vorbis/Exception.php';
|
||||
throw new Zend_Media_Vorbis_Exception('Undecodable Vorbis stream');
|
||||
if (!isset($options['vorbisContext']) || $options['vorbisContext']) {
|
||||
$this->_framingFlag = $this->_reader->readUInt8() & 0x1;
|
||||
if ($this->_framingFlag == 0) {
|
||||
require_once 'Zend/Media/Vorbis/Exception.php';
|
||||
throw new Zend_Media_Vorbis_Exception('Undecodable Vorbis stream');
|
||||
}
|
||||
$this->_reader->skip($this->_packetSize - $this->_reader->getOffset() + 30 /* header */);
|
||||
}
|
||||
$this->_reader->skip($this->_packetSize - $this->_reader->getOffset() + 30 /* header */);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the vendor string.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getVendor()
|
||||
{
|
||||
return $this->_vendor;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -124,7 +145,7 @@ final class Zend_Media_Vorbis_Header_Comment extends Zend_Media_Vorbis_Header
|
||||
*/
|
||||
public function __isset($name)
|
||||
{
|
||||
return empty($this->_comments[strtoupper($name)]);
|
||||
return count($this->_comments[strtoupper($name)]) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user