21 {
22 $info = &$this->getid3->info;
23
24
25
26
27 $info[
'fileformat'] =
'mac';
28 $info[
'audio'][
'dataformat'] =
'mac';
29 $info[
'audio'][
'bitrate_mode'] =
'vbr';
30 $info[
'audio'][
'lossless'] =
true;
31
32 $info[
'monkeys_audio'][
'raw'] = array();
33 $thisfile_monkeysaudio = &
$info[
'monkeys_audio'];
34 $thisfile_monkeysaudio_raw = &$thisfile_monkeysaudio['raw'];
35
37 $MACheaderData = $this->
fread(74);
38
39 $thisfile_monkeysaudio_raw['magic'] = substr($MACheaderData, 0, 4);
40 $magic = 'MAC ';
41 if ($thisfile_monkeysaudio_raw['magic'] != $magic) {
43 unset(
$info[
'fileformat']);
44 return false;
45 }
47
48 if ($thisfile_monkeysaudio_raw['nVersion'] < 3980) {
59 $offset = 8;
60 } else {
61 $offset = 8;
62
64 $offset += 4;
66 $offset += 4;
68 $offset += 4;
70 $offset += 4;
72 $offset += 4;
74 $offset += 4;
76 $offset += 4;
77 $thisfile_monkeysaudio_raw['cFileMD5'] = substr($MACheaderData, $offset, 16);
78 $offset += 16;
79
80
82 $offset += 2;
84 $offset += 2;
86 $offset += 4;
88 $offset += 4;
90 $offset += 4;
92 $offset += 2;
94 $offset += 2;
96 $offset += 4;
97 }
98
99 $thisfile_monkeysaudio['flags']['8-bit'] = (bool) ($thisfile_monkeysaudio_raw['nFormatFlags'] & 0x0001);
100 $thisfile_monkeysaudio['flags']['crc-32'] = (bool) ($thisfile_monkeysaudio_raw['nFormatFlags'] & 0x0002);
101 $thisfile_monkeysaudio['flags']['peak_level'] = (bool) ($thisfile_monkeysaudio_raw['nFormatFlags'] & 0x0004);
102 $thisfile_monkeysaudio['flags']['24-bit'] = (bool) ($thisfile_monkeysaudio_raw['nFormatFlags'] & 0x0008);
103 $thisfile_monkeysaudio['flags']['seek_elements'] = (bool) ($thisfile_monkeysaudio_raw['nFormatFlags'] & 0x0010);
104 $thisfile_monkeysaudio['flags']['no_wav_header'] = (bool) ($thisfile_monkeysaudio_raw['nFormatFlags'] & 0x0020);
105 $thisfile_monkeysaudio['version'] = $thisfile_monkeysaudio_raw['nVersion'] / 1000;
107 if ($thisfile_monkeysaudio_raw['nVersion'] < 3980) {
108 $thisfile_monkeysaudio[
'samples_per_frame'] = $this->
MonkeySamplesPerFrame($thisfile_monkeysaudio_raw[
'nVersion'], $thisfile_monkeysaudio_raw[
'nCompressionLevel']);
109 }
110 $thisfile_monkeysaudio['bits_per_sample'] = ($thisfile_monkeysaudio['flags']['24-bit'] ? 24 : ($thisfile_monkeysaudio['flags']['8-bit'] ? 8 : 16));
111 $thisfile_monkeysaudio['channels'] = $thisfile_monkeysaudio_raw['nChannels'];
112 $info[
'audio'][
'channels'] = $thisfile_monkeysaudio[
'channels'];
113 $thisfile_monkeysaudio['sample_rate'] = $thisfile_monkeysaudio_raw['nSampleRate'];
114 if ($thisfile_monkeysaudio['sample_rate'] == 0) {
115 $this->
error(
'Corrupt MAC file: frequency == zero');
116 return false;
117 }
118 $info[
'audio'][
'sample_rate'] = $thisfile_monkeysaudio[
'sample_rate'];
119 if ($thisfile_monkeysaudio['flags']['peak_level']) {
120 $thisfile_monkeysaudio['peak_level'] = $thisfile_monkeysaudio_raw['nPeakLevel'];
121 $thisfile_monkeysaudio['peak_ratio'] = $thisfile_monkeysaudio['peak_level'] / pow(2, $thisfile_monkeysaudio['bits_per_sample'] - 1);
122 }
123 if ($thisfile_monkeysaudio_raw['nVersion'] >= 3980) {
124 $thisfile_monkeysaudio['samples'] = (($thisfile_monkeysaudio_raw['nTotalFrames'] - 1) * $thisfile_monkeysaudio_raw['nBlocksPerFrame']) + $thisfile_monkeysaudio_raw['nFinalFrameBlocks'];
125 } else {
126 $thisfile_monkeysaudio['samples'] = (($thisfile_monkeysaudio_raw['nTotalFrames'] - 1) * $thisfile_monkeysaudio['samples_per_frame']) + $thisfile_monkeysaudio_raw['nFinalFrameSamples'];
127 }
128 $thisfile_monkeysaudio['playtime'] = $thisfile_monkeysaudio['samples'] / $thisfile_monkeysaudio['sample_rate'];
129 if ($thisfile_monkeysaudio['playtime'] == 0) {
130 $this->
error(
'Corrupt MAC file: playtime == zero');
131 return false;
132 }
133 $info[
'playtime_seconds'] = $thisfile_monkeysaudio[
'playtime'];
134 $thisfile_monkeysaudio[
'compressed_size'] =
$info[
'avdataend'] -
$info[
'avdataoffset'];
135 $thisfile_monkeysaudio['uncompressed_size'] = $thisfile_monkeysaudio['samples'] * $thisfile_monkeysaudio['channels'] * ($thisfile_monkeysaudio['bits_per_sample'] / 8);
136 if ($thisfile_monkeysaudio['uncompressed_size'] == 0) {
137 $this->
error(
'Corrupt MAC file: uncompressed_size == zero');
138 return false;
139 }
140 $thisfile_monkeysaudio['compression_ratio'] = $thisfile_monkeysaudio['compressed_size'] / ($thisfile_monkeysaudio['uncompressed_size'] + $thisfile_monkeysaudio_raw['nHeaderDataBytes']);
141 $thisfile_monkeysaudio['bitrate'] = (($thisfile_monkeysaudio['samples'] * $thisfile_monkeysaudio['channels'] * $thisfile_monkeysaudio['bits_per_sample']) / $thisfile_monkeysaudio['playtime']) * $thisfile_monkeysaudio['compression_ratio'];
142 $info[
'audio'][
'bitrate'] = $thisfile_monkeysaudio[
'bitrate'];
143
144
145 if ($thisfile_monkeysaudio_raw['nVersion'] >= 3980) {
146 $info[
'avdataoffset'] += $thisfile_monkeysaudio_raw[
'nDescriptorBytes'];
147 $info[
'avdataoffset'] += $thisfile_monkeysaudio_raw[
'nHeaderBytes'];
148 $info[
'avdataoffset'] += $thisfile_monkeysaudio_raw[
'nSeekTableBytes'];
149 $info[
'avdataoffset'] += $thisfile_monkeysaudio_raw[
'nHeaderDataBytes'];
150
151 $info[
'avdataend'] -= $thisfile_monkeysaudio_raw[
'nTerminatingDataBytes'];
152 } else {
153 $info[
'avdataoffset'] += $offset;
154 }
155
156 if ($thisfile_monkeysaudio_raw['nVersion'] >= 3980) {
157 if ($thisfile_monkeysaudio_raw['cFileMD5'] === str_repeat("\x00", 16)) {
158
159 } else {
160 $info[
'md5_data_source'] =
'';
161 $md5 = $thisfile_monkeysaudio_raw['cFileMD5'];
162 for (
$i = 0;
$i < strlen($md5);
$i++) {
163 $info[
'md5_data_source'] .= str_pad(dechex(ord($md5{
$i})), 2,
'00', STR_PAD_LEFT);
164 }
165 if (!preg_match(
'/^[0-9a-f]{32}$/',
$info[
'md5_data_source'])) {
166 unset(
$info[
'md5_data_source']);
167 }
168 }
169 }
170
171
172
173 $info[
'audio'][
'bits_per_sample'] = $thisfile_monkeysaudio[
'bits_per_sample'];
174 $info[
'audio'][
'encoder'] =
'MAC v'.number_format($thisfile_monkeysaudio[
'version'], 2);
175 $info[
'audio'][
'encoder_options'] = ucfirst($thisfile_monkeysaudio[
'compression']).
' compression';
176
177 return true;
178 }
fseek($bytes, $whence=SEEK_SET)
static PrintHexBytes($string, $hex=true, $spaces=true, $htmlencoding='UTF-8')
static LittleEndian2Int($byteword, $signed=false)
MonkeyCompressionLevelNameLookup($compressionlevel)
MonkeySamplesPerFrame($versionid, $compressionlevel)