getid3_real::Analyze()   F
last analyzed

Complexity

Conditions 46
Paths 4405

Size

Total Lines 359
Code Lines 239

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 46
eloc 239
c 1
b 0
f 0
nc 4405
nop 0
dl 0
loc 359
rs 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
// +----------------------------------------------------------------------+
3
// | PHP version 5                                                        |
4
// +----------------------------------------------------------------------+
5
// | Copyright (c) 2002-2006 James Heinrich, Allan Hansen                 |
6
// +----------------------------------------------------------------------+
7
// | This source file is subject to version 2 of the GPL license,         |
8
// | that is bundled with this package in the file license.txt and is     |
9
// | available through the world-wide-web at the following url:           |
10
// | http://www.gnu.org/copyleft/gpl.html                                 |
11
// +----------------------------------------------------------------------+
12
// | getID3() - http://getid3.sourceforge.net or http://www.getid3.org    |
13
// +----------------------------------------------------------------------+
14
// | Authors: James Heinrich <info�getid3*org>                            |
15
// |          Allan Hansen <ah�artemis*dk>                                |
16
// +----------------------------------------------------------------------+
17
// | module.audio-video.real.php                                          |
18
// | Module for analyzing Real Audio/Video files                          |
19
// | dependencies: module.audio-video.riff.php                            |
20
// +----------------------------------------------------------------------+
21
//
22
// $Id: module.audio-video.real.php,v 1.4 2006/11/02 10:48:00 ah Exp $
23
24
class getid3_real extends getid3_handler
25
{
26
27
    public function Analyze()
28
    {
29
        $getid3 = $this->getid3;
30
31
        $getid3->include_module('audio-video.riff');
32
33
        $getid3->info['fileformat']       = 'real';
34
        $getid3->info['bitrate']          = 0;
35
        $getid3->info['playtime_seconds'] = 0;
36
37
        fseek($getid3->fp, $getid3->info['avdataoffset'], SEEK_SET);
38
        $chunk_counter = 0;
39
40
        while (ftell($getid3->fp) < $getid3->info['avdataend']) {
41
            $chunk_data = fread($getid3->fp, 8);
42
            $chunk_name = substr($chunk_data, 0, 4);
43
            $chunk_size = getid3_lib::BigEndian2Int(substr($chunk_data, 4, 4));
44
45
            if ($chunk_name == '.ra' . "\xFD") {
46
                $chunk_data .= fread($getid3->fp, $chunk_size - 8);
47
48
                if ($this->ParseOldRAheader(substr($chunk_data, 0, 128), $getid3->info['real']['old_ra_header'])) {
49
                    $getid3->info['audio']['dataformat']      = 'real';
50
                    $getid3->info['audio']['lossless']        = false;
51
                    $getid3->info['audio']['sample_rate']     = $getid3->info['real']['old_ra_header']['sample_rate'];
52
                    $getid3->info['audio']['bits_per_sample'] = $getid3->info['real']['old_ra_header']['bits_per_sample'];
53
                    $getid3->info['audio']['channels']        = $getid3->info['real']['old_ra_header']['channels'];
54
55
                    $getid3->info['playtime_seconds'] = 60 * ($getid3->info['real']['old_ra_header']['audio_bytes'] / $getid3->info['real']['old_ra_header']['bytes_per_minute']);
56
                    $getid3->info['audio']['bitrate'] = 8 * ($getid3->info['real']['old_ra_header']['audio_bytes'] / $getid3->info['playtime_seconds']);
57
                    $getid3->info['audio']['codec']   = $this->RealAudioCodecFourCClookup($getid3->info['real']['old_ra_header']['fourcc'], $getid3->info['audio']['bitrate']);
58
59
                    foreach ($getid3->info['real']['old_ra_header']['comments'] as $key => $value_array) {
60
                        if (strlen(trim($value_array[0])) > 0) {
61
                            $getid3->info['real']['comments'][$key][] = trim($value_array[0]);
62
                        }
63
                    }
64
                    return true;
65
                }
66
67
                throw new getid3_exception('There was a problem parsing this RealAudio file. Please submit it for analysis to http://www.getid3.org/upload/ or [email protected]');
68
            }
69
70
            $getid3->info['real']['chunks'][$chunk_counter] = [];
71
            $info_real_chunks_current_chunk                 = &$getid3->info['real']['chunks'][$chunk_counter];
72
73
            $info_real_chunks_current_chunk['name']   = $chunk_name;
74
            $info_real_chunks_current_chunk['offset'] = ftell($getid3->fp) - 8;
75
            $info_real_chunks_current_chunk['length'] = $chunk_size;
76
77
            if (($info_real_chunks_current_chunk['offset'] + $info_real_chunks_current_chunk['length']) > $getid3->info['avdataend']) {
78
                $getid3->warning('Chunk "' . $info_real_chunks_current_chunk['name'] . '" at offset ' . $info_real_chunks_current_chunk['offset'] . ' claims to be ' . $info_real_chunks_current_chunk['length'] . ' bytes long, which is beyond end of file');
79
                return false;
80
            }
81
82
            if ($chunk_size > (getid3::FREAD_BUFFER_SIZE + 8)) {
83
                $chunk_data .= fread($getid3->fp, getid3::FREAD_BUFFER_SIZE - 8);
84
                fseek($getid3->fp, $info_real_chunks_current_chunk['offset'] + $chunk_size, SEEK_SET);
85
            } elseif (($chunk_size - 8) > 0) {
86
                $chunk_data .= fread($getid3->fp, $chunk_size - 8);
87
            }
88
            $offset = 8;
89
90
            switch ($chunk_name) {
91
                case '.RMF': // RealMedia File Header
92
93
                    $info_real_chunks_current_chunk['object_version'] = getid3_lib::BigEndian2Int(substr($chunk_data, $offset, 2));
94
                    $offset                                           += 2;
95
96
                    switch ($info_real_chunks_current_chunk['object_version']) {
97
                        case 0:
98
                            $info_real_chunks_current_chunk['file_version'] = getid3_lib::BigEndian2Int(substr($chunk_data, $offset, 4));
99
                            $offset                                         += 4;
100
101
                            $info_real_chunks_current_chunk['headers_count'] = getid3_lib::BigEndian2Int(substr($chunk_data, $offset, 4));
102
                            $offset                                          += 4;
103
                            break;
104
105
                        default:
106
                            //$getid3->warning('Expected .RMF-object_version to be "0", actual value is "'.$info_real_chunks_current_chunk['object_version'].'" (should not be a problem)';
107
                            break;
108
                    }
109
                    break;
110
111
                case 'PROP': // Properties Header
112
113
                    $info_real_chunks_current_chunk['object_version'] = getid3_lib::BigEndian2Int(substr($chunk_data, $offset, 2));
114
                    $offset                                           += 2;
115
116
                    if (0 == $info_real_chunks_current_chunk['object_version']) {
117
                        getid3_lib::ReadSequence(
118
                            'BigEndian2Int',
119
                            $info_real_chunks_current_chunk,
120
                            $chunk_data,
121
                            $offset,
122
                            [
123
                                'max_bit_rate'    => 4,
124
                                'avg_bit_rate'    => 4,
125
                                'max_packet_size' => 4,
126
                                'avg_packet_size' => 4,
127
                                'num_packets'     => 4,
128
                                'duration'        => 4,
129
                                'preroll'         => 4,
130
                                'index_offset'    => 4,
131
                                'data_offset'     => 4,
132
                                'num_streams'     => 2,
133
                                'flags_raw'       => 2
134
                            ]
135
                        );
136
                        $offset += 40;
137
138
                        $getid3->info['playtime_seconds'] = $info_real_chunks_current_chunk['duration'] / 1000;
139
                        if ($info_real_chunks_current_chunk['duration'] > 0) {
140
                            $getid3->info['bitrate'] += $info_real_chunks_current_chunk['avg_bit_rate'];
141
                        }
142
143
                        $info_real_chunks_current_chunk['flags']['save_enabled']   = (bool)($info_real_chunks_current_chunk['flags_raw'] & 0x0001);
144
                        $info_real_chunks_current_chunk['flags']['perfect_play']   = (bool)($info_real_chunks_current_chunk['flags_raw'] & 0x0002);
145
                        $info_real_chunks_current_chunk['flags']['live_broadcast'] = (bool)($info_real_chunks_current_chunk['flags_raw'] & 0x0004);
146
                    }
147
                    break;
148
149
                case 'MDPR': // Media Properties Header
150
151
                    $info_real_chunks_current_chunk['object_version'] = getid3_lib::BigEndian2Int(substr($chunk_data, $offset, 2));
152
                    $offset                                           += 2;
153
154
                    if (0 == $info_real_chunks_current_chunk['object_version']) {
155
                        getid3_lib::ReadSequence(
156
                            'BigEndian2Int',
157
                            $info_real_chunks_current_chunk,
158
                            $chunk_data,
159
                            $offset,
160
                            [
161
                                'stream_number'    => 2,
162
                                'max_bit_rate'     => 4,
163
                                'avg_bit_rate'     => 4,
164
                                'max_packet_size'  => 4,
165
                                'avg_packet_size'  => 4,
166
                                'start_time'       => 4,
167
                                'preroll'          => 4,
168
                                'duration'         => 4,
169
                                'stream_name_size' => 1
170
                            ]
171
                        );
172
                        $offset += 31;
173
174
                        $info_real_chunks_current_chunk['stream_name'] = substr($chunk_data, $offset, $info_real_chunks_current_chunk['stream_name_size']);
175
                        $offset                                        += $info_real_chunks_current_chunk['stream_name_size'];
176
177
                        $info_real_chunks_current_chunk['mime_type_size'] = getid3_lib::BigEndian2Int($chunk_data{$offset++});
178
179
                        $info_real_chunks_current_chunk['mime_type'] = substr($chunk_data, $offset, $info_real_chunks_current_chunk['mime_type_size']);
180
                        $offset                                      += $info_real_chunks_current_chunk['mime_type_size'];
181
182
                        $info_real_chunks_current_chunk['type_specific_len'] = getid3_lib::BigEndian2Int(substr($chunk_data, $offset, 4));
183
                        $offset                                              += 4;
184
185
                        $info_real_chunks_current_chunk['type_specific_data'] = substr($chunk_data, $offset, $info_real_chunks_current_chunk['type_specific_len']);
186
                        $offset                                               += $info_real_chunks_current_chunk['type_specific_len'];
187
188
                        $info_real_chunks_current_chunk_typespecificdata = &$info_real_chunks_current_chunk['type_specific_data'];
189
190
                        switch ($info_real_chunks_current_chunk['mime_type']) {
191
                            case 'video/x-pn-realvideo':
192
                            case 'video/x-pn-multirate-realvideo':
193
                                // http://www.freelists.org/archives/matroska-devel/07-2003/msg00010.html
194
195
                                $info_real_chunks_current_chunk['video_info'] = [];
196
                                $info_real_chunks_current_chunk_video_info    = &$info_real_chunks_current_chunk['video_info'];
197
198
                                getid3_lib::ReadSequence(
199
                                    'BigEndian2Int',
200
                                    $info_real_chunks_current_chunk_video_info,
201
                                    $info_real_chunks_current_chunk_typespecificdata,
202
                                    0,
203
                                    [
204
                                        'dwSize'            => 4,
205
                                        'fourcc1'           => -4,
206
                                        'fourcc2'           => -4,
207
                                        'width'             => 2,
208
                                        'height'            => 2,
209
                                        'bits_per_sample'   => 2,
210
                                        'IGNORE-unknown1'   => 2,
211
                                        'IGNORE-unknown2'   => 2,
212
                                        'frames_per_second' => 2,
213
                                        'IGNORE-unknown3'   => 2,
214
                                        'IGNORE-unknown4'   => 2,
215
                                        'IGNORE-unknown5'   => 2,
216
                                        'IGNORE-unknown6'   => 2,
217
                                        'IGNORE-unknown7'   => 2,
218
                                        'IGNORE-unknown8'   => 2,
219
                                        'IGNORE-unknown9'   => 2
220
                                    ]
221
                                );
222
223
                                $info_real_chunks_current_chunk_video_info['codec'] = getid3_riff::RIFFfourccLookup($info_real_chunks_current_chunk_video_info['fourcc2']);
224
225
                                $getid3->info['video']['resolution_x']    = $info_real_chunks_current_chunk_video_info['width'];
226
                                $getid3->info['video']['resolution_y']    = $info_real_chunks_current_chunk_video_info['height'];
227
                                $getid3->info['video']['frame_rate']      = (float)$info_real_chunks_current_chunk_video_info['frames_per_second'];
228
                                $getid3->info['video']['codec']           = $info_real_chunks_current_chunk_video_info['codec'];
229
                                $getid3->info['video']['bits_per_sample'] = $info_real_chunks_current_chunk_video_info['bits_per_sample'];
230
                                break;
231
232
                            case 'audio/x-pn-realaudio':
233
                            case 'audio/x-pn-multirate-realaudio':
234
235
                                $this->ParseOldRAheader($info_real_chunks_current_chunk_typespecificdata, $info_real_chunks_current_chunk['parsed_audio_data']);
236
237
                                $getid3->info['audio']['sample_rate']     = $info_real_chunks_current_chunk['parsed_audio_data']['sample_rate'];
238
                                $getid3->info['audio']['bits_per_sample'] = $info_real_chunks_current_chunk['parsed_audio_data']['bits_per_sample'];
239
                                $getid3->info['audio']['channels']        = $info_real_chunks_current_chunk['parsed_audio_data']['channels'];
240
241
                                if (!empty($getid3->info['audio']['dataformat'])) {
242
                                    foreach ($getid3->info['audio'] as $key => $value) {
243
                                        if ('streams' != $key) {
244
                                            $getid3->info['audio']['streams'][$info_real_chunks_current_chunk['stream_number']][$key] = $value;
245
                                        }
246
                                    }
247
                                }
248
                                break;
249
250
                            case 'logical-fileinfo':
251
252
                                $info_real_chunks_current_chunk['logical_fileinfo']['logical_fileinfo_length'] = getid3_lib::BigEndian2Int(substr($info_real_chunks_current_chunk_typespecificdata, 0, 4));
253
                                // $info_real_chunks_current_chunk['logical_fileinfo']['IGNORE-unknown1']             = getid3_lib::BigEndian2Int(substr($info_real_chunks_current_chunk_typespecificdata, 4, 4));
254
                                $info_real_chunks_current_chunk['logical_fileinfo']['num_tags'] = getid3_lib::BigEndian2Int(substr($info_real_chunks_current_chunk_typespecificdata, 8, 4));
255
                                // $info_real_chunks_current_chunk['logical_fileinfo']['IGNORE-unknown2']             = getid3_lib::BigEndian2Int(substr($info_real_chunks_current_chunk_typespecificdata, 12, 4));
256
                                break;
257
                        }
258
259
                        if (empty($getid3->info['playtime_seconds'])) {
260
                            $getid3->info['playtime_seconds'] = max($getid3->info['playtime_seconds'], ($info_real_chunks_current_chunk['duration'] + $info_real_chunks_current_chunk['start_time']) / 1000);
261
                        }
262
263
                        if ($info_real_chunks_current_chunk['duration'] > 0) {
264
                            switch ($info_real_chunks_current_chunk['mime_type']) {
265
                                case 'audio/x-pn-realaudio':
266
                                case 'audio/x-pn-multirate-realaudio':
267
268
                                    $getid3->info['audio']['bitrate']    = (isset($getid3->info['audio']['bitrate']) ? $getid3->info['audio']['bitrate'] : 0) + $info_real_chunks_current_chunk['avg_bit_rate'];
269
                                    $getid3->info['audio']['codec']      = $this->RealAudioCodecFourCClookup($info_real_chunks_current_chunk['parsed_audio_data']['fourcc'], $getid3->info['audio']['bitrate']);
270
                                    $getid3->info['audio']['dataformat'] = 'real';
271
                                    $getid3->info['audio']['lossless']   = false;
272
                                    break;
273
274
                                case 'video/x-pn-realvideo':
275
                                case 'video/x-pn-multirate-realvideo':
276
277
                                    $getid3->info['video']['bitrate']            = (isset($getid3->info['video']['bitrate']) ? $getid3->info['video']['bitrate'] : 0) + $info_real_chunks_current_chunk['avg_bit_rate'];
278
                                    $getid3->info['video']['bitrate_mode']       = 'cbr';
279
                                    $getid3->info['video']['dataformat']         = 'real';
280
                                    $getid3->info['video']['lossless']           = false;
281
                                    $getid3->info['video']['pixel_aspect_ratio'] = (float)1;
282
                                    break;
283
284
                                case 'audio/x-ralf-mpeg4-generic':
285
286
                                    $getid3->info['audio']['bitrate']    = (isset($getid3->info['audio']['bitrate']) ? $getid3->info['audio']['bitrate'] : 0) + $info_real_chunks_current_chunk['avg_bit_rate'];
287
                                    $getid3->info['audio']['codec']      = 'RealAudio Lossless';
288
                                    $getid3->info['audio']['dataformat'] = 'real';
289
                                    $getid3->info['audio']['lossless']   = true;
290
                                    break;
291
                            }
292
293
                            $getid3->info['bitrate'] = (isset($getid3->info['video']['bitrate']) ? $getid3->info['video']['bitrate'] : 0) + (isset($getid3->info['audio']['bitrate']) ? $getid3->info['audio']['bitrate'] : 0);
294
                        }
295
                    }
296
                    break;
297
298
                case 'CONT': // Content Description Header (text comments)
299
300
                    $info_real_chunks_current_chunk['object_version'] = getid3_lib::BigEndian2Int(substr($chunk_data, $offset, 2));
301
                    $offset                                           += 2;
302
303
                    if (0 == $info_real_chunks_current_chunk['object_version']) {
304
                        $info_real_chunks_current_chunk['title_len'] = getid3_lib::BigEndian2Int(substr($chunk_data, $offset, 2));
305
                        $offset                                      += 2;
306
307
                        $info_real_chunks_current_chunk['title'] = (string)substr($chunk_data, $offset, $info_real_chunks_current_chunk['title_len']);
308
                        $offset                                  += $info_real_chunks_current_chunk['title_len'];
309
310
                        $info_real_chunks_current_chunk['artist_len'] = getid3_lib::BigEndian2Int(substr($chunk_data, $offset, 2));
311
                        $offset                                       += 2;
312
313
                        $info_real_chunks_current_chunk['artist'] = (string)substr($chunk_data, $offset, $info_real_chunks_current_chunk['artist_len']);
314
                        $offset                                   += $info_real_chunks_current_chunk['artist_len'];
315
316
                        $info_real_chunks_current_chunk['copyright_len'] = getid3_lib::BigEndian2Int(substr($chunk_data, $offset, 2));
317
                        $offset                                          += 2;
318
319
                        $info_real_chunks_current_chunk['copyright'] = (string)substr($chunk_data, $offset, $info_real_chunks_current_chunk['copyright_len']);
320
                        $offset                                      += $info_real_chunks_current_chunk['copyright_len'];
321
322
                        $info_real_chunks_current_chunk['comment_len'] = getid3_lib::BigEndian2Int(substr($chunk_data, $offset, 2));
323
                        $offset                                        += 2;
324
325
                        $info_real_chunks_current_chunk['comment'] = (string)substr($chunk_data, $offset, $info_real_chunks_current_chunk['comment_len']);
326
                        $offset                                    += $info_real_chunks_current_chunk['comment_len'];
327
328
                        foreach (['title' => 'title', 'artist' => 'artist', 'copyright' => 'copyright', 'comment' => 'comment'] as $key => $val) {
329
                            if ($info_real_chunks_current_chunk[$key]) {
330
                                $getid3->info['real']['comments'][$val][] = trim($info_real_chunks_current_chunk[$key]);
331
                            }
332
                        }
333
                    }
334
                    break;
335
336
                case 'DATA': // Data Chunk Header
337
338
                    // do nothing
339
                    break;
340
341
                case 'INDX': // Index Section Header
342
343
                    $info_real_chunks_current_chunk['object_version'] = getid3_lib::BigEndian2Int(substr($chunk_data, $offset, 2));
344
                    $offset                                           += 2;
345
346
                    if (0 == $info_real_chunks_current_chunk['object_version']) {
347
                        getid3_lib::ReadSequence(
348
                            'BigEndian2Int',
349
                            $info_real_chunks_current_chunk,
350
                            $chunk_data,
351
                            $offset,
352
                            [
353
                                'num_indices'       => 4,
354
                                'stream_number'     => 2,
355
                                'next_index_header' => 4
356
                            ]
357
                        );
358
                        $offset += 10;
359
360
                        if (0 == $info_real_chunks_current_chunk['next_index_header']) {
361
                            // last index chunk found, ignore rest of file
362
                            break 2;
363
                        } else {
364
                            // non-last index chunk, seek to next index chunk (skipping actual index data)
365
                            fseek($getid3->fp, $info_real_chunks_current_chunk['next_index_header'], SEEK_SET);
366
                        }
367
                    }
368
                    break;
369
370
                default:
371
                    $getid3->warning('Unhandled RealMedia chunk "' . $chunk_name . '" at offset ' . $info_real_chunks_current_chunk['offset']);
372
                    break;
373
            }
374
            $chunk_counter++;
375
        }
376
377
        if (!empty($getid3->info['audio']['streams'])) {
378
            $getid3->info['audio']['bitrate'] = 0;
379
380
            foreach ($getid3->info['audio']['streams'] as $key => $value_array) {
381
                $getid3->info['audio']['bitrate'] += $value_array['bitrate'];
382
            }
383
        }
384
385
        return true;
386
    }
387
388
    public static function ParseOldRAheader($old_ra_header_data, &$parsed_array)
389
    {
390
        // http://www.freelists.org/archives/matroska-devel/07-2003/msg00010.html
391
392
        $parsed_array          = [];
393
        $parsed_array['magic'] = substr($old_ra_header_data, 0, 4);
394
395
        if ($parsed_array['magic'] != '.ra' . "\xFD") {
396
            return false;
397
        }
398
399
        $parsed_array['version1'] = getid3_lib::BigEndian2Int(substr($old_ra_header_data, 4, 2));
400
401
        if ($parsed_array['version1'] < 3) {
402
            return false;
403
        }
404
405
        if (3 == $parsed_array['version1']) {
406
            $parsed_array['fourcc1']         = '.ra3';
407
            $parsed_array['bits_per_sample'] = 16;   // hard-coded for old versions?
408
            $parsed_array['sample_rate']     = 8000; // hard-coded for old versions?
409
410
            getid3_lib::ReadSequence(
411
                'BigEndian2Int',
412
                $parsed_array,
413
                $old_ra_header_data,
414
                6,
415
                [
416
                    'header_size'      => 2,
417
                    'channels'         => 2, // always 1 (?)
418
                    'IGNORE-unknown1'  => 2,
419
                    'IGNORE-unknown2'  => 2,
420
                    'IGNORE-unknown3'  => 2,
421
                    'bytes_per_minute' => 2,
422
                    'audio_bytes'      => 4,
423
                ]
424
            );
425
426
            $parsed_array['comments_raw'] = substr($old_ra_header_data, 22, $parsed_array['header_size'] - 22 + 1); // not including null terminator
427
428
            $comment_offset = 0;
429
430
            foreach (['title', 'artist', 'copyright'] as $name) {
431
                $comment_length                    = getid3_lib::BigEndian2Int($parsed_array['comments_raw']{$comment_offset++});
432
                $parsed_array['comments'][$name][] = substr($parsed_array['comments_raw'], $comment_offset, $comment_length);
433
                $comment_offset                    += $comment_length;
434
            }
435
436
            $comment_offset++; // final null terminator (?)
437
            $comment_offset++; // fourcc length (?) should be 4
438
439
            $parsed_array['fourcc'] = substr($old_ra_header_data, 23 + $comment_offset, 4);
440
        } elseif ($parsed_array['version1'] <= 5) {
441
            getid3_lib::ReadSequence(
442
                'BigEndian2Int',
443
                $parsed_array,
444
                $old_ra_header_data,
445
                6,
446
                [
447
                    'IGNORE-unknown1'  => 2,
448
                    'fourcc1'          => -4,
449
                    'file_size'        => 4,
450
                    'version2'         => 2,
451
                    'header_size'      => 4,
452
                    'codec_flavor_id'  => 2,
453
                    'coded_frame_size' => 4,
454
                    'audio_bytes'      => 4,
455
                    'bytes_per_minute' => 4,
456
                    'IGNORE-unknown5'  => 4,
457
                    'sub_packet_h'     => 2,
458
                    'frame_size'       => 2,
459
                    'sub_packet_size'  => 2,
460
                    'IGNORE-unknown6'  => 2
461
                ]
462
            );
463
464
            switch ($parsed_array['version1']) {
465
                case 4:
466
467
                    getid3_lib::ReadSequence(
468
                        'BigEndian2Int',
469
                        $parsed_array,
470
                        $old_ra_header_data,
471
                        48,
472
                        [
473
                            'sample_rate'      => 2,
474
                            'IGNORE-unknown8'  => 2,
475
                            'bits_per_sample'  => 2,
476
                            'channels'         => 2,
477
                            'length_fourcc2'   => 1,
478
                            'fourcc2'          => -4,
479
                            'length_fourcc3'   => 1,
480
                            'fourcc3'          => -4,
481
                            'IGNORE-unknown9'  => 1,
482
                            'IGNORE-unknown10' => 2,
483
                        ]
484
                    );
485
486
                    $parsed_array['comments_raw'] = substr($old_ra_header_data, 69, $parsed_array['header_size'] - 69 + 16);
487
488
                    $comment_offset = 0;
489
490
                    foreach (['title', 'artist', 'copyright'] as $name) {
491
                        $comment_length                    = getid3_lib::BigEndian2Int($parsed_array['comments_raw']{$comment_offset++});
492
                        $parsed_array['comments'][$name][] = substr($parsed_array['comments_raw'], $comment_offset, $comment_length);
493
                        $comment_offset                    += $comment_length;
494
                    }
495
                    break;
496
497
                case 5:
498
499
                    getid3_lib::ReadSequence(
500
                        'BigEndian2Int',
501
                        $parsed_array,
502
                        $old_ra_header_data,
503
                        48,
504
                        [
505
                            'sample_rate'     => 4,
506
                            'sample_rate2'    => 4,
507
                            'bits_per_sample' => 4,
508
                            'channels'        => 2,
509
                            'genr'            => -4,
510
                            'fourcc3'         => -4,
511
                        ]
512
                    );
513
                    $parsed_array['comments'] = [];
514
                    break;
515
            }
516
517
            $parsed_array['fourcc'] = $parsed_array['fourcc3'];
518
        }
519
520
        foreach ($parsed_array['comments'] as $key => $value) {
521
            if (false === $parsed_array['comments'][$key][0]) {
522
                $parsed_array['comments'][$key][0] = '';
523
            }
524
        }
525
526
        return true;
527
    }
528
529
    public static function RealAudioCodecFourCClookup($fourcc, $bitrate)
530
    {
531
        // http://www.its.msstate.edu/net/real/reports/config/tags.stats
532
        // http://www.freelists.org/archives/matroska-devel/06-2003/fullthread18.html
533
534
        static $lookup;
535
536
        if (empty($lookup)) {
537
            $lookup['14_4'][8000]  = 'RealAudio v2 (14.4kbps)';
538
            $lookup['14.4'][8000]  = 'RealAudio v2 (14.4kbps)';
539
            $lookup['lpcJ'][8000]  = 'RealAudio v2 (14.4kbps)';
540
            $lookup['28_8'][15200] = 'RealAudio v2 (28.8kbps)';
541
            $lookup['28.8'][15200] = 'RealAudio v2 (28.8kbps)';
542
            $lookup['sipr'][4933]  = 'RealAudio v4 (5kbps Voice)';
543
            $lookup['sipr'][6444]  = 'RealAudio v4 (6.5kbps Voice)';
544
            $lookup['sipr'][8444]  = 'RealAudio v4 (8.5kbps Voice)';
545
            $lookup['sipr'][16000] = 'RealAudio v4 (16kbps Wideband)';
546
            $lookup['dnet'][8000]  = 'RealAudio v3 (8kbps Music)';
547
            $lookup['dnet'][16000] = 'RealAudio v3 (16kbps Music Low Response)';
548
            $lookup['dnet'][15963] = 'RealAudio v3 (16kbps Music Mid/High Response)';
549
            $lookup['dnet'][20000] = 'RealAudio v3 (20kbps Music Stereo)';
550
            $lookup['dnet'][32000] = 'RealAudio v3 (32kbps Music Mono)';
551
            $lookup['dnet'][31951] = 'RealAudio v3 (32kbps Music Stereo)';
552
            $lookup['dnet'][39965] = 'RealAudio v3 (40kbps Music Mono)';
553
            $lookup['dnet'][40000] = 'RealAudio v3 (40kbps Music Stereo)';
554
            $lookup['dnet'][79947] = 'RealAudio v3 (80kbps Music Mono)';
555
            $lookup['dnet'][80000] = 'RealAudio v3 (80kbps Music Stereo)';
556
557
            $lookup['dnet'][0] = 'RealAudio v3';
558
            $lookup['sipr'][0] = 'RealAudio v4';
559
            $lookup['cook'][0] = 'RealAudio G2';
560
            $lookup['atrc'][0] = 'RealAudio 8';
561
        }
562
563
        $round_bitrate = intval(round($bitrate));
564
565
        if (isset($lookup[$fourcc][$round_bitrate])) {
566
            return $lookup[$fourcc][$round_bitrate];
567
        }
568
569
        if (isset($lookup[$fourcc][0])) {
570
            return $lookup[$fourcc][0];
571
        }
572
573
        return $fourcc;
574
    }
575
576
}
577
578
579