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

Last change on this file since 3318 was 3318, checked in by vdigital, 15 years ago

+ Add Charlies' content to depository

  • Property svn:keywords set to Author Date Id Revision
File size: 9.7 KB
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.mpc.php                                                 |
18// | Module for analyzing Musepack/MPEG+ Audio files                      |
19// | dependencies: NONE                                                   |
20// +----------------------------------------------------------------------+
21//
22// $Id: module.audio.mpc.php 3318 2009-05-20 21:54:10Z vdigital $
23
24       
25       
26class getid3_mpc extends getid3_handler
27{
28
29    public function Analyze() {
30
31        $getid3 = $this->getid3;
32       
33        // http://www.uni-jena.de/~pfk/mpp/sv8/header.html
34
35        $getid3->info['fileformat']            = 'mpc';
36        $getid3->info['audio']['dataformat']   = 'mpc';
37        $getid3->info['audio']['bitrate_mode'] = 'vbr';
38        $getid3->info['audio']['channels']     = 2;  // the format appears to be hardcoded for stereo only
39        $getid3->info['audio']['lossless']     = false;
40       
41        $getid3->info['mpc']['header'] = array ();
42        $info_mpc_header = &$getid3->info['mpc']['header'];
43        $info_mpc_header['size'] = 28;
44        $info_mpc_header['raw']['preamble'] = 'MP+';    // Magic bytes
45       
46        fseek($getid3->fp, $getid3->info['avdataoffset'], SEEK_SET);
47        $mpc_header_data = fread($getid3->fp, 28);
48       
49        $stream_version_byte = getid3_lib::LittleEndian2Int(substr($mpc_header_data, 3, 1));
50        $info_mpc_header['stream_major_version'] = ($stream_version_byte & 0x0F);
51        $info_mpc_header['stream_minor_version'] = ($stream_version_byte & 0xF0) >> 4;
52        if ($info_mpc_header['stream_major_version'] != 7) {
53            throw new getid3_exception('Only Musepack SV7 supported');
54        }
55           
56        $info_mpc_header['frame_count'] = getid3_lib::LittleEndian2Int(substr($mpc_header_data, 4, 4));
57       
58        $info_mpc_header['raw']['title_peak']      = getid3_lib::LittleEndian2Int(substr($mpc_header_data, 12, 2));
59        $info_mpc_header['raw']['title_gain']      = getid3_lib::LittleEndian2Int(substr($mpc_header_data, 14, 2), true);
60        $info_mpc_header['raw']['album_peak']      = getid3_lib::LittleEndian2Int(substr($mpc_header_data, 16, 2));
61        $info_mpc_header['raw']['album_gain']      = getid3_lib::LittleEndian2Int(substr($mpc_header_data, 18, 2), true);
62       
63        $info_mpc_header['raw']['not_sure_what']   = getid3_lib::LittleEndian2Int(substr($mpc_header_data, 24, 3));
64        $info_mpc_header['raw']['encoder_version'] = getid3_lib::LittleEndian2Int(substr($mpc_header_data, 27, 1));
65       
66        $flags_dword1                              = getid3_lib::LittleEndian2Int(substr($mpc_header_data, 8, 4));
67        $flags_dword2                              = getid3_lib::LittleEndian2Int(substr($mpc_header_data, 20, 4));
68       
69        $info_mpc_header['intensity_stereo']   = (bool)(($flags_dword1 & 0x80000000) >> 31);
70        $info_mpc_header['mid_side_stereo']    = (bool)(($flags_dword1 & 0x40000000) >> 30);
71        $info_mpc_header['max_subband']        =         ($flags_dword1 & 0x3F000000) >> 24;
72        $info_mpc_header['raw']['profile']     =         ($flags_dword1 & 0x00F00000) >> 20;
73        $info_mpc_header['begin_loud']         = (bool)(($flags_dword1 & 0x00080000) >> 19);
74        $info_mpc_header['end_loud']           = (bool)(($flags_dword1 & 0x00040000) >> 18);
75        $info_mpc_header['raw']['sample_rate'] =         ($flags_dword1 & 0x00030000) >> 16;
76        $info_mpc_header['max_level']          =         ($flags_dword1 & 0x0000FFFF);
77       
78        $info_mpc_header['true_gapless']       = (bool)(($flags_dword2 & 0x80000000) >> 31);
79        $info_mpc_header['last_frame_length']  =         ($flags_dword2 & 0x7FF00000) >> 20;
80       
81        $info_mpc_header['profile']            = getid3_mpc::MPCprofileNameLookup($info_mpc_header['raw']['profile']);
82        $info_mpc_header['sample_rate']        = getid3_mpc::MPCfrequencyLookup($info_mpc_header['raw']['sample_rate']);
83        $getid3->info['audio']['sample_rate']  = $info_mpc_header['sample_rate'];
84        $info_mpc_header['samples']            = ((($info_mpc_header['frame_count'] - 1) * 1152) + $info_mpc_header['last_frame_length']) * $getid3->info['audio']['channels'];
85
86        $getid3->info['playtime_seconds'] = ($info_mpc_header['samples'] / $getid3->info['audio']['channels']) / $getid3->info['audio']['sample_rate'];
87
88        $getid3->info['avdataoffset'] += $info_mpc_header['size'];
89       
90        $getid3->info['audio']['bitrate'] = (($getid3->info['avdataend'] - $getid3->info['avdataoffset']) * 8) / $getid3->info['playtime_seconds'];
91
92        $info_mpc_header['title_peak']    = $info_mpc_header['raw']['title_peak'];
93        $info_mpc_header['title_peak_db'] = getid3_mpc::MPCpeakDBLookup($info_mpc_header['title_peak']);
94        if ($info_mpc_header['raw']['title_gain'] < 0) {
95            $info_mpc_header['title_gain_db'] = (float)(32768 + $info_mpc_header['raw']['title_gain']) / -100;
96        } 
97        else {
98            $info_mpc_header['title_gain_db'] = (float)$info_mpc_header['raw']['title_gain'] / 100;
99        }
100
101        $info_mpc_header['album_peak']    = $info_mpc_header['raw']['album_peak'];
102        $info_mpc_header['album_peak_db'] = getid3_mpc::MPCpeakDBLookup($info_mpc_header['album_peak']);
103        if ($info_mpc_header['raw']['album_gain'] < 0) {
104            $info_mpc_header['album_gain_db'] = (float)(32768 + $info_mpc_header['raw']['album_gain']) / -100;
105        } 
106        else {
107            $info_mpc_header['album_gain_db'] = (float)$info_mpc_header['raw']['album_gain'] / 100;;
108        }
109        $info_mpc_header['encoder_version'] = getid3_mpc::MPCencoderVersionLookup($info_mpc_header['raw']['encoder_version']);
110
111        $getid3->info['replay_gain']['track']['adjustment'] = $info_mpc_header['title_gain_db'];
112        $getid3->info['replay_gain']['album']['adjustment'] = $info_mpc_header['album_gain_db'];
113
114        if ($info_mpc_header['title_peak'] > 0) {
115            $getid3->info['replay_gain']['track']['peak'] = $info_mpc_header['title_peak'];
116        } 
117        elseif (round($info_mpc_header['max_level'] * 1.18) > 0) {
118            $getid3->info['replay_gain']['track']['peak'] = (int)(round($info_mpc_header['max_level'] * 1.18)); // why? I don't know - see mppdec.c
119        }
120        if ($info_mpc_header['album_peak'] > 0) {
121            $getid3->info['replay_gain']['album']['peak'] = $info_mpc_header['album_peak'];
122        }
123
124        $getid3->info['audio']['encoder']         = $info_mpc_header['encoder_version'];
125        $getid3->info['audio']['encoder_options'] = $info_mpc_header['profile'];
126       
127        return true;
128    }
129
130
131
132    public static function MPCprofileNameLookup($profileid) {
133       
134        static $lookup = array (
135            0  => 'no profile',
136            1  => 'Experimental',
137            2  => 'unused',
138            3  => 'unused',
139            4  => 'unused',
140            5  => 'below Telephone (q = 0.0)',
141            6  => 'below Telephone (q = 1.0)',
142            7  => 'Telephone (q = 2.0)',
143            8  => 'Thumb (q = 3.0)',
144            9  => 'Radio (q = 4.0)',
145            10 => 'Standard (q = 5.0)',
146            11 => 'Extreme (q = 6.0)',
147            12 => 'Insane (q = 7.0)',
148            13 => 'BrainDead (q = 8.0)',
149            14 => 'above BrainDead (q = 9.0)',
150            15 => 'above BrainDead (q = 10.0)'
151        );
152        return (isset($lookup[$profileid]) ? $lookup[$profileid] : 'invalid');
153    }
154
155
156
157    public static function MPCfrequencyLookup($frequencyid) {
158       
159        static $lookup = array (
160            0 => 44100,
161            1 => 48000,
162            2 => 37800,
163            3 => 32000
164        );
165        return (isset($lookup[$frequencyid]) ? $lookup[$frequencyid] : 'invalid');
166    }
167
168
169
170    public static function MPCpeakDBLookup($int_value) {
171       
172        if ($int_value > 0) {
173            return ((log10($int_value) / log10(2)) - 15) * 6;
174        }
175        return false;
176    }
177
178
179
180    public static function MPCencoderVersionLookup($encoder_version) {
181   
182        //Encoder version * 100  (106 = 1.06)
183        //EncoderVersion % 10 == 0        Release (1.0)
184        //EncoderVersion %  2 == 0        Beta (1.06)
185        //EncoderVersion %  2 == 1        Alpha (1.05a...z)
186
187        if ($encoder_version == 0) {
188            // very old version, not known exactly which
189            return 'Buschmann v1.7.0-v1.7.9 or Klemm v0.90-v1.05';
190        }
191
192        if (($encoder_version % 10) == 0) {
193
194            // release version
195            return number_format($encoder_version / 100, 2);
196
197        } elseif (($encoder_version % 2) == 0) {
198
199            // beta version
200            return number_format($encoder_version / 100, 2).' beta';
201
202        }
203
204        // alpha version
205        return number_format($encoder_version / 100, 2).' alpha';
206    }
207
208}
209
210
211?>
Note: See TracBrowser for help on using the repository browser.