getid3_riff::DateMac2Unix()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 5
rs 10
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.riff.php                                          |
18
// | module for analyzing RIFF files:                                     |
19
// |    Wave, AVI, AIFF/AIFC, (MP3,AC3)/RIFF, Wavpack3, 8SVX              |
20
// | dependencies: module.audio.mp3.php (optional)                        |
21
// |               module.audio.ac3.php (optional)                        |
22
// |               module.audio.dts.php (optional)                        |
23
// |               module.audio-video.mpeg.php (optional)                 |
24
// +----------------------------------------------------------------------+
25
//
26
// $Id: module.audio-video.riff.php,v 1.10 2006/12/03 20:13:17 ah Exp $
27
28
class getid3_riff extends getid3_handler
29
{
30
31
    private $endian_function = 'LittleEndian2Int';
32
33
    public function Analyze()
34
    {
35
        $getid3 = $this->getid3;
36
37
        $getid3->info['riff']['raw'] = [];
38
        $info_riff                   = &$getid3->info['riff'];
39
        $info_riff_raw               = &$info_riff['raw'];
40
        $info_audio                  = &$getid3->info['audio'];
41
        $info_video                  = &$getid3->info['video'];
42
        $info_avdataoffset           = &$getid3->info['avdataoffset'];
43
        $info_avdataend              = &$getid3->info['avdataend'];
44
        $info_audio_dataformat       = &$info_audio['dataformat'];
45
        $info_riff_audio             = &$info_riff['audio'];
46
        $info_riff_video             = &$info_riff['video'];
47
48
        $original['avdataend'] = $info_avdataend;
0 ignored issues
show
Comprehensibility Best Practice introduced by
$original was never initialized. Although not strictly required by PHP, it is generally a good practice to add $original = array(); before regardless.
Loading history...
49
50
        $this->fseek($info_avdataoffset, SEEK_SET);
51
        $riff_header = $this->fread(12);
52
53
        $riff_sub_type = substr($riff_header, 8, 4);
54
55
        switch (substr($riff_header, 0, 4)) {
56
            case 'FORM':
57
                $getid3->info['fileformat'] = 'aiff';
58
                $this->endian_function      = 'BigEndian2Int';
59
                $riff_header_size           = getid3_lib::BigEndian2Int(substr($riff_header, 4, 4));
60
                $info_riff[$riff_sub_type]  = $this->ParseRIFF($info_avdataoffset + 12, $info_avdataoffset + $riff_header_size);
61
                $info_riff['header_size']   = $riff_header_size;
62
                break;
63
64
            case 'RIFF':
65
            case 'SDSS':  // SDSS is identical to RIFF, just renamed. Used by SmartSound QuickTracks (www.smartsound.com)
66
            case 'RMP3':  // RMP3 is identical to RIFF, just renamed. Used by [unknown program] when creating RIFF-MP3s
67
68
                if ('RMP3' == $riff_sub_type) {
69
                    $riff_sub_type = 'WAVE';
70
                }
71
72
                $getid3->info['fileformat'] = 'riff';
73
                $this->endian_function      = 'LittleEndian2Int';
74
                $riff_header_size           = getid3_lib::LittleEndian2Int(substr($riff_header, 4, 4));
75
                $info_riff[$riff_sub_type]  = $this->ParseRIFF($info_avdataoffset + 12, $info_avdataoffset + $riff_header_size);
76
                $info_riff['header_size']   = $riff_header_size;
77
                if ('WAVE' == $riff_sub_type) {
78
                    $info_riff_wave = &$info_riff['WAVE'];
79
                }
80
                break;
81
82
            default:
83
                throw new getid3_exception('Cannot parse RIFF (this is maybe not a RIFF / WAV / AVI file?) - expecting "FORM|RIFF|SDSS|RMP3" found "' . $riff_sub_type . '" instead');
84
        }
85
86
        $endian_function = $this->endian_function;
87
88
        $stream_index = 0;
89
        switch ($riff_sub_type) {
90
            case 'WAVE':
91
92
                if (empty($info_audio['bitrate_mode'])) {
93
                    $info_audio['bitrate_mode'] = 'cbr';
94
                }
95
96
                if (empty($info_audio_dataformat)) {
97
                    $info_audio_dataformat = 'wav';
98
                }
99
100
                if (isset($info_riff_wave['data'][0]['offset'])) {
101
                    $info_avdataoffset = $info_riff_wave['data'][0]['offset'] + 8;
102
                    $info_avdataend    = $info_avdataoffset + $info_riff_wave['data'][0]['size'];
103
                }
104
105
                if (isset($info_riff_wave['fmt '][0]['data'])) {
106
                    $info_riff_audio[$stream_index] = getid3_riff::RIFFparseWAVEFORMATex($info_riff_wave['fmt '][0]['data']);
107
                    $info_audio['wformattag']       = $info_riff_audio[$stream_index]['raw']['wFormatTag'];
108
                    $info_riff_raw['fmt ']          = $info_riff_audio[$stream_index]['raw'];
109
                    unset($info_riff_audio[$stream_index]['raw']);
110
                    $info_audio['streams'][$stream_index] = $info_riff_audio[$stream_index];
111
112
                    $info_audio = getid3_riff::array_merge_noclobber($info_audio, $info_riff_audio[$stream_index]);
113
                    if ('unknown: 0x' == substr($info_audio['codec'], 0, strlen('unknown: 0x'))) {
114
                        $getid3->warning('Audio codec = ' . $info_audio['codec']);
115
                    }
116
                    $info_audio['bitrate'] = $info_riff_audio[$stream_index]['bitrate'];
117
118
                    $getid3->info['playtime_seconds'] = (float)((($info_avdataend - $info_avdataoffset) * 8) / $info_audio['bitrate']);
119
120
                    $info_audio['lossless'] = false;
121
122
                    if (isset($info_riff_wave['data'][0]['offset']) && isset($info_riff_raw['fmt ']['wFormatTag'])) {
123
                        switch ($info_riff_raw['fmt ']['wFormatTag']) {
124
                            case 0x0001:  // PCM
125
                                $info_audio['lossless'] = true;
126
                                break;
127
128
                            case 0x2000:  // AC-3
129
                                $info_audio_dataformat = 'ac3';
130
                                break;
131
132
                            default:
133
                                // do nothing
134
                                break;
135
                        }
136
                    }
137
138
                    $info_audio['streams'][$stream_index]['wformattag']   = $info_audio['wformattag'];
139
                    $info_audio['streams'][$stream_index]['bitrate_mode'] = $info_audio['bitrate_mode'];
140
                    $info_audio['streams'][$stream_index]['lossless']     = $info_audio['lossless'];
141
                    $info_audio['streams'][$stream_index]['dataformat']   = $info_audio_dataformat;
142
                }
143
144
                if (isset($info_riff_wave['rgad'][0]['data'])) {
145
                    // shortcuts
146
                    $rgadData                 = &$info_riff_wave['rgad'][0]['data'];
147
                    $info_riff_raw['rgad']    = ['track' => [], 'album' => []];
148
                    $info_riff_raw_rgad       = &$info_riff_raw['rgad'];
149
                    $info_riff_raw_rgad_track = &$info_riff_raw_rgad['track'];
150
                    $info_riff_raw_rgad_album = &$info_riff_raw_rgad['album'];
151
152
                    $info_riff_raw_rgad['fPeakAmplitude']      = getid3_riff::BigEndian2Float(strrev(substr($rgadData, 0, 4)));   // LittleEndian2Float()
0 ignored issues
show
Bug Best Practice introduced by
The method getid3_riff::BigEndian2Float() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

152
                    /** @scrutinizer ignore-call */ 
153
                    $info_riff_raw_rgad['fPeakAmplitude']      = getid3_riff::BigEndian2Float(strrev(substr($rgadData, 0, 4)));   // LittleEndian2Float()
Loading history...
153
                    $info_riff_raw_rgad['nRadioRgAdjust']      = getid3_lib::$endian_function(substr($rgadData, 4, 2));
154
                    $info_riff_raw_rgad['nAudiophileRgAdjust'] = getid3_lib::$endian_function(substr($rgadData, 6, 2));
155
156
                    $n_track_rg_adjust_bit_string = str_pad(decbin($info_riff_raw_rgad['nRadioRgAdjust']), 16, '0', STR_PAD_LEFT);
157
                    $n_album_rg_adjust_bit_string = str_pad(decbin($info_riff_raw_rgad['nAudiophileRgAdjust']), 16, '0', STR_PAD_LEFT);
158
159
                    $info_riff_raw_rgad_track['name']       = bindec(substr($n_track_rg_adjust_bit_string, 0, 3));
160
                    $info_riff_raw_rgad_track['originator'] = bindec(substr($n_track_rg_adjust_bit_string, 3, 3));
161
                    $info_riff_raw_rgad_track['signbit']    = bindec($n_track_rg_adjust_bit_string[6]);
162
                    $info_riff_raw_rgad_track['adjustment'] = bindec(substr($n_track_rg_adjust_bit_string, 7, 9));
163
                    $info_riff_raw_rgad_album['name']       = bindec(substr($n_album_rg_adjust_bit_string, 0, 3));
164
                    $info_riff_raw_rgad_album['originator'] = bindec(substr($n_album_rg_adjust_bit_string, 3, 3));
165
                    $info_riff_raw_rgad_album['signbit']    = bindec($n_album_rg_adjust_bit_string[6]);
166
                    $info_riff_raw_rgad_album['adjustment'] = bindec(substr($n_album_rg_adjust_bit_string, 7, 9));
167
168
                    $info_riff['rgad']['peakamplitude'] = $info_riff_raw_rgad['fPeakAmplitude'];
169
                    if ((0 != $info_riff_raw_rgad_track['name']) && (0 != $info_riff_raw_rgad_track['originator'])) {
170
                        $info_riff['rgad']['track']['name']       = getid3_lib_replaygain::NameLookup($info_riff_raw_rgad_track['name']);
171
                        $info_riff['rgad']['track']['originator'] = getid3_lib_replaygain::OriginatorLookup($info_riff_raw_rgad_track['originator']);
172
                        $info_riff['rgad']['track']['adjustment'] = getid3_lib_replaygain::AdjustmentLookup($info_riff_raw_rgad_track['adjustment'], $info_riff_raw_rgad_track['signbit']);
173
                    }
174
175
                    if ((0 != $info_riff_raw_rgad_album['name']) && (0 != $info_riff_raw_rgad_album['originator'])) {
176
                        $info_riff['rgad']['album']['name']       = getid3_lib_replaygain::NameLookup($info_riff_raw_rgad_album['name']);
177
                        $info_riff['rgad']['album']['originator'] = getid3_lib_replaygain::OriginatorLookup($info_riff_raw_rgad_album['originator']);
178
                        $info_riff['rgad']['album']['adjustment'] = getid3_lib_replaygain::AdjustmentLookup($info_riff_raw_rgad_album['adjustment'], $info_riff_raw_rgad_album['signbit']);
179
                    }
180
                }
181
182
                if (isset($info_riff_wave['fact'][0]['data'])) {
183
                    $info_riff_raw['fact']['NumberOfSamples'] = getid3_lib::$endian_function(substr($info_riff_wave['fact'][0]['data'], 0, 4));
184
185
                    // This should be a good way of calculating exact playtime, but some sample files have had incorrect number of samples, so cannot use this method
186
                    // if (!empty($info_riff_raw['fmt ']['nSamplesPerSec'])) {
187
                    //     $getid3->info['playtime_seconds'] = (float)$info_riff_raw['fact']['NumberOfSamples'] / $info_riff_raw['fmt ']['nSamplesPerSec'];
188
                    // }
189
                }
190
191
                if (!empty($info_riff_raw['fmt ']['nAvgBytesPerSec'])) {
192
                    $info_audio['bitrate'] = (int)$info_riff_raw['fmt ']['nAvgBytesPerSec'] * 8;
193
                }
194
195
                if (isset($info_riff_wave['bext'][0]['data'])) {
196
                    $info_riff_wave_bext_0 = &$info_riff_wave['bext'][0];
197
198
                    getid3_lib::ReadSequence(
199
                        'LittleEndian2Int',
200
                        $info_riff_wave_bext_0,
201
                        $info_riff_wave_bext_0['data'],
202
                        0,
203
                        [
204
                            'title'          => -256,
205
                            'author'         => -32,
206
                            'reference'      => -32,
207
                            'origin_date'    => -10,
208
                            'origin_time'    => -8,
209
                            'time_reference' => 8,
210
                            'bwf_version'    => 1,
211
                            'reserved'       => 254
212
                        ]
213
                    );
214
215
                    foreach (['title', 'author', 'reference'] as $key) {
216
                        $info_riff_wave_bext_0[$key] = trim($info_riff_wave_bext_0[$key]);
217
                    }
218
219
                    $info_riff_wave_bext_0['coding_history'] = explode("\r\n", trim(substr($info_riff_wave_bext_0['data'], 601)));
220
221
                    $info_riff_wave_bext_0['origin_date_unix'] = gmmktime(
222
                        substr($info_riff_wave_bext_0['origin_time'], 0, 2),
0 ignored issues
show
Bug introduced by
substr($info_riff_wave_b...0['origin_time'], 0, 2) of type string is incompatible with the type integer expected by parameter $hour of gmmktime(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

222
                        /** @scrutinizer ignore-type */ substr($info_riff_wave_bext_0['origin_time'], 0, 2),
Loading history...
223
                        substr($info_riff_wave_bext_0['origin_time'], 3, 2),
0 ignored issues
show
Bug introduced by
substr($info_riff_wave_b...0['origin_time'], 3, 2) of type string is incompatible with the type integer expected by parameter $minute of gmmktime(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

223
                        /** @scrutinizer ignore-type */ substr($info_riff_wave_bext_0['origin_time'], 3, 2),
Loading history...
224
                        substr($info_riff_wave_bext_0['origin_time'], 6, 2),
0 ignored issues
show
Bug introduced by
substr($info_riff_wave_b...0['origin_time'], 6, 2) of type string is incompatible with the type integer expected by parameter $second of gmmktime(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

224
                        /** @scrutinizer ignore-type */ substr($info_riff_wave_bext_0['origin_time'], 6, 2),
Loading history...
225
                        substr($info_riff_wave_bext_0['origin_date'], 5, 2),
0 ignored issues
show
Bug introduced by
substr($info_riff_wave_b...0['origin_date'], 5, 2) of type string is incompatible with the type integer expected by parameter $month of gmmktime(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

225
                        /** @scrutinizer ignore-type */ substr($info_riff_wave_bext_0['origin_date'], 5, 2),
Loading history...
226
                        substr($info_riff_wave_bext_0['origin_date'], 8, 2),
0 ignored issues
show
Bug introduced by
substr($info_riff_wave_b...0['origin_date'], 8, 2) of type string is incompatible with the type integer expected by parameter $day of gmmktime(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

226
                        /** @scrutinizer ignore-type */ substr($info_riff_wave_bext_0['origin_date'], 8, 2),
Loading history...
227
                        substr($info_riff_wave_bext_0['origin_date'], 0, 4)
0 ignored issues
show
Bug introduced by
substr($info_riff_wave_b...0['origin_date'], 0, 4) of type string is incompatible with the type integer expected by parameter $year of gmmktime(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

227
                        /** @scrutinizer ignore-type */ substr($info_riff_wave_bext_0['origin_date'], 0, 4)
Loading history...
228
                    );
229
230
                    $info_riff['comments']['author'][] = $info_riff_wave_bext_0['author'];
231
                    $info_riff['comments']['title'][]  = $info_riff_wave_bext_0['title'];
232
                }
233
234
                if (isset($info_riff_wave['MEXT'][0]['data'])) {
235
                    $info_riff_wave_mext_0 = &$info_riff_wave['MEXT'][0];
236
237
                    $info_riff_wave_mext_0['raw']['sound_information'] = getid3_lib::LittleEndian2Int(substr($info_riff_wave_mext_0['data'], 0, 2));
238
                    $info_riff_wave_mext_0['flags']['homogenous']      = (bool)($info_riff_wave_mext_0['raw']['sound_information'] & 0x0001);
239
                    if ($info_riff_wave_mext_0['flags']['homogenous']) {
240
                        $info_riff_wave_mext_0['flags']['padding']     = ($info_riff_wave_mext_0['raw']['sound_information'] & 0x0002) ? false : true;
241
                        $info_riff_wave_mext_0['flags']['22_or_44']    = (bool)($info_riff_wave_mext_0['raw']['sound_information'] & 0x0004);
242
                        $info_riff_wave_mext_0['flags']['free_format'] = (bool)($info_riff_wave_mext_0['raw']['sound_information'] & 0x0008);
243
244
                        $info_riff_wave_mext_0['nominal_frame_size'] = getid3_lib::LittleEndian2Int(substr($info_riff_wave_mext_0['data'], 2, 2));
245
                    }
246
                    $info_riff_wave_mext_0['anciliary_data_length']         = getid3_lib::LittleEndian2Int(substr($info_riff_wave_mext_0['data'], 6, 2));
247
                    $info_riff_wave_mext_0['raw']['anciliary_data_def']     = getid3_lib::LittleEndian2Int(substr($info_riff_wave_mext_0['data'], 8, 2));
248
                    $info_riff_wave_mext_0['flags']['anciliary_data_left']  = (bool)($info_riff_wave_mext_0['raw']['anciliary_data_def'] & 0x0001);
249
                    $info_riff_wave_mext_0['flags']['anciliary_data_free']  = (bool)($info_riff_wave_mext_0['raw']['anciliary_data_def'] & 0x0002);
250
                    $info_riff_wave_mext_0['flags']['anciliary_data_right'] = (bool)($info_riff_wave_mext_0['raw']['anciliary_data_def'] & 0x0004);
251
                }
252
253
                if (isset($info_riff_wave['cart'][0]['data'])) {
254
                    $info_riff_wave_cart_0 = &$info_riff_wave['cart'][0];
255
256
                    getid3_lib::ReadSequence(
257
                        'LittleEndian2Int',
258
                        $info_riff_wave_cart_0,
259
                        $info_riff_wave_cart_0['data'],
260
                        0,
261
                        [
262
                            'version'              => -4,
263
                            'title'                => -64,
264
                            'artist'               => -64,
265
                            'cut_id'               => -64,
266
                            'client_id'            => -64,
267
                            'category'             => -64,
268
                            'classification'       => -64,
269
                            'out_cue'              => -64,
270
                            'start_date'           => -10,
271
                            'start_time'           => -8,
272
                            'end_date'             => -10,
273
                            'end_time'             => -8,
274
                            'producer_app_id'      => -64,
275
                            'producer_app_version' => -64,
276
                            'user_defined_text'    => -64,
277
                        ]
278
                    );
279
280
                    foreach (['artist', 'cut_id', 'client_id', 'category', 'classification', 'out_cue', 'start_date', 'start_time', 'end_date', 'end_time', 'producer_app_id', 'producer_app_version', 'user_defined_text'] as $key) {
281
                        $info_riff_wave_cart_0[$key] = trim($info_riff_wave_cart_0[$key]);
282
                    }
283
284
                    $info_riff_wave_cart_0['zero_db_reference'] = getid3_lib::LittleEndian2Int(substr($info_riff_wave_cart_0['data'], 680, 4), true);
285
286
                    for ($i = 0; $i < 8; $i++) {
287
                        $info_riff_wave_cart_0['post_time'][$i]['usage_fourcc'] = substr($info_riff_wave_cart_0['data'], 684 + ($i * 8), 4);
288
                        $info_riff_wave_cart_0['post_time'][$i]['timer_value']  = getid3_lib::LittleEndian2Int(substr($info_riff_wave_cart_0['data'], 684 + ($i * 8) + 4, 4));
289
                    }
290
                    $info_riff_wave_cart_0['url']      = trim(substr($info_riff_wave_cart_0['data'], 748, 1024));
291
                    $info_riff_wave_cart_0['tag_text'] = explode("\r\n", trim(substr($info_riff_wave_cart_0['data'], 1772)));
292
293
                    $info_riff['comments']['artist'][] = $info_riff_wave_cart_0['artist'];
294
                    $info_riff['comments']['title'][]  = $info_riff_wave_cart_0['title'];
295
                }
296
297
                if (!isset($info_audio['bitrate']) && isset($info_riff_audio[$stream_index]['bitrate'])) {
298
                    $info_audio['bitrate']            = $info_riff_audio[$stream_index]['bitrate'];
299
                    $getid3->info['playtime_seconds'] = (float)((($info_avdataend - $info_avdataoffset) * 8) / $info_audio['bitrate']);
300
                }
301
302
                if (@$getid3->info['wavpack']) {
303
                    if (!$this->data_string_flag) {
304
                        $info_audio_dataformat      = 'wavpack';
305
                        $info_audio['bitrate_mode'] = 'vbr';
306
                        $info_audio['encoder']      = 'WavPack v' . $getid3->info['wavpack']['version'];
307
308
                        // Reset to the way it was - RIFF parsing will have messed this up
309
                        $info_avdataend        = $original['avdataend'];
310
                        $info_audio['bitrate'] = (($info_avdataend - $info_avdataoffset) * 8) / $getid3->info['playtime_seconds'];
311
312
                        $this->fseek($info_avdataoffset - 44, SEEK_SET);
313
                        $riff_data                = $this->fread(44);
314
                        $orignal_riff_header_size = getid3_lib::LittleEndian2Int(substr($riff_data, 4, 4)) + 8;
315
                        $orignal_riff_data_size   = getid3_lib::LittleEndian2Int(substr($riff_data, 40, 4)) + 44;
316
317
                        if ($orignal_riff_header_size > $orignal_riff_data_size) {
318
                            $info_avdataend -= ($orignal_riff_header_size - $orignal_riff_data_size);
319
                            $this->fseek($info_avdataend, SEEK_SET);
320
                            $riff_data .= $this->fread($orignal_riff_header_size - $orignal_riff_data_size);
321
                        }
322
323
                        // move the data chunk after all other chunks (if any)
324
                        // so that the RIFF parser doesn't see EOF when trying
325
                        // to skip over the data chunk
326
                        $riff_data = substr($riff_data, 0, 36) . substr($riff_data, 44) . substr($riff_data, 36, 8);
327
328
                        // Save audio info key
329
                        $saved_info_audio = $info_audio;
330
331
                        // Analyze riff_data 
332
                        $this->AnalyzeString($riff_data);
333
334
                        // Restore info key
335
                        $info_audio = $saved_info_audio;
336
                    }
337
                }
338
339
                if (isset($info_riff_raw['fmt ']['wFormatTag'])) {
340
                    switch ($info_riff_raw['fmt ']['wFormatTag']) {
341
                        case 0x08AE: // ClearJump LiteWave
342
                            $info_audio['bitrate_mode'] = 'vbr';
343
                            $info_audio_dataformat      = 'litewave';
344
345
                            //typedef struct tagSLwFormat {
346
                            //  WORD    m_wCompFormat;     // low byte defines compression method, high byte is compression flags
347
                            //  DWORD   m_dwScale;         // scale factor for lossy compression
348
                            //  DWORD   m_dwBlockSize;     // number of samples in encoded blocks
349
                            //  WORD    m_wQuality;        // alias for the scale factor
350
                            //  WORD    m_wMarkDistance;   // distance between marks in bytes
351
                            //  WORD    m_wReserved;
352
                            //
353
                            //  //following paramters are ignored if CF_FILESRC is not set
354
                            //  DWORD   m_dwOrgSize;       // original file size in bytes
355
                            //  WORD    m_bFactExists;     // indicates if 'fact' chunk exists in the original file
356
                            //  DWORD   m_dwRiffChunkSize; // riff chunk size in the original file
357
                            //
358
                            //  PCMWAVEFORMAT m_OrgWf;     // original wave format
359
                            // }SLwFormat, *PSLwFormat;
360
361
                            $info_riff['litewave']['raw'] = [];
362
                            $info_riff_litewave           = &$info_riff['litewave'];
363
                            $info_riff_litewave_raw       = &$info_riff_litewave['raw'];
364
365
                            getid3_lib::ReadSequence(
366
                                'LittleEndian2Int',
367
                                $info_riff_litewave_raw,
368
                                $info_riff_wave['fmt '][0]['data'],
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $info_riff_wave does not seem to be defined for all execution paths leading up to this point.
Loading history...
369
                                18,
370
                                [
371
                                    'compression_method' => 1,
372
                                    'compression_flags'  => 1,
373
                                    'm_dwScale'          => 4,
374
                                    'm_dwBlockSize'      => 4,
375
                                    'm_wQuality'         => 2,
376
                                    'm_wMarkDistance'    => 2,
377
                                    'm_wReserved'        => 2,
378
                                    'm_dwOrgSize'        => 4,
379
                                    'm_bFactExists'      => 2,
380
                                    'm_dwRiffChunkSize'  => 4
381
                                ]
382
                            );
383
384
                            //$info_riff_litewave['quality_factor'] = intval(round((2000 - $info_riff_litewave_raw['m_dwScale']) / 20));
385
                            $info_riff_litewave['quality_factor'] = $info_riff_litewave_raw['m_wQuality'];
386
387
                            $info_riff_litewave['flags']['raw_source']    = ($info_riff_litewave_raw['compression_flags'] & 0x01) ? false : true;
388
                            $info_riff_litewave['flags']['vbr_blocksize'] = ($info_riff_litewave_raw['compression_flags'] & 0x02) ? false : true;
389
                            $info_riff_litewave['flags']['seekpoints']    = (bool)($info_riff_litewave_raw['compression_flags'] & 0x04);
390
391
                            $info_audio['lossless']        = ((100 == $info_riff_litewave_raw['m_wQuality']) ? true : false);
392
                            $info_audio['encoder_options'] = '-q' . $info_riff_litewave['quality_factor'];
393
                            break;
394
                    }
395
                }
396
397
                if ($info_avdataend > $getid3->info['filesize']) {
398
                    switch (@$info_audio_dataformat) {
399
                        case 'wavpack': // WavPack
400
                        case 'lpac':    // LPAC
401
                        case 'ofr':     // OptimFROG
402
                        case 'ofs':     // OptimFROG DualStream
403
                            // lossless compressed audio formats that keep original RIFF headers - skip warning
404
                            break;
405
406
                        case 'litewave':
407
408
                            if (1 == ($info_avdataend - $getid3->info['filesize'])) {
409
                                // LiteWave appears to incorrectly *not* pad actual output file
410
                                // to nearest WORD boundary so may appear to be short by one
411
                                // byte, in which case - skip warning
412
                            } else {
413
                                // Short by more than one byte, throw warning
414
                                $getid3->warning(
415
                                    'Probably truncated file - expecting '
416
                                    . $info_riff[$riff_sub_type]['data'][0]['size']
417
                                    . ' bytes of data, only found '
418
                                    . ($getid3->info['filesize'] - $info_avdataoffset)
419
                                    . ' (short by '
420
                                    . ($info_riff[$riff_sub_type]['data'][0]['size'] - ($getid3->info['filesize']
421
                                                                                        - $info_avdataoffset))
422
                                    . ' bytes)'
423
                                );
424
                            }
425
                            break;
426
427
                        default:
428
429
                            if ((1 == ($info_avdataend - $getid3->info['filesize'])) && (0 == ($info_riff[$riff_sub_type]['data'][0]['size'] % 2)) && (1 == (($getid3->info['filesize'] - $info_avdataoffset) % 2))) {
430
                                // output file appears to be incorrectly *not* padded to nearest WORD boundary
431
                                // Output less severe warning
432
                                $getid3->warning(
433
                                    'File should probably be padded to nearest WORD boundary, but it is not (expecting '
434
                                    . $info_riff[$riff_sub_type]['data'][0]['size']
435
                                    . ' bytes of data, only found '
436
                                    . ($getid3->info['filesize'] - $info_avdataoffset)
437
                                    . ' therefore short by '
438
                                    . ($info_riff[$riff_sub_type]['data'][0]['size'] - ($getid3->info['filesize'] - $info_avdataoffset))
439
                                    . ' bytes)'
440
                                );
441
                                $info_avdataend = $getid3->info['filesize'];
442
                                break;
443
                            }
444
                            // Short by more than one byte, throw warning
445
                            $getid3->warning(
446
                                'Probably truncated file - expecting '
447
                                . $info_riff[$riff_sub_type]['data'][0]['size']
448
                                . ' bytes of data, only found '
449
                                . ($getid3->info['filesize'] - $info_avdataoffset)
450
                                . ' (short by '
451
                                . ($info_riff[$riff_sub_type]['data'][0]['size'] - ($getid3->info['filesize']
452
                                                                                    - $info_avdataoffset))
453
                                . ' bytes)'
454
                            );
455
                            $info_avdataend = $getid3->info['filesize'];
456
                            break;
457
                    }
458
                }
459
460
                if (!empty($getid3->info['mpeg']['audio']['LAME']['audio_bytes'])) {
461
                    if (1 == (($info_avdataend - $info_avdataoffset) - $getid3->info['mpeg']['audio']['LAME']['audio_bytes'])) {
462
                        $info_avdataend--;
463
                        $getid3->warning('Extra null byte at end of MP3 data assumed to be RIFF padding and therefore ignored');
464
                    }
465
                }
466
467
                if ('ac3' == @$info_audio_dataformat) {
468
                    unset($info_audio['bits_per_sample']);
469
                    if (!empty($getid3->info['ac3']['bitrate']) && ($getid3->info['ac3']['bitrate'] != $info_audio['bitrate'])) {
470
                        $info_audio['bitrate'] = $getid3->info['ac3']['bitrate'];
471
                    }
472
                }
473
                break;
474
475
            case 'AVI ':
476
                $info_video['bitrate_mode'] = 'vbr'; // maybe not, but probably
477
                $info_video['dataformat']   = 'avi';
478
                $getid3->info['mime_type']  = 'video/avi';
479
480
                if (isset($info_riff[$riff_sub_type]['movi']['offset'])) {
481
                    $info_avdataoffset = $info_riff[$riff_sub_type]['movi']['offset'] + 8;
482
                    $info_avdataend    = $info_avdataoffset + $info_riff[$riff_sub_type]['movi']['size'];
483
                    if ($info_avdataend > $getid3->info['filesize']) {
484
                        $getid3->warning(
485
                            'Probably truncated file - expecting ' . $info_riff[$riff_sub_type]['movi']['size'] . ' bytes of data, only found ' . ($getid3->info['filesize'] - $info_avdataoffset) . ' (short by ' . ($info_riff[$riff_sub_type]['movi']['size'] - ($getid3->info['filesize']
486
                                                                                                                                                                                                                                                                    - $info_avdataoffset)) . ' bytes)'
487
                        );
488
                        $info_avdataend = $getid3->info['filesize'];
489
                    }
490
                }
491
492
                if (isset($info_riff['AVI ']['hdrl']['avih'][$stream_index]['data'])) {
493
                    $avihData = $info_riff['AVI ']['hdrl']['avih'][$stream_index]['data'];
494
495
                    $info_riff_raw['avih'] = [];
496
                    $info_riff_raw_avih    = &$info_riff_raw['avih'];
497
498
                    getid3_lib::ReadSequence(
499
                        $this->endian_function,
500
                        $info_riff_raw_avih,
501
                        $avihData,
502
                        0,
503
                        [
504
                            'dwMicroSecPerFrame'    => 4, // frame display rate (or 0L)
505
                            'dwMaxBytesPerSec'      => 4, // max. transfer rate
506
                            'dwPaddingGranularity'  => 4, // pad to multiples of this size; normally 2K.
507
                            'dwFlags'               => 4, // the ever-present flags
508
                            'dwTotalFrames'         => 4, // # frames in file
509
                            'dwInitialFrames'       => 4,
510
                            'dwStreams'             => 4,
511
                            'dwSuggestedBufferSize' => 4,
512
                            'dwWidth'               => 4,
513
                            'dwHeight'              => 4,
514
                            'dwScale'               => 4,
515
                            'dwRate'                => 4,
516
                            'dwStart'               => 4,
517
                            'dwLength'              => 4
518
                        ]
519
                    );
520
521
                    $info_riff_raw_avih['flags']['hasindex']     = (bool)($info_riff_raw_avih['dwFlags'] & 0x00000010);
522
                    $info_riff_raw_avih['flags']['mustuseindex'] = (bool)($info_riff_raw_avih['dwFlags'] & 0x00000020);
523
                    $info_riff_raw_avih['flags']['interleaved']  = (bool)($info_riff_raw_avih['dwFlags'] & 0x00000100);
524
                    $info_riff_raw_avih['flags']['trustcktype']  = (bool)($info_riff_raw_avih['dwFlags'] & 0x00000800);
525
                    $info_riff_raw_avih['flags']['capturedfile'] = (bool)($info_riff_raw_avih['dwFlags'] & 0x00010000);
526
                    $info_riff_raw_avih['flags']['copyrighted']  = (bool)($info_riff_raw_avih['dwFlags'] & 0x00020010);
527
528
                    $info_riff_video[$stream_index] = [];
529
                    $info_riff_video_current        = &$info_riff_video[$stream_index];
530
531
                    if ($info_riff_raw_avih['dwWidth'] > 0) {
532
                        $info_riff_video_current['frame_width'] = $info_riff_raw_avih['dwWidth'];
533
                        $info_video['resolution_x']             = $info_riff_video_current['frame_width'];
534
                    }
535
536
                    if ($info_riff_raw_avih['dwHeight'] > 0) {
537
                        $info_riff_video_current['frame_height'] = $info_riff_raw_avih['dwHeight'];
538
                        $info_video['resolution_y']              = $info_riff_video_current['frame_height'];
539
                    }
540
541
                    if ($info_riff_raw_avih['dwTotalFrames'] > 0) {
542
                        $info_riff_video_current['total_frames'] = $info_riff_raw_avih['dwTotalFrames'];
543
                        $info_video['total_frames']              = $info_riff_video_current['total_frames'];
544
                    }
545
546
                    $info_riff_video_current['frame_rate'] = round(1000000 / $info_riff_raw_avih['dwMicroSecPerFrame'], 3);
547
                    $info_video['frame_rate']              = $info_riff_video_current['frame_rate'];
548
                }
549
550
                if (isset($info_riff['AVI ']['hdrl']['strl']['strh'][0]['data'])) {
551
                    if (is_array($info_riff['AVI ']['hdrl']['strl']['strh'])) {
552
                        for ($i = 0; $i < count($info_riff['AVI ']['hdrl']['strl']['strh']); $i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
553
                            if (isset($info_riff['AVI ']['hdrl']['strl']['strh'][$i]['data'])) {
554
                                $strh_data     = $info_riff['AVI ']['hdrl']['strl']['strh'][$i]['data'];
555
                                $strh_fcc_type = substr($strh_data, 0, 4);
556
557
                                if (isset($info_riff['AVI ']['hdrl']['strl']['strf'][$i]['data'])) {
558
                                    $strf_data = $info_riff['AVI ']['hdrl']['strl']['strf'][$i]['data'];
559
560
                                    // shortcut
561
                                    $info_riff_raw_strf_strh_fcc_type_stream_index = &$info_riff_raw['strf'][$strh_fcc_type][$stream_index];
562
563
                                    switch ($strh_fcc_type) {
564
                                        case 'auds':
565
                                            $info_audio['bitrate_mode'] = 'cbr';
566
                                            $info_audio_dataformat      = 'wav';
567
                                            if (isset($info_riff_audio) && is_array($info_riff_audio)) {
568
                                                $stream_index = count($info_riff_audio);
569
                                            }
570
571
                                            $info_riff_audio[$stream_index] = getid3_riff::RIFFparseWAVEFORMATex($strf_data);
572
                                            $info_audio['wformattag']       = $info_riff_audio[$stream_index]['raw']['wFormatTag'];
573
574
                                            // shortcut
575
                                            $info_audio['streams'][$stream_index] = $info_riff_audio[$stream_index];
576
                                            $info_audio_streams_currentstream     = &$info_audio['streams'][$stream_index];
577
578
                                            if (0 === @$info_audio_streams_currentstream['bits_per_sample']) {
579
                                                unset($info_audio_streams_currentstream['bits_per_sample']);
580
                                            }
581
                                            $info_audio_streams_currentstream['wformattag'] = $info_audio_streams_currentstream['raw']['wFormatTag'];
582
                                            unset($info_audio_streams_currentstream['raw']);
583
584
                                            // shortcut
585
                                            $info_riff_raw['strf'][$strh_fcc_type][$stream_index] = $info_riff_audio[$stream_index]['raw'];
586
587
                                            unset($info_riff_audio[$stream_index]['raw']);
588
                                            $info_audio = getid3_riff::array_merge_noclobber($info_audio, $info_riff_audio[$stream_index]);
589
590
                                            $info_audio['lossless'] = false;
591
                                            switch ($info_riff_raw_strf_strh_fcc_type_stream_index['wFormatTag']) {
592
                                                case 0x0001:  // PCM
593
                                                    $info_audio_dataformat  = 'wav';
594
                                                    $info_audio['lossless'] = true;
595
                                                    break;
596
597
                                                case 0x0050: // MPEG Layer 2 or Layer 1
598
                                                    $info_audio_dataformat = 'mp2'; // Assume Layer-2
599
                                                    break;
600
601
                                                case 0x0055: // MPEG Layer 3
602
                                                    $info_audio_dataformat = 'mp3';
603
                                                    break;
604
605
                                                case 0x00FF: // AAC
606
                                                    $info_audio_dataformat = 'aac';
607
                                                    break;
608
609
                                                case 0x0161: // Windows Media v7 / v8 / v9
610
                                                case 0x0162: // Windows Media Professional v9
611
                                                case 0x0163: // Windows Media Lossess v9
612
                                                    $info_audio_dataformat = 'wma';
613
                                                    break;
614
615
                                                case 0x2000: // AC-3
616
                                                    $info_audio_dataformat = 'ac3';
617
                                                    break;
618
619
                                                case 0x2001: // DTS
620
                                                    $info_audio_dataformat = 'dts';
621
                                                    break;
622
623
                                                default:
624
                                                    $info_audio_dataformat = 'wav';
625
                                                    break;
626
                                            }
627
                                            $info_audio_streams_currentstream['dataformat']   = $info_audio_dataformat;
628
                                            $info_audio_streams_currentstream['lossless']     = $info_audio['lossless'];
629
                                            $info_audio_streams_currentstream['bitrate_mode'] = $info_audio['bitrate_mode'];
630
                                            break;
631
632
                                        case 'iavs':
633
                                        case 'vids':
634
                                            // shortcut
635
                                            $info_riff_raw['strh'][$i]  = [];
636
                                            $info_riff_raw_strh_current = &$info_riff_raw['strh'][$i];
637
638
                                            getid3_lib::ReadSequence(
639
                                                $this->endian_function,
640
                                                $info_riff_raw_strh_current,
641
                                                $strh_data,
642
                                                0,
643
                                                [
644
                                                    'fccType'               => -4, // same as $strh_fcc_type;
645
                                                    'fccHandler'            => -4,
646
                                                    'dwFlags'               => 4, // Contains AVITF_* flags
647
                                                    'wPriority'             => 2,
648
                                                    'wLanguage'             => 2,
649
                                                    'dwInitialFrames'       => 4,
650
                                                    'dwScale'               => 4,
651
                                                    'dwRate'                => 4,
652
                                                    'dwStart'               => 4,
653
                                                    'dwLength'              => 4,
654
                                                    'dwSuggestedBufferSize' => 4,
655
                                                    'dwQuality'             => 4,
656
                                                    'dwSampleSize'          => 4,
657
                                                    'rcFrame'               => 4
658
                                                ]
659
                                            );
660
661
                                            $info_riff_video_current['codec'] = getid3_riff::RIFFfourccLookup($info_riff_raw_strh_current['fccHandler']);
662
                                            $info_video['fourcc']             = $info_riff_raw_strh_current['fccHandler'];
663
664
                                            if (!$info_riff_video_current['codec'] && isset($info_riff_raw_strf_strh_fcc_type_stream_index['fourcc']) && getid3_riff::RIFFfourccLookup($info_riff_raw_strf_strh_fcc_type_stream_index['fourcc'])) {
665
                                                $info_riff_video_current['codec'] = getid3_riff::RIFFfourccLookup($info_riff_raw_strf_strh_fcc_type_stream_index['fourcc']);
666
                                                $info_video['fourcc']             = $info_riff_raw_strf_strh_fcc_type_stream_index['fourcc'];
667
                                            }
668
669
                                            $info_video['codec']              = $info_riff_video_current['codec'];
670
                                            $info_video['pixel_aspect_ratio'] = (float)1;
671
672
                                            switch ($info_riff_raw_strh_current['fccHandler']) {
673
                                                case 'HFYU': // Huffman Lossless Codec
674
                                                case 'IRAW': // Intel YUV Uncompressed
675
                                                case 'YUY2': // Uncompressed YUV 4:2:2
676
                                                    $info_video['lossless'] = true;
677
                                                    break;
678
679
                                                default:
680
                                                    $info_video['lossless'] = false;
681
                                                    break;
682
                                            }
683
684
                                            switch ($strh_fcc_type) {
685
                                                case 'vids':
686
                                                    getid3_lib::ReadSequence(
687
                                                        $this->endian_function,
688
                                                        $info_riff_raw_strf_strh_fcc_type_stream_index,
689
                                                        $strf_data,
690
                                                        0,
691
                                                        [
692
                                                            'biSize'          => 4,
693
                                                            // number of bytes required by the BITMAPINFOHEADER structure
694
                                                            'biWidth'         => 4,
695
                                                            // width of the bitmap in pixels
696
                                                            'biHeight'        => 4,
697
                                                            // height of the bitmap in pixels. If biHeight is positive, the bitmap is a 'bottom-up' DIB and its origin is the lower left corner. If biHeight is negative, the bitmap is a 'top-down' DIB and its origin is the upper left corner
698
                                                            'biPlanes'        => 2,
699
                                                            // number of color planes on the target device. In most cases this value must be set to 1
700
                                                            'biBitCount'      => 2,
701
                                                            // Specifies the number of bits per pixels
702
                                                            'fourcc'          => -4,
703
                                                            //
704
                                                            'biSizeImage'     => 4,
705
                                                            // size of the bitmap data section of the image (the actual pixel data, excluding BITMAPINFOHEADER and RGBQUAD structures)
706
                                                            'biXPelsPerMeter' => 4,
707
                                                            // horizontal resolution, in pixels per metre, of the target device
708
                                                            'biYPelsPerMeter' => 4,
709
                                                            // vertical resolution, in pixels per metre, of the target device
710
                                                            'biClrUsed'       => 4,
711
                                                            // actual number of color indices in the color table used by the bitmap. If this value is zero, the bitmap uses the maximum number of colors corresponding to the value of the biBitCount member for the compression mode specified by biCompression
712
                                                            'biClrImportant'  => 4
713
                                                            // number of color indices that are considered important for displaying the bitmap. If this value is zero, all colors are important
714
                                                        ]
715
                                                    );
716
717
                                                    $info_video['bits_per_sample'] = $info_riff_raw_strf_strh_fcc_type_stream_index['biBitCount'];
718
719
                                                    if ('DV' == $info_riff_video_current['codec']) {
720
                                                        $info_riff_video_current['dv_type'] = 2;
721
                                                    }
722
                                                    break;
723
724
                                                case 'iavs':
725
                                                    $info_riff_video_current['dv_type'] = 1;
726
                                                    break;
727
                                            }
728
                                            break;
729
730
                                        default:
731
                                            $getid3->warning('Unhandled fccType for stream (' . $i . '): "' . $strh_fcc_type . '"');
732
                                            break;
733
                                    }
734
                                }
735
                            }
736
737
                            if (isset($info_riff_raw_strf_strh_fcc_type_stream_index['fourcc']) && getid3_riff::RIFFfourccLookup($info_riff_raw_strf_strh_fcc_type_stream_index['fourcc'])) {
738
                                $info_riff_video_current['codec'] = getid3_riff::RIFFfourccLookup($info_riff_raw_strf_strh_fcc_type_stream_index['fourcc']);
739
                                $info_video['codec']              = $info_riff_video_current['codec'];
740
                                $info_video['fourcc']             = $info_riff_raw_strf_strh_fcc_type_stream_index['fourcc'];
741
742
                                switch ($info_riff_raw_strf_strh_fcc_type_stream_index['fourcc']) {
743
                                    case 'HFYU': // Huffman Lossless Codec
744
                                    case 'IRAW': // Intel YUV Uncompressed
745
                                    case 'YUY2': // Uncompressed YUV 4:2:2
746
                                        $info_video['lossless']        = true;
747
                                        $info_video['bits_per_sample'] = 24;
748
                                        break;
749
750
                                    default:
751
                                        $info_video['lossless']        = false;
752
                                        $info_video['bits_per_sample'] = 24;
753
                                        break;
754
                                }
755
                            }
756
                        }
757
                    }
758
                }
759
                break;
760
761
            case 'CDDA':
762
                $info_audio['bitrate_mode'] = 'cbr';
763
                $info_audio_dataformat      = 'cda';
764
                $info_audio['lossless']     = true;
765
                unset($getid3->info['mime_type']);
766
767
                $info_avdataoffset = 44;
768
769
                if (isset($info_riff['CDDA']['fmt '][0]['data'])) {
770
                    $info_riff_cdda_fmt_0 = &$info_riff['CDDA']['fmt '][0];
771
772
                    getid3_lib::ReadSequence(
773
                        $this->endian_function,
774
                        $info_riff_cdda_fmt_0,
775
                        $info_riff_cdda_fmt_0['data'],
776
                        0,
777
                        [
778
                            'unknown1'           => 2,
779
                            'track_num'          => 2,
780
                            'disc_id'            => 4,
781
                            'start_offset_frame' => 4,
782
                            'playtime_frames'    => 4,
783
                            'unknown6'           => 4,
784
                            'unknown7'           => 4
785
                        ]
786
                    );
787
788
                    $info_riff_cdda_fmt_0['start_offset_seconds'] = (float)$info_riff_cdda_fmt_0['start_offset_frame'] / 75;
789
                    $info_riff_cdda_fmt_0['playtime_seconds']     = (float)$info_riff_cdda_fmt_0['playtime_frames'] / 75;
790
                    $getid3->info['comments']['track']            = $info_riff_cdda_fmt_0['track_num'];
791
                    $getid3->info['playtime_seconds']             = $info_riff_cdda_fmt_0['playtime_seconds'];
792
793
                    // hardcoded data for CD-audio
794
                    $info_audio['sample_rate']     = 44100;
795
                    $info_audio['channels']        = 2;
796
                    $info_audio['bits_per_sample'] = 16;
797
                    $info_audio['bitrate']         = $info_audio['sample_rate'] * $info_audio['channels'] * $info_audio['bits_per_sample'];
798
                    $info_audio['bitrate_mode']    = 'cbr';
799
                }
800
                break;
801
802
            case 'AIFF':
803
            case 'AIFC':
804
                $info_audio['bitrate_mode'] = 'cbr';
805
                $info_audio_dataformat      = 'aiff';
806
                $info_audio['lossless']     = true;
807
                $getid3->info['mime_type']  = 'audio/x-aiff';
808
809
                if (isset($info_riff[$riff_sub_type]['SSND'][0]['offset'])) {
810
                    $info_avdataoffset = $info_riff[$riff_sub_type]['SSND'][0]['offset'] + 8;
811
                    $info_avdataend    = $info_avdataoffset + $info_riff[$riff_sub_type]['SSND'][0]['size'];
812
                    if ($info_avdataend > $getid3->info['filesize']) {
813
                        if (($info_avdataend == ($getid3->info['filesize'] + 1)) && (1 == ($getid3->info['filesize'] % 2))) {
814
                            // structures rounded to 2-byte boundary, but dumb encoders
815
                            // forget to pad end of file to make this actually work
816
                        } else {
817
                            $getid3->warning('Probable truncated AIFF file: expecting ' . $info_riff[$riff_sub_type]['SSND'][0]['size'] . ' bytes of audio data, only ' . ($getid3->info['filesize'] - $info_avdataoffset) . ' bytes found');
818
                        }
819
                        $info_avdataend = $getid3->info['filesize'];
820
                    }
821
                }
822
823
                if (isset($info_riff[$riff_sub_type]['COMM'][0]['data'])) {
824
                    // shortcut
825
                    $info_riff_RIFFsubtype_COMM_0_data = &$info_riff[$riff_sub_type]['COMM'][0]['data'];
826
827
                    $info_riff_audio['channels']        = getid3_lib::BigEndianSyncSafe2Int(substr($info_riff_RIFFsubtype_COMM_0_data, 0, 2));
828
                    $info_riff_audio['total_samples']   = getid3_lib::BigEndian2Int(substr($info_riff_RIFFsubtype_COMM_0_data, 2, 4));
829
                    $info_riff_audio['bits_per_sample'] = getid3_lib::BigEndianSyncSafe2Int(substr($info_riff_RIFFsubtype_COMM_0_data, 6, 2));
830
                    $info_riff_audio['sample_rate']     = (int)getid3_riff::BigEndian2Float(substr($info_riff_RIFFsubtype_COMM_0_data, 8, 10));
831
832
                    if ($info_riff[$riff_sub_type]['COMM'][0]['size'] > 18) {
833
                        $info_riff_audio['codec_fourcc'] = substr($info_riff_RIFFsubtype_COMM_0_data, 18, 4);
834
                        $codec_name_size                 = getid3_lib::BigEndian2Int(substr($info_riff_RIFFsubtype_COMM_0_data, 22, 1));
835
                        $info_riff_audio['codec_name']   = substr($info_riff_RIFFsubtype_COMM_0_data, 23, $codec_name_size);
836
837
                        switch ($info_riff_audio['codec_name']) {
838
                            case 'NONE':
839
                                $info_audio['codec']    = 'Pulse Code Modulation (PCM)';
840
                                $info_audio['lossless'] = true;
841
                                break;
842
843
                            case '':
844
                                switch ($info_riff_audio['codec_fourcc']) {
845
                                    // http://developer.apple.com/qa/snd/snd07.html
846
                                    case 'sowt':
847
                                        $info_riff_audio['codec_name'] = 'Two\'s Compliment Little-Endian PCM';
848
                                        $info_audio['lossless']        = true;
849
                                        break;
850
851
                                    case 'twos':
852
                                        $info_riff_audio['codec_name'] = 'Two\'s Compliment Big-Endian PCM';
853
                                        $info_audio['lossless']        = true;
854
                                        break;
855
856
                                    default:
857
                                        break;
858
                                }
859
                                break;
860
861
                            default:
862
                                $info_audio['codec']    = $info_riff_audio['codec_name'];
863
                                $info_audio['lossless'] = false;
864
                                break;
865
                        }
866
                    }
867
868
                    $info_audio['channels'] = $info_riff_audio['channels'];
869
870
                    if ($info_riff_audio['bits_per_sample'] > 0) {
871
                        $info_audio['bits_per_sample'] = $info_riff_audio['bits_per_sample'];
872
                    }
873
874
                    $info_audio['sample_rate']        = $info_riff_audio['sample_rate'];
875
                    $getid3->info['playtime_seconds'] = $info_riff_audio['total_samples'] / $info_audio['sample_rate'];
876
                }
877
878
                if (isset($info_riff[$riff_sub_type]['COMT'])) {
879
                    $comment_count = getid3_lib::BigEndian2Int(substr($info_riff[$riff_sub_type]['COMT'][0]['data'], 0, 2));
880
                    $offset        = 2;
881
882
                    for ($i = 0; $i < $comment_count; $i++) {
883
                        $getid3->info['comments_raw'][$i]['timestamp'] = getid3_lib::BigEndian2Int(substr($info_riff[$riff_sub_type]['COMT'][0]['data'], $offset, 4));
884
                        $offset                                        += 4;
885
886
                        $getid3->info['comments_raw'][$i]['marker_id'] = getid3_lib::BigEndianSyncSafe2Int(substr($info_riff[$riff_sub_type]['COMT'][0]['data'], $offset, 2));
887
                        $offset                                        += 2;
888
889
                        $comment_length = getid3_lib::BigEndian2Int(substr($info_riff[$riff_sub_type]['COMT'][0]['data'], $offset, 2));
890
                        $offset         += 2;
891
892
                        $getid3->info['comments_raw'][$i]['comment'] = substr($info_riff[$riff_sub_type]['COMT'][0]['data'], $offset, $comment_length);
893
                        $offset                                      += $comment_length;
894
895
                        $getid3->info['comments_raw'][$i]['timestamp_unix'] = getid3_riff::DateMac2Unix($getid3->info['comments_raw'][$i]['timestamp']);
896
                        $info_riff['comments']['comment'][]                 = $getid3->info['comments_raw'][$i]['comment'];
897
                    }
898
                }
899
900
                foreach (['NAME' => 'title', 'author' => 'artist', '(c) ' => 'copyright', 'ANNO' => 'comment'] as $key => $value) {
901
                    if (isset($info_riff[$riff_sub_type][$key][0]['data'])) {
902
                        $info_riff['comments'][$value][] = $info_riff[$riff_sub_type][$key][0]['data'];
903
                    }
904
                }
905
                break;
906
907
            case '8SVX':
908
                $info_audio['bitrate_mode']    = 'cbr';
909
                $info_audio_dataformat         = '8svx';
910
                $info_audio['bits_per_sample'] = 8;
911
                $info_audio['channels']        = 1; // overridden below, if need be
912
                $getid3->info['mime_type']     = 'audio/x-aiff';
913
914
                if (isset($info_riff[$riff_sub_type]['BODY'][0]['offset'])) {
915
                    $info_avdataoffset = $info_riff[$riff_sub_type]['BODY'][0]['offset'] + 8;
916
                    $info_avdataend    = $info_avdataoffset + $info_riff[$riff_sub_type]['BODY'][0]['size'];
917
                    if ($info_avdataend > $getid3->info['filesize']) {
918
                        $getid3->warning('Probable truncated AIFF file: expecting ' . $info_riff[$riff_sub_type]['BODY'][0]['size'] . ' bytes of audio data, only ' . ($getid3->info['filesize'] - $info_avdataoffset) . ' bytes found');
919
                    }
920
                }
921
922
                if (isset($info_riff[$riff_sub_type]['VHDR'][0]['offset'])) {
923
                    // shortcut
924
                    $info_riff_riff_sub_type_vhdr_0 = &$info_riff[$riff_sub_type]['VHDR'][0];
925
926
                    getid3_lib::ReadSequence(
927
                        'BigEndian2Int',
928
                        $info_riff_riff_sub_type_vhdr_0,
929
                        $info_riff_riff_sub_type_vhdr_0['data'],
930
                        0,
931
                        [
932
                            'oneShotHiSamples'  => 4,
933
                            'repeatHiSamples'   => 4,
934
                            'samplesPerHiCycle' => 4,
935
                            'samplesPerSec'     => 2,
936
                            'ctOctave'          => 1,
937
                            'sCompression'      => 1,
938
                            'Volume'            => -4
939
                        ]
940
                    );
941
942
                    $info_riff_riff_sub_type_vhdr_0['Volume'] = getid3_riff::FixedPoint16_16($info_riff_riff_sub_type_vhdr_0['Volume']);
943
944
                    $info_audio['sample_rate'] = $info_riff_riff_sub_type_vhdr_0['samplesPerSec'];
945
946
                    switch ($info_riff_riff_sub_type_vhdr_0['sCompression']) {
947
                        case 0:
948
                            $info_audio['codec']    = 'Pulse Code Modulation (PCM)';
949
                            $info_audio['lossless'] = true;
950
                            $actual_bits_per_sample = 8;
951
                            break;
952
953
                        case 1:
954
                            $info_audio['codec']    = 'Fibonacci-delta encoding';
955
                            $info_audio['lossless'] = false;
956
                            $actual_bits_per_sample = 4;
957
                            break;
958
959
                        default:
960
                            $getid3->warning('Unexpected sCompression value in 8SVX.VHDR chunk - expecting 0 or 1, found "' . sCompression . '"');
0 ignored issues
show
Bug introduced by
The constant sCompression was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
961
                            break;
962
                    }
963
                }
964
965
                if (isset($info_riff[$riff_sub_type]['CHAN'][0]['data'])) {
966
                    $ChannelsIndex = getid3_lib::BigEndian2Int(substr($info_riff[$riff_sub_type]['CHAN'][0]['data'], 0, 4));
967
                    switch ($ChannelsIndex) {
968
                        case 6: // Stereo
969
                            $info_audio['channels'] = 2;
970
                            break;
971
972
                        case 2: // Left channel only
973
                        case 4: // Right channel only
974
                            $info_audio['channels'] = 1;
975
                            break;
976
977
                        default:
978
                            $getid3->warning('Unexpected value in 8SVX.CHAN chunk - expecting 2 or 4 or 6, found "' . $ChannelsIndex . '"');
979
                            break;
980
                    }
981
                }
982
983
                foreach (['NAME' => 'title', 'author' => 'artist', '(c) ' => 'copyright', 'ANNO' => 'comment'] as $key => $value) {
984
                    if (isset($info_riff[$riff_sub_type][$key][0]['data'])) {
985
                        $info_riff['comments'][$value][] = $info_riff[$riff_sub_type][$key][0]['data'];
986
                    }
987
                }
988
989
                $info_audio['bitrate'] = $info_audio['sample_rate'] * $actual_bits_per_sample * $info_audio['channels'];
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $actual_bits_per_sample does not seem to be defined for all execution paths leading up to this point.
Loading history...
990
                if (!empty($info_audio['bitrate'])) {
991
                    $getid3->info['playtime_seconds'] = ($info_avdataend - $info_avdataoffset) / ($info_audio['bitrate'] / 8);
992
                }
993
                break;
994
995
            case 'CDXA':
996
997
                $getid3->info['mime_type'] = 'video/mpeg';
998
                if (!empty($info_riff['CDXA']['data'][0]['size'])) {
999
                    $GETID3_ERRORARRAY = &$getid3->info['warning'];
0 ignored issues
show
Unused Code introduced by
The assignment to $GETID3_ERRORARRAY is dead and can be removed.
Loading history...
1000
1001
                    if (!$getid3->include_module_optional('audio-video.mpeg')) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $getid3->include_module_...nal('audio-video.mpeg') of type null|true is loosely compared to false; this is ambiguous if the boolean can be false. You might want to explicitly use !== null instead.

If an expression can have both false, and null as possible values. It is generally a good practice to always use strict comparison to clearly distinguish between those two values.

$a = canBeFalseAndNull();

// Instead of
if ( ! $a) { }

// Better use one of the explicit versions:
if ($a !== null) { }
if ($a !== false) { }
if ($a !== null && $a !== false) { }
Loading history...
1002
                        $getid3->warning('MPEG skipped because mpeg module is missing.');
1003
                    } else {
1004
                        // Clone getid3 - messing with offsets - better safe than sorry
1005
                        $clone = clone $getid3;
1006
1007
                        // Analyse
1008
                        $mpeg = new getid3_mpeg($clone);
1009
                        $mpeg->Analyze();
1010
1011
                        // Import from clone and destroy                            
1012
                        $getid3->info['audio']   = $clone->info['audio'];
1013
                        $getid3->info['video']   = $clone->info['video'];
1014
                        $getid3->info['mpeg']    = $clone->info['mpeg'];
1015
                        $getid3->info['warning'] = $clone->info['warning'];
1016
1017
                        unset($clone);
1018
                    }
1019
                }
1020
1021
                break;
1022
1023
            default:
1024
                throw new getid3_exception('Unknown RIFF type: expecting one of (WAVE|RMP3|AVI |CDDA|AIFF|AIFC|8SVX|CDXA), found "' . $riff_sub_type . '" instead');
1025
        }
1026
1027
        if (1 == @$info_riff_raw['fmt ']['wFormatTag']) {
1028
            // http://www.mega-nerd.com/erikd/Blog/Windiots/dts.html
1029
            $this->fseek($getid3->info['avdataoffset'], SEEK_SET);
1030
            $bytes4 = $this->fread(4);
1031
1032
            // DTSWAV
1033
            if (preg_match('/^\xFF\x1F\x00\xE8/s', $bytes4)) {
1034
                $info_audio_dataformat = 'dts';
1035
            } // DTS, but this probably shouldn't happen
1036
            elseif (preg_match('/^\x7F\xFF\x80\x01/s', $bytes4)) {
1037
                $info_audio_dataformat = 'dts';
1038
            }
1039
        }
1040
1041
        if (@is_array($info_riff_wave['DISP'])) {
1042
            $info_riff['comments']['title'][] = trim(substr($info_riff_wave['DISP'][count($info_riff_wave['DISP']) - 1]['data'], 4));
1043
        }
1044
1045
        if (@is_array($info_riff_wave['INFO'])) {
1046
            getid3_riff::RIFFCommentsParse($info_riff_wave['INFO'], $info_riff['comments']);
1047
        }
1048
1049
        if (isset($info_riff_wave['INFO']) && is_array($info_riff_wave['INFO'])) {
1050
            foreach (
1051
                [
1052
                    'IARL' => 'archivallocation',
1053
                    'IART' => 'artist',
1054
                    'ICDS' => 'costumedesigner',
1055
                    'ICMS' => 'commissionedby',
1056
                    'ICMT' => 'comment',
1057
                    'ICNT' => 'country',
1058
                    'ICOP' => 'copyright',
1059
                    'ICRD' => 'creationdate',
1060
                    'IDIM' => 'dimensions',
1061
                    'IDIT' => 'digitizationdate',
1062
                    'IDPI' => 'resolution',
1063
                    'IDST' => 'distributor',
1064
                    'IEDT' => 'editor',
1065
                    'IENG' => 'engineers',
1066
                    'IFRM' => 'accountofparts',
1067
                    'IGNR' => 'genre',
1068
                    'IKEY' => 'keywords',
1069
                    'ILGT' => 'lightness',
1070
                    'ILNG' => 'language',
1071
                    'IMED' => 'orignalmedium',
1072
                    'IMUS' => 'composer',
1073
                    'INAM' => 'title',
1074
                    'IPDS' => 'productiondesigner',
1075
                    'IPLT' => 'palette',
1076
                    'IPRD' => 'product',
1077
                    'IPRO' => 'producer',
1078
                    'IPRT' => 'part',
1079
                    'IRTD' => 'rating',
1080
                    'ISBJ' => 'subject',
1081
                    'ISFT' => 'software',
1082
                    'ISGN' => 'secondarygenre',
1083
                    'ISHP' => 'sharpness',
1084
                    'ISRC' => 'sourcesupplier',
1085
                    'ISRF' => 'digitizationsource',
1086
                    'ISTD' => 'productionstudio',
1087
                    'ISTR' => 'starring',
1088
                    'ITCH' => 'encoded_by',
1089
                    'IWEB' => 'url',
1090
                    'IWRI' => 'writer'
1091
                ] as $key => $value
1092
            ) {
1093
                if (isset($info_riff_wave['INFO'][$key])) {
1094
                    foreach ($info_riff_wave['INFO'][$key] as $comment_id => $comment_data) {
1095
                        if ('' != trim($comment_data['data'])) {
1096
                            $info_riff['comments'][$value][] = trim($comment_data['data']);
1097
                        }
1098
                    }
1099
                }
1100
            }
1101
        }
1102
1103
        if (empty($info_audio['encoder']) && !empty($getid3->info['mpeg']['audio']['LAME']['short_version'])) {
1104
            $info_audio['encoder'] = $getid3->info['mpeg']['audio']['LAME']['short_version'];
1105
        }
1106
1107
        if (!isset($getid3->info['playtime_seconds'])) {
1108
            $getid3->info['playtime_seconds'] = 0;
1109
        }
1110
1111
        if (isset($info_riff_raw['avih']['dwTotalFrames']) && isset($info_riff_raw['avih']['dwMicroSecPerFrame'])) {
1112
            $getid3->info['playtime_seconds'] = $info_riff_raw['avih']['dwTotalFrames'] * ($info_riff_raw['avih']['dwMicroSecPerFrame'] / 1000000);
1113
        }
1114
1115
        if ($getid3->info['playtime_seconds'] > 0) {
1116
            if (isset($info_riff_audio) && isset($info_riff_video)) {
1117
                if (!isset($getid3->info['bitrate'])) {
1118
                    $getid3->info['bitrate'] = ((($info_avdataend - $info_avdataoffset) / $getid3->info['playtime_seconds']) * 8);
1119
                }
1120
            } elseif (isset($info_riff_audio) && !isset($info_riff_video)) {
1121
                if (!isset($info_audio['bitrate'])) {
1122
                    $info_audio['bitrate'] = ((($info_avdataend - $info_avdataoffset) / $getid3->info['playtime_seconds']) * 8);
1123
                }
1124
            } elseif (!isset($info_riff_audio) && isset($info_riff_video)) {
1125
                if (!isset($info_video['bitrate'])) {
1126
                    $info_video['bitrate'] = ((($info_avdataend - $info_avdataoffset) / $getid3->info['playtime_seconds']) * 8);
1127
                }
1128
            }
1129
        }
1130
1131
        if (isset($info_riff_video) && isset($info_audio['bitrate']) && ($info_audio['bitrate'] > 0) && ($getid3->info['playtime_seconds'] > 0)) {
1132
            $getid3->info['bitrate'] = ((($info_avdataend - $info_avdataoffset) / $getid3->info['playtime_seconds']) * 8);
1133
            $info_audio['bitrate']   = 0;
1134
            $info_video['bitrate']   = $getid3->info['bitrate'];
1135
            foreach ($info_riff_audio as $channelnumber => $audioinfoarray) {
1136
                $info_video['bitrate'] -= $audioinfoarray['bitrate'];
1137
                $info_audio['bitrate'] += $audioinfoarray['bitrate'];
1138
            }
1139
            if ($info_video['bitrate'] <= 0) {
1140
                unset($info_video['bitrate']);
1141
            }
1142
            if ($info_audio['bitrate'] <= 0) {
1143
                unset($info_audio['bitrate']);
1144
            }
1145
        }
1146
1147
        if (isset($getid3->info['mpeg']['audio'])) {
1148
            $info_audio_dataformat      = 'mp' . $getid3->info['mpeg']['audio']['layer'];
1149
            $info_audio['sample_rate']  = $getid3->info['mpeg']['audio']['sample_rate'];
1150
            $info_audio['channels']     = $getid3->info['mpeg']['audio']['channels'];
1151
            $info_audio['bitrate']      = $getid3->info['mpeg']['audio']['bitrate'];
1152
            $info_audio['bitrate_mode'] = strtolower($getid3->info['mpeg']['audio']['bitrate_mode']);
1153
1154
            if (!empty($getid3->info['mpeg']['audio']['codec'])) {
1155
                $info_audio['codec'] = $getid3->info['mpeg']['audio']['codec'] . ' ' . $info_audio['codec'];
1156
            }
1157
1158
            if (!empty($info_audio['streams'])) {
1159
                foreach ($info_audio['streams'] as $streamnumber => $streamdata) {
1160
                    if ($streamdata['dataformat'] == $info_audio_dataformat) {
1161
                        $info_audio['streams'][$streamnumber]['sample_rate']  = $info_audio['sample_rate'];
1162
                        $info_audio['streams'][$streamnumber]['channels']     = $info_audio['channels'];
1163
                        $info_audio['streams'][$streamnumber]['bitrate']      = $info_audio['bitrate'];
1164
                        $info_audio['streams'][$streamnumber]['bitrate_mode'] = $info_audio['bitrate_mode'];
1165
                        $info_audio['streams'][$streamnumber]['codec']        = $info_audio['codec'];
1166
                    }
1167
                }
1168
            }
1169
            $info_audio['encoder_options'] = getid3_mp3::GuessEncoderOptions($getid3->info);
1170
        }
1171
1172
        if (!empty($info_riff_raw['fmt ']['wBitsPerSample']) && ($info_riff_raw['fmt ']['wBitsPerSample'] > 0)) {
1173
            switch ($info_audio_dataformat) {
1174
                case 'ac3':
1175
                    // ignore bits_per_sample
1176
                    break;
1177
1178
                default:
1179
                    $info_audio['bits_per_sample'] = $info_riff_raw['fmt ']['wBitsPerSample'];
1180
                    break;
1181
            }
1182
        }
1183
1184
        if (empty($info_riff_raw)) {
1185
            unset($info_riff['raw']);
1186
        }
1187
        if (empty($info_riff_audio)) {
1188
            unset($info_riff['audio']);
1189
        }
1190
        if (empty($info_riff_video)) {
1191
            unset($info_riff['video']);
1192
        }
1193
        if (empty($info_audio_dataformat)) {
1194
            unset($info_audio['dataformat']);
1195
        }
1196
        if (empty($getid3->info['audio'])) {
1197
            unset($getid3->info['audio']);
1198
        }
1199
        if (empty($info_video)) {
1200
            unset($getid3->info['video']);
1201
        }
1202
1203
        return true;
1204
    }
1205
1206
    public function ParseRIFF($start_offset, $max_offset)
1207
    {
1208
        $getid3 = $this->getid3;
1209
1210
        $info = &$getid3->info;
1211
1212
        $endian_function = $this->endian_function;
1213
1214
        $max_offset = min($max_offset, $info['avdataend']);
1215
1216
        $riff_chunk = false;
1217
1218
        $this->fseek($start_offset, SEEK_SET);
1219
1220
        while ($this->ftell() < $max_offset) {
1221
            $chunk_name = $this->fread(4);
1222
1223
            if (strlen($chunk_name) < 4) {
1224
                throw new getid3_exception('Expecting chunk name at offset ' . ($this->ftell() - 4) . ' but found nothing. Aborting RIFF parsing.');
1225
            }
1226
1227
            $chunk_size = getid3_lib::$endian_function($this->fread(4));
1228
1229
            if (0 == $chunk_size) {
1230
                continue;
1231
                throw new getid3_exception('Chunk size at offset ' . ($this->ftell() - 4) . ' is zero. Aborting RIFF parsing.');
0 ignored issues
show
Unused Code introduced by
ThrowNode is not reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
1232
            }
1233
1234
            if (0 != ($chunk_size % 2)) {
1235
                // all structures are packed on word boundaries
1236
                $chunk_size++;
1237
            }
1238
1239
            switch ($chunk_name) {
1240
                case 'LIST':
1241
                    $list_name = $this->fread(4);
1242
1243
                    switch ($list_name) {
1244
                        case 'movi':
1245
                        case 'rec ':
1246
                            $riff_chunk[$list_name]['offset'] = $this->ftell() - 4;
1247
                            $riff_chunk[$list_name]['size']   = $chunk_size;
1248
1249
                            static $parsed_audio_stream = false;
1250
1251
                            if (!$parsed_audio_stream) {
1252
                                $where_we_were           = $this->ftell();
1253
                                $audio_chunk_header      = $this->fread(12);
1254
                                $audio_chunk_stream_num  = substr($audio_chunk_header, 0, 2);
0 ignored issues
show
Unused Code introduced by
The assignment to $audio_chunk_stream_num is dead and can be removed.
Loading history...
1255
                                $audio_chunk_stream_type = substr($audio_chunk_header, 2, 2);
1256
                                $audio_chunk_size        = getid3_lib::LittleEndian2Int(substr($audio_chunk_header, 4, 4));
1257
1258
                                if ('wb' == $audio_chunk_stream_type) {
1259
                                    $first_four_bytes = substr($audio_chunk_header, 8, 4);
1260
1261
                                    //// MPEG
1262
1263
                                    if (preg_match('/^\xFF[\xE2-\xE7\xF2-\xF7\xFA-\xFF][\x00-\xEB]/s', $first_four_bytes)) {
1264
                                        if (!$getid3->include_module_optional('audio.mp3')) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $getid3->include_module_optional('audio.mp3') of type null|true is loosely compared to false; this is ambiguous if the boolean can be false. You might want to explicitly use !== null instead.

If an expression can have both false, and null as possible values. It is generally a good practice to always use strict comparison to clearly distinguish between those two values.

$a = canBeFalseAndNull();

// Instead of
if ( ! $a) { }

// Better use one of the explicit versions:
if ($a !== null) { }
if ($a !== false) { }
if ($a !== null && $a !== false) { }
Loading history...
1265
                                            $getid3->warning('MP3 skipped because mp3 module is missing.');
1266
                                        } elseif (getid3_mp3::MPEGaudioHeaderBytesValid($first_four_bytes)) {
1267
                                            // Clone getid3 - messing with offsets - better safe than sorry
1268
                                            $clone                       = clone $getid3;
1269
                                            $clone->info['avdataoffset'] = $this->ftell() - 4;
1270
                                            $clone->info['avdataend']    = $this->ftell() + $audio_chunk_size;
1271
1272
                                            $mp3 = new getid3_mp3($clone);
1273
                                            $mp3->AnalyzeMPEGaudioInfo();
1274
1275
                                            // Import from clone and destroy
1276
                                            if (isset($clone->info['mpeg']['audio'])) {
1277
                                                $info['mpeg']['audio'] = $clone->info['mpeg']['audio'];
1278
1279
                                                $info['audio']['dataformat']   = 'mp' . $info['mpeg']['audio']['layer'];
1280
                                                $info['audio']['sample_rate']  = $info['mpeg']['audio']['sample_rate'];
1281
                                                $info['audio']['channels']     = $info['mpeg']['audio']['channels'];
1282
                                                $info['audio']['bitrate']      = $info['mpeg']['audio']['bitrate'];
1283
                                                $info['audio']['bitrate_mode'] = strtolower($info['mpeg']['audio']['bitrate_mode']);
1284
                                                $info['bitrate']               = $info['audio']['bitrate'];
1285
1286
                                                $getid3->warning($clone->warnings());
1287
                                                unset($clone);
1288
                                            }
1289
                                        }
1290
                                    } //// AC3-WAVE
1291
1292
                                    elseif (preg_match('/^\x0B\x77/s', $first_four_bytes)) {
1293
                                        if (!$getid3->include_module_optional('audio.ac3')) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $getid3->include_module_optional('audio.ac3') of type null|true is loosely compared to false; this is ambiguous if the boolean can be false. You might want to explicitly use !== null instead.

If an expression can have both false, and null as possible values. It is generally a good practice to always use strict comparison to clearly distinguish between those two values.

$a = canBeFalseAndNull();

// Instead of
if ( ! $a) { }

// Better use one of the explicit versions:
if ($a !== null) { }
if ($a !== false) { }
if ($a !== null && $a !== false) { }
Loading history...
1294
                                            $getid3->warning('AC3 skipped because ac3 module is missing.');
1295
                                        } else {
1296
                                            // Clone getid3 - messing with offsets - better safe than sorry
1297
                                            $clone                       = clone $getid3;
1298
                                            $clone->info['avdataoffset'] = $this->ftell() - 4;
1299
                                            $clone->info['avdataend']    = $this->ftell() + $audio_chunk_size;
1300
1301
                                            // Analyze clone by fp
1302
                                            $ac3 = new getid3_ac3($clone);
1303
                                            $ac3->Analyze();
1304
1305
                                            // Import from clone and destroy
1306
                                            $info['audio'] = $clone->info['audio'];
1307
                                            $info['ac3']   = $clone->info['ac3'];
1308
                                            $getid3->warning($clone->warnings());
1309
                                            unset($clone);
1310
                                        }
1311
                                    }
1312
                                }
1313
1314
                                $parsed_audio_stream = true;
1315
                                $this->fseek($where_we_were, SEEK_SET);
1316
                            }
1317
                            $this->fseek($chunk_size - 4, SEEK_CUR);
1318
                            break;
1319
1320
                        default:
1321
                            if (!isset($riff_chunk[$list_name])) {
1322
                                $riff_chunk[$list_name] = [];
1323
                            }
1324
                            $list_chunk_parent     = $list_name;
1325
                            $list_chunk_max_offset = $this->ftell() - 4 + $chunk_size;
1326
                            if ($parsed_chunk = $this->ParseRIFF($this->ftell(), $this->ftell() + $chunk_size - 4)) {
1327
                                $riff_chunk[$list_name] = array_merge_recursive($riff_chunk[$list_name], $parsed_chunk);
1328
                            }
1329
                            break;
1330
                    }
1331
                    break;
1332
1333
                default:
1334
1335
                    $this_index = 0;
1336
                    if (isset($riff_chunk[$chunk_name]) && is_array($riff_chunk[$chunk_name])) {
1337
                        $this_index = count($riff_chunk[$chunk_name]);
1338
                    }
1339
                    $riff_chunk[$chunk_name][$this_index]['offset'] = $this->ftell() - 8;
1340
                    $riff_chunk[$chunk_name][$this_index]['size']   = $chunk_size;
1341
                    switch ($chunk_name) {
1342
                        case 'data':
1343
                            $info['avdataoffset'] = $this->ftell();
1344
                            $info['avdataend']    = $info['avdataoffset'] + $chunk_size;
1345
1346
                            $riff_data_chunk_contents_test = $this->fread(36);
1347
1348
                            //// This is probably MP3 data
1349
1350
                            if ((strlen($riff_data_chunk_contents_test) > 0) && preg_match('/^\xFF[\xE2-\xE7\xF2-\xF7\xFA-\xFF][\x00-\xEB]/s', substr($riff_data_chunk_contents_test, 0, 4))) {
1351
                                try {
1352
                                    if (!$getid3->include_module_optional('audio.mp3')) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $getid3->include_module_optional('audio.mp3') of type null|true is loosely compared to false; this is ambiguous if the boolean can be false. You might want to explicitly use !== null instead.

If an expression can have both false, and null as possible values. It is generally a good practice to always use strict comparison to clearly distinguish between those two values.

$a = canBeFalseAndNull();

// Instead of
if ( ! $a) { }

// Better use one of the explicit versions:
if ($a !== null) { }
if ($a !== false) { }
if ($a !== null && $a !== false) { }
Loading history...
1353
                                        $getid3->warning('MP3 skipped because mp3 module is missing.');
1354
                                    }
1355
1356
                                    // Clone getid3 - messing with offsets - better safe than sorry
1357
                                    $clone = clone $getid3;
1358
1359
                                    if (getid3_mp3::MPEGaudioHeaderBytesValid(substr($riff_data_chunk_contents_test, 0, 4))) {
1360
                                        $mp3 = new getid3_mp3($clone);
1361
                                        $mp3->AnalyzeMPEGaudioInfo();
1362
1363
                                        // Import from clone and destroy
1364
                                        if (isset($clone->info['mpeg']['audio'])) {
1365
                                            $info['mpeg']['audio'] = $clone->info['mpeg']['audio'];
1366
1367
                                            $info['audio']['sample_rate']  = $info['mpeg']['audio']['sample_rate'];
1368
                                            $info['audio']['channels']     = $info['mpeg']['audio']['channels'];
1369
                                            $info['audio']['bitrate']      = $info['mpeg']['audio']['bitrate'];
1370
                                            $info['audio']['bitrate_mode'] = strtolower($info['mpeg']['audio']['bitrate_mode']);
1371
                                            $info['bitrate']               = $info['audio']['bitrate'];
1372
1373
                                            $getid3->warning($clone->warnings());
1374
                                            unset($clone);
1375
                                        }
1376
                                    }
1377
                                } catch (Exception $e) {
1378
                                    // do nothing - not MP3 data
1379
                                }
1380
                            } //// This is probably AC-3 data
1381
1382
                            elseif ((strlen($riff_data_chunk_contents_test) > 0) && ("\x0B\x77" == substr($riff_data_chunk_contents_test, 0, 2))) {
1383
                                if (!$getid3->include_module_optional('audio.ac3')) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $getid3->include_module_optional('audio.ac3') of type null|true is loosely compared to false; this is ambiguous if the boolean can be false. You might want to explicitly use !== null instead.

If an expression can have both false, and null as possible values. It is generally a good practice to always use strict comparison to clearly distinguish between those two values.

$a = canBeFalseAndNull();

// Instead of
if ( ! $a) { }

// Better use one of the explicit versions:
if ($a !== null) { }
if ($a !== false) { }
if ($a !== null && $a !== false) { }
Loading history...
1384
                                    $getid3->warning('AC3 skipped because ac3 module is missing.');
1385
                                } else {
1386
                                    // Clone getid3 - messing with offsets - better safe than sorry
1387
                                    $clone                       = clone $getid3;
1388
                                    $clone->info['avdataoffset'] = $riff_chunk[$chunk_name][$this_index]['offset'];
1389
                                    $clone->info['avdataend']    = $clone->info['avdataoffset'] + $riff_chunk[$chunk_name][$this_index]['size'];
1390
1391
                                    // Analyze clone by fp
1392
                                    $ac3 = new getid3_ac3($clone);
1393
                                    $ac3->Analyze();
1394
1395
                                    // Import from clone and destroy
1396
                                    $info['audio'] = $clone->info['audio'];
1397
                                    $info['ac3']   = $clone->info['ac3'];
1398
                                    $getid3->warning($clone->warnings());
1399
                                    unset($clone);
1400
                                }
1401
                            }
1402
1403
1404
                            // Dolby Digital WAV
1405
                            // AC-3 content, but not encoded in same format as normal AC-3 file
1406
                            // For one thing, byte order is swapped
1407
1408
                            elseif ((strlen($riff_data_chunk_contents_test) > 0) && ("\x77\x0B" == substr($riff_data_chunk_contents_test, 8, 2))) {
1409
                                if (!$getid3->include_module_optional('audio.ac3')) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $getid3->include_module_optional('audio.ac3') of type null|true is loosely compared to false; this is ambiguous if the boolean can be false. You might want to explicitly use !== null instead.

If an expression can have both false, and null as possible values. It is generally a good practice to always use strict comparison to clearly distinguish between those two values.

$a = canBeFalseAndNull();

// Instead of
if ( ! $a) { }

// Better use one of the explicit versions:
if ($a !== null) { }
if ($a !== false) { }
if ($a !== null && $a !== false) { }
Loading history...
1410
                                    $getid3->warning('AC3 skipped because ac3 module is missing.');
1411
                                } else {
1412
                                    // Extract ac3 data to string
1413
                                    $ac3_data = '';
1414
                                    for ($i = 0; $i < 28; $i += 2) {
1415
                                        // swap byte order
1416
                                        $ac3_data .= substr($riff_data_chunk_contents_test, 8 + $i + 1, 1);
1417
                                        $ac3_data .= substr($riff_data_chunk_contents_test, 8 + $i + 0, 1);
1418
                                    }
1419
1420
                                    // Clone getid3 - messing with offsets - better safe than sorry
1421
                                    $clone                       = clone $getid3;
1422
                                    $clone->info['avdataoffset'] = 0;
1423
                                    $clone->info['avdataend']    = 20;
1424
1425
                                    // Analyse clone by string
1426
                                    $ac3 = new getid3_ac3($clone);
1427
                                    $ac3->AnalyzeString($ac3_data);
1428
1429
                                    // Import from clone and destroy
1430
                                    $info['audio'] = $clone->info['audio'];
1431
                                    $info['ac3']   = $clone->info['ac3'];
1432
                                    $getid3->warning($clone->warnings());
1433
                                    unset($clone);
1434
                                }
1435
                            }
1436
1437
                            if ((strlen($riff_data_chunk_contents_test) > 0) && ('wvpk' == substr($riff_data_chunk_contents_test, 0, 4))) {
1438
                                // This is WavPack data
1439
                                $info['wavpack']['offset'] = $riff_chunk[$chunk_name][$this_index]['offset'];
1440
                                $info['wavpack']['size']   = getid3_lib::LittleEndian2Int(substr($riff_data_chunk_contents_test, 4, 4));
1441
                                $this->RIFFparseWavPackHeader(substr($riff_data_chunk_contents_test, 8, 28));
1442
                            } else {
1443
                                // This is some other kind of data (quite possibly just PCM)
1444
                                // do nothing special, just skip it
1445
1446
                            }
1447
                            $this->fseek($riff_chunk[$chunk_name][$this_index]['offset'] + 8 + $chunk_size, SEEK_SET);
1448
                            break;
1449
1450
                        case 'bext':
1451
                        case 'cart':
1452
                        case 'fmt ':
1453
                        case 'MEXT':
1454
                        case 'DISP':
1455
                            // always read data in
1456
                            $riff_chunk[$chunk_name][$this_index]['data'] = $this->fread($chunk_size);
1457
                            break;
1458
1459
                        default:
1460
                            if (!empty($list_chunk_parent) && (($riff_chunk[$chunk_name][$this_index]['offset'] + $riff_chunk[$chunk_name][$this_index]['size']) <= $list_chunk_max_offset)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $list_chunk_max_offset does not seem to be defined for all execution paths leading up to this point.
Loading history...
1461
                                $riff_chunk[$list_chunk_parent][$chunk_name][$this_index]['offset'] = $riff_chunk[$chunk_name][$this_index]['offset'];
1462
                                $riff_chunk[$list_chunk_parent][$chunk_name][$this_index]['size']   = $riff_chunk[$chunk_name][$this_index]['size'];
1463
                                unset($riff_chunk[$chunk_name][$this_index]['offset']);
1464
                                unset($riff_chunk[$chunk_name][$this_index]['size']);
1465
                                if (isset($riff_chunk[$chunk_name][$this_index]) && empty($riff_chunk[$chunk_name][$this_index])) {
1466
                                    unset($riff_chunk[$chunk_name][$this_index]);
1467
                                }
1468
                                if (isset($riff_chunk[$chunk_name]) && empty($riff_chunk[$chunk_name])) {
1469
                                    unset($riff_chunk[$chunk_name]);
1470
                                }
1471
                                $riff_chunk[$list_chunk_parent][$chunk_name][$this_index]['data'] = $this->fread($chunk_size);
1472
                            } elseif ($chunk_size < 2048) {
1473
                                // only read data in if smaller than 2kB
1474
                                $riff_chunk[$chunk_name][$this_index]['data'] = $this->fread($chunk_size);
1475
                            } else {
1476
                                $this->fseek($chunk_size, SEEK_CUR);
1477
                            }
1478
                            break;
1479
                    }
1480
                    break;
1481
            }
1482
        }
1483
1484
        return $riff_chunk;
1485
    }
1486
1487
    private function RIFFparseWavPackHeader($wavpack3_chunk_data)
1488
    {
1489
        // typedef struct {
1490
        //     char ckID [4];
1491
        //     long ckSize;
1492
        //     short version;
1493
        //     short bits;                // added for version 2.00
1494
        //     short flags, shift;        // added for version 3.00
1495
        //     long total_samples, crc, crc2;
1496
        //     char extension [4], extra_bc, extras [3];
1497
        // } WavpackHeader;
1498
1499
        $this->getid3->info['wavpack'] = [];
1500
        $info_wavpack                  = &$this->getid3->info['wavpack'];
1501
1502
        $info_wavpack['version'] = getid3_lib::LittleEndian2Int(substr($wavpack3_chunk_data, 0, 2));
1503
1504
        if ($info_wavpack['version'] >= 2) {
1505
            $info_wavpack['bits'] = getid3_lib::LittleEndian2Int(substr($wavpack3_chunk_data, 2, 2));
1506
        }
1507
1508
        if ($info_wavpack['version'] >= 3) {
1509
            getid3_lib::ReadSequence(
1510
                'LittleEndian2Int',
1511
                $info_wavpack,
1512
                $wavpack3_chunk_data,
1513
                4,
1514
                [
1515
                    'flags_raw'     => 2,
1516
                    'shift'         => 2,
1517
                    'total_samples' => 4,
1518
                    'crc1'          => 4,
1519
                    'crc2'          => 4,
1520
                    'extension'     => -4,
1521
                    'extra_bc'      => 1
1522
                ]
1523
            );
1524
1525
            for ($i = 0; $i < 3; $i++) {
1526
                $info_wavpack['extras'][] = getid3_lib::LittleEndian2Int($wavpack3_chunk_data{25 + $i});
1527
            }
1528
1529
            $info_wavpack['flags'] = [];
1530
            $info_wavpack_flags    = &$info_wavpack['flags'];
1531
1532
            $info_wavpack_flags['mono']                 = (bool)($info_wavpack['flags_raw'] & 0x000001);
1533
            $info_wavpack_flags['fast_mode']            = (bool)($info_wavpack['flags_raw'] & 0x000002);
1534
            $info_wavpack_flags['raw_mode']             = (bool)($info_wavpack['flags_raw'] & 0x000004);
1535
            $info_wavpack_flags['calc_noise']           = (bool)($info_wavpack['flags_raw'] & 0x000008);
1536
            $info_wavpack_flags['high_quality']         = (bool)($info_wavpack['flags_raw'] & 0x000010);
1537
            $info_wavpack_flags['3_byte_samples']       = (bool)($info_wavpack['flags_raw'] & 0x000020);
1538
            $info_wavpack_flags['over_20_bits']         = (bool)($info_wavpack['flags_raw'] & 0x000040);
1539
            $info_wavpack_flags['use_wvc']              = (bool)($info_wavpack['flags_raw'] & 0x000080);
1540
            $info_wavpack_flags['noiseshaping']         = (bool)($info_wavpack['flags_raw'] & 0x000100);
1541
            $info_wavpack_flags['very_fast_mode']       = (bool)($info_wavpack['flags_raw'] & 0x000200);
1542
            $info_wavpack_flags['new_high_quality']     = (bool)($info_wavpack['flags_raw'] & 0x000400);
1543
            $info_wavpack_flags['cancel_extreme']       = (bool)($info_wavpack['flags_raw'] & 0x000800);
1544
            $info_wavpack_flags['cross_decorrelation']  = (bool)($info_wavpack['flags_raw'] & 0x001000);
1545
            $info_wavpack_flags['new_decorrelation']    = (bool)($info_wavpack['flags_raw'] & 0x002000);
1546
            $info_wavpack_flags['joint_stereo']         = (bool)($info_wavpack['flags_raw'] & 0x004000);
1547
            $info_wavpack_flags['extra_decorrelation']  = (bool)($info_wavpack['flags_raw'] & 0x008000);
1548
            $info_wavpack_flags['override_noiseshape']  = (bool)($info_wavpack['flags_raw'] & 0x010000);
1549
            $info_wavpack_flags['override_jointstereo'] = (bool)($info_wavpack['flags_raw'] & 0x020000);
1550
            $info_wavpack_flags['copy_source_filetime'] = (bool)($info_wavpack['flags_raw'] & 0x040000);
1551
            $info_wavpack_flags['create_exe']           = (bool)($info_wavpack['flags_raw'] & 0x080000);
1552
        }
1553
1554
        return true;
1555
    }
1556
1557
    public function AnalyzeString(&$string)
1558
    {
1559
        // Rewrite header_size in header
1560
        $new_header_size = getid3_lib::LittleEndian2String(strlen($string), 4);
1561
        for ($i = 0; $i < 4; $i++) {
1562
            $string{$i + 4} = $new_header_size{$i};
1563
        }
1564
1565
        return parent::AnalyzeString($string);
0 ignored issues
show
Bug introduced by
Are you sure the usage of parent::AnalyzeString($string) targeting getid3_handler::AnalyzeString() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
1566
    }
1567
1568
    public static function RIFFparseWAVEFORMATex($wave_format_ex_data)
1569
    {
1570
        $wave_format_ex['raw'] = [];
0 ignored issues
show
Comprehensibility Best Practice introduced by
$wave_format_ex was never initialized. Although not strictly required by PHP, it is generally a good practice to add $wave_format_ex = array(); before regardless.
Loading history...
1571
        $wave_format_ex_raw    = &$wave_format_ex['raw'];
1572
1573
        getid3_lib::ReadSequence(
1574
            'LittleEndian2Int',
1575
            $wave_format_ex_raw,
1576
            $wave_format_ex_data,
1577
            0,
1578
            [
1579
                'wFormatTag'      => 2,
1580
                'nChannels'       => 2,
1581
                'nSamplesPerSec'  => 4,
1582
                'nAvgBytesPerSec' => 4,
1583
                'nBlockAlign'     => 2,
1584
                'wBitsPerSample'  => 2
1585
            ]
1586
        );
1587
1588
        if (strlen($wave_format_ex_data) > 16) {
1589
            $wave_format_ex_raw['cbSize'] = getid3_lib::LittleEndian2Int(substr($wave_format_ex_data, 16, 2));
1590
        }
1591
1592
        $wave_format_ex['codec']       = getid3_riff::RIFFwFormatTagLookup($wave_format_ex_raw['wFormatTag']);
1593
        $wave_format_ex['channels']    = $wave_format_ex_raw['nChannels'];
1594
        $wave_format_ex['sample_rate'] = $wave_format_ex_raw['nSamplesPerSec'];
1595
        $wave_format_ex['bitrate']     = $wave_format_ex_raw['nAvgBytesPerSec'] * 8;
1596
        if (@$wave_format_ex_raw['wBitsPerSample']) {
1597
            $wave_format_ex['bits_per_sample'] = $wave_format_ex_raw['wBitsPerSample'];
1598
        }
1599
1600
        return $wave_format_ex;
1601
    }
1602
1603
    public static function RIFFwFormatTagLookup($w_format_tag)
1604
    {
1605
        static $lookup = [
1606
            0x0000 => 'Microsoft Unknown Wave Format',
1607
            0x0001 => 'Pulse Code Modulation (PCM)',
1608
            0x0002 => 'Microsoft ADPCM',
1609
            0x0003 => 'IEEE Float',
1610
            0x0004 => 'Compaq Computer VSELP',
1611
            0x0005 => 'IBM CVSD',
1612
            0x0006 => 'Microsoft A-Law',
1613
            0x0007 => 'Microsoft mu-Law',
1614
            0x0008 => 'Microsoft DTS',
1615
            0x0010 => 'OKI ADPCM',
1616
            0x0011 => 'Intel DVI/IMA ADPCM',
1617
            0x0012 => 'Videologic MediaSpace ADPCM',
1618
            0x0013 => 'Sierra Semiconductor ADPCM',
1619
            0x0014 => 'Antex Electronics G.723 ADPCM',
1620
            0x0015 => 'DSP Solutions DigiSTD',
1621
            0x0016 => 'DSP Solutions DigiFIX',
1622
            0x0017 => 'Dialogic OKI ADPCM',
1623
            0x0018 => 'MediaVision ADPCM',
1624
            0x0019 => 'Hewlett-Packard CU',
1625
            0x0020 => 'Yamaha ADPCM',
1626
            0x0021 => 'Speech Compression Sonarc',
1627
            0x0022 => 'DSP Group TrueSpeech',
1628
            0x0023 => 'Echo Speech EchoSC1',
1629
            0x0024 => 'Audiofile AF36',
1630
            0x0025 => 'Audio Processing Technology APTX',
1631
            0x0026 => 'AudioFile AF10',
1632
            0x0027 => 'Prosody 1612',
1633
            0x0028 => 'LRC',
1634
            0x0030 => 'Dolby AC2',
1635
            0x0031 => 'Microsoft GSM 6.10',
1636
            0x0032 => 'MSNAudio',
1637
            0x0033 => 'Antex Electronics ADPCME',
1638
            0x0034 => 'Control Resources VQLPC',
1639
            0x0035 => 'DSP Solutions DigiREAL',
1640
            0x0036 => 'DSP Solutions DigiADPCM',
1641
            0x0037 => 'Control Resources CR10',
1642
            0x0038 => 'Natural MicroSystems VBXADPCM',
1643
            0x0039 => 'Crystal Semiconductor IMA ADPCM',
1644
            0x003A => 'EchoSC3',
1645
            0x003B => 'Rockwell ADPCM',
1646
            0x003C => 'Rockwell Digit LK',
1647
            0x003D => 'Xebec',
1648
            0x0040 => 'Antex Electronics G.721 ADPCM',
1649
            0x0041 => 'G.728 CELP',
1650
            0x0042 => 'MSG723',
1651
            0x0050 => 'MPEG Layer-2 or Layer-1',
1652
            0x0052 => 'RT24',
1653
            0x0053 => 'PAC',
1654
            0x0055 => 'MPEG Layer-3',
1655
            0x0059 => 'Lucent G.723',
1656
            0x0060 => 'Cirrus',
1657
            0x0061 => 'ESPCM',
1658
            0x0062 => 'Voxware',
1659
            0x0063 => 'Canopus Atrac',
1660
            0x0064 => 'G.726 ADPCM',
1661
            0x0065 => 'G.722 ADPCM',
1662
            0x0066 => 'DSAT',
1663
            0x0067 => 'DSAT Display',
1664
            0x0069 => 'Voxware Byte Aligned',
1665
            0x0070 => 'Voxware AC8',
1666
            0x0071 => 'Voxware AC10',
1667
            0x0072 => 'Voxware AC16',
1668
            0x0073 => 'Voxware AC20',
1669
            0x0074 => 'Voxware MetaVoice',
1670
            0x0075 => 'Voxware MetaSound',
1671
            0x0076 => 'Voxware RT29HW',
1672
            0x0077 => 'Voxware VR12',
1673
            0x0078 => 'Voxware VR18',
1674
            0x0079 => 'Voxware TQ40',
1675
            0x0080 => 'Softsound',
1676
            0x0081 => 'Voxware TQ60',
1677
            0x0082 => 'MSRT24',
1678
            0x0083 => 'G.729A',
1679
            0x0084 => 'MVI MV12',
1680
            0x0085 => 'DF G.726',
1681
            0x0086 => 'DF GSM610',
1682
            0x0088 => 'ISIAudio',
1683
            0x0089 => 'Onlive',
1684
            0x0091 => 'SBC24',
1685
            0x0092 => 'Dolby AC3 SPDIF',
1686
            0x0093 => 'MediaSonic G.723',
1687
            0x0094 => 'Aculab PLC    Prosody 8kbps',
1688
            0x0097 => 'ZyXEL ADPCM',
1689
            0x0098 => 'Philips LPCBB',
1690
            0x0099 => 'Packed',
1691
            0x00FF => 'AAC',
1692
            0x0100 => 'Rhetorex ADPCM',
1693
            0x0101 => 'IBM mu-law',
1694
            0x0102 => 'IBM A-law',
1695
            0x0103 => 'IBM AVC Adaptive Differential Pulse Code Modulation (ADPCM)',
1696
            0x0111 => 'Vivo G.723',
1697
            0x0112 => 'Vivo Siren',
1698
            0x0123 => 'Digital G.723',
1699
            0x0125 => 'Sanyo LD ADPCM',
1700
            0x0130 => 'Sipro Lab Telecom ACELP NET',
1701
            0x0131 => 'Sipro Lab Telecom ACELP 4800',
1702
            0x0132 => 'Sipro Lab Telecom ACELP 8V3',
1703
            0x0133 => 'Sipro Lab Telecom G.729',
1704
            0x0134 => 'Sipro Lab Telecom G.729A',
1705
            0x0135 => 'Sipro Lab Telecom Kelvin',
1706
            0x0140 => 'Windows Media Video V8',
1707
            0x0150 => 'Qualcomm PureVoice',
1708
            0x0151 => 'Qualcomm HalfRate',
1709
            0x0155 => 'Ring Zero Systems TUB GSM',
1710
            0x0160 => 'Microsoft Audio 1',
1711
            0x0161 => 'Windows Media Audio V7 / V8 / V9',
1712
            0x0162 => 'Windows Media Audio Professional V9',
1713
            0x0163 => 'Windows Media Audio Lossless V9',
1714
            0x0200 => 'Creative Labs ADPCM',
1715
            0x0202 => 'Creative Labs Fastspeech8',
1716
            0x0203 => 'Creative Labs Fastspeech10',
1717
            0x0210 => 'UHER Informatic GmbH ADPCM',
1718
            0x0220 => 'Quarterdeck',
1719
            0x0230 => 'I-link Worldwide VC',
1720
            0x0240 => 'Aureal RAW Sport',
1721
            0x0250 => 'Interactive Products HSX',
1722
            0x0251 => 'Interactive Products RPELP',
1723
            0x0260 => 'Consistent Software CS2',
1724
            0x0270 => 'Sony SCX',
1725
            0x0300 => 'Fujitsu FM Towns Snd',
1726
            0x0400 => 'BTV Digital',
1727
            0x0401 => 'Intel Music Coder',
1728
            0x0450 => 'QDesign Music',
1729
            0x0680 => 'VME VMPCM',
1730
            0x0681 => 'AT&T Labs TPC',
1731
            0x08AE => 'ClearJump LiteWave',
1732
            0x1000 => 'Olivetti GSM',
1733
            0x1001 => 'Olivetti ADPCM',
1734
            0x1002 => 'Olivetti CELP',
1735
            0x1003 => 'Olivetti SBC',
1736
            0x1004 => 'Olivetti OPR',
1737
            0x1100 => 'Lernout & Hauspie Codec (0x1100)',
1738
            0x1101 => 'Lernout & Hauspie CELP Codec (0x1101)',
1739
            0x1102 => 'Lernout & Hauspie SBC Codec (0x1102)',
1740
            0x1103 => 'Lernout & Hauspie SBC Codec (0x1103)',
1741
            0x1104 => 'Lernout & Hauspie SBC Codec (0x1104)',
1742
            0x1400 => 'Norris',
1743
            0x1401 => 'AT&T ISIAudio',
1744
            0x1500 => 'Soundspace Music Compression',
1745
            0x181C => 'VoxWare RT24 Speech',
1746
            0x1FC4 => 'NCT Soft ALF2CD (www.nctsoft.com)',
1747
            0x2000 => 'Dolby AC3',
1748
            0x2001 => 'Dolby DTS',
1749
            0x2002 => 'WAVE_FORMAT_14_4',
1750
            0x2003 => 'WAVE_FORMAT_28_8',
1751
            0x2004 => 'WAVE_FORMAT_COOK',
1752
            0x2005 => 'WAVE_FORMAT_DNET',
1753
            0x674F => 'Ogg Vorbis 1',
1754
            0x6750 => 'Ogg Vorbis 2',
1755
            0x6751 => 'Ogg Vorbis 3',
1756
            0x676F => 'Ogg Vorbis 1+',
1757
            0x6770 => 'Ogg Vorbis 2+',
1758
            0x6771 => 'Ogg Vorbis 3+',
1759
            0x7A21 => 'GSM-AMR (CBR, no SID)',
1760
            0x7A22 => 'GSM-AMR (VBR, including SID)',
1761
            0xFFFE => 'WAVE_FORMAT_EXTENSIBLE',
1762
            0xFFFF => 'WAVE_FORMAT_DEVELOPMENT'
1763
        ];
1764
1765
        return @$lookup[$w_format_tag];
1766
    }
1767
1768
    public static function RIFFfourccLookup($four_cc)
1769
    {
1770
        static $lookup = [
1771
            'swot' => 'http://developer.apple.com/qa/snd/snd07.html',
1772
            '____' => 'No Codec (____)',
1773
            '_BIT' => 'BI_BITFIELDS (Raw RGB)',
1774
            '_JPG' => 'JPEG compressed',
1775
            '_PNG' => 'PNG compressed W3C/ISO/IEC (RFC-2083)',
1776
            '_RAW' => 'Full Frames (Uncompressed)',
1777
            '_RGB' => 'Raw RGB Bitmap',
1778
            '_RL4' => 'RLE 4bpp RGB',
1779
            '_RL8' => 'RLE 8bpp RGB',
1780
            '3IV1' => '3ivx MPEG-4 v1',
1781
            '3IV2' => '3ivx MPEG-4 v2',
1782
            '3IVX' => '3ivx MPEG-4',
1783
            'AASC' => 'Autodesk Animator',
1784
            'ABYR' => 'Kensington ?ABYR?',
1785
            'AEMI' => 'Array Microsystems VideoONE MPEG1-I Capture',
1786
            'AFLC' => 'Autodesk Animator FLC',
1787
            'AFLI' => 'Autodesk Animator FLI',
1788
            'AMPG' => 'Array Microsystems VideoONE MPEG',
1789
            'ANIM' => 'Intel RDX (ANIM)',
1790
            'AP41' => 'AngelPotion Definitive',
1791
            'ASV1' => 'Asus Video v1',
1792
            'ASV2' => 'Asus Video v2',
1793
            'ASVX' => 'Asus Video 2.0 (audio)',
1794
            'AUR2' => 'AuraVision Aura 2 Codec - YUV 4:2:2',
1795
            'AURA' => 'AuraVision Aura 1 Codec - YUV 4:1:1',
1796
            'AVDJ' => 'Independent JPEG Group\'s codec (AVDJ)',
1797
            'AVRN' => 'Independent JPEG Group\'s codec (AVRN)',
1798
            'AYUV' => '4:4:4 YUV (AYUV)',
1799
            'AZPR' => 'Quicktime Apple Video (AZPR)',
1800
            'BGR ' => 'Raw RGB32',
1801
            'BLZ0' => 'FFmpeg MPEG-4',
1802
            'BTVC' => 'Conexant Composite Video',
1803
            'BINK' => 'RAD Game Tools Bink Video',
1804
            'BT20' => 'Conexant Prosumer Video',
1805
            'BTCV' => 'Conexant Composite Video Codec',
1806
            'BW10' => 'Data Translation Broadway MPEG Capture',
1807
            'CC12' => 'Intel YUV12',
1808
            'CDVC' => 'Canopus DV',
1809
            'CFCC' => 'Digital Processing Systems DPS Perception',
1810
            'CGDI' => 'Microsoft Office 97 Camcorder Video',
1811
            'CHAM' => 'Winnov Caviara Champagne',
1812
            'CJPG' => 'Creative WebCam JPEG',
1813
            'CLJR' => 'Cirrus Logic YUV 4:1:1',
1814
            'CMYK' => 'Common Data Format in Printing (Colorgraph)',
1815
            'CPLA' => 'Weitek 4:2:0 YUV Planar',
1816
            'CRAM' => 'Microsoft Video 1 (CRAM)',
1817
            'cvid' => 'Radius Cinepak',
1818
            'CVID' => 'Radius Cinepak',
1819
            'CWLT' => 'Microsoft Color WLT DIB',
1820
            'CYUV' => 'Creative Labs YUV',
1821
            'CYUY' => 'ATI YUV',
1822
            'D261' => 'H.261',
1823
            'D263' => 'H.263',
1824
            'DIB ' => 'Device Independent Bitmap',
1825
            'DIV1' => 'FFmpeg OpenDivX',
1826
            'DIV2' => 'Microsoft MPEG-4 v1/v2',
1827
            'DIV3' => 'DivX ;-) MPEG-4 v3.x Low-Motion',
1828
            'DIV4' => 'DivX ;-) MPEG-4 v3.x Fast-Motion',
1829
            'DIV5' => 'DivX MPEG-4 v5.x',
1830
            'DIV6' => 'DivX ;-) (MS MPEG-4 v3.x)',
1831
            'DIVX' => 'DivX MPEG-4 v4 (OpenDivX / Project Mayo)',
1832
            'divx' => 'DivX MPEG-4',
1833
            'DMB1' => 'Matrox Rainbow Runner hardware MJPEG',
1834
            'DMB2' => 'Paradigm MJPEG',
1835
            'DSVD' => '?DSVD?',
1836
            'DUCK' => 'Duck TrueMotion 1.0',
1837
            'DPS0' => 'DPS/Leitch Reality Motion JPEG',
1838
            'DPSC' => 'DPS/Leitch PAR Motion JPEG',
1839
            'DV25' => 'Matrox DVCPRO codec',
1840
            'DV50' => 'Matrox DVCPRO50 codec',
1841
            'DVC ' => 'IEC 61834 and SMPTE 314M (DVC/DV Video)',
1842
            'DVCP' => 'IEC 61834 and SMPTE 314M (DVC/DV Video)',
1843
            'DVHD' => 'IEC Standard DV 1125 lines @ 30fps / 1250 lines @ 25fps',
1844
            'DVMA' => 'Darim Vision DVMPEG (dummy for MPEG compressor) (www.darvision.com)',
1845
            'DVSL' => 'IEC Standard DV compressed in SD (SDL)',
1846
            'DVAN' => '?DVAN?',
1847
            'DVE2' => 'InSoft DVE-2 Videoconferencing',
1848
            'dvsd' => 'IEC 61834 and SMPTE 314M DVC/DV Video',
1849
            'DVSD' => 'IEC 61834 and SMPTE 314M DVC/DV Video',
1850
            'DVX1' => 'Lucent DVX1000SP Video Decoder',
1851
            'DVX2' => 'Lucent DVX2000S Video Decoder',
1852
            'DVX3' => 'Lucent DVX3000S Video Decoder',
1853
            'DX50' => 'DivX v5',
1854
            'DXT1' => 'Microsoft DirectX Compressed Texture (DXT1)',
1855
            'DXT2' => 'Microsoft DirectX Compressed Texture (DXT2)',
1856
            'DXT3' => 'Microsoft DirectX Compressed Texture (DXT3)',
1857
            'DXT4' => 'Microsoft DirectX Compressed Texture (DXT4)',
1858
            'DXT5' => 'Microsoft DirectX Compressed Texture (DXT5)',
1859
            'DXTC' => 'Microsoft DirectX Compressed Texture (DXTC)',
1860
            'DXTn' => 'Microsoft DirectX Compressed Texture (DXTn)',
1861
            'EM2V' => 'Etymonix MPEG-2 I-frame (www.etymonix.com)',
1862
            'EKQ0' => 'Elsa ?EKQ0?',
1863
            'ELK0' => 'Elsa ?ELK0?',
1864
            'ESCP' => 'Eidos Escape',
1865
            'ETV1' => 'eTreppid Video ETV1',
1866
            'ETV2' => 'eTreppid Video ETV2',
1867
            'ETVC' => 'eTreppid Video ETVC',
1868
            'FLIC' => 'Autodesk FLI/FLC Animation',
1869
            'FRWT' => 'Darim Vision Forward Motion JPEG (www.darvision.com)',
1870
            'FRWU' => 'Darim Vision Forward Uncompressed (www.darvision.com)',
1871
            'FLJP' => 'D-Vision Field Encoded Motion JPEG',
1872
            'FRWA' => 'SoftLab-Nsk Forward Motion JPEG w/ alpha channel',
1873
            'FRWD' => 'SoftLab-Nsk Forward Motion JPEG',
1874
            'FVF1' => 'Iterated Systems Fractal Video Frame',
1875
            'GLZW' => 'Motion LZW ([email protected])',
1876
            'GPEG' => 'Motion JPEG ([email protected])',
1877
            'GWLT' => 'Microsoft Greyscale WLT DIB',
1878
            'H260' => 'Intel ITU H.260 Videoconferencing',
1879
            'H261' => 'Intel ITU H.261 Videoconferencing',
1880
            'H262' => 'Intel ITU H.262 Videoconferencing',
1881
            'H263' => 'Intel ITU H.263 Videoconferencing',
1882
            'H264' => 'Intel ITU H.264 Videoconferencing',
1883
            'H265' => 'Intel ITU H.265 Videoconferencing',
1884
            'H266' => 'Intel ITU H.266 Videoconferencing',
1885
            'H267' => 'Intel ITU H.267 Videoconferencing',
1886
            'H268' => 'Intel ITU H.268 Videoconferencing',
1887
            'H269' => 'Intel ITU H.269 Videoconferencing',
1888
            'HFYU' => 'Huffman Lossless Codec',
1889
            'HMCR' => 'Rendition Motion Compensation Format (HMCR)',
1890
            'HMRR' => 'Rendition Motion Compensation Format (HMRR)',
1891
            'I263' => 'FFmpeg I263 decoder',
1892
            'IF09' => 'Indeo YVU9 ("YVU9 with additional delta-frame info after the U plane")',
1893
            'IUYV' => 'Interlaced version of UYVY (www.leadtools.com)',
1894
            'IY41' => 'Interlaced version of Y41P (www.leadtools.com)',
1895
            'IYU1' => '12 bit format used in mode 2 of the IEEE 1394 Digital Camera 1.04 spec    IEEE standard',
1896
            'IYU2' => '24 bit format used in mode 2 of the IEEE 1394 Digital Camera 1.04 spec    IEEE standard',
1897
            'IYUV' => 'Planar YUV format (8-bpp Y plane, followed by 8-bpp 2�2 U and V planes)',
1898
            'i263' => 'Intel ITU H.263 Videoconferencing (i263)',
1899
            'I420' => 'Intel Indeo 4',
1900
            'IAN ' => 'Intel Indeo 4 (RDX)',
1901
            'ICLB' => 'InSoft CellB Videoconferencing',
1902
            'IGOR' => 'Power DVD',
1903
            'IJPG' => 'Intergraph JPEG',
1904
            'ILVC' => 'Intel Layered Video',
1905
            'ILVR' => 'ITU-T H.263+',
1906
            'IPDV' => 'I-O Data Device Giga AVI DV Codec',
1907
            'IR21' => 'Intel Indeo 2.1',
1908
            'IRAW' => 'Intel YUV Uncompressed',
1909
            'IV30' => 'Intel Indeo 3.0',
1910
            'IV31' => 'Intel Indeo 3.1',
1911
            'IV32' => 'Ligos Indeo 3.2',
1912
            'IV33' => 'Ligos Indeo 3.3',
1913
            'IV34' => 'Ligos Indeo 3.4',
1914
            'IV35' => 'Ligos Indeo 3.5',
1915
            'IV36' => 'Ligos Indeo 3.6',
1916
            'IV37' => 'Ligos Indeo 3.7',
1917
            'IV38' => 'Ligos Indeo 3.8',
1918
            'IV39' => 'Ligos Indeo 3.9',
1919
            'IV40' => 'Ligos Indeo Interactive 4.0',
1920
            'IV41' => 'Ligos Indeo Interactive 4.1',
1921
            'IV42' => 'Ligos Indeo Interactive 4.2',
1922
            'IV43' => 'Ligos Indeo Interactive 4.3',
1923
            'IV44' => 'Ligos Indeo Interactive 4.4',
1924
            'IV45' => 'Ligos Indeo Interactive 4.5',
1925
            'IV46' => 'Ligos Indeo Interactive 4.6',
1926
            'IV47' => 'Ligos Indeo Interactive 4.7',
1927
            'IV48' => 'Ligos Indeo Interactive 4.8',
1928
            'IV49' => 'Ligos Indeo Interactive 4.9',
1929
            'IV50' => 'Ligos Indeo Interactive 5.0',
1930
            'JBYR' => 'Kensington ?JBYR?',
1931
            'JPEG' => 'Still Image JPEG DIB',
1932
            'JPGL' => 'Pegasus Lossless Motion JPEG',
1933
            'KMVC' => 'Team17 Software Karl Morton\'s Video Codec',
1934
            'LSVM' => 'Vianet Lighting Strike Vmail (Streaming) (www.vianet.com)',
1935
            'LEAD' => 'LEAD Video Codec',
1936
            'Ljpg' => 'LEAD MJPEG Codec',
1937
            'MDVD' => 'Alex MicroDVD Video (hacked MS MPEG-4) (www.tiasoft.de)',
1938
            'MJPA' => 'Morgan Motion JPEG (MJPA) (www.morgan-multimedia.com)',
1939
            'MJPB' => 'Morgan Motion JPEG (MJPB) (www.morgan-multimedia.com)',
1940
            'MMES' => 'Matrox MPEG-2 I-frame',
1941
            'MP2v' => 'Microsoft S-Mpeg 4 version 1 (MP2v)',
1942
            'MP42' => 'Microsoft S-Mpeg 4 version 2 (MP42)',
1943
            'MP43' => 'Microsoft S-Mpeg 4 version 3 (MP43)',
1944
            'MP4S' => 'Microsoft S-Mpeg 4 version 3 (MP4S)',
1945
            'MP4V' => 'FFmpeg MPEG-4',
1946
            'MPG1' => 'FFmpeg MPEG 1/2',
1947
            'MPG2' => 'FFmpeg MPEG 1/2',
1948
            'MPG3' => 'FFmpeg DivX ;-) (MS MPEG-4 v3)',
1949
            'MPG4' => 'Microsoft MPEG-4',
1950
            'MPGI' => 'Sigma Designs MPEG',
1951
            'MPNG' => 'PNG images decoder',
1952
            'MSS1' => 'Microsoft Windows Screen Video',
1953
            'MSZH' => 'LCL (Lossless Codec Library) (www.geocities.co.jp/Playtown-Denei/2837/LRC.htm)',
1954
            'M261' => 'Microsoft H.261',
1955
            'M263' => 'Microsoft H.263',
1956
            'M4S2' => 'Microsoft Fully Compliant MPEG-4 v2 simple profile (M4S2)',
1957
            'm4s2' => 'Microsoft Fully Compliant MPEG-4 v2 simple profile (m4s2)',
1958
            'MC12' => 'ATI Motion Compensation Format (MC12)',
1959
            'MCAM' => 'ATI Motion Compensation Format (MCAM)',
1960
            'MJ2C' => 'Morgan Multimedia Motion JPEG2000',
1961
            'mJPG' => 'IBM Motion JPEG w/ Huffman Tables',
1962
            'MJPG' => 'Microsoft Motion JPEG DIB',
1963
            'MP42' => 'Microsoft MPEG-4 (low-motion)',
1964
            'MP43' => 'Microsoft MPEG-4 (fast-motion)',
1965
            'MP4S' => 'Microsoft MPEG-4 (MP4S)',
1966
            'mp4s' => 'Microsoft MPEG-4 (mp4s)',
1967
            'MPEG' => 'Chromatic Research MPEG-1 Video I-Frame',
1968
            'MPG4' => 'Microsoft MPEG-4 Video High Speed Compressor',
1969
            'MPGI' => 'Sigma Designs MPEG',
1970
            'MRCA' => 'FAST Multimedia Martin Regen Codec',
1971
            'MRLE' => 'Microsoft Run Length Encoding',
1972
            'MSVC' => 'Microsoft Video 1',
1973
            'MTX1' => 'Matrox ?MTX1?',
1974
            'MTX2' => 'Matrox ?MTX2?',
1975
            'MTX3' => 'Matrox ?MTX3?',
1976
            'MTX4' => 'Matrox ?MTX4?',
1977
            'MTX5' => 'Matrox ?MTX5?',
1978
            'MTX6' => 'Matrox ?MTX6?',
1979
            'MTX7' => 'Matrox ?MTX7?',
1980
            'MTX8' => 'Matrox ?MTX8?',
1981
            'MTX9' => 'Matrox ?MTX9?',
1982
            'MV12' => 'Motion Pixels Codec (old)',
1983
            'MWV1' => 'Aware Motion Wavelets',
1984
            'nAVI' => 'SMR Codec (hack of Microsoft MPEG-4) (IRC #shadowrealm)',
1985
            'NT00' => 'NewTek LightWave HDTV YUV w/ Alpha (www.newtek.com)',
1986
            'NUV1' => 'NuppelVideo',
1987
            'NTN1' => 'Nogatech Video Compression 1',
1988
            'NVS0' => 'nVidia GeForce Texture (NVS0)',
1989
            'NVS1' => 'nVidia GeForce Texture (NVS1)',
1990
            'NVS2' => 'nVidia GeForce Texture (NVS2)',
1991
            'NVS3' => 'nVidia GeForce Texture (NVS3)',
1992
            'NVS4' => 'nVidia GeForce Texture (NVS4)',
1993
            'NVS5' => 'nVidia GeForce Texture (NVS5)',
1994
            'NVT0' => 'nVidia GeForce Texture (NVT0)',
1995
            'NVT1' => 'nVidia GeForce Texture (NVT1)',
1996
            'NVT2' => 'nVidia GeForce Texture (NVT2)',
1997
            'NVT3' => 'nVidia GeForce Texture (NVT3)',
1998
            'NVT4' => 'nVidia GeForce Texture (NVT4)',
1999
            'NVT5' => 'nVidia GeForce Texture (NVT5)',
2000
            'PIXL' => 'MiroXL, Pinnacle PCTV',
2001
            'PDVC' => 'I-O Data Device Digital Video Capture DV codec',
2002
            'PGVV' => 'Radius Video Vision',
2003
            'PHMO' => 'IBM Photomotion',
2004
            'PIM1' => 'MPEG Realtime (Pinnacle Cards)',
2005
            'PIM2' => 'Pegasus Imaging ?PIM2?',
2006
            'PIMJ' => 'Pegasus Imaging Lossless JPEG',
2007
            'PVEZ' => 'Horizons Technology PowerEZ',
2008
            'PVMM' => 'PacketVideo Corporation MPEG-4',
2009
            'PVW2' => 'Pegasus Imaging Wavelet Compression',
2010
            'Q1.0' => 'Q-Team\'s QPEG 1.0 (www.q-team.de)',
2011
            'Q1.1' => 'Q-Team\'s QPEG 1.1 (www.q-team.de)',
2012
            'QPEG' => 'Q-Team QPEG 1.0',
2013
            'qpeq' => 'Q-Team QPEG 1.1',
2014
            'RGB ' => 'Raw BGR32',
2015
            'RGBA' => 'Raw RGB w/ Alpha',
2016
            'RMP4' => 'REALmagic MPEG-4 (unauthorized XVID copy) (www.sigmadesigns.com)',
2017
            'ROQV' => 'Id RoQ File Video Decoder',
2018
            'RPZA' => 'Quicktime Apple Video (RPZA)',
2019
            'RUD0' => 'Rududu video codec (http://rududu.ifrance.com/rududu/)',
2020
            'RV10' => 'RealVideo 1.0 (aka RealVideo 5.0)',
2021
            'RV13' => 'RealVideo 1.0 (RV13)',
2022
            'RV20' => 'RealVideo G2',
2023
            'RV30' => 'RealVideo 8',
2024
            'RV40' => 'RealVideo 9',
2025
            'RGBT' => 'Raw RGB w/ Transparency',
2026
            'RLE ' => 'Microsoft Run Length Encoder',
2027
            'RLE4' => 'Run Length Encoded (4bpp, 16-color)',
2028
            'RLE8' => 'Run Length Encoded (8bpp, 256-color)',
2029
            'RT21' => 'Intel Indeo RealTime Video 2.1',
2030
            'rv20' => 'RealVideo G2',
2031
            'rv30' => 'RealVideo 8',
2032
            'RVX ' => 'Intel RDX (RVX )',
2033
            'SMC ' => 'Apple Graphics (SMC )',
2034
            'SP54' => 'Logitech Sunplus Sp54 Codec for Mustek GSmart Mini 2',
2035
            'SPIG' => 'Radius Spigot',
2036
            'SVQ3' => 'Sorenson Video 3 (Apple Quicktime 5)',
2037
            's422' => 'Tekram VideoCap C210 YUV 4:2:2',
2038
            'SDCC' => 'Sun Communication Digital Camera Codec',
2039
            'SFMC' => 'CrystalNet Surface Fitting Method',
2040
            'SMSC' => 'Radius SMSC',
2041
            'SMSD' => 'Radius SMSD',
2042
            'smsv' => 'WorldConnect Wavelet Video',
2043
            'SPIG' => 'Radius Spigot',
2044
            'SPLC' => 'Splash Studios ACM Audio Codec (www.splashstudios.net)',
2045
            'SQZ2' => 'Microsoft VXTreme Video Codec V2',
2046
            'STVA' => 'ST Microelectronics CMOS Imager Data (Bayer)',
2047
            'STVB' => 'ST Microelectronics CMOS Imager Data (Nudged Bayer)',
2048
            'STVC' => 'ST Microelectronics CMOS Imager Data (Bunched)',
2049
            'STVX' => 'ST Microelectronics CMOS Imager Data (Extended CODEC Data Format)',
2050
            'STVY' => 'ST Microelectronics CMOS Imager Data (Extended CODEC Data Format with Correction Data)',
2051
            'SV10' => 'Sorenson Video R1',
2052
            'SVQ1' => 'Sorenson Video',
2053
            'T420' => 'Toshiba YUV 4:2:0',
2054
            'TM2A' => 'Duck TrueMotion Archiver 2.0 (www.duck.com)',
2055
            'TVJP' => 'Pinnacle/Truevision Targa 2000 board (TVJP)',
2056
            'TVMJ' => 'Pinnacle/Truevision Targa 2000 board (TVMJ)',
2057
            'TY0N' => 'Tecomac Low-Bit Rate Codec (www.tecomac.com)',
2058
            'TY2C' => 'Trident Decompression Driver',
2059
            'TLMS' => 'TeraLogic Motion Intraframe Codec (TLMS)',
2060
            'TLST' => 'TeraLogic Motion Intraframe Codec (TLST)',
2061
            'TM20' => 'Duck TrueMotion 2.0',
2062
            'TM2X' => 'Duck TrueMotion 2X',
2063
            'TMIC' => 'TeraLogic Motion Intraframe Codec (TMIC)',
2064
            'TMOT' => 'Horizons Technology TrueMotion S',
2065
            'tmot' => 'Horizons TrueMotion Video Compression',
2066
            'TR20' => 'Duck TrueMotion RealTime 2.0',
2067
            'TSCC' => 'TechSmith Screen Capture Codec',
2068
            'TV10' => 'Tecomac Low-Bit Rate Codec',
2069
            'TY2N' => 'Trident ?TY2N?',
2070
            'U263' => 'UB Video H.263/H.263+/H.263++ Decoder',
2071
            'UMP4' => 'UB Video MPEG 4 (www.ubvideo.com)',
2072
            'UYNV' => 'Nvidia UYVY packed 4:2:2',
2073
            'UYVP' => 'Evans & Sutherland YCbCr 4:2:2 extended precision',
2074
            'UCOD' => 'eMajix.com ClearVideo',
2075
            'ULTI' => 'IBM Ultimotion',
2076
            'UYVY' => 'UYVY packed 4:2:2',
2077
            'V261' => 'Lucent VX2000S',
2078
            'VIFP' => 'VFAPI Reader Codec (www.yks.ne.jp/~hori/)',
2079
            'VIV1' => 'FFmpeg H263+ decoder',
2080
            'VIV2' => 'Vivo H.263',
2081
            'VQC2' => 'Vector-quantised codec 2 (research) http://eprints.ecs.soton.ac.uk/archive/00001310/01/VTC97-js.pdf)',
2082
            'VTLP' => 'Alaris VideoGramPiX',
2083
            'VYU9' => 'ATI YUV (VYU9)',
2084
            'VYUY' => 'ATI YUV (VYUY)',
2085
            'V261' => 'Lucent VX2000S',
2086
            'V422' => 'Vitec Multimedia 24-bit YUV 4:2:2 Format',
2087
            'V655' => 'Vitec Multimedia 16-bit YUV 4:2:2 Format',
2088
            'VCR1' => 'ATI Video Codec 1',
2089
            'VCR2' => 'ATI Video Codec 2',
2090
            'VCR3' => 'ATI VCR 3.0',
2091
            'VCR4' => 'ATI VCR 4.0',
2092
            'VCR5' => 'ATI VCR 5.0',
2093
            'VCR6' => 'ATI VCR 6.0',
2094
            'VCR7' => 'ATI VCR 7.0',
2095
            'VCR8' => 'ATI VCR 8.0',
2096
            'VCR9' => 'ATI VCR 9.0',
2097
            'VDCT' => 'Vitec Multimedia Video Maker Pro DIB',
2098
            'VDOM' => 'VDOnet VDOWave',
2099
            'VDOW' => 'VDOnet VDOLive (H.263)',
2100
            'VDTZ' => 'Darim Vison VideoTizer YUV',
2101
            'VGPX' => 'Alaris VideoGramPiX',
2102
            'VIDS' => 'Vitec Multimedia YUV 4:2:2 CCIR 601 for V422',
2103
            'VIVO' => 'Vivo H.263 v2.00',
2104
            'vivo' => 'Vivo H.263',
2105
            'VIXL' => 'Miro/Pinnacle Video XL',
2106
            'VLV1' => 'VideoLogic/PURE Digital Videologic Capture',
2107
            'VP30' => 'On2 VP3.0',
2108
            'VP31' => 'On2 VP3.1',
2109
            'VX1K' => 'Lucent VX1000S Video Codec',
2110
            'VX2K' => 'Lucent VX2000S Video Codec',
2111
            'VXSP' => 'Lucent VX1000SP Video Codec',
2112
            'WBVC' => 'Winbond W9960',
2113
            'WHAM' => 'Microsoft Video 1 (WHAM)',
2114
            'WINX' => 'Winnov Software Compression',
2115
            'WJPG' => 'AverMedia Winbond JPEG',
2116
            'WMV1' => 'Windows Media Video V7',
2117
            'WMV2' => 'Windows Media Video V8',
2118
            'WMV3' => 'Windows Media Video V9',
2119
            'WNV1' => 'Winnov Hardware Compression',
2120
            'XYZP' => 'Extended PAL format XYZ palette (www.riff.org)',
2121
            'x263' => 'Xirlink H.263',
2122
            'XLV0' => 'NetXL Video Decoder',
2123
            'XMPG' => 'Xing MPEG (I-Frame only)',
2124
            'XVID' => 'XviD MPEG-4 (www.xvid.org)',
2125
            'XXAN' => '?XXAN?',
2126
            'YU92' => 'Intel YUV (YU92)',
2127
            'YUNV' => 'Nvidia Uncompressed YUV 4:2:2',
2128
            'YUVP' => 'Extended PAL format YUV palette (www.riff.org)',
2129
            'Y211' => 'YUV 2:1:1 Packed',
2130
            'Y411' => 'YUV 4:1:1 Packed',
2131
            'Y41B' => 'Weitek YUV 4:1:1 Planar',
2132
            'Y41P' => 'Brooktree PC1 YUV 4:1:1 Packed',
2133
            'Y41T' => 'Brooktree PC1 YUV 4:1:1 with transparency',
2134
            'Y42B' => 'Weitek YUV 4:2:2 Planar',
2135
            'Y42T' => 'Brooktree UYUV 4:2:2 with transparency',
2136
            'Y422' => 'ADS Technologies Copy of UYVY used in Pyro WebCam firewire camera',
2137
            'Y800' => 'Simple, single Y plane for monochrome images',
2138
            'Y8  ' => 'Grayscale video',
2139
            'YC12' => 'Intel YUV 12 codec',
2140
            'YUV8' => 'Winnov Caviar YUV8',
2141
            'YUV9' => 'Intel YUV9',
2142
            'YUY2' => 'Uncompressed YUV 4:2:2',
2143
            'YUYV' => 'Canopus YUV',
2144
            'YV12' => 'YVU12 Planar',
2145
            'YVU9' => 'Intel YVU9 Planar (8-bpp Y plane, followed by 8-bpp 4x4 U and V planes)',
2146
            'YVYU' => 'YVYU 4:2:2 Packed',
2147
            'ZLIB' => 'Lossless Codec Library zlib compression (www.geocities.co.jp/Playtown-Denei/2837/LRC.htm)',
2148
            'ZPEG' => 'Metheus Video Zipper'
2149
        ];
2150
2151
        return @$lookup[$four_cc];
2152
    }
2153
2154
    public static function RIFFcommentsParse(&$riff_info_aray, &$comments_target_array)
2155
    {
2156
        static $lookup = [
2157
            'IARL' => 'archivallocation',
2158
            'IART' => 'artist',
2159
            'ICDS' => 'costumedesigner',
2160
            'ICMS' => 'commissionedby',
2161
            'ICMT' => 'comment',
2162
            'ICNT' => 'country',
2163
            'ICOP' => 'copyright',
2164
            'ICRD' => 'creationdate',
2165
            'IDIM' => 'dimensions',
2166
            'IDIT' => 'digitizationdate',
2167
            'IDPI' => 'resolution',
2168
            'IDST' => 'distributor',
2169
            'IEDT' => 'editor',
2170
            'IENG' => 'engineers',
2171
            'IFRM' => 'accountofparts',
2172
            'IGNR' => 'genre',
2173
            'IKEY' => 'keywords',
2174
            'ILGT' => 'lightness',
2175
            'ILNG' => 'language',
2176
            'IMED' => 'orignalmedium',
2177
            'IMUS' => 'composer',
2178
            'INAM' => 'title',
2179
            'IPDS' => 'productiondesigner',
2180
            'IPLT' => 'palette',
2181
            'IPRD' => 'product',
2182
            'IPRO' => 'producer',
2183
            'IPRT' => 'part',
2184
            'IRTD' => 'rating',
2185
            'ISBJ' => 'subject',
2186
            'ISFT' => 'software',
2187
            'ISGN' => 'secondarygenre',
2188
            'ISHP' => 'sharpness',
2189
            'ISRC' => 'sourcesupplier',
2190
            'ISRF' => 'digitizationsource',
2191
            'ISTD' => 'productionstudio',
2192
            'ISTR' => 'starring',
2193
            'ITCH' => 'encoded_by',
2194
            'IWEB' => 'url',
2195
            'IWRI' => 'writer'
2196
        ];
2197
2198
        foreach ($lookup as $key => $value) {
2199
            if (isset($riff_info_aray[$key])) {
2200
                foreach ($riff_info_aray[$key] as $comment_id => $comment_data) {
2201
                    if ('' != trim($comment_data['data'])) {
2202
                        @$comments_target_array[$value][] = trim($comment_data['data']);
2203
                    }
2204
                }
2205
            }
2206
        }
2207
        return true;
2208
    }
2209
2210
    public static function array_merge_noclobber($array1, $array2)
2211
    {
2212
        if (!is_array($array1) || !is_array($array2)) {
2213
            return false;
2214
        }
2215
        $new_array = $array1;
2216
        foreach ($array2 as $key => $val) {
2217
            if (is_array($val) && isset($new_array[$key]) && is_array($new_array[$key])) {
2218
                $new_array[$key] = getid3_riff::array_merge_noclobber($new_array[$key], $val);
2219
            } elseif (!isset($new_array[$key])) {
2220
                $new_array[$key] = $val;
2221
            }
2222
        }
2223
        return $new_array;
2224
    }
2225
2226
    public static function DateMac2Unix($mac_date)
2227
    {
2228
        // Macintosh timestamp: seconds since 00:00h January 1, 1904
2229
        // UNIX timestamp:      seconds since 00:00h January 1, 1970
2230
        return (int)($mac_date - 2082844800);
2231
    }
2232
2233
    public static function FixedPoint16_16($raw_data)
2234
    {
2235
        return getid3_lib::BigEndian2Int(substr($raw_data, 0, 2)) + (float)(getid3_lib::BigEndian2Int(substr($raw_data, 2, 2)) / 65536);  // pow(2, 16) = 65536
2236
    }
2237
2238
    public function BigEndian2Float($byte_word)
2239
    {
2240
        // ANSI/IEEE Standard 754-1985, Standard for Binary Floating Point Arithmetic
2241
        // http://www.psc.edu/general/software/packages/ieee/ieee.html
2242
        // http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/ieee.html
2243
2244
        $bit_word = getid3_lib::BigEndian2Bin($byte_word);
2245
        $sign_bit = $bit_word{0};
2246
2247
        switch (strlen($byte_word) * 8) {
2248
            case 32:
2249
                $exponent_bits = 8;
2250
                $fraction_bits = 23;
2251
                break;
2252
2253
            case 64:
2254
                $exponent_bits = 11;
2255
                $fraction_bits = 52;
2256
                break;
2257
2258
            case 80:
2259
                // 80-bit Apple SANE format
2260
                // http://www.mactech.com/articles/mactech/Vol.06/06.01/SANENormalized/
2261
                $exponent_string = substr($bit_word, 1, 15);
2262
                $is_normalized   = intval($bit_word{16});
2263
                $fraction_string = substr($bit_word, 17, 63);
2264
                $exponent        = pow(2, bindec($exponent_string) - 16383);
2265
                $fraction        = $is_normalized + bindec($fraction_string) / bindec('1' . str_repeat('0', strlen($fraction_string)));
2266
                $float_value     = $exponent * $fraction;
2267
                if ('1' == $sign_bit) {
2268
                    $float_value *= -1;
2269
                }
2270
                return $float_value;
2271
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
2272
2273
            default:
2274
                return false;
2275
                break;
2276
        }
2277
        $exponent_string = substr($bit_word, 1, $exponent_bits);
2278
        $fraction_string = substr($bit_word, $exponent_bits + 1, $fraction_bits);
2279
        $exponent        = bindec($exponent_string);
2280
        $fraction        = bindec($fraction_string);
2281
2282
        if (($exponent == (pow(2, $exponent_bits) - 1)) && (0 != $fraction)) {
2283
            // Not a Number
2284
            $float_value = false;
2285
        } elseif (($exponent == (pow(2, $exponent_bits) - 1)) && (0 == $fraction)) {
2286
            if ('1' == $sign_bit) {
2287
                $float_value = '-infinity';
2288
            } else {
2289
                $float_value = '+infinity';
2290
            }
2291
        } elseif ((0 == $exponent) && (0 == $fraction)) {
2292
            if ('1' == $sign_bit) {
2293
                $float_value = -0;
0 ignored issues
show
Unused Code introduced by
The assignment to $float_value is dead and can be removed.
Loading history...
2294
            } else {
2295
                $float_value = 0;
2296
            }
2297
            $float_value = ($sign_bit ? 0 : -0);
2298
        } elseif ((0 == $exponent) && (0 != $fraction)) {
2299
            // These are 'unnormalized' values
2300
            $float_value = pow(2, (-1 * (pow(2, $exponent_bits - 1) - 2))) * bindec($fraction_string) / bindec('1' . str_repeat('0', strlen($fraction_string)));
2301
            if ('1' == $sign_bit) {
2302
                $float_value *= -1;
2303
            }
2304
        } elseif (0 != $exponent) {
2305
            $float_value = pow(2, ($exponent - (pow(2, $exponent_bits - 1) - 1))) * (1 + bindec($fraction_string) / bindec('1' . str_repeat('0', strlen($fraction_string))));
2306
            if ('1' == $sign_bit) {
2307
                $float_value *= -1;
2308
            }
2309
        }
2310
        return (float)$float_value;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $float_value does not seem to be defined for all execution paths leading up to this point.
Loading history...
2311
    }
2312
}
2313
2314
2315