21 {
22
23 $ThisFileInfo['fileformat'] = 'ogg';
24
25
26 if (isset($ThisFileInfo['id3v2'])) {
27 $ThisFileInfo['warning'][] = 'Illegal ID3v2 tag present.';
28 }
29 if (isset($ThisFileInfo['id3v1'])) {
30 $ThisFileInfo['warning'][] = 'Illegal ID3v1 tag present.';
31 }
32 if (isset($ThisFileInfo['ape'])) {
33 $ThisFileInfo['warning'][] = 'Illegal APE tag present.';
34 }
35
36
37
38
39 fseek($fd, $ThisFileInfo[
'avdataoffset'], SEEK_SET);
40
42 $ThisFileInfo['ogg']['pageheader'][$oggpageinfo['page_seqno']] = $oggpageinfo;
43
45 $ThisFileInfo['error'][] = 'Could not find start of Ogg page in the first '.GETID3_FREAD_BUFFER_SIZE.' bytes (this might not be an Ogg-Vorbis file?)';
46 unset($ThisFileInfo['fileformat']);
47 unset($ThisFileInfo['ogg']);
48 return false;
49 }
50
51 $filedata =
fread($fd, $oggpageinfo[
'page_length']);
52 $filedataoffset = 0;
53
54 if (substr($filedata, 0, 4) == 'fLaC') {
55
56 $ThisFileInfo['audio']['dataformat'] = 'flac';
57 $ThisFileInfo['audio']['bitrate_mode'] = 'vbr';
58 $ThisFileInfo['audio']['lossless'] = true;
59
60 } elseif (substr($filedata, 1, 6) == 'vorbis') {
61
62 $ThisFileInfo['audio']['dataformat'] = 'vorbis';
63 $ThisFileInfo['audio']['lossless'] = false;
64
65 $ThisFileInfo[
'ogg'][
'pageheader'][$oggpageinfo[
'page_seqno']][
'packet_type'] =
getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 1));
66 $filedataoffset += 1;
67 $ThisFileInfo['ogg']['pageheader'][$oggpageinfo['page_seqno']]['stream_type'] = substr($filedata, $filedataoffset, 6);
68 $filedataoffset += 6;
70 $filedataoffset += 4;
72 $filedataoffset += 1;
73 $ThisFileInfo['audio']['channels'] = $ThisFileInfo['ogg']['numberofchannels'];
75 $filedataoffset += 4;
76 if ($ThisFileInfo['ogg']['samplerate'] == 0) {
77 $ThisFileInfo['error'][] = 'Corrupt Ogg file: sample rate == zero';
78 return false;
79 }
80 $ThisFileInfo['audio']['sample_rate'] = $ThisFileInfo['ogg']['samplerate'];
81 $ThisFileInfo['ogg']['samples'] = 0;
82 $ThisFileInfo['ogg']['bitrate_average'] = 0;
84 $filedataoffset += 4;
86 $filedataoffset += 4;
88 $filedataoffset += 4;
92
93 $ThisFileInfo['audio']['bitrate_mode'] = 'vbr';
94 if ($ThisFileInfo['ogg']['bitrate_max'] == 0xFFFFFFFF) {
95 unset($ThisFileInfo['ogg']['bitrate_max']);
96 $ThisFileInfo['audio']['bitrate_mode'] = 'abr';
97 }
98 if ($ThisFileInfo['ogg']['bitrate_nominal'] == 0xFFFFFFFF) {
99 unset($ThisFileInfo['ogg']['bitrate_nominal']);
100 }
101 if ($ThisFileInfo['ogg']['bitrate_min'] == 0xFFFFFFFF) {
102 unset($ThisFileInfo['ogg']['bitrate_min']);
103 $ThisFileInfo['audio']['bitrate_mode'] = 'abr';
104 }
105
106 } elseif (substr($filedata, 0, 8) == 'Speex ') {
107
108
109
110 $ThisFileInfo['audio']['dataformat'] = 'speex';
111 $ThisFileInfo['mime_type'] = 'audio/speex';
112 $ThisFileInfo['audio']['bitrate_mode'] = 'abr';
113 $ThisFileInfo['audio']['lossless'] = false;
114
115 $ThisFileInfo['ogg']['pageheader'][$oggpageinfo['page_seqno']]['speex_string'] = substr($filedata, $filedataoffset, 8);
116 $filedataoffset += 8;
117 $ThisFileInfo['ogg']['pageheader'][$oggpageinfo['page_seqno']]['speex_version'] = substr($filedata, $filedataoffset, 20);
118 $filedataoffset += 20;
119 $ThisFileInfo[
'ogg'][
'pageheader'][$oggpageinfo[
'page_seqno']][
'speex_version_id'] =
getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
120 $filedataoffset += 4;
121 $ThisFileInfo[
'ogg'][
'pageheader'][$oggpageinfo[
'page_seqno']][
'header_size'] =
getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
122 $filedataoffset += 4;
123 $ThisFileInfo[
'ogg'][
'pageheader'][$oggpageinfo[
'page_seqno']][
'rate'] =
getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
124 $filedataoffset += 4;
125 $ThisFileInfo[
'ogg'][
'pageheader'][$oggpageinfo[
'page_seqno']][
'mode'] =
getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
126 $filedataoffset += 4;
127 $ThisFileInfo[
'ogg'][
'pageheader'][$oggpageinfo[
'page_seqno']][
'mode_bitstream_version'] =
getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
128 $filedataoffset += 4;
129 $ThisFileInfo[
'ogg'][
'pageheader'][$oggpageinfo[
'page_seqno']][
'nb_channels'] =
getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
130 $filedataoffset += 4;
131 $ThisFileInfo[
'ogg'][
'pageheader'][$oggpageinfo[
'page_seqno']][
'bitrate'] =
getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
132 $filedataoffset += 4;
133 $ThisFileInfo[
'ogg'][
'pageheader'][$oggpageinfo[
'page_seqno']][
'framesize'] =
getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
134 $filedataoffset += 4;
135 $ThisFileInfo[
'ogg'][
'pageheader'][$oggpageinfo[
'page_seqno']][
'vbr'] =
getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
136 $filedataoffset += 4;
137 $ThisFileInfo[
'ogg'][
'pageheader'][$oggpageinfo[
'page_seqno']][
'frames_per_packet'] =
getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
138 $filedataoffset += 4;
139 $ThisFileInfo[
'ogg'][
'pageheader'][$oggpageinfo[
'page_seqno']][
'extra_headers'] =
getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
140 $filedataoffset += 4;
141 $ThisFileInfo[
'ogg'][
'pageheader'][$oggpageinfo[
'page_seqno']][
'reserved1'] =
getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
142 $filedataoffset += 4;
143 $ThisFileInfo[
'ogg'][
'pageheader'][$oggpageinfo[
'page_seqno']][
'reserved2'] =
getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
144 $filedataoffset += 4;
145
146 $ThisFileInfo['speex']['speex_version'] = trim($ThisFileInfo['ogg']['pageheader'][$oggpageinfo['page_seqno']]['speex_version']);
147 $ThisFileInfo['speex']['sample_rate'] = $ThisFileInfo['ogg']['pageheader'][$oggpageinfo['page_seqno']]['rate'];
148 $ThisFileInfo['speex']['channels'] = $ThisFileInfo['ogg']['pageheader'][$oggpageinfo['page_seqno']]['nb_channels'];
149 $ThisFileInfo['speex']['vbr'] = (bool) $ThisFileInfo['ogg']['pageheader'][$oggpageinfo['page_seqno']]['vbr'];
151
152 $ThisFileInfo['audio']['sample_rate'] = $ThisFileInfo['speex']['sample_rate'];
153 $ThisFileInfo['audio']['channels'] = $ThisFileInfo['speex']['channels'];
154 if ($ThisFileInfo['speex']['vbr']) {
155 $ThisFileInfo['audio']['bitrate_mode'] = 'vbr';
156 }
157
158 } else {
159
160 $ThisFileInfo['error'][] = 'Expecting either "Speex " or "vorbis" identifier strings, found neither';
161 unset($ThisFileInfo['ogg']);
162 unset($ThisFileInfo['mime_type']);
163 return false;
164
165 }
166
167
168
169
171 $ThisFileInfo['ogg']['pageheader'][$oggpageinfo['page_seqno']] = $oggpageinfo;
172
173 switch ($ThisFileInfo['audio']['dataformat']) {
174
175 case 'vorbis':
176 $filedata =
fread($fd, $ThisFileInfo[
'ogg'][
'pageheader'][$oggpageinfo[
'page_seqno']][
'page_length']);
178 $ThisFileInfo['ogg']['pageheader'][$oggpageinfo['page_seqno']]['stream_type'] = substr($filedata, 1, 6);
179
181 break;
182
183 case 'flac':
185 $ThisFileInfo['error'][] = 'Failed to parse FLAC headers';
186 return false;
187 }
188 break;
189
190 case 'speex':
191 fseek($fd, $ThisFileInfo[
'ogg'][
'pageheader'][$oggpageinfo[
'page_seqno']][
'page_length'], SEEK_CUR);
193 break;
194
195 }
196
197
198
199
200
203 if ($LastOggSpostion = strpos($LastChunkOfOgg, 'SggO')) {
204 fseek($fd, $ThisFileInfo[
'avdataend'] - ($LastOggSpostion + strlen(
'SggO')), SEEK_SET);
205 $ThisFileInfo[
'avdataend'] =
ftell($fd);
207 $ThisFileInfo['ogg']['samples'] = $ThisFileInfo['ogg']['pageheader']['eos']['pcm_abs_position'];
208 if ($ThisFileInfo['ogg']['samples'] == 0) {
209 $ThisFileInfo['error'][] = 'Corrupt Ogg file: eos.number of samples == zero';
210 return false;
211 }
212 $ThisFileInfo['ogg']['bitrate_average'] = (($ThisFileInfo['avdataend'] - $ThisFileInfo['avdataoffset']) * 8) / ($ThisFileInfo['ogg']['samples'] / $ThisFileInfo['audio']['sample_rate']);
213 }
214
215 if (!empty($ThisFileInfo['ogg']['bitrate_average'])) {
216 $ThisFileInfo['audio']['bitrate'] = $ThisFileInfo['ogg']['bitrate_average'];
217 } elseif (!empty($ThisFileInfo['ogg']['bitrate_nominal'])) {
218 $ThisFileInfo['audio']['bitrate'] = $ThisFileInfo['ogg']['bitrate_nominal'];
219 } elseif (!empty($ThisFileInfo['ogg']['bitrate_min']) && !empty($ThisFileInfo['ogg']['bitrate_max'])) {
220 $ThisFileInfo['audio']['bitrate'] = ($ThisFileInfo['ogg']['bitrate_min'] + $ThisFileInfo['ogg']['bitrate_max']) / 2;
221 }
222 if (isset($ThisFileInfo['audio']['bitrate']) && !isset($ThisFileInfo['playtime_seconds'])) {
223 if ($ThisFileInfo['audio']['bitrate'] == 0) {
224 $ThisFileInfo['error'][] = 'Corrupt Ogg file: bitrate_audio == zero';
225 return false;
226 }
227 $ThisFileInfo['playtime_seconds'] = (float) ((($ThisFileInfo['avdataend'] - $ThisFileInfo['avdataoffset']) * 8) / $ThisFileInfo['audio']['bitrate']);
228 }
229
230 if (isset($ThisFileInfo['ogg']['vendor'])) {
231 $ThisFileInfo['audio']['encoder'] = preg_replace('/^Encoded with /', '', $ThisFileInfo['ogg']['vendor']);
232
233
234 if ($ThisFileInfo['audio']['dataformat'] == 'vorbis') {
235
236
237 if (preg_match('/^Xiph.Org/', $ThisFileInfo['audio']['encoder'])) {
238
239 if ($ThisFileInfo['audio']['bitrate_mode'] == 'abr') {
240
241
242 $ThisFileInfo['audio']['encoder_options'] = '-b '.round($ThisFileInfo['ogg']['bitrate_nominal'] / 1000);
243
244 } elseif (($ThisFileInfo['audio']['bitrate_mode'] == 'vbr') && ($ThisFileInfo['audio']['channels'] == 2) && ($ThisFileInfo['audio']['sample_rate'] >= 44100) && ($ThisFileInfo['audio']['sample_rate'] <= 48000)) {
245
246 $ThisFileInfo['audio']['encoder_options'] = '-q '.$this->get_quality_from_nominal_bitrate($ThisFileInfo['ogg']['bitrate_nominal']);
247
248 }
249 }
250
251 if (empty($ThisFileInfo['audio']['encoder_options']) && !empty($ThisFileInfo['ogg']['bitrate_nominal'])) {
252 $ThisFileInfo['audio']['encoder_options'] = 'Nominal bitrate: '.intval(round($ThisFileInfo['ogg']['bitrate_nominal'] / 1000)).'kbps';
253 }
254 }
255 }
256
257 return true;
258 }
FLACparseMETAdata(&$fd, &$ThisFileInfo)
ParseVorbisCommentsFilepointer(&$fd, &$ThisFileInfo)
const GETID3_FREAD_BUFFER_SIZE