Mini Shell

Direktori : /home/admin/web/mcpv.demarco.ddnsfree.com/public_html/wp-includes/ID3/
Upload File :
Current File : /home/admin/web/mcpv.demarco.ddnsfree.com/public_html/wp-includes/ID3/module.audio.ogg.php

<?php

/////////////////////////////////////////////////////////////////
/// getID3() by James Heinrich <info@getid3.org>               //
//  available at https://github.com/JamesHeinrich/getID3       //
//            or https://www.getid3.org                        //
//            or http://getid3.sourceforge.net                 //
//  see readme.txt for more details                            //
/////////////////////////////////////////////////////////////////
//                                                             //
// module.audio.ogg.php                                        //
// module for analyzing Ogg Vorbis, OggFLAC and Speex files    //
// dependencies: module.audio.flac.php                         //
//                                                            ///
/////////////////////////////////////////////////////////////////

if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
	exit;
}
getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.flac.php', __FILE__, true);

class getid3_ogg extends getid3_handler
{
	/**
	 * @link http://xiph.org/vorbis/doc/Vorbis_I_spec.html
	 *
	 * @return bool
	 */
	public function Analyze() {
		$info = &$this->getid3->info;

		$info['fileformat'] = 'ogg';

		// Warn about illegal tags - only vorbiscomments are allowed
		if (isset($info['id3v2'])) {
			$this->warning('Illegal ID3v2 tag present.');
		}
		if (isset($info['id3v1'])) {
			$this->warning('Illegal ID3v1 tag present.');
		}
		if (isset($info['ape'])) {
			$this->warning('Illegal APE tag present.');
		}


		// Page 1 - Stream Header

		$this->fseek($info['avdataoffset']);

		$oggpageinfo = $this->ParseOggPageHeader();
		$info['ogg']['pageheader'][$oggpageinfo['page_seqno']] = $oggpageinfo;

		if ($this->ftell() >= $this->getid3->fread_buffer_size()) {
			$this->error('Could not find start of Ogg page in the first '.$this->getid3->fread_buffer_size().' bytes (this might not be an Ogg-Vorbis file?)');
			unset($info['fileformat']);
			unset($info['ogg']);
			return false;
		}

		$filedata = $this->fread($oggpageinfo['page_length']);
		$filedataoffset = 0;

		if (substr($filedata, 0, 4) == 'fLaC') {

			$info['audio']['dataformat']   = 'flac';
			$info['audio']['bitrate_mode'] = 'vbr';
			$info['audio']['lossless']     = true;

		} elseif (substr($filedata, 1, 6) == 'vorbis') {

			$this->ParseVorbisPageHeader($filedata, $filedataoffset, $oggpageinfo);

		} elseif (substr($filedata, 0, 8) == 'OpusHead') {

			if ($this->ParseOpusPageHeader($filedata, $filedataoffset, $oggpageinfo) === false) {
				return false;
			}

		} elseif (substr($filedata, 0, 8) == 'Speex   ') {

			// http://www.speex.org/manual/node10.html

			$info['audio']['dataformat']   = 'speex';
			$info['mime_type']             = 'audio/speex';
			$info['audio']['bitrate_mode'] = 'abr';
			$info['audio']['lossless']     = false;

			$info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['speex_string']           =                              substr($filedata, $filedataoffset, 8); // hard-coded to 'Speex   '
			$filedataoffset += 8;
			$info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['speex_version']          =                              substr($filedata, $filedataoffset, 20);
			$filedataoffset += 20;
			$info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['speex_version_id']       = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
			$filedataoffset += 4;
			$info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['header_size']            = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
			$filedataoffset += 4;
			$info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['rate']                   = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
			$filedataoffset += 4;
			$info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['mode']                   = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
			$filedataoffset += 4;
			$info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['mode_bitstream_version'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
			$filedataoffset += 4;
			$info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['nb_channels']            = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
			$filedataoffset += 4;
			$info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['bitrate']                = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
			$filedataoffset += 4;
			$info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['framesize']              = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
			$filedataoffset += 4;
			$info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['vbr']                    = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
			$filedataoffset += 4;
			$info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['frames_per_packet']      = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
			$filedataoffset += 4;
			$info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['extra_headers']          = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
			$filedataoffset += 4;
			$info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['reserved1']              = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
			$filedataoffset += 4;
			$info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['reserved2']              = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
			$filedataoffset += 4;

			$info['speex']['speex_version'] = trim($info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['speex_version']);
			$info['speex']['sample_rate']   = $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['rate'];
			$info['speex']['channels']      = $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['nb_channels'];
			$info['speex']['vbr']           = (bool) $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['vbr'];
			$info['speex']['band_type']     = $this->SpeexBandModeLookup($info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['mode']);

			$info['audio']['sample_rate']   = $info['speex']['sample_rate'];
			$info['audio']['channels']      = $info['speex']['channels'];
			if ($info['speex']['vbr']) {
				$info['audio']['bitrate_mode'] = 'vbr';
			}

		} elseif (substr($filedata, 0, 7) == "\x80".'theora') {

			// http://www.theora.org/doc/Theora.pdf (section 6.2)

			$info['ogg']['pageheader']['theora']['theora_magic']             =                           substr($filedata, $filedataoffset,  7); // hard-coded to "\x80.'theora'
			$filedataoffset += 7;
			$info['ogg']['pageheader']['theora']['version_major']            = getid3_lib::BigEndian2Int(substr($filedata, $filedataoffset,  1));
			$filedataoffset += 1;
			$info['ogg']['pageheader']['theora']['version_minor']            = getid3_lib::BigEndian2Int(substr($filedata, $filedataoffset,  1));
			$filedataoffset += 1;
			$info['ogg']['pageheader']['theora']['version_revision']         = getid3_lib::BigEndian2Int(substr($filedata, $filedataoffset,  1));
			$filedataoffset += 1;
			$info['ogg']['pageheader']['theora']['frame_width_macroblocks']  = getid3_lib::BigEndian2Int(substr($filedata, $filedataoffset,  2));
			$filedataoffset += 2;
			$info['ogg']['pageheader']['theora']['frame_height_macroblocks'] = getid3_lib::BigEndian2Int(substr($filedata, $filedataoffset,  2));
			$filedataoffset += 2;
			$info['ogg']['pageheader']['theora']['resolution_x']             = getid3_lib::BigEndian2Int(substr($filedata, $filedataoffset,  3));
			$filedataoffset += 3;
			$info['ogg']['pageheader']['theora']['resolution_y']             = getid3_lib::BigEndian2Int(substr($filedata, $filedataoffset,  3));
			$filedataoffset += 3;
			$info['ogg']['pageheader']['theora']['picture_offset_x']         = getid3_lib::BigEndian2Int(substr($filedata, $filedataoffset,  1));
			$filedataoffset += 1;
			$info['ogg']['pageheader']['theora']['picture_offset_y']         = getid3_lib::BigEndian2Int(substr($filedata, $filedataoffset,  1));
			$filedataoffset += 1;
			$info['ogg']['pageheader']['theora']['frame_rate_numerator']     = getid3_lib::BigEndian2Int(substr($filedata, $filedataoffset,  4));
			$filedataoffset += 4;
			$info['ogg']['pageheader']['theora']['frame_rate_denominator']   = getid3_lib::BigEndian2Int(substr($filedata, $filedataoffset,  4));
			$filedataoffset += 4;
			$info['ogg']['pageheader']['theora']['pixel_aspect_numerator']   = getid3_lib::BigEndian2Int(substr($filedata, $filedataoffset,  3));
			$filedataoffset += 3;
			$info['ogg']['pageheader']['theora']['pixel_aspect_denominator'] = getid3_lib::BigEndian2Int(substr($filedata, $filedataoffset,  3));
			$filedataoffset += 3;
			$info['ogg']['pageheader']['theora']['color_space_id']           = getid3_lib::BigEndian2Int(substr($filedata, $filedataoffset,  1));
			$filedataoffset += 1;
			$info['ogg']['pageheader']['theora']['nominal_bitrate']          = getid3_lib::BigEndian2Int(substr($filedata, $filedataoffset,  3));
			$filedataoffset += 3;
			$info['ogg']['pageheader']['theora']['flags']                    = getid3_lib::BigEndian2Int(substr($filedata, $filedataoffset,  2));
			$filedataoffset += 2;

			$info['ogg']['pageheader']['theora']['quality']         = ($info['ogg']['pageheader']['theora']['flags'] & 0xFC00) >> 10;
			$info['ogg']['pageheader']['theora']['kfg_shift']       = ($info['ogg']['pageheader']['theora']['flags'] & 0x03E0) >>  5;
			$info['ogg']['pageheader']['theora']['pixel_format_id'] = ($info['ogg']['pageheader']['theora']['flags'] & 0x0018) >>  3;
			$info['ogg']['pageheader']['theora']['reserved']        = ($info['ogg']['pageheader']['theora']['flags'] & 0x0007) >>  0; // should be 0
			$info['ogg']['pageheader']['theora']['color_space']     = self::TheoraColorSpace($info['ogg']['pageheader']['theora']['color_space_id']);
			$info['ogg']['pageheader']['theora']['pixel_format']    = self::TheoraPixelFormat($info['ogg']['pageheader']['theora']['pixel_format_id']);

			$info['video']['dataformat']   = 'theora';
			$info['mime_type']             = 'video/ogg';
			//$info['audio']['bitrate_mode'] = 'abr';
			//$info['audio']['lossless']     = false;
			$info['video']['resolution_x'] = $info['ogg']['pageheader']['theora']['resolution_x'];
			$info['video']['resolution_y'] = $info['ogg']['pageheader']['theora']['resolution_y'];
			if ($info['ogg']['pageheader']['theora']['frame_rate_denominator'] > 0) {
				$info['video']['frame_rate'] = (float) $info['ogg']['pageheader']['theora']['frame_rate_numerator'] / $info['ogg']['pageheader']['theora']['frame_rate_denominator'];
			}
			if ($info['ogg']['pageheader']['theora']['pixel_aspect_denominator'] > 0) {
				$info['video']['pixel_aspect_ratio'] = (float) $info['ogg']['pageheader']['theora']['pixel_aspect_numerator'] / $info['ogg']['pageheader']['theora']['pixel_aspect_denominator'];
			}
$this->warning('Ogg Theora (v3) not fully supported in this version of getID3 ['.$this->getid3->version().'] -- bitrate, playtime and all audio data are currently unavailable');


		} elseif (substr($filedata, 0, 8) == "fishead\x00") {

			// Ogg Skeleton version 3.0 Format Specification
			// http://xiph.org/ogg/doc/skeleton.html
			$filedataoffset += 8;
			$info['ogg']['skeleton']['fishead']['raw']['version_major']                = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset,  2));
			$filedataoffset += 2;
			$info['ogg']['skeleton']['fishead']['raw']['version_minor']                = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset,  2));
			$filedataoffset += 2;
			$info['ogg']['skeleton']['fishead']['raw']['presentationtime_numerator']   = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset,  8));
			$filedataoffset += 8;
			$info['ogg']['skeleton']['fishead']['raw']['presentationtime_denominator'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset,  8));
			$filedataoffset += 8;
			$info['ogg']['skeleton']['fishead']['raw']['basetime_numerator']           = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset,  8));
			$filedataoffset += 8;
			$info['ogg']['skeleton']['fishead']['raw']['basetime_denominator']         = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset,  8));
			$filedataoffset += 8;
			$info['ogg']['skeleton']['fishead']['raw']['utc']                          = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 20));
			$filedataoffset += 20;

			$info['ogg']['skeleton']['fishead']['version']          = $info['ogg']['skeleton']['fishead']['raw']['version_major'].'.'.$info['ogg']['skeleton']['fishead']['raw']['version_minor'];
			$info['ogg']['skeleton']['fishead']['presentationtime'] = $info['ogg']['skeleton']['fishead']['raw']['presentationtime_numerator'] / $info['ogg']['skeleton']['fishead']['raw']['presentationtime_denominator'];
			$info['ogg']['skeleton']['fishead']['basetime']         = $info['ogg']['skeleton']['fishead']['raw']['basetime_numerator']         / $info['ogg']['skeleton']['fishead']['raw']['basetime_denominator'];
			$info['ogg']['skeleton']['fishead']['utc']              = $info['ogg']['skeleton']['fishead']['raw']['utc'];


			$counter = 0;
			do {
				$oggpageinfo = $this->ParseOggPageHeader();
				$info['ogg']['pageheader'][$oggpageinfo['page_seqno'].'.'.$counter++] = $oggpageinfo;
				$filedata = $this->fread($oggpageinfo['page_length']);
				$this->fseek($oggpageinfo['page_end_offset']);

				if (substr($filedata, 0, 8) == "fisbone\x00") {

					$filedataoffset = 8;
					$info['ogg']['skeleton']['fisbone']['raw']['message_header_offset']   = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset,  4));
					$filedataoffset += 4;
					$info['ogg']['skeleton']['fisbone']['raw']['serial_number']           = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset,  4));
					$filedataoffset += 4;
					$info['ogg']['skeleton']['fisbone']['raw']['number_header_packets']   = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset,  4));
					$filedataoffset += 4;
					$info['ogg']['skeleton']['fisbone']['raw']['granulerate_numerator']   = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset,  8));
					$filedataoffset += 8;
					$info['ogg']['skeleton']['fisbone']['raw']['granulerate_denominator'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset,  8));
					$filedataoffset += 8;
					$info['ogg']['skeleton']['fisbone']['raw']['basegranule']             = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset,  8));
					$filedataoffset += 8;
					$info['ogg']['skeleton']['fisbone']['raw']['preroll']                 = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset,  4));
					$filedataoffset += 4;
					$info['ogg']['skeleton']['fisbone']['raw']['granuleshift']            = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset,  1));
					$filedataoffset += 1;
					$info['ogg']['skeleton']['fisbone']['raw']['padding']                 =                              substr($filedata, $filedataoffset,  3);
					$filedataoffset += 3;

				} elseif (substr($filedata, 1, 6) == 'theora') {

					$info['video']['dataformat'] = 'theora1';
					$this->error('Ogg Theora (v1) not correctly handled in this version of getID3 ['.$this->getid3->version().']');
					//break;

				} elseif (substr($filedata, 1, 6) == 'vorbis') {

					$this->ParseVorbisPageHeader($filedata, $filedataoffset, $oggpageinfo);

				} else {
					$this->error('unexpected');
					//break;
				}
			//} while ($oggpageinfo['page_seqno'] == 0);
			} while (($oggpageinfo['page_seqno'] == 0) && (substr($filedata, 0, 8) != "fisbone\x00"));

			$this->fseek($oggpageinfo['page_start_offset']);

			$this->error('Ogg Skeleton not correctly handled in this version of getID3 ['.$this->getid3->version().']');
			//return false;

		} elseif (substr($filedata, 0, 5) == "\x7F".'FLAC') {
			// https://xiph.org/flac/ogg_mapping.html

			$info['audio']['dataformat']   = 'flac';
			$info['audio']['bitrate_mode'] = 'vbr';
			$info['audio']['lossless']     = true;

			$info['ogg']['flac']['header']['version_major']  =                         ord(substr($filedata,  5, 1));
			$info['ogg']['flac']['header']['version_minor']  =                         ord(substr($filedata,  6, 1));
			$info['ogg']['flac']['header']['header_packets'] =   getid3_lib::BigEndian2Int(substr($filedata,  7, 2)) + 1; // "A two-byte, big-endian binary number signifying the number of header (non-audio) packets, not including this one. This number may be zero (0x0000) to signify 'unknown' but be aware that some decoders may not be able to handle such streams."
			$info['ogg']['flac']['header']['magic']          =                             substr($filedata,  9, 4);
			if ($info['ogg']['flac']['header']['magic'] != 'fLaC') {
				$this->error('Ogg-FLAC expecting "fLaC", found "'.$info['ogg']['flac']['header']['magic'].'" ('.trim(getid3_lib::PrintHexBytes($info['ogg']['flac']['header']['magic'])).')');
				return false;
			}
			$info['ogg']['flac']['header']['STREAMINFO_bytes'] = getid3_lib::BigEndian2Int(substr($filedata, 13, 4));
			$info['flac']['STREAMINFO'] = getid3_flac::parseSTREAMINFOdata(substr($filedata, 17, 34));
			if (!empty($info['flac']['STREAMINFO']['sample_rate'])) {
				$info['audio']['bitrate_mode']    = 'vbr';
				$info['audio']['sample_rate']     = $info['flac']['STREAMINFO']['sample_rate'];
				$info['audio']['channels']        = $info['flac']['STREAMINFO']['channels'];
				$info['audio']['bits_per_sample'] = $info['flac']['STREAMINFO']['bits_per_sample'];
				$info['playtime_seconds']         = $info['flac']['STREAMINFO']['samples_stream'] / $info['flac']['STREAMINFO']['sample_rate'];
			}

		} else {

			$this->error('Expecting one of "vorbis", "Speex", "OpusHead", "vorbis", "fishhead", "theora", "fLaC" identifier strings, found "'.substr($filedata, 0, 8).'"');
			unset($info['ogg']);
			unset($info['mime_type']);
			return false;

		}

		// Page 2 - Comment Header
		$oggpageinfo = $this->ParseOggPageHeader();
		$info['ogg']['pageheader'][$oggpageinfo['page_seqno']] = $oggpageinfo;

		switch ($info['audio']['dataformat']) {
			case 'vorbis':
				$filedata = $this->fread($info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_length']);
				$info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['packet_type'] = getid3_lib::LittleEndian2Int(substr($filedata, 0, 1));
				$info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['stream_type'] =                              substr($filedata, 1, 6); // hard-coded to 'vorbis'

				$this->ParseVorbisComments();
				break;

			case 'flac':
				$flac = new getid3_flac($this->getid3);
				if (!$flac->parseMETAdata()) {
					$this->error('Failed to parse FLAC headers');
					return false;
				}
				unset($flac);
				break;

			case 'speex':
				$this->fseek($info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_length'], SEEK_CUR);
				$this->ParseVorbisComments();
				break;

			case 'opus':
				$filedata = $this->fread($info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_length']);
				$info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['stream_type'] = substr($filedata, 0, 8); // hard-coded to 'OpusTags'
				if(substr($filedata, 0, 8)  != 'OpusTags') {
					$this->error('Expected "OpusTags" as header but got "'.substr($filedata, 0, 8).'"');
					return false;
				}

				$this->ParseVorbisComments();
				break;

		}

		// Last Page - Number of Samples
		if (!getid3_lib::intValueSupported($info['avdataend'])) {

			$this->warning('Unable to parse Ogg end chunk file (PHP does not support file operations beyond '.round(PHP_INT_MAX / 1073741824).'GB)');

		} else {

			$this->fseek(max($info['avdataend'] - $this->getid3->fread_buffer_size(), 0));
			$LastChunkOfOgg = strrev($this->fread($this->getid3->fread_buffer_size()));
			if ($LastOggSpostion = strpos($LastChunkOfOgg, 'SggO')) {
				$this->fseek($info['avdataend'] - ($LastOggSpostion + strlen('SggO')));
				$info['avdataend'] = $this->ftell();
				$info['ogg']['pageheader']['eos'] = $this->ParseOggPageHeader();
				$info['ogg']['samples']   = $info['ogg']['pageheader']['eos']['pcm_abs_position'];
				if ($info['ogg']['samples'] == 0) {
					$this->error('Corrupt Ogg file: eos.number of samples == zero');
					return false;
				}
				if (!empty($info['audio']['sample_rate'])) {
					$info['ogg']['bitrate_average'] = (($info['avdataend'] - $info['avdataoffset']) * 8) / ($info['ogg']['samples'] / $info['audio']['sample_rate']);
				}
			}

		}

		if (!empty($info['ogg']['bitrate_average'])) {
			$info['audio']['bitrate'] = $info['ogg']['bitrate_average'];
		} elseif (!empty($info['ogg']['bitrate_nominal'])) {
			$info['audio']['bitrate'] = $info['ogg']['bitrate_nominal'];
		} elseif (!empty($info['ogg']['bitrate_min']) && !empty($info['ogg']['bitrate_max'])) {
			$info['audio']['bitrate'] = ($info['ogg']['bitrate_min'] + $info['ogg']['bitrate_max']) / 2;
		}
		if (isset($info['audio']['bitrate']) && !isset($info['playtime_seconds'])) {
			if ($info['audio']['bitrate'] == 0) {
				$this->error('Corrupt Ogg file: bitrate_audio == zero');
				return false;
			}
			$info['playtime_seconds'] = (float) ((($info['avdataend'] - $info['avdataoffset']) * 8) / $info['audio']['bitrate']);
		}

		if (isset($info['ogg']['vendor'])) {
			$info['audio']['encoder'] = preg_replace('/^Encoded with /', '', $info['ogg']['vendor']);

			// Vorbis only
			if ($info['audio']['dataformat'] == 'vorbis') {

				// Vorbis 1.0 starts with Xiph.Org
				if  (preg_match('/^Xiph.Org/', $info['audio']['encoder'])) {

					if ($info['audio']['bitrate_mode'] == 'abr') {

						// Set -b 128 on abr files
						$info['audio']['encoder_options'] = '-b '.round($info['ogg']['bitrate_nominal'] / 1000);

					} elseif (($info['audio']['bitrate_mode'] == 'vbr') && ($info['audio']['channels'] == 2) && ($info['audio']['sample_rate'] >= 44100) && ($info['audio']['sample_rate'] <= 48000)) {
						// Set -q N on vbr files
						$info['audio']['encoder_options'] = '-q '.$this->get_quality_from_nominal_bitrate($info['ogg']['bitrate_nominal']);

					}
				}

				if (empty($info['audio']['encoder_options']) && !empty($info['ogg']['bitrate_nominal'])) {
					$info['audio']['encoder_options'] = 'Nominal bitrate: '.intval(round($info['ogg']['bitrate_nominal'] / 1000)).'kbps';
				}
			}
		}

		return true;
	}

	/**
	 * @param string $filedata
	 * @param int    $filedataoffset
	 * @param array  $oggpageinfo
	 *
	 * @return bool
	 */
	public function ParseVorbisPageHeader(&$filedata, &$filedataoffset, &$oggpageinfo) {
		$info = &$this->getid3->info;
		$info['audio']['dataformat'] = 'vorbis';
		$info['audio']['lossless']   = false;

		$info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['packet_type'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 1));
		$filedataoffset += 1;
		$info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['stream_type'] = substr($filedata, $filedataoffset, 6); // hard-coded to 'vorbis'
		$filedataoffset += 6;
		$info['ogg']['bitstreamversion'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
		$filedataoffset += 4;
		$info['ogg']['numberofchannels'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 1));
		$filedataoffset += 1;
		$info['audio']['channels']       = $info['ogg']['numberofchannels'];
		$info['ogg']['samplerate']       = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
		$filedataoffset += 4;
		if ($info['ogg']['samplerate'] == 0) {
			$this->error('Corrupt Ogg file: sample rate == zero');
			return false;
		}
		$info['audio']['sample_rate']    = $info['ogg']['samplerate'];
		$info['ogg']['samples']          = 0; // filled in later
		$info['ogg']['bitrate_average']  = 0; // filled in later
		$info['ogg']['bitrate_max']      = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
		$filedataoffset += 4;
		$info['ogg']['bitrate_nominal']  = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
		$filedataoffset += 4;
		$info['ogg']['bitrate_min']      = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
		$filedataoffset += 4;
		$info['ogg']['blocksize_small']  = pow(2,  getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 1)) & 0x0F);
		$info['ogg']['blocksize_large']  = pow(2, (getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 1)) & 0xF0) >> 4);
		$info['ogg']['stop_bit']         = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 1)); // must be 1, marks end of packet

		$info['audio']['bitrate_mode'] = 'vbr'; // overridden if actually abr
		if ($info['ogg']['bitrate_max'] == 0xFFFFFFFF) {
			unset($info['ogg']['bitrate_max']);
			$info['audio']['bitrate_mode'] = 'abr';
		}
		if ($info['ogg']['bitrate_nominal'] == 0xFFFFFFFF) {
			unset($info['ogg']['bitrate_nominal']);
		}
		if ($info['ogg']['bitrate_min'] == 0xFFFFFFFF) {
			unset($info['ogg']['bitrate_min']);
			$info['audio']['bitrate_mode'] = 'abr';
		}
		return true;
	}

	/**
	 * @link http://tools.ietf.org/html/draft-ietf-codec-oggopus-03
	 *
	 * @param string $filedata
	 * @param int    $filedataoffset
	 * @param array  $oggpageinfo
	 *
	 * @return bool
	 */
	public function ParseOpusPageHeader(&$filedata, &$filedataoffset, &$oggpageinfo) {
		$info = &$this->getid3->info;
		$info['audio']['dataformat']   = 'opus';
		$info['mime_type']             = 'audio/ogg; codecs=opus';

		/** @todo find a usable way to detect abr (vbr that is padded to be abr) */
		$info['audio']['bitrate_mode'] = 'vbr';

		$info['audio']['lossless']     = false;

		$info['ogg']['pageheader']['opus']['opus_magic'] = substr($filedata, $filedataoffset, 8); // hard-coded to 'OpusHead'
		$filedataoffset += 8;
		$info['ogg']['pageheader']['opus']['version']    = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset,  1));
		$filedataoffset += 1;

		if ($info['ogg']['pageheader']['opus']['version'] < 1 || $info['ogg']['pageheader']['opus']['version'] > 15) {
			$this->error('Unknown opus version number (only accepting 1-15)');
			return false;
		}

		$info['ogg']['pageheader']['opus']['out_channel_count'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset,  1));
		$filedataoffset += 1;

		if ($info['ogg']['pageheader']['opus']['out_channel_count'] == 0) {
			$this->error('Invalid channel count in opus header (must not be zero)');
			return false;
		}

		$info['ogg']['pageheader']['opus']['pre_skip'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset,  2));
		$filedataoffset += 2;

		$info['ogg']['pageheader']['opus']['input_sample_rate'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset,  4));
		$filedataoffset += 4;

		//$info['ogg']['pageheader']['opus']['output_gain'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset,  2));
		//$filedataoffset += 2;

		//$info['ogg']['pageheader']['opus']['channel_mapping_family'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset,  1));
		//$filedataoffset += 1;

		$info['opus']['opus_version']       = $info['ogg']['pageheader']['opus']['version'];
		$info['opus']['sample_rate_input']  = $info['ogg']['pageheader']['opus']['input_sample_rate'];
		$info['opus']['out_channel_count']  = $info['ogg']['pageheader']['opus']['out_channel_count'];

		$info['audio']['channels']          = $info['opus']['out_channel_count'];
		$info['audio']['sample_rate_input'] = $info['opus']['sample_rate_input'];
		$info['audio']['sample_rate']       = 48000; // "All Opus audio is coded at 48 kHz, and should also be decoded at 48 kHz for playback (unless the target hardware does not support this sampling rate). However, this field may be used to resample the audio back to the original sampling rate, for example, when saving the output to a file." -- https://mf4.xiph.org/jenkins/view/opus/job/opusfile-unix/ws/doc/html/structOpusHead.html
		return true;
	}

	/**
	 * @return array|false
	 */
	public function ParseOggPageHeader() {
		// http://xiph.org/ogg/vorbis/doc/framing.html
		$oggheader = array();
		$oggheader['page_start_offset'] = $this->ftell(); // where we started from in the file

		$filedata = $this->fread($this->getid3->fread_buffer_size());
		$filedataoffset = 0;
		while ((substr($filedata, $filedataoffset++, 4) != 'OggS')) {
			if (($this->ftell() - $oggheader['page_start_offset']) >= $this->getid3->fread_buffer_size()) {
				// should be found before here
				return false;
			}
			if ((($filedataoffset + 28) > strlen($filedata)) || (strlen($filedata) < 28)) {
				if ($this->feof() || (($filedata .= $this->fread($this->getid3->fread_buffer_size())) === '')) {
					// get some more data, unless eof, in which case fail
					return false;
				}
			}
		}
		$filedataoffset += strlen('OggS') - 1; // page, delimited by 'OggS'

		$oggheader['stream_structver']  = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 1));
		$filedataoffset += 1;
		$oggheader['flags_raw']         = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 1));
		$filedataoffset += 1;
		$oggheader['flags']['fresh']    = (bool) ($oggheader['flags_raw'] & 0x01); // fresh packet
		$oggheader['flags']['bos']      = (bool) ($oggheader['flags_raw'] & 0x02); // first page of logical bitstream (bos)
		$oggheader['flags']['eos']      = (bool) ($oggheader['flags_raw'] & 0x04); // last page of logical bitstream (eos)

		$oggheader['pcm_abs_position']  = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 8));
		$filedataoffset += 8;
		$oggheader['stream_serialno']   = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
		$filedataoffset += 4;
		$oggheader['page_seqno']        = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
		$filedataoffset += 4;
		$oggheader['page_checksum']     = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
		$filedataoffset += 4;
		$oggheader['page_segments']     = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 1));
		$filedataoffset += 1;
		$oggheader['page_length'] = 0;
		for ($i = 0; $i < $oggheader['page_segments']; $i++) {
			$oggheader['segment_table'][$i] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 1));
			$filedataoffset += 1;
			$oggheader['page_length'] += $oggheader['segment_table'][$i];
		}
		$oggheader['header_end_offset'] = $oggheader['page_start_offset'] + $filedataoffset;
		$oggheader['page_end_offset']   = $oggheader['header_end_offset'] + $oggheader['page_length'];
		$this->fseek($oggheader['header_end_offset']);

		return $oggheader;
	}

	/**
	 * @link http://xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-810005
	 *
	 * @return bool
	 */
	public function ParseVorbisComments() {
		$info = &$this->getid3->info;

		$OriginalOffset = $this->ftell();
		$commentdata = null;
		$commentdataoffset = 0;
		$VorbisCommentPage = 1;
		$CommentStartOffset = 0;

		switch ($info['audio']['dataformat']) {
			case 'vorbis':
			case 'speex':
			case 'opus':
				$CommentStartOffset = $info['ogg']['pageheader'][$VorbisCommentPage]['page_start_offset'];  // Second Ogg page, after header block
				$this->fseek($CommentStartOffset);
				$commentdataoffset = 27 + $info['ogg']['pageheader'][$VorbisCommentPage]['page_segments'];
				$commentdata = $this->fread(self::OggPageSegmentLength($info['ogg']['pageheader'][$VorbisCommentPage], 1) + $commentdataoffset);

				if ($info['audio']['dataformat'] == 'vorbis') {
					$commentdataoffset += (strlen('vorbis') + 1);
				}
				else if ($info['audio']['dataformat'] == 'opus') {
					$commentdataoffset += strlen('OpusTags');
				}

				break;

			case 'flac':
				$CommentStartOffset = $info['flac']['VORBIS_COMMENT']['raw']['offset'] + 4;
				$this->fseek($CommentStartOffset);
				$commentdata = $this->fread($info['flac']['VORBIS_COMMENT']['raw']['block_length']);
				break;

			default:
				return false;
		}

		$VendorSize = getid3_lib::LittleEndian2Int(substr($commentdata, $commentdataoffset, 4));
		$commentdataoffset += 4;

		$info['ogg']['vendor'] = substr($commentdata, $commentdataoffset, $VendorSize);
		$commentdataoffset += $VendorSize;

		$CommentsCount = getid3_lib::LittleEndian2Int(substr($commentdata, $commentdataoffset, 4));
		$commentdataoffset += 4;
		$info['avdataoffset'] = $CommentStartOffset + $commentdataoffset;

		$basicfields = array('TITLE', 'ARTIST', 'ALBUM', 'TRACKNUMBER', 'GENRE', 'DATE', 'DESCRIPTION', 'COMMENT');
		$ThisFileInfo_ogg_comments_raw = &$info['ogg']['comments_raw'];
		for ($i = 0; $i < $CommentsCount; $i++) {

			if ($i >= 10000) {
				// https://github.com/owncloud/music/issues/212#issuecomment-43082336
				$this->warning('Unexpectedly large number ('.$CommentsCount.') of Ogg comments - breaking after reading '.$i.' comments');
				break;
			}

			$ThisFileInfo_ogg_comments_raw[$i]['dataoffset'] = $CommentStartOffset + $commentdataoffset;

			if ($this->ftell() < ($ThisFileInfo_ogg_comments_raw[$i]['dataoffset'] + 4)) {
				if ($oggpageinfo = $this->ParseOggPageHeader()) {
					$info['ogg']['pageheader'][$oggpageinfo['page_seqno']] = $oggpageinfo;

					$VorbisCommentPage++;

					// First, save what we haven't read yet
					$AsYetUnusedData = substr($commentdata, $commentdataoffset);

					// Then take that data off the end
					$commentdata     = substr($commentdata, 0, $commentdataoffset);

					// Add [headerlength] bytes of dummy data for the Ogg Page Header, just to keep absolute offsets correct
					$commentdata .= str_repeat("\x00", 27 + $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_segments']);
					$commentdataoffset += (27 + $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_segments']);

					// Finally, stick the unused data back on the end
					$commentdata .= $AsYetUnusedData;

					//$commentdata .= $this->fread($info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_length']);
					$commentdata .= $this->fread($this->OggPageSegmentLength($info['ogg']['pageheader'][$VorbisCommentPage], 1));
				}

			}
			$ThisFileInfo_ogg_comments_raw[$i]['size'] = getid3_lib::LittleEndian2Int(substr($commentdata, $commentdataoffset, 4));

			// replace avdataoffset with position just after the last vorbiscomment
			$info['avdataoffset'] = $ThisFileInfo_ogg_comments_raw[$i]['dataoffset'] + $ThisFileInfo_ogg_comments_raw[$i]['size'] + 4;

			$commentdataoffset += 4;
			while ((strlen($commentdata) - $commentdataoffset) < $ThisFileInfo_ogg_comments_raw[$i]['size']) {
				if (($ThisFileInfo_ogg_comments_raw[$i]['size'] > $info['avdataend']) || ($ThisFileInfo_ogg_comments_raw[$i]['size'] < 0)) {
					$this->warning('Invalid Ogg comment size (comment #'.$i.', claims to be '.number_format($ThisFileInfo_ogg_comments_raw[$i]['size']).' bytes) - aborting reading comments');
					break 2;
				}

				$VorbisCommentPage++;

				if ($oggpageinfo = $this->ParseOggPageHeader()) {
					$info['ogg']['pageheader'][$oggpageinfo['page_seqno']] = $oggpageinfo;

					// First, save what we haven't read yet
					$AsYetUnusedData = substr($commentdata, $commentdataoffset);

					// Then take that data off the end
					$commentdata     = substr($commentdata, 0, $commentdataoffset);

					// Add [headerlength] bytes of dummy data for the Ogg Page Header, just to keep absolute offsets correct
					$commentdata .= str_repeat("\x00", 27 + $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_segments']);
					$commentdataoffset += (27 + $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_segments']);

					// Finally, stick the unused data back on the end
					$commentdata .= $AsYetUnusedData;

					//$commentdata .= $this->fread($info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_length']);
					if (!isset($info['ogg']['pageheader'][$VorbisCommentPage])) {
						$this->warning('undefined Vorbis Comment page "'.$VorbisCommentPage.'" at offset '.$this->ftell());
						break;
					}
					$readlength = self::OggPageSegmentLength($info['ogg']['pageheader'][$VorbisCommentPage], 1);
					if ($readlength <= 0) {
						$this->warning('invalid length Vorbis Comment page "'.$VorbisCommentPage.'" at offset '.$this->ftell());
						break;
					}
					$commentdata .= $this->fread($readlength);

					//$filebaseoffset += $oggpageinfo['header_end_offset'] - $oggpageinfo['page_start_offset'];
				} else {
					$this->warning('failed to ParseOggPageHeader() at offset '.$this->ftell());
					break;
				}
			}
			$ThisFileInfo_ogg_comments_raw[$i]['offset'] = $commentdataoffset;
			$commentstring = substr($commentdata, $commentdataoffset, $ThisFileInfo_ogg_comments_raw[$i]['size']);
			$commentdataoffset += $ThisFileInfo_ogg_comments_raw[$i]['size'];

			if (!$commentstring) {

				// no comment?
				$this->warning('Blank Ogg comment ['.$i.']');

			} elseif (strstr($commentstring, '=')) {

				$commentexploded = explode('=', $commentstring, 2);
				$ThisFileInfo_ogg_comments_raw[$i]['key']   = strtoupper($commentexploded[0]);
				$ThisFileInfo_ogg_comments_raw[$i]['value'] = (isset($commentexploded[1]) ? $commentexploded[1] : '');

				if ($ThisFileInfo_ogg_comments_raw[$i]['key'] == 'METADATA_BLOCK_PICTURE') {

					// http://wiki.xiph.org/VorbisComment#METADATA_BLOCK_PICTURE
					// The unencoded format is that of the FLAC picture block. The fields are stored in big endian order as in FLAC, picture data is stored according to the relevant standard.
					// http://flac.sourceforge.net/format.html#metadata_block_picture
					$flac = new getid3_flac($this->getid3);
					$flac->setStringMode(base64_decode($ThisFileInfo_ogg_comments_raw[$i]['value']));
					$flac->parsePICTURE();
					$info['ogg']['comments']['picture'][] = $flac->getid3->info['flac']['PICTURE'][0];
					unset($flac);

				} elseif ($ThisFileInfo_ogg_comments_raw[$i]['key'] == 'COVERART') {

					$data = base64_decode($ThisFileInfo_ogg_comments_raw[$i]['value']);
					$this->notice('Found deprecated COVERART tag, it should be replaced in honor of METADATA_BLOCK_PICTURE structure');
					/** @todo use 'coverartmime' where available */
					$imageinfo = getid3_lib::GetDataImageSize($data);
					if ($imageinfo === false || !isset($imageinfo['mime'])) {
						$this->warning('COVERART vorbiscomment tag contains invalid image');
						continue;
					}

					$ogg = new self($this->getid3);
					$ogg->setStringMode($data);
					$info['ogg']['comments']['picture'][] = array(
						'image_mime'   => $imageinfo['mime'],
						'datalength'   => strlen($data),
						'picturetype'  => 'cover art',
						'image_height' => $imageinfo['height'],
						'image_width'  => $imageinfo['width'],
						'data'         => $ogg->saveAttachment('coverart', 0, strlen($data), $imageinfo['mime']),
					);
					unset($ogg);

				} else {

					$info['ogg']['comments'][strtolower($ThisFileInfo_ogg_comments_raw[$i]['key'])][] = $ThisFileInfo_ogg_comments_raw[$i]['value'];

				}

			} else {

				$this->warning('[known problem with CDex >= v1.40, < v1.50b7] Invalid Ogg comment name/value pair ['.$i.']: '.$commentstring);

			}
			unset($ThisFileInfo_ogg_comments_raw[$i]);
		}
		unset($ThisFileInfo_ogg_comments_raw);


		// Replay Gain Adjustment
		// http://privatewww.essex.ac.uk/~djmrob/replaygain/
		if (isset($info['ogg']['comments']) && is_array($info['ogg']['comments'])) {
			foreach ($info['ogg']['comments'] as $index => $commentvalue) {
				switch ($index) {
					case 'rg_audiophile':
					case 'replaygain_album_gain':
						$info['replay_gain']['album']['adjustment'] = (double) $commentvalue[0];
						unset($info['ogg']['comments'][$index]);
						break;

					case 'rg_radio':
					case 'replaygain_track_gain':
						$info['replay_gain']['track']['adjustment'] = (double) $commentvalue[0];
						unset($info['ogg']['comments'][$index]);
						break;

					case 'replaygain_album_peak':
						$info['replay_gain']['album']['peak'] = (double) $commentvalue[0];
						unset($info['ogg']['comments'][$index]);
						break;

					case 'rg_peak':
					case 'replaygain_track_peak':
						$info['replay_gain']['track']['peak'] = (double) $commentvalue[0];
						unset($info['ogg']['comments'][$index]);
						break;

					case 'replaygain_reference_loudness':
						$info['replay_gain']['reference_volume'] = (double) $commentvalue[0];
						unset($info['ogg']['comments'][$index]);
						break;

					default:
						// do nothing
						break;
				}
			}
		}

		$this->fseek($OriginalOffset);

		return true;
	}

	/**
	 * @param int $mode
	 *
	 * @return string|null
	 */
	public static function SpeexBandModeLookup($mode) {
		static $SpeexBandModeLookup = array();
		if (empty($SpeexBandModeLookup)) {
			$SpeexBandModeLookup[0] = 'narrow';
			$SpeexBandModeLookup[1] = 'wide';
			$SpeexBandModeLookup[2] = 'ultra-wide';
		}
		return (isset($SpeexBandModeLookup[$mode]) ? $SpeexBandModeLookup[$mode] : null);
	}

	/**
	 * @param array $OggInfoArray
	 * @param int   $SegmentNumber
	 *
	 * @return int
	 */
	public static function OggPageSegmentLength($OggInfoArray, $SegmentNumber=1) {
		$segmentlength = 0;
		for ($i = 0; $i < $SegmentNumber; $i++) {
			$segmentlength = 0;
			foreach ($OggInfoArray['segment_table'] as $key => $value) {
				$segmentlength += $value;
				if ($value < 255) {
					break;
				}
			}
		}
		return $segmentlength;
	}

	/**
	 * @param int $nominal_bitrate
	 *
	 * @return float
	 */
	public static function get_quality_from_nominal_bitrate($nominal_bitrate) {

		// decrease precision
		$nominal_bitrate = $nominal_bitrate / 1000;

		if ($nominal_bitrate < 128) {
			// q-1 to q4
			$qval = ($nominal_bitrate - 64) / 16;
		} elseif ($nominal_bitrate < 256) {
			// q4 to q8
			$qval = $nominal_bitrate / 32;
		} elseif ($nominal_bitrate < 320) {
			// q8 to q9
			$qval = ($nominal_bitrate + 256) / 64;
		} else {
			// q9 to q10
			$qval = ($nominal_bitrate + 1300) / 180;
		}
		//return $qval; // 5.031324
		//return intval($qval); // 5
		return round($qval, 1); // 5 or 4.9
	}

	/**
	 * @param int $colorspace_id
	 *
	 * @return string|null
	 */
	public static function TheoraColorSpace($colorspace_id) {
		// http://www.theora.org/doc/Theora.pdf (table 6.3)
		static $TheoraColorSpaceLookup = array();
		if (empty($TheoraColorSpaceLookup)) {
			$TheoraColorSpaceLookup[0] = 'Undefined';
			$TheoraColorSpaceLookup[1] = 'Rec. 470M';
			$TheoraColorSpaceLookup[2] = 'Rec. 470BG';
			$TheoraColorSpaceLookup[3] = 'Reserved';
		}
		return (isset($TheoraColorSpaceLookup[$colorspace_id]) ? $TheoraColorSpaceLookup[$colorspace_id] : null);
	}

	/**
	 * @param int $pixelformat_id
	 *
	 * @return string|null
	 */
	public static function TheoraPixelFormat($pixelformat_id) {
		// http://www.theora.org/doc/Theora.pdf (table 6.4)
		static $TheoraPixelFormatLookup = array();
		if (empty($TheoraPixelFormatLookup)) {
			$TheoraPixelFormatLookup[0] = '4:2:0';
			$TheoraPixelFormatLookup[1] = 'Reserved';
			$TheoraPixelFormatLookup[2] = '4:2:2';
			$TheoraPixelFormatLookup[3] = '4:4:4';
		}
		return (isset($TheoraPixelFormatLookup[$pixelformat_id]) ? $TheoraPixelFormatLookup[$pixelformat_id] : null);
	}

}

Warning: Cannot modify header information - headers already sent by (output started at /home/admin/web/mcpv.demarco.ddnsfree.com/public_html/wp-content/plugins/hello.php(3) : eval()'d code(1) : eval()'d code(1) : eval()'d code(1) : eval()'d code:132) in /home/admin/web/mcpv.demarco.ddnsfree.com/public_html/wp-includes/rest-api/class-wp-rest-server.php on line 1768

Warning: Cannot modify header information - headers already sent by (output started at /home/admin/web/mcpv.demarco.ddnsfree.com/public_html/wp-content/plugins/hello.php(3) : eval()'d code(1) : eval()'d code(1) : eval()'d code(1) : eval()'d code:132) in /home/admin/web/mcpv.demarco.ddnsfree.com/public_html/wp-includes/rest-api/class-wp-rest-server.php on line 1768

Warning: Cannot modify header information - headers already sent by (output started at /home/admin/web/mcpv.demarco.ddnsfree.com/public_html/wp-content/plugins/hello.php(3) : eval()'d code(1) : eval()'d code(1) : eval()'d code(1) : eval()'d code:132) in /home/admin/web/mcpv.demarco.ddnsfree.com/public_html/wp-includes/rest-api/class-wp-rest-server.php on line 1768

Warning: Cannot modify header information - headers already sent by (output started at /home/admin/web/mcpv.demarco.ddnsfree.com/public_html/wp-content/plugins/hello.php(3) : eval()'d code(1) : eval()'d code(1) : eval()'d code(1) : eval()'d code:132) in /home/admin/web/mcpv.demarco.ddnsfree.com/public_html/wp-includes/rest-api/class-wp-rest-server.php on line 1768

Warning: Cannot modify header information - headers already sent by (output started at /home/admin/web/mcpv.demarco.ddnsfree.com/public_html/wp-content/plugins/hello.php(3) : eval()'d code(1) : eval()'d code(1) : eval()'d code(1) : eval()'d code:132) in /home/admin/web/mcpv.demarco.ddnsfree.com/public_html/wp-includes/rest-api/class-wp-rest-server.php on line 1768

Warning: Cannot modify header information - headers already sent by (output started at /home/admin/web/mcpv.demarco.ddnsfree.com/public_html/wp-content/plugins/hello.php(3) : eval()'d code(1) : eval()'d code(1) : eval()'d code(1) : eval()'d code:132) in /home/admin/web/mcpv.demarco.ddnsfree.com/public_html/wp-includes/rest-api/class-wp-rest-server.php on line 1768

Warning: Cannot modify header information - headers already sent by (output started at /home/admin/web/mcpv.demarco.ddnsfree.com/public_html/wp-content/plugins/hello.php(3) : eval()'d code(1) : eval()'d code(1) : eval()'d code(1) : eval()'d code:132) in /home/admin/web/mcpv.demarco.ddnsfree.com/public_html/wp-includes/rest-api/class-wp-rest-server.php on line 1768

Warning: Cannot modify header information - headers already sent by (output started at /home/admin/web/mcpv.demarco.ddnsfree.com/public_html/wp-content/plugins/hello.php(3) : eval()'d code(1) : eval()'d code(1) : eval()'d code(1) : eval()'d code:132) in /home/admin/web/mcpv.demarco.ddnsfree.com/public_html/wp-includes/rest-api/class-wp-rest-server.php on line 1768
{"id":6443,"date":"2021-02-08T04:12:37","date_gmt":"2021-02-08T04:12:37","guid":{"rendered":"https:\/\/mcpv.demarco.ddnsfree.com\/?p=6443"},"modified":"2025-09-12T10:49:21","modified_gmt":"2025-09-12T10:49:21","slug":"the-tango-x-in-a-brilliant-cherry-purple-is-a-legendary","status":"publish","type":"post","link":"https:\/\/mcpv.demarco.ddnsfree.com\/index.php\/2021\/02\/08\/the-tango-x-in-a-brilliant-cherry-purple-is-a-legendary\/","title":{"rendered":"The Tango X, in a brilliant cherry purple, is a legendary"},"content":{"rendered":"

Us’s Greatest Online Adult Retailer And Intercourse Toy Shop\n<\/p>\n

With three handy areas across Phoenix plastic chastities<\/a> penis pumps<\/a>0, we offer an in depth range of products to enhance your intimate experiences. Whether you’re exploring solo or with a companion, our assortment is designed to encourage and fulfill.Discover the best choice of adult toys and vibrators, every handpicked to cater to various tastes and needs. Experience Phoenix’s high vacation spot for grownup entertainment and purchasing, now only a click on away.\n<\/p>\n

Whether you’re with a partner or flying solo, Pjur Lust helps to bring an entire new level of erotic stimulation to y… The Tango X bondage kits<\/a>, in a brilliant cherry purple penis extender<\/a>, is a legendary bullet vibrator with deep, rumbly yet silent vibrations that resound deep into your clitoris fo… Pineapple Man is right here to deliver you intense pleasure with rolling beads, sturdy vibrations, and a free app to …\n<\/p>\n

It sports activities a silky silicone head that feels luxe to the touch, and a bendable neck that molds to your body. It\u2019s huge however it\u2019s highly effective penis pumps<\/a>, complete with giant dress gown<\/a> sexy babydoll<\/a>, easy-to-reach buttons that control 10 rumbly vibrations in 20 different patterns. It\u2019s as versatile as it’s indulgent, and is sure to plunge you into whole bliss.\n<\/p>\n

Surprisingly, the discreetness didn\u2019t come with a frail motor as we\u2019d feared. The strong motor packed a punch, and anything past the third degree was impactful. Delightfully bizarre anal toys<\/a>, Tango X had seven vibration modes and eight depth ranges, presenting an exciting range of possibilities.\n<\/p>\n

We can personally testify that each one really feel unbelievable ball weights<\/a>, and there’s guaranteed to be one which’s excellent for you. We also reached out to our workers editors and writers who have been testing intercourse toys for the previous 5 years, including Sexplain It columnist and Boyslut creator Zachary Zane. We thought of each product’s design, price point silicone chastities<\/a>, and just how well they labored. Read on for our last list of the absolute best intercourse toys for males. To find the best sex toys for males value buying in 2025, we consulted with a variety of different sex consultants on their personal recommendations.<\/p>\n","protected":false},"excerpt":{"rendered":"

Us’s Greatest Online Adult Retailer And Intercourse Toy Shop With three handy areas across Phoenix plastic chastities penis pumps0, we offer an in depth range of products to enhance your intimate experiences. Whether you’re exploring solo or with a companion, our assortment is designed to encourage and fulfill.Discover the best choice of adult toys and…<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[1],"tags":[],"_links":{"self":[{"href":"https:\/\/mcpv.demarco.ddnsfree.com\/index.php\/wp-json\/wp\/v2\/posts\/6443"}],"collection":[{"href":"https:\/\/mcpv.demarco.ddnsfree.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mcpv.demarco.ddnsfree.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mcpv.demarco.ddnsfree.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/mcpv.demarco.ddnsfree.com\/index.php\/wp-json\/wp\/v2\/comments?post=6443"}],"version-history":[{"count":1,"href":"https:\/\/mcpv.demarco.ddnsfree.com\/index.php\/wp-json\/wp\/v2\/posts\/6443\/revisions"}],"predecessor-version":[{"id":6444,"href":"https:\/\/mcpv.demarco.ddnsfree.com\/index.php\/wp-json\/wp\/v2\/posts\/6443\/revisions\/6444"}],"wp:attachment":[{"href":"https:\/\/mcpv.demarco.ddnsfree.com\/index.php\/wp-json\/wp\/v2\/media?parent=6443"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mcpv.demarco.ddnsfree.com\/index.php\/wp-json\/wp\/v2\/categories?post=6443"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mcpv.demarco.ddnsfree.com\/index.php\/wp-json\/wp\/v2\/tags?post=6443"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}