Beispiel #1
0
 /**
  * Removes the ID3v2 tag altogether.
  *
  * @param string $filename The path to the file.
  */
 public static function remove($filename)
 {
     if ($filename instanceof Zend_Io_Reader) {
         $reader =& $filename;
     } else {
         $reader = new Zend_Io_FileReader($filename, 'r+b');
     }
     $fileSize = $reader->getSize();
     if ($reader->read(3) == 'ID3') {
         $header = new Zend_Media_Id3_Header($reader);
         $tagSize = 10 + $header->getSize();
     } else {
         return;
     }
     $fd = $reader->getFileDescriptor();
     for ($i = 0; $tagSize + $i * 1024 < $fileSize; $i++) {
         fseek($fd, $tagSize + $i * 1024);
         $buffer = fread($fd, 1024);
         fseek($fd, $i * 1024);
         $bytes = fwrite($fd, $buffer, 1024);
     }
     ftruncate($fd, $fileSize - $tagSize);
 }
Beispiel #2
0
 /**
  * Writes the tag data.
  *
  * @param Zend_Io_Writer $writer The writer object.
  * @return void
  */
 private function _writeData($writer)
 {
     $this->clearOption('unsyncronisation');
     $buffer = new Zend_Io_StringWriter();
     foreach ($this->_frames as $frames) {
         foreach ($frames as $frame) {
             $frame->write($buffer);
         }
     }
     $frameData = $buffer->toString();
     $frameDataLength = strlen($frameData);
     $paddingLength = 0;
     // ID3v2.4.0 supports frame level unsynchronisation. The corresponding
     // option is set to true when any of the frames use the
     // unsynchronisation scheme.
     if ($this->getOption('unsyncronisation', false) === true) {
         $this->_header->setFlags($this->_header->getFlags() | Zend_Media_Id3_Header::UNSYNCHRONISATION);
     }
     // ID3v2.3.0 supports only tag level unsynchronisation
     if ($this->getOption('version', 4) < 4) {
         $frameData = $this->_encodeUnsynchronisation($frameData);
         if (($len = strlen($frameData)) != $frameDataLength) {
             $frameDataLength = $len;
             $this->_header->setFlags($this->_header->getFlags() | Zend_Media_Id3_Header::UNSYNCHRONISATION);
         } else {
             $this->_header->setFlags($this->_header->getFlags() & ~Zend_Media_Id3_Header::UNSYNCHRONISATION);
         }
     }
     // The tag padding is calculated as follows. If the tag can be written
     // in the space of the previous tag, the remaining space is used for
     // padding. If there is no previous tag or the new tag is bigger than
     // the space taken by the previous tag, the padding is a constant
     // 4096 bytes.
     if ($this->hasFooter() === false) {
         if ($this->_reader !== null && $frameDataLength < $this->_header->getSize()) {
             $paddingLength = $this->_header->getSize() - $frameDataLength;
         } else {
             $paddingLength = 4096;
         }
     }
     /* ID3v2.4.0 CRC calculated w/ padding */
     if ($this->getOption('version', 4) >= 4) {
         $frameData = str_pad($frameData, $frameDataLength += $paddingLength, "");
     }
     $extendedHeaderData = '';
     $extendedHeaderDataLength = 0;
     if ($this->hasExtendedHeader()) {
         $this->_extendedHeader->setPadding($paddingLength);
         if ($this->_extendedHeader->hasFlag(Zend_Media_Id3_ExtendedHeader::CRC32)) {
             $crc = crc32($frameData);
             if ($crc & 2147483648.0) {
                 $crc = -(($crc ^ 4294967295.0) + 1);
             }
             $this->_extendedHeader->setCrc($crc);
         }
         $buffer = new Zend_Io_StringWriter();
         $this->_extendedHeader->write($buffer);
         $extendedHeaderData = $buffer->toString();
         $extendedHeaderDataLength = strlen($extendedHeaderData);
     }
     /* ID3v2.3.0 CRC calculated w/o padding */
     if ($this->getOption('version', 4) < 4) {
         $frameData = str_pad($frameData, $frameDataLength += $paddingLength, "");
     }
     $this->_header->setSize($extendedHeaderDataLength + $frameDataLength);
     $writer->write('ID3');
     $this->_header->write($writer);
     $writer->write($extendedHeaderData);
     $writer->write($frameData);
     if ($this->hasFooter()) {
         $writer->write('3DI');
         $this->_footer->write($writer);
     }
 }
Beispiel #3
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;
     }
 }
Beispiel #4
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;
     }
 }