23 fseek($fd, $ThisFileInfo[
'avdataoffset'], SEEK_SET);
26 switch (substr($rawdata, $offset, 4)) {
30 $ThisFileInfo[
'fileformat'] =
'la';
31 $ThisFileInfo[
'audio'][
'dataformat'] =
'la';
32 $ThisFileInfo[
'audio'][
'lossless'] =
true;
34 $ThisFileInfo[
'la'][
'version_major'] = (int) substr($rawdata, $offset + 2, 1);
35 $ThisFileInfo[
'la'][
'version_minor'] = (int) substr($rawdata, $offset + 3, 1);
36 $ThisFileInfo[
'la'][
'version'] = (float) $ThisFileInfo[
'la'][
'version_major'] + ($ThisFileInfo[
'la'][
'version_minor'] / 10);
41 if ($ThisFileInfo[
'la'][
'uncompressed_size'] == 0) {
42 $ThisFileInfo[
'error'][] =
'Corrupt LA file: uncompressed_size == zero';
46 $WAVEchunk = substr($rawdata, $offset, 4);
47 if ($WAVEchunk !==
'WAVE') {
48 $ThisFileInfo[
'error'][] =
'Expected "WAVE" ('.getid3_lib::PrintHexBytes(
'WAVE').
') at offset '.$offset.
', found "'.$WAVEchunk.
'" ('.
getid3_lib::PrintHexBytes($WAVEchunk).
') instead.';
53 $ThisFileInfo[
'la'][
'fmt_size'] = 24;
54 if ($ThisFileInfo[
'la'][
'version'] >= 0.3) {
57 $ThisFileInfo[
'la'][
'header_size'] = 49 + $ThisFileInfo[
'la'][
'fmt_size'] - 24;
63 $ThisFileInfo[
'la'][
'header_size'] = 41;
67 $fmt_chunk = substr($rawdata, $offset, 4);
68 if ($fmt_chunk !==
'fmt ') {
69 $ThisFileInfo[
'error'][] =
'Expected "fmt " ('.getid3_lib::PrintHexBytes(
'fmt ').
') at offset '.$offset.
', found "'.$fmt_chunk.
'" ('.
getid3_lib::PrintHexBytes($fmt_chunk).
') instead.';
81 if ($ThisFileInfo[
'la'][
'channels'] == 0) {
82 $ThisFileInfo[
'error'][] =
'Corrupt LA file: channels == zero';
88 if ($ThisFileInfo[
'la'][
'sample_rate'] == 0) {
89 $ThisFileInfo[
'error'][] =
'Corrupt LA file: sample_rate == zero';
105 $ThisFileInfo[
'la'][
'flags'][
'seekable'] = (bool) ($ThisFileInfo[
'la'][
'raw'][
'flags'] & 0x01);
106 if ($ThisFileInfo[
'la'][
'version'] >= 0.4) {
107 $ThisFileInfo[
'la'][
'flags'][
'high_compression'] = (bool) ($ThisFileInfo[
'la'][
'raw'][
'flags'] & 0x02);
119 if ($ThisFileInfo[
'la'][
'version'] >= 0.4) {
120 $ThisFileInfo[
'la'][
'blocksize'] = 61440;
121 $ThisFileInfo[
'la'][
'seekevery'] = 19;
123 $ThisFileInfo[
'la'][
'blocksize'] = 73728;
124 $ThisFileInfo[
'la'][
'seekevery'] = 16;
127 $ThisFileInfo[
'la'][
'seekpoint_count'] = 0;
128 if ($ThisFileInfo[
'la'][
'flags'][
'seekable']) {
129 $ThisFileInfo[
'la'][
'seekpoint_count'] = floor($ThisFileInfo[
'la'][
'samples'] / ($ThisFileInfo[
'la'][
'blocksize'] * $ThisFileInfo[
'la'][
'seekevery']));
131 for ($i = 0; $i < $ThisFileInfo[
'la'][
'seekpoint_count']; $i++) {
137 if ($ThisFileInfo[
'la'][
'version'] >= 0.3) {
145 if ($ThisFileInfo[
'la'][
'footerstart'] > $ThisFileInfo[
'filesize']) {
146 $ThisFileInfo[
'warning'][] =
'FooterStart value points to offset '.$ThisFileInfo[
'la'][
'footerstart'].
' which is beyond end-of-file ('.$ThisFileInfo[
'filesize'].
')';
147 $ThisFileInfo[
'la'][
'footerstart'] = $ThisFileInfo[
'filesize'];
153 $ThisFileInfo[
'la'][
'footerstart'] = $ThisFileInfo[
'avdataend'];
157 if ($ThisFileInfo[
'la'][
'footerstart'] < $ThisFileInfo[
'avdataend']) {
158 if ($RIFFtempfilename = tempnam(
'*',
'id3')) {
159 if ($RIFF_fp = fopen($RIFFtempfilename,
'w+b')) {
161 if ($ThisFileInfo[
'la'][
'version'] == 0.2) {
162 $RIFFdata .= substr($rawdata, 12, 24);
164 $RIFFdata .= substr($rawdata, 16, 24);
166 if ($ThisFileInfo[
'la'][
'footerstart'] < $ThisFileInfo[
'avdataend']) {
167 fseek($fd, $ThisFileInfo[
'la'][
'footerstart'], SEEK_SET);
168 $RIFFdata .= fread($fd, $ThisFileInfo[
'avdataend'] - $ThisFileInfo[
'la'][
'footerstart']);
170 $RIFFdata =
'RIFF'.getid3_lib::LittleEndian2String(strlen($RIFFdata), 4,
false).$RIFFdata;
171 fwrite($RIFF_fp, $RIFFdata, strlen($RIFFdata));
172 $dummy = $ThisFileInfo;
173 $dummy[
'filesize'] = strlen($RIFFdata);
174 $dummy[
'avdataoffset'] = 0;
175 $dummy[
'avdataend'] = $dummy[
'filesize'];
178 if (empty($dummy[
'error'])) {
179 $ThisFileInfo[
'riff'] = $dummy[
'riff'];
181 $ThisFileInfo[
'warning'][] =
'Error parsing RIFF portion of La file: '.implode($dummy[
'error']);
186 unlink($RIFFtempfilename);
191 $ThisFileInfo[
'avdataend'] = $ThisFileInfo[
'avdataoffset'] + $ThisFileInfo[
'la'][
'footerstart'];
192 $ThisFileInfo[
'avdataoffset'] = $ThisFileInfo[
'avdataoffset'] + $offset;
195 $ThisFileInfo[
'la'][
'compression_ratio'] = (float) (($ThisFileInfo[
'avdataend'] - $ThisFileInfo[
'avdataoffset']) / $ThisFileInfo[
'la'][
'uncompressed_size']);
196 $ThisFileInfo[
'playtime_seconds'] = (float) ($ThisFileInfo[
'la'][
'samples'] / $ThisFileInfo[
'la'][
'sample_rate']) / $ThisFileInfo[
'la'][
'channels'];
197 if ($ThisFileInfo[
'playtime_seconds'] == 0) {
198 $ThisFileInfo[
'error'][] =
'Corrupt LA file: playtime_seconds == zero';
202 $ThisFileInfo[
'audio'][
'bitrate'] = ($ThisFileInfo[
'avdataend'] - $ThisFileInfo[
'avdataoffset']) * 8 / $ThisFileInfo[
'playtime_seconds'];
204 $ThisFileInfo[
'audio'][
'bits_per_sample'] = $ThisFileInfo[
'la'][
'bits_per_sample'];
208 if (substr($rawdata, $offset, 2) ==
'LA') {
209 $ThisFileInfo[
'error'][] =
'This version of getID3() (v'.GETID3_VERSION.
') doesn\'t support LA version '.substr($rawdata, $offset + 2, 1).
'.'.substr($rawdata, $offset + 3, 1).
' which this appears to be - check http://getid3.sourceforge.net for updates.';
211 $ThisFileInfo[
'error'][] =
'Not a LA (Lossless-Audio) file';
217 $ThisFileInfo[
'audio'][
'channels'] = $ThisFileInfo[
'la'][
'channels'];
218 $ThisFileInfo[
'audio'][
'sample_rate'] = (int) $ThisFileInfo[
'la'][
'sample_rate'];
219 $ThisFileInfo[
'audio'][
'encoder'] =
'LA v'.$ThisFileInfo[
'la'][
'version'];