ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
getid3_ogg Class Reference
+ Inheritance diagram for getid3_ogg:
+ Collaboration diagram for getid3_ogg:

Public Member Functions

 Analyze ()
 
 ParseVorbisPageHeader (&$filedata, &$filedataoffset, &$oggpageinfo)
 
 ParseOpusPageHeader (&$filedata, &$filedataoffset, &$oggpageinfo)
 
 ParseOggPageHeader ()
 
 ParseVorbisComments ()
 
- Public Member Functions inherited from getid3_handler
 __construct (getID3 $getid3, $call_module=null)
 
 Analyze ()
 
 AnalyzeString ($string)
 
 setStringMode ($string)
 
 saveAttachment ($name, $offset, $length, $image_mime=null)
 

Static Public Member Functions

static SpeexBandModeLookup ($mode)
 
static OggPageSegmentLength ($OggInfoArray, $SegmentNumber=1)
 
static get_quality_from_nominal_bitrate ($nominal_bitrate)
 
static TheoraColorSpace ($colorspace_id)
 
static TheoraPixelFormat ($pixelformat_id)
 

Additional Inherited Members

- Protected Member Functions inherited from getid3_handler
 ftell ()
 
 fread ($bytes)
 
 fseek ($bytes, $whence=SEEK_SET)
 
 feof ()
 
 isDependencyFor ($module)
 
 error ($text)
 
 warning ($text)
 
 notice ($text)
 
- Protected Attributes inherited from getid3_handler
 $getid3
 
 $data_string_flag = false
 
 $data_string = ''
 
 $data_string_position = 0
 
 $data_string_length = 0
 

Detailed Description

Definition at line 19 of file module.audio.ogg.php.

Member Function Documentation

◆ Analyze()

getid3_ogg::Analyze ( )

Definition at line 22 of file module.audio.ogg.php.

References $info, getid3_lib\BigEndian2Int(), getid3_handler\error(), getid3_handler\fread(), getid3_handler\fseek(), getid3_handler\ftell(), getid3_lib\intValueSupported(), getid3_lib\LittleEndian2Int(), ParseOggPageHeader(), ParseOpusPageHeader(), ParseVorbisComments(), ParseVorbisPageHeader(), SpeexBandModeLookup(), and getid3_handler\warning().

22  {
23  $info = &$this->getid3->info;
24 
25  $info['fileformat'] = 'ogg';
26 
27  // Warn about illegal tags - only vorbiscomments are allowed
28  if (isset($info['id3v2'])) {
29  $this->warning('Illegal ID3v2 tag present.');
30  }
31  if (isset($info['id3v1'])) {
32  $this->warning('Illegal ID3v1 tag present.');
33  }
34  if (isset($info['ape'])) {
35  $this->warning('Illegal APE tag present.');
36  }
37 
38 
39  // Page 1 - Stream Header
40 
41  $this->fseek($info['avdataoffset']);
42 
43  $oggpageinfo = $this->ParseOggPageHeader();
44  $info['ogg']['pageheader'][$oggpageinfo['page_seqno']] = $oggpageinfo;
45 
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']);
49  unset($info['ogg']);
50  return false;
51  }
52 
53  $filedata = $this->fread($oggpageinfo['page_length']);
54  $filedataoffset = 0;
55 
56  if (substr($filedata, 0, 4) == 'fLaC') {
57 
58  $info['audio']['dataformat'] = 'flac';
59  $info['audio']['bitrate_mode'] = 'vbr';
60  $info['audio']['lossless'] = true;
61 
62  } elseif (substr($filedata, 1, 6) == 'vorbis') {
63 
64  $this->ParseVorbisPageHeader($filedata, $filedataoffset, $oggpageinfo);
65 
66  } elseif (substr($filedata, 0, 8) == 'OpusHead') {
67 
68  if( $this->ParseOpusPageHeader($filedata, $filedataoffset, $oggpageinfo) == false ) {
69  return false;
70  }
71 
72  } elseif (substr($filedata, 0, 8) == 'Speex ') {
73 
74  // http://www.speex.org/manual/node10.html
75 
76  $info['audio']['dataformat'] = 'speex';
77  $info['mime_type'] = 'audio/speex';
78  $info['audio']['bitrate_mode'] = 'abr';
79  $info['audio']['lossless'] = false;
80 
81  $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['speex_string'] = substr($filedata, $filedataoffset, 8); // hard-coded to 'Speex '
82  $filedataoffset += 8;
83  $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['speex_version'] = substr($filedata, $filedataoffset, 20);
84  $filedataoffset += 20;
85  $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['speex_version_id'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
86  $filedataoffset += 4;
87  $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['header_size'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
88  $filedataoffset += 4;
89  $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['rate'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
90  $filedataoffset += 4;
91  $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['mode'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
92  $filedataoffset += 4;
93  $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['mode_bitstream_version'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
94  $filedataoffset += 4;
95  $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['nb_channels'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
96  $filedataoffset += 4;
97  $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['bitrate'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
98  $filedataoffset += 4;
99  $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['framesize'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
100  $filedataoffset += 4;
101  $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['vbr'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
102  $filedataoffset += 4;
103  $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['frames_per_packet'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
104  $filedataoffset += 4;
105  $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['extra_headers'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
106  $filedataoffset += 4;
107  $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['reserved1'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
108  $filedataoffset += 4;
109  $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['reserved2'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
110  $filedataoffset += 4;
111 
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'];
116  $info['speex']['band_type'] = $this->SpeexBandModeLookup($info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['mode']);
117 
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';
122  }
123 
124  } elseif (substr($filedata, 0, 7) == "\x80".'theora') {
125 
126  // http://www.theora.org/doc/Theora.pdf (section 6.2)
127 
128  $info['ogg']['pageheader']['theora']['theora_magic'] = substr($filedata, $filedataoffset, 7); // hard-coded to "\x80.'theora'
129  $filedataoffset += 7;
130  $info['ogg']['pageheader']['theora']['version_major'] = getid3_lib::BigEndian2Int(substr($filedata, $filedataoffset, 1));
131  $filedataoffset += 1;
132  $info['ogg']['pageheader']['theora']['version_minor'] = getid3_lib::BigEndian2Int(substr($filedata, $filedataoffset, 1));
133  $filedataoffset += 1;
134  $info['ogg']['pageheader']['theora']['version_revision'] = getid3_lib::BigEndian2Int(substr($filedata, $filedataoffset, 1));
135  $filedataoffset += 1;
136  $info['ogg']['pageheader']['theora']['frame_width_macroblocks'] = getid3_lib::BigEndian2Int(substr($filedata, $filedataoffset, 2));
137  $filedataoffset += 2;
138  $info['ogg']['pageheader']['theora']['frame_height_macroblocks'] = getid3_lib::BigEndian2Int(substr($filedata, $filedataoffset, 2));
139  $filedataoffset += 2;
140  $info['ogg']['pageheader']['theora']['resolution_x'] = getid3_lib::BigEndian2Int(substr($filedata, $filedataoffset, 3));
141  $filedataoffset += 3;
142  $info['ogg']['pageheader']['theora']['resolution_y'] = getid3_lib::BigEndian2Int(substr($filedata, $filedataoffset, 3));
143  $filedataoffset += 3;
144  $info['ogg']['pageheader']['theora']['picture_offset_x'] = getid3_lib::BigEndian2Int(substr($filedata, $filedataoffset, 1));
145  $filedataoffset += 1;
146  $info['ogg']['pageheader']['theora']['picture_offset_y'] = getid3_lib::BigEndian2Int(substr($filedata, $filedataoffset, 1));
147  $filedataoffset += 1;
148  $info['ogg']['pageheader']['theora']['frame_rate_numerator'] = getid3_lib::BigEndian2Int(substr($filedata, $filedataoffset, 4));
149  $filedataoffset += 4;
150  $info['ogg']['pageheader']['theora']['frame_rate_denominator'] = getid3_lib::BigEndian2Int(substr($filedata, $filedataoffset, 4));
151  $filedataoffset += 4;
152  $info['ogg']['pageheader']['theora']['pixel_aspect_numerator'] = getid3_lib::BigEndian2Int(substr($filedata, $filedataoffset, 3));
153  $filedataoffset += 3;
154  $info['ogg']['pageheader']['theora']['pixel_aspect_denominator'] = getid3_lib::BigEndian2Int(substr($filedata, $filedataoffset, 3));
155  $filedataoffset += 3;
156  $info['ogg']['pageheader']['theora']['color_space_id'] = getid3_lib::BigEndian2Int(substr($filedata, $filedataoffset, 1));
157  $filedataoffset += 1;
158  $info['ogg']['pageheader']['theora']['nominal_bitrate'] = getid3_lib::BigEndian2Int(substr($filedata, $filedataoffset, 3));
159  $filedataoffset += 3;
160  $info['ogg']['pageheader']['theora']['flags'] = getid3_lib::BigEndian2Int(substr($filedata, $filedataoffset, 2));
161  $filedataoffset += 2;
162 
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; // should be 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']);
169 
170  $info['video']['dataformat'] = 'theora';
171  $info['mime_type'] = 'video/ogg';
172  //$info['audio']['bitrate_mode'] = 'abr';
173  //$info['audio']['lossless'] = false;
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'];
178  }
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'];
181  }
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');
183 
184 
185  } elseif (substr($filedata, 0, 8) == "fishead\x00") {
186 
187  // Ogg Skeleton version 3.0 Format Specification
188  // http://xiph.org/ogg/doc/skeleton.html
189  $filedataoffset += 8;
190  $info['ogg']['skeleton']['fishead']['raw']['version_major'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 2));
191  $filedataoffset += 2;
192  $info['ogg']['skeleton']['fishead']['raw']['version_minor'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 2));
193  $filedataoffset += 2;
194  $info['ogg']['skeleton']['fishead']['raw']['presentationtime_numerator'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 8));
195  $filedataoffset += 8;
196  $info['ogg']['skeleton']['fishead']['raw']['presentationtime_denominator'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 8));
197  $filedataoffset += 8;
198  $info['ogg']['skeleton']['fishead']['raw']['basetime_numerator'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 8));
199  $filedataoffset += 8;
200  $info['ogg']['skeleton']['fishead']['raw']['basetime_denominator'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 8));
201  $filedataoffset += 8;
202  $info['ogg']['skeleton']['fishead']['raw']['utc'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 20));
203  $filedataoffset += 20;
204 
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'];
209 
210 
211  $counter = 0;
212  do {
213  $oggpageinfo = $this->ParseOggPageHeader();
214  $info['ogg']['pageheader'][$oggpageinfo['page_seqno'].'.'.$counter++] = $oggpageinfo;
215  $filedata = $this->fread($oggpageinfo['page_length']);
216  $this->fseek($oggpageinfo['page_end_offset']);
217 
218  if (substr($filedata, 0, 8) == "fisbone\x00") {
219 
220  $filedataoffset = 8;
221  $info['ogg']['skeleton']['fisbone']['raw']['message_header_offset'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
222  $filedataoffset += 4;
223  $info['ogg']['skeleton']['fisbone']['raw']['serial_number'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
224  $filedataoffset += 4;
225  $info['ogg']['skeleton']['fisbone']['raw']['number_header_packets'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
226  $filedataoffset += 4;
227  $info['ogg']['skeleton']['fisbone']['raw']['granulerate_numerator'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 8));
228  $filedataoffset += 8;
229  $info['ogg']['skeleton']['fisbone']['raw']['granulerate_denominator'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 8));
230  $filedataoffset += 8;
231  $info['ogg']['skeleton']['fisbone']['raw']['basegranule'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 8));
232  $filedataoffset += 8;
233  $info['ogg']['skeleton']['fisbone']['raw']['preroll'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
234  $filedataoffset += 4;
235  $info['ogg']['skeleton']['fisbone']['raw']['granuleshift'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 1));
236  $filedataoffset += 1;
237  $info['ogg']['skeleton']['fisbone']['raw']['padding'] = substr($filedata, $filedataoffset, 3);
238  $filedataoffset += 3;
239 
240  } elseif (substr($filedata, 1, 6) == 'theora') {
241 
242  $info['video']['dataformat'] = 'theora1';
243  $this->error('Ogg Theora (v1) not correctly handled in this version of getID3 ['.$this->getid3->version().']');
244  //break;
245 
246  } elseif (substr($filedata, 1, 6) == 'vorbis') {
247 
248  $this->ParseVorbisPageHeader($filedata, $filedataoffset, $oggpageinfo);
249 
250  } else {
251  $this->error('unexpected');
252  //break;
253  }
254  //} while ($oggpageinfo['page_seqno'] == 0);
255  } while (($oggpageinfo['page_seqno'] == 0) && (substr($filedata, 0, 8) != "fisbone\x00"));
256 
257  $this->fseek($oggpageinfo['page_start_offset']);
258 
259  $this->error('Ogg Skeleton not correctly handled in this version of getID3 ['.$this->getid3->version().']');
260  //return false;
261 
262  } else {
263 
264  $this->error('Expecting either "Speex ", "OpusHead" or "vorbis" identifier strings, found "'.substr($filedata, 0, 8).'"');
265  unset($info['ogg']);
266  unset($info['mime_type']);
267  return false;
268 
269  }
270 
271  // Page 2 - Comment Header
272  $oggpageinfo = $this->ParseOggPageHeader();
273  $info['ogg']['pageheader'][$oggpageinfo['page_seqno']] = $oggpageinfo;
274 
275  switch ($info['audio']['dataformat']) {
276  case 'vorbis':
277  $filedata = $this->fread($info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_length']);
278  $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['packet_type'] = getid3_lib::LittleEndian2Int(substr($filedata, 0, 1));
279  $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['stream_type'] = substr($filedata, 1, 6); // hard-coded to 'vorbis'
280 
281  $this->ParseVorbisComments();
282  break;
283 
284  case 'flac':
285  $flac = new getid3_flac($this->getid3);
286  if (!$flac->parseMETAdata()) {
287  $this->error('Failed to parse FLAC headers');
288  return false;
289  }
290  unset($flac);
291  break;
292 
293  case 'speex':
294  $this->fseek($info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_length'], SEEK_CUR);
295  $this->ParseVorbisComments();
296  break;
297 
298  case 'opus':
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); // hard-coded to 'OpusTags'
301  if(substr($filedata, 0, 8) != 'OpusTags') {
302  $this->error('Expected "OpusTags" as header but got "'.substr($filedata, 0, 8).'"');
303  return false;
304  }
305 
306  $this->ParseVorbisComments();
307  break;
308 
309  }
310 
311  // Last Page - Number of Samples
312  if (!getid3_lib::intValueSupported($info['avdataend'])) {
313 
314  $this->warning('Unable to parse Ogg end chunk file (PHP does not support file operations beyond '.round(PHP_INT_MAX / 1073741824).'GB)');
315 
316  } else {
317 
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')));
322  $info['avdataend'] = $this->ftell();
323  $info['ogg']['pageheader']['eos'] = $this->ParseOggPageHeader();
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');
327  return false;
328  }
329  if (!empty($info['audio']['sample_rate'])) {
330  $info['ogg']['bitrate_average'] = (($info['avdataend'] - $info['avdataoffset']) * 8) / ($info['ogg']['samples'] / $info['audio']['sample_rate']);
331  }
332  }
333 
334  }
335 
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;
342  }
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');
346  return false;
347  }
348  $info['playtime_seconds'] = (float) ((($info['avdataend'] - $info['avdataoffset']) * 8) / $info['audio']['bitrate']);
349  }
350 
351  if (isset($info['ogg']['vendor'])) {
352  $info['audio']['encoder'] = preg_replace('/^Encoded with /', '', $info['ogg']['vendor']);
353 
354  // Vorbis only
355  if ($info['audio']['dataformat'] == 'vorbis') {
356 
357  // Vorbis 1.0 starts with Xiph.Org
358  if (preg_match('/^Xiph.Org/', $info['audio']['encoder'])) {
359 
360  if ($info['audio']['bitrate_mode'] == 'abr') {
361 
362  // Set -b 128 on abr files
363  $info['audio']['encoder_options'] = '-b '.round($info['ogg']['bitrate_nominal'] / 1000);
364 
365  } elseif (($info['audio']['bitrate_mode'] == 'vbr') && ($info['audio']['channels'] == 2) && ($info['audio']['sample_rate'] >= 44100) && ($info['audio']['sample_rate'] <= 48000)) {
366  // Set -q N on vbr files
367  $info['audio']['encoder_options'] = '-q '.$this->get_quality_from_nominal_bitrate($info['ogg']['bitrate_nominal']);
368 
369  }
370  }
371 
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';
374  }
375  }
376  }
377 
378  return true;
379  }
ParseOpusPageHeader(&$filedata, &$filedataoffset, &$oggpageinfo)
error($text)
Definition: getid3.php:1752
static intValueSupported($num)
Definition: getid3.lib.php:80
warning($text)
Definition: getid3.php:1758
static LittleEndian2Int($byteword, $signed=false)
Definition: getid3.lib.php:292
fread($bytes)
Definition: getid3.php:1683
ParseVorbisPageHeader(&$filedata, &$filedataoffset, &$oggpageinfo)
fseek($bytes, $whence=SEEK_SET)
Definition: getid3.php:1711
$info
Definition: index.php:5
static BigEndian2Int($byteword, $synchsafe=false, $signed=false)
Definition: getid3.lib.php:263
static SpeexBandModeLookup($mode)
http://flac.sourceforge.net/format.html
+ Here is the call graph for this function:

◆ get_quality_from_nominal_bitrate()

static getid3_ogg::get_quality_from_nominal_bitrate (   $nominal_bitrate)
static

Definition at line 793 of file module.audio.ogg.php.

793  {
794 
795  // decrease precision
796  $nominal_bitrate = $nominal_bitrate / 1000;
797 
798  if ($nominal_bitrate < 128) {
799  // q-1 to q4
800  $qval = ($nominal_bitrate - 64) / 16;
801  } elseif ($nominal_bitrate < 256) {
802  // q4 to q8
803  $qval = $nominal_bitrate / 32;
804  } elseif ($nominal_bitrate < 320) {
805  // q8 to q9
806  $qval = ($nominal_bitrate + 256) / 64;
807  } else {
808  // q9 to q10
809  $qval = ($nominal_bitrate + 1300) / 180;
810  }
811  //return $qval; // 5.031324
812  //return intval($qval); // 5
813  return round($qval, 1); // 5 or 4.9
814  }

◆ OggPageSegmentLength()

static getid3_ogg::OggPageSegmentLength (   $OggInfoArray,
  $SegmentNumber = 1 
)
static

Definition at line 779 of file module.audio.ogg.php.

References $i, and $key.

Referenced by ParseVorbisComments().

779  {
780  for ($i = 0; $i < $SegmentNumber; $i++) {
781  $segmentlength = 0;
782  foreach ($OggInfoArray['segment_table'] as $key => $value) {
783  $segmentlength += $value;
784  if ($value < 255) {
785  break;
786  }
787  }
788  }
789  return $segmentlength;
790  }
$i
Definition: disco.tpl.php:19
$key
Definition: croninfo.php:18
+ Here is the caller graph for this function:

◆ ParseOggPageHeader()

getid3_ogg::ParseOggPageHeader ( )

Definition at line 480 of file module.audio.ogg.php.

References $i, getid3_handler\feof(), getid3_handler\fread(), getid3_handler\fseek(), getid3_handler\ftell(), and getid3_lib\LittleEndian2Int().

Referenced by Analyze(), and ParseVorbisComments().

480  {
481  // http://xiph.org/ogg/vorbis/doc/framing.html
482  $oggheader['page_start_offset'] = $this->ftell(); // where we started from in the file
483 
484  $filedata = $this->fread($this->getid3->fread_buffer_size());
485  $filedataoffset = 0;
486  while ((substr($filedata, $filedataoffset++, 4) != 'OggS')) {
487  if (($this->ftell() - $oggheader['page_start_offset']) >= $this->getid3->fread_buffer_size()) {
488  // should be found before here
489  return false;
490  }
491  if ((($filedataoffset + 28) > strlen($filedata)) || (strlen($filedata) < 28)) {
492  if ($this->feof() || (($filedata .= $this->fread($this->getid3->fread_buffer_size())) === false)) {
493  // get some more data, unless eof, in which case fail
494  return false;
495  }
496  }
497  }
498  $filedataoffset += strlen('OggS') - 1; // page, delimited by 'OggS'
499 
500  $oggheader['stream_structver'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 1));
501  $filedataoffset += 1;
502  $oggheader['flags_raw'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 1));
503  $filedataoffset += 1;
504  $oggheader['flags']['fresh'] = (bool) ($oggheader['flags_raw'] & 0x01); // fresh packet
505  $oggheader['flags']['bos'] = (bool) ($oggheader['flags_raw'] & 0x02); // first page of logical bitstream (bos)
506  $oggheader['flags']['eos'] = (bool) ($oggheader['flags_raw'] & 0x04); // last page of logical bitstream (eos)
507 
508  $oggheader['pcm_abs_position'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 8));
509  $filedataoffset += 8;
510  $oggheader['stream_serialno'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
511  $filedataoffset += 4;
512  $oggheader['page_seqno'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
513  $filedataoffset += 4;
514  $oggheader['page_checksum'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
515  $filedataoffset += 4;
516  $oggheader['page_segments'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 1));
517  $filedataoffset += 1;
518  $oggheader['page_length'] = 0;
519  for ($i = 0; $i < $oggheader['page_segments']; $i++) {
520  $oggheader['segment_table'][$i] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 1));
521  $filedataoffset += 1;
522  $oggheader['page_length'] += $oggheader['segment_table'][$i];
523  }
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']);
527 
528  return $oggheader;
529  }
static LittleEndian2Int($byteword, $signed=false)
Definition: getid3.lib.php:292
fread($bytes)
Definition: getid3.php:1683
$i
Definition: disco.tpl.php:19
fseek($bytes, $whence=SEEK_SET)
Definition: getid3.php:1711
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ ParseOpusPageHeader()

getid3_ogg::ParseOpusPageHeader ( $filedata,
$filedataoffset,
$oggpageinfo 
)
Todo:
find a usable way to detect abr (vbr that is padded to be abr)

Definition at line 430 of file module.audio.ogg.php.

References $info, getid3_handler\error(), and getid3_lib\LittleEndian2Int().

Referenced by Analyze().

430  {
431  $info = &$this->getid3->info;
432  $info['audio']['dataformat'] = 'opus';
433  $info['mime_type'] = 'audio/ogg; codecs=opus';
434 
436  $info['audio']['bitrate_mode'] = 'vbr';
437 
438  $info['audio']['lossless'] = false;
439 
440  $info['ogg']['pageheader']['opus']['opus_magic'] = substr($filedata, $filedataoffset, 8); // hard-coded to 'OpusHead'
441  $filedataoffset += 8;
442  $info['ogg']['pageheader']['opus']['version'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 1));
443  $filedataoffset += 1;
444 
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)');
447  return false;
448  }
449 
450  $info['ogg']['pageheader']['opus']['out_channel_count'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 1));
451  $filedataoffset += 1;
452 
453  if ($info['ogg']['pageheader']['opus']['out_channel_count'] == 0) {
454  $this->error('Invalid channel count in opus header (must not be zero)');
455  return false;
456  }
457 
458  $info['ogg']['pageheader']['opus']['pre_skip'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 2));
459  $filedataoffset += 2;
460 
461  $info['ogg']['pageheader']['opus']['sample_rate'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
462  $filedataoffset += 4;
463 
464  //$info['ogg']['pageheader']['opus']['output_gain'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 2));
465  //$filedataoffset += 2;
466 
467  //$info['ogg']['pageheader']['opus']['channel_mapping_family'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 1));
468  //$filedataoffset += 1;
469 
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'];
473 
474  $info['audio']['channels'] = $info['opus']['out_channel_count'];
475  $info['audio']['sample_rate'] = $info['opus']['sample_rate'];
476  return true;
477  }
error($text)
Definition: getid3.php:1752
static LittleEndian2Int($byteword, $signed=false)
Definition: getid3.lib.php:292
$info
Definition: index.php:5
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ ParseVorbisComments()

getid3_ogg::ParseVorbisComments ( )
Todo:
use 'coverartmime' where available

Definition at line 532 of file module.audio.ogg.php.

References $data, getid3_handler\$getid3, $i, $index, $info, getid3_handler\fread(), getid3_handler\fseek(), getid3_handler\ftell(), getid3_lib\GetDataImageSize(), getid3_lib\LittleEndian2Int(), getid3_handler\notice(), OggPageSegmentLength(), ParseOggPageHeader(), and getid3_handler\warning().

Referenced by Analyze().

532  {
533  $info = &$this->getid3->info;
534 
535  $OriginalOffset = $this->ftell();
536  $commentdataoffset = 0;
537  $VorbisCommentPage = 1;
538 
539  switch ($info['audio']['dataformat']) {
540  case 'vorbis':
541  case 'speex':
542  case 'opus':
543  $CommentStartOffset = $info['ogg']['pageheader'][$VorbisCommentPage]['page_start_offset']; // Second Ogg page, after header block
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);
547 
548  if ($info['audio']['dataformat'] == 'vorbis') {
549  $commentdataoffset += (strlen('vorbis') + 1);
550  }
551  else if ($info['audio']['dataformat'] == 'opus') {
552  $commentdataoffset += strlen('OpusTags');
553  }
554 
555  break;
556 
557  case 'flac':
558  $CommentStartOffset = $info['flac']['VORBIS_COMMENT']['raw']['offset'] + 4;
559  $this->fseek($CommentStartOffset);
560  $commentdata = $this->fread($info['flac']['VORBIS_COMMENT']['raw']['block_length']);
561  break;
562 
563  default:
564  return false;
565  break;
566  }
567 
568  $VendorSize = getid3_lib::LittleEndian2Int(substr($commentdata, $commentdataoffset, 4));
569  $commentdataoffset += 4;
570 
571  $info['ogg']['vendor'] = substr($commentdata, $commentdataoffset, $VendorSize);
572  $commentdataoffset += $VendorSize;
573 
574  $CommentsCount = getid3_lib::LittleEndian2Int(substr($commentdata, $commentdataoffset, 4));
575  $commentdataoffset += 4;
576  $info['avdataoffset'] = $CommentStartOffset + $commentdataoffset;
577 
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++) {
581 
582  if ($i >= 10000) {
583  // https://github.com/owncloud/music/issues/212#issuecomment-43082336
584  $this->warning('Unexpectedly large number ('.$CommentsCount.') of Ogg comments - breaking after reading '.$i.' comments');
585  break;
586  }
587 
588  $ThisFileInfo_ogg_comments_raw[$i]['dataoffset'] = $CommentStartOffset + $commentdataoffset;
589 
590  if ($this->ftell() < ($ThisFileInfo_ogg_comments_raw[$i]['dataoffset'] + 4)) {
591  if ($oggpageinfo = $this->ParseOggPageHeader()) {
592  $info['ogg']['pageheader'][$oggpageinfo['page_seqno']] = $oggpageinfo;
593 
594  $VorbisCommentPage++;
595 
596  // First, save what we haven't read yet
597  $AsYetUnusedData = substr($commentdata, $commentdataoffset);
598 
599  // Then take that data off the end
600  $commentdata = substr($commentdata, 0, $commentdataoffset);
601 
602  // Add [headerlength] bytes of dummy data for the Ogg Page Header, just to keep absolute offsets correct
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']);
605 
606  // Finally, stick the unused data back on the end
607  $commentdata .= $AsYetUnusedData;
608 
609  //$commentdata .= $this->fread($info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_length']);
610  $commentdata .= $this->fread($this->OggPageSegmentLength($info['ogg']['pageheader'][$VorbisCommentPage], 1));
611  }
612 
613  }
614  $ThisFileInfo_ogg_comments_raw[$i]['size'] = getid3_lib::LittleEndian2Int(substr($commentdata, $commentdataoffset, 4));
615 
616  // replace avdataoffset with position just after the last vorbiscomment
617  $info['avdataoffset'] = $ThisFileInfo_ogg_comments_raw[$i]['dataoffset'] + $ThisFileInfo_ogg_comments_raw[$i]['size'] + 4;
618 
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');
623  break 2;
624  }
625 
626  $VorbisCommentPage++;
627 
628  $oggpageinfo = $this->ParseOggPageHeader();
629  $info['ogg']['pageheader'][$oggpageinfo['page_seqno']] = $oggpageinfo;
630 
631  // First, save what we haven't read yet
632  $AsYetUnusedData = substr($commentdata, $commentdataoffset);
633 
634  // Then take that data off the end
635  $commentdata = substr($commentdata, 0, $commentdataoffset);
636 
637  // Add [headerlength] bytes of dummy data for the Ogg Page Header, just to keep absolute offsets correct
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']);
640 
641  // Finally, stick the unused data back on the end
642  $commentdata .= $AsYetUnusedData;
643 
644  //$commentdata .= $this->fread($info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_length']);
645  if (!isset($info['ogg']['pageheader'][$VorbisCommentPage])) {
646  $this->warning('undefined Vorbis Comment page "'.$VorbisCommentPage.'" at offset '.$this->ftell());
647  break;
648  }
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());
652  break;
653  }
654  $commentdata .= $this->fread($readlength);
655 
656  //$filebaseoffset += $oggpageinfo['header_end_offset'] - $oggpageinfo['page_start_offset'];
657  }
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'];
661 
662  if (!$commentstring) {
663 
664  // no comment?
665  $this->warning('Blank Ogg comment ['.$i.']');
666 
667  } elseif (strstr($commentstring, '=')) {
668 
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] : '');
672 
673  if ($ThisFileInfo_ogg_comments_raw[$i]['key'] == 'METADATA_BLOCK_PICTURE') {
674 
675  // http://wiki.xiph.org/VorbisComment#METADATA_BLOCK_PICTURE
676  // 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.
677  // http://flac.sourceforge.net/format.html#metadata_block_picture
678  $flac = new getid3_flac($this->getid3);
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];
682  unset($flac);
683 
684  } elseif ($ThisFileInfo_ogg_comments_raw[$i]['key'] == 'COVERART') {
685 
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');
689  $imageinfo = getid3_lib::GetDataImageSize($data);
690  if ($imageinfo === false || !isset($imageinfo['mime'])) {
691  $this->warning('COVERART vorbiscomment tag contains invalid image');
692  continue;
693  }
694 
695  $ogg = new self($this->getid3);
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']),
704  );
705  unset($ogg);
706 
707  } else {
708 
709  $info['ogg']['comments'][strtolower($ThisFileInfo_ogg_comments_raw[$i]['key'])][] = $ThisFileInfo_ogg_comments_raw[$i]['value'];
710 
711  }
712 
713  } else {
714 
715  $this->warning('[known problem with CDex >= v1.40, < v1.50b7] Invalid Ogg comment name/value pair ['.$i.']: '.$commentstring);
716 
717  }
718  unset($ThisFileInfo_ogg_comments_raw[$i]);
719  }
720  unset($ThisFileInfo_ogg_comments_raw);
721 
722 
723  // Replay Gain Adjustment
724  // http://privatewww.essex.ac.uk/~djmrob/replaygain/
725  if (isset($info['ogg']['comments']) && is_array($info['ogg']['comments'])) {
726  foreach ($info['ogg']['comments'] as $index => $commentvalue) {
727  switch ($index) {
728  case 'rg_audiophile':
729  case 'replaygain_album_gain':
730  $info['replay_gain']['album']['adjustment'] = (double) $commentvalue[0];
731  unset($info['ogg']['comments'][$index]);
732  break;
733 
734  case 'rg_radio':
735  case 'replaygain_track_gain':
736  $info['replay_gain']['track']['adjustment'] = (double) $commentvalue[0];
737  unset($info['ogg']['comments'][$index]);
738  break;
739 
740  case 'replaygain_album_peak':
741  $info['replay_gain']['album']['peak'] = (double) $commentvalue[0];
742  unset($info['ogg']['comments'][$index]);
743  break;
744 
745  case 'rg_peak':
746  case 'replaygain_track_peak':
747  $info['replay_gain']['track']['peak'] = (double) $commentvalue[0];
748  unset($info['ogg']['comments'][$index]);
749  break;
750 
751  case 'replaygain_reference_loudness':
752  $info['replay_gain']['reference_volume'] = (double) $commentvalue[0];
753  unset($info['ogg']['comments'][$index]);
754  break;
755 
756  default:
757  // do nothing
758  break;
759  }
760  }
761  }
762 
763  $this->fseek($OriginalOffset);
764 
765  return true;
766  }
notice($text)
Definition: getid3.php:1762
warning($text)
Definition: getid3.php:1758
$index
Definition: metadata.php:60
static LittleEndian2Int($byteword, $signed=false)
Definition: getid3.lib.php:292
static OggPageSegmentLength($OggInfoArray, $SegmentNumber=1)
fread($bytes)
Definition: getid3.php:1683
static GetDataImageSize($imgData, &$imageinfo=array())
$i
Definition: disco.tpl.php:19
fseek($bytes, $whence=SEEK_SET)
Definition: getid3.php:1711
$info
Definition: index.php:5
http://flac.sourceforge.net/format.html
$data
Definition: bench.php:6
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ ParseVorbisPageHeader()

getid3_ogg::ParseVorbisPageHeader ( $filedata,
$filedataoffset,
$oggpageinfo 
)

Definition at line 381 of file module.audio.ogg.php.

References $info, getid3_handler\error(), and getid3_lib\LittleEndian2Int().

Referenced by Analyze().

381  {
382  $info = &$this->getid3->info;
383  $info['audio']['dataformat'] = 'vorbis';
384  $info['audio']['lossless'] = false;
385 
386  $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['packet_type'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 1));
387  $filedataoffset += 1;
388  $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['stream_type'] = substr($filedata, $filedataoffset, 6); // hard-coded to 'vorbis'
389  $filedataoffset += 6;
390  $info['ogg']['bitstreamversion'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
391  $filedataoffset += 4;
392  $info['ogg']['numberofchannels'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 1));
393  $filedataoffset += 1;
394  $info['audio']['channels'] = $info['ogg']['numberofchannels'];
395  $info['ogg']['samplerate'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
396  $filedataoffset += 4;
397  if ($info['ogg']['samplerate'] == 0) {
398  $this->error('Corrupt Ogg file: sample rate == zero');
399  return false;
400  }
401  $info['audio']['sample_rate'] = $info['ogg']['samplerate'];
402  $info['ogg']['samples'] = 0; // filled in later
403  $info['ogg']['bitrate_average'] = 0; // filled in later
404  $info['ogg']['bitrate_max'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
405  $filedataoffset += 4;
406  $info['ogg']['bitrate_nominal'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
407  $filedataoffset += 4;
408  $info['ogg']['bitrate_min'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
409  $filedataoffset += 4;
410  $info['ogg']['blocksize_small'] = pow(2, getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 1)) & 0x0F);
411  $info['ogg']['blocksize_large'] = pow(2, (getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 1)) & 0xF0) >> 4);
412  $info['ogg']['stop_bit'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 1)); // must be 1, marks end of packet
413 
414  $info['audio']['bitrate_mode'] = 'vbr'; // overridden if actually abr
415  if ($info['ogg']['bitrate_max'] == 0xFFFFFFFF) {
416  unset($info['ogg']['bitrate_max']);
417  $info['audio']['bitrate_mode'] = 'abr';
418  }
419  if ($info['ogg']['bitrate_nominal'] == 0xFFFFFFFF) {
420  unset($info['ogg']['bitrate_nominal']);
421  }
422  if ($info['ogg']['bitrate_min'] == 0xFFFFFFFF) {
423  unset($info['ogg']['bitrate_min']);
424  $info['audio']['bitrate_mode'] = 'abr';
425  }
426  return true;
427  }
error($text)
Definition: getid3.php:1752
static LittleEndian2Int($byteword, $signed=false)
Definition: getid3.lib.php:292
$info
Definition: index.php:5
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ SpeexBandModeLookup()

static getid3_ogg::SpeexBandModeLookup (   $mode)
static

Definition at line 768 of file module.audio.ogg.php.

Referenced by Analyze().

768  {
769  static $SpeexBandModeLookup = array();
770  if (empty($SpeexBandModeLookup)) {
771  $SpeexBandModeLookup[0] = 'narrow';
772  $SpeexBandModeLookup[1] = 'wide';
773  $SpeexBandModeLookup[2] = 'ultra-wide';
774  }
775  return (isset($SpeexBandModeLookup[$mode]) ? $SpeexBandModeLookup[$mode] : null);
776  }
+ Here is the caller graph for this function:

◆ TheoraColorSpace()

static getid3_ogg::TheoraColorSpace (   $colorspace_id)
static

Definition at line 816 of file module.audio.ogg.php.

816  {
817  // http://www.theora.org/doc/Theora.pdf (table 6.3)
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';
824  }
825  return (isset($TheoraColorSpaceLookup[$colorspace_id]) ? $TheoraColorSpaceLookup[$colorspace_id] : null);
826  }

◆ TheoraPixelFormat()

static getid3_ogg::TheoraPixelFormat (   $pixelformat_id)
static

Definition at line 828 of file module.audio.ogg.php.

828  {
829  // http://www.theora.org/doc/Theora.pdf (table 6.4)
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';
836  }
837  return (isset($TheoraPixelFormatLookup[$pixelformat_id]) ? $TheoraPixelFormatLookup[$pixelformat_id] : null);
838  }

The documentation for this class was generated from the following file: