23 $info = &$this->getid3->info;
27 $rawdata = $this->
fread($this->getid3->fread_buffer_size());
29 switch (substr($rawdata, $offset, 4)) {
33 $info[
'fileformat'] =
'la';
34 $info[
'audio'][
'dataformat'] =
'la';
35 $info[
'audio'][
'lossless'] =
true;
37 $info[
'la'][
'version_major'] = (int) substr($rawdata, $offset + 2, 1);
38 $info[
'la'][
'version_minor'] = (int) substr($rawdata, $offset + 3, 1);
39 $info[
'la'][
'version'] = (float)
$info[
'la'][
'version_major'] + (
$info[
'la'][
'version_minor'] / 10);
44 if (
$info[
'la'][
'uncompressed_size'] == 0) {
45 $this->
error(
'Corrupt LA file: uncompressed_size == zero');
49 $WAVEchunk = substr($rawdata, $offset, 4);
50 if ($WAVEchunk !==
'WAVE') {
56 $info[
'la'][
'fmt_size'] = 24;
57 if (
$info[
'la'][
'version'] >= 0.3) {
60 $info[
'la'][
'header_size'] = 49 +
$info[
'la'][
'fmt_size'] - 24;
66 $info[
'la'][
'header_size'] = 41;
70 $fmt_chunk = substr($rawdata, $offset, 4);
71 if ($fmt_chunk !==
'fmt ') {
84 if (
$info[
'la'][
'channels'] == 0) {
85 $this->
error(
'Corrupt LA file: channels == zero');
91 if (
$info[
'la'][
'sample_rate'] == 0) {
92 $this->
error(
'Corrupt LA file: sample_rate == zero');
108 $info[
'la'][
'flags'][
'seekable'] = (bool) (
$info[
'la'][
'raw'][
'flags'] & 0x01);
109 if (
$info[
'la'][
'version'] >= 0.4) {
110 $info[
'la'][
'flags'][
'high_compression'] = (bool) (
$info[
'la'][
'raw'][
'flags'] & 0x02);
122 if (
$info[
'la'][
'version'] >= 0.4) {
123 $info[
'la'][
'blocksize'] = 61440;
124 $info[
'la'][
'seekevery'] = 19;
126 $info[
'la'][
'blocksize'] = 73728;
127 $info[
'la'][
'seekevery'] = 16;
130 $info[
'la'][
'seekpoint_count'] = 0;
131 if (
$info[
'la'][
'flags'][
'seekable']) {
132 $info[
'la'][
'seekpoint_count'] = floor(
$info[
'la'][
'samples'] / (
$info[
'la'][
'blocksize'] *
$info[
'la'][
'seekevery']));
134 for (
$i = 0;
$i <
$info[
'la'][
'seekpoint_count'];
$i++) {
140 if ($info[
'la'][
'version'] >= 0.3) {
148 if ($info[
'la'][
'footerstart'] > $info[
'filesize']) {
149 $this->
warning(
'FooterStart value points to offset '.$info[
'la'][
'footerstart'].
' which is beyond end-of-file ('.$info[
'filesize'].
')');
150 $info[
'la'][
'footerstart'] = $info[
'filesize'];
156 $info[
'la'][
'footerstart'] = $info[
'avdataend'];
160 if ($info[
'la'][
'footerstart'] < $info[
'avdataend']) {
161 if ($RIFFtempfilename = tempnam(GETID3_TEMP_DIR,
'id3')) {
162 if ($RIFF_fp =
fopen($RIFFtempfilename,
'w+b')) {
164 if ($info[
'la'][
'version'] == 0.2) {
165 $RIFFdata .= substr($rawdata, 12, 24);
167 $RIFFdata .= substr($rawdata, 16, 24);
169 if ($info[
'la'][
'footerstart'] < $info[
'avdataend']) {
170 $this->
fseek($info[
'la'][
'footerstart']);
171 $RIFFdata .= $this->
fread($info[
'avdataend'] - $info[
'la'][
'footerstart']);
173 $RIFFdata =
'RIFF'.getid3_lib::LittleEndian2String(strlen($RIFFdata), 4,
false).$RIFFdata;
174 fwrite($RIFF_fp, $RIFFdata, strlen($RIFFdata));
177 $getid3_temp =
new getID3();
178 $getid3_temp->openfile($RIFFtempfilename);
180 $getid3_riff->Analyze();
182 if (empty($getid3_temp->info[
'error'])) {
183 $info[
'riff'] = $getid3_temp->info[
'riff'];
185 $this->
warning(
'Error parsing RIFF portion of La file: '.implode($getid3_temp->info[
'error']));
187 unset($getid3_temp, $getid3_riff);
189 unlink($RIFFtempfilename);
194 $info[
'avdataend'] = $info[
'avdataoffset'] + $info[
'la'][
'footerstart'];
195 $info[
'avdataoffset'] = $info[
'avdataoffset'] + $offset;
197 $info[
'la'][
'compression_ratio'] = (float) (($info[
'avdataend'] - $info[
'avdataoffset']) / $info[
'la'][
'uncompressed_size']);
198 $info[
'playtime_seconds'] = (float) ($info[
'la'][
'samples'] / $info[
'la'][
'sample_rate']) / $info[
'la'][
'channels'];
199 if ($info[
'playtime_seconds'] == 0) {
200 $this->
error(
'Corrupt LA file: playtime_seconds == zero');
204 $info[
'audio'][
'bitrate'] = ($info[
'avdataend'] - $info[
'avdataoffset']) * 8 / $info[
'playtime_seconds'];
206 $info[
'audio'][
'bits_per_sample'] = $info[
'la'][
'bits_per_sample'];
210 if (substr($rawdata, $offset, 2) ==
'LA') {
211 $this->
error(
'This version of getID3() ['.$this->getid3->version().
'] does not 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.');
213 $this->
error(
'Not a LA (Lossless-Audio) file');
219 $info[
'audio'][
'channels'] = $info[
'la'][
'channels'];
220 $info[
'audio'][
'sample_rate'] = (int) $info[
'la'][
'sample_rate'];
221 $info[
'audio'][
'encoder'] =
'LA v'.$info[
'la'][
'version'];
static LittleEndian2Int($byteword, $signed=false)
static PrintHexBytes($string, $hex=true, $spaces=true, $htmlencoding='UTF-8')
fseek($bytes, $whence=SEEK_SET)