cd059c927bacb89f6516980ed5579b45481d07fb
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 /////////////////////////////////////////////////////////////////
11 // module.audio.dsf.php //
12 // module for analyzing dsf/DSF Audio files //
13 // dependencies: module.tag.id3v2.php //
15 /////////////////////////////////////////////////////////////////
17 if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
20 getid3_lib
::IncludeDependency(GETID3_INCLUDEPATH
.'module.tag.id3v2.php', __FILE__
, true);
22 class getid3_dsf
extends getid3_handler
27 public function Analyze() {
28 $info = &$this->getid3
->info
;
30 $info['fileformat'] = 'dsf';
31 $info['audio']['dataformat'] = 'dsf';
32 $info['audio']['lossless'] = true;
33 $info['audio']['bitrate_mode'] = 'cbr';
35 $this->fseek($info['avdataoffset']);
36 $dsfheader = $this->fread(28 +
12);
39 $info['dsf']['dsd']['magic'] = substr($dsfheader, $headeroffset, 4);
42 if ($info['dsf']['dsd']['magic'] != $magic) {
43 $this->error('Expecting "'.getid3_lib
::PrintHexBytes($magic).'" at offset '.$info['avdataoffset'].', found "'.getid3_lib
::PrintHexBytes($info['dsf']['dsd']['magic']).'"');
44 unset($info['fileformat']);
45 unset($info['audio']);
49 $info['dsf']['dsd']['dsd_chunk_size'] = getid3_lib
::LittleEndian2Int(substr($dsfheader, $headeroffset, 8)); // should be 28
51 $info['dsf']['dsd']['dsf_file_size'] = getid3_lib
::LittleEndian2Int(substr($dsfheader, $headeroffset, 8));
53 $info['dsf']['dsd']['meta_chunk_offset'] = getid3_lib
::LittleEndian2Int(substr($dsfheader, $headeroffset, 8));
57 $info['dsf']['fmt']['magic'] = substr($dsfheader, $headeroffset, 4);
60 if ($info['dsf']['fmt']['magic'] != $magic) {
61 $this->error('Expecting "'.getid3_lib
::PrintHexBytes($magic).'" at offset '.$headeroffset.', found "'.getid3_lib
::PrintHexBytes($info['dsf']['fmt']['magic']).'"');
64 $info['dsf']['fmt']['fmt_chunk_size'] = getid3_lib
::LittleEndian2Int(substr($dsfheader, $headeroffset, 8)); // usually 52 bytes
66 $dsfheader .= $this->fread($info['dsf']['fmt']['fmt_chunk_size'] - 12 +
12); // we have already read the entire DSD chunk, plus 12 bytes of FMT. We now want to read the size of FMT, plus 12 bytes into the next chunk to get magic and size.
67 if (strlen($dsfheader) != ($info['dsf']['dsd']['dsd_chunk_size'] +
$info['dsf']['fmt']['fmt_chunk_size'] +
12)) {
68 $this->error('Expecting '.($info['dsf']['dsd']['dsd_chunk_size'] +
$info['dsf']['fmt']['fmt_chunk_size']).' bytes header, found '.strlen($dsfheader).' bytes');
71 $info['dsf']['fmt']['format_version'] = getid3_lib
::LittleEndian2Int(substr($dsfheader, $headeroffset, 4)); // usually "1"
73 $info['dsf']['fmt']['format_id'] = getid3_lib
::LittleEndian2Int(substr($dsfheader, $headeroffset, 4)); // usually "0" = "DSD Raw"
75 $info['dsf']['fmt']['channel_type_id'] = getid3_lib
::LittleEndian2Int(substr($dsfheader, $headeroffset, 4));
77 $info['dsf']['fmt']['channels'] = getid3_lib
::LittleEndian2Int(substr($dsfheader, $headeroffset, 4));
79 $info['dsf']['fmt']['sample_rate'] = getid3_lib
::LittleEndian2Int(substr($dsfheader, $headeroffset, 4));
81 $info['dsf']['fmt']['bits_per_sample'] = getid3_lib
::LittleEndian2Int(substr($dsfheader, $headeroffset, 4));
83 $info['dsf']['fmt']['sample_count'] = getid3_lib
::LittleEndian2Int(substr($dsfheader, $headeroffset, 8));
85 $info['dsf']['fmt']['channel_block_size'] = getid3_lib
::LittleEndian2Int(substr($dsfheader, $headeroffset, 4));
87 $info['dsf']['fmt']['reserved'] = getid3_lib
::LittleEndian2Int(substr($dsfheader, $headeroffset, 4)); // zero-filled
91 $info['dsf']['data']['magic'] = substr($dsfheader, $headeroffset, 4);
94 if ($info['dsf']['data']['magic'] != $magic) {
95 $this->error('Expecting "'.getid3_lib
::PrintHexBytes($magic).'" at offset '.$headeroffset.', found "'.getid3_lib
::PrintHexBytes($info['dsf']['data']['magic']).'"');
98 $info['dsf']['data']['data_chunk_size'] = getid3_lib
::LittleEndian2Int(substr($dsfheader, $headeroffset, 8));
100 $info['avdataoffset'] = $headeroffset;
101 $info['avdataend'] = $info['avdataoffset'] +
$info['dsf']['data']['data_chunk_size'];
104 if ($info['dsf']['dsd']['meta_chunk_offset'] > 0) {
105 $getid3_id3v2 = new getid3_id3v2($this->getid3
);
106 $getid3_id3v2->StartingOffset
= $info['dsf']['dsd']['meta_chunk_offset'];
107 $getid3_id3v2->Analyze();
108 unset($getid3_id3v2);
112 $info['dsf']['fmt']['channel_type'] = $this->DSFchannelTypeLookup($info['dsf']['fmt']['channel_type_id']);
113 $info['audio']['channelmode'] = $info['dsf']['fmt']['channel_type'];
114 $info['audio']['bits_per_sample'] = $info['dsf']['fmt']['bits_per_sample'];
115 $info['audio']['sample_rate'] = $info['dsf']['fmt']['sample_rate'];
116 $info['audio']['channels'] = $info['dsf']['fmt']['channels'];
117 $info['audio']['bitrate'] = $info['audio']['bits_per_sample'] * $info['audio']['sample_rate'] * $info['audio']['channels'];
118 $info['playtime_seconds'] = ($info['dsf']['data']['data_chunk_size'] * 8) / $info['audio']['bitrate'];
124 * @param int $channel_type_id
128 public static function DSFchannelTypeLookup($channel_type_id) {
129 static $DSFchannelTypeLookup = array(
130 // interleaving order:
131 1 => 'mono', // 1: Mono
132 2 => 'stereo', // 1: Front-Left; 2: Front-Right
133 3 => '3-channel', // 1: Front-Left; 2: Front-Right; 3: Center
134 4 => 'quad', // 1: Front-Left; 2: Front-Right; 3: Back-Left; 4: Back-Right
135 5 => '4-channel', // 1: Front-Left; 2: Front-Right; 3: Center; 4: Low-Frequency
136 6 => '5-channel', // 1: Front-Left; 2: Front-Right; 3: Center; 4: Back-Left 5: Back-Right
137 7 => '5.1', // 1: Front-Left; 2: Front-Right; 3: Center; 4: Low-Frequency; 5: Back-Left; 6: Back-Right
139 return (isset($DSFchannelTypeLookup[$channel_type_id]) ?
$DSFchannelTypeLookup[$channel_type_id] : '');