23 $info = &$this->getid3->info;
25 $info[
'fileformat'] =
'ogg';
28 if (isset(
$info[
'id3v2'])) {
29 $this->
warning(
'Illegal ID3v2 tag present.');
31 if (isset(
$info[
'id3v1'])) {
32 $this->
warning(
'Illegal ID3v1 tag present.');
34 if (isset(
$info[
'ape'])) {
35 $this->
warning(
'Illegal APE tag present.');
44 $info[
'ogg'][
'pageheader'][$oggpageinfo[
'page_seqno']] = $oggpageinfo;
46 if ($this->
ftell() >= $this->getid3->fread_buffer_size()) {
47 $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?)');
48 unset(
$info[
'fileformat']);
53 $filedata = $this->
fread($oggpageinfo[
'page_length']);
56 if (substr($filedata, 0, 4) ==
'fLaC') {
58 $info[
'audio'][
'dataformat'] =
'flac';
59 $info[
'audio'][
'bitrate_mode'] =
'vbr';
60 $info[
'audio'][
'lossless'] =
true;
62 } elseif (substr($filedata, 1, 6) ==
'vorbis') {
66 } elseif (substr($filedata, 0, 8) ==
'OpusHead') {
72 } elseif (substr($filedata, 0, 8) ==
'Speex ') {
76 $info[
'audio'][
'dataformat'] =
'speex';
77 $info[
'mime_type'] =
'audio/speex';
78 $info[
'audio'][
'bitrate_mode'] =
'abr';
79 $info[
'audio'][
'lossless'] =
false;
81 $info[
'ogg'][
'pageheader'][$oggpageinfo[
'page_seqno']][
'speex_string'] = substr($filedata, $filedataoffset, 8);
83 $info[
'ogg'][
'pageheader'][$oggpageinfo[
'page_seqno']][
'speex_version'] = substr($filedata, $filedataoffset, 20);
84 $filedataoffset += 20;
100 $filedataoffset += 4;
102 $filedataoffset += 4;
104 $filedataoffset += 4;
106 $filedataoffset += 4;
108 $filedataoffset += 4;
110 $filedataoffset += 4;
112 $info[
'speex'][
'speex_version'] = trim(
$info[
'ogg'][
'pageheader'][$oggpageinfo[
'page_seqno']][
'speex_version']);
113 $info[
'speex'][
'sample_rate'] =
$info[
'ogg'][
'pageheader'][$oggpageinfo[
'page_seqno']][
'rate'];
114 $info[
'speex'][
'channels'] =
$info[
'ogg'][
'pageheader'][$oggpageinfo[
'page_seqno']][
'nb_channels'];
115 $info[
'speex'][
'vbr'] = (bool)
$info[
'ogg'][
'pageheader'][$oggpageinfo[
'page_seqno']][
'vbr'];
118 $info[
'audio'][
'sample_rate'] =
$info[
'speex'][
'sample_rate'];
119 $info[
'audio'][
'channels'] =
$info[
'speex'][
'channels'];
120 if (
$info[
'speex'][
'vbr']) {
121 $info[
'audio'][
'bitrate_mode'] =
'vbr';
124 } elseif (substr($filedata, 0, 7) ==
"\x80".
'theora') {
128 $info[
'ogg'][
'pageheader'][
'theora'][
'theora_magic'] = substr($filedata, $filedataoffset, 7);
129 $filedataoffset += 7;
131 $filedataoffset += 1;
133 $filedataoffset += 1;
135 $filedataoffset += 1;
137 $filedataoffset += 2;
139 $filedataoffset += 2;
141 $filedataoffset += 3;
143 $filedataoffset += 3;
145 $filedataoffset += 1;
147 $filedataoffset += 1;
149 $filedataoffset += 4;
151 $filedataoffset += 4;
153 $filedataoffset += 3;
155 $filedataoffset += 3;
157 $filedataoffset += 1;
159 $filedataoffset += 3;
161 $filedataoffset += 2;
163 $info[
'ogg'][
'pageheader'][
'theora'][
'quality'] = (
$info[
'ogg'][
'pageheader'][
'theora'][
'flags'] & 0xFC00) >> 10;
164 $info[
'ogg'][
'pageheader'][
'theora'][
'kfg_shift'] = (
$info[
'ogg'][
'pageheader'][
'theora'][
'flags'] & 0x03E0) >> 5;
165 $info[
'ogg'][
'pageheader'][
'theora'][
'pixel_format_id'] = (
$info[
'ogg'][
'pageheader'][
'theora'][
'flags'] & 0x0018) >> 3;
166 $info[
'ogg'][
'pageheader'][
'theora'][
'reserved'] = (
$info[
'ogg'][
'pageheader'][
'theora'][
'flags'] & 0x0007) >> 0;
167 $info[
'ogg'][
'pageheader'][
'theora'][
'color_space'] = self::TheoraColorSpace(
$info[
'ogg'][
'pageheader'][
'theora'][
'color_space_id']);
168 $info[
'ogg'][
'pageheader'][
'theora'][
'pixel_format'] = self::TheoraPixelFormat(
$info[
'ogg'][
'pageheader'][
'theora'][
'pixel_format_id']);
170 $info[
'video'][
'dataformat'] =
'theora';
171 $info[
'mime_type'] =
'video/ogg';
174 $info[
'video'][
'resolution_x'] =
$info[
'ogg'][
'pageheader'][
'theora'][
'resolution_x'];
175 $info[
'video'][
'resolution_y'] =
$info[
'ogg'][
'pageheader'][
'theora'][
'resolution_y'];
176 if (
$info[
'ogg'][
'pageheader'][
'theora'][
'frame_rate_denominator'] > 0) {
177 $info[
'video'][
'frame_rate'] = (float)
$info[
'ogg'][
'pageheader'][
'theora'][
'frame_rate_numerator'] /
$info[
'ogg'][
'pageheader'][
'theora'][
'frame_rate_denominator'];
179 if (
$info[
'ogg'][
'pageheader'][
'theora'][
'pixel_aspect_denominator'] > 0) {
180 $info[
'video'][
'pixel_aspect_ratio'] = (float)
$info[
'ogg'][
'pageheader'][
'theora'][
'pixel_aspect_numerator'] /
$info[
'ogg'][
'pageheader'][
'theora'][
'pixel_aspect_denominator'];
182 $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');
185 } elseif (substr($filedata, 0, 8) ==
"fishead\x00") {
189 $filedataoffset += 8;
191 $filedataoffset += 2;
193 $filedataoffset += 2;
195 $filedataoffset += 8;
197 $filedataoffset += 8;
199 $filedataoffset += 8;
201 $filedataoffset += 8;
203 $filedataoffset += 20;
205 $info[
'ogg'][
'skeleton'][
'fishead'][
'version'] =
$info[
'ogg'][
'skeleton'][
'fishead'][
'raw'][
'version_major'].
'.'.
$info[
'ogg'][
'skeleton'][
'fishead'][
'raw'][
'version_minor'];
206 $info[
'ogg'][
'skeleton'][
'fishead'][
'presentationtime'] =
$info[
'ogg'][
'skeleton'][
'fishead'][
'raw'][
'presentationtime_numerator'] /
$info[
'ogg'][
'skeleton'][
'fishead'][
'raw'][
'presentationtime_denominator'];
207 $info[
'ogg'][
'skeleton'][
'fishead'][
'basetime'] =
$info[
'ogg'][
'skeleton'][
'fishead'][
'raw'][
'basetime_numerator'] /
$info[
'ogg'][
'skeleton'][
'fishead'][
'raw'][
'basetime_denominator'];
208 $info[
'ogg'][
'skeleton'][
'fishead'][
'utc'] =
$info[
'ogg'][
'skeleton'][
'fishead'][
'raw'][
'utc'];
214 $info[
'ogg'][
'pageheader'][$oggpageinfo[
'page_seqno'].
'.'.
$counter++] = $oggpageinfo;
215 $filedata = $this->
fread($oggpageinfo[
'page_length']);
216 $this->
fseek($oggpageinfo[
'page_end_offset']);
218 if (substr($filedata, 0, 8) ==
"fisbone\x00") {
222 $filedataoffset += 4;
224 $filedataoffset += 4;
226 $filedataoffset += 4;
228 $filedataoffset += 8;
230 $filedataoffset += 8;
232 $filedataoffset += 8;
234 $filedataoffset += 4;
236 $filedataoffset += 1;
237 $info[
'ogg'][
'skeleton'][
'fisbone'][
'raw'][
'padding'] = substr($filedata, $filedataoffset, 3);
238 $filedataoffset += 3;
240 } elseif (substr($filedata, 1, 6) ==
'theora') {
242 $info[
'video'][
'dataformat'] =
'theora1';
243 $this->
error(
'Ogg Theora (v1) not correctly handled in this version of getID3 ['.$this->getid3->version().
']');
246 } elseif (substr($filedata, 1, 6) ==
'vorbis') {
251 $this->
error(
'unexpected');
255 }
while (($oggpageinfo[
'page_seqno'] == 0) && (substr($filedata, 0, 8) !=
"fisbone\x00"));
257 $this->
fseek($oggpageinfo[
'page_start_offset']);
259 $this->
error(
'Ogg Skeleton not correctly handled in this version of getID3 ['.$this->getid3->version().
']');
264 $this->
error(
'Expecting either "Speex ", "OpusHead" or "vorbis" identifier strings, found "'.substr($filedata, 0, 8).
'"');
266 unset(
$info[
'mime_type']);
273 $info[
'ogg'][
'pageheader'][$oggpageinfo[
'page_seqno']] = $oggpageinfo;
275 switch (
$info[
'audio'][
'dataformat']) {
277 $filedata = $this->
fread(
$info[
'ogg'][
'pageheader'][$oggpageinfo[
'page_seqno']][
'page_length']);
279 $info[
'ogg'][
'pageheader'][$oggpageinfo[
'page_seqno']][
'stream_type'] = substr($filedata, 1, 6);
286 if (!$flac->parseMETAdata()) {
287 $this->
error(
'Failed to parse FLAC headers');
294 $this->
fseek(
$info[
'ogg'][
'pageheader'][$oggpageinfo[
'page_seqno']][
'page_length'], SEEK_CUR);
299 $filedata = $this->
fread(
$info[
'ogg'][
'pageheader'][$oggpageinfo[
'page_seqno']][
'page_length']);
300 $info[
'ogg'][
'pageheader'][$oggpageinfo[
'page_seqno']][
'stream_type'] = substr($filedata, 0, 8);
301 if(substr($filedata, 0, 8) !=
'OpusTags') {
302 $this->
error(
'Expected "OpusTags" as header but got "'.substr($filedata, 0, 8).
'"');
314 $this->
warning(
'Unable to parse Ogg end chunk file (PHP does not support file operations beyond '.round(PHP_INT_MAX / 1073741824).
'GB)');
318 $this->
fseek(max(
$info[
'avdataend'] - $this->getid3->fread_buffer_size(), 0));
319 $LastChunkOfOgg = strrev($this->
fread($this->getid3->fread_buffer_size()));
320 if ($LastOggSpostion = strpos($LastChunkOfOgg,
'SggO')) {
321 $this->
fseek(
$info[
'avdataend'] - ($LastOggSpostion + strlen(
'SggO')));
324 $info[
'ogg'][
'samples'] =
$info[
'ogg'][
'pageheader'][
'eos'][
'pcm_abs_position'];
325 if (
$info[
'ogg'][
'samples'] == 0) {
326 $this->
error(
'Corrupt Ogg file: eos.number of samples == zero');
329 if (!empty(
$info[
'audio'][
'sample_rate'])) {
330 $info[
'ogg'][
'bitrate_average'] = ((
$info[
'avdataend'] -
$info[
'avdataoffset']) * 8) / (
$info[
'ogg'][
'samples'] /
$info[
'audio'][
'sample_rate']);
336 if (!empty(
$info[
'ogg'][
'bitrate_average'])) {
337 $info[
'audio'][
'bitrate'] =
$info[
'ogg'][
'bitrate_average'];
338 } elseif (!empty(
$info[
'ogg'][
'bitrate_nominal'])) {
339 $info[
'audio'][
'bitrate'] =
$info[
'ogg'][
'bitrate_nominal'];
340 } elseif (!empty(
$info[
'ogg'][
'bitrate_min']) && !empty(
$info[
'ogg'][
'bitrate_max'])) {
341 $info[
'audio'][
'bitrate'] = (
$info[
'ogg'][
'bitrate_min'] +
$info[
'ogg'][
'bitrate_max']) / 2;
343 if (isset(
$info[
'audio'][
'bitrate']) && !isset(
$info[
'playtime_seconds'])) {
344 if (
$info[
'audio'][
'bitrate'] == 0) {
345 $this->
error(
'Corrupt Ogg file: bitrate_audio == zero');
348 $info[
'playtime_seconds'] = (float) (((
$info[
'avdataend'] -
$info[
'avdataoffset']) * 8) /
$info[
'audio'][
'bitrate']);
351 if (isset(
$info[
'ogg'][
'vendor'])) {
352 $info[
'audio'][
'encoder'] = preg_replace(
'/^Encoded with /',
'',
$info[
'ogg'][
'vendor']);
355 if (
$info[
'audio'][
'dataformat'] ==
'vorbis') {
358 if (preg_match(
'/^Xiph.Org/',
$info[
'audio'][
'encoder'])) {
360 if (
$info[
'audio'][
'bitrate_mode'] ==
'abr') {
363 $info[
'audio'][
'encoder_options'] =
'-b '.round(
$info[
'ogg'][
'bitrate_nominal'] / 1000);
365 } elseif ((
$info[
'audio'][
'bitrate_mode'] ==
'vbr') && (
$info[
'audio'][
'channels'] == 2) && (
$info[
'audio'][
'sample_rate'] >= 44100) && (
$info[
'audio'][
'sample_rate'] <= 48000)) {
367 $info[
'audio'][
'encoder_options'] =
'-q '.$this->get_quality_from_nominal_bitrate(
$info[
'ogg'][
'bitrate_nominal']);
372 if (empty(
$info[
'audio'][
'encoder_options']) && !empty(
$info[
'ogg'][
'bitrate_nominal'])) {
373 $info[
'audio'][
'encoder_options'] =
'Nominal bitrate: '.intval(round(
$info[
'ogg'][
'bitrate_nominal'] / 1000)).
'kbps';
382 $info = &$this->getid3->info;
383 $info[
'audio'][
'dataformat'] =
'vorbis';
384 $info[
'audio'][
'lossless'] =
false;
387 $filedataoffset += 1;
388 $info[
'ogg'][
'pageheader'][$oggpageinfo[
'page_seqno']][
'stream_type'] = substr($filedata, $filedataoffset, 6);
389 $filedataoffset += 6;
391 $filedataoffset += 4;
393 $filedataoffset += 1;
394 $info[
'audio'][
'channels'] =
$info[
'ogg'][
'numberofchannels'];
396 $filedataoffset += 4;
397 if (
$info[
'ogg'][
'samplerate'] == 0) {
398 $this->
error(
'Corrupt Ogg file: sample rate == zero');
401 $info[
'audio'][
'sample_rate'] =
$info[
'ogg'][
'samplerate'];
402 $info[
'ogg'][
'samples'] = 0;
403 $info[
'ogg'][
'bitrate_average'] = 0;
405 $filedataoffset += 4;
407 $filedataoffset += 4;
409 $filedataoffset += 4;
414 $info[
'audio'][
'bitrate_mode'] =
'vbr';
415 if (
$info[
'ogg'][
'bitrate_max'] == 0xFFFFFFFF) {
416 unset(
$info[
'ogg'][
'bitrate_max']);
417 $info[
'audio'][
'bitrate_mode'] =
'abr';
419 if (
$info[
'ogg'][
'bitrate_nominal'] == 0xFFFFFFFF) {
420 unset(
$info[
'ogg'][
'bitrate_nominal']);
422 if (
$info[
'ogg'][
'bitrate_min'] == 0xFFFFFFFF) {
423 unset(
$info[
'ogg'][
'bitrate_min']);
424 $info[
'audio'][
'bitrate_mode'] =
'abr';
431 $info = &$this->getid3->info;
432 $info[
'audio'][
'dataformat'] =
'opus';
433 $info[
'mime_type'] =
'audio/ogg; codecs=opus';
436 $info[
'audio'][
'bitrate_mode'] =
'vbr';
438 $info[
'audio'][
'lossless'] =
false;
440 $info[
'ogg'][
'pageheader'][
'opus'][
'opus_magic'] = substr($filedata, $filedataoffset, 8);
441 $filedataoffset += 8;
443 $filedataoffset += 1;
445 if (
$info[
'ogg'][
'pageheader'][
'opus'][
'version'] < 1 ||
$info[
'ogg'][
'pageheader'][
'opus'][
'version'] > 15) {
446 $this->
error(
'Unknown opus version number (only accepting 1-15)');
451 $filedataoffset += 1;
453 if (
$info[
'ogg'][
'pageheader'][
'opus'][
'out_channel_count'] == 0) {
454 $this->
error(
'Invalid channel count in opus header (must not be zero)');
459 $filedataoffset += 2;
462 $filedataoffset += 4;
470 $info[
'opus'][
'opus_version'] =
$info[
'ogg'][
'pageheader'][
'opus'][
'version'];
471 $info[
'opus'][
'sample_rate'] =
$info[
'ogg'][
'pageheader'][
'opus'][
'sample_rate'];
472 $info[
'opus'][
'out_channel_count'] =
$info[
'ogg'][
'pageheader'][
'opus'][
'out_channel_count'];
474 $info[
'audio'][
'channels'] =
$info[
'opus'][
'out_channel_count'];
475 $info[
'audio'][
'sample_rate'] =
$info[
'opus'][
'sample_rate'];
482 $oggheader[
'page_start_offset'] = $this->
ftell();
484 $filedata = $this->
fread($this->getid3->fread_buffer_size());
486 while ((substr($filedata, $filedataoffset++, 4) !=
'OggS')) {
487 if (($this->
ftell() - $oggheader[
'page_start_offset']) >= $this->getid3->fread_buffer_size()) {
491 if ((($filedataoffset + 28) > strlen($filedata)) || (strlen($filedata) < 28)) {
492 if ($this->
feof() || (($filedata .= $this->
fread($this->getid3->fread_buffer_size())) ===
false)) {
498 $filedataoffset += strlen(
'OggS') - 1;
501 $filedataoffset += 1;
503 $filedataoffset += 1;
504 $oggheader[
'flags'][
'fresh'] = (bool) ($oggheader[
'flags_raw'] & 0x01);
505 $oggheader[
'flags'][
'bos'] = (bool) ($oggheader[
'flags_raw'] & 0x02);
506 $oggheader[
'flags'][
'eos'] = (bool) ($oggheader[
'flags_raw'] & 0x04);
509 $filedataoffset += 8;
511 $filedataoffset += 4;
513 $filedataoffset += 4;
515 $filedataoffset += 4;
517 $filedataoffset += 1;
518 $oggheader[
'page_length'] = 0;
519 for (
$i = 0;
$i < $oggheader[
'page_segments'];
$i++) {
521 $filedataoffset += 1;
522 $oggheader[
'page_length'] += $oggheader[
'segment_table'][
$i];
524 $oggheader[
'header_end_offset'] = $oggheader[
'page_start_offset'] + $filedataoffset;
525 $oggheader[
'page_end_offset'] = $oggheader[
'header_end_offset'] + $oggheader[
'page_length'];
526 $this->
fseek($oggheader[
'header_end_offset']);
533 $info = &$this->getid3->info;
535 $OriginalOffset = $this->
ftell();
536 $commentdataoffset = 0;
537 $VorbisCommentPage = 1;
539 switch (
$info[
'audio'][
'dataformat']) {
543 $CommentStartOffset =
$info[
'ogg'][
'pageheader'][$VorbisCommentPage][
'page_start_offset'];
544 $this->
fseek($CommentStartOffset);
545 $commentdataoffset = 27 +
$info[
'ogg'][
'pageheader'][$VorbisCommentPage][
'page_segments'];
546 $commentdata = $this->
fread(self::OggPageSegmentLength(
$info[
'ogg'][
'pageheader'][$VorbisCommentPage], 1) + $commentdataoffset);
548 if (
$info[
'audio'][
'dataformat'] ==
'vorbis') {
549 $commentdataoffset += (strlen(
'vorbis') + 1);
551 else if (
$info[
'audio'][
'dataformat'] ==
'opus') {
552 $commentdataoffset += strlen(
'OpusTags');
558 $CommentStartOffset =
$info[
'flac'][
'VORBIS_COMMENT'][
'raw'][
'offset'] + 4;
559 $this->
fseek($CommentStartOffset);
560 $commentdata = $this->
fread(
$info[
'flac'][
'VORBIS_COMMENT'][
'raw'][
'block_length']);
569 $commentdataoffset += 4;
571 $info[
'ogg'][
'vendor'] = substr($commentdata, $commentdataoffset, $VendorSize);
572 $commentdataoffset += $VendorSize;
575 $commentdataoffset += 4;
576 $info[
'avdataoffset'] = $CommentStartOffset + $commentdataoffset;
578 $basicfields =
array(
'TITLE',
'ARTIST',
'ALBUM',
'TRACKNUMBER',
'GENRE',
'DATE',
'DESCRIPTION',
'COMMENT');
579 $ThisFileInfo_ogg_comments_raw = &
$info[
'ogg'][
'comments_raw'];
580 for (
$i = 0;
$i < $CommentsCount;
$i++) {
584 $this->
warning(
'Unexpectedly large number ('.$CommentsCount.
') of Ogg comments - breaking after reading '.
$i.
' comments');
588 $ThisFileInfo_ogg_comments_raw[
$i][
'dataoffset'] = $CommentStartOffset + $commentdataoffset;
590 if ($this->
ftell() < ($ThisFileInfo_ogg_comments_raw[
$i][
'dataoffset'] + 4)) {
592 $info[
'ogg'][
'pageheader'][$oggpageinfo[
'page_seqno']] = $oggpageinfo;
594 $VorbisCommentPage++;
597 $AsYetUnusedData = substr($commentdata, $commentdataoffset);
600 $commentdata = substr($commentdata, 0, $commentdataoffset);
603 $commentdata .= str_repeat(
"\x00", 27 +
$info[
'ogg'][
'pageheader'][$oggpageinfo[
'page_seqno']][
'page_segments']);
604 $commentdataoffset += (27 +
$info[
'ogg'][
'pageheader'][$oggpageinfo[
'page_seqno']][
'page_segments']);
607 $commentdata .= $AsYetUnusedData;
617 $info[
'avdataoffset'] = $ThisFileInfo_ogg_comments_raw[
$i][
'dataoffset'] + $ThisFileInfo_ogg_comments_raw[
$i][
'size'] + 4;
619 $commentdataoffset += 4;
620 while ((strlen($commentdata) - $commentdataoffset) < $ThisFileInfo_ogg_comments_raw[
$i][
'size']) {
621 if (($ThisFileInfo_ogg_comments_raw[$i][
'size'] >
$info[
'avdataend']) || ($ThisFileInfo_ogg_comments_raw[$i][
'size'] < 0)) {
622 $this->
warning(
'Invalid Ogg comment size (comment #'.$i.
', claims to be '.number_format($ThisFileInfo_ogg_comments_raw[$i][
'size']).
' bytes) - aborting reading comments');
626 $VorbisCommentPage++;
629 $info[
'ogg'][
'pageheader'][$oggpageinfo[
'page_seqno']] = $oggpageinfo;
632 $AsYetUnusedData = substr($commentdata, $commentdataoffset);
635 $commentdata = substr($commentdata, 0, $commentdataoffset);
638 $commentdata .= str_repeat(
"\x00", 27 +
$info[
'ogg'][
'pageheader'][$oggpageinfo[
'page_seqno']][
'page_segments']);
639 $commentdataoffset += (27 +
$info[
'ogg'][
'pageheader'][$oggpageinfo[
'page_seqno']][
'page_segments']);
642 $commentdata .= $AsYetUnusedData;
645 if (!isset(
$info[
'ogg'][
'pageheader'][$VorbisCommentPage])) {
646 $this->
warning(
'undefined Vorbis Comment page "'.$VorbisCommentPage.
'" at offset '.$this->ftell());
649 $readlength = self::OggPageSegmentLength(
$info[
'ogg'][
'pageheader'][$VorbisCommentPage], 1);
650 if ($readlength <= 0) {
651 $this->
warning(
'invalid length Vorbis Comment page "'.$VorbisCommentPage.
'" at offset '.$this->ftell());
654 $commentdata .= $this->
fread($readlength);
658 $ThisFileInfo_ogg_comments_raw[
$i][
'offset'] = $commentdataoffset;
659 $commentstring = substr($commentdata, $commentdataoffset, $ThisFileInfo_ogg_comments_raw[$i][
'size']);
660 $commentdataoffset += $ThisFileInfo_ogg_comments_raw[
$i][
'size'];
662 if (!$commentstring) {
665 $this->
warning(
'Blank Ogg comment ['.$i.
']');
667 } elseif (strstr($commentstring,
'=')) {
669 $commentexploded = explode(
'=', $commentstring, 2);
670 $ThisFileInfo_ogg_comments_raw[
$i][
'key'] = strtoupper($commentexploded[0]);
671 $ThisFileInfo_ogg_comments_raw[
$i][
'value'] = (isset($commentexploded[1]) ? $commentexploded[1] :
'');
673 if ($ThisFileInfo_ogg_comments_raw[$i][
'key'] ==
'METADATA_BLOCK_PICTURE') {
679 $flac->setStringMode(base64_decode($ThisFileInfo_ogg_comments_raw[$i][
'value']));
680 $flac->parsePICTURE();
681 $info[
'ogg'][
'comments'][
'picture'][] = $flac->getid3->info[
'flac'][
'PICTURE'][0];
684 } elseif ($ThisFileInfo_ogg_comments_raw[$i][
'key'] ==
'COVERART') {
686 $data = base64_decode($ThisFileInfo_ogg_comments_raw[$i][
'value']);
687 $this->
notice(
'Found deprecated COVERART tag, it should be replaced in honor of METADATA_BLOCK_PICTURE structure');
690 if ($imageinfo ===
false || !isset($imageinfo[
'mime'])) {
691 $this->
warning(
'COVERART vorbiscomment tag contains invalid image');
696 $ogg->setStringMode(
$data);
697 $info[
'ogg'][
'comments'][
'picture'][] =
array(
698 'image_mime' => $imageinfo[
'mime'],
699 'datalength' => strlen(
$data),
700 'picturetype' =>
'cover art',
701 'image_height' => $imageinfo[
'height'],
702 'image_width' => $imageinfo[
'width'],
703 'data' => $ogg->saveAttachment(
'coverart', 0, strlen(
$data), $imageinfo[
'mime']),
709 $info[
'ogg'][
'comments'][strtolower($ThisFileInfo_ogg_comments_raw[$i][
'key'])][] = $ThisFileInfo_ogg_comments_raw[
$i][
'value'];
715 $this->
warning(
'[known problem with CDex >= v1.40, < v1.50b7] Invalid Ogg comment name/value pair ['.$i.
']: '.$commentstring);
718 unset($ThisFileInfo_ogg_comments_raw[$i]);
720 unset($ThisFileInfo_ogg_comments_raw);
725 if (isset(
$info[
'ogg'][
'comments']) && is_array(
$info[
'ogg'][
'comments'])) {
726 foreach (
$info[
'ogg'][
'comments'] as
$index => $commentvalue) {
728 case 'rg_audiophile':
729 case 'replaygain_album_gain':
730 $info[
'replay_gain'][
'album'][
'adjustment'] = (double) $commentvalue[0];
735 case 'replaygain_track_gain':
736 $info[
'replay_gain'][
'track'][
'adjustment'] = (double) $commentvalue[0];
737 unset(
$info[
'ogg'][
'comments'][$index]);
740 case 'replaygain_album_peak':
741 $info[
'replay_gain'][
'album'][
'peak'] = (double) $commentvalue[0];
742 unset(
$info[
'ogg'][
'comments'][$index]);
746 case 'replaygain_track_peak':
747 $info[
'replay_gain'][
'track'][
'peak'] = (double) $commentvalue[0];
748 unset(
$info[
'ogg'][
'comments'][$index]);
751 case 'replaygain_reference_loudness':
752 $info[
'replay_gain'][
'reference_volume'] = (double) $commentvalue[0];
753 unset(
$info[
'ogg'][
'comments'][$index]);
763 $this->
fseek($OriginalOffset);
769 static $SpeexBandModeLookup =
array();
770 if (empty($SpeexBandModeLookup)) {
771 $SpeexBandModeLookup[0] =
'narrow';
772 $SpeexBandModeLookup[1] =
'wide';
773 $SpeexBandModeLookup[2] =
'ultra-wide';
775 return (isset($SpeexBandModeLookup[$mode]) ? $SpeexBandModeLookup[$mode] : null);
780 for (
$i = 0;
$i < $SegmentNumber;
$i++) {
782 foreach ($OggInfoArray[
'segment_table'] as
$key => $value) {
783 $segmentlength += $value;
789 return $segmentlength;
796 $nominal_bitrate = $nominal_bitrate / 1000;
798 if ($nominal_bitrate < 128) {
800 $qval = ($nominal_bitrate - 64) / 16;
801 } elseif ($nominal_bitrate < 256) {
803 $qval = $nominal_bitrate / 32;
804 } elseif ($nominal_bitrate < 320) {
806 $qval = ($nominal_bitrate + 256) / 64;
809 $qval = ($nominal_bitrate + 1300) / 180;
813 return round($qval, 1);
818 static $TheoraColorSpaceLookup =
array();
819 if (empty($TheoraColorSpaceLookup)) {
820 $TheoraColorSpaceLookup[0] =
'Undefined';
821 $TheoraColorSpaceLookup[1] =
'Rec. 470M';
822 $TheoraColorSpaceLookup[2] =
'Rec. 470BG';
823 $TheoraColorSpaceLookup[3] =
'Reserved';
825 return (isset($TheoraColorSpaceLookup[$colorspace_id]) ? $TheoraColorSpaceLookup[$colorspace_id] : null);
830 static $TheoraPixelFormatLookup =
array();
831 if (empty($TheoraPixelFormatLookup)) {
832 $TheoraPixelFormatLookup[0] =
'4:2:0';
833 $TheoraPixelFormatLookup[1] =
'Reserved';
834 $TheoraPixelFormatLookup[2] =
'4:2:2';
835 $TheoraPixelFormatLookup[3] =
'4:4:4';
837 return (isset($TheoraPixelFormatLookup[$pixelformat_id]) ? $TheoraPixelFormatLookup[$pixelformat_id] : null);
static TheoraPixelFormat($pixelformat_id)
ParseOpusPageHeader(&$filedata, &$filedataoffset, &$oggpageinfo)
static intValueSupported($num)
static LittleEndian2Int($byteword, $signed=false)
static IncludeDependency($filename, $sourcefile, $DieOnFailure=false)
static OggPageSegmentLength($OggInfoArray, $SegmentNumber=1)
static TheoraColorSpace($colorspace_id)
static GetDataImageSize($imgData, &$imageinfo=array())
Create styles array
The data for the language used.
ParseVorbisPageHeader(&$filedata, &$filedataoffset, &$oggpageinfo)
fseek($bytes, $whence=SEEK_SET)
static BigEndian2Int($byteword, $synchsafe=false, $signed=false)
static get_quality_from_nominal_bitrate($nominal_bitrate)
static SpeexBandModeLookup($mode)
http://flac.sourceforge.net/format.html