ID3v2.4 tag for .mp3 files: PHP parsing library

File extension

mp3

KS implementation details

License: CC0-1.0

References

This page hosts a formal specification of ID3v2.4 tag for .mp3 files using Kaitai Struct. This specification can be automatically translated into a variety of programming languages to get a parsing library.

PHP source code to parse ID3v2.4 tag for .mp3 files

Id3v24.php

<?php
// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild

namespace {
    class Id3v24 extends \Kaitai\Struct\Struct {
        public function __construct(\Kaitai\Struct\Stream $_io, \Kaitai\Struct\Struct $_parent = null, \Id3v24 $_root = null) {
            parent::__construct($_io, $_parent, $_root);
            $this->_read();
        }

        private function _read() {
            $this->_m_tag = new \Id3v24\Tag($this->_io, $this, $this->_root);
        }
        protected $_m_tag;
        public function tag() { return $this->_m_tag; }
    }
}

namespace Id3v24 {
    class U1beSynchsafe extends \Kaitai\Struct\Struct {
        public function __construct(\Kaitai\Struct\Stream $_io, \Id3v24\U2beSynchsafe $_parent = null, \Id3v24 $_root = null) {
            parent::__construct($_io, $_parent, $_root);
            $this->_read();
        }

        private function _read() {
            $this->_m_padding = $this->_io->readBitsIntBe(1) != 0;
            $this->_m_value = $this->_io->readBitsIntBe(7);
        }
        protected $_m_padding;
        protected $_m_value;
        public function padding() { return $this->_m_padding; }
        public function value() { return $this->_m_value; }
    }
}

namespace Id3v24 {
    class U2beSynchsafe extends \Kaitai\Struct\Struct {
        public function __construct(\Kaitai\Struct\Stream $_io, \Id3v24\U4beSynchsafe $_parent = null, \Id3v24 $_root = null) {
            parent::__construct($_io, $_parent, $_root);
            $this->_read();
        }

        private function _read() {
            $this->_m_byte0 = new \Id3v24\U1beSynchsafe($this->_io, $this, $this->_root);
            $this->_m_byte1 = new \Id3v24\U1beSynchsafe($this->_io, $this, $this->_root);
        }
        protected $_m_value;
        public function value() {
            if ($this->_m_value !== null)
                return $this->_m_value;
            $this->_m_value = (($this->byte0()->value() << 7) | $this->byte1()->value());
            return $this->_m_value;
        }
        protected $_m_byte0;
        protected $_m_byte1;
        public function byte0() { return $this->_m_byte0; }
        public function byte1() { return $this->_m_byte1; }
    }
}

namespace Id3v24 {
    class Tag extends \Kaitai\Struct\Struct {
        public function __construct(\Kaitai\Struct\Stream $_io, \Id3v24 $_parent = null, \Id3v24 $_root = null) {
            parent::__construct($_io, $_parent, $_root);
            $this->_read();
        }

        private function _read() {
            $this->_m_header = new \Id3v24\Header($this->_io, $this, $this->_root);
            if ($this->header()->flags()->flagHeaderex()) {
                $this->_m_headerEx = new \Id3v24\HeaderEx($this->_io, $this, $this->_root);
            }
            $this->_m_frames = [];
            $i = 0;
            do {
                $_ = new \Id3v24\Frame($this->_io, $this, $this->_root);
                $this->_m_frames[] = $_;
                $i++;
            } while (!( ((($this->_io()->pos() + $_->size()->value()) > $this->header()->size()->value()) || ($_->isInvalid())) ));
            if (!($this->header()->flags()->flagFooter())) {
                $this->_m_padding = new \Id3v24\Padding($this->_io, $this, $this->_root);
            }
            if ($this->header()->flags()->flagFooter()) {
                $this->_m_footer = new \Id3v24\Footer($this->_io, $this, $this->_root);
            }
        }
        protected $_m_header;
        protected $_m_headerEx;
        protected $_m_frames;
        protected $_m_padding;
        protected $_m_footer;
        public function header() { return $this->_m_header; }
        public function headerEx() { return $this->_m_headerEx; }
        public function frames() { return $this->_m_frames; }
        public function padding() { return $this->_m_padding; }
        public function footer() { return $this->_m_footer; }
    }
}

namespace Id3v24 {
    class U4beSynchsafe extends \Kaitai\Struct\Struct {
        public function __construct(\Kaitai\Struct\Stream $_io, \Kaitai\Struct\Struct $_parent = null, \Id3v24 $_root = null) {
            parent::__construct($_io, $_parent, $_root);
            $this->_read();
        }

        private function _read() {
            $this->_m_short0 = new \Id3v24\U2beSynchsafe($this->_io, $this, $this->_root);
            $this->_m_short1 = new \Id3v24\U2beSynchsafe($this->_io, $this, $this->_root);
        }
        protected $_m_value;
        public function value() {
            if ($this->_m_value !== null)
                return $this->_m_value;
            $this->_m_value = (($this->short0()->value() << 14) | $this->short1()->value());
            return $this->_m_value;
        }
        protected $_m_short0;
        protected $_m_short1;
        public function short0() { return $this->_m_short0; }
        public function short1() { return $this->_m_short1; }
    }
}

namespace Id3v24 {
    class Frame extends \Kaitai\Struct\Struct {
        public function __construct(\Kaitai\Struct\Stream $_io, \Id3v24\Tag $_parent = null, \Id3v24 $_root = null) {
            parent::__construct($_io, $_parent, $_root);
            $this->_read();
        }

        private function _read() {
            $this->_m_id = \Kaitai\Struct\Stream::bytesToStr($this->_io->readBytes(4), "ASCII");
            $this->_m_size = new \Id3v24\U4beSynchsafe($this->_io, $this, $this->_root);
            $this->_m_flagsStatus = new \Id3v24\Frame\FlagsStatus($this->_io, $this, $this->_root);
            $this->_m_flagsFormat = new \Id3v24\Frame\FlagsFormat($this->_io, $this, $this->_root);
            $this->_m_data = $this->_io->readBytes($this->size()->value());
        }
        protected $_m_isInvalid;
        public function isInvalid() {
            if ($this->_m_isInvalid !== null)
                return $this->_m_isInvalid;
            $this->_m_isInvalid = $this->id() == "\000\000\000\000";
            return $this->_m_isInvalid;
        }
        protected $_m_id;
        protected $_m_size;
        protected $_m_flagsStatus;
        protected $_m_flagsFormat;
        protected $_m_data;
        public function id() { return $this->_m_id; }
        public function size() { return $this->_m_size; }
        public function flagsStatus() { return $this->_m_flagsStatus; }
        public function flagsFormat() { return $this->_m_flagsFormat; }
        public function data() { return $this->_m_data; }
    }
}

namespace Id3v24\Frame {
    class FlagsStatus extends \Kaitai\Struct\Struct {
        public function __construct(\Kaitai\Struct\Stream $_io, \Id3v24\Frame $_parent = null, \Id3v24 $_root = null) {
            parent::__construct($_io, $_parent, $_root);
            $this->_read();
        }

        private function _read() {
            $this->_m_reserved1 = $this->_io->readBitsIntBe(1) != 0;
            $this->_m_flagDiscardAlterTag = $this->_io->readBitsIntBe(1) != 0;
            $this->_m_flagDiscardAlterFile = $this->_io->readBitsIntBe(1) != 0;
            $this->_m_flagReadOnly = $this->_io->readBitsIntBe(1) != 0;
            $this->_m_reserved2 = $this->_io->readBitsIntBe(4);
        }
        protected $_m_reserved1;
        protected $_m_flagDiscardAlterTag;
        protected $_m_flagDiscardAlterFile;
        protected $_m_flagReadOnly;
        protected $_m_reserved2;
        public function reserved1() { return $this->_m_reserved1; }
        public function flagDiscardAlterTag() { return $this->_m_flagDiscardAlterTag; }
        public function flagDiscardAlterFile() { return $this->_m_flagDiscardAlterFile; }
        public function flagReadOnly() { return $this->_m_flagReadOnly; }
        public function reserved2() { return $this->_m_reserved2; }
    }
}

namespace Id3v24\Frame {
    class FlagsFormat extends \Kaitai\Struct\Struct {
        public function __construct(\Kaitai\Struct\Stream $_io, \Id3v24\Frame $_parent = null, \Id3v24 $_root = null) {
            parent::__construct($_io, $_parent, $_root);
            $this->_read();
        }

        private function _read() {
            $this->_m_reserved1 = $this->_io->readBitsIntBe(1) != 0;
            $this->_m_flagGrouping = $this->_io->readBitsIntBe(1) != 0;
            $this->_m_reserved2 = $this->_io->readBitsIntBe(2);
            $this->_m_flagCompressed = $this->_io->readBitsIntBe(1) != 0;
            $this->_m_flagEncrypted = $this->_io->readBitsIntBe(1) != 0;
            $this->_m_flagUnsynchronisated = $this->_io->readBitsIntBe(1) != 0;
            $this->_m_flagIndicator = $this->_io->readBitsIntBe(1) != 0;
        }
        protected $_m_reserved1;
        protected $_m_flagGrouping;
        protected $_m_reserved2;
        protected $_m_flagCompressed;
        protected $_m_flagEncrypted;
        protected $_m_flagUnsynchronisated;
        protected $_m_flagIndicator;
        public function reserved1() { return $this->_m_reserved1; }
        public function flagGrouping() { return $this->_m_flagGrouping; }
        public function reserved2() { return $this->_m_reserved2; }
        public function flagCompressed() { return $this->_m_flagCompressed; }
        public function flagEncrypted() { return $this->_m_flagEncrypted; }
        public function flagUnsynchronisated() { return $this->_m_flagUnsynchronisated; }
        public function flagIndicator() { return $this->_m_flagIndicator; }
    }
}

namespace Id3v24 {
    class HeaderEx extends \Kaitai\Struct\Struct {
        public function __construct(\Kaitai\Struct\Stream $_io, \Id3v24\Tag $_parent = null, \Id3v24 $_root = null) {
            parent::__construct($_io, $_parent, $_root);
            $this->_read();
        }

        private function _read() {
            $this->_m_size = new \Id3v24\U4beSynchsafe($this->_io, $this, $this->_root);
            $this->_m_flagsEx = new \Id3v24\HeaderEx\FlagsEx($this->_io, $this, $this->_root);
            $this->_m_data = $this->_io->readBytes(($this->size()->value() - 5));
        }
        protected $_m_size;
        protected $_m_flagsEx;
        protected $_m_data;
        public function size() { return $this->_m_size; }
        public function flagsEx() { return $this->_m_flagsEx; }
        public function data() { return $this->_m_data; }
    }
}

namespace Id3v24\HeaderEx {
    class FlagsEx extends \Kaitai\Struct\Struct {
        public function __construct(\Kaitai\Struct\Stream $_io, \Id3v24\HeaderEx $_parent = null, \Id3v24 $_root = null) {
            parent::__construct($_io, $_parent, $_root);
            $this->_read();
        }

        private function _read() {
            $this->_m_reserved1 = $this->_io->readBitsIntBe(1) != 0;
            $this->_m_flagUpdate = $this->_io->readBitsIntBe(1) != 0;
            $this->_m_flagCrc = $this->_io->readBitsIntBe(1) != 0;
            $this->_m_flagRestrictions = $this->_io->readBitsIntBe(1) != 0;
            $this->_m_reserved2 = $this->_io->readBitsIntBe(4);
        }
        protected $_m_reserved1;
        protected $_m_flagUpdate;
        protected $_m_flagCrc;
        protected $_m_flagRestrictions;
        protected $_m_reserved2;
        public function reserved1() { return $this->_m_reserved1; }
        public function flagUpdate() { return $this->_m_flagUpdate; }
        public function flagCrc() { return $this->_m_flagCrc; }
        public function flagRestrictions() { return $this->_m_flagRestrictions; }
        public function reserved2() { return $this->_m_reserved2; }
    }
}

namespace Id3v24 {
    class Header extends \Kaitai\Struct\Struct {
        public function __construct(\Kaitai\Struct\Stream $_io, \Id3v24\Tag $_parent = null, \Id3v24 $_root = null) {
            parent::__construct($_io, $_parent, $_root);
            $this->_read();
        }

        private function _read() {
            $this->_m_magic = $this->_io->readBytes(3);
            if (!($this->magic() == "\x49\x44\x33")) {
                throw new \Kaitai\Struct\Error\ValidationNotEqualError("\x49\x44\x33", $this->magic(), $this->_io(), "/types/header/seq/0");
            }
            $this->_m_versionMajor = $this->_io->readU1();
            $this->_m_versionRevision = $this->_io->readU1();
            $this->_m_flags = new \Id3v24\Header\Flags($this->_io, $this, $this->_root);
            $this->_m_size = new \Id3v24\U4beSynchsafe($this->_io, $this, $this->_root);
        }
        protected $_m_magic;
        protected $_m_versionMajor;
        protected $_m_versionRevision;
        protected $_m_flags;
        protected $_m_size;
        public function magic() { return $this->_m_magic; }
        public function versionMajor() { return $this->_m_versionMajor; }
        public function versionRevision() { return $this->_m_versionRevision; }
        public function flags() { return $this->_m_flags; }
        public function size() { return $this->_m_size; }
    }
}

namespace Id3v24\Header {
    class Flags extends \Kaitai\Struct\Struct {
        public function __construct(\Kaitai\Struct\Stream $_io, \Id3v24\Header $_parent = null, \Id3v24 $_root = null) {
            parent::__construct($_io, $_parent, $_root);
            $this->_read();
        }

        private function _read() {
            $this->_m_flagUnsynchronization = $this->_io->readBitsIntBe(1) != 0;
            $this->_m_flagHeaderex = $this->_io->readBitsIntBe(1) != 0;
            $this->_m_flagExperimental = $this->_io->readBitsIntBe(1) != 0;
            $this->_m_flagFooter = $this->_io->readBitsIntBe(1) != 0;
            $this->_m_reserved = $this->_io->readBitsIntBe(4);
        }
        protected $_m_flagUnsynchronization;
        protected $_m_flagHeaderex;
        protected $_m_flagExperimental;
        protected $_m_flagFooter;
        protected $_m_reserved;
        public function flagUnsynchronization() { return $this->_m_flagUnsynchronization; }
        public function flagHeaderex() { return $this->_m_flagHeaderex; }
        public function flagExperimental() { return $this->_m_flagExperimental; }
        public function flagFooter() { return $this->_m_flagFooter; }
        public function reserved() { return $this->_m_reserved; }
    }
}

namespace Id3v24 {
    class Padding extends \Kaitai\Struct\Struct {
        public function __construct(\Kaitai\Struct\Stream $_io, \Id3v24\Tag $_parent = null, \Id3v24 $_root = null) {
            parent::__construct($_io, $_parent, $_root);
            $this->_read();
        }

        private function _read() {
            $this->_m_padding = $this->_io->readBytes(($this->_root()->tag()->header()->size()->value() - $this->_io()->pos()));
        }
        protected $_m_padding;
        public function padding() { return $this->_m_padding; }
    }
}

namespace Id3v24 {
    class Footer extends \Kaitai\Struct\Struct {
        public function __construct(\Kaitai\Struct\Stream $_io, \Id3v24\Tag $_parent = null, \Id3v24 $_root = null) {
            parent::__construct($_io, $_parent, $_root);
            $this->_read();
        }

        private function _read() {
            $this->_m_magic = $this->_io->readBytes(3);
            if (!($this->magic() == "\x33\x44\x49")) {
                throw new \Kaitai\Struct\Error\ValidationNotEqualError("\x33\x44\x49", $this->magic(), $this->_io(), "/types/footer/seq/0");
            }
            $this->_m_versionMajor = $this->_io->readU1();
            $this->_m_versionRevision = $this->_io->readU1();
            $this->_m_flags = new \Id3v24\Footer\Flags($this->_io, $this, $this->_root);
            $this->_m_size = new \Id3v24\U4beSynchsafe($this->_io, $this, $this->_root);
        }
        protected $_m_magic;
        protected $_m_versionMajor;
        protected $_m_versionRevision;
        protected $_m_flags;
        protected $_m_size;
        public function magic() { return $this->_m_magic; }
        public function versionMajor() { return $this->_m_versionMajor; }
        public function versionRevision() { return $this->_m_versionRevision; }
        public function flags() { return $this->_m_flags; }
        public function size() { return $this->_m_size; }
    }
}

namespace Id3v24\Footer {
    class Flags extends \Kaitai\Struct\Struct {
        public function __construct(\Kaitai\Struct\Stream $_io, \Id3v24\Footer $_parent = null, \Id3v24 $_root = null) {
            parent::__construct($_io, $_parent, $_root);
            $this->_read();
        }

        private function _read() {
            $this->_m_flagUnsynchronization = $this->_io->readBitsIntBe(1) != 0;
            $this->_m_flagHeaderex = $this->_io->readBitsIntBe(1) != 0;
            $this->_m_flagExperimental = $this->_io->readBitsIntBe(1) != 0;
            $this->_m_flagFooter = $this->_io->readBitsIntBe(1) != 0;
            $this->_m_reserved = $this->_io->readBitsIntBe(4);
        }
        protected $_m_flagUnsynchronization;
        protected $_m_flagHeaderex;
        protected $_m_flagExperimental;
        protected $_m_flagFooter;
        protected $_m_reserved;
        public function flagUnsynchronization() { return $this->_m_flagUnsynchronization; }
        public function flagHeaderex() { return $this->_m_flagHeaderex; }
        public function flagExperimental() { return $this->_m_flagExperimental; }
        public function flagFooter() { return $this->_m_flagFooter; }
        public function reserved() { return $this->_m_reserved; }
    }
}