source: spip-zone/_core_/branches/spip-3.1/plugins/medias/lib/getid3/module.audio.monkey.php @ 113163

Last change on this file since 113163 was 113163, checked in by spip.franck@…, 7 months ago

Mise à jour de la lib getid en version 1.9.16, nous étions en 1.9.12
https://github.com/JamesHeinrich/getID3/blob/master/changelog.txt

File size: 11.5 KB
Line 
1<?php
2
3/////////////////////////////////////////////////////////////////
4/// getID3() by James Heinrich <info@getid3.org>               //
5//  available at https://github.com/JamesHeinrich/getID3       //
6//            or https://www.getid3.org                        //
7//            or http://getid3.sourceforge.net                 //
8//  see readme.txt for more details                            //
9/////////////////////////////////////////////////////////////////
10//                                                             //
11// module.audio.monkey.php                                     //
12// module for analyzing Monkey's Audio files                   //
13// dependencies: NONE                                          //
14//                                                            ///
15/////////////////////////////////////////////////////////////////
16
17
18class getid3_monkey extends getid3_handler
19{
20        /**
21         * @return bool
22         */
23        public function Analyze() {
24                $info = &$this->getid3->info;
25
26                // based loosely on code from TMonkey by Jurgen Faul <jfaulØgmx*de>
27                // http://jfaul.de/atl  or  http://j-faul.virtualave.net/atl/atl.html
28
29                $info['fileformat']            = 'mac';
30                $info['audio']['dataformat']   = 'mac';
31                $info['audio']['bitrate_mode'] = 'vbr';
32                $info['audio']['lossless']     = true;
33
34                $info['monkeys_audio']['raw'] = array();
35                $thisfile_monkeysaudio                = &$info['monkeys_audio'];
36                $thisfile_monkeysaudio_raw            = &$thisfile_monkeysaudio['raw'];
37
38                $this->fseek($info['avdataoffset']);
39                $MACheaderData = $this->fread(74);
40
41                $thisfile_monkeysaudio_raw['magic'] = substr($MACheaderData, 0, 4);
42                $magic = 'MAC ';
43                if ($thisfile_monkeysaudio_raw['magic'] != $magic) {
44                        $this->error('Expecting "'.getid3_lib::PrintHexBytes($magic).'" at offset '.$info['avdataoffset'].', found "'.getid3_lib::PrintHexBytes($thisfile_monkeysaudio_raw['magic']).'"');
45                        unset($info['fileformat']);
46                        return false;
47                }
48                $thisfile_monkeysaudio_raw['nVersion']             = getid3_lib::LittleEndian2Int(substr($MACheaderData, 4, 2)); // appears to be uint32 in 3.98+
49
50                if ($thisfile_monkeysaudio_raw['nVersion'] < 3980) {
51                        $thisfile_monkeysaudio_raw['nCompressionLevel']    = getid3_lib::LittleEndian2Int(substr($MACheaderData, 6, 2));
52                        $thisfile_monkeysaudio_raw['nFormatFlags']         = getid3_lib::LittleEndian2Int(substr($MACheaderData, 8, 2));
53                        $thisfile_monkeysaudio_raw['nChannels']            = getid3_lib::LittleEndian2Int(substr($MACheaderData, 10, 2));
54                        $thisfile_monkeysaudio_raw['nSampleRate']          = getid3_lib::LittleEndian2Int(substr($MACheaderData, 12, 4));
55                        $thisfile_monkeysaudio_raw['nHeaderDataBytes']     = getid3_lib::LittleEndian2Int(substr($MACheaderData, 16, 4));
56                        $thisfile_monkeysaudio_raw['nWAVTerminatingBytes'] = getid3_lib::LittleEndian2Int(substr($MACheaderData, 20, 4));
57                        $thisfile_monkeysaudio_raw['nTotalFrames']         = getid3_lib::LittleEndian2Int(substr($MACheaderData, 24, 4));
58                        $thisfile_monkeysaudio_raw['nFinalFrameSamples']   = getid3_lib::LittleEndian2Int(substr($MACheaderData, 28, 4));
59                        $thisfile_monkeysaudio_raw['nPeakLevel']           = getid3_lib::LittleEndian2Int(substr($MACheaderData, 32, 4));
60                        $thisfile_monkeysaudio_raw['nSeekElements']        = getid3_lib::LittleEndian2Int(substr($MACheaderData, 38, 2));
61                        $offset = 8;
62                } else {
63                        $offset = 8;
64                        // APE_DESCRIPTOR
65                        $thisfile_monkeysaudio_raw['nDescriptorBytes']       = getid3_lib::LittleEndian2Int(substr($MACheaderData, $offset,  4));
66                        $offset += 4;
67                        $thisfile_monkeysaudio_raw['nHeaderBytes']           = getid3_lib::LittleEndian2Int(substr($MACheaderData, $offset,  4));
68                        $offset += 4;
69                        $thisfile_monkeysaudio_raw['nSeekTableBytes']        = getid3_lib::LittleEndian2Int(substr($MACheaderData, $offset,  4));
70                        $offset += 4;
71                        $thisfile_monkeysaudio_raw['nHeaderDataBytes']       = getid3_lib::LittleEndian2Int(substr($MACheaderData, $offset,  4));
72                        $offset += 4;
73                        $thisfile_monkeysaudio_raw['nAPEFrameDataBytes']     = getid3_lib::LittleEndian2Int(substr($MACheaderData, $offset,  4));
74                        $offset += 4;
75                        $thisfile_monkeysaudio_raw['nAPEFrameDataBytesHigh'] = getid3_lib::LittleEndian2Int(substr($MACheaderData, $offset,  4));
76                        $offset += 4;
77                        $thisfile_monkeysaudio_raw['nTerminatingDataBytes']  = getid3_lib::LittleEndian2Int(substr($MACheaderData, $offset,  4));
78                        $offset += 4;
79                        $thisfile_monkeysaudio_raw['cFileMD5']               =                              substr($MACheaderData, $offset, 16);
80                        $offset += 16;
81
82                        // APE_HEADER
83                        $thisfile_monkeysaudio_raw['nCompressionLevel']    = getid3_lib::LittleEndian2Int(substr($MACheaderData, $offset, 2));
84                        $offset += 2;
85                        $thisfile_monkeysaudio_raw['nFormatFlags']         = getid3_lib::LittleEndian2Int(substr($MACheaderData, $offset, 2));
86                        $offset += 2;
87                        $thisfile_monkeysaudio_raw['nBlocksPerFrame']      = getid3_lib::LittleEndian2Int(substr($MACheaderData, $offset, 4));
88                        $offset += 4;
89                        $thisfile_monkeysaudio_raw['nFinalFrameBlocks']    = getid3_lib::LittleEndian2Int(substr($MACheaderData, $offset, 4));
90                        $offset += 4;
91                        $thisfile_monkeysaudio_raw['nTotalFrames']         = getid3_lib::LittleEndian2Int(substr($MACheaderData, $offset, 4));
92                        $offset += 4;
93                        $thisfile_monkeysaudio_raw['nBitsPerSample']       = getid3_lib::LittleEndian2Int(substr($MACheaderData, $offset, 2));
94                        $offset += 2;
95                        $thisfile_monkeysaudio_raw['nChannels']            = getid3_lib::LittleEndian2Int(substr($MACheaderData, $offset, 2));
96                        $offset += 2;
97                        $thisfile_monkeysaudio_raw['nSampleRate']          = getid3_lib::LittleEndian2Int(substr($MACheaderData, $offset, 4));
98                        $offset += 4;
99                }
100
101                $thisfile_monkeysaudio['flags']['8-bit']         = (bool) ($thisfile_monkeysaudio_raw['nFormatFlags'] & 0x0001);
102                $thisfile_monkeysaudio['flags']['crc-32']        = (bool) ($thisfile_monkeysaudio_raw['nFormatFlags'] & 0x0002);
103                $thisfile_monkeysaudio['flags']['peak_level']    = (bool) ($thisfile_monkeysaudio_raw['nFormatFlags'] & 0x0004);
104                $thisfile_monkeysaudio['flags']['24-bit']        = (bool) ($thisfile_monkeysaudio_raw['nFormatFlags'] & 0x0008);
105                $thisfile_monkeysaudio['flags']['seek_elements'] = (bool) ($thisfile_monkeysaudio_raw['nFormatFlags'] & 0x0010);
106                $thisfile_monkeysaudio['flags']['no_wav_header'] = (bool) ($thisfile_monkeysaudio_raw['nFormatFlags'] & 0x0020);
107                $thisfile_monkeysaudio['version']                = $thisfile_monkeysaudio_raw['nVersion'] / 1000;
108                $thisfile_monkeysaudio['compression']            = $this->MonkeyCompressionLevelNameLookup($thisfile_monkeysaudio_raw['nCompressionLevel']);
109                if ($thisfile_monkeysaudio_raw['nVersion'] < 3980) {
110                        $thisfile_monkeysaudio['samples_per_frame']      = $this->MonkeySamplesPerFrame($thisfile_monkeysaudio_raw['nVersion'], $thisfile_monkeysaudio_raw['nCompressionLevel']);
111                }
112                $thisfile_monkeysaudio['bits_per_sample']        = ($thisfile_monkeysaudio['flags']['24-bit'] ? 24 : ($thisfile_monkeysaudio['flags']['8-bit'] ? 8 : 16));
113                $thisfile_monkeysaudio['channels']               = $thisfile_monkeysaudio_raw['nChannels'];
114                $info['audio']['channels']               = $thisfile_monkeysaudio['channels'];
115                $thisfile_monkeysaudio['sample_rate']            = $thisfile_monkeysaudio_raw['nSampleRate'];
116                if ($thisfile_monkeysaudio['sample_rate'] == 0) {
117                        $this->error('Corrupt MAC file: frequency == zero');
118                        return false;
119                }
120                $info['audio']['sample_rate']            = $thisfile_monkeysaudio['sample_rate'];
121                if ($thisfile_monkeysaudio['flags']['peak_level']) {
122                        $thisfile_monkeysaudio['peak_level']         = $thisfile_monkeysaudio_raw['nPeakLevel'];
123                        $thisfile_monkeysaudio['peak_ratio']         = $thisfile_monkeysaudio['peak_level'] / pow(2, $thisfile_monkeysaudio['bits_per_sample'] - 1);
124                }
125                if ($thisfile_monkeysaudio_raw['nVersion'] >= 3980) {
126                        $thisfile_monkeysaudio['samples']            = (($thisfile_monkeysaudio_raw['nTotalFrames'] - 1) * $thisfile_monkeysaudio_raw['nBlocksPerFrame']) + $thisfile_monkeysaudio_raw['nFinalFrameBlocks'];
127                } else {
128                        $thisfile_monkeysaudio['samples']            = (($thisfile_monkeysaudio_raw['nTotalFrames'] - 1) * $thisfile_monkeysaudio['samples_per_frame']) + $thisfile_monkeysaudio_raw['nFinalFrameSamples'];
129                }
130                $thisfile_monkeysaudio['playtime']               = $thisfile_monkeysaudio['samples'] / $thisfile_monkeysaudio['sample_rate'];
131                if ($thisfile_monkeysaudio['playtime'] == 0) {
132                        $this->error('Corrupt MAC file: playtime == zero');
133                        return false;
134                }
135                $info['playtime_seconds']                = $thisfile_monkeysaudio['playtime'];
136                $thisfile_monkeysaudio['compressed_size']        = $info['avdataend'] - $info['avdataoffset'];
137                $thisfile_monkeysaudio['uncompressed_size']      = $thisfile_monkeysaudio['samples'] * $thisfile_monkeysaudio['channels'] * ($thisfile_monkeysaudio['bits_per_sample'] / 8);
138                if ($thisfile_monkeysaudio['uncompressed_size'] == 0) {
139                        $this->error('Corrupt MAC file: uncompressed_size == zero');
140                        return false;
141                }
142                $thisfile_monkeysaudio['compression_ratio']      = $thisfile_monkeysaudio['compressed_size'] / ($thisfile_monkeysaudio['uncompressed_size'] + $thisfile_monkeysaudio_raw['nHeaderDataBytes']);
143                $thisfile_monkeysaudio['bitrate']                = (($thisfile_monkeysaudio['samples'] * $thisfile_monkeysaudio['channels'] * $thisfile_monkeysaudio['bits_per_sample']) / $thisfile_monkeysaudio['playtime']) * $thisfile_monkeysaudio['compression_ratio'];
144                $info['audio']['bitrate']                = $thisfile_monkeysaudio['bitrate'];
145
146                // add size of MAC header to avdataoffset
147                if ($thisfile_monkeysaudio_raw['nVersion'] >= 3980) {
148                        $info['avdataoffset'] += $thisfile_monkeysaudio_raw['nDescriptorBytes'];
149                        $info['avdataoffset'] += $thisfile_monkeysaudio_raw['nHeaderBytes'];
150                        $info['avdataoffset'] += $thisfile_monkeysaudio_raw['nSeekTableBytes'];
151                        $info['avdataoffset'] += $thisfile_monkeysaudio_raw['nHeaderDataBytes'];
152
153                        $info['avdataend'] -= $thisfile_monkeysaudio_raw['nTerminatingDataBytes'];
154                } else {
155                        $info['avdataoffset'] += $offset;
156                }
157
158                if ($thisfile_monkeysaudio_raw['nVersion'] >= 3980) {
159                        if ($thisfile_monkeysaudio_raw['cFileMD5'] === str_repeat("\x00", 16)) {
160                                //$this->warning('cFileMD5 is null');
161                        } else {
162                                $info['md5_data_source'] = '';
163                                $md5 = $thisfile_monkeysaudio_raw['cFileMD5'];
164                                for ($i = 0; $i < strlen($md5); $i++) {
165                                        $info['md5_data_source'] .= str_pad(dechex(ord($md5{$i})), 2, '00', STR_PAD_LEFT);
166                                }
167                                if (!preg_match('/^[0-9a-f]{32}$/', $info['md5_data_source'])) {
168                                        unset($info['md5_data_source']);
169                                }
170                        }
171                }
172
173
174
175                $info['audio']['bits_per_sample'] = $thisfile_monkeysaudio['bits_per_sample'];
176                $info['audio']['encoder']         = 'MAC v'.number_format($thisfile_monkeysaudio['version'], 2);
177                $info['audio']['encoder_options'] = ucfirst($thisfile_monkeysaudio['compression']).' compression';
178
179                return true;
180        }
181
182        /**
183         * @param int $compressionlevel
184         *
185         * @return string
186         */
187        public function MonkeyCompressionLevelNameLookup($compressionlevel) {
188                static $MonkeyCompressionLevelNameLookup = array(
189                        0     => 'unknown',
190                        1000  => 'fast',
191                        2000  => 'normal',
192                        3000  => 'high',
193                        4000  => 'extra-high',
194                        5000  => 'insane'
195                );
196                return (isset($MonkeyCompressionLevelNameLookup[$compressionlevel]) ? $MonkeyCompressionLevelNameLookup[$compressionlevel] : 'invalid');
197        }
198
199        /**
200         * @param int $versionid
201         * @param int $compressionlevel
202         *
203         * @return int
204         */
205        public function MonkeySamplesPerFrame($versionid, $compressionlevel) {
206                if ($versionid >= 3950) {
207                        return 73728 * 4;
208                } elseif ($versionid >= 3900) {
209                        return 73728;
210                } elseif (($versionid >= 3800) && ($compressionlevel == 4000)) {
211                        return 73728;
212                } else {
213                        return 9216;
214                }
215        }
216
217}
Note: See TracBrowser for help on using the repository browser.