Esempio n. 1
0
 /**
  * Constructs the Zend_Media_Mpeg_ABS class with given file and options.
  *
  * The following options are currently recognized:
  *   o readmode -- Can be one of full or lazy and determines when the read
  *     of frames and their data happens. When in full mode the data is read
  *     automatically during the instantiation of the frame and all the
  *     frames are read during the instantiation of this class. While this
  *     allows faster validation and data fetching, it is unnecessary in
  *     terms of determining just the play duration of the file. Defaults to
  *     lazy.
  *
  *   o estimatePrecision -- Only applicaple with lazy read mode to determine
  *     the precision of play duration estimate. This precision is equal to
  *     how many frames are read before fixing the average bitrate that is
  *     used to calculate the play duration estimate of the whole file. Each
  *     frame adds about 0.1-0.2ms to the processing of the file. Defaults to
  *     1000.
  *
  * When in lazy data reading mode it is first checked whether a VBR header
  * is found in a file. If so, the play duration is calculated based no its
  * data and no further frames are read from the file. If no VBR header is
  * found, frames up to estimatePrecision are read to calculate an average
  * bitrate.
  *
  * Hence, only zero or <var>estimatePrecision</var> number of frames are
  * read in lazy data reading mode. The rest of the frames are read
  * automatically when directly referenced, ie the data is read when it is
  * needed.
  *
  * @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.
  * @param Array                          $options  The options array.
  */
 public function __construct($filename, $options = array())
 {
     if ($filename instanceof Zend_Io_Reader) {
         $this->_reader =& $filename;
     } else {
         try {
             $this->_reader = new Zend_Io_FileReader($filename);
         } catch (Zend_Io_Exception $e) {
             $this->_reader = null;
             throw new Zend_Media_Mpeg_Exception($e->getMessage());
         }
     }
     $this->setOptions($options);
     $offset = $this->_reader->getOffset();
     $this->_bytes = $this->_reader->getSize();
     /* Skip ID3v1 tag */
     $this->_reader->setOffset(-128);
     if ($this->_reader->read(3) == 'TAG') {
         $this->_bytes -= 128;
     }
     $this->_reader->setOffset($offset);
     /* Skip ID3v2 tags (some files errorneusly contain multiple tags) */
     while ($this->_reader->readString8(3) == 'ID3') {
         $header = new Zend_Media_Id3_Header($this->_reader);
         $this->_reader->skip($header->getSize() + ($header->hasFlag(Zend_Media_Id3_Header::FOOTER) ? 10 : 0));
         $offset = $this->_reader->getOffset();
     }
     $this->_reader->setOffset($offset);
     /* Check whether the ABS is contained within a RIFF chunk */
     $offset = $this->_reader->getOffset();
     if ($this->_reader->readString8(4) == 'RIFF') {
         $riffSize = $this->_reader->readUInt32LE();
         $riffType = $this->_reader->read(4);
         // WAVE
         while ($this->_reader->getOffset() < $offset + 8 + $riffSize - 1) {
             $chunkId = $this->_reader->read(4);
             $chunkSize = $this->_reader->readUInt32LE();
             if ($chunkId == 'fmt ') {
                 if ($this->_reader->readInt16LE() != 85) {
                     // 85: MPEG-1 Layer 3 Codec
                     throw new Zend_Media_Mpeg_Exception('File does not contain a valid MPEG Audio Bit Stream (Contains RIFF with no MPEG ABS)');
                 } else {
                     $this->_reader->skip($chunkSize - 2);
                 }
             } else {
                 if ($chunkId == 'data') {
                     $offset = $this->_reader->getOffset();
                     break;
                 } else {
                     $this->_reader->skip($chunkSize);
                 }
             }
         }
     } else {
         $this->_reader->setOffset($offset);
     }
     /* Check for VBR headers */
     $this->_frames[] = $firstFrame = new Zend_Media_Mpeg_Abs_Frame($this->_reader, $options);
     $offset = $this->_reader->getOffset();
     $this->_reader->setOffset($firstFrame->getOffset() + 4 + self::$sidesizes[$firstFrame->getFrequencyType()][$firstFrame->getMode()]);
     if (($xing = $this->_reader->readString8(4)) == 'Xing' || $xing == 'Info') {
         $this->_xingHeader = new Zend_Media_Mpeg_Abs_XingHeader($this->_reader, $options);
         if ($this->_reader->readString8(4) == 'LAME') {
             $this->_lameHeader = new Zend_Media_Mpeg_Abs_LameHeader($this->_reader, $options);
         }
         // A header frame is not counted as an audio frame
         array_pop($this->_frames);
     }
     $this->_reader->setOffset($firstFrame->getOffset() + 4 + 32);
     if ($this->_reader->readString8(4) == 'VBRI') {
         $this->_vbriHeader = new Zend_Media_Mpeg_Abs_VbriHeader($this->_reader, $options);
         // A header frame is not counted as an audio frame
         array_pop($this->_frames);
     }
     $this->_reader->setOffset($offset);
     // Ensure we always have read at least one frame
     if (empty($this->_frames)) {
         $this->_readFrames(1);
     }
     /* Read necessary frames */
     if ($this->getOption('readmode', 'lazy') == 'lazy') {
         if ((($header = $this->_xingHeader) !== null || ($header = $this->_vbriHeader) !== null) && $header->getFrames() != 0) {
             $this->_estimatedPlayDuration = $header->getFrames() * $firstFrame->getSamples() / $firstFrame->getSamplingFrequency();
             if ($this->_lameHeader !== null) {
                 $this->_estimatedBitrate = $this->_lameHeader->getBitrate();
                 if ($this->_estimatedBitrate == 255) {
                     $this->_estimatedBitrate = round($this->_lameHeader->getMusicLength() / ($header->getFrames() * $firstFrame->getSamples() / $firstFrame->getSamplingFrequency()) / 1000 * 8);
                 }
             } else {
                 $this->_estimatedBitrate = ($this->_bytes - $firstFrame->getOffset()) / $this->_estimatedPlayDuration / 1000 * 8;
             }
         } else {
             $this->_readFrames($this->getOption('estimatePrecision', 1000));
             $this->_estimatedBitrate = $this->_cumulativeBitrate / count($this->_frames);
             $this->_estimatedPlayDuration = ($this->_bytes - $firstFrame->getOffset()) / ($this->_estimatedBitrate * 1000 / 8);
         }
     } else {
         $this->_readFrames();
         $this->_estimatedBitrate = $this->_cumulativeBitrate / count($this->_frames);
         $this->_estimatedPlayDuration = $this->_cumulativePlayDuration;
     }
 }
Esempio n. 2
0
 /**
  * Constructs the Zend_Media_Mpeg_ABS class with given file and options.
  *
  * The following options are currently recognized:
  *   o readmode -- Can be one of full or lazy and determines when the read
  *     of frames and their data happens. When in full mode the data is read
  *     automatically during the instantiation of the frame and all the
  *     frames are read during the instantiation of this class. While this
  *     allows faster validation and data fetching, it is unnecessary in
  *     terms of determining just the play duration of the file. Defaults to
  *     lazy.
  *
  *   o estimatePrecision -- Only applicaple with lazy read mode to determine
  *     the precision of play duration estimate. This precision is equal to
  *     how many frames are read before fixing the average bitrate that is
  *     used to calculate the play duration estimate of the whole file. Each
  *     frame adds about 0.1-0.2ms to the processing of the file. Defaults to
  *     1000.
  *
  * When in lazy data reading mode it is first checked whether a VBR header
  * is found in a file. If so, the play duration is calculated based no its
  * data and no further frames are read from the file. If no VBR header is
  * found, frames up to estimatePrecision are read to calculate an average
  * bitrate.
  *
  * Hence, only zero or <var>estimatePrecision</var> number of frames are
  * read in lazy data reading mode. The rest of the frames are read
  * automatically when directly referenced, ie the data is read when it is
  * needed.
  *
  * @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.
  * @param Array                          $options  The options array.
  */
 public function __construct($filename, $options = array())
 {
     if ($filename instanceof Zend_Io_Reader) {
         $this->_reader =& $filename;
     } else {
         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/Mpeg/Exception.php';
             throw new Zend_Media_Mpeg_Exception($e->getMessage());
         }
     }
     $this->setOptions($options);
     $offset = $this->_reader->getOffset();
     $this->_bytes = $this->_reader->getSize();
     /* Skip ID3v1 tag */
     $this->_reader->setOffset(-128);
     if ($this->_reader->read(3) == 'TAG') {
         $this->_bytes -= 128;
     }
     $this->_reader->setOffset($offset);
     /* Skip ID3v2 tag */
     if ($this->_reader->readString8(3) == 'ID3') {
         require_once 'Zend/Media/Id3/Header.php';
         $header = new Zend_Media_Id3_Header($this->_reader);
         $this->_reader->skip($header->getSize() + ($header->hasFlag(Zend_Media_Id3_Header::FOOTER) ? 10 : 0));
     } else {
         $this->_reader->setOffset($offset);
     }
     /* Check for VBR headers */
     $offset = $this->_reader->getOffset();
     $this->_frames[] = $firstFrame = new Zend_Media_Mpeg_Abs_Frame($this->_reader, $options);
     $postoffset = $this->_reader->getOffset();
     $this->_reader->setOffset($offset + 4 + self::$sidesizes[$firstFrame->getFrequencyType()][$firstFrame->getMode()]);
     if (($xing = $this->_reader->readString8(4)) == 'Xing' || $xing == 'Info') {
         require_once 'Zend/Media/Mpeg/Abs/XingHeader.php';
         $this->_xingHeader = new Zend_Media_Mpeg_Abs_XingHeader($this->_reader, $options);
         if ($this->_reader->readString8(4) == 'LAME') {
             require_once 'Zend/Media/Mpeg/Abs/LameHeader.php';
             $this->_lameHeader = new Zend_Media_Mpeg_Abs_LameHeader($this->_reader, $options);
         }
         // A header frame is not counted as an audio frame
         array_pop($this->_frames);
     }
     $this->_reader->setOffset($offset + 4 + 32);
     if ($this->_reader->readString8(4) == 'VBRI') {
         require_once 'Zend/Media/Mpeg/Abs/VbriHeader.php';
         $this->_vbriHeader = new Zend_Media_Mpeg_Abs_VbriHeader($this->_reader, $options);
         // A header frame is not counted as an audio frame
         array_pop($this->_frames);
     }
     $this->_reader->setOffset($postoffset);
     // Ensure we always have read at least one frame
     if (empty($this->_frames)) {
         $this->_readFrames(1);
     }
     /* Read necessary frames */
     if ($this->getOption('readmode', 'lazy') == 'lazy') {
         if (($header = $this->_xingHeader) !== null || ($header = $this->_vbriHeader) !== null) {
             $this->_estimatedPlayDuration = $header->getFrames() * $firstFrame->getSamples() / $firstFrame->getSamplingFrequency();
             if ($this->_lameHeader !== null) {
                 $this->_estimatedBitrate = $this->_lameHeader->getBitrate();
                 if ($this->_estimatedBitrate == 255) {
                     $this->_estimatedBitrate = round($this->_lameHeader->getMusicLength() / ($header->getFrames() * $firstFrame->getSamples() / $firstFrame->getSamplingFrequency()) / 1000 * 8);
                 }
             } else {
                 $this->_estimatedBitrate = ($this->_bytes - $offset) / $this->_estimatedPlayDuration / 1000 * 8;
             }
         } else {
             $this->_readFrames($this->getOption('estimatePrecision', 1000));
             $this->_estimatedBitrate = $this->_cumulativeBitrate / count($this->_frames);
             $this->_estimatedPlayDuration = ($this->_bytes - $offset) / ($this->_estimatedBitrate * 1000 / 8);
         }
     } else {
         $this->_readFrames();
         $this->_estimatedBitrate = $this->_cumulativeBitrate / count($this->_frames);
         $this->_estimatedPlayDuration = $this->_cumulativePlayDuration;
     }
 }