ILIAS  release_5-2 Revision v5.2.25-18-g3f80b828510
GetId3\Module\Audio\Monkey Class Reference

GetId3() by James Heinrich info@.nosp@m.geti.nosp@m.d3.or.nosp@m.g //. More...

+ Inheritance diagram for GetId3\Module\Audio\Monkey:
+ Collaboration diagram for GetId3\Module\Audio\Monkey:

Public Member Functions

 analyze ()
 
 MonkeyCompressionLevelNameLookup ($compressionlevel)
 @staticvar array $MonkeyCompressionLevelNameLookup More...
 
 MonkeySamplesPerFrame ($versionid, $compressionlevel)
 
- Public Member Functions inherited from GetId3\Handler\BaseHandler
 __construct (GetId3Core $getid3, $call_module=null)
 
 analyze ()
 Analyze from file pointer. More...
 
 AnalyzeString (&$string)
 Analyze from string instead. More...
 
 saveAttachment (&$ThisFileInfoIndex, $filename, $offset, $length)
 

Additional Inherited Members

- Protected Member Functions inherited from GetId3\Handler\BaseHandler
 ftell ()
 
 fread ($bytes)
 
 fseek ($bytes, $whence=SEEK_SET)
 
 feof ()
 
 isDependencyFor ($module)
 
 error ($text)
 
 warning ($text)
 
- Protected Attributes inherited from GetId3\Handler\BaseHandler
 $getid3
 
 $data_string_flag = false
 
 $data_string = ''
 
 $data_string_position = 0
 
 $data_string_length = 0
 

Detailed Description

GetId3() by James Heinrich info@.nosp@m.geti.nosp@m.d3.or.nosp@m.g //.

module for analyzing Monkey's Audio files

Author
James Heinrich info@.nosp@m.geti.nosp@m.d3.or.nosp@m.g http://www.getid3.org

Definition at line 29 of file Monkey.php.

Member Function Documentation

◆ analyze()

GetId3\Module\Audio\Monkey::analyze ( )
Returns
boolean

Reimplemented from GetId3\Handler\BaseHandler.

Definition at line 36 of file Monkey.php.

37 {
38 $info = &$this->getid3->info;
39
40 // based loosely on code from TMonkey by Jurgen Faul <jfaulØgmx*de>
41 // http://jfaul.de/atl or http://j-faul.virtualave.net/atl/atl.html
42
43 $info['fileformat'] = 'mac';
44 $info['audio']['dataformat'] = 'mac';
45 $info['audio']['bitrate_mode'] = 'vbr';
46 $info['audio']['lossless'] = true;
47
48 $info['monkeys_audio']['raw'] = array();
49 $thisfile_monkeysaudio = &$info['monkeys_audio'];
50 $thisfile_monkeysaudio_raw = &$thisfile_monkeysaudio['raw'];
51
52 fseek($this->getid3->fp, $info['avdataoffset'], SEEK_SET);
53 $MACheaderData = fread($this->getid3->fp, 74);
54
55 $thisfile_monkeysaudio_raw['magic'] = substr($MACheaderData, 0, 4);
56 $magic = 'MAC ';
57 if ($thisfile_monkeysaudio_raw['magic'] != $magic) {
58 $info['error'][] = 'Expecting "'.Helper::PrintHexBytes($magic).'" at offset '.$info['avdataoffset'].', found "'.Helper::PrintHexBytes($thisfile_monkeysaudio_raw['magic']).'"';
59 unset($info['fileformat']);
60
61 return false;
62 }
63 $thisfile_monkeysaudio_raw['nVersion'] = Helper::LittleEndian2Int(substr($MACheaderData, 4, 2)); // appears to be uint32 in 3.98+
64
65 if ($thisfile_monkeysaudio_raw['nVersion'] < 3980) {
66 $thisfile_monkeysaudio_raw['nCompressionLevel'] = Helper::LittleEndian2Int(substr($MACheaderData, 6, 2));
67 $thisfile_monkeysaudio_raw['nFormatFlags'] = Helper::LittleEndian2Int(substr($MACheaderData, 8, 2));
68 $thisfile_monkeysaudio_raw['nChannels'] = Helper::LittleEndian2Int(substr($MACheaderData, 10, 2));
69 $thisfile_monkeysaudio_raw['nSampleRate'] = Helper::LittleEndian2Int(substr($MACheaderData, 12, 4));
70 $thisfile_monkeysaudio_raw['nHeaderDataBytes'] = Helper::LittleEndian2Int(substr($MACheaderData, 16, 4));
71 $thisfile_monkeysaudio_raw['nWAVTerminatingBytes'] = Helper::LittleEndian2Int(substr($MACheaderData, 20, 4));
72 $thisfile_monkeysaudio_raw['nTotalFrames'] = Helper::LittleEndian2Int(substr($MACheaderData, 24, 4));
73 $thisfile_monkeysaudio_raw['nFinalFrameSamples'] = Helper::LittleEndian2Int(substr($MACheaderData, 28, 4));
74 $thisfile_monkeysaudio_raw['nPeakLevel'] = Helper::LittleEndian2Int(substr($MACheaderData, 32, 4));
75 $thisfile_monkeysaudio_raw['nSeekElements'] = Helper::LittleEndian2Int(substr($MACheaderData, 38, 2));
76 $offset = 8;
77 } else {
78 $offset = 8;
79 // APE_DESCRIPTOR
80 $thisfile_monkeysaudio_raw['nDescriptorBytes'] = Helper::LittleEndian2Int(substr($MACheaderData, $offset, 4));
81 $offset += 4;
82 $thisfile_monkeysaudio_raw['nHeaderBytes'] = Helper::LittleEndian2Int(substr($MACheaderData, $offset, 4));
83 $offset += 4;
84 $thisfile_monkeysaudio_raw['nSeekTableBytes'] = Helper::LittleEndian2Int(substr($MACheaderData, $offset, 4));
85 $offset += 4;
86 $thisfile_monkeysaudio_raw['nHeaderDataBytes'] = Helper::LittleEndian2Int(substr($MACheaderData, $offset, 4));
87 $offset += 4;
88 $thisfile_monkeysaudio_raw['nAPEFrameDataBytes'] = Helper::LittleEndian2Int(substr($MACheaderData, $offset, 4));
89 $offset += 4;
90 $thisfile_monkeysaudio_raw['nAPEFrameDataBytesHigh'] = Helper::LittleEndian2Int(substr($MACheaderData, $offset, 4));
91 $offset += 4;
92 $thisfile_monkeysaudio_raw['nTerminatingDataBytes'] = Helper::LittleEndian2Int(substr($MACheaderData, $offset, 4));
93 $offset += 4;
94 $thisfile_monkeysaudio_raw['cFileMD5'] = substr($MACheaderData, $offset, 16);
95 $offset += 16;
96
97 // APE_HEADER
98 $thisfile_monkeysaudio_raw['nCompressionLevel'] = Helper::LittleEndian2Int(substr($MACheaderData, $offset, 2));
99 $offset += 2;
100 $thisfile_monkeysaudio_raw['nFormatFlags'] = Helper::LittleEndian2Int(substr($MACheaderData, $offset, 2));
101 $offset += 2;
102 $thisfile_monkeysaudio_raw['nBlocksPerFrame'] = Helper::LittleEndian2Int(substr($MACheaderData, $offset, 4));
103 $offset += 4;
104 $thisfile_monkeysaudio_raw['nFinalFrameBlocks'] = Helper::LittleEndian2Int(substr($MACheaderData, $offset, 4));
105 $offset += 4;
106 $thisfile_monkeysaudio_raw['nTotalFrames'] = Helper::LittleEndian2Int(substr($MACheaderData, $offset, 4));
107 $offset += 4;
108 $thisfile_monkeysaudio_raw['nBitsPerSample'] = Helper::LittleEndian2Int(substr($MACheaderData, $offset, 2));
109 $offset += 2;
110 $thisfile_monkeysaudio_raw['nChannels'] = Helper::LittleEndian2Int(substr($MACheaderData, $offset, 2));
111 $offset += 2;
112 $thisfile_monkeysaudio_raw['nSampleRate'] = Helper::LittleEndian2Int(substr($MACheaderData, $offset, 4));
113 $offset += 4;
114 }
115
116 $thisfile_monkeysaudio['flags']['8-bit'] = (bool) ($thisfile_monkeysaudio_raw['nFormatFlags'] & 0x0001);
117 $thisfile_monkeysaudio['flags']['crc-32'] = (bool) ($thisfile_monkeysaudio_raw['nFormatFlags'] & 0x0002);
118 $thisfile_monkeysaudio['flags']['peak_level'] = (bool) ($thisfile_monkeysaudio_raw['nFormatFlags'] & 0x0004);
119 $thisfile_monkeysaudio['flags']['24-bit'] = (bool) ($thisfile_monkeysaudio_raw['nFormatFlags'] & 0x0008);
120 $thisfile_monkeysaudio['flags']['seek_elements'] = (bool) ($thisfile_monkeysaudio_raw['nFormatFlags'] & 0x0010);
121 $thisfile_monkeysaudio['flags']['no_wav_header'] = (bool) ($thisfile_monkeysaudio_raw['nFormatFlags'] & 0x0020);
122 $thisfile_monkeysaudio['version'] = $thisfile_monkeysaudio_raw['nVersion'] / 1000;
123 $thisfile_monkeysaudio['compression'] = $this->MonkeyCompressionLevelNameLookup($thisfile_monkeysaudio_raw['nCompressionLevel']);
124 if ($thisfile_monkeysaudio_raw['nVersion'] < 3980) {
125 $thisfile_monkeysaudio['samples_per_frame'] = $this->MonkeySamplesPerFrame($thisfile_monkeysaudio_raw['nVersion'], $thisfile_monkeysaudio_raw['nCompressionLevel']);
126 }
127 $thisfile_monkeysaudio['bits_per_sample'] = ($thisfile_monkeysaudio['flags']['24-bit'] ? 24 : ($thisfile_monkeysaudio['flags']['8-bit'] ? 8 : 16));
128 $thisfile_monkeysaudio['channels'] = $thisfile_monkeysaudio_raw['nChannels'];
129 $info['audio']['channels'] = $thisfile_monkeysaudio['channels'];
130 $thisfile_monkeysaudio['sample_rate'] = $thisfile_monkeysaudio_raw['nSampleRate'];
131 if ($thisfile_monkeysaudio['sample_rate'] == 0) {
132 $info['error'][] = 'Corrupt MAC file: frequency == zero';
133
134 return false;
135 }
136 $info['audio']['sample_rate'] = $thisfile_monkeysaudio['sample_rate'];
137 if ($thisfile_monkeysaudio['flags']['peak_level']) {
138 $thisfile_monkeysaudio['peak_level'] = $thisfile_monkeysaudio_raw['nPeakLevel'];
139 $thisfile_monkeysaudio['peak_ratio'] = $thisfile_monkeysaudio['peak_level'] / pow(2, $thisfile_monkeysaudio['bits_per_sample'] - 1);
140 }
141 if ($thisfile_monkeysaudio_raw['nVersion'] >= 3980) {
142 $thisfile_monkeysaudio['samples'] = (($thisfile_monkeysaudio_raw['nTotalFrames'] - 1) * $thisfile_monkeysaudio_raw['nBlocksPerFrame']) + $thisfile_monkeysaudio_raw['nFinalFrameBlocks'];
143 } else {
144 $thisfile_monkeysaudio['samples'] = (($thisfile_monkeysaudio_raw['nTotalFrames'] - 1) * $thisfile_monkeysaudio['samples_per_frame']) + $thisfile_monkeysaudio_raw['nFinalFrameSamples'];
145 }
146 $thisfile_monkeysaudio['playtime'] = $thisfile_monkeysaudio['samples'] / $thisfile_monkeysaudio['sample_rate'];
147 if ($thisfile_monkeysaudio['playtime'] == 0) {
148 $info['error'][] = 'Corrupt MAC file: playtime == zero';
149
150 return false;
151 }
152 $info['playtime_seconds'] = $thisfile_monkeysaudio['playtime'];
153 $thisfile_monkeysaudio['compressed_size'] = $info['avdataend'] - $info['avdataoffset'];
154 $thisfile_monkeysaudio['uncompressed_size'] = $thisfile_monkeysaudio['samples'] * $thisfile_monkeysaudio['channels'] * ($thisfile_monkeysaudio['bits_per_sample'] / 8);
155 if ($thisfile_monkeysaudio['uncompressed_size'] == 0) {
156 $info['error'][] = 'Corrupt MAC file: uncompressed_size == zero';
157
158 return false;
159 }
160 $thisfile_monkeysaudio['compression_ratio'] = $thisfile_monkeysaudio['compressed_size'] / ($thisfile_monkeysaudio['uncompressed_size'] + $thisfile_monkeysaudio_raw['nHeaderDataBytes']);
161 $thisfile_monkeysaudio['bitrate'] = (($thisfile_monkeysaudio['samples'] * $thisfile_monkeysaudio['channels'] * $thisfile_monkeysaudio['bits_per_sample']) / $thisfile_monkeysaudio['playtime']) * $thisfile_monkeysaudio['compression_ratio'];
162 $info['audio']['bitrate'] = $thisfile_monkeysaudio['bitrate'];
163
164 // add size of MAC header to avdataoffset
165 if ($thisfile_monkeysaudio_raw['nVersion'] >= 3980) {
166 $info['avdataoffset'] += $thisfile_monkeysaudio_raw['nDescriptorBytes'];
167 $info['avdataoffset'] += $thisfile_monkeysaudio_raw['nHeaderBytes'];
168 $info['avdataoffset'] += $thisfile_monkeysaudio_raw['nSeekTableBytes'];
169 $info['avdataoffset'] += $thisfile_monkeysaudio_raw['nHeaderDataBytes'];
170
171 $info['avdataend'] -= $thisfile_monkeysaudio_raw['nTerminatingDataBytes'];
172 } else {
173 $info['avdataoffset'] += $offset;
174 }
175
176 if ($thisfile_monkeysaudio_raw['nVersion'] >= 3980) {
177 if ($thisfile_monkeysaudio_raw['cFileMD5'] === str_repeat("\x00", 16)) {
178 //$info['warning'][] = 'cFileMD5 is null';
179 } else {
180 $info['md5_data_source'] = '';
181 $md5 = $thisfile_monkeysaudio_raw['cFileMD5'];
182 for ($i = 0; $i < strlen($md5); $i++) {
183 $info['md5_data_source'] .= str_pad(dechex(ord($md5{$i})), 2, '00', STR_PAD_LEFT);
184 }
185 if (!preg_match('/^[0-9a-f]{32}$/', $info['md5_data_source'])) {
186 unset($info['md5_data_source']);
187 }
188 }
189 }
190
191 $info['audio']['bits_per_sample'] = $thisfile_monkeysaudio['bits_per_sample'];
192 $info['audio']['encoder'] = 'MAC v'.number_format($thisfile_monkeysaudio['version'], 2);
193 $info['audio']['encoder_options'] = ucfirst($thisfile_monkeysaudio['compression']).' compression';
194
195 return true;
196 }
fseek($bytes, $whence=SEEK_SET)
static LittleEndian2Int($byteword, $signed=false)
Definition: Helper.php:413
static PrintHexBytes($string, $hex=true, $spaces=true, $htmlencoding='UTF-8')
Definition: Helper.php:36
MonkeySamplesPerFrame($versionid, $compressionlevel)
Definition: Monkey.php:224
MonkeyCompressionLevelNameLookup($compressionlevel)
@staticvar array $MonkeyCompressionLevelNameLookup
Definition: Monkey.php:204
$info
Definition: example_052.php:80

References $info, GetId3\Handler\BaseHandler\fread(), GetId3\Handler\BaseHandler\fseek(), GetId3\Lib\Helper\LittleEndian2Int(), GetId3\Module\Audio\Monkey\MonkeyCompressionLevelNameLookup(), GetId3\Module\Audio\Monkey\MonkeySamplesPerFrame(), and GetId3\Lib\Helper\PrintHexBytes().

+ Here is the call graph for this function:

◆ MonkeyCompressionLevelNameLookup()

GetId3\Module\Audio\Monkey::MonkeyCompressionLevelNameLookup (   $compressionlevel)

@staticvar array $MonkeyCompressionLevelNameLookup

Parameters
type$compressionlevel
Returns
type

Definition at line 204 of file Monkey.php.

205 {
206 static $MonkeyCompressionLevelNameLookup = array(
207 0 => 'unknown',
208 1000 => 'fast',
209 2000 => 'normal',
210 3000 => 'high',
211 4000 => 'extra-high',
212 5000 => 'insane'
213 );
214
215 return (isset($MonkeyCompressionLevelNameLookup[$compressionlevel]) ? $MonkeyCompressionLevelNameLookup[$compressionlevel] : 'invalid');
216 }

Referenced by GetId3\Module\Audio\Monkey\analyze().

+ Here is the caller graph for this function:

◆ MonkeySamplesPerFrame()

GetId3\Module\Audio\Monkey::MonkeySamplesPerFrame (   $versionid,
  $compressionlevel 
)
Parameters
type$versionid
type$compressionlevel
Returns
int

Definition at line 224 of file Monkey.php.

225 {
226 if ($versionid >= 3950) {
227 return 73728 * 4;
228 } elseif ($versionid >= 3900) {
229 return 73728;
230 } elseif (($versionid >= 3800) && ($compressionlevel == 4000)) {
231 return 73728;
232 } else {
233 return 9216;
234 }
235 }

Referenced by GetId3\Module\Audio\Monkey\analyze().

+ Here is the caller graph for this function:

The documentation for this class was generated from the following file: