1 | <?php |
---|
2 | ///////////////////////////////////////////////////////////////// |
---|
3 | /// getID3() by James Heinrich <info@getid3.org> // |
---|
4 | // available at http://getid3.sourceforge.net // |
---|
5 | // or http://www.getid3.org // |
---|
6 | ///////////////////////////////////////////////////////////////// |
---|
7 | // See readme.txt for more details // |
---|
8 | ///////////////////////////////////////////////////////////////// |
---|
9 | // // |
---|
10 | // module.audio.flac.php // |
---|
11 | // module for analyzing FLAC and OggFLAC audio files // |
---|
12 | // dependencies: module.audio.ogg.php // |
---|
13 | // /// |
---|
14 | ///////////////////////////////////////////////////////////////// |
---|
15 | |
---|
16 | |
---|
17 | getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.ogg.php', __FILE__, true); |
---|
18 | |
---|
19 | class getid3_flac |
---|
20 | { |
---|
21 | |
---|
22 | function getid3_flac(&$fd, &$ThisFileInfo) { |
---|
23 | // http://flac.sourceforge.net/format.html |
---|
24 | |
---|
25 | fseek($fd, $ThisFileInfo['avdataoffset'], SEEK_SET); |
---|
26 | $StreamMarker = fread($fd, 4); |
---|
27 | if ($StreamMarker != 'fLaC') { |
---|
28 | $ThisFileInfo['error'][] = 'Expecting "fLaC" at offset '.$ThisFileInfo['avdataoffset'].', found "'.$StreamMarker.'"'; |
---|
29 | return false; |
---|
30 | } |
---|
31 | $ThisFileInfo['fileformat'] = 'flac'; |
---|
32 | $ThisFileInfo['audio']['dataformat'] = 'flac'; |
---|
33 | $ThisFileInfo['audio']['bitrate_mode'] = 'vbr'; |
---|
34 | $ThisFileInfo['audio']['lossless'] = true; |
---|
35 | |
---|
36 | return getid3_flac::FLACparseMETAdata($fd, $ThisFileInfo); |
---|
37 | } |
---|
38 | |
---|
39 | |
---|
40 | function FLACparseMETAdata(&$fd, &$ThisFileInfo) { |
---|
41 | |
---|
42 | do { |
---|
43 | $METAdataBlockOffset = ftell($fd); |
---|
44 | $METAdataBlockHeader = fread($fd, 4); |
---|
45 | $METAdataLastBlockFlag = (bool) (getid3_lib::BigEndian2Int(substr($METAdataBlockHeader, 0, 1)) & 0x80); |
---|
46 | $METAdataBlockType = getid3_lib::BigEndian2Int(substr($METAdataBlockHeader, 0, 1)) & 0x7F; |
---|
47 | $METAdataBlockLength = getid3_lib::BigEndian2Int(substr($METAdataBlockHeader, 1, 3)); |
---|
48 | $METAdataBlockTypeText = getid3_flac::FLACmetaBlockTypeLookup($METAdataBlockType); |
---|
49 | |
---|
50 | if ($METAdataBlockLength < 0) { |
---|
51 | $ThisFileInfo['error'][] = 'corrupt or invalid METADATA_BLOCK_HEADER.BLOCK_TYPE ('.$METAdataBlockType.') at offset '.$METAdataBlockOffset; |
---|
52 | break; |
---|
53 | } |
---|
54 | |
---|
55 | $ThisFileInfo['flac'][$METAdataBlockTypeText]['raw'] = array(); |
---|
56 | $ThisFileInfo_flac_METAdataBlockTypeText_raw = &$ThisFileInfo['flac'][$METAdataBlockTypeText]['raw']; |
---|
57 | |
---|
58 | $ThisFileInfo_flac_METAdataBlockTypeText_raw['offset'] = $METAdataBlockOffset; |
---|
59 | $ThisFileInfo_flac_METAdataBlockTypeText_raw['last_meta_block'] = $METAdataLastBlockFlag; |
---|
60 | $ThisFileInfo_flac_METAdataBlockTypeText_raw['block_type'] = $METAdataBlockType; |
---|
61 | $ThisFileInfo_flac_METAdataBlockTypeText_raw['block_type_text'] = $METAdataBlockTypeText; |
---|
62 | $ThisFileInfo_flac_METAdataBlockTypeText_raw['block_length'] = $METAdataBlockLength; |
---|
63 | $ThisFileInfo_flac_METAdataBlockTypeText_raw['block_data'] = @fread($fd, $METAdataBlockLength); |
---|
64 | $ThisFileInfo['avdataoffset'] = ftell($fd); |
---|
65 | |
---|
66 | switch ($METAdataBlockTypeText) { |
---|
67 | |
---|
68 | case 'STREAMINFO': |
---|
69 | if (!getid3_flac::FLACparseSTREAMINFO($ThisFileInfo_flac_METAdataBlockTypeText_raw['block_data'], $ThisFileInfo)) { |
---|
70 | return false; |
---|
71 | } |
---|
72 | break; |
---|
73 | |
---|
74 | case 'PADDING': |
---|
75 | // ignore |
---|
76 | break; |
---|
77 | |
---|
78 | case 'APPLICATION': |
---|
79 | if (!getid3_flac::FLACparseAPPLICATION($ThisFileInfo_flac_METAdataBlockTypeText_raw['block_data'], $ThisFileInfo)) { |
---|
80 | return false; |
---|
81 | } |
---|
82 | break; |
---|
83 | |
---|
84 | case 'SEEKTABLE': |
---|
85 | if (!getid3_flac::FLACparseSEEKTABLE($ThisFileInfo_flac_METAdataBlockTypeText_raw['block_data'], $ThisFileInfo)) { |
---|
86 | return false; |
---|
87 | } |
---|
88 | break; |
---|
89 | |
---|
90 | case 'VORBIS_COMMENT': |
---|
91 | $OldOffset = ftell($fd); |
---|
92 | fseek($fd, 0 - $METAdataBlockLength, SEEK_CUR); |
---|
93 | getid3_ogg::ParseVorbisCommentsFilepointer($fd, $ThisFileInfo); |
---|
94 | fseek($fd, $OldOffset, SEEK_SET); |
---|
95 | break; |
---|
96 | |
---|
97 | case 'CUESHEET': |
---|
98 | if (!getid3_flac::FLACparseCUESHEET($ThisFileInfo_flac_METAdataBlockTypeText_raw['block_data'], $ThisFileInfo)) { |
---|
99 | return false; |
---|
100 | } |
---|
101 | break; |
---|
102 | |
---|
103 | case 'PICTURE': |
---|
104 | if (!$this->FLACparsePICTURE($ThisFileInfo_flac_METAdataBlockTypeText_raw['block_data'], $ThisFileInfo)) { |
---|
105 | return false; |
---|
106 | } |
---|
107 | break; |
---|
108 | |
---|
109 | default: |
---|
110 | $ThisFileInfo['warning'][] = 'Unhandled METADATA_BLOCK_HEADER.BLOCK_TYPE ('.$METAdataBlockType.') at offset '.$METAdataBlockOffset; |
---|
111 | break; |
---|
112 | } |
---|
113 | |
---|
114 | } while ($METAdataLastBlockFlag === false); |
---|
115 | |
---|
116 | |
---|
117 | if (isset($ThisFileInfo['flac']['STREAMINFO'])) { |
---|
118 | $ThisFileInfo['flac']['compressed_audio_bytes'] = $ThisFileInfo['avdataend'] - $ThisFileInfo['avdataoffset']; |
---|
119 | $ThisFileInfo['flac']['uncompressed_audio_bytes'] = $ThisFileInfo['flac']['STREAMINFO']['samples_stream'] * $ThisFileInfo['flac']['STREAMINFO']['channels'] * ($ThisFileInfo['flac']['STREAMINFO']['bits_per_sample'] / 8); |
---|
120 | if ($ThisFileInfo['flac']['uncompressed_audio_bytes'] == 0) { |
---|
121 | $ThisFileInfo['error'][] = 'Corrupt FLAC file: uncompressed_audio_bytes == zero'; |
---|
122 | return false; |
---|
123 | } |
---|
124 | $ThisFileInfo['flac']['compression_ratio'] = $ThisFileInfo['flac']['compressed_audio_bytes'] / $ThisFileInfo['flac']['uncompressed_audio_bytes']; |
---|
125 | } |
---|
126 | |
---|
127 | // set md5_data_source - built into flac 0.5+ |
---|
128 | if (isset($ThisFileInfo['flac']['STREAMINFO']['audio_signature'])) { |
---|
129 | |
---|
130 | if ($ThisFileInfo['flac']['STREAMINFO']['audio_signature'] === str_repeat("\x00", 16)) { |
---|
131 | |
---|
132 | $ThisFileInfo['warning'][] = 'FLAC STREAMINFO.audio_signature is null (known issue with libOggFLAC)'; |
---|
133 | |
---|
134 | } else { |
---|
135 | |
---|
136 | $ThisFileInfo['md5_data_source'] = ''; |
---|
137 | $md5 = $ThisFileInfo['flac']['STREAMINFO']['audio_signature']; |
---|
138 | for ($i = 0; $i < strlen($md5); $i++) { |
---|
139 | $ThisFileInfo['md5_data_source'] .= str_pad(dechex(ord($md5{$i})), 2, '00', STR_PAD_LEFT); |
---|
140 | } |
---|
141 | if (!preg_match('/^[0-9a-f]{32}$/', $ThisFileInfo['md5_data_source'])) { |
---|
142 | unset($ThisFileInfo['md5_data_source']); |
---|
143 | } |
---|
144 | |
---|
145 | } |
---|
146 | |
---|
147 | } |
---|
148 | |
---|
149 | $ThisFileInfo['audio']['bits_per_sample'] = $ThisFileInfo['flac']['STREAMINFO']['bits_per_sample']; |
---|
150 | if ($ThisFileInfo['audio']['bits_per_sample'] == 8) { |
---|
151 | // special case |
---|
152 | // must invert sign bit on all data bytes before MD5'ing to match FLAC's calculated value |
---|
153 | // MD5sum calculates on unsigned bytes, but FLAC calculated MD5 on 8-bit audio data as signed |
---|
154 | $ThisFileInfo['warning'][] = 'FLAC calculates MD5 data strangely on 8-bit audio, so the stored md5_data_source value will not match the decoded WAV file'; |
---|
155 | } |
---|
156 | if (!empty($ThisFileInfo['ogg']['vendor'])) { |
---|
157 | $ThisFileInfo['audio']['encoder'] = $ThisFileInfo['ogg']['vendor']; |
---|
158 | } |
---|
159 | |
---|
160 | return true; |
---|
161 | } |
---|
162 | |
---|
163 | function FLACmetaBlockTypeLookup($blocktype) { |
---|
164 | static $FLACmetaBlockTypeLookup = array(); |
---|
165 | if (empty($FLACmetaBlockTypeLookup)) { |
---|
166 | $FLACmetaBlockTypeLookup[0] = 'STREAMINFO'; |
---|
167 | $FLACmetaBlockTypeLookup[1] = 'PADDING'; |
---|
168 | $FLACmetaBlockTypeLookup[2] = 'APPLICATION'; |
---|
169 | $FLACmetaBlockTypeLookup[3] = 'SEEKTABLE'; |
---|
170 | $FLACmetaBlockTypeLookup[4] = 'VORBIS_COMMENT'; |
---|
171 | $FLACmetaBlockTypeLookup[5] = 'CUESHEET'; |
---|
172 | $FLACmetaBlockTypeLookup[6] = 'PICTURE'; |
---|
173 | } |
---|
174 | return (isset($FLACmetaBlockTypeLookup[$blocktype]) ? $FLACmetaBlockTypeLookup[$blocktype] : 'reserved'); |
---|
175 | } |
---|
176 | |
---|
177 | function FLACapplicationIDLookup($applicationid) { |
---|
178 | static $FLACapplicationIDLookup = array(); |
---|
179 | if (empty($FLACapplicationIDLookup)) { |
---|
180 | // http://flac.sourceforge.net/id.html |
---|
181 | $FLACapplicationIDLookup[0x46746F6C] = 'flac-tools'; // 'Ftol' |
---|
182 | $FLACapplicationIDLookup[0x46746F6C] = 'Sound Font FLAC'; // 'SFFL' |
---|
183 | } |
---|
184 | return (isset($FLACapplicationIDLookup[$applicationid]) ? $FLACapplicationIDLookup[$applicationid] : 'reserved'); |
---|
185 | } |
---|
186 | |
---|
187 | function FLACpictureTypeLookup($type_id) { |
---|
188 | static $lookup = array ( |
---|
189 | 0 => 'Other', |
---|
190 | 1 => '32x32 pixels \'file icon\' (PNG only)', |
---|
191 | 2 => 'Other file icon', |
---|
192 | 3 => 'Cover (front)', |
---|
193 | 4 => 'Cover (back)', |
---|
194 | 5 => 'Leaflet page', |
---|
195 | 6 => 'Media (e.g. label side of CD)', |
---|
196 | 7 => 'Lead artist/lead performer/soloist', |
---|
197 | 8 => 'Artist/performer', |
---|
198 | 9 => 'Conductor', |
---|
199 | 10 => 'Band/Orchestra', |
---|
200 | 11 => 'Composer', |
---|
201 | 12 => 'Lyricist/text writer', |
---|
202 | 13 => 'Recording Location', |
---|
203 | 14 => 'During recording', |
---|
204 | 15 => 'During performance', |
---|
205 | 16 => 'Movie/video screen capture', |
---|
206 | 17 => 'A bright coloured fish', |
---|
207 | 18 => 'Illustration', |
---|
208 | 19 => 'Band/artist logotype', |
---|
209 | 20 => 'Publisher/Studio logotype', |
---|
210 | ); |
---|
211 | return (isset($lookup[$type_id]) ? $lookup[$type_id] : 'reserved'); |
---|
212 | } |
---|
213 | |
---|
214 | function FLACparseSTREAMINFO($METAdataBlockData, &$ThisFileInfo) { |
---|
215 | $offset = 0; |
---|
216 | $ThisFileInfo['flac']['STREAMINFO']['min_block_size'] = getid3_lib::BigEndian2Int(substr($METAdataBlockData, $offset, 2)); |
---|
217 | $offset += 2; |
---|
218 | $ThisFileInfo['flac']['STREAMINFO']['max_block_size'] = getid3_lib::BigEndian2Int(substr($METAdataBlockData, $offset, 2)); |
---|
219 | $offset += 2; |
---|
220 | $ThisFileInfo['flac']['STREAMINFO']['min_frame_size'] = getid3_lib::BigEndian2Int(substr($METAdataBlockData, $offset, 3)); |
---|
221 | $offset += 3; |
---|
222 | $ThisFileInfo['flac']['STREAMINFO']['max_frame_size'] = getid3_lib::BigEndian2Int(substr($METAdataBlockData, $offset, 3)); |
---|
223 | $offset += 3; |
---|
224 | |
---|
225 | $SampleRateChannelsSampleBitsStreamSamples = getid3_lib::BigEndian2Bin(substr($METAdataBlockData, $offset, 8)); |
---|
226 | $ThisFileInfo['flac']['STREAMINFO']['sample_rate'] = getid3_lib::Bin2Dec(substr($SampleRateChannelsSampleBitsStreamSamples, 0, 20)); |
---|
227 | $ThisFileInfo['flac']['STREAMINFO']['channels'] = getid3_lib::Bin2Dec(substr($SampleRateChannelsSampleBitsStreamSamples, 20, 3)) + 1; |
---|
228 | $ThisFileInfo['flac']['STREAMINFO']['bits_per_sample'] = getid3_lib::Bin2Dec(substr($SampleRateChannelsSampleBitsStreamSamples, 23, 5)) + 1; |
---|
229 | $ThisFileInfo['flac']['STREAMINFO']['samples_stream'] = getid3_lib::Bin2Dec(substr($SampleRateChannelsSampleBitsStreamSamples, 28, 36)); |
---|
230 | $offset += 8; |
---|
231 | |
---|
232 | $ThisFileInfo['flac']['STREAMINFO']['audio_signature'] = substr($METAdataBlockData, $offset, 16); |
---|
233 | $offset += 16; |
---|
234 | |
---|
235 | if (!empty($ThisFileInfo['flac']['STREAMINFO']['sample_rate'])) { |
---|
236 | |
---|
237 | $ThisFileInfo['audio']['bitrate_mode'] = 'vbr'; |
---|
238 | $ThisFileInfo['audio']['sample_rate'] = $ThisFileInfo['flac']['STREAMINFO']['sample_rate']; |
---|
239 | $ThisFileInfo['audio']['channels'] = $ThisFileInfo['flac']['STREAMINFO']['channels']; |
---|
240 | $ThisFileInfo['audio']['bits_per_sample'] = $ThisFileInfo['flac']['STREAMINFO']['bits_per_sample']; |
---|
241 | $ThisFileInfo['playtime_seconds'] = $ThisFileInfo['flac']['STREAMINFO']['samples_stream'] / $ThisFileInfo['flac']['STREAMINFO']['sample_rate']; |
---|
242 | $ThisFileInfo['audio']['bitrate'] = (($ThisFileInfo['avdataend'] - $ThisFileInfo['avdataoffset']) * 8) / $ThisFileInfo['playtime_seconds']; |
---|
243 | |
---|
244 | } else { |
---|
245 | |
---|
246 | $ThisFileInfo['error'][] = 'Corrupt METAdata block: STREAMINFO'; |
---|
247 | return false; |
---|
248 | |
---|
249 | } |
---|
250 | |
---|
251 | unset($ThisFileInfo['flac']['STREAMINFO']['raw']); |
---|
252 | |
---|
253 | return true; |
---|
254 | } |
---|
255 | |
---|
256 | |
---|
257 | function FLACparseAPPLICATION($METAdataBlockData, &$ThisFileInfo) { |
---|
258 | $offset = 0; |
---|
259 | $ApplicationID = getid3_lib::BigEndian2Int(substr($METAdataBlockData, $offset, 4)); |
---|
260 | $offset += 4; |
---|
261 | $ThisFileInfo['flac']['APPLICATION'][$ApplicationID]['name'] = getid3_flac::FLACapplicationIDLookup($ApplicationID); |
---|
262 | $ThisFileInfo['flac']['APPLICATION'][$ApplicationID]['data'] = substr($METAdataBlockData, $offset); |
---|
263 | $offset = $METAdataBlockLength; |
---|
264 | |
---|
265 | unset($ThisFileInfo['flac']['APPLICATION']['raw']); |
---|
266 | |
---|
267 | return true; |
---|
268 | } |
---|
269 | |
---|
270 | |
---|
271 | function FLACparseSEEKTABLE($METAdataBlockData, &$ThisFileInfo) { |
---|
272 | $offset = 0; |
---|
273 | $METAdataBlockLength = strlen($METAdataBlockData); |
---|
274 | $placeholderpattern = str_repeat("\xFF", 8); |
---|
275 | while ($offset < $METAdataBlockLength) { |
---|
276 | $SampleNumberString = substr($METAdataBlockData, $offset, 8); |
---|
277 | $offset += 8; |
---|
278 | if ($SampleNumberString == $placeholderpattern) { |
---|
279 | |
---|
280 | // placeholder point |
---|
281 | @$ThisFileInfo['flac']['SEEKTABLE']['placeholders']++; |
---|
282 | $offset += 10; |
---|
283 | |
---|
284 | } else { |
---|
285 | |
---|
286 | $SampleNumber = getid3_lib::BigEndian2Int($SampleNumberString); |
---|
287 | $ThisFileInfo['flac']['SEEKTABLE'][$SampleNumber]['offset'] = getid3_lib::BigEndian2Int(substr($METAdataBlockData, $offset, 8)); |
---|
288 | $offset += 8; |
---|
289 | $ThisFileInfo['flac']['SEEKTABLE'][$SampleNumber]['samples'] = getid3_lib::BigEndian2Int(substr($METAdataBlockData, $offset, 2)); |
---|
290 | $offset += 2; |
---|
291 | |
---|
292 | } |
---|
293 | } |
---|
294 | |
---|
295 | unset($ThisFileInfo['flac']['SEEKTABLE']['raw']); |
---|
296 | |
---|
297 | return true; |
---|
298 | } |
---|
299 | |
---|
300 | function FLACparseCUESHEET($METAdataBlockData, &$ThisFileInfo) { |
---|
301 | $offset = 0; |
---|
302 | $ThisFileInfo['flac']['CUESHEET']['media_catalog_number'] = trim(substr($METAdataBlockData, $offset, 128), "\0"); |
---|
303 | $offset += 128; |
---|
304 | $ThisFileInfo['flac']['CUESHEET']['lead_in_samples'] = getid3_lib::BigEndian2Int(substr($METAdataBlockData, $offset, 8)); |
---|
305 | $offset += 8; |
---|
306 | $ThisFileInfo['flac']['CUESHEET']['flags']['is_cd'] = (bool) (getid3_lib::BigEndian2Int(substr($METAdataBlockData, $offset, 1)) & 0x80); |
---|
307 | $offset += 1; |
---|
308 | |
---|
309 | $offset += 258; // reserved |
---|
310 | |
---|
311 | $ThisFileInfo['flac']['CUESHEET']['number_tracks'] = getid3_lib::BigEndian2Int(substr($METAdataBlockData, $offset, 1)); |
---|
312 | $offset += 1; |
---|
313 | |
---|
314 | for ($track = 0; $track < $ThisFileInfo['flac']['CUESHEET']['number_tracks']; $track++) { |
---|
315 | $TrackSampleOffset = getid3_lib::BigEndian2Int(substr($METAdataBlockData, $offset, 8)); |
---|
316 | $offset += 8; |
---|
317 | $TrackNumber = getid3_lib::BigEndian2Int(substr($METAdataBlockData, $offset, 1)); |
---|
318 | $offset += 1; |
---|
319 | |
---|
320 | $ThisFileInfo['flac']['CUESHEET']['tracks'][$TrackNumber]['sample_offset'] = $TrackSampleOffset; |
---|
321 | |
---|
322 | $ThisFileInfo['flac']['CUESHEET']['tracks'][$TrackNumber]['isrc'] = substr($METAdataBlockData, $offset, 12); |
---|
323 | $offset += 12; |
---|
324 | |
---|
325 | $TrackFlagsRaw = getid3_lib::BigEndian2Int(substr($METAdataBlockData, $offset, 1)); |
---|
326 | $offset += 1; |
---|
327 | $ThisFileInfo['flac']['CUESHEET']['tracks'][$TrackNumber]['flags']['is_audio'] = (bool) ($TrackFlagsRaw & 0x80); |
---|
328 | $ThisFileInfo['flac']['CUESHEET']['tracks'][$TrackNumber]['flags']['pre_emphasis'] = (bool) ($TrackFlagsRaw & 0x40); |
---|
329 | |
---|
330 | $offset += 13; // reserved |
---|
331 | |
---|
332 | $ThisFileInfo['flac']['CUESHEET']['tracks'][$TrackNumber]['index_points'] = getid3_lib::BigEndian2Int(substr($METAdataBlockData, $offset, 1)); |
---|
333 | $offset += 1; |
---|
334 | |
---|
335 | for ($index = 0; $index < $ThisFileInfo['flac']['CUESHEET']['tracks'][$TrackNumber]['index_points']; $index++) { |
---|
336 | $IndexSampleOffset = getid3_lib::BigEndian2Int(substr($METAdataBlockData, $offset, 8)); |
---|
337 | $offset += 8; |
---|
338 | $IndexNumber = getid3_lib::BigEndian2Int(substr($METAdataBlockData, $offset, 1)); |
---|
339 | $offset += 1; |
---|
340 | |
---|
341 | $offset += 3; // reserved |
---|
342 | |
---|
343 | $ThisFileInfo['flac']['CUESHEET']['tracks'][$TrackNumber]['indexes'][$IndexNumber] = $IndexSampleOffset; |
---|
344 | } |
---|
345 | } |
---|
346 | |
---|
347 | unset($ThisFileInfo['flac']['CUESHEET']['raw']); |
---|
348 | |
---|
349 | return true; |
---|
350 | } |
---|
351 | |
---|
352 | |
---|
353 | function FLACparsePICTURE($meta_data_block_data, &$ThisFileInfo) { |
---|
354 | $picture = &$ThisFileInfo['flac']['PICTURE'][sizeof($ThisFileInfo['flac']['PICTURE']) - 1]; |
---|
355 | |
---|
356 | $offset = 0; |
---|
357 | |
---|
358 | $picture['type'] = $this->FLACpictureTypeLookup(getid3_lib::BigEndian2Int(substr($meta_data_block_data, $offset, 4))); |
---|
359 | $offset += 4; |
---|
360 | |
---|
361 | $length = getid3_lib::BigEndian2Int(substr($meta_data_block_data, $offset, 4)); |
---|
362 | $offset += 4; |
---|
363 | |
---|
364 | $picture['mime_type'] = substr($meta_data_block_data, $offset, $length); |
---|
365 | $offset += $length; |
---|
366 | |
---|
367 | $length = getid3_lib::BigEndian2Int(substr($meta_data_block_data, $offset, 4)); |
---|
368 | $offset += 4; |
---|
369 | |
---|
370 | $picture['description'] = substr($meta_data_block_data, $offset, $length); |
---|
371 | $offset += $length; |
---|
372 | |
---|
373 | $picture['width'] = getid3_lib::BigEndian2Int(substr($meta_data_block_data, $offset, 4)); |
---|
374 | $offset += 4; |
---|
375 | |
---|
376 | $picture['height'] = getid3_lib::BigEndian2Int(substr($meta_data_block_data, $offset, 4)); |
---|
377 | $offset += 4; |
---|
378 | |
---|
379 | $picture['color_depth'] = getid3_lib::BigEndian2Int(substr($meta_data_block_data, $offset, 4)); |
---|
380 | $offset += 4; |
---|
381 | |
---|
382 | $picture['colors_indexed'] = getid3_lib::BigEndian2Int(substr($meta_data_block_data, $offset, 4)); |
---|
383 | $offset += 4; |
---|
384 | |
---|
385 | $length = getid3_lib::BigEndian2Int(substr($meta_data_block_data, $offset, 4)); |
---|
386 | $offset += 4; |
---|
387 | |
---|
388 | $picture['image_data'] = substr($meta_data_block_data, $offset, $length); |
---|
389 | $offset += $length; |
---|
390 | |
---|
391 | unset($ThisFileInfo['flac']['PICTURE']['raw']); |
---|
392 | |
---|
393 | return true; |
---|
394 | } |
---|
395 | } |
---|
396 | |
---|
397 | ?> |
---|