source: extensions/charlies_content/getid3/getid3/module.audio.monkey.php @ 3318

Revision 3318, 10.5 KB checked in by vdigital, 11 years ago (diff)

+ Add Charlies' content to depository

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