2011-07-22 08:30:52 +04:00
< ? php
/////////////////////////////////////////////////////////////////
/// getID3() by James Heinrich <info@getid3.org> //
// available at http://getid3.sourceforge.net //
// or http://www.getid3.org //
/////////////////////////////////////////////////////////////////
// See readme.txt for more details //
/////////////////////////////////////////////////////////////////
// //
// module.audio.shorten.php //
// module for analyzing Shorten Audio files //
// dependencies: NONE //
// ///
/////////////////////////////////////////////////////////////////
2012-04-03 01:33:18 +04:00
class getid3_shorten extends getid3_handler
2011-07-22 08:30:52 +04:00
{
2012-04-03 01:33:18 +04:00
function Analyze () {
$info = & $this -> getid3 -> info ;
2011-07-22 08:30:52 +04:00
2012-04-03 01:33:18 +04:00
fseek ( $this -> getid3 -> fp , $info [ 'avdataoffset' ], SEEK_SET );
2011-07-22 08:30:52 +04:00
2012-04-03 01:33:18 +04:00
$ShortenHeader = fread ( $this -> getid3 -> fp , 8 );
$magic = 'ajkg' ;
if ( substr ( $ShortenHeader , 0 , 4 ) != $magic ) {
$info [ 'error' ][] = 'Expecting "' . getid3_lib :: PrintHexBytes ( $magic ) . '" at offset ' . $info [ 'avdataoffset' ] . ', found "' . getid3_lib :: PrintHexBytes ( substr ( $ShortenHeader , 0 , 4 )) . '"' ;
2011-07-22 08:30:52 +04:00
return false ;
}
2012-04-03 01:33:18 +04:00
$info [ 'fileformat' ] = 'shn' ;
$info [ 'audio' ][ 'dataformat' ] = 'shn' ;
$info [ 'audio' ][ 'lossless' ] = true ;
$info [ 'audio' ][ 'bitrate_mode' ] = 'vbr' ;
$info [ 'shn' ][ 'version' ] = getid3_lib :: LittleEndian2Int ( substr ( $ShortenHeader , 4 , 1 ));
fseek ( $this -> getid3 -> fp , $info [ 'avdataend' ] - 12 , SEEK_SET );
$SeekTableSignatureTest = fread ( $this -> getid3 -> fp , 12 );
$info [ 'shn' ][ 'seektable' ][ 'present' ] = ( bool ) ( substr ( $SeekTableSignatureTest , 4 , 8 ) == 'SHNAMPSK' );
if ( $info [ 'shn' ][ 'seektable' ][ 'present' ]) {
$info [ 'shn' ][ 'seektable' ][ 'length' ] = getid3_lib :: LittleEndian2Int ( substr ( $SeekTableSignatureTest , 0 , 4 ));
$info [ 'shn' ][ 'seektable' ][ 'offset' ] = $info [ 'avdataend' ] - $info [ 'shn' ][ 'seektable' ][ 'length' ];
fseek ( $this -> getid3 -> fp , $info [ 'shn' ][ 'seektable' ][ 'offset' ], SEEK_SET );
$SeekTableMagic = fread ( $this -> getid3 -> fp , 4 );
$magic = 'SEEK' ;
if ( $SeekTableMagic != $magic ) {
$info [ 'error' ][] = 'Expecting "' . getid3_lib :: PrintHexBytes ( $magic ) . '" at offset ' . $info [ 'shn' ][ 'seektable' ][ 'offset' ] . ', found "' . getid3_lib :: PrintHexBytes ( $SeekTableMagic ) . '"' ;
2011-07-22 08:30:52 +04:00
return false ;
} else {
// typedef struct tag_TSeekEntry
// {
// unsigned long SampleNumber;
// unsigned long SHNFileByteOffset;
// unsigned long SHNLastBufferReadPosition;
// unsigned short SHNByteGet;
// unsigned short SHNBufferOffset;
// unsigned short SHNFileBitOffset;
// unsigned long SHNGBuffer;
// unsigned short SHNBitShift;
// long CBuf0[3];
// long CBuf1[3];
// long Offset0[4];
// long Offset1[4];
// }TSeekEntry;
2012-04-03 01:33:18 +04:00
$SeekTableData = fread ( $this -> getid3 -> fp , $info [ 'shn' ][ 'seektable' ][ 'length' ] - 16 );
$info [ 'shn' ][ 'seektable' ][ 'entry_count' ] = floor ( strlen ( $SeekTableData ) / 80 );
//$info['shn']['seektable']['entries'] = array();
2011-07-22 08:30:52 +04:00
//$SeekTableOffset = 0;
2012-04-03 01:33:18 +04:00
//for ($i = 0; $i < $info['shn']['seektable']['entry_count']; $i++) {
2011-07-22 08:30:52 +04:00
// $SeekTableEntry['sample_number'] = getid3_lib::LittleEndian2Int(substr($SeekTableData, $SeekTableOffset, 4));
// $SeekTableOffset += 4;
// $SeekTableEntry['shn_file_byte_offset'] = getid3_lib::LittleEndian2Int(substr($SeekTableData, $SeekTableOffset, 4));
// $SeekTableOffset += 4;
// $SeekTableEntry['shn_last_buffer_read_position'] = getid3_lib::LittleEndian2Int(substr($SeekTableData, $SeekTableOffset, 4));
// $SeekTableOffset += 4;
// $SeekTableEntry['shn_byte_get'] = getid3_lib::LittleEndian2Int(substr($SeekTableData, $SeekTableOffset, 2));
// $SeekTableOffset += 2;
// $SeekTableEntry['shn_buffer_offset'] = getid3_lib::LittleEndian2Int(substr($SeekTableData, $SeekTableOffset, 2));
// $SeekTableOffset += 2;
// $SeekTableEntry['shn_file_bit_offset'] = getid3_lib::LittleEndian2Int(substr($SeekTableData, $SeekTableOffset, 2));
// $SeekTableOffset += 2;
// $SeekTableEntry['shn_gbuffer'] = getid3_lib::LittleEndian2Int(substr($SeekTableData, $SeekTableOffset, 4));
// $SeekTableOffset += 4;
// $SeekTableEntry['shn_bit_shift'] = getid3_lib::LittleEndian2Int(substr($SeekTableData, $SeekTableOffset, 2));
// $SeekTableOffset += 2;
// for ($j = 0; $j < 3; $j++) {
// $SeekTableEntry['cbuf0'][$j] = getid3_lib::LittleEndian2Int(substr($SeekTableData, $SeekTableOffset, 4));
// $SeekTableOffset += 4;
// }
// for ($j = 0; $j < 3; $j++) {
// $SeekTableEntry['cbuf1'][$j] = getid3_lib::LittleEndian2Int(substr($SeekTableData, $SeekTableOffset, 4));
// $SeekTableOffset += 4;
// }
// for ($j = 0; $j < 4; $j++) {
// $SeekTableEntry['offset0'][$j] = getid3_lib::LittleEndian2Int(substr($SeekTableData, $SeekTableOffset, 4));
// $SeekTableOffset += 4;
// }
// for ($j = 0; $j < 4; $j++) {
// $SeekTableEntry['offset1'][$j] = getid3_lib::LittleEndian2Int(substr($SeekTableData, $SeekTableOffset, 4));
// $SeekTableOffset += 4;
// }
2012-04-03 01:33:18 +04:00
//
// $info['shn']['seektable']['entries'][] = $SeekTableEntry;
2011-07-22 08:30:52 +04:00
//}
}
}
2012-04-03 01:33:18 +04:00
if ( preg_match ( '#(1|ON)#i' , ini_get ( 'safe_mode' ))) {
$info [ 'error' ][] = 'PHP running in Safe Mode - backtick operator not available, cannot run shntool to analyze Shorten files' ;
2011-07-22 08:30:52 +04:00
return false ;
}
if ( GETID3_OS_ISWINDOWS ) {
$RequiredFiles = array ( 'shorten.exe' , 'cygwin1.dll' , 'head.exe' );
foreach ( $RequiredFiles as $required_file ) {
if ( ! is_readable ( GETID3_HELPERAPPSDIR . $required_file )) {
2012-04-03 01:33:18 +04:00
$info [ 'error' ][] = GETID3_HELPERAPPSDIR . $required_file . ' does not exist' ;
2011-07-22 08:30:52 +04:00
return false ;
}
}
2012-04-03 01:33:18 +04:00
$commandline = GETID3_HELPERAPPSDIR . 'shorten.exe -x "' . $info [ 'filenamepath' ] . '" - | ' . GETID3_HELPERAPPSDIR . 'head.exe -c 64' ;
2011-07-22 08:30:52 +04:00
$commandline = str_replace ( '/' , '\\' , $commandline );
} else {
2012-04-03 01:33:18 +04:00
static $shorten_present ;
if ( ! isset ( $shorten_present )) {
$shorten_present = file_exists ( '/usr/local/bin/shorten' ) || `which shorten` ;
}
if ( ! $shorten_present ) {
$info [ 'error' ][] = 'shorten binary was not found in path or /usr/local/bin' ;
return false ;
}
$commandline = ( file_exists ( '/usr/local/bin/shorten' ) ? '/usr/local/bin/' : '' ) . 'shorten -x ' . escapeshellarg ( $info [ 'filenamepath' ]) . ' - | head -c 64' ;
2011-07-22 08:30:52 +04:00
}
$output = `$commandline` ;
if ( ! empty ( $output ) && ( substr ( $output , 12 , 4 ) == 'fmt ' )) {
getid3_lib :: IncludeDependency ( GETID3_INCLUDEPATH . 'module.audio-video.riff.php' , __FILE__ , true );
$fmt_size = getid3_lib :: LittleEndian2Int ( substr ( $output , 16 , 4 ));
$DecodedWAVFORMATEX = getid3_riff :: RIFFparseWAVEFORMATex ( substr ( $output , 20 , $fmt_size ));
2012-04-03 01:33:18 +04:00
$info [ 'audio' ][ 'channels' ] = $DecodedWAVFORMATEX [ 'channels' ];
$info [ 'audio' ][ 'bits_per_sample' ] = $DecodedWAVFORMATEX [ 'bits_per_sample' ];
$info [ 'audio' ][ 'sample_rate' ] = $DecodedWAVFORMATEX [ 'sample_rate' ];
2011-07-22 08:30:52 +04:00
if ( substr ( $output , 20 + $fmt_size , 4 ) == 'data' ) {
2012-04-03 01:33:18 +04:00
$info [ 'playtime_seconds' ] = getid3_lib :: LittleEndian2Int ( substr ( $output , 20 + 4 + $fmt_size , 4 )) / $DecodedWAVFORMATEX [ 'raw' ][ 'nAvgBytesPerSec' ];
2011-07-22 08:30:52 +04:00
} else {
2012-04-03 01:33:18 +04:00
$info [ 'error' ][] = 'shorten failed to decode DATA chunk to expected location, cannot determine playtime' ;
2011-07-22 08:30:52 +04:00
return false ;
}
2012-04-03 01:33:18 +04:00
$info [ 'audio' ][ 'bitrate' ] = (( $info [ 'avdataend' ] - $info [ 'avdataoffset' ]) / $info [ 'playtime_seconds' ]) * 8 ;
2011-07-22 08:30:52 +04:00
} else {
2012-04-03 01:33:18 +04:00
$info [ 'error' ][] = 'shorten failed to decode file to WAV for parsing' ;
2011-07-22 08:30:52 +04:00
return false ;
}
return true ;
}
}
?>