20 {
21
22 $OriginalAVdataOffset = $ThisFileInfo['avdataoffset'];
23 fseek($fd, $ThisFileInfo['avdataoffset'], SEEK_SET);
24 $VOCheader = fread($fd, 26);
25
26 if (substr($VOCheader, 0, 19) != 'Creative Voice File') {
27 $ThisFileInfo['error'][] = 'Expecting "Creative Voice File" at offset '.$ThisFileInfo['avdataoffset'].', found "'.substr($VOCheader, 0, 19).'"';
28 return false;
29 }
30
31
32 $thisfile_audio = &$ThisFileInfo['audio'];
33 $ThisFileInfo['voc'] = array();
34 $thisfile_voc = &$ThisFileInfo['voc'];
35
36 $ThisFileInfo['fileformat'] = 'voc';
37 $thisfile_audio['dataformat'] = 'voc';
38 $thisfile_audio['bitrate_mode'] = 'cbr';
39 $thisfile_audio['lossless'] = true;
40 $thisfile_audio['channels'] = 1;
41 $thisfile_audio['bits_per_sample'] = 8;
42
43
44
45
46
47
48
49
50
54
55 do {
56
57 $BlockOffset = ftell($fd);
58 $BlockData = fread($fd, 4);
59 $BlockType = ord($BlockData{0});
61 $ThisBlock = array();
62
63 @$thisfile_voc['blocktypes'][$BlockType]++;
64 switch ($BlockType) {
65 case 0:
66
67 break;
68
69 case 1:
70 $BlockData .= fread($fd, 2);
71 if ($ThisFileInfo['avdataoffset'] <= $OriginalAVdataOffset) {
72 $ThisFileInfo['avdataoffset'] = ftell($fd);
73 }
74 fseek($fd, $BlockSize - 2, SEEK_CUR);
75
78
80 if ($ThisBlock['compression_type'] <= 3) {
81 $thisfile_voc[
'compressed_bits_per_sample'] =
getid3_lib::CastAsInt(str_replace(
'-bit',
'', $ThisBlock[
'compression_name']));
82 }
83
84
85 if (empty($thisfile_audio['sample_rate'])) {
86
87 $thisfile_audio[
'sample_rate'] =
getid3_lib::trunc((1000000 / (256 - $ThisBlock[
'sample_rate_id'])) / $thisfile_audio[
'channels']);
88 }
89 break;
90
91 case 2:
92 case 3:
93 case 4:
94 case 6:
95 case 7:
96
97 fseek($fd, $BlockSize, SEEK_CUR);
98 break;
99
100 case 8:
101 $BlockData .= fread($fd, 4);
102
103
104
105
109
110 $thisfile_audio['channels'] = ($ThisBlock['stereo'] ? 2 : 1);
111 $thisfile_audio[
'sample_rate'] =
getid3_lib::trunc((256000000 / (65536 - $ThisBlock[
'time_constant'])) / $thisfile_audio[
'channels']);
112 break;
113
114 case 9:
115 $BlockData .= fread($fd, 12);
116 if ($ThisFileInfo['avdataoffset'] <= $OriginalAVdataOffset) {
117 $ThisFileInfo['avdataoffset'] = ftell($fd);
118 }
119 fseek($fd, $BlockSize - 12, SEEK_CUR);
120
125
126 $ThisBlock[
'compression_name'] = $this->
VOCwFormatLookup($ThisBlock[
'wFormat']);
129 }
130
131 $thisfile_audio['sample_rate'] = $ThisBlock['sample_rate'];
132 $thisfile_audio['bits_per_sample'] = $ThisBlock['bits_per_sample'];
133 $thisfile_audio['channels'] = $ThisBlock['channels'];
134 break;
135
136 default:
137 $ThisFileInfo['warning'][] = 'Unhandled block type "'.$BlockType.'" at offset '.$BlockOffset;
138 fseek($fd, $BlockSize, SEEK_CUR);
139 break;
140 }
141
142 if (!empty($ThisBlock)) {
143 $ThisBlock['block_offset'] = $BlockOffset;
144 $ThisBlock['block_size'] = $BlockSize;
145 $ThisBlock['block_type_id'] = $BlockType;
146 $thisfile_voc['blocks'][] = $ThisBlock;
147 }
148
149 } while (!feof($fd) && ($BlockType != 0));
150
151
152 fseek($fd, -3, SEEK_CUR);
153
154 ksort($thisfile_voc['blocktypes']);
155
156 if (!empty($thisfile_voc['compressed_bits_per_sample'])) {
157 $ThisFileInfo['playtime_seconds'] = (($ThisFileInfo['avdataend'] - $ThisFileInfo['avdataoffset']) * 8) / ($thisfile_voc['compressed_bits_per_sample'] * $thisfile_audio['channels'] * $thisfile_audio['sample_rate']);
158 $thisfile_audio['bitrate'] = (($ThisFileInfo['avdataend'] - $ThisFileInfo['avdataoffset']) * 8) / $ThisFileInfo['playtime_seconds'];
159 }
160
161 return true;
162 }
LittleEndian2Int($byteword, $signed=false)
VOCwFormatActualBitsPerSampleLookup($index)
VOCcompressionTypeLookup($index)