Initial revision
This commit is contained in:
parent
a9b564e98d
commit
0dee919581
29 changed files with 11227 additions and 0 deletions
129
livesupport/modules/getid3/Makefile
Normal file
129
livesupport/modules/getid3/Makefile
Normal file
|
@ -0,0 +1,129 @@
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
# getID3 - read and writes tags in media files - see getid3.readme.txt
|
||||||
|
# getID3 by James Heinrich <getid3@users.sourceforge.net>
|
||||||
|
#
|
||||||
|
# This file is part of the LiveSupport project.
|
||||||
|
# Copyright (c) 2004 Media Development Loan Fund
|
||||||
|
#
|
||||||
|
# LiveSupport is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# LiveSupport is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with LiveSupport; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# Author : Author: James Heinrich <getid3@users.sourceforge.net>
|
||||||
|
# Version : $Revision: 1.1 $
|
||||||
|
# Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/getid3/Attic/Makefile,v $
|
||||||
|
#
|
||||||
|
# @configure_input@
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
# General command definitions
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
MKDIR = mkdir -p
|
||||||
|
RM = rm -f
|
||||||
|
RMDIR = rm -rf
|
||||||
|
DOXYGEN = doxygen
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
# Misc
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
MODULE_NAME = getid3
|
||||||
|
TAR_C = tar -cj --exclude CVS --exclude '*~' -C ${BASE_DIR} -f
|
||||||
|
DIST_EXT = .tgz
|
||||||
|
DATE = `date +%y%m%d`
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
# Basic directory and file definitions
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
#BASE_DIR = @builddir@
|
||||||
|
BASE_DIR = .
|
||||||
|
DOC_DIR = ${BASE_DIR}/doc
|
||||||
|
DOXYGEN_DIR = ${DOC_DIR}/doxygen
|
||||||
|
ETC_DIR = ${BASE_DIR}/etc
|
||||||
|
INCLUDE_DIR = ${BASE_DIR}/include
|
||||||
|
LIB_DIR = ${BASE_DIR}/lib
|
||||||
|
SRC_DIR = ${BASE_DIR}/src
|
||||||
|
TMP_DIR = ${BASE_DIR}/tmp
|
||||||
|
|
||||||
|
USR_DIR = ${BASE_DIR}/../../usr
|
||||||
|
USR_INCLUDE_DIR = ${USR_DIR}/include
|
||||||
|
USR_LIB_DIR = ${USR_DIR}/lib
|
||||||
|
|
||||||
|
DOXYGEN_CONFIG = ${ETC_DIR}/doxygen.config
|
||||||
|
|
||||||
|
PHP_DIR = ${BASE_DIR}/var
|
||||||
|
#TEST_RUNNER = ${PHP_DIR}/tests/index.php
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
# Configuration parameters
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
#CPPFLAGS = @CPPFLAGS@
|
||||||
|
#CXXFLAGS = @CXXFLAGS@ @DEFS@ -I${USR_INCLUDE_DIR} -I${INCLUDE_DIR} -I${TMP_DIR}\
|
||||||
|
# -pedantic -Wall
|
||||||
|
#LDFLAGS = @LDFLAGS@ -L${USR_LIB_DIR} -L${LIB_DIR}
|
||||||
|
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
# Dependencies
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
#HELLO_LIB_OBJS = ${TMP_DIR}/Hello.o
|
||||||
|
#TEST_RUNNER_OBJS = ${TMP_DIR}/HelloTest.o ${TMP_DIR}/TestRunner.o
|
||||||
|
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
# Targets
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
.PHONY: all dir_setup doc clean docclean depclean distclean dist
|
||||||
|
|
||||||
|
all: dir_setup
|
||||||
|
|
||||||
|
#dir_setup: ${TMP_DIR} ${DOXYGEN_DIR}
|
||||||
|
dir_setup: ${DOXYGEN_DIR}
|
||||||
|
|
||||||
|
doc:
|
||||||
|
${DOXYGEN} ${DOXYGEN_CONFIG}
|
||||||
|
|
||||||
|
clean:
|
||||||
|
# ${RM} ...
|
||||||
|
|
||||||
|
docclean:
|
||||||
|
${RMDIR} ${DOXYGEN_DIR}/html
|
||||||
|
|
||||||
|
depclean: clean
|
||||||
|
|
||||||
|
dist: all
|
||||||
|
${TAR_C} ${MODULE_NAME}${DATE}${DIST_EXT} *
|
||||||
|
|
||||||
|
distclean: clean docclean
|
||||||
|
# ${RMDIR} ${TMP_DIR}/config* ${TMP_DIR}/autom4te*
|
||||||
|
|
||||||
|
#check: all ${TEST_RUNNER}
|
||||||
|
# ${TEST_RUNNER}
|
||||||
|
check: all
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
# Specific targets
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
${DOXYGEN_DIR}:
|
||||||
|
${MKDIR} ${DOXYGEN_DIR}
|
||||||
|
|
||||||
|
#${TEST_RUNNER}:
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
# Pattern rules
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
#${TMP_DIR}/%.o : ${SRC_DIR}/%.cxx
|
||||||
|
# ${CXX} ${CPPFLAGS} ${CXXFLAGS} -c -o $@ $<
|
||||||
|
|
1144
livesupport/modules/getid3/etc/doxygen.config
Normal file
1144
livesupport/modules/getid3/etc/doxygen.config
Normal file
File diff suppressed because it is too large
Load diff
312
livesupport/modules/getid3/var/audioinfo.class.php
Normal file
312
livesupport/modules/getid3/var/audioinfo.class.php
Normal file
|
@ -0,0 +1,312 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
// +----------------------------------------------------------------------+
|
||||||
|
// | PHP version 4.1.0 |
|
||||||
|
// +----------------------------------------------------------------------+
|
||||||
|
// | Placed in public domain by Allan Hansen, 2002. Share and enjoy! |
|
||||||
|
// +----------------------------------------------------------------------+
|
||||||
|
// | audioinfo.class.php |
|
||||||
|
// | |
|
||||||
|
// | Example wrapper class to extract information from audio files |
|
||||||
|
// | through getID3(). |
|
||||||
|
// | |
|
||||||
|
// | getID3() returns a lot of information. Much of this information is |
|
||||||
|
// | not needed for the end-application. It is also possible that some |
|
||||||
|
// | users want to extract specific info. Modifying getID3() files is a |
|
||||||
|
// | bad idea, as modifications needs to be done to future versions of |
|
||||||
|
// | getID3(). |
|
||||||
|
// | |
|
||||||
|
// | Modify this wrapper class instead. This example extracts certain |
|
||||||
|
// | fields only and adds a new root value - encoder_options if possible. |
|
||||||
|
// | It also checks for mp3 files with wave headers. |
|
||||||
|
// +----------------------------------------------------------------------+
|
||||||
|
// | Example code: |
|
||||||
|
// | $au = new AudioInfo(); |
|
||||||
|
// | print_r($au->Info('file.flac'); |
|
||||||
|
// +----------------------------------------------------------------------+
|
||||||
|
// | Authors: Allan Hansen <ah@artemis.dk> |
|
||||||
|
// +----------------------------------------------------------------------+
|
||||||
|
//
|
||||||
|
// $Id: audioinfo.class.php,v 1.1 2004/09/12 21:32:36 tomas Exp $
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* getID3() settings
|
||||||
|
*/
|
||||||
|
|
||||||
|
include_once('getid3.php');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class for extracting information from audio files with getID3().
|
||||||
|
*/
|
||||||
|
|
||||||
|
class AudioInfo {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Private variables
|
||||||
|
*/
|
||||||
|
var $result = NULL;
|
||||||
|
var $info = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract information - only public function
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string file Audio file to extract info from.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function Info($file) {
|
||||||
|
|
||||||
|
// Too many mp3 encoders on the market put gabage in front of mpeg files - use assume format on these
|
||||||
|
$assume_mpeg = eregi('\.mp[123a]$', $file);
|
||||||
|
|
||||||
|
// Extract info with GetAllFileInfo() - in this example we want MD5data (fourth param).
|
||||||
|
// If MD5data is not needed, set to FALSE for performance improvement.
|
||||||
|
$this->info = GetAllFileInfo($file, ($assume_mpeg ? 'mp3' : ''), FALSE, TRUE);
|
||||||
|
//dump($this->info, false);
|
||||||
|
|
||||||
|
// Exit here on error
|
||||||
|
if (isset($this->info['error'])) {
|
||||||
|
return array ('error' => $this->info['error']);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Init wrapper object
|
||||||
|
$this->result = array ();
|
||||||
|
$this->result['format_name'] = @$this->info['fileformat'].'/'.@$this->info['audio']['dataformat'].(isset($this->info['video']['dataformat']) ? '/'.@$this->info['video']['dataformat'] : '');
|
||||||
|
$this->result['encoder_version'] = @$this->info['audio']['encoder'];
|
||||||
|
$this->result['encoder_options'] = NULL;
|
||||||
|
$this->result['bitrate_mode'] = @$this->info['audio']['bitrate_mode'];
|
||||||
|
$this->result['channels'] = @$this->info['audio']['channels'];
|
||||||
|
$this->result['sample_rate'] = @$this->info['audio']['sample_rate'];
|
||||||
|
$this->result['bits_per_sample'] = @$this->info['audio']['bits_per_sample'];
|
||||||
|
$this->result['playing_time'] = @$this->info['playtime_seconds'];
|
||||||
|
$this->result['avg_bit_rate'] = @$this->info['audio']['bitrate'];
|
||||||
|
$this->result['tags'] = @$this->info['tags'];
|
||||||
|
$this->result['comments'] = @$this->info['comments'];
|
||||||
|
$this->result['warning'] = @$this->info['warning'];
|
||||||
|
$this->result['md5'] = @$this->info['md5_data'];
|
||||||
|
|
||||||
|
// Post getID3() data handling based on file format
|
||||||
|
$method = @$this->info['fileformat'].'Info';
|
||||||
|
if (@$this->info['fileformat'] && method_exists($this, $method)) {
|
||||||
|
$this->$method();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* post-getID3() data handling for AAC files.
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
|
||||||
|
function aacInfo() {
|
||||||
|
$this->result['format_name'] = 'AAC';
|
||||||
|
$this->result['encoder_options'] = $this->info['aac']['header_type'].' '.$this->info['aac']['header']['profile_text'];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* post-getID3() data handling for Wave files.
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
|
||||||
|
function riffInfo() {
|
||||||
|
if ($this->info['audio']['dataformat'] == 'wav') {
|
||||||
|
|
||||||
|
$this->result['format_name'] = 'Wave';
|
||||||
|
|
||||||
|
} else if (ereg('^mp[1-3]$', $this->info['audio']['dataformat'])) {
|
||||||
|
|
||||||
|
$this->result['format_name'] = strtoupper($this->info['audio']['dataformat']);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
$this->result['format_name'] = 'riff/'.$this->info['audio']['dataformat'];
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* * post-getID3() data handling for FLAC files.
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
|
||||||
|
function flacInfo() {
|
||||||
|
$this->result['format_name'] = 'FLAC';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* post-getID3() data handling for Monkey's Audio files.
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
|
||||||
|
function macInfo() {
|
||||||
|
$this->result['format_name'] = 'Monkey\'s Audio';
|
||||||
|
$this->result['encoder_options'] = $this->info['monkeys_audio']['compression'].' compression';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* post-getID3() data handling for Monkey's Audio files.
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
|
||||||
|
function laInfo() {
|
||||||
|
$this->result['format_name'] = 'La';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* post-getID3() data handling for Ogg Vorbis files.
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
|
||||||
|
function oggInfo() {
|
||||||
|
if ($this->info['audio']['dataformat'] == 'vorbis') {
|
||||||
|
|
||||||
|
$this->result['format_name'] = 'Ogg Vorbis';
|
||||||
|
$this->result['encoder_options'] = 'Nominal bitrate: '.$this->info['ogg']['bitrate_nominal'];
|
||||||
|
|
||||||
|
} else if ($this->info['audio']['dataformat'] == 'flac') {
|
||||||
|
|
||||||
|
$this->result['format_name'] = 'Ogg FLAC';
|
||||||
|
|
||||||
|
} else if ($this->info['audio']['dataformat'] == 'speex') {
|
||||||
|
|
||||||
|
$this->result['format_name'] = 'Ogg Speex';
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
$this->result['format_name'] = 'Ogg '.$this->info['audio']['dataformat'];
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* post-getID3() data handling for Musepack files.
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
|
||||||
|
function mpcInfo() {
|
||||||
|
$this->result['format_name'] = 'Musepack';
|
||||||
|
$this->result['encoder_options'] = $this->info['mpc']['header']['profile'];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* post-getID3() data handling for MPEG files.
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
|
||||||
|
function mp3Info() {
|
||||||
|
$this->result['format_name'] = 'MP3';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* post-getID3() data handling for MPEG files.
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
|
||||||
|
function mp2Info() {
|
||||||
|
$this->result['format_name'] = 'MP2';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* post-getID3() data handling for MPEG files.
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
|
||||||
|
function mp1Info() {
|
||||||
|
$this->result['format_name'] = 'MP1';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* post-getID3() data handling for WMA files.
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
|
||||||
|
function asfInfo() {
|
||||||
|
$this->result['format_name'] = strtoupper($this->info['audio']['dataformat']);
|
||||||
|
$this->result['encoder_options'] = trim($this->info['asf']['codec_list']['codec_entries'][0]['description_ascii']);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* post-getID3() data handling for Real files.
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
|
||||||
|
function realInfo() {
|
||||||
|
$this->result['format_name'] = 'Real';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* post-getID3() data handling for VQF files.
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
|
||||||
|
function vqfInfo() {
|
||||||
|
$this->result['format_name'] = 'VQF';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
?>
|
507
livesupport/modules/getid3/var/getid3.aac.php
Normal file
507
livesupport/modules/getid3/var/getid3.aac.php
Normal file
|
@ -0,0 +1,507 @@
|
||||||
|
<?php
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
/// getID3() by James Heinrich <getid3@users.sourceforge.net> //
|
||||||
|
// available at http://getid3.sourceforge.net ///
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
// //
|
||||||
|
// getid3.aac.php - part of getID3() //
|
||||||
|
// See getid3.readme.txt for more details //
|
||||||
|
// //
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
function getAACADIFheaderFilepointer(&$fd, &$ThisFileInfo) {
|
||||||
|
$ThisFileInfo['fileformat'] = 'aac';
|
||||||
|
$ThisFileInfo['audio']['dataformat'] = 'aac';
|
||||||
|
|
||||||
|
fseek($fd, $ThisFileInfo['avdataoffset'], SEEK_SET);
|
||||||
|
$AACheader = fread($fd, 1024);
|
||||||
|
$offset = 0;
|
||||||
|
|
||||||
|
if (substr($AACheader, 0, 4) == 'ADIF') {
|
||||||
|
|
||||||
|
// http://faac.sourceforge.net/wiki/index.php?page=ADIF
|
||||||
|
|
||||||
|
// http://libmpeg.org/mpeg4/doc/w2203tfs.pdf
|
||||||
|
// adif_header() {
|
||||||
|
// adif_id 32
|
||||||
|
// copyright_id_present 1
|
||||||
|
// if( copyright_id_present )
|
||||||
|
// copyright_id 72
|
||||||
|
// original_copy 1
|
||||||
|
// home 1
|
||||||
|
// bitstream_type 1
|
||||||
|
// bitrate 23
|
||||||
|
// num_program_config_elements 4
|
||||||
|
// for (i = 0; i < num_program_config_elements + 1; i++ ) {
|
||||||
|
// if( bitstream_type == '0' )
|
||||||
|
// adif_buffer_fullness 20
|
||||||
|
// program_config_element()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
$AACheaderBitstream = BigEndian2Bin($AACheader);
|
||||||
|
$bitoffset = 0;
|
||||||
|
|
||||||
|
$ThisFileInfo['aac']['header_type'] = 'ADIF';
|
||||||
|
$bitoffset += 32;
|
||||||
|
$ThisFileInfo['aac']['header']['mpeg_version'] = 4;
|
||||||
|
|
||||||
|
$ThisFileInfo['aac']['header']['copyright'] = (bool) (substr($AACheaderBitstream, $bitoffset, 1) == '1');
|
||||||
|
$bitoffset += 1;
|
||||||
|
if ($ThisFileInfo['aac']['header']['copyright']) {
|
||||||
|
$ThisFileInfo['aac']['header']['copyright_id'] = Bin2String(substr($AACheaderBitstream, $bitoffset, 72));
|
||||||
|
$bitoffset += 72;
|
||||||
|
}
|
||||||
|
$ThisFileInfo['aac']['header']['original_copy'] = (bool) (substr($AACheaderBitstream, $bitoffset, 1) == '1');
|
||||||
|
$bitoffset += 1;
|
||||||
|
$ThisFileInfo['aac']['header']['home'] = (bool) (substr($AACheaderBitstream, $bitoffset, 1) == '1');
|
||||||
|
$bitoffset += 1;
|
||||||
|
$ThisFileInfo['aac']['header']['is_vbr'] = (bool) (substr($AACheaderBitstream, $bitoffset, 1) == '1');
|
||||||
|
$bitoffset += 1;
|
||||||
|
if ($ThisFileInfo['aac']['header']['is_vbr']) {
|
||||||
|
$ThisFileInfo['audio']['bitrate_mode'] = 'vbr';
|
||||||
|
$ThisFileInfo['aac']['header']['bitrate_max'] = Bin2Dec(substr($AACheaderBitstream, $bitoffset, 23));
|
||||||
|
$bitoffset += 23;
|
||||||
|
} else {
|
||||||
|
$ThisFileInfo['audio']['bitrate_mode'] = 'cbr';
|
||||||
|
$ThisFileInfo['aac']['header']['bitrate'] = Bin2Dec(substr($AACheaderBitstream, $bitoffset, 23));
|
||||||
|
$bitoffset += 23;
|
||||||
|
$ThisFileInfo['audio']['bitrate'] = $ThisFileInfo['aac']['header']['bitrate'];
|
||||||
|
}
|
||||||
|
if ($ThisFileInfo['audio']['bitrate'] == 0) {
|
||||||
|
$ThisFileInfo['error'] .= "\n".'Corrupt AAC file: bitrate_audio == zero';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$ThisFileInfo['aac']['header']['num_program_configs'] = 1 + Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4));
|
||||||
|
$bitoffset += 4;
|
||||||
|
|
||||||
|
for ($i = 0; $i < $ThisFileInfo['aac']['header']['num_program_configs']; $i++) {
|
||||||
|
// http://www.audiocoding.com/wiki/index.php?page=program_config_element
|
||||||
|
|
||||||
|
// buffer_fullness 20
|
||||||
|
|
||||||
|
// element_instance_tag 4
|
||||||
|
// object_type 2
|
||||||
|
// sampling_frequency_index 4
|
||||||
|
// num_front_channel_elements 4
|
||||||
|
// num_side_channel_elements 4
|
||||||
|
// num_back_channel_elements 4
|
||||||
|
// num_lfe_channel_elements 2
|
||||||
|
// num_assoc_data_elements 3
|
||||||
|
// num_valid_cc_elements 4
|
||||||
|
// mono_mixdown_present 1
|
||||||
|
// mono_mixdown_element_number 4 if mono_mixdown_present == 1
|
||||||
|
// stereo_mixdown_present 1
|
||||||
|
// stereo_mixdown_element_number 4 if stereo_mixdown_present == 1
|
||||||
|
// matrix_mixdown_idx_present 1
|
||||||
|
// matrix_mixdown_idx 2 if matrix_mixdown_idx_present == 1
|
||||||
|
// pseudo_surround_enable 1 if matrix_mixdown_idx_present == 1
|
||||||
|
// for (i = 0; i < num_front_channel_elements; i++) {
|
||||||
|
// front_element_is_cpe[i] 1
|
||||||
|
// front_element_tag_select[i] 4
|
||||||
|
// }
|
||||||
|
// for (i = 0; i < num_side_channel_elements; i++) {
|
||||||
|
// side_element_is_cpe[i] 1
|
||||||
|
// side_element_tag_select[i] 4
|
||||||
|
// }
|
||||||
|
// for (i = 0; i < num_back_channel_elements; i++) {
|
||||||
|
// back_element_is_cpe[i] 1
|
||||||
|
// back_element_tag_select[i] 4
|
||||||
|
// }
|
||||||
|
// for (i = 0; i < num_lfe_channel_elements; i++) {
|
||||||
|
// lfe_element_tag_select[i] 4
|
||||||
|
// }
|
||||||
|
// for (i = 0; i < num_assoc_data_elements; i++) {
|
||||||
|
// assoc_data_element_tag_select[i] 4
|
||||||
|
// }
|
||||||
|
// for (i = 0; i < num_valid_cc_elements; i++) {
|
||||||
|
// cc_element_is_ind_sw[i] 1
|
||||||
|
// valid_cc_element_tag_select[i] 4
|
||||||
|
// }
|
||||||
|
// byte_alignment() VAR
|
||||||
|
// comment_field_bytes 8
|
||||||
|
// for (i = 0; i < comment_field_bytes; i++) {
|
||||||
|
// comment_field_data[i] 8
|
||||||
|
// }
|
||||||
|
|
||||||
|
if (!$ThisFileInfo['aac']['header']['is_vbr']) {
|
||||||
|
$ThisFileInfo['aac']['program_configs'][$i]['buffer_fullness'] = Bin2Dec(substr($AACheaderBitstream, $bitoffset, 20));
|
||||||
|
$bitoffset += 20;
|
||||||
|
}
|
||||||
|
$ThisFileInfo['aac']['program_configs'][$i]['element_instance_tag'] = Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4));
|
||||||
|
$bitoffset += 4;
|
||||||
|
$ThisFileInfo['aac']['program_configs'][$i]['object_type'] = Bin2Dec(substr($AACheaderBitstream, $bitoffset, 2));
|
||||||
|
$bitoffset += 2;
|
||||||
|
$ThisFileInfo['aac']['program_configs'][$i]['sampling_frequency_index'] = Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4));
|
||||||
|
$bitoffset += 4;
|
||||||
|
$ThisFileInfo['aac']['program_configs'][$i]['num_front_channel_elements'] = Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4));
|
||||||
|
$bitoffset += 4;
|
||||||
|
$ThisFileInfo['aac']['program_configs'][$i]['num_side_channel_elements'] = Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4));
|
||||||
|
$bitoffset += 4;
|
||||||
|
$ThisFileInfo['aac']['program_configs'][$i]['num_back_channel_elements'] = Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4));
|
||||||
|
$bitoffset += 4;
|
||||||
|
$ThisFileInfo['aac']['program_configs'][$i]['num_lfe_channel_elements'] = Bin2Dec(substr($AACheaderBitstream, $bitoffset, 2));
|
||||||
|
$bitoffset += 2;
|
||||||
|
$ThisFileInfo['aac']['program_configs'][$i]['num_assoc_data_elements'] = Bin2Dec(substr($AACheaderBitstream, $bitoffset, 3));
|
||||||
|
$bitoffset += 3;
|
||||||
|
$ThisFileInfo['aac']['program_configs'][$i]['num_valid_cc_elements'] = Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4));
|
||||||
|
$bitoffset += 4;
|
||||||
|
$ThisFileInfo['aac']['program_configs'][$i]['mono_mixdown_present'] = (bool) Bin2Dec(substr($AACheaderBitstream, $bitoffset, 1));
|
||||||
|
$bitoffset += 1;
|
||||||
|
if ($ThisFileInfo['aac']['program_configs'][$i]['mono_mixdown_present']) {
|
||||||
|
$ThisFileInfo['aac']['program_configs'][$i]['mono_mixdown_element_number'] = Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4));
|
||||||
|
$bitoffset += 4;
|
||||||
|
}
|
||||||
|
$ThisFileInfo['aac']['program_configs'][$i]['stereo_mixdown_present'] = (bool) Bin2Dec(substr($AACheaderBitstream, $bitoffset, 1));
|
||||||
|
$bitoffset += 1;
|
||||||
|
if ($ThisFileInfo['aac']['program_configs'][$i]['stereo_mixdown_present']) {
|
||||||
|
$ThisFileInfo['aac']['program_configs'][$i]['stereo_mixdown_element_number'] = Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4));
|
||||||
|
$bitoffset += 4;
|
||||||
|
}
|
||||||
|
$ThisFileInfo['aac']['program_configs'][$i]['matrix_mixdown_idx_present'] = (bool) Bin2Dec(substr($AACheaderBitstream, $bitoffset, 1));
|
||||||
|
$bitoffset += 1;
|
||||||
|
if ($ThisFileInfo['aac']['program_configs'][$i]['matrix_mixdown_idx_present']) {
|
||||||
|
$ThisFileInfo['aac']['program_configs'][$i]['matrix_mixdown_idx'] = Bin2Dec(substr($AACheaderBitstream, $bitoffset, 2));
|
||||||
|
$bitoffset += 2;
|
||||||
|
$ThisFileInfo['aac']['program_configs'][$i]['pseudo_surround_enable'] = (bool) Bin2Dec(substr($AACheaderBitstream, $bitoffset, 1));
|
||||||
|
$bitoffset += 1;
|
||||||
|
}
|
||||||
|
for ($j = 0; $j < $ThisFileInfo['aac']['program_configs'][$i]['num_front_channel_elements']; $j++) {
|
||||||
|
$ThisFileInfo['aac']['program_configs'][$i]['front_element_is_cpe'][$j] = (bool) Bin2Dec(substr($AACheaderBitstream, $bitoffset, 1));
|
||||||
|
$bitoffset += 1;
|
||||||
|
$ThisFileInfo['aac']['program_configs'][$i]['front_element_tag_select'][$j] = Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4));
|
||||||
|
$bitoffset += 4;
|
||||||
|
}
|
||||||
|
for ($j = 0; $j < $ThisFileInfo['aac']['program_configs'][$i]['num_side_channel_elements']; $j++) {
|
||||||
|
$ThisFileInfo['aac']['program_configs'][$i]['side_element_is_cpe'][$j] = (bool) Bin2Dec(substr($AACheaderBitstream, $bitoffset, 1));
|
||||||
|
$bitoffset += 1;
|
||||||
|
$ThisFileInfo['aac']['program_configs'][$i]['side_element_tag_select'][$j] = Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4));
|
||||||
|
$bitoffset += 4;
|
||||||
|
}
|
||||||
|
for ($j = 0; $j < $ThisFileInfo['aac']['program_configs'][$i]['num_back_channel_elements']; $j++) {
|
||||||
|
$ThisFileInfo['aac']['program_configs'][$i]['back_element_is_cpe'][$j] = (bool) Bin2Dec(substr($AACheaderBitstream, $bitoffset, 1));
|
||||||
|
$bitoffset += 1;
|
||||||
|
$ThisFileInfo['aac']['program_configs'][$i]['back_element_tag_select'][$j] = Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4));
|
||||||
|
$bitoffset += 4;
|
||||||
|
}
|
||||||
|
for ($j = 0; $j < $ThisFileInfo['aac']['program_configs'][$i]['num_lfe_channel_elements']; $j++) {
|
||||||
|
$ThisFileInfo['aac']['program_configs'][$i]['lfe_element_tag_select'][$j] = Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4));
|
||||||
|
$bitoffset += 4;
|
||||||
|
}
|
||||||
|
for ($j = 0; $j < $ThisFileInfo['aac']['program_configs'][$i]['num_assoc_data_elements']; $j++) {
|
||||||
|
$ThisFileInfo['aac']['program_configs'][$i]['assoc_data_element_tag_select'][$j] = Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4));
|
||||||
|
$bitoffset += 4;
|
||||||
|
}
|
||||||
|
for ($j = 0; $j < $ThisFileInfo['aac']['program_configs'][$i]['num_valid_cc_elements']; $j++) {
|
||||||
|
$ThisFileInfo['aac']['program_configs'][$i]['cc_element_is_ind_sw'][$j] = (bool) Bin2Dec(substr($AACheaderBitstream, $bitoffset, 1));
|
||||||
|
$bitoffset += 1;
|
||||||
|
$ThisFileInfo['aac']['program_configs'][$i]['valid_cc_element_tag_select'][$j] = Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4));
|
||||||
|
$bitoffset += 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
$bitoffset = ceil($bitoffset / 8) * 8;
|
||||||
|
|
||||||
|
$ThisFileInfo['aac']['program_configs'][$i]['comment_field_bytes'] = Bin2Dec(substr($AACheaderBitstream, $bitoffset, 8));
|
||||||
|
$bitoffset += 8;
|
||||||
|
$ThisFileInfo['aac']['program_configs'][$i]['comment_field'] = Bin2String(substr($AACheaderBitstream, $bitoffset, 8 * $ThisFileInfo['aac']['program_configs'][$i]['comment_field_bytes']));
|
||||||
|
$bitoffset += 8 * $ThisFileInfo['aac']['program_configs'][$i]['comment_field_bytes'];
|
||||||
|
|
||||||
|
|
||||||
|
$ThisFileInfo['aac']['header']['profile_text'] = AACprofileLookup($ThisFileInfo['aac']['program_configs'][$i]['object_type'], $ThisFileInfo['aac']['header']['mpeg_version']);
|
||||||
|
$ThisFileInfo['aac']['program_configs'][$i]['sampling_frequency'] = AACsampleRateLookup($ThisFileInfo['aac']['program_configs'][$i]['sampling_frequency_index']);
|
||||||
|
$ThisFileInfo['audio']['sample_rate'] = $ThisFileInfo['aac']['program_configs'][$i]['sampling_frequency'];
|
||||||
|
$ThisFileInfo['audio']['channels'] = AACchannelCountCalculate($ThisFileInfo['aac']['program_configs'][$i]);
|
||||||
|
if ($ThisFileInfo['aac']['program_configs'][$i]['comment_field']) {
|
||||||
|
$ThisFileInfo['comments']['comment'][] = $ThisFileInfo['aac']['program_configs'][$i]['comment_field'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$ThisFileInfo['playtime_seconds'] = (($ThisFileInfo['avdataend'] - $ThisFileInfo['avdataoffset']) * 8) / $ThisFileInfo['audio']['bitrate'];
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
unset($ThisFileInfo['fileformat']);
|
||||||
|
unset($ThisFileInfo['aac']);
|
||||||
|
$ThisFileInfo['error'] .= "\n".'AAC-ADIF synch not found (expected "ADIF", found "'.substr($AACheader, 0, 4).'" instead)';
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function getAACADTSheaderFilepointer(&$fd, &$ThisFileInfo, $MaxFramesToScan=1000000, $ReturnExtendedInfo=false) {
|
||||||
|
// based loosely on code from AACfile by Jurgen Faul
|
||||||
|
// jfaul@gmx.de http://jfaul.de/atl
|
||||||
|
|
||||||
|
|
||||||
|
// http://faac.sourceforge.net/wiki/index.php?page=ADTS
|
||||||
|
|
||||||
|
// * ADTS Fixed Header: these don't change from frame to frame
|
||||||
|
// syncword 12 always: '111111111111'
|
||||||
|
// ID 1 0: MPEG-4, 1: MPEG-2
|
||||||
|
// layer 2 always: '00'
|
||||||
|
// protection_absent 1
|
||||||
|
// profile 2
|
||||||
|
// sampling_frequency_index 4
|
||||||
|
// private_bit 1
|
||||||
|
// channel_configuration 3
|
||||||
|
// original/copy 1
|
||||||
|
// home 1
|
||||||
|
// emphasis 2 only if ID == 0 (ie MPEG-4)
|
||||||
|
|
||||||
|
// * ADTS Variable Header: these can change from frame to frame
|
||||||
|
// copyright_identification_bit 1
|
||||||
|
// copyright_identification_start 1
|
||||||
|
// aac_frame_length 13 length of the frame including header (in bytes)
|
||||||
|
// adts_buffer_fullness 11 0x7FF indicates VBR
|
||||||
|
// no_raw_data_blocks_in_frame 2
|
||||||
|
|
||||||
|
// * ADTS Error check
|
||||||
|
// crc_check 16 only if protection_absent == 0
|
||||||
|
|
||||||
|
$byteoffset = 0;
|
||||||
|
$framenumber = 0;
|
||||||
|
|
||||||
|
// Init bit pattern array
|
||||||
|
static $decbin = array();
|
||||||
|
|
||||||
|
// Populate $bindec
|
||||||
|
for ($i = 0; $i < 256; $i++) {
|
||||||
|
$decbin[chr($i)] = str_pad(decbin($i), 8, '0', STR_PAD_LEFT);
|
||||||
|
}
|
||||||
|
|
||||||
|
// used to calculate bitrate below
|
||||||
|
static $BitrateCache = array();
|
||||||
|
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
// breaks out when end-of-file encountered, or invalid data found,
|
||||||
|
// or MaxFramesToScan frames have been scanned
|
||||||
|
|
||||||
|
fseek($fd, $byteoffset, SEEK_SET);
|
||||||
|
|
||||||
|
// First get substring
|
||||||
|
$substring = fread($fd, 10);
|
||||||
|
$substringlength = strlen($substring);
|
||||||
|
if ($substringlength != 10) {
|
||||||
|
$ThisFileInfo['error'] .= "\n".'Failed to read 10 bytes at offset '.(ftell($fd) - $substringlength).' (only read '.$substringlength.' bytes)';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialise $AACheaderBitstream
|
||||||
|
$AACheaderBitstream = '';
|
||||||
|
|
||||||
|
// Loop thru substring chars
|
||||||
|
for ($i = 0; $i < 10; $i++) {
|
||||||
|
$AACheaderBitstream .= $decbin[$substring{$i}];
|
||||||
|
}
|
||||||
|
|
||||||
|
$bitoffset = 0;
|
||||||
|
|
||||||
|
$synctest = bindec(substr($AACheaderBitstream, $bitoffset, 12));
|
||||||
|
|
||||||
|
$bitoffset += 12;
|
||||||
|
if ($synctest != 0x0FFF) {
|
||||||
|
$ThisFileInfo['error'] .= "\n".'Synch pattern (0x0FFF) not found at offset '.(ftell($fd) - 10).' (found 0x0'.strtoupper(dechex($synctest)).' instead)';
|
||||||
|
if ($ThisFileInfo['fileformat'] == 'aac') {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gather info for first frame only - this takes time to do 1000 times!
|
||||||
|
if ($framenumber > 0) {
|
||||||
|
|
||||||
|
if (!$AACheaderBitstream[$bitoffset]) {
|
||||||
|
|
||||||
|
// MPEG-4
|
||||||
|
$bitoffset += 20;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// MPEG-2
|
||||||
|
$bitoffset += 18;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
$ThisFileInfo['aac']['header_type'] = 'ADTS';
|
||||||
|
$ThisFileInfo['aac']['header']['synch'] = $synctest;
|
||||||
|
$ThisFileInfo['fileformat'] = 'aac';
|
||||||
|
$ThisFileInfo['audio']['dataformat'] = 'aac';
|
||||||
|
|
||||||
|
$ThisFileInfo['aac']['header']['mpeg_version'] = ((substr($AACheaderBitstream, $bitoffset, 1) == '0') ? 4 : 2);
|
||||||
|
$bitoffset += 1;
|
||||||
|
$ThisFileInfo['aac']['header']['layer'] = Bin2Dec(substr($AACheaderBitstream, $bitoffset, 2));
|
||||||
|
$bitoffset += 2;
|
||||||
|
if ($ThisFileInfo['aac']['header']['layer'] != 0) {
|
||||||
|
$ThisFileInfo['error'] .= "\n".'Layer error - expected 0x00, found 0x'.dechex($ThisFileInfo['aac']['header']['layer']).' instead';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$ThisFileInfo['aac']['header']['crc_present'] = ((substr($AACheaderBitstream, $bitoffset, 1) == '0') ? true : false);
|
||||||
|
$bitoffset += 1;
|
||||||
|
$ThisFileInfo['aac']['header']['profile_id'] = Bin2Dec(substr($AACheaderBitstream, $bitoffset, 2));
|
||||||
|
$bitoffset += 2;
|
||||||
|
$ThisFileInfo['aac']['header']['profile_text'] = AACprofileLookup($ThisFileInfo['aac']['header']['profile_id'], $ThisFileInfo['aac']['header']['mpeg_version']);
|
||||||
|
|
||||||
|
$ThisFileInfo['aac']['header']['sample_frequency_index'] = Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4));
|
||||||
|
$bitoffset += 4;
|
||||||
|
$ThisFileInfo['aac']['header']['sample_frequency'] = AACsampleRateLookup($ThisFileInfo['aac']['header']['sample_frequency_index']);
|
||||||
|
if ($ThisFileInfo['aac']['header']['sample_frequency'] == 0) {
|
||||||
|
$ThisFileInfo['error'] .= "\n".'Corrupt AAC file: sample_frequency == zero';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$ThisFileInfo['audio']['sample_rate'] = $ThisFileInfo['aac']['header']['sample_frequency'];
|
||||||
|
|
||||||
|
$ThisFileInfo['aac']['header']['private'] = (bool) Bin2Dec(substr($AACheaderBitstream, $bitoffset, 1));
|
||||||
|
$bitoffset += 1;
|
||||||
|
$ThisFileInfo['aac']['header']['channel_configuration'] = Bin2Dec(substr($AACheaderBitstream, $bitoffset, 3));
|
||||||
|
$bitoffset += 3;
|
||||||
|
$ThisFileInfo['audio']['channels'] = $ThisFileInfo['aac']['header']['channel_configuration'];
|
||||||
|
$ThisFileInfo['aac']['header']['original'] = (bool) Bin2Dec(substr($AACheaderBitstream, $bitoffset, 1));
|
||||||
|
$bitoffset += 1;
|
||||||
|
$ThisFileInfo['aac']['header']['home'] = (bool) Bin2Dec(substr($AACheaderBitstream, $bitoffset, 1));
|
||||||
|
$bitoffset += 1;
|
||||||
|
|
||||||
|
if ($ThisFileInfo['aac']['header']['mpeg_version'] == 4) {
|
||||||
|
$ThisFileInfo['aac']['header']['emphasis'] = Bin2Dec(substr($AACheaderBitstream, $bitoffset, 2));
|
||||||
|
$bitoffset += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($ReturnExtendedInfo) {
|
||||||
|
|
||||||
|
$ThisFileInfo['aac'][$framenumber]['copyright_id_bit'] = (bool) Bin2Dec(substr($AACheaderBitstream, $bitoffset, 1));
|
||||||
|
$bitoffset += 1;
|
||||||
|
$ThisFileInfo['aac'][$framenumber]['copyright_id_start'] = (bool) Bin2Dec(substr($AACheaderBitstream, $bitoffset, 1));
|
||||||
|
$bitoffset += 1;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
$bitoffset += 2;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
$FrameLength = bindec(substr($AACheaderBitstream, $bitoffset, 13));
|
||||||
|
|
||||||
|
if (!isset($BitrateCache[$FrameLength])) {
|
||||||
|
$BitrateCache[$FrameLength] = ($ThisFileInfo['aac']['header']['sample_frequency'] / 1024) * $FrameLength * 8;
|
||||||
|
}
|
||||||
|
safe_inc($ThisFileInfo['aac']['bitrate_distribution'][$BitrateCache[$FrameLength]]);
|
||||||
|
|
||||||
|
$ThisFileInfo['aac'][$framenumber]['aac_frame_length'] = $FrameLength;
|
||||||
|
$bitoffset += 13;
|
||||||
|
$ThisFileInfo['aac'][$framenumber]['adts_buffer_fullness'] = bindec(substr($AACheaderBitstream, $bitoffset, 11));
|
||||||
|
$bitoffset += 11;
|
||||||
|
if ($ThisFileInfo['aac'][$framenumber]['adts_buffer_fullness'] == 0x07FF) {
|
||||||
|
$ThisFileInfo['audio']['bitrate_mode'] = 'vbr';
|
||||||
|
} else {
|
||||||
|
$ThisFileInfo['audio']['bitrate_mode'] = 'cbr';
|
||||||
|
}
|
||||||
|
$ThisFileInfo['aac'][$framenumber]['num_raw_data_blocks'] = bindec(substr($AACheaderBitstream, $bitoffset, 2));
|
||||||
|
$bitoffset += 2;
|
||||||
|
|
||||||
|
if ($ThisFileInfo['aac']['header']['crc_present']) {
|
||||||
|
//$ThisFileInfo['aac'][$framenumber]['crc'] = bindec(substr($AACheaderBitstream, $bitoffset, 16));
|
||||||
|
$bitoffset += 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$ReturnExtendedInfo) {
|
||||||
|
unset($ThisFileInfo['aac'][$framenumber]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$byteoffset += $FrameLength;
|
||||||
|
if ((++$framenumber < $MaxFramesToScan) && (($byteoffset + 10) < $ThisFileInfo['avdataend'])) {
|
||||||
|
|
||||||
|
// keep scanning
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
$ThisFileInfo['aac']['frames'] = $framenumber;
|
||||||
|
$ThisFileInfo['playtime_seconds'] = ($ThisFileInfo['avdataend'] / $byteoffset) * (($framenumber * 1024) / $ThisFileInfo['aac']['header']['sample_frequency']); // (1 / % of file scanned) * (samples / (samples/sec)) = seconds
|
||||||
|
if ($ThisFileInfo['playtime_seconds'] == 0) {
|
||||||
|
$ThisFileInfo['error'] .= "\n".'Corrupt AAC file: playtime_seconds == zero';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$ThisFileInfo['audio']['bitrate'] = (($ThisFileInfo['avdataend'] - $ThisFileInfo['avdataoffset']) * 8) / $ThisFileInfo['playtime_seconds'];
|
||||||
|
ksort($ThisFileInfo['aac']['bitrate_distribution']);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// should never get here.
|
||||||
|
}
|
||||||
|
|
||||||
|
function AACsampleRateLookup($samplerateid) {
|
||||||
|
static $AACsampleRateLookup = array();
|
||||||
|
if (empty($AACsampleRateLookup)) {
|
||||||
|
$AACsampleRateLookup[0] = 96000;
|
||||||
|
$AACsampleRateLookup[1] = 88200;
|
||||||
|
$AACsampleRateLookup[2] = 64000;
|
||||||
|
$AACsampleRateLookup[3] = 48000;
|
||||||
|
$AACsampleRateLookup[4] = 44100;
|
||||||
|
$AACsampleRateLookup[5] = 32000;
|
||||||
|
$AACsampleRateLookup[6] = 24000;
|
||||||
|
$AACsampleRateLookup[7] = 22050;
|
||||||
|
$AACsampleRateLookup[8] = 16000;
|
||||||
|
$AACsampleRateLookup[9] = 12000;
|
||||||
|
$AACsampleRateLookup[10] = 11025;
|
||||||
|
$AACsampleRateLookup[11] = 8000;
|
||||||
|
$AACsampleRateLookup[12] = 0;
|
||||||
|
$AACsampleRateLookup[13] = 0;
|
||||||
|
$AACsampleRateLookup[14] = 0;
|
||||||
|
$AACsampleRateLookup[15] = 0;
|
||||||
|
}
|
||||||
|
return (isset($AACsampleRateLookup[$samplerateid]) ? $AACsampleRateLookup[$samplerateid] : 'invalid');
|
||||||
|
}
|
||||||
|
|
||||||
|
function AACprofileLookup($profileid, $mpegversion) {
|
||||||
|
static $AACprofileLookup = array();
|
||||||
|
if (empty($AACprofileLookup)) {
|
||||||
|
$AACprofileLookup[2][0] = 'Main profile';
|
||||||
|
$AACprofileLookup[2][1] = 'Low Complexity profile (LC)';
|
||||||
|
$AACprofileLookup[2][2] = 'Scalable Sample Rate profile (SSR)';
|
||||||
|
$AACprofileLookup[2][3] = '(reserved)';
|
||||||
|
$AACprofileLookup[4][0] = 'AAC_MAIN';
|
||||||
|
$AACprofileLookup[4][1] = 'AAC_LC';
|
||||||
|
$AACprofileLookup[4][2] = 'AAC_SSR';
|
||||||
|
$AACprofileLookup[4][3] = 'AAC_LTP';
|
||||||
|
}
|
||||||
|
return (isset($AACprofileLookup[$mpegversion][$profileid]) ? $AACprofileLookup[$mpegversion][$profileid] : 'invalid');
|
||||||
|
}
|
||||||
|
|
||||||
|
function AACchannelCountCalculate($program_configs) {
|
||||||
|
$channels = 0;
|
||||||
|
for ($i = 0; $i < $program_configs['num_front_channel_elements']; $i++) {
|
||||||
|
$channels++;
|
||||||
|
if ($program_configs['front_element_is_cpe'][$i]) {
|
||||||
|
// each front element is channel pair (CPE = Channel Pair Element)
|
||||||
|
$channels++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for ($i = 0; $i < $program_configs['num_side_channel_elements']; $i++) {
|
||||||
|
$channels++;
|
||||||
|
if ($program_configs['side_element_is_cpe'][$i]) {
|
||||||
|
// each side element is channel pair (CPE = Channel Pair Element)
|
||||||
|
$channels++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for ($i = 0; $i < $program_configs['num_back_channel_elements']; $i++) {
|
||||||
|
$channels++;
|
||||||
|
if ($program_configs['back_element_is_cpe'][$i]) {
|
||||||
|
// each back element is channel pair (CPE = Channel Pair Element)
|
||||||
|
$channels++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for ($i = 0; $i < $program_configs['num_lfe_channel_elements']; $i++) {
|
||||||
|
$channels++;
|
||||||
|
}
|
||||||
|
return $channels;
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
188
livesupport/modules/getid3/var/getid3.ape.php
Normal file
188
livesupport/modules/getid3/var/getid3.ape.php
Normal file
|
@ -0,0 +1,188 @@
|
||||||
|
<?php
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
/// getID3() by James Heinrich <getid3@users.sourceforge.net> //
|
||||||
|
// available at http://getid3.sourceforge.net ///
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
// //
|
||||||
|
// getid3.ape.php - part of getID3() //
|
||||||
|
// See getid3.readme.txt for more details //
|
||||||
|
// //
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
function getAPEtagFilepointer(&$fd, &$ThisFileInfo) {
|
||||||
|
$id3v1tagsize = 128;
|
||||||
|
$apetagheadersize = 32;
|
||||||
|
fseek($fd, 0 - $id3v1tagsize - $apetagheadersize, SEEK_END);
|
||||||
|
$APEfooterID3v1 = fread($fd, $id3v1tagsize + $apetagheadersize);
|
||||||
|
if (substr($APEfooterID3v1, 0, strlen('APETAGEX')) == 'APETAGEX') {
|
||||||
|
|
||||||
|
// APE tag found before ID3v1
|
||||||
|
$APEfooterData = substr($APEfooterID3v1, 0, $apetagheadersize);
|
||||||
|
$APEfooterOffset = 0 - $apetagheadersize - $id3v1tagsize;
|
||||||
|
|
||||||
|
} elseif (substr($APEfooterID3v1, $id3v1tagsize, strlen('APETAGEX')) == 'APETAGEX') {
|
||||||
|
|
||||||
|
// APE tag found, no ID3v1
|
||||||
|
$APEfooterData = substr($APEfooterID3v1, $id3v1tagsize, $apetagheadersize);
|
||||||
|
$APEfooterOffset = 0 - $apetagheadersize;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// APE tag not found
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($ThisFileInfo['fileformat'])) {
|
||||||
|
$ThisFileInfo['fileformat'] = 'ape';
|
||||||
|
}
|
||||||
|
$ThisFileInfo['ape']['footer'] = parseAPEheaderFooter($APEfooterData);
|
||||||
|
|
||||||
|
if (isset($ThisFileInfo['ape']['footer']['flags']['header']) && $ThisFileInfo['ape']['footer']['flags']['header']) {
|
||||||
|
fseek($fd, $APEfooterOffset - $ThisFileInfo['ape']['footer']['raw']['tagsize'] + $apetagheadersize - $apetagheadersize, SEEK_END);
|
||||||
|
$APEtagData = fread($fd, $ThisFileInfo['ape']['footer']['raw']['tagsize'] + $apetagheadersize);
|
||||||
|
} else {
|
||||||
|
fseek($fd, $APEfooterOffset - $ThisFileInfo['ape']['footer']['raw']['tagsize'] + $apetagheadersize, SEEK_END);
|
||||||
|
$APEtagData = fread($fd, $ThisFileInfo['ape']['footer']['raw']['tagsize']);
|
||||||
|
}
|
||||||
|
$offset = 0;
|
||||||
|
if (isset($ThisFileInfo['ape']['footer']['flags']['header']) && $ThisFileInfo['ape']['footer']['flags']['header']) {
|
||||||
|
$ThisFileInfo['ape']['header'] = parseAPEheaderFooter(substr($APEtagData, 0, $apetagheadersize));
|
||||||
|
$offset += $apetagheadersize;
|
||||||
|
}
|
||||||
|
|
||||||
|
for ($i = 0; $i < $ThisFileInfo['ape']['footer']['raw']['tag_items']; $i++) {
|
||||||
|
$value_size = LittleEndian2Int(substr($APEtagData, $offset, 4));
|
||||||
|
$offset += 4;
|
||||||
|
$item_flags = LittleEndian2Int(substr($APEtagData, $offset, 4));
|
||||||
|
$offset += 4;
|
||||||
|
$ItemKeyLength = strpos($APEtagData, chr(0), $offset) - $offset;
|
||||||
|
$item_key = strtolower(substr($APEtagData, $offset, $ItemKeyLength));
|
||||||
|
$offset += $ItemKeyLength + 1; // skip 0x00 terminator
|
||||||
|
$data = substr($APEtagData, $offset, $value_size);
|
||||||
|
$offset += $value_size;
|
||||||
|
|
||||||
|
$ThisFileInfo['ape']['items']["$item_key"]['raw']['value_size'] = $value_size;
|
||||||
|
$ThisFileInfo['ape']['items']["$item_key"]['raw']['item_flags'] = $item_flags;
|
||||||
|
if ($ThisFileInfo['ape']['footer']['tag_version'] >= 2) {
|
||||||
|
$ThisFileInfo['ape']['items']["$item_key"]['flags'] = parseAPEtagFlags($item_flags);
|
||||||
|
}
|
||||||
|
$ThisFileInfo['ape']['items']["$item_key"]['data'] = $data;
|
||||||
|
$ThisFileInfo['ape']['items']["$item_key"]['data_ascii'] = $data;
|
||||||
|
if (APEtagItemIsUTF8Lookup($item_key)) {
|
||||||
|
$ThisFileInfo['ape']['items']["$item_key"]['data_ascii'] = RoughTranslateUnicodeToASCII($ThisFileInfo['ape']['items']["$item_key"]['data'], 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ($item_key) {
|
||||||
|
case 'replaygain_track_gain':
|
||||||
|
$ThisFileInfo['replay_gain']['radio']['adjustment'] = (float) $ThisFileInfo['ape']['items']["$item_key"]['data_ascii'];
|
||||||
|
$ThisFileInfo['replay_gain']['radio']['originator'] = 'unspecified';
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'replaygain_track_peak':
|
||||||
|
$ThisFileInfo['replay_gain']['radio']['peak'] = (float) $ThisFileInfo['ape']['items']["$item_key"]['data_ascii'];
|
||||||
|
$ThisFileInfo['replay_gain']['radio']['originator'] = 'unspecified';
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'replaygain_album_gain':
|
||||||
|
$ThisFileInfo['replay_gain']['audiophile']['adjustment'] = (float) $ThisFileInfo['ape']['items']["$item_key"]['data_ascii'];
|
||||||
|
$ThisFileInfo['replay_gain']['audiophile']['originator'] = 'unspecified';
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'replaygain_album_peak':
|
||||||
|
$ThisFileInfo['replay_gain']['audiophile']['peak'] = (float) $ThisFileInfo['ape']['items']["$item_key"]['data_ascii'];
|
||||||
|
$ThisFileInfo['replay_gain']['audiophile']['originator'] = 'unspecified';
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'title':
|
||||||
|
case 'artist':
|
||||||
|
case 'album':
|
||||||
|
case 'track':
|
||||||
|
case 'genre':
|
||||||
|
case 'comment':
|
||||||
|
case 'year':
|
||||||
|
$ThisFileInfo['ape']['comments']["$item_key"][] = $ThisFileInfo['ape']['items']["$item_key"]['data_ascii'];
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if (isset($ThisFileInfo['ape']['comments'])) {
|
||||||
|
CopyFormatCommentsToRootComments($ThisFileInfo['ape']['comments'], $ThisFileInfo, true, true, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseAPEheaderFooter($APEheaderFooterData) {
|
||||||
|
// http://www.uni-jena.de/~pfk/mpp/sv8/apeheader.html
|
||||||
|
$headerfooterinfo['raw']['footer_tag'] = substr($APEheaderFooterData, 0, 8);
|
||||||
|
$headerfooterinfo['raw']['version'] = LittleEndian2Int(substr($APEheaderFooterData, 8, 4));
|
||||||
|
$headerfooterinfo['raw']['tagsize'] = LittleEndian2Int(substr($APEheaderFooterData, 12, 4));
|
||||||
|
$headerfooterinfo['raw']['tag_items'] = LittleEndian2Int(substr($APEheaderFooterData, 16, 4));
|
||||||
|
$headerfooterinfo['raw']['global_flags'] = LittleEndian2Int(substr($APEheaderFooterData, 20, 4));
|
||||||
|
$headerfooterinfo['raw']['reserved'] = substr($APEheaderFooterData, 24, 8);
|
||||||
|
|
||||||
|
$headerfooterinfo['tag_version'] = $headerfooterinfo['raw']['version'] / 1000;
|
||||||
|
if ($headerfooterinfo['tag_version'] >= 2) {
|
||||||
|
$headerfooterinfo['flags'] = parseAPEtagFlags($headerfooterinfo['raw']['global_flags']);
|
||||||
|
}
|
||||||
|
return $headerfooterinfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseAPEtagFlags($rawflagint) {
|
||||||
|
// "Note: APE Tags 1.0 do not use any of the APE Tag flags.
|
||||||
|
// All are set to zero on creation and ignored on reading."
|
||||||
|
// http://www.uni-jena.de/~pfk/mpp/sv8/apetagflags.html
|
||||||
|
$flags['header'] = (bool) ($rawflagint & 0x80000000);
|
||||||
|
$flags['footer'] = (bool) ($rawflagint & 0x40000000);
|
||||||
|
$flags['this_is_header'] = (bool) ($rawflagint & 0x20000000);
|
||||||
|
$flags['item_contents_raw'] = ($rawflagint & 0x00000006) >> 1;
|
||||||
|
$flags['item_contents'] = APEcontentTypeFlagLookup($flags['item_contents_raw']);
|
||||||
|
$flags['read_only'] = (bool) ($rawflagint & 0x00000001);
|
||||||
|
|
||||||
|
return $flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
function APEcontentTypeFlagLookup($contenttypeid) {
|
||||||
|
static $APEcontentTypeFlagLookup = array();
|
||||||
|
if (empty($APEcontentTypeFlagLookup)) {
|
||||||
|
$APEcontentTypeFlagLookup[0] = 'utf-8';
|
||||||
|
$APEcontentTypeFlagLookup[1] = 'binary';
|
||||||
|
$APEcontentTypeFlagLookup[2] = 'external';
|
||||||
|
$APEcontentTypeFlagLookup[3] = 'reserved';
|
||||||
|
}
|
||||||
|
return (isset($APEcontentTypeFlagLookup[$contenttypeid]) ? $APEcontentTypeFlagLookup[$contenttypeid] : 'invalid');
|
||||||
|
}
|
||||||
|
|
||||||
|
function APEtagItemIsUTF8Lookup($itemkey) {
|
||||||
|
static $APEtagItemIsUTF8Lookup = array();
|
||||||
|
if (empty($APEtagItemIsUTF8Lookup)) {
|
||||||
|
$APEtagItemIsUTF8Lookup[] = 'Title';
|
||||||
|
$APEtagItemIsUTF8Lookup[] = 'Subtitle';
|
||||||
|
$APEtagItemIsUTF8Lookup[] = 'Artist';
|
||||||
|
$APEtagItemIsUTF8Lookup[] = 'Album';
|
||||||
|
$APEtagItemIsUTF8Lookup[] = 'Debut Album';
|
||||||
|
$APEtagItemIsUTF8Lookup[] = 'Publisher';
|
||||||
|
$APEtagItemIsUTF8Lookup[] = 'Conductor';
|
||||||
|
$APEtagItemIsUTF8Lookup[] = 'Track';
|
||||||
|
$APEtagItemIsUTF8Lookup[] = 'Composer';
|
||||||
|
$APEtagItemIsUTF8Lookup[] = 'Comment';
|
||||||
|
$APEtagItemIsUTF8Lookup[] = 'Copyright';
|
||||||
|
$APEtagItemIsUTF8Lookup[] = 'Publicationright';
|
||||||
|
$APEtagItemIsUTF8Lookup[] = 'File';
|
||||||
|
$APEtagItemIsUTF8Lookup[] = 'Year';
|
||||||
|
$APEtagItemIsUTF8Lookup[] = 'Record Date';
|
||||||
|
$APEtagItemIsUTF8Lookup[] = 'Record Location';
|
||||||
|
$APEtagItemIsUTF8Lookup[] = 'Genre';
|
||||||
|
$APEtagItemIsUTF8Lookup[] = 'Media';
|
||||||
|
$APEtagItemIsUTF8Lookup[] = 'Related';
|
||||||
|
$APEtagItemIsUTF8Lookup[] = 'ISRC';
|
||||||
|
$APEtagItemIsUTF8Lookup[] = 'Abstract';
|
||||||
|
$APEtagItemIsUTF8Lookup[] = 'Language';
|
||||||
|
$APEtagItemIsUTF8Lookup[] = 'Bibliography';
|
||||||
|
}
|
||||||
|
return in_array($itemkey, $APEtagItemIsUTF8Lookup);
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
1375
livesupport/modules/getid3/var/getid3.changelog.txt
Normal file
1375
livesupport/modules/getid3/var/getid3.changelog.txt
Normal file
File diff suppressed because it is too large
Load diff
301
livesupport/modules/getid3/var/getid3.check.php
Normal file
301
livesupport/modules/getid3/var/getid3.check.php
Normal file
|
@ -0,0 +1,301 @@
|
||||||
|
<?php
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
/// getID3() by James Heinrich <getid3@users.sourceforge.net> //
|
||||||
|
// available at http://getid3.sourceforge.net ///
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
// //
|
||||||
|
// getid3.zip.php - part of getID3() //
|
||||||
|
// Sample script for checking remote and local files and //
|
||||||
|
// displaying information returned by getID3() //
|
||||||
|
// See getid3.readme.txt for more details //
|
||||||
|
// //
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
require_once('getid3.php');
|
||||||
|
require_once(GETID3_INCLUDEPATH.'getid3.functions.php'); // Function library
|
||||||
|
|
||||||
|
echo '<HTML><HEAD>';
|
||||||
|
echo '<TITLE>getID3() - getid3.check.php (sample script)</TITLE>';
|
||||||
|
echo '<STYLE>BODY,TD,TH { font-family: sans-serif; font-size: 9pt; }</STYLE>';
|
||||||
|
echo '</HEAD><BODY>';
|
||||||
|
|
||||||
|
if (isset($_REQUEST['deletefile'])) {
|
||||||
|
if (file_exists($_REQUEST['deletefile'])) {
|
||||||
|
if (unlink($_REQUEST['deletefile'])) {
|
||||||
|
echo '<SCRIPT LANGUAGE="JavaScript">alert("Successfully deleted '.addslashes($_REQUEST['deletefile']).'");</SCRIPT>';
|
||||||
|
} else {
|
||||||
|
echo '<SCRIPT LANGUAGE="JavaScript">alert("FAILED to delete '.addslashes($_REQUEST['deletefile']).'");</SCRIPT>';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
echo '<SCRIPT LANGUAGE="JavaScript">alert("'.addslashes($_REQUEST['deletefile']).' does not exist - cannot delete");</SCRIPT>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($_REQUEST['filename'])) {
|
||||||
|
$starttime = getmicrotime();
|
||||||
|
if (isset($_REQUEST['assumeFormat'])) {
|
||||||
|
$ThisFileInfo = GetAllFileInfo($_REQUEST['filename'], $_REQUEST['assumeFormat'], true, (filesize($_REQUEST['filename']) < 52428800)); // auto-get md5_data if filesize < 50MB
|
||||||
|
} else {
|
||||||
|
$ThisFileInfo = GetAllFileInfo($_REQUEST['filename'], '', true, (filesize($_REQUEST['filename']) < 52428800)); // auto-get md5_data if filesize < 50MB
|
||||||
|
if (!isset($ThisFileInfo['fileformat']) || ($ThisFileInfo['fileformat'] == '') || ($ThisFileInfo['fileformat'] == 'id3')) {
|
||||||
|
$formatExtensions = array('mp3'=>'mp3', 'ogg'=>'ogg', 'zip'=>'zip', 'wav'=>'riff', 'avi'=>'riff', 'mid'=>'midi', 'mpg'=>'mpeg', 'jpg'=>'image', 'gif'=>'image', 'png'=>'image');
|
||||||
|
if (isset($formatExtensions[fileextension($_REQUEST['filename'])])) {
|
||||||
|
$ThisFileInfo = GetAllFileInfo($_REQUEST['filename'], $formatExtensions[fileextension($_REQUEST['filename'])], true, (filesize($_REQUEST['filename']) < 52428800)); // auto-get md5_data if filesize < 50MB
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$listdirectory = dirname(SafeStripSlashes($_REQUEST['filename']));
|
||||||
|
$listdirectory = realpath($listdirectory); // get rid of /../../ references
|
||||||
|
|
||||||
|
if (substr(php_uname(), 0, 7) == 'Windows') {
|
||||||
|
// this mostly just gives a consistant look to Windows and *nix filesystems
|
||||||
|
// (windows uses \ as directory seperator, *nix uses /)
|
||||||
|
$listdirectory = str_replace('\\', '/', $listdirectory.'/');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strstr($_REQUEST['filename'], 'http://') || strstr($_REQUEST['filename'], 'ftp://')) {
|
||||||
|
echo '<I>Cannot browse remote filesystems</I><BR>';
|
||||||
|
} else {
|
||||||
|
echo 'Browse: <A HREF="'.$_SERVER['PHP_SELF'].'?listdirectory='.urlencode($listdirectory).'">'.$listdirectory.'</A><BR>';
|
||||||
|
}
|
||||||
|
|
||||||
|
echo 'Parse this file as: ';
|
||||||
|
$allowedFormats = array('zip', 'ogg', 'riff', 'mpeg', 'midi', 'aac', 'mp3');
|
||||||
|
foreach ($allowedFormats as $possibleFormat) {
|
||||||
|
if (isset($_REQUEST['assumeFormat']) && ($_REQUEST['assumeFormat'] == $possibleFormat)) {
|
||||||
|
echo '<B>'.$possibleFormat.'</B> | ';
|
||||||
|
} else {
|
||||||
|
echo '<A HREF="'.$_SERVER['PHP_SELF'].'?filename='.urlencode($_REQUEST['filename']).'&assumeFormat='.$possibleFormat.'">'.$possibleFormat.'</A> | ';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isset($_REQUEST['assumeFormat'])) {
|
||||||
|
echo '<A HREF="'.$_SERVER['PHP_SELF'].'?filename='.urlencode($_REQUEST['filename']).'">default</A><BR>';
|
||||||
|
} else {
|
||||||
|
echo '<B>default</B><BR>';
|
||||||
|
}
|
||||||
|
|
||||||
|
echo table_var_dump($ThisFileInfo);
|
||||||
|
$endtime = getmicrotime();
|
||||||
|
echo 'File parsed in '.number_format($endtime - $starttime, 3).' seconds.<BR>';
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
$listdirectory = (isset($_REQUEST['listdirectory']) ? SafeStripSlashes($_REQUEST['listdirectory']) : '.');
|
||||||
|
$listdirectory = realpath($listdirectory); // get rid of /../../ references
|
||||||
|
$currentfulldir = $listdirectory.'/';
|
||||||
|
|
||||||
|
if (substr(php_uname(), 0, 7) == 'Windows') {
|
||||||
|
// this mostly just gives a consistant look to Windows and *nix filesystems
|
||||||
|
// (windows uses \ as directory seperator, *nix uses /)
|
||||||
|
$currentfulldir = str_replace('\\', '/', $listdirectory.'/');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($handle = @opendir($listdirectory)) {
|
||||||
|
|
||||||
|
echo str_repeat(' ', 300); // IE buffers the first 300 or so chars, making this progressive display useless - fill the buffer with spaces
|
||||||
|
echo 'Processing';
|
||||||
|
|
||||||
|
$starttime = getmicrotime();
|
||||||
|
while ($file = readdir($handle)) {
|
||||||
|
set_time_limit(30); // allocate another 30 seconds to process this file - should go much quicker than this unless intense processing (like bitrate histogram analysis) is enabled
|
||||||
|
echo ' .'; // progress indicator dot
|
||||||
|
flush(); // make sure the dot is shown, otherwise it's useless
|
||||||
|
$currentfilename = $listdirectory.'/'.$file;
|
||||||
|
|
||||||
|
// symbolic-link-resolution enhancements by davidbullock@tech-center.com
|
||||||
|
$TargetObject = realpath($currentfilename); // Find actual file path, resolve if it's a symbolic link
|
||||||
|
$TargetObjectType = filetype($TargetObject); // Check file type without examining extension
|
||||||
|
|
||||||
|
if($TargetObjectType == 'dir') {
|
||||||
|
switch ($file) {
|
||||||
|
case '..':
|
||||||
|
$ParentDir = realpath($file.'/..').'/';
|
||||||
|
if (substr(php_uname(), 0, 7) == 'Windows') {
|
||||||
|
$ParentDir = str_replace('\\', '/', $ParentDir);
|
||||||
|
}
|
||||||
|
$DirectoryContents["$currentfulldir"]['dir']["$file"]['filename'] = $ParentDir;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '.':
|
||||||
|
// ignore
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
$DirectoryContents["$currentfulldir"]['dir']["$file"]['filename'] = $file;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} elseif ($TargetObjectType == 'file') {
|
||||||
|
$fileinformation = GetAllFileInfo($currentfilename, false, isset($_REQUEST['ShowMD5']), isset($_REQUEST['ShowMD5']));
|
||||||
|
|
||||||
|
|
||||||
|
if (empty($fileinformation['fileformat'])) {
|
||||||
|
// auto-detect couldn't find the file format (probably corrupt header?), re-scan based on extension, if applicable
|
||||||
|
$formatExtensions = array('mp3'=>'mp3', 'ogg'=>'ogg', 'zip'=>'zip', 'wav'=>'riff', 'avi'=>'riff', 'mid'=>'midi', 'mpg'=>'mpeg', 'jpg'=>'image', 'gif'=>'image', 'png'=>'image');
|
||||||
|
if (isset($formatExtensions[fileextension($currentfilename)])) {
|
||||||
|
$fileinformation = GetAllFileInfo($currentfilename, $formatExtensions[fileextension($currentfilename)], isset($_REQUEST['ShowMD5']), isset($_REQUEST['ShowMD5']));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (!empty($fileinformation['fileformat'])) {
|
||||||
|
$DirectoryContents["$currentfulldir"]['known']["$file"] = $fileinformation;
|
||||||
|
} else {
|
||||||
|
$DirectoryContents["$currentfulldir"]['other']["$file"] = $fileinformation;
|
||||||
|
$DirectoryContents["$currentfulldir"]['other']["$file"]['playtime_string'] = '-';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$endtime = getmicrotime();
|
||||||
|
closedir($handle);
|
||||||
|
echo 'done<BR>';
|
||||||
|
echo 'Directory scanned in '.number_format($endtime - $starttime, 2).' seconds.<BR>';
|
||||||
|
flush();
|
||||||
|
|
||||||
|
$columnsintable = 13;
|
||||||
|
echo '<TABLE BORDER="1" CELLSPACING="0" CELLPADDING="3">';
|
||||||
|
echo '<TR BGCOLOR="#CCCCDD"><TH COLSPAN="'.$columnsintable.'">Files in '.$currentfulldir.'</TH></TR>';
|
||||||
|
$rowcounter = 0;
|
||||||
|
foreach ($DirectoryContents as $dirname => $val) {
|
||||||
|
if (is_array($DirectoryContents["$dirname"]['dir'])) {
|
||||||
|
uksort($DirectoryContents["$dirname"]['dir'], 'MoreNaturalSort');
|
||||||
|
foreach ($DirectoryContents["$dirname"]['dir'] as $filename => $fileinfo) {
|
||||||
|
echo '<TR BGCOLOR="#'.(($rowcounter++ % 2) ? 'FFCCCC' : 'EEBBBB').'">';
|
||||||
|
if ($filename == '..') {
|
||||||
|
echo '<TD COLSPAN="'.$columnsintable.'">Parent directory: <A HREF="'.$_SERVER['PHP_SELF'].'?listdirectory='.urlencode($dirname.$filename).'"><B>';
|
||||||
|
if (substr(php_uname(), 0, 7) == 'Windows') {
|
||||||
|
echo str_replace('\\', '/', realpath($dirname.$filename));
|
||||||
|
} else {
|
||||||
|
echo realpath($dirname.$filename);
|
||||||
|
}
|
||||||
|
echo '/</B></A></TD>';
|
||||||
|
} else {
|
||||||
|
echo '<TD COLSPAN="'.$columnsintable.'"><A HREF="'.$_SERVER['PHP_SELF'].'?listdirectory='.urlencode($dirname.$filename).'"><B>'.$filename.'</B></A></TD>';
|
||||||
|
}
|
||||||
|
echo '</TR>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
echo '<TR BGCOLOR="#CCCCEE">';
|
||||||
|
echo '<TH>Filename</TH>';
|
||||||
|
echo '<TH>File Size</TH>';
|
||||||
|
echo '<TH>Format</TH>';
|
||||||
|
echo '<TH>Playtime</TH>';
|
||||||
|
echo '<TH>Bitrate</TH>';
|
||||||
|
echo '<TH>Artist</TH>';
|
||||||
|
echo '<TH>Title</TH>';
|
||||||
|
if (isset($_REQUEST['ShowMD5'])) {
|
||||||
|
echo '<TH>MD5 Data (<A HREF="'.$_SERVER['PHP_SELF'].'?listdirectory='.rawurlencode(isset($_REQUEST['listdirectory']) ? $_REQUEST['listdirectory'] : '.').'">disable</A>)</TH>';
|
||||||
|
echo '<TH>MD5 File (<A HREF="'.$_SERVER['PHP_SELF'].'?listdirectory='.rawurlencode(isset($_REQUEST['listdirectory']) ? $_REQUEST['listdirectory'] : '.').'">disable</A>)</TH>';
|
||||||
|
} else {
|
||||||
|
echo '<TH COLSPAN="2">MD5 Data (<A HREF="'.$_SERVER['PHP_SELF'].'?listdirectory='.rawurlencode(isset($_REQUEST['listdirectory']) ? $_REQUEST['listdirectory'] : '.').'&ShowMD5=1">enable</A>)</TH>';
|
||||||
|
}
|
||||||
|
echo '<TH>Tags</TH>';
|
||||||
|
echo '<TH>Errors</TH>';
|
||||||
|
echo '<TH>Edit</TH>';
|
||||||
|
echo '<TH>Delete</TH>';
|
||||||
|
echo '</TR>';
|
||||||
|
if (isset($DirectoryContents["$dirname"]['known']) && is_array($DirectoryContents["$dirname"]['known'])) {
|
||||||
|
uksort($DirectoryContents["$dirname"]['known'], 'MoreNaturalSort');
|
||||||
|
foreach ($DirectoryContents["$dirname"]['known'] as $filename => $fileinfo) {
|
||||||
|
echo '<TR BGCOLOR="#'.(($rowcounter++ % 2) ? 'DDDDDD' : 'EEEEEE').'">';
|
||||||
|
echo '<TD><A HREF="'.$_SERVER['PHP_SELF'].'?filename='.urlencode($dirname.$filename).'" TITLE="View detailed analysis">'.$filename.'</A></TD>';
|
||||||
|
echo '<TD ALIGN="RIGHT"> '.number_format($fileinfo['filesize']).'</TD>';
|
||||||
|
echo '<TD ALIGN="RIGHT"> '.NiceDisplayFiletypeFormat($fileinfo).'</TD>';
|
||||||
|
echo '<TD ALIGN="RIGHT"> '.(isset($fileinfo['playtime_string']) ? $fileinfo['playtime_string'] : '-').'</TD>';
|
||||||
|
echo '<TD ALIGN="RIGHT"> '.(isset($fileinfo['bitrate']) ? BitrateText($fileinfo['bitrate'] / 1000) : '-').'</TD>';
|
||||||
|
echo '<TD ALIGN="LEFT"> '.(isset($fileinfo['comments']['artist']) ? implode("\n", $fileinfo['comments']['artist']) : '').'</TD>';
|
||||||
|
echo '<TD ALIGN="LEFT"> '.(isset($fileinfo['comments']['title']) ? implode("\n", $fileinfo['comments']['title']) : '').'</TD>';
|
||||||
|
if (isset($_REQUEST['ShowMD5'])) {
|
||||||
|
echo '<TD ALIGN="LEFT"><TT>'.(isset($fileinfo['md5_data']) ? $fileinfo['md5_data'] : '').'</TT></TD>';
|
||||||
|
echo '<TD ALIGN="LEFT"><TT>'.(isset($fileinfo['md5_file']) ? $fileinfo['md5_file'] : '').'</TT></TD>';
|
||||||
|
} else {
|
||||||
|
echo '<TD ALIGN="CENTER" COLSPAN="2">-</TD>';
|
||||||
|
}
|
||||||
|
echo '<TD ALIGN="LEFT"> '.implode(', ', $fileinfo['tags']).'</TD>';
|
||||||
|
|
||||||
|
echo '<TD ALIGN="LEFT"> ';
|
||||||
|
if (!empty($fileinfo['warning'])) {
|
||||||
|
echo '<A HREF="javascript:alert(\''.str_replace("\n", '\\n', FixTextFields($fileinfo['warning'])).'\');" TITLE="'.FixTextFields($fileinfo['warning']).'">warning</ACRONYM><BR>';
|
||||||
|
}
|
||||||
|
if (!empty($fileinfo['error'])) {
|
||||||
|
echo '<A HREF="javascript:alert(\''.str_replace("\n", '\\n', FixTextFields($fileinfo['error'])).'\');" TITLE="'.FixTextFields($fileinfo['error']).'">error</ACRONYM><BR>';
|
||||||
|
}
|
||||||
|
echo '</TD>';
|
||||||
|
|
||||||
|
echo '<TD ALIGN="LEFT"> ';
|
||||||
|
if (in_array('id3v1', $fileinfo['tags']) || in_array('id3v2', $fileinfo['tags'])) {
|
||||||
|
echo '<A HREF="getid3.write.php?EditorFilename='.urlencode($dirname.$filename).'" TITLE="Edit ID3 tag">edit ID3';
|
||||||
|
} elseif (in_array('vorbiscomment', $fileinfo['tags'])) {
|
||||||
|
echo '<A HREF="getid3.write.php?EditorFilename='.urlencode($dirname.$filename).'" TITLE="Edit Ogg comment tags">edit tags';
|
||||||
|
}
|
||||||
|
echo '</TD>';
|
||||||
|
echo '<TD ALIGN="LEFT"> <A HREF="'.$_SERVER['PHP_SELF'].'?listdirectory='.urlencode($listdirectory).'&deletefile='.urlencode($dirname.$filename).'" onClick="return confirm(\'Are you sure you want to delete '.addslashes($dirname.$filename).'? \n(this action cannot be un-done)\');" TITLE="Permanently delete '."\n".FixTextFields($filename)."\n".' from'."\n".' '.FixTextFields($dirname).'">delete</A></TD>';
|
||||||
|
echo '</TR>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isset($DirectoryContents["$dirname"]['other']) && is_array($DirectoryContents["$dirname"]['other'])) {
|
||||||
|
uksort($DirectoryContents["$dirname"]['other'], 'MoreNaturalSort');
|
||||||
|
foreach ($DirectoryContents["$dirname"]['other'] as $filename => $fileinfo) {
|
||||||
|
echo '<TR BGCOLOR="#'.(($rowcounter++ % 2) ? 'BBBBDD' : 'CCCCFF').'">';
|
||||||
|
echo '<TD><A HREF="'.$_SERVER['PHP_SELF'].'?filename='.urlencode($dirname.$filename).'"><I>'.$filename.'</I></A></TD>';
|
||||||
|
echo '<TD ALIGN="RIGHT"> '.(isset($fileinfo['filesize']) ? number_format($fileinfo['filesize']) : '-').'</TD>';
|
||||||
|
echo '<TD ALIGN="RIGHT"> '.NiceDisplayFiletypeFormat($fileinfo).'</TD>';
|
||||||
|
echo '<TD ALIGN="RIGHT"> '.(isset($fileinfo['playtime_string']) ? $fileinfo['playtime_string'] : '-').'</TD>';
|
||||||
|
echo '<TD ALIGN="RIGHT"> '.(isset($fileinfo['bitrate']) ? BitrateText($fileinfo['bitrate'] / 1000) : '-').'</TD>';
|
||||||
|
echo '<TD ALIGN="LEFT"> </TD>'; // Artist
|
||||||
|
echo '<TD ALIGN="LEFT"> </TD>'; // Title
|
||||||
|
echo '<TD ALIGN="LEFT" COLSPAN="2"> </TD>'; // MD5_data
|
||||||
|
echo '<TD ALIGN="LEFT"> </TD>'; // Tags
|
||||||
|
echo '<TD ALIGN="LEFT"> </TD>'; // Warning/Error
|
||||||
|
echo '<TD ALIGN="LEFT"> </TD>'; // Edit
|
||||||
|
echo '<TD ALIGN="LEFT"> <A HREF="'.$_SERVER['PHP_SELF'].'?listdirectory='.urlencode($listdirectory).'&deletefile='.urlencode($dirname.$filename).'" onClick="return confirm(\'Are you sure you want to delete '.addslashes($dirname.$filename).'? \n(this action cannot be un-done)\');" TITLE="Permanently delete '.addslashes($dirname.$filename).'">delete</A></TD>';
|
||||||
|
echo '</TR>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
echo '</TABLE>';
|
||||||
|
} else {
|
||||||
|
echo '<B>ERROR: Could not open directory: <U>'.$currentfulldir.'</U></B><BR>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
echo PoweredBygetID3();
|
||||||
|
echo '</BODY></HTML>';
|
||||||
|
|
||||||
|
function NiceDisplayFiletypeFormat(&$fileinfo) {
|
||||||
|
|
||||||
|
if (empty($fileinfo['fileformat'])) {
|
||||||
|
return '-';
|
||||||
|
}
|
||||||
|
|
||||||
|
$output = $fileinfo['fileformat'];
|
||||||
|
if (empty($fileinfo['video']['dataformat']) && empty($fileinfo['audio']['dataformat'])) {
|
||||||
|
return $output; // 'gif'
|
||||||
|
}
|
||||||
|
if (empty($fileinfo['video']['dataformat']) && !empty($fileinfo['audio']['dataformat'])) {
|
||||||
|
if ($fileinfo['fileformat'] == $fileinfo['audio']['dataformat']) {
|
||||||
|
return $output; // 'mp3'
|
||||||
|
}
|
||||||
|
$output .= '.'.$fileinfo['audio']['dataformat']; // 'ogg.flac'
|
||||||
|
return $output;
|
||||||
|
}
|
||||||
|
if (!empty($fileinfo['video']['dataformat']) && empty($fileinfo['audio']['dataformat'])) {
|
||||||
|
if ($fileinfo['fileformat'] == $fileinfo['video']['dataformat']) {
|
||||||
|
return $output; // 'mpeg'
|
||||||
|
}
|
||||||
|
$output .= '.'.$fileinfo['video']['dataformat']; // 'riff.avi'
|
||||||
|
return $output;
|
||||||
|
}
|
||||||
|
if ($fileinfo['video']['dataformat'] == $fileinfo['audio']['dataformat']) {
|
||||||
|
if ($fileinfo['fileformat'] == $fileinfo['video']['dataformat']) {
|
||||||
|
return $output; // 'real'
|
||||||
|
}
|
||||||
|
$output .= '.'.$fileinfo['video']['dataformat']; // any examples?
|
||||||
|
return $output;
|
||||||
|
}
|
||||||
|
$output .= '.'.$fileinfo['video']['dataformat'];
|
||||||
|
$output .= '.'.$fileinfo['audio']['dataformat']; // asf.wmv.wma
|
||||||
|
return $output;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
21
livesupport/modules/getid3/var/getid3.exe.php
Normal file
21
livesupport/modules/getid3/var/getid3.exe.php
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
<?php
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
/// getID3() by James Heinrich <getid3@users.sourceforge.net> //
|
||||||
|
// available at http://getid3.sourceforge.net ///
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
// //
|
||||||
|
// getid3.exe.php - part of getID3() //
|
||||||
|
// See getid3.readme.txt for more details //
|
||||||
|
// //
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
function getEXEHeaderFilepointer(&$fd, &$ThisFileInfo) {
|
||||||
|
|
||||||
|
$ThisFileInfo['fileformat'] = 'exe';
|
||||||
|
|
||||||
|
$ThisFileInfo['error'] .= "\n".'EXE parsing not enabled in this version of getID3()';
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
285
livesupport/modules/getid3/var/getid3.flac.php
Normal file
285
livesupport/modules/getid3/var/getid3.flac.php
Normal file
|
@ -0,0 +1,285 @@
|
||||||
|
<?php
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
/// getID3() by James Heinrich <getid3@users.sourceforge.net> //
|
||||||
|
// available at http://getid3.sourceforge.net ///
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
// //
|
||||||
|
// getid3.flac.php - part of getID3() //
|
||||||
|
// See getid3.readme.txt for more details //
|
||||||
|
// //
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
function getFLACHeaderFilepointer(&$fd, &$ThisFileInfo) {
|
||||||
|
// http://flac.sourceforge.net/format.html
|
||||||
|
|
||||||
|
fseek($fd, $ThisFileInfo['avdataoffset'], SEEK_SET);
|
||||||
|
$StreamMarker = fread($fd, 4);
|
||||||
|
if ($StreamMarker != 'fLaC') {
|
||||||
|
$ThisFileInfo['error'] .= "\n".'Invalid stream_marker - expected "fLaC", found "'.$StreamMarker.'"';;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$ThisFileInfo['fileformat'] = 'flac';
|
||||||
|
$ThisFileInfo['audio']['dataformat'] = 'flac';
|
||||||
|
$ThisFileInfo['audio']['bitrate_mode'] = 'vbr';
|
||||||
|
|
||||||
|
return FLACparseMETAdata($fd, $ThisFileInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function FLACparseMETAdata(&$fd, &$ThisFileInfo) {
|
||||||
|
|
||||||
|
do {
|
||||||
|
$METAdataBlockOffset = ftell($fd);
|
||||||
|
$METAdataBlockHeader = fread($fd, 4);
|
||||||
|
$METAdataLastBlockFlag = (bool) (BigEndian2Int(substr($METAdataBlockHeader, 0, 1)) & 0x80);
|
||||||
|
$METAdataBlockType = BigEndian2Int(substr($METAdataBlockHeader, 0, 1)) & 0x7F;
|
||||||
|
$METAdataBlockLength = BigEndian2Int(substr($METAdataBlockHeader, 1, 3));
|
||||||
|
$METAdataBlockTypeText = FLACmetaBlockTypeLookup($METAdataBlockType);
|
||||||
|
|
||||||
|
$ThisFileInfo['flac']["$METAdataBlockTypeText"]['raw']['offset'] = $METAdataBlockOffset;
|
||||||
|
$ThisFileInfo['flac']["$METAdataBlockTypeText"]['raw']['last_meta_block'] = $METAdataLastBlockFlag;
|
||||||
|
$ThisFileInfo['flac']["$METAdataBlockTypeText"]['raw']['block_type'] = $METAdataBlockType;
|
||||||
|
$ThisFileInfo['flac']["$METAdataBlockTypeText"]['raw']['block_type_text'] = $METAdataBlockTypeText;
|
||||||
|
$ThisFileInfo['flac']["$METAdataBlockTypeText"]['raw']['block_length'] = $METAdataBlockLength;
|
||||||
|
$ThisFileInfo['flac']["$METAdataBlockTypeText"]['raw']['block_data'] = fread($fd, $METAdataBlockLength);
|
||||||
|
$ThisFileInfo['avdataoffset'] = ftell($fd);
|
||||||
|
|
||||||
|
switch ($METAdataBlockTypeText) {
|
||||||
|
|
||||||
|
case 'STREAMINFO':
|
||||||
|
if (!FLACparseSTREAMINFO($ThisFileInfo['flac']["$METAdataBlockTypeText"]['raw']['block_data'], $ThisFileInfo)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'PADDING':
|
||||||
|
// ignore
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'APPLICATION':
|
||||||
|
if (!FLACparseAPPLICATION($ThisFileInfo['flac']["$METAdataBlockTypeText"]['raw']['block_data'], $ThisFileInfo)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'SEEKTABLE':
|
||||||
|
if (!FLACparseSEEKTABLE($ThisFileInfo['flac']["$METAdataBlockTypeText"]['raw']['block_data'], $ThisFileInfo)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'VORBIS_COMMENT':
|
||||||
|
require_once(GETID3_INCLUDEPATH.'getid3.ogg.php');
|
||||||
|
//ParseVorbisComments($ThisFileInfo['flac']["$METAdataBlockTypeText"]['raw']['block_data'], $ThisFileInfo, $METAdataBlockOffset, $fd);
|
||||||
|
|
||||||
|
$OldOffset = ftell($fd);
|
||||||
|
fseek($fd, 0 - $METAdataBlockLength, SEEK_CUR);
|
||||||
|
ParseVorbisCommentsFilepointer($fd, $ThisFileInfo);
|
||||||
|
fseek($fd, $OldOffset, SEEK_SET);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'CUESHEET':
|
||||||
|
if (!FLACparseCUESHEET($ThisFileInfo['flac']["$METAdataBlockTypeText"]['raw']['block_data'], $ThisFileInfo)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
$ThisFileInfo['warning'] .= "\n".'Unhandled METADATA_BLOCK_HEADER.BLOCK_TYPE ('.$METAdataBlockType.') at offset '.$METAdataBlockOffset;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
} while ($METAdataLastBlockFlag === false);
|
||||||
|
|
||||||
|
|
||||||
|
if (isset($ThisFileInfo['flac']['STREAMINFO'])) {
|
||||||
|
$ThisFileInfo['flac']['compressed_audio_bytes'] = $ThisFileInfo['avdataend'] - $ThisFileInfo['avdataoffset'];
|
||||||
|
$ThisFileInfo['flac']['uncompressed_audio_bytes'] = $ThisFileInfo['flac']['STREAMINFO']['samples_stream'] * $ThisFileInfo['flac']['STREAMINFO']['channels'] * ($ThisFileInfo['flac']['STREAMINFO']['bits_per_sample'] / 8);
|
||||||
|
if ($ThisFileInfo['flac']['uncompressed_audio_bytes'] == 0) {
|
||||||
|
$ThisFileInfo['error'] .= "\n".'Corrupt FLAC file: uncompressed_audio_bytes == zero';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$ThisFileInfo['flac']['compression_ratio'] = $ThisFileInfo['flac']['compressed_audio_bytes'] / $ThisFileInfo['flac']['uncompressed_audio_bytes'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// set md5_data - built into flac 0.5+
|
||||||
|
if (isset($ThisFileInfo['flac']['STREAMINFO']['audio_signature'])) {
|
||||||
|
|
||||||
|
if ($ThisFileInfo['flac']['STREAMINFO']['audio_signature'] === str_repeat(chr(0), 16)) {
|
||||||
|
|
||||||
|
$ThisFileInfo['warning'] .= "\n".'FLAC STREAMINFO.audio_signature is null (known issue with libOggFLAC), using calculated md5_data';
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
$ThisFileInfo['md5_data'] = '';
|
||||||
|
$md5 = $ThisFileInfo['flac']['STREAMINFO']['audio_signature'];
|
||||||
|
for ($i = 0; $i < strlen($md5); $i++) {
|
||||||
|
$ThisFileInfo['md5_data'] .= str_pad(dechex(ord($md5[$i])), 2, '00', STR_PAD_LEFT);
|
||||||
|
}
|
||||||
|
if (!preg_match('/^[0-9a-f]{32}$/', $ThisFileInfo['md5_data'])) {
|
||||||
|
unset($ThisFileInfo['md5_data']);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
$ThisFileInfo['audio']['bits_per_sample'] = $ThisFileInfo['flac']['STREAMINFO']['bits_per_sample'];
|
||||||
|
if (!empty($ThisFileInfo['ogg']['vendor'])) {
|
||||||
|
$ThisFileInfo['audio']['encoder'] = $ThisFileInfo['ogg']['vendor'];
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function FLACmetaBlockTypeLookup($blocktype) {
|
||||||
|
static $FLACmetaBlockTypeLookup = array();
|
||||||
|
if (empty($FLACmetaBlockTypeLookup)) {
|
||||||
|
$FLACmetaBlockTypeLookup[0] = 'STREAMINFO';
|
||||||
|
$FLACmetaBlockTypeLookup[1] = 'PADDING';
|
||||||
|
$FLACmetaBlockTypeLookup[2] = 'APPLICATION';
|
||||||
|
$FLACmetaBlockTypeLookup[3] = 'SEEKTABLE';
|
||||||
|
$FLACmetaBlockTypeLookup[4] = 'VORBIS_COMMENT';
|
||||||
|
$FLACmetaBlockTypeLookup[5] = 'CUESHEET';
|
||||||
|
}
|
||||||
|
return (isset($FLACmetaBlockTypeLookup[$blocktype]) ? $FLACmetaBlockTypeLookup[$blocktype] : 'reserved');
|
||||||
|
}
|
||||||
|
|
||||||
|
function FLACapplicationIDLookup($applicationid) {
|
||||||
|
static $FLACapplicationIDLookup = array();
|
||||||
|
if (empty($FLACapplicationIDLookup)) {
|
||||||
|
// http://flac.sourceforge.net/id.html
|
||||||
|
$FLACapplicationIDLookup[0x46746F6C] = 'flac-tools'; // 'Ftol'
|
||||||
|
$FLACapplicationIDLookup[0x46746F6C] = 'Sound Font FLAC'; // 'SFFL'
|
||||||
|
}
|
||||||
|
return (isset($FLACapplicationIDLookup[$applicationid]) ? $FLACapplicationIDLookup[$applicationid] : 'reserved');
|
||||||
|
}
|
||||||
|
|
||||||
|
function FLACparseSTREAMINFO($METAdataBlockData, &$ThisFileInfo) {
|
||||||
|
$offset = 0;
|
||||||
|
$ThisFileInfo['flac']['STREAMINFO']['min_block_size'] = BigEndian2Int(substr($METAdataBlockData, $offset, 2));
|
||||||
|
$offset += 2;
|
||||||
|
$ThisFileInfo['flac']['STREAMINFO']['max_block_size'] = BigEndian2Int(substr($METAdataBlockData, $offset, 2));
|
||||||
|
$offset += 2;
|
||||||
|
$ThisFileInfo['flac']['STREAMINFO']['min_frame_size'] = BigEndian2Int(substr($METAdataBlockData, $offset, 3));
|
||||||
|
$offset += 3;
|
||||||
|
$ThisFileInfo['flac']['STREAMINFO']['max_frame_size'] = BigEndian2Int(substr($METAdataBlockData, $offset, 3));
|
||||||
|
$offset += 3;
|
||||||
|
|
||||||
|
$SampleRateChannelsSampleBitsStreamSamples = BigEndian2Bin(substr($METAdataBlockData, $offset, 8));
|
||||||
|
$ThisFileInfo['flac']['STREAMINFO']['sample_rate'] = Bin2Dec(substr($SampleRateChannelsSampleBitsStreamSamples, 0, 20));
|
||||||
|
$ThisFileInfo['flac']['STREAMINFO']['channels'] = Bin2Dec(substr($SampleRateChannelsSampleBitsStreamSamples, 20, 3)) + 1;
|
||||||
|
$ThisFileInfo['flac']['STREAMINFO']['bits_per_sample'] = Bin2Dec(substr($SampleRateChannelsSampleBitsStreamSamples, 23, 5)) + 1;
|
||||||
|
$ThisFileInfo['flac']['STREAMINFO']['samples_stream'] = Bin2Dec(substr($SampleRateChannelsSampleBitsStreamSamples, 28, 36));
|
||||||
|
$offset += 8;
|
||||||
|
|
||||||
|
$ThisFileInfo['flac']['STREAMINFO']['audio_signature'] = substr($METAdataBlockData, $offset, 16);
|
||||||
|
$offset += 16;
|
||||||
|
|
||||||
|
if (!empty($ThisFileInfo['flac']['STREAMINFO']['sample_rate'])) {
|
||||||
|
|
||||||
|
$ThisFileInfo['audio']['bitrate_mode'] = 'vbr';
|
||||||
|
$ThisFileInfo['audio']['sample_rate'] = $ThisFileInfo['flac']['STREAMINFO']['sample_rate'];
|
||||||
|
$ThisFileInfo['audio']['channels'] = $ThisFileInfo['flac']['STREAMINFO']['channels'];
|
||||||
|
$ThisFileInfo['audio']['bits_per_sample'] = $ThisFileInfo['flac']['STREAMINFO']['bits_per_sample'];
|
||||||
|
$ThisFileInfo['playtime_seconds'] = $ThisFileInfo['flac']['STREAMINFO']['samples_stream'] / $ThisFileInfo['flac']['STREAMINFO']['sample_rate'];
|
||||||
|
$ThisFileInfo['audio']['bitrate'] = (($ThisFileInfo['avdataend'] - $ThisFileInfo['avdataoffset']) * 8) / $ThisFileInfo['playtime_seconds'];
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
$ThisFileInfo['error'] .= "\n".'Corrupt METAdata block: STREAMINFO';
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function FLACparseAPPLICATION($METAdataBlockData, &$ThisFileInfo) {
|
||||||
|
$offset = 0;
|
||||||
|
$ApplicationID = BigEndian2Int(substr($METAdataBlockData, $offset, 4));
|
||||||
|
$offset += 4;
|
||||||
|
$ThisFileInfo['flac']['APPLICATION'][$ApplicationID]['name'] = FLACapplicationIDLookup($ApplicationID);
|
||||||
|
$ThisFileInfo['flac']['APPLICATION'][$ApplicationID]['data'] = substr($METAdataBlockData, $offset);
|
||||||
|
$offset = $METAdataBlockLength;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function FLACparseSEEKTABLE($METAdataBlockData, &$ThisFileInfo) {
|
||||||
|
$offset = 0;
|
||||||
|
$METAdataBlockLength = strlen($METAdataBlockData);
|
||||||
|
$placeholderpattern = str_repeat(chr(0xFF), 8);
|
||||||
|
while ($offset < $METAdataBlockLength) {
|
||||||
|
$SampleNumberString = substr($METAdataBlockData, $offset, 8);
|
||||||
|
$offset += 8;
|
||||||
|
if ($SampleNumberString == $placeholderpattern) {
|
||||||
|
|
||||||
|
// placeholder point
|
||||||
|
safe_inc($ThisFileInfo['flac']['SEEKTABLE']['placeholders']);
|
||||||
|
$offset += 10;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
$SampleNumber = BigEndian2Int($SampleNumberString);
|
||||||
|
$ThisFileInfo['flac']['SEEKTABLE'][$SampleNumber]['offset'] = BigEndian2Int(substr($METAdataBlockData, $offset, 8));
|
||||||
|
$offset += 8;
|
||||||
|
$ThisFileInfo['flac']['SEEKTABLE'][$SampleNumber]['samples'] = BigEndian2Int(substr($METAdataBlockData, $offset, 2));
|
||||||
|
$offset += 2;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function FLACparseCUESHEET($METAdataBlockData, &$ThisFileInfo) {
|
||||||
|
$offset = 0;
|
||||||
|
$ThisFileInfo['flac']['CUESHEET']['media_catalog_number'] = trim(substr($METAdataBlockData, $offset, 128), "\0");
|
||||||
|
$offset += 128;
|
||||||
|
$ThisFileInfo['flac']['CUESHEET']['lead_in_samples'] = BigEndian2Int(substr($METAdataBlockData, $offset, 8));
|
||||||
|
$offset += 8;
|
||||||
|
$ThisFileInfo['flac']['CUESHEET']['flags']['is_cd'] = (bool) (BigEndian2Int(substr($METAdataBlockData, $offset, 1)) & 0x80);
|
||||||
|
$offset += 1;
|
||||||
|
|
||||||
|
$offset += 258; // reserved
|
||||||
|
|
||||||
|
$ThisFileInfo['flac']['CUESHEET']['number_tracks'] = BigEndian2Int(substr($METAdataBlockData, $offset, 1));
|
||||||
|
$offset += 1;
|
||||||
|
|
||||||
|
for ($track = 0; $track < $ThisFileInfo['flac']['CUESHEET']['number_tracks']; $track++) {
|
||||||
|
$TrackSampleOffset = BigEndian2Int(substr($METAdataBlockData, $offset, 8));
|
||||||
|
$offset += 8;
|
||||||
|
$TrackNumber = BigEndian2Int(substr($METAdataBlockData, $offset, 1));
|
||||||
|
$offset += 1;
|
||||||
|
|
||||||
|
$ThisFileInfo['flac']['CUESHEET']['tracks'][$TrackNumber]['sample_offset'] = $TrackSampleOffset;
|
||||||
|
|
||||||
|
$ThisFileInfo['flac']['CUESHEET']['tracks'][$TrackNumber]['isrc'] = substr($METAdataBlockData, $offset, 12);
|
||||||
|
$offset += 12;
|
||||||
|
|
||||||
|
$TrackFlagsRaw = BigEndian2Int(substr($METAdataBlockData, $offset, 1));
|
||||||
|
$offset += 1;
|
||||||
|
$ThisFileInfo['flac']['CUESHEET']['tracks'][$TrackNumber]['flags']['is_audio'] = (bool) ($TrackFlagsRaw & 0x80);
|
||||||
|
$ThisFileInfo['flac']['CUESHEET']['tracks'][$TrackNumber]['flags']['pre_emphasis'] = (bool) ($TrackFlagsRaw & 0x40);
|
||||||
|
|
||||||
|
$offset += 13; // reserved
|
||||||
|
|
||||||
|
$ThisFileInfo['flac']['CUESHEET']['tracks'][$TrackNumber]['index_points'] = BigEndian2Int(substr($METAdataBlockData, $offset, 1));
|
||||||
|
$offset += 1;
|
||||||
|
|
||||||
|
for ($index = 0; $index < $ThisFileInfo['flac']['CUESHEET']['tracks'][$TrackNumber]['index_points']; $index++) {
|
||||||
|
$IndexSampleOffset = BigEndian2Int(substr($METAdataBlockData, $offset, 8));
|
||||||
|
$offset += 8;
|
||||||
|
$IndexNumber = BigEndian2Int(substr($METAdataBlockData, $offset, 8));
|
||||||
|
$offset += 1;
|
||||||
|
|
||||||
|
$offset += 3; // reserved
|
||||||
|
|
||||||
|
$ThisFileInfo['flac']['CUESHEET']['tracks'][$TrackNumber]['indexes'][$IndexNumber] = $IndexSampleOffset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
1152
livesupport/modules/getid3/var/getid3.functions.php
Normal file
1152
livesupport/modules/getid3/var/getid3.functions.php
Normal file
File diff suppressed because it is too large
Load diff
157
livesupport/modules/getid3/var/getid3.getimagesize.php
Normal file
157
livesupport/modules/getid3/var/getid3.getimagesize.php
Normal file
|
@ -0,0 +1,157 @@
|
||||||
|
<?php
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
/// getID3() by James Heinrich <getid3@users.sourceforge.net> //
|
||||||
|
// available at http://getid3.sourceforge.net ///
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
// //
|
||||||
|
// getid3.getimagesize.php - part of getID3() //
|
||||||
|
// See getid3.readme.txt for more details //
|
||||||
|
// //
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
// GetURLImageSize( $urlpic ) determines the //
|
||||||
|
// dimensions of local/remote URL pictures. //
|
||||||
|
// returns array with ($width, $height, $type) //
|
||||||
|
// //
|
||||||
|
// Thanks to: Oyvind Hallsteinsen aka Gosub / ELq - //
|
||||||
|
// gosub@elq.org for the original size determining code //
|
||||||
|
// //
|
||||||
|
// PHP Hack by Filipe Laborde-Basto Oct 21/2000 //
|
||||||
|
// FREELY DISTRIBUTABLE -- use at your sole discretion! :) //
|
||||||
|
// Enjoy. (Not to be sold in commercial packages though, //
|
||||||
|
// keep it free!) Feel free to contact me at fil@rezox.com //
|
||||||
|
// (http://www.rezox.com) //
|
||||||
|
// //
|
||||||
|
// Modified by James Heinrich <getid3@users.sourceforge.net> //
|
||||||
|
// June 1, 2001 - created GetDataImageSize($imgData) by //
|
||||||
|
// seperating the fopen() stuff to GetURLImageSize($urlpic) //
|
||||||
|
// which then calls GetDataImageSize($imgData). The idea being //
|
||||||
|
// you can call GetDataImageSize($imgData) with image data //
|
||||||
|
// from a database etc. //
|
||||||
|
// //
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
define('GIF_SIG', chr(0x47).chr(0x49).chr(0x46)); // 'GIF'
|
||||||
|
|
||||||
|
define('PNG_SIG', chr(0x89).chr(0x50).chr(0x4E).chr(0x47).chr(0x0D).chr(0x0A).chr(0x1A).chr(0x0A));
|
||||||
|
|
||||||
|
define('JPG_SIG', chr(0xFF).chr(0xD8).chr(0xFF));
|
||||||
|
define('JPG_SOS', chr(0xDA)); // Start Of Scan - image data start
|
||||||
|
define('JPG_SOF0', chr(0xC0)); // Start Of Frame N
|
||||||
|
define('JPG_SOF1', chr(0xC1)); // N indicates which compression process
|
||||||
|
define('JPG_SOF2', chr(0xC2)); // Only SOF0-SOF2 are now in common use
|
||||||
|
define('JPG_SOF3', chr(0xC3));
|
||||||
|
// NB: codes C4 and CC are *not* SOF markers
|
||||||
|
define('JPG_SOF5', chr(0xC5));
|
||||||
|
define('JPG_SOF6', chr(0xC6));
|
||||||
|
define('JPG_SOF7', chr(0xC7));
|
||||||
|
define('JPG_SOF9', chr(0xC9));
|
||||||
|
define('JPG_SOF10', chr(0xCA));
|
||||||
|
define('JPG_SOF11', chr(0xCB));
|
||||||
|
// NB: codes C4 and CC are *not* SOF markers
|
||||||
|
define('JPG_SOF13', chr(0xCD));
|
||||||
|
define('JPG_SOF14', chr(0xCE));
|
||||||
|
define('JPG_SOF15', chr(0xCF));
|
||||||
|
define('JPG_EOI', chr(0xD9)); // End Of Image (end of datastream)
|
||||||
|
|
||||||
|
|
||||||
|
function GetURLImageSize($urlpic) {
|
||||||
|
if ($fd = @fopen($urlpic, 'rb')){
|
||||||
|
$imgData = fread($fd, filesize($urlpic));
|
||||||
|
fclose($fd);
|
||||||
|
return GetDataImageSize($imgData);
|
||||||
|
} else {
|
||||||
|
return array('', '', '');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function GetDataImageSize($imgData) {
|
||||||
|
$height = '';
|
||||||
|
$width = '';
|
||||||
|
$type = '';
|
||||||
|
if ((substr($imgData, 0, 3) == GIF_SIG) && (strlen($imgData) > 10)) {
|
||||||
|
$dim = unpack('v2dim', substr($imgData, 6, 4));
|
||||||
|
$width = $dim['dim1'];
|
||||||
|
$height = $dim['dim2'];
|
||||||
|
$type = 1;
|
||||||
|
} elseif ((substr($imgData, 0, 8) == PNG_SIG) && (strlen($imgData) > 24)) {
|
||||||
|
$dim = unpack('N2dim', substr($imgData, 16, 8));
|
||||||
|
$width = $dim['dim1'];
|
||||||
|
$height = $dim['dim2'];
|
||||||
|
$type = 3;
|
||||||
|
} elseif ((substr($imgData, 0, 3) == JPG_SIG) && (strlen($imgData) > 4)) {
|
||||||
|
///////////////// JPG CHUNK SCAN ////////////////////
|
||||||
|
$imgPos = 2;
|
||||||
|
$type = 2;
|
||||||
|
$buffer = strlen($imgData) - 2;
|
||||||
|
while ($imgPos < strlen($imgData)) {
|
||||||
|
// synchronize to the marker 0xFF
|
||||||
|
$imgPos = strpos($imgData, 0xFF, $imgPos) + 1;
|
||||||
|
$marker = $imgData[$imgPos];
|
||||||
|
do {
|
||||||
|
$marker = ord($imgData[$imgPos++]);
|
||||||
|
} while ($marker == 255);
|
||||||
|
// find dimensions of block
|
||||||
|
switch (chr($marker)) {
|
||||||
|
// Grab width/height from SOF segment (these are acceptable chunk types)
|
||||||
|
case JPG_SOF0:
|
||||||
|
case JPG_SOF1:
|
||||||
|
case JPG_SOF2:
|
||||||
|
case JPG_SOF3:
|
||||||
|
case JPG_SOF5:
|
||||||
|
case JPG_SOF6:
|
||||||
|
case JPG_SOF7:
|
||||||
|
case JPG_SOF9:
|
||||||
|
case JPG_SOF10:
|
||||||
|
case JPG_SOF11:
|
||||||
|
case JPG_SOF13:
|
||||||
|
case JPG_SOF14:
|
||||||
|
case JPG_SOF15:
|
||||||
|
$dim = unpack('n2dim', substr($imgData, $imgPos + 3, 4));
|
||||||
|
$height = $dim['dim1'];
|
||||||
|
$width = $dim['dim2'];
|
||||||
|
break 2; // found it so exit
|
||||||
|
case JPG_EOI:
|
||||||
|
case JPG_SOS:
|
||||||
|
return false; // End loop in case we find one of these markers
|
||||||
|
default: // We're not interested in other markers
|
||||||
|
$skiplen = (ord($imgData[$imgPos++]) << 8) + ord($imgData[$imgPos++]) - 2;
|
||||||
|
// if the skip is more than what we've read in, read more
|
||||||
|
$buffer -= $skiplen;
|
||||||
|
if ($buffer < 512) { // if the buffer of data is too low, read more file.
|
||||||
|
// $imgData .= fread( $fd,$skiplen+1024 );
|
||||||
|
// $buffer += $skiplen + 1024;
|
||||||
|
return false; // End loop in case we find run out of data
|
||||||
|
}
|
||||||
|
$imgPos += $skiplen;
|
||||||
|
break;
|
||||||
|
} // endswitch check marker type
|
||||||
|
} // endif loop through JPG chunks
|
||||||
|
} // endif chk for valid file types
|
||||||
|
|
||||||
|
return array($width, $height, $type);
|
||||||
|
} // end function
|
||||||
|
|
||||||
|
|
||||||
|
function ImageTypesLookup($imagetypeid) {
|
||||||
|
static $ImageTypesLookup = array();
|
||||||
|
if (empty($ImageTypesLookup)) {
|
||||||
|
$ImageTypesLookup[1] = 'gif';
|
||||||
|
$ImageTypesLookup[2] = 'jpg';
|
||||||
|
$ImageTypesLookup[3] = 'png';
|
||||||
|
$ImageTypesLookup[4] = 'swf';
|
||||||
|
$ImageTypesLookup[5] = 'psd';
|
||||||
|
$ImageTypesLookup[6] = 'bmp';
|
||||||
|
$ImageTypesLookup[7] = 'tiff (little-endian)';
|
||||||
|
$ImageTypesLookup[8] = 'tiff (big-endian)';
|
||||||
|
$ImageTypesLookup[9] = 'jpc';
|
||||||
|
$ImageTypesLookup[10] = 'jp2';
|
||||||
|
$ImageTypesLookup[11] = 'jpx';
|
||||||
|
$ImageTypesLookup[12] = 'jb2';
|
||||||
|
$ImageTypesLookup[13] = 'swc';
|
||||||
|
$ImageTypesLookup[14] = 'iff';
|
||||||
|
}
|
||||||
|
return (isset($ImageTypesLookup[$imagetypeid]) ? $ImageTypesLookup[$imagetypeid] : '');
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
75
livesupport/modules/getid3/var/getid3.gif.php
Normal file
75
livesupport/modules/getid3/var/getid3.gif.php
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
<?php
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
/// getID3() by James Heinrich <getid3@users.sourceforge.net> //
|
||||||
|
// available at http://getid3.sourceforge.net ///
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
// //
|
||||||
|
// getid3.gif.php - part of getID3() //
|
||||||
|
// See getid3.readme.txt for more details //
|
||||||
|
// //
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
function getGIFHeaderFilepointer(&$fd, &$ThisFileInfo) {
|
||||||
|
$ThisFileInfo['fileformat'] = 'gif';
|
||||||
|
$ThisFileInfo['video']['dataformat'] = 'gif';
|
||||||
|
|
||||||
|
fseek($fd, $ThisFileInfo['avdataoffset'], SEEK_SET);
|
||||||
|
$GIFheader = fread($fd, 13);
|
||||||
|
$offset = 0;
|
||||||
|
|
||||||
|
$ThisFileInfo['gif']['header']['raw']['identifier'] = substr($GIFheader, $offset, 3);
|
||||||
|
$offset += 3;
|
||||||
|
$ThisFileInfo['gif']['header']['raw']['version'] = substr($GIFheader, $offset, 3);
|
||||||
|
$offset += 3;
|
||||||
|
$ThisFileInfo['gif']['header']['raw']['width'] = LittleEndian2Int(substr($GIFheader, $offset, 2));
|
||||||
|
$offset += 2;
|
||||||
|
$ThisFileInfo['gif']['header']['raw']['height'] = LittleEndian2Int(substr($GIFheader, $offset, 2));
|
||||||
|
$offset += 2;
|
||||||
|
$ThisFileInfo['gif']['header']['raw']['flags'] = LittleEndian2Int(substr($GIFheader, $offset, 1));
|
||||||
|
$offset += 1;
|
||||||
|
$ThisFileInfo['gif']['header']['raw']['bg_color_index'] = LittleEndian2Int(substr($GIFheader, $offset, 1));
|
||||||
|
$offset += 1;
|
||||||
|
$ThisFileInfo['gif']['header']['raw']['aspect_ratio'] = LittleEndian2Int(substr($GIFheader, $offset, 1));
|
||||||
|
$offset += 1;
|
||||||
|
|
||||||
|
$ThisFileInfo['video']['resolution_x'] = $ThisFileInfo['gif']['header']['raw']['width'];
|
||||||
|
$ThisFileInfo['video']['resolution_y'] = $ThisFileInfo['gif']['header']['raw']['height'];
|
||||||
|
$ThisFileInfo['gif']['version'] = $ThisFileInfo['gif']['header']['raw']['version'];
|
||||||
|
$ThisFileInfo['gif']['header']['flags']['global_color_table'] = (bool) ($ThisFileInfo['gif']['header']['raw']['flags'] & 0x80);
|
||||||
|
if ($ThisFileInfo['gif']['header']['raw']['flags'] & 0x80) {
|
||||||
|
// Number of bits per primary color available to the original image, minus 1
|
||||||
|
$ThisFileInfo['gif']['header']['flags']['bits_per_pixel'] = 3 * ((($ThisFileInfo['gif']['header']['raw']['flags'] & 0x70) >> 4) + 1);
|
||||||
|
} else {
|
||||||
|
$ThisFileInfo['gif']['header']['flags']['bits_per_pixel'] = 0;
|
||||||
|
}
|
||||||
|
$ThisFileInfo['gif']['header']['flags']['global_color_sorted'] = (bool) ($ThisFileInfo['gif']['header']['raw']['flags'] & 0x40);
|
||||||
|
if ($ThisFileInfo['gif']['header']['flags']['global_color_table']) {
|
||||||
|
// the number of bytes contained in the Global Color Table. To determine that
|
||||||
|
// actual size of the color table, raise 2 to [the value of the field + 1]
|
||||||
|
$ThisFileInfo['gif']['header']['flags']['global_color_size'] = pow(2, ($ThisFileInfo['gif']['header']['raw']['flags'] & 0x07) + 1);
|
||||||
|
} else {
|
||||||
|
$ThisFileInfo['gif']['header']['flags']['global_color_size'] = 0;
|
||||||
|
}
|
||||||
|
if ($ThisFileInfo['gif']['header']['raw']['aspect_ratio'] != 0) {
|
||||||
|
// Aspect Ratio = (Pixel Aspect Ratio + 15) / 64
|
||||||
|
$ThisFileInfo['gif']['header']['aspect_ratio'] = ($ThisFileInfo['gif']['header']['raw']['aspect_ratio'] + 15) / 64;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($ThisFileInfo['gif']['header']['flags']['global_color_table']) {
|
||||||
|
$GIFcolorTable = fread($fd, 3 * $ThisFileInfo['gif']['header']['flags']['global_color_size']);
|
||||||
|
$offset = 0;
|
||||||
|
for ($i = 0; $i < $ThisFileInfo['gif']['header']['flags']['global_color_size']; $i++) {
|
||||||
|
//$ThisFileInfo['gif']['global_color_table']['red'][$i] = LittleEndian2Int(substr($GIFcolorTable, $offset++, 1));
|
||||||
|
//$ThisFileInfo['gif']['global_color_table']['green'][$i] = LittleEndian2Int(substr($GIFcolorTable, $offset++, 1));
|
||||||
|
//$ThisFileInfo['gif']['global_color_table']['blue'][$i] = LittleEndian2Int(substr($GIFcolorTable, $offset++, 1));
|
||||||
|
$red = LittleEndian2Int(substr($GIFcolorTable, $offset++, 1));
|
||||||
|
$green = LittleEndian2Int(substr($GIFcolorTable, $offset++, 1));
|
||||||
|
$blue = LittleEndian2Int(substr($GIFcolorTable, $offset++, 1));
|
||||||
|
$ThisFileInfo['gif']['global_color_table'][$i] = (($red << 16) | ($green << 8) | ($blue));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
193
livesupport/modules/getid3/var/getid3.id3.php
Normal file
193
livesupport/modules/getid3/var/getid3.id3.php
Normal file
|
@ -0,0 +1,193 @@
|
||||||
|
<?php
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
/// getID3() by James Heinrich <getid3@users.sourceforge.net> //
|
||||||
|
// available at http://getid3.sourceforge.net ///
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
// //
|
||||||
|
// getid3.id3.php - part of getID3() //
|
||||||
|
// See getid3.readme.txt for more details //
|
||||||
|
// //
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
function ArrayOfGenres() {
|
||||||
|
static $GenreLookup = array();
|
||||||
|
if (empty($GenreLookup)) {
|
||||||
|
$GenreLookup[0] = 'Blues';
|
||||||
|
$GenreLookup[1] = 'Classic Rock';
|
||||||
|
$GenreLookup[2] = 'Country';
|
||||||
|
$GenreLookup[3] = 'Dance';
|
||||||
|
$GenreLookup[4] = 'Disco';
|
||||||
|
$GenreLookup[5] = 'Funk';
|
||||||
|
$GenreLookup[6] = 'Grunge';
|
||||||
|
$GenreLookup[7] = 'Hip-Hop';
|
||||||
|
$GenreLookup[8] = 'Jazz';
|
||||||
|
$GenreLookup[9] = 'Metal';
|
||||||
|
$GenreLookup[10] = 'New Age';
|
||||||
|
$GenreLookup[11] = 'Oldies';
|
||||||
|
$GenreLookup[12] = 'Other';
|
||||||
|
$GenreLookup[13] = 'Pop';
|
||||||
|
$GenreLookup[14] = 'R&B';
|
||||||
|
$GenreLookup[15] = 'Rap';
|
||||||
|
$GenreLookup[16] = 'Reggae';
|
||||||
|
$GenreLookup[17] = 'Rock';
|
||||||
|
$GenreLookup[18] = 'Techno';
|
||||||
|
$GenreLookup[19] = 'Industrial';
|
||||||
|
$GenreLookup[20] = 'Alternative';
|
||||||
|
$GenreLookup[21] = 'Ska';
|
||||||
|
$GenreLookup[22] = 'Death Metal';
|
||||||
|
$GenreLookup[23] = 'Pranks';
|
||||||
|
$GenreLookup[24] = 'Soundtrack';
|
||||||
|
$GenreLookup[25] = 'Euro-Techno';
|
||||||
|
$GenreLookup[26] = 'Ambient';
|
||||||
|
$GenreLookup[27] = 'Trip-Hop';
|
||||||
|
$GenreLookup[28] = 'Vocal';
|
||||||
|
$GenreLookup[29] = 'Jazz+Funk';
|
||||||
|
$GenreLookup[30] = 'Fusion';
|
||||||
|
$GenreLookup[31] = 'Trance';
|
||||||
|
$GenreLookup[32] = 'Classical';
|
||||||
|
$GenreLookup[33] = 'Instrumental';
|
||||||
|
$GenreLookup[34] = 'Acid';
|
||||||
|
$GenreLookup[35] = 'House';
|
||||||
|
$GenreLookup[36] = 'Game';
|
||||||
|
$GenreLookup[37] = 'Sound Clip';
|
||||||
|
$GenreLookup[38] = 'Gospel';
|
||||||
|
$GenreLookup[39] = 'Noise';
|
||||||
|
$GenreLookup[40] = 'Alt. Rock';
|
||||||
|
$GenreLookup[41] = 'Bass';
|
||||||
|
$GenreLookup[42] = 'Soul';
|
||||||
|
$GenreLookup[43] = 'Punk';
|
||||||
|
$GenreLookup[44] = 'Space';
|
||||||
|
$GenreLookup[45] = 'Meditative';
|
||||||
|
$GenreLookup[46] = 'Instrumental Pop';
|
||||||
|
$GenreLookup[47] = 'Instrumental Rock';
|
||||||
|
$GenreLookup[48] = 'Ethnic';
|
||||||
|
$GenreLookup[49] = 'Gothic';
|
||||||
|
$GenreLookup[50] = 'Darkwave';
|
||||||
|
$GenreLookup[51] = 'Techno-Industrial';
|
||||||
|
$GenreLookup[52] = 'Electronic';
|
||||||
|
$GenreLookup[53] = 'Folk/Pop';
|
||||||
|
$GenreLookup[54] = 'Eurodance';
|
||||||
|
$GenreLookup[55] = 'Dream';
|
||||||
|
$GenreLookup[56] = 'Southern Rock';
|
||||||
|
$GenreLookup[57] = 'Comedy';
|
||||||
|
$GenreLookup[58] = 'Cult';
|
||||||
|
$GenreLookup[59] = 'Gangsta';
|
||||||
|
$GenreLookup[60] = 'Top 40';
|
||||||
|
$GenreLookup[61] = 'Christian Rap';
|
||||||
|
$GenreLookup[62] = 'Pop/Funk';
|
||||||
|
$GenreLookup[63] = 'Jungle';
|
||||||
|
$GenreLookup[64] = 'Native American';
|
||||||
|
$GenreLookup[65] = 'Cabaret';
|
||||||
|
$GenreLookup[66] = 'New Wave';
|
||||||
|
$GenreLookup[67] = 'Psychadelic';
|
||||||
|
$GenreLookup[68] = 'Rave';
|
||||||
|
$GenreLookup[69] = 'Showtunes';
|
||||||
|
$GenreLookup[70] = 'Trailer';
|
||||||
|
$GenreLookup[71] = 'Lo-Fi';
|
||||||
|
$GenreLookup[72] = 'Tribal';
|
||||||
|
$GenreLookup[73] = 'Acid Punk';
|
||||||
|
$GenreLookup[74] = 'Acid Jazz';
|
||||||
|
$GenreLookup[75] = 'Polka';
|
||||||
|
$GenreLookup[76] = 'Retro';
|
||||||
|
$GenreLookup[77] = 'Musical';
|
||||||
|
$GenreLookup[78] = 'Rock & Roll';
|
||||||
|
$GenreLookup[79] = 'Hard Rock';
|
||||||
|
$GenreLookup[80] = 'Folk';
|
||||||
|
$GenreLookup[81] = 'Folk/Rock';
|
||||||
|
$GenreLookup[82] = 'National Folk';
|
||||||
|
$GenreLookup[83] = 'Swing';
|
||||||
|
$GenreLookup[84] = 'Fast-Fusion';
|
||||||
|
$GenreLookup[85] = 'Bebob';
|
||||||
|
$GenreLookup[86] = 'Latin';
|
||||||
|
$GenreLookup[87] = 'Revival';
|
||||||
|
$GenreLookup[88] = 'Celtic';
|
||||||
|
$GenreLookup[89] = 'Bluegrass';
|
||||||
|
$GenreLookup[90] = 'Avantgarde';
|
||||||
|
$GenreLookup[91] = 'Gothic Rock';
|
||||||
|
$GenreLookup[92] = 'Progressive Rock';
|
||||||
|
$GenreLookup[93] = 'Psychedelic Rock';
|
||||||
|
$GenreLookup[94] = 'Symphonic Rock';
|
||||||
|
$GenreLookup[95] = 'Slow Rock';
|
||||||
|
$GenreLookup[96] = 'Big Band';
|
||||||
|
$GenreLookup[97] = 'Chorus';
|
||||||
|
$GenreLookup[98] = 'Easy Listening';
|
||||||
|
$GenreLookup[99] = 'Acoustic';
|
||||||
|
$GenreLookup[100] = 'Humour';
|
||||||
|
$GenreLookup[101] = 'Speech';
|
||||||
|
$GenreLookup[102] = 'Chanson';
|
||||||
|
$GenreLookup[103] = 'Opera';
|
||||||
|
$GenreLookup[104] = 'Chamber Music';
|
||||||
|
$GenreLookup[105] = 'Sonata';
|
||||||
|
$GenreLookup[106] = 'Symphony';
|
||||||
|
$GenreLookup[107] = 'Booty Bass';
|
||||||
|
$GenreLookup[108] = 'Primus';
|
||||||
|
$GenreLookup[109] = 'Porn Groove';
|
||||||
|
$GenreLookup[110] = 'Satire';
|
||||||
|
$GenreLookup[111] = 'Slow Jam';
|
||||||
|
$GenreLookup[112] = 'Club';
|
||||||
|
$GenreLookup[113] = 'Tango';
|
||||||
|
$GenreLookup[114] = 'Samba';
|
||||||
|
$GenreLookup[115] = 'Folklore';
|
||||||
|
$GenreLookup[116] = 'Ballad';
|
||||||
|
$GenreLookup[117] = 'Power Ballad';
|
||||||
|
$GenreLookup[118] = 'Rhythmic Soul';
|
||||||
|
$GenreLookup[119] = 'Freestyle';
|
||||||
|
$GenreLookup[120] = 'Duet';
|
||||||
|
$GenreLookup[121] = 'Punk Rock';
|
||||||
|
$GenreLookup[122] = 'Drum Solo';
|
||||||
|
$GenreLookup[123] = 'A Cappella';
|
||||||
|
$GenreLookup[124] = 'Euro-House';
|
||||||
|
$GenreLookup[125] = 'Dance Hall';
|
||||||
|
$GenreLookup[126] = 'Goa';
|
||||||
|
$GenreLookup[127] = 'Drum & Bass';
|
||||||
|
$GenreLookup[128] = 'Club-House';
|
||||||
|
$GenreLookup[129] = 'Hardcore';
|
||||||
|
$GenreLookup[130] = 'Terror';
|
||||||
|
$GenreLookup[131] = 'Indie';
|
||||||
|
$GenreLookup[132] = 'BritPop';
|
||||||
|
$GenreLookup[133] = 'Negerpunk';
|
||||||
|
$GenreLookup[134] = 'Polsk Punk';
|
||||||
|
$GenreLookup[135] = 'Beat';
|
||||||
|
$GenreLookup[136] = 'Christian Gangsta Rap';
|
||||||
|
$GenreLookup[137] = 'Heavy Metal';
|
||||||
|
$GenreLookup[138] = 'Black Metal';
|
||||||
|
$GenreLookup[139] = 'Crossover';
|
||||||
|
$GenreLookup[140] = 'Contemporary Christian';
|
||||||
|
$GenreLookup[141] = 'Christian Rock';
|
||||||
|
$GenreLookup[142] = 'Merengue';
|
||||||
|
$GenreLookup[143] = 'Salsa';
|
||||||
|
$GenreLookup[144] = 'Trash Metal';
|
||||||
|
$GenreLookup[145] = 'Anime';
|
||||||
|
$GenreLookup[146] = 'Jpop';
|
||||||
|
$GenreLookup[147] = 'Synthpop';
|
||||||
|
$GenreLookup[255] = 'Unknown';
|
||||||
|
|
||||||
|
$GenreLookup['CR'] = 'Cover';
|
||||||
|
$GenreLookup['RX'] = 'Remix';
|
||||||
|
}
|
||||||
|
return $GenreLookup;
|
||||||
|
}
|
||||||
|
|
||||||
|
function LookupGenre($genreid, $returnkey=false) {
|
||||||
|
if (($genreid != 'RX') && ($genreid === 'CR')) {
|
||||||
|
$genreid = (int) $genreid; // to handle 3 or '3' or '03'
|
||||||
|
}
|
||||||
|
$GenreLookup = ArrayOfGenres();
|
||||||
|
if ($returnkey) {
|
||||||
|
|
||||||
|
$LowerCaseNoSpaceSearchTerm = strtolower(str_replace(' ', '', $genreid));
|
||||||
|
foreach ($GenreLookup as $key => $value) {
|
||||||
|
if (strtolower(str_replace(' ', '', $value)) == $LowerCaseNoSpaceSearchTerm) {
|
||||||
|
return $key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
return (isset($GenreLookup[$genreid]) ? $GenreLookup[$genreid] : '');
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
41
livesupport/modules/getid3/var/getid3.id3v1.php
Normal file
41
livesupport/modules/getid3/var/getid3.id3v1.php
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
<?php
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
/// getID3() by James Heinrich <getid3@users.sourceforge.net> //
|
||||||
|
// available at http://getid3.sourceforge.net ///
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
// //
|
||||||
|
// getid3.id3v1.php - part of getID3() //
|
||||||
|
// See getid3.readme.txt for more details //
|
||||||
|
// //
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
function getID3v1Filepointer(&$fd, &$ThisFileInfo) {
|
||||||
|
|
||||||
|
fseek($fd, -128, SEEK_END);
|
||||||
|
$id3v1tag = fread($fd, 128);
|
||||||
|
|
||||||
|
if (substr($id3v1tag, 0, 3) == 'TAG') {
|
||||||
|
require_once(GETID3_INCLUDEPATH.'getid3.id3.php');
|
||||||
|
|
||||||
|
$ThisFileInfo['id3v1']['title'] = trim(substr($id3v1tag, 3, 30));
|
||||||
|
$ThisFileInfo['id3v1']['artist'] = trim(substr($id3v1tag, 33, 30));
|
||||||
|
$ThisFileInfo['id3v1']['album'] = trim(substr($id3v1tag, 63, 30));
|
||||||
|
$ThisFileInfo['id3v1']['year'] = trim(substr($id3v1tag, 93, 4));
|
||||||
|
$ThisFileInfo['id3v1']['comment'] = substr($id3v1tag, 97, 30); // can't remove nulls yet, track detection depends on them
|
||||||
|
$ThisFileInfo['id3v1']['genreid'] = ord(substr($id3v1tag, 127, 1));
|
||||||
|
|
||||||
|
if ((substr($ThisFileInfo['id3v1']['comment'], 28, 1) === chr(0)) && (substr($ThisFileInfo['id3v1']['comment'], 29, 1) !== chr(0))) {
|
||||||
|
$ThisFileInfo['id3v1']['track'] = ord(substr($ThisFileInfo['id3v1']['comment'], 29, 1));
|
||||||
|
$ThisFileInfo['id3v1']['comment'] = substr($ThisFileInfo['id3v1']['comment'], 0, 28);
|
||||||
|
}
|
||||||
|
$ThisFileInfo['id3v1']['comment'] = trim($ThisFileInfo['id3v1']['comment']);
|
||||||
|
$ThisFileInfo['id3v1']['genre'] = LookupGenre($ThisFileInfo['id3v1']['genreid']);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
400
livesupport/modules/getid3/var/getid3.id3v2.php
Normal file
400
livesupport/modules/getid3/var/getid3.id3v2.php
Normal file
|
@ -0,0 +1,400 @@
|
||||||
|
<?php
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
/// getID3() by James Heinrich <getid3@users.sourceforge.net> //
|
||||||
|
// available at http://getid3.sourceforge.net ///
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
// //
|
||||||
|
// getid3.id3v2.php - part of getID3() //
|
||||||
|
// See getid3.readme.txt for more details //
|
||||||
|
// //
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
function getID3v2Filepointer($fd, &$ThisFileInfo) {
|
||||||
|
// Overall tag structure:
|
||||||
|
// +-----------------------------+
|
||||||
|
// | Header (10 bytes) |
|
||||||
|
// +-----------------------------+
|
||||||
|
// | Extended Header |
|
||||||
|
// | (variable length, OPTIONAL) |
|
||||||
|
// +-----------------------------+
|
||||||
|
// | Frames (variable length) |
|
||||||
|
// +-----------------------------+
|
||||||
|
// | Padding |
|
||||||
|
// | (variable length, OPTIONAL) |
|
||||||
|
// +-----------------------------+
|
||||||
|
// | Footer (10 bytes, OPTIONAL) |
|
||||||
|
// +-----------------------------+
|
||||||
|
|
||||||
|
// Header
|
||||||
|
// ID3v2/file identifier "ID3"
|
||||||
|
// ID3v2 version $04 00
|
||||||
|
// ID3v2 flags (%ab000000 in v2.2, %abc00000 in v2.3, %abcd0000 in v2.4.x)
|
||||||
|
// ID3v2 size 4 * %0xxxxxxx
|
||||||
|
|
||||||
|
require_once(GETID3_INCLUDEPATH.'getid3.frames.php'); // ID3v2FrameProcessing()
|
||||||
|
|
||||||
|
rewind($fd);
|
||||||
|
$header = fread ($fd, 10);
|
||||||
|
if (substr($header, 0, 3) == 'ID3') {
|
||||||
|
$ThisFileInfo['id3v2']['header'] = true;
|
||||||
|
$ThisFileInfo['id3v2']['majorversion'] = ord($header{3});
|
||||||
|
$ThisFileInfo['id3v2']['minorversion'] = ord($header{4});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($ThisFileInfo['id3v2']['header']) && ($ThisFileInfo['id3v2']['majorversion'] <= 4)) { // this script probably won't correctly parse ID3v2.5.x and above.
|
||||||
|
|
||||||
|
$id3_flags = BigEndian2Bin($header{5});
|
||||||
|
switch ($ThisFileInfo['id3v2']['majorversion']) {
|
||||||
|
case 2:
|
||||||
|
// %ab000000 in v2.2
|
||||||
|
$ThisFileInfo['id3v2']['flags']['unsynch'] = $id3_flags{0}; // a - Unsynchronisation
|
||||||
|
$ThisFileInfo['id3v2']['flags']['compression'] = $id3_flags{1}; // b - Compression
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
// %abc00000 in v2.3
|
||||||
|
$ThisFileInfo['id3v2']['flags']['unsynch'] = $id3_flags{0}; // a - Unsynchronisation
|
||||||
|
$ThisFileInfo['id3v2']['flags']['exthead'] = $id3_flags{1}; // b - Extended header
|
||||||
|
$ThisFileInfo['id3v2']['flags']['experim'] = $id3_flags{2}; // c - Experimental indicator
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4:
|
||||||
|
// %abcd0000 in v2.4
|
||||||
|
$ThisFileInfo['id3v2']['flags']['unsynch'] = $id3_flags{0}; // a - Unsynchronisation
|
||||||
|
$ThisFileInfo['id3v2']['flags']['exthead'] = $id3_flags{1}; // b - Extended header
|
||||||
|
$ThisFileInfo['id3v2']['flags']['experim'] = $id3_flags{2}; // c - Experimental indicator
|
||||||
|
$ThisFileInfo['id3v2']['flags']['isfooter'] = $id3_flags{3}; // d - Footer present
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
$ThisFileInfo['id3v2']['headerlength'] = BigEndian2Int(substr($header, 6, 4), 1) + ID3v2HeaderLength($ThisFileInfo['id3v2']['majorversion']);
|
||||||
|
|
||||||
|
// Extended Header
|
||||||
|
if (isset($ThisFileInfo['id3v2']['flags']['exthead']) && $ThisFileInfo['id3v2']['flags']['exthead']) {
|
||||||
|
// Extended header size 4 * %0xxxxxxx
|
||||||
|
// Number of flag bytes $01
|
||||||
|
// Extended Flags $xx
|
||||||
|
// Where the 'Extended header size' is the size of the whole extended header, stored as a 32 bit synchsafe integer.
|
||||||
|
$extheader = fread ($fd, 4);
|
||||||
|
$ThisFileInfo['id3v2']['extheaderlength'] = BigEndian2Int($extheader, 1);
|
||||||
|
|
||||||
|
// The extended flags field, with its size described by 'number of flag bytes', is defined as:
|
||||||
|
// %0bcd0000
|
||||||
|
// b - Tag is an update
|
||||||
|
// Flag data length $00
|
||||||
|
// c - CRC data present
|
||||||
|
// Flag data length $05
|
||||||
|
// Total frame CRC 5 * %0xxxxxxx
|
||||||
|
// d - Tag restrictions
|
||||||
|
// Flag data length $01
|
||||||
|
$extheaderflagbytes = fread ($fd, 1);
|
||||||
|
$extheaderflags = fread ($fd, $extheaderflagbytes);
|
||||||
|
$id3_exthead_flags = BigEndian2Bin(substr($header, 5, 1));
|
||||||
|
$ThisFileInfo['id3v2']['exthead_flags']['update'] = substr($id3_exthead_flags, 1, 1);
|
||||||
|
$ThisFileInfo['id3v2']['exthead_flags']['CRC'] = substr($id3_exthead_flags, 2, 1);
|
||||||
|
if ($ThisFileInfo['id3v2']['exthead_flags']['CRC']) {
|
||||||
|
$extheaderrawCRC = fread ($fd, 5);
|
||||||
|
$ThisFileInfo['id3v2']['exthead_flags']['CRC'] = BigEndian2Int($extheaderrawCRC, 1);
|
||||||
|
}
|
||||||
|
$ThisFileInfo['id3v2']['exthead_flags']['restrictions'] = substr($id3_exthead_flags, 3, 1);
|
||||||
|
if ($ThisFileInfo['id3v2']['exthead_flags']['restrictions']) {
|
||||||
|
// Restrictions %ppqrrstt
|
||||||
|
$extheaderrawrestrictions = fread ($fd, 1);
|
||||||
|
$ThisFileInfo['id3v2']['exthead_flags']['restrictions_tagsize'] = (bindec('11000000') & ord($extheaderrawrestrictions)) >> 6; // p - Tag size restrictions
|
||||||
|
$ThisFileInfo['id3v2']['exthead_flags']['restrictions_textenc'] = (bindec('00100000') & ord($extheaderrawrestrictions)) >> 5; // q - Text encoding restrictions
|
||||||
|
$ThisFileInfo['id3v2']['exthead_flags']['restrictions_textsize'] = (bindec('00011000') & ord($extheaderrawrestrictions)) >> 3; // r - Text fields size restrictions
|
||||||
|
$ThisFileInfo['id3v2']['exthead_flags']['restrictions_imgenc'] = (bindec('00000100') & ord($extheaderrawrestrictions)) >> 2; // s - Image encoding restrictions
|
||||||
|
$ThisFileInfo['id3v2']['exthead_flags']['restrictions_imgsize'] = (bindec('00000011') & ord($extheaderrawrestrictions)) >> 0; // t - Image size restrictions
|
||||||
|
}
|
||||||
|
} // end extended header
|
||||||
|
|
||||||
|
// Frames
|
||||||
|
|
||||||
|
// All ID3v2 frames consists of one frame header followed by one or more
|
||||||
|
// fields containing the actual information. The header is always 10
|
||||||
|
// bytes and laid out as follows:
|
||||||
|
//
|
||||||
|
// Frame ID $xx xx xx xx (four characters)
|
||||||
|
// Size 4 * %0xxxxxxx
|
||||||
|
// Flags $xx xx
|
||||||
|
|
||||||
|
$sizeofframes = $ThisFileInfo['id3v2']['headerlength'] - ID3v2HeaderLength($ThisFileInfo['id3v2']['majorversion']);
|
||||||
|
if (isset($ThisFileInfo['id3v2']['extheaderlength'])) {
|
||||||
|
$sizeofframes -= $ThisFileInfo['id3v2']['extheaderlength'];
|
||||||
|
}
|
||||||
|
if (isset($ThisFileInfo['id3v2']['flags']['isfooter']) && $ThisFileInfo['id3v2']['flags']['isfooter']) {
|
||||||
|
$sizeofframes -= 10; // footer takes last 10 bytes of ID3v2 header, after frame data, before audio
|
||||||
|
}
|
||||||
|
if ($sizeofframes > 0) {
|
||||||
|
$framedata = fread($fd, $sizeofframes); // read all frames from file into $framedata variable
|
||||||
|
|
||||||
|
// if entire frame data is unsynched, de-unsynch it now (ID3v2.3.x)
|
||||||
|
if (isset($ThisFileInfo['id3v2']['flags']['unsynch']) && $ThisFileInfo['id3v2']['flags']['unsynch'] && ($ThisFileInfo['id3v2']['majorversion'] <= 3)) {
|
||||||
|
$framedata = DeUnSynchronise($framedata);
|
||||||
|
}
|
||||||
|
// [in ID3v2.4.0] Unsynchronisation [S:6.1] is done on frame level, instead
|
||||||
|
// of on tag level, making it easier to skip frames, increasing the streamability
|
||||||
|
// of the tag. The unsynchronisation flag in the header [S:3.1] indicates that
|
||||||
|
// there exists an unsynchronised frame, while the new unsynchronisation flag in
|
||||||
|
// the frame header [S:4.1.2] indicates unsynchronisation.
|
||||||
|
|
||||||
|
$framedataoffset = 10; // how many bytes into the stream - start from after the 10-byte header
|
||||||
|
while (isset($framedata) && (strlen($framedata) > 0)) { // cycle through until no more frame data is left to parse
|
||||||
|
if ($ThisFileInfo['id3v2']['majorversion'] == 2) {
|
||||||
|
// Frame ID $xx xx xx (three characters)
|
||||||
|
// Size $xx xx xx (24-bit integer)
|
||||||
|
// Flags $xx xx
|
||||||
|
|
||||||
|
$frame_header = substr($framedata, 0, 6); // take next 6 bytes for header
|
||||||
|
$framedata = substr($framedata, 6); // and leave the rest in $framedata
|
||||||
|
$frame_name = substr($frame_header, 0, 3);
|
||||||
|
$frame_size = BigEndian2Int(substr($frame_header, 3, 3), 0);
|
||||||
|
$frame_flags = ''; // not used for anything, just to avoid E_NOTICEs
|
||||||
|
|
||||||
|
} elseif ($ThisFileInfo['id3v2']['majorversion'] > 2) {
|
||||||
|
|
||||||
|
// Frame ID $xx xx xx xx (four characters)
|
||||||
|
// Size $xx xx xx xx (32-bit integer in v2.3, 28-bit synchsafe in v2.4+)
|
||||||
|
// Flags $xx xx
|
||||||
|
|
||||||
|
$frame_header = substr($framedata, 0, 10); // take next 10 bytes for header
|
||||||
|
$framedata = substr($framedata, 10); // and leave the rest in $framedata
|
||||||
|
|
||||||
|
$frame_name = substr($frame_header, 0, 4);
|
||||||
|
if ($ThisFileInfo['id3v2']['majorversion'] == 3) {
|
||||||
|
$frame_size = BigEndian2Int(substr($frame_header, 4, 4), 0); // 32-bit integer
|
||||||
|
} else { // ID3v2.4+
|
||||||
|
$frame_size = BigEndian2Int(substr($frame_header, 4, 4), 1); // 32-bit synchsafe integer (28-bit value)
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($frame_size < (strlen($framedata) + 4)) {
|
||||||
|
$nextFrameID = substr($framedata, $frame_size, 4);
|
||||||
|
if (IsValidID3v2FrameName($nextFrameID, $ThisFileInfo['id3v2']['majorversion'])) {
|
||||||
|
// next frame is OK
|
||||||
|
} elseif (($frame_name == chr(0).'MP3') || ($frame_name == chr(0).chr(0).'MP') || ($frame_name == ' MP3') || ($frame_name == 'MP3e')) {
|
||||||
|
// MP3ext known broken frames - "ok" for the purposes of this test
|
||||||
|
} elseif (($ThisFileInfo['id3v2']['majorversion'] == 4) && (IsValidID3v2FrameName(substr($framedata, BigEndian2Int(substr($frame_header, 4, 4), 0), 4), 3))) {
|
||||||
|
$ThisFileInfo['warning'] .= "\n".'ID3v2 tag written as ID3v2.4, but with non-synchsafe integers (ID3v2.3 style). Older versions of Helium2 (www.helium2.com) is a known culprit of this. Tag has been parsed as ID3v2.3';
|
||||||
|
$ThisFileInfo['id3v2']['majorversion'] = 3;
|
||||||
|
$frame_size = BigEndian2Int(substr($frame_header, 4, 4), 0); // 32-bit integer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$frame_flags = BigEndian2Bin(substr($frame_header, 8, 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((($ThisFileInfo['id3v2']['majorversion'] == 2) && ($frame_name == chr(0).chr(0).chr(0))) || ($frame_name == chr(0).chr(0).chr(0).chr(0))) {
|
||||||
|
// padding encountered
|
||||||
|
|
||||||
|
$ThisFileInfo['id3v2']['padding']['start'] = $framedataoffset;
|
||||||
|
$ThisFileInfo['id3v2']['padding']['length'] = strlen($framedata);
|
||||||
|
$ThisFileInfo['id3v2']['padding']['valid'] = true;
|
||||||
|
for ($i = 0; $i < $ThisFileInfo['id3v2']['padding']['length']; $i++) {
|
||||||
|
if (substr($framedata, $i, 1) != chr(0)) {
|
||||||
|
$ThisFileInfo['id3v2']['padding']['valid'] = false;
|
||||||
|
$ThisFileInfo['id3v2']['padding']['errorpos'] = $ThisFileInfo['id3v2']['padding']['start'] + $i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break; // skip rest of ID3v2 header
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($frame_name == 'COM ') {
|
||||||
|
$ThisFileInfo['warning'] .= "\n".'error parsing "'.$frame_name.'" ('.$framedataoffset.' bytes into the ID3v2.'.$ThisFileInfo['id3v2']['majorversion'].' tag). (ERROR: !IsValidID3v2FrameName("'.str_replace(chr(0), ' ', $frame_name).'", '.$ThisFileInfo['id3v2']['majorversion'].'))). [Note: this particular error has been known to happen with tags edited by iTunes (versions "X v2.0.3", "v3.0.1" are known-guilty, probably others too)]';
|
||||||
|
$frame_name = 'COMM';
|
||||||
|
}
|
||||||
|
if (($frame_size <= strlen($framedata)) && (IsValidID3v2FrameName($frame_name, $ThisFileInfo['id3v2']['majorversion']))) {
|
||||||
|
|
||||||
|
$ThisFileInfo['id3v2']["$frame_name"]['data'] = substr($framedata, 0, $frame_size);
|
||||||
|
$ThisFileInfo['id3v2']["$frame_name"]['datalength'] = CastAsInt($frame_size);
|
||||||
|
$ThisFileInfo['id3v2']["$frame_name"]['dataoffset'] = $framedataoffset;
|
||||||
|
$framedata = substr($framedata, $frame_size);
|
||||||
|
|
||||||
|
// in getid3.frames.php - this function does all the FrameID-level parsing
|
||||||
|
ID3v2FrameProcessing($frame_name, $frame_flags, $ThisFileInfo);
|
||||||
|
|
||||||
|
} else { // invalid frame length or FrameID
|
||||||
|
|
||||||
|
if ($frame_size <= strlen($framedata)) {
|
||||||
|
|
||||||
|
if (IsValidID3v2FrameName(substr($framedata, $frame_size, 4), $ThisFileInfo['id3v2']['majorversion'])) {
|
||||||
|
|
||||||
|
// next frame is valid, just skip the current frame
|
||||||
|
$framedata = substr($framedata, $frame_size);
|
||||||
|
$InvalidFrameMessageType = 'warning';
|
||||||
|
$InvalidFrameMessageText = ' Next frame is valid, skipping current frame.';
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// next frame is invalid too, abort processing
|
||||||
|
unset($framedata);
|
||||||
|
$InvalidFrameMessageType = 'error';
|
||||||
|
$InvalidFrameMessageText = ' Next frame is also invalid, aborting processing.';
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} elseif ($frame_size == strlen($framedata)) {
|
||||||
|
|
||||||
|
// this is the last frame, just skip
|
||||||
|
$InvalidFrameMessageType = 'warning';
|
||||||
|
$InvalidFrameMessageText = ' This was the last frame.';
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// next frame is invalid too, abort processing
|
||||||
|
unset($framedata);
|
||||||
|
$InvalidFrameMessageType = 'error';
|
||||||
|
$InvalidFrameMessageText = ' Invalid frame size, aborting.';
|
||||||
|
|
||||||
|
}
|
||||||
|
if (!IsValidID3v2FrameName($frame_name, $ThisFileInfo['id3v2']['majorversion'])) {
|
||||||
|
|
||||||
|
switch ($frame_name) {
|
||||||
|
case chr(0).chr(0).'MP':
|
||||||
|
case chr(0).'MP3':
|
||||||
|
case ' MP3':
|
||||||
|
case 'MP3e':
|
||||||
|
case chr(0).'MP':
|
||||||
|
case ' MP':
|
||||||
|
case 'MP3':
|
||||||
|
$InvalidFrameMessageType = 'warning';
|
||||||
|
$ThisFileInfo["$InvalidFrameMessageType"] .= "\n".'error parsing "'.$frame_name.'" ('.$framedataoffset.' bytes into the ID3v2.'.$ThisFileInfo['id3v2']['majorversion'].' tag). (ERROR: !IsValidID3v2FrameName("'.str_replace(chr(0), ' ', $frame_name).'", '.$ThisFileInfo['id3v2']['majorversion'].'))). [Note: this particular error has been known to happen with tags edited by "MP3ext (www.mutschler.de/mp3ext/)"]';
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
$ThisFileInfo["$InvalidFrameMessageType"] .= "\n".'error parsing "'.$frame_name.'" ('.$framedataoffset.' bytes into the ID3v2.'.$ThisFileInfo['id3v2']['majorversion'].' tag). (ERROR: !IsValidID3v2FrameName("'.str_replace(chr(0), ' ', $frame_name).'", '.$ThisFileInfo['id3v2']['majorversion'].'))).';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
} elseif ($frame_size > strlen($framedata)){
|
||||||
|
|
||||||
|
$ThisFileInfo["$InvalidFrameMessageType"] .= "\n".'error parsing "'.$frame_name.'" ('.$framedataoffset.' bytes into the ID3v2.'.$ThisFileInfo['id3v2']['majorversion'].' tag). (ERROR: $frame_size ('.$frame_size.') > strlen($framedata) ('.strlen($framedata).')).';
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
$ThisFileInfo["$InvalidFrameMessageType"] .= "\n".'error parsing "'.$frame_name.'" ('.$framedataoffset.' bytes into the ID3v2.'.$ThisFileInfo['id3v2']['majorversion'].' tag).';
|
||||||
|
|
||||||
|
}
|
||||||
|
$ThisFileInfo["$InvalidFrameMessageType"] .= $InvalidFrameMessageText;
|
||||||
|
|
||||||
|
}
|
||||||
|
$framedataoffset += ($frame_size + ID3v2HeaderLength($ThisFileInfo['id3v2']['majorversion']));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Footer
|
||||||
|
|
||||||
|
// The footer is a copy of the header, but with a different identifier.
|
||||||
|
// ID3v2 identifier "3DI"
|
||||||
|
// ID3v2 version $04 00
|
||||||
|
// ID3v2 flags %abcd0000
|
||||||
|
// ID3v2 size 4 * %0xxxxxxx
|
||||||
|
|
||||||
|
if (isset($ThisFileInfo['id3v2']['flags']['isfooter']) && $ThisFileInfo['id3v2']['flags']['isfooter']) {
|
||||||
|
$footer = fread ($fd, 10);
|
||||||
|
if (substr($footer, 0, 3) == '3DI') {
|
||||||
|
$ThisFileInfo['id3v2']['footer'] = true;
|
||||||
|
$ThisFileInfo['id3v2']['majorversion_footer'] = ord(substr($footer, 3, 1));
|
||||||
|
$ThisFileInfo['id3v2']['minorversion_footer'] = ord(substr($footer, 4, 1));
|
||||||
|
}
|
||||||
|
if ($ThisFileInfo['id3v2']['majorversion_footer'] <= 4) {
|
||||||
|
$id3_flags = BigEndian2Bin(substr($footer, 5, 1));
|
||||||
|
$ThisFileInfo['id3v2']['flags']['unsynch_footer'] = substr($id3_flags, 0, 1);
|
||||||
|
$ThisFileInfo['id3v2']['flags']['extfoot_footer'] = substr($id3_flags, 1, 1);
|
||||||
|
$ThisFileInfo['id3v2']['flags']['experim_footer'] = substr($id3_flags, 2, 1);
|
||||||
|
$ThisFileInfo['id3v2']['flags']['isfooter_footer'] = substr($id3_flags, 3, 1);
|
||||||
|
|
||||||
|
$ThisFileInfo['id3v2']['footerlength'] = BigEndian2Int(substr($footer, 6, 4), 1);
|
||||||
|
}
|
||||||
|
} // end footer
|
||||||
|
|
||||||
|
|
||||||
|
if (isset($ThisFileInfo['id3v2']['comments']['genre'])) {
|
||||||
|
foreach ($ThisFileInfo['id3v2']['comments']['genre'] as $key => $value) {
|
||||||
|
unset($ThisFileInfo['id3v2']['comments']['genre'][$key]);
|
||||||
|
$ThisFileInfo['id3v2']['comments'] = array_merge_noclobber($ThisFileInfo['id3v2']['comments'], ParseID3v2GenreString($value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($ThisFileInfo['id3v2']['comments']['track'])) {
|
||||||
|
foreach ($ThisFileInfo['id3v2']['comments']['track'] as $key => $value) {
|
||||||
|
if (strstr($value, '/')) {
|
||||||
|
list($ThisFileInfo['id3v2']['comments']['track'][$key], $ThisFileInfo['id3v2']['comments']['totaltracks'][$key]) = explode('/', $ThisFileInfo['id3v2']['comments']['track'][$key]);
|
||||||
|
}
|
||||||
|
// Convert track number to integer (ID3v2 track numbers could be returned as a
|
||||||
|
// string ('03' for example) - this will ensure all track numbers are integers
|
||||||
|
$ThisFileInfo['id3v2']['comments']['track'][$key] = intval($ThisFileInfo['id3v2']['comments']['track'][$key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} else { // MajorVersion is > 4, or no ID3v2 header present
|
||||||
|
|
||||||
|
if (isset($ThisFileInfo['id3v2']['header'])) { // MajorVersion is > 4
|
||||||
|
$ThisFileInfo['error'] .= "\n".'this script only parses up to ID3v2.4.x - this tag is ID3v2.'.$ThisFileInfo['id3v2']['majorversion'].'.'.$ThisFileInfo['id3v2']['minorversion'];
|
||||||
|
} else {
|
||||||
|
// no ID3v2 header present - this is fine, just don't process anything.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function ParseID3v2GenreString($genrestring) {
|
||||||
|
// Parse genres into arrays of genreName and genreID
|
||||||
|
// ID3v2.2.x, ID3v2.3.x: '(21)' or '(4)Eurodisco' or '(51)(39)' or '(55)((I think...)'
|
||||||
|
// ID3v2.4.x: '21' $00 'Eurodisco' $00
|
||||||
|
|
||||||
|
require_once(GETID3_INCLUDEPATH.'getid3.id3.php');
|
||||||
|
$returnarray = null;
|
||||||
|
if (strpos($genrestring, chr(0)) !== false) {
|
||||||
|
$unprocessed = trim($genrestring); // trailing nulls will cause an infinite loop.
|
||||||
|
$genrestring = '';
|
||||||
|
while (strpos($unprocessed, chr(0)) !== false) {
|
||||||
|
// convert null-seperated v2.4-format into v2.3 ()-seperated format
|
||||||
|
$endpos = strpos($unprocessed, chr(0));
|
||||||
|
$genrestring .= '('.substr($unprocessed, 0, $endpos).')';
|
||||||
|
$unprocessed = substr($unprocessed, $endpos + 1);
|
||||||
|
}
|
||||||
|
unset($unprocessed);
|
||||||
|
}
|
||||||
|
while (strpos($genrestring, '(') !== false) {
|
||||||
|
$startpos = strpos($genrestring, '(');
|
||||||
|
$endpos = strpos($genrestring, ')');
|
||||||
|
if (substr($genrestring, $startpos + 1, 1) == '(') {
|
||||||
|
$genrestring = substr($genrestring, 0, $startpos).substr($genrestring, $startpos + 1);
|
||||||
|
$endpos--;
|
||||||
|
}
|
||||||
|
$element = substr($genrestring, $startpos + 1, $endpos - ($startpos + 1));
|
||||||
|
$genrestring = substr($genrestring, 0, $startpos).substr($genrestring, $endpos + 1);
|
||||||
|
if (LookupGenre($element) !== '') { // $element is a valid genre id/abbreviation
|
||||||
|
if (!is_array($returnarray['genre']) || !in_array(LookupGenre($element), $returnarray['genre'])) { // avoid duplicate entires
|
||||||
|
if (($element == 'CR') && ($element == 'RX')) {
|
||||||
|
$returnarray['genreid'][] = $element;
|
||||||
|
} else {
|
||||||
|
$returnarray['genreid'][] = (int) $element;
|
||||||
|
}
|
||||||
|
$returnarray['genre'][] = LookupGenre($element);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!is_array($returnarray['genre']) || !in_array($element, $returnarray['genre'])) { // avoid duplicate entires
|
||||||
|
$returnarray['genreid'][] = '';
|
||||||
|
$returnarray['genre'][] = $element;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($genrestring) {
|
||||||
|
if (!is_array($returnarray['genre']) || !in_array($genrestring, $returnarray['genre'])) { // avoid duplicate entires
|
||||||
|
$returnarray['genreid'][] = '';
|
||||||
|
$returnarray['genre'][] = $genrestring;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $returnarray;
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
139
livesupport/modules/getid3/var/getid3.lyrics3.php
Normal file
139
livesupport/modules/getid3/var/getid3.lyrics3.php
Normal file
|
@ -0,0 +1,139 @@
|
||||||
|
<?php
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
/// getID3() by James Heinrich <getid3@users.sourceforge.net> //
|
||||||
|
// available at http://getid3.sourceforge.net ///
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
// //
|
||||||
|
// getid3.lyrics3.php - part of getID3() //
|
||||||
|
// See getid3.readme.txt for more details //
|
||||||
|
// //
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
function getLyrics3Filepointer(&$ThisFileInfo, $fd, $endoffset, $version, $length) {
|
||||||
|
// http://www.volweb.cz/str/tags.htm
|
||||||
|
|
||||||
|
fseek($fd, $endoffset, SEEK_END);
|
||||||
|
$rawdata = fread($fd, $length);
|
||||||
|
|
||||||
|
if (substr($rawdata, 0, 11) == 'LYRICSBEGIN') {
|
||||||
|
|
||||||
|
switch ($version) {
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
if (substr($rawdata, strlen($rawdata) - 9, 9) == 'LYRICSEND') {
|
||||||
|
$ThisFileInfo['lyrics3']['raw']['lyrics3version'] = $version;
|
||||||
|
$ThisFileInfo['lyrics3']['raw']['lyrics3tagsize'] = $length;
|
||||||
|
$ThisFileInfo['lyrics3']['raw']['LYR'] = trim(substr($rawdata, 11, strlen($rawdata) - 11 - 9));
|
||||||
|
Lyrics3LyricsTimestampParse($ThisFileInfo);
|
||||||
|
} else {
|
||||||
|
$ThisFileInfo['error'] .= "\n".'"LYRICSEND" expected at '.(ftell($fd) - 11 + $length - 9).' but found "'.substr($rawdata, strlen($rawdata) - 9, 9).'" instead';
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
if (substr($rawdata, strlen($rawdata) - 9, 9) == 'LYRICS200') {
|
||||||
|
$ThisFileInfo['lyrics3']['raw']['lyrics3version'] = $version;
|
||||||
|
$ThisFileInfo['lyrics3']['raw']['lyrics3tagsize'] = $length;
|
||||||
|
$ThisFileInfo['lyrics3']['raw']['unparsed'] = substr($rawdata, 11, strlen($rawdata) - 11 - 9 - 6); // LYRICSBEGIN + LYRICS200 + LSZ
|
||||||
|
$rawdata = $ThisFileInfo['lyrics3']['raw']['unparsed'];
|
||||||
|
while (strlen($rawdata) > 0) {
|
||||||
|
$fieldname = substr($rawdata, 0, 3);
|
||||||
|
$fieldsize = (int) substr($rawdata, 3, 5);
|
||||||
|
$ThisFileInfo['lyrics3']['raw']["$fieldname"] = substr($rawdata, 8, $fieldsize);
|
||||||
|
$rawdata = substr($rawdata, 3 + 5 + $fieldsize);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($ThisFileInfo['lyrics3']['raw']['IND'])) {
|
||||||
|
$i = 0;
|
||||||
|
$flagnames = array('lyrics', 'timestamps', 'inhibitrandom');
|
||||||
|
foreach ($flagnames as $flagname) {
|
||||||
|
if (strlen($ThisFileInfo['lyrics3']['raw']['IND']) > ++$i) {
|
||||||
|
$ThisFileInfo['lyrics3']['flags']["$flagname"] = IntString2Bool(substr($ThisFileInfo['lyrics3']['raw']['IND'], $i, 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$fieldnametranslation = array('ETT'=>'title', 'EAR'=>'artist', 'EAL'=>'album', 'INF'=>'comment', 'AUT'=>'author');
|
||||||
|
foreach ($fieldnametranslation as $key => $value) {
|
||||||
|
if (isset($ThisFileInfo['lyrics3']['raw']["$key"])) {
|
||||||
|
$ThisFileInfo['lyrics3']['comments']["$value"] = $ThisFileInfo['lyrics3']['raw']["$key"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!empty($ThisFileInfo['lyrics3']['comments'])) {
|
||||||
|
CopyFormatCommentsToRootComments($ThisFileInfo['lyrics3']['comments'], $ThisFileInfo, true, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($ThisFileInfo['lyrics3']['raw']['IMG'])) {
|
||||||
|
$imagestrings = explode("\r\n", $ThisFileInfo['lyrics3']['raw']['IMG']);
|
||||||
|
foreach ($imagestrings as $key => $imagestring) {
|
||||||
|
if (strpos($imagestring, '||') !== false) {
|
||||||
|
$imagearray = explode('||', $imagestring);
|
||||||
|
$ThisFileInfo['lyrics3']['images']["$key"]['filename'] = $imagearray[0];
|
||||||
|
$ThisFileInfo['lyrics3']['images']["$key"]['description'] = $imagearray[1];
|
||||||
|
$ThisFileInfo['lyrics3']['images']["$key"]['timestamp'] = Lyrics3Timestamp2Seconds($imagearray[2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isset($ThisFileInfo['lyrics3']['raw']['LYR'])) {
|
||||||
|
Lyrics3LyricsTimestampParse($ThisFileInfo);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$ThisFileInfo['error'] .= "\n".'"LYRICS200" expected at '.(ftell($fd) - 11 + $length - 9).' but found "'.substr($rawdata, strlen($rawdata) - 9, 9).'" instead';
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
$ThisFileInfo['error'] .= "\n".'Cannot process Lyrics3 version '.$version.' (only v1 and v2)';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
$ThisFileInfo['error'] .= "\n".'"LYRICSBEGIN" expected at '.(ftell($fd) - 11).' but found "'.substr($rawdata, 0, 11).'" instead';
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($ThisFileInfo['lyrics3'])) {
|
||||||
|
$ThisFileInfo['tags'][] = 'lyrics3';
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function Lyrics3Timestamp2Seconds($rawtimestamp) {
|
||||||
|
if (ereg('^\\[([0-9]{2}):([0-9]{2})\\]$', $rawtimestamp, $regs)) {
|
||||||
|
return (int) (($regs[1] * 60) + $regs[2]);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function Lyrics3LyricsTimestampParse(&$ThisFileInfo) {
|
||||||
|
$lyricsarray = explode("\r\n", $ThisFileInfo['lyrics3']['raw']['LYR']);
|
||||||
|
foreach ($lyricsarray as $key => $lyricline) {
|
||||||
|
$regs = array();
|
||||||
|
unset($thislinetimestamps);
|
||||||
|
while (ereg('^(\\[[0-9]{2}:[0-9]{2}\\])', $lyricline, $regs)) {
|
||||||
|
$thislinetimestamps[] = Lyrics3Timestamp2Seconds($regs[0]);
|
||||||
|
$lyricline = str_replace($regs[0], '', $lyricline);
|
||||||
|
}
|
||||||
|
$notimestamplyricsarray["$key"] = $lyricline;
|
||||||
|
if (isset($thislinetimestamps) && is_array($thislinetimestamps)) {
|
||||||
|
sort($thislinetimestamps);
|
||||||
|
foreach ($thislinetimestamps as $timestampkey => $timestamp) {
|
||||||
|
if (isset($ThisFileInfo['lyrics3']['synchedlyrics'][$timestamp])) {
|
||||||
|
// timestamps only have a 1-second resolution, it's possible that multiple lines
|
||||||
|
// could have the same timestamp, if so, append
|
||||||
|
$ThisFileInfo['lyrics3']['synchedlyrics'][$timestamp] .= "\r\n".$lyricline;
|
||||||
|
} else {
|
||||||
|
$ThisFileInfo['lyrics3']['synchedlyrics'][$timestamp] = $lyricline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$ThisFileInfo['lyrics3']['unsynchedlyrics'] = implode("\r\n", $notimestamplyricsarray);
|
||||||
|
if (isset($ThisFileInfo['lyrics3']['synchedlyrics']) && is_array($ThisFileInfo['lyrics3']['synchedlyrics'])) {
|
||||||
|
ksort($ThisFileInfo['lyrics3']['synchedlyrics']);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
487
livesupport/modules/getid3/var/getid3.midi.php
Normal file
487
livesupport/modules/getid3/var/getid3.midi.php
Normal file
|
@ -0,0 +1,487 @@
|
||||||
|
<?php
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
/// getID3() by James Heinrich <getid3@users.sourceforge.net> //
|
||||||
|
// available at http://getid3.sourceforge.net ///
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
// //
|
||||||
|
// getid3.midi.php - part of getID3() //
|
||||||
|
// See getid3.readme.txt for more details //
|
||||||
|
// //
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
function getMIDIHeaderFilepointer(&$fd, &$ThisFileInfo, $scanwholefile=true) {
|
||||||
|
|
||||||
|
$ThisFileInfo['fileformat'] = 'midi';
|
||||||
|
$ThisFileInfo['audio']['dataformat'] = 'midi';
|
||||||
|
|
||||||
|
fseek($fd, $ThisFileInfo['avdataoffset'], SEEK_SET);
|
||||||
|
$MIDIdata = fread($fd, FREAD_BUFFER_SIZE);
|
||||||
|
$offset = 0;
|
||||||
|
$MIDIheaderID = substr($MIDIdata, $offset, 4); // 'MThd'
|
||||||
|
$offset += 4;
|
||||||
|
$ThisFileInfo['midi']['raw']['headersize'] = BigEndian2Int(substr($MIDIdata, $offset, 4));
|
||||||
|
$offset += 4;
|
||||||
|
$ThisFileInfo['midi']['raw']['fileformat'] = BigEndian2Int(substr($MIDIdata, $offset, 2));
|
||||||
|
$offset += 2;
|
||||||
|
$ThisFileInfo['midi']['raw']['tracks'] = BigEndian2Int(substr($MIDIdata, $offset, 2));
|
||||||
|
$offset += 2;
|
||||||
|
$ThisFileInfo['midi']['raw']['ticksperqnote'] = BigEndian2Int(substr($MIDIdata, $offset, 2));
|
||||||
|
$offset += 2;
|
||||||
|
|
||||||
|
for ($i = 0; $i < $ThisFileInfo['midi']['raw']['tracks']; $i++) {
|
||||||
|
if ((strlen($MIDIdata) - $offset) < 8) {
|
||||||
|
$MIDIdata .= fread($fd, FREAD_BUFFER_SIZE);
|
||||||
|
}
|
||||||
|
$trackID = substr($MIDIdata, $offset, 4);
|
||||||
|
$offset += 4;
|
||||||
|
if ($trackID == 'MTrk') {
|
||||||
|
$tracksize = BigEndian2Int(substr($MIDIdata, $offset, 4));
|
||||||
|
$offset += 4;
|
||||||
|
// $ThisFileInfo['midi']['tracks'][$i]['size'] = $tracksize;
|
||||||
|
$trackdataarray[$i] = substr($MIDIdata, $offset, $tracksize);
|
||||||
|
$offset += $tracksize;
|
||||||
|
} else {
|
||||||
|
$ThisFileInfo['error'] .= "\n".'Expecting "MTrk" at '.$offset.', found '.$trackID.' instead';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($trackdataarray) || !is_array($trackdataarray)) {
|
||||||
|
$ThisFileInfo['error'] .= "\n".'Cannot find MIDI track information';
|
||||||
|
unset($ThisFileInfo['midi']);
|
||||||
|
unset($ThisFileInfo['fileformat']);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($scanwholefile) { // this can take quite a long time, so have the option to bypass it if speed is very important
|
||||||
|
$ThisFileInfo['midi']['totalticks'] = 0;
|
||||||
|
$ThisFileInfo['playtime_seconds'] = 0;
|
||||||
|
$CurrentMicroSecondsPerBeat = 500000; // 120 beats per minute; 60,000,000 microseconds per minute -> 500,000 microseconds per beat
|
||||||
|
$CurrentBeatsPerMinute = 120; // 120 beats per minute; 60,000,000 microseconds per minute -> 500,000 microseconds per beat
|
||||||
|
|
||||||
|
foreach ($trackdataarray as $tracknumber => $trackdata) {
|
||||||
|
|
||||||
|
$eventsoffset = 0;
|
||||||
|
$LastIssuedMIDIcommand = 0;
|
||||||
|
$LastIssuedMIDIchannel = 0;
|
||||||
|
$CumulativeDeltaTime = 0;
|
||||||
|
$TicksAtCurrentBPM = 0;
|
||||||
|
while ($eventsoffset < strlen($trackdata)) {
|
||||||
|
$eventid = 0;
|
||||||
|
if (isset($MIDIevents[$tracknumber]) && is_array($MIDIevents[$tracknumber])) {
|
||||||
|
$eventid = count($MIDIevents[$tracknumber]);
|
||||||
|
}
|
||||||
|
$deltatime = 0;
|
||||||
|
for ($i=0;$i<4;$i++) {
|
||||||
|
$deltatimebyte = ord(substr($trackdata, $eventsoffset++, 1));
|
||||||
|
$deltatime = ($deltatime << 7) + ($deltatimebyte & 0x7F);
|
||||||
|
if ($deltatimebyte & 0x80) {
|
||||||
|
// another byte follows
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$CumulativeDeltaTime += $deltatime;
|
||||||
|
$TicksAtCurrentBPM += $deltatime;
|
||||||
|
$MIDIevents[$tracknumber][$eventid]['deltatime'] = $deltatime;
|
||||||
|
$MIDI_event_channel = ord(substr($trackdata, $eventsoffset++, 1));
|
||||||
|
if ($MIDI_event_channel & 0x80) {
|
||||||
|
// OK, normal event - MIDI command has MSB set
|
||||||
|
$LastIssuedMIDIcommand = $MIDI_event_channel >> 4;
|
||||||
|
$LastIssuedMIDIchannel = $MIDI_event_channel & 0x0F;
|
||||||
|
} else {
|
||||||
|
// running event - assume last command
|
||||||
|
$eventsoffset--;
|
||||||
|
}
|
||||||
|
$MIDIevents[$tracknumber][$eventid]['eventid'] = $LastIssuedMIDIcommand;
|
||||||
|
$MIDIevents[$tracknumber][$eventid]['channel'] = $LastIssuedMIDIchannel;
|
||||||
|
if ($MIDIevents[$tracknumber][$eventid]['eventid'] == 0x8) { // Note off (key is released)
|
||||||
|
|
||||||
|
$notenumber = ord(substr($trackdata, $eventsoffset++, 1));
|
||||||
|
$velocity = ord(substr($trackdata, $eventsoffset++, 1));
|
||||||
|
|
||||||
|
} elseif ($MIDIevents[$tracknumber][$eventid]['eventid'] == 0x9) { // Note on (key is pressed)
|
||||||
|
|
||||||
|
$notenumber = ord(substr($trackdata, $eventsoffset++, 1));
|
||||||
|
$velocity = ord(substr($trackdata, $eventsoffset++, 1));
|
||||||
|
|
||||||
|
} elseif ($MIDIevents[$tracknumber][$eventid]['eventid'] == 0xA) { // Key after-touch
|
||||||
|
|
||||||
|
$notenumber = ord(substr($trackdata, $eventsoffset++, 1));
|
||||||
|
$velocity = ord(substr($trackdata, $eventsoffset++, 1));
|
||||||
|
|
||||||
|
} elseif ($MIDIevents[$tracknumber][$eventid]['eventid'] == 0xB) { // Control Change
|
||||||
|
|
||||||
|
$controllernum = ord(substr($trackdata, $eventsoffset++, 1));
|
||||||
|
$newvalue = ord(substr($trackdata, $eventsoffset++, 1));
|
||||||
|
|
||||||
|
} elseif ($MIDIevents[$tracknumber][$eventid]['eventid'] == 0xC) { // Program (patch) change
|
||||||
|
|
||||||
|
$newprogramnum = ord(substr($trackdata, $eventsoffset++, 1));
|
||||||
|
|
||||||
|
$ThisFileInfo['midi']['raw']['track'][$tracknumber]['instrumentid'] = $newprogramnum;
|
||||||
|
if ($tracknumber == 10) {
|
||||||
|
$ThisFileInfo['midi']['raw']['track'][$tracknumber]['instrument'] = GeneralMIDIpercussionLookup($newprogramnum);
|
||||||
|
} else {
|
||||||
|
$ThisFileInfo['midi']['raw']['track'][$tracknumber]['instrument'] = GeneralMIDIinstrumentLookup($newprogramnum);
|
||||||
|
}
|
||||||
|
|
||||||
|
} elseif ($MIDIevents[$tracknumber][$eventid]['eventid'] == 0xD) { // Channel after-touch
|
||||||
|
|
||||||
|
$channelnumber = ord(substr($trackdata, $eventsoffset++, 1));
|
||||||
|
|
||||||
|
} elseif ($MIDIevents[$tracknumber][$eventid]['eventid'] == 0xE) { // Pitch wheel change (2000H is normal or no change)
|
||||||
|
|
||||||
|
$changeLSB = ord(substr($trackdata, $eventsoffset++, 1));
|
||||||
|
$changeMSB = ord(substr($trackdata, $eventsoffset++, 1));
|
||||||
|
$pitchwheelchange = (($changeMSB & 0x7F) << 7) & ($changeLSB & 0x7F);
|
||||||
|
|
||||||
|
} elseif (($MIDIevents[$tracknumber][$eventid]['eventid'] == 0xF) && ($MIDIevents[$tracknumber][$eventid]['channel'] == 0xF)) {
|
||||||
|
|
||||||
|
$METAeventCommand = ord(substr($trackdata, $eventsoffset++, 1));
|
||||||
|
$METAeventLength = ord(substr($trackdata, $eventsoffset++, 1));
|
||||||
|
$METAeventData = substr($trackdata, $eventsoffset, $METAeventLength);
|
||||||
|
$eventsoffset += $METAeventLength;
|
||||||
|
switch ($METAeventCommand) {
|
||||||
|
case 0x00: // Set track sequence number
|
||||||
|
$track_sequence_number = BigEndian2Int(substr($METAeventData, 0, $METAeventLength));
|
||||||
|
//$ThisFileInfo['midi']['raw']['events'][$tracknumber][$eventid]['seqno'] = $track_sequence_number;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x01: // Text: generic
|
||||||
|
$text_generic = substr($METAeventData, 0, $METAeventLength);
|
||||||
|
//$ThisFileInfo['midi']['raw']['events'][$tracknumber][$eventid]['text'] = $text_generic;
|
||||||
|
if (empty($ThisFileInfo['midi']['comments']['comment'])) {
|
||||||
|
$ThisFileInfo['midi']['comments']['comment'] = '';
|
||||||
|
}
|
||||||
|
$ThisFileInfo['midi']['comments']['comment'] .= $text_generic."\n";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x02: // Text: copyright
|
||||||
|
$text_copyright = substr($METAeventData, 0, $METAeventLength);
|
||||||
|
//$ThisFileInfo['midi']['raw']['events'][$tracknumber][$eventid]['copyright'] = $text_copyright;
|
||||||
|
if (empty($ThisFileInfo['midi']['comments']['copyright'])) {
|
||||||
|
$ThisFileInfo['midi']['comments']['copyright'] = '';
|
||||||
|
}
|
||||||
|
$ThisFileInfo['midi']['comments']['copyright'] = $text_copyright."\n";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x03: // Text: track name
|
||||||
|
$text_trackname = substr($METAeventData, 0, $METAeventLength);
|
||||||
|
$ThisFileInfo['midi']['raw']['track'][$tracknumber]['name'] = $text_trackname;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x04: // Text: track instrument name
|
||||||
|
$text_instrument = substr($METAeventData, 0, $METAeventLength);
|
||||||
|
//$ThisFileInfo['midi']['raw']['events'][$tracknumber][$eventid]['instrument'] = $text_instrument;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x05: // Text: lyric
|
||||||
|
$text_lyric = substr($METAeventData, 0, $METAeventLength);
|
||||||
|
//$ThisFileInfo['midi']['raw']['events'][$tracknumber][$eventid]['lyric'] = $text_lyric;
|
||||||
|
if (!isset($ThisFileInfo['midi']['lyric'])) {
|
||||||
|
$ThisFileInfo['midi']['lyric'] = '';
|
||||||
|
}
|
||||||
|
$ThisFileInfo['midi']['lyric'] .= $text_lyric."\n";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x06: // Text: marker
|
||||||
|
$text_marker = substr($METAeventData, 0, $METAeventLength);
|
||||||
|
//$ThisFileInfo['midi']['raw']['events'][$tracknumber][$eventid]['marker'] = $text_marker;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x07: // Text: cue point
|
||||||
|
$text_cuepoint = substr($METAeventData, 0, $METAeventLength);
|
||||||
|
//$ThisFileInfo['midi']['raw']['events'][$tracknumber][$eventid]['cuepoint'] = $text_cuepoint;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x2F: // End Of Track
|
||||||
|
//$ThisFileInfo['midi']['raw']['events'][$tracknumber][$eventid]['EOT'] = $CumulativeDeltaTime;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x51: // Tempo: microseconds / quarter note
|
||||||
|
$CurrentMicroSecondsPerBeat = BigEndian2Int(substr($METAeventData, 0, $METAeventLength));
|
||||||
|
if ($CurrentMicroSecondsPerBeat == 0) {
|
||||||
|
$ThisFileInfo['error'] .= "\n".'Corrupt MIDI file: CurrentMicroSecondsPerBeat == zero';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$ThisFileInfo['midi']['raw']['events'][$tracknumber][$CumulativeDeltaTime]['us_qnote'] = $CurrentMicroSecondsPerBeat;
|
||||||
|
$CurrentBeatsPerMinute = (1000000 / $CurrentMicroSecondsPerBeat) * 60;
|
||||||
|
$MicroSecondsPerQuarterNoteAfter[$CumulativeDeltaTime] = $CurrentMicroSecondsPerBeat;
|
||||||
|
$TicksAtCurrentBPM = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x58: // Time signature
|
||||||
|
$timesig_numerator = BigEndian2Int($METAeventData{0});
|
||||||
|
$timesig_denominator = pow(2, BigEndian2Int($METAeventData{1})); // $02 -> x/4, $03 -> x/8, etc
|
||||||
|
$timesig_32inqnote = BigEndian2Int($METAeventData{2}); // number of 32nd notes to the quarter note
|
||||||
|
//$ThisFileInfo['midi']['raw']['events'][$tracknumber][$eventid]['timesig_32inqnote'] = $timesig_32inqnote;
|
||||||
|
//$ThisFileInfo['midi']['raw']['events'][$tracknumber][$eventid]['timesig_numerator'] = $timesig_numerator;
|
||||||
|
//$ThisFileInfo['midi']['raw']['events'][$tracknumber][$eventid]['timesig_denominator'] = $timesig_denominator;
|
||||||
|
//$ThisFileInfo['midi']['raw']['events'][$tracknumber][$eventid]['timesig_text'] = $timesig_numerator.'/'.$timesig_denominator;
|
||||||
|
$ThisFileInfo['midi']['timesignature'][] = $timesig_numerator.'/'.$timesig_denominator;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x59: // Keysignature
|
||||||
|
$keysig_sharpsflats = BigEndian2Int($METAeventData{0});
|
||||||
|
if ($keysig_sharpsflats & 0x80) {
|
||||||
|
// (-7 -> 7 flats, 0 ->key of C, 7 -> 7 sharps)
|
||||||
|
$keysig_sharpsflats -= 256;
|
||||||
|
}
|
||||||
|
|
||||||
|
$keysig_majorminor = BigEndian2Int($METAeventData{1}); // 0 -> major, 1 -> minor
|
||||||
|
$keysigs = array(-7=>'Cb', -6=>'Gb', -5=>'Db', -4=>'Ab', -3=>'Eb', -2=>'Bb', -1=>'F', 0=>'C', 1=>'G', 2=>'D', 3=>'A', 4=>'E', 5=>'B', 6=>'F#', 7=>'C#');
|
||||||
|
//$ThisFileInfo['midi']['raw']['events'][$tracknumber][$eventid]['keysig_sharps'] = (($keysig_sharpsflats > 0) ? abs($keysig_sharpsflats) : 0);
|
||||||
|
//$ThisFileInfo['midi']['raw']['events'][$tracknumber][$eventid]['keysig_flats'] = (($keysig_sharpsflats < 0) ? abs($keysig_sharpsflats) : 0);
|
||||||
|
//$ThisFileInfo['midi']['raw']['events'][$tracknumber][$eventid]['keysig_minor'] = (bool) $keysig_majorminor;
|
||||||
|
//$ThisFileInfo['midi']['raw']['events'][$tracknumber][$eventid]['keysig_text'] = $keysigs[$keysig_sharpsflats].' '.($ThisFileInfo['midi']['raw']['events'][$tracknumber][$eventid]['keysig_minor'] ? 'minor' : 'major');
|
||||||
|
|
||||||
|
// $keysigs[$keysig_sharpsflats] gets an int key (correct) - $keysigs["$keysig_sharpsflats"] gets a string key (incorrect)
|
||||||
|
$ThisFileInfo['midi']['keysignature'][] = $keysigs[$keysig_sharpsflats].' '.((bool) $keysig_majorminor ? 'minor' : 'major');
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x7F: // Sequencer specific information
|
||||||
|
$custom_data = substr($METAeventData, 0, $METAeventLength);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
$ThisFileInfo['warning'] .= "\n".'Unhandled META Event Command: '.$METAeventCommand;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
$ThisFileInfo['warning'] .= "\n".'Unhandled MIDI Event ID: '.$MIDIevents[$tracknumber][$eventid]['eventid'];
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($tracknumber > 0) {
|
||||||
|
$ThisFileInfo['midi']['totalticks'] = max($ThisFileInfo['midi']['totalticks'], $CumulativeDeltaTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$previoustickoffset = 0;
|
||||||
|
foreach ($MicroSecondsPerQuarterNoteAfter as $tickoffset => $microsecondsperbeat) {
|
||||||
|
if ($ThisFileInfo['midi']['totalticks'] > $tickoffset) {
|
||||||
|
|
||||||
|
if ($ThisFileInfo['midi']['raw']['ticksperqnote'] == 0) {
|
||||||
|
$ThisFileInfo['error'] .= "\n".'Corrupt MIDI file: ticksperqnote == zero';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$ThisFileInfo['playtime_seconds'] += (($tickoffset - $previoustickoffset) / $ThisFileInfo['midi']['raw']['ticksperqnote']) * ($microsecondsperbeat / 1000000);
|
||||||
|
$previoustickoffset = $tickoffset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($ThisFileInfo['midi']['totalticks'] > $previoustickoffset) {
|
||||||
|
|
||||||
|
if ($ThisFileInfo['midi']['raw']['ticksperqnote'] == 0) {
|
||||||
|
$ThisFileInfo['error'] .= "\n".'Corrupt MIDI file: ticksperqnote == zero';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$ThisFileInfo['playtime_seconds'] += (($ThisFileInfo['midi']['totalticks'] - $previoustickoffset) / $ThisFileInfo['midi']['raw']['ticksperqnote']) * ($microsecondsperbeat / 1000000);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MIDI tags have highest priority
|
||||||
|
if (!empty($ThisFileInfo['midi']['comments'])) {
|
||||||
|
CopyFormatCommentsToRootComments($ThisFileInfo['midi']['comments'], $ThisFileInfo, true, true, true);
|
||||||
|
// add tag to array of tags
|
||||||
|
$ThisFileInfo['tags'][] = 'midi';
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function GeneralMIDIinstrumentLookup($instrumentid) {
|
||||||
|
static $GeneralMIDIinstrumentLookup = array();
|
||||||
|
if (empty($GeneralMIDIinstrumentLookup)) {
|
||||||
|
$GeneralMIDIinstrumentLookup[0] = 'Acoustic Grand';
|
||||||
|
$GeneralMIDIinstrumentLookup[1] = 'Bright Acoustic';
|
||||||
|
$GeneralMIDIinstrumentLookup[2] = 'Electric Grand';
|
||||||
|
$GeneralMIDIinstrumentLookup[3] = 'Honky-Tonk';
|
||||||
|
$GeneralMIDIinstrumentLookup[4] = 'Electric Piano 1';
|
||||||
|
$GeneralMIDIinstrumentLookup[5] = 'Electric Piano 2';
|
||||||
|
$GeneralMIDIinstrumentLookup[6] = 'Harpsichord';
|
||||||
|
$GeneralMIDIinstrumentLookup[7] = 'Clav';
|
||||||
|
$GeneralMIDIinstrumentLookup[8] = 'Celesta';
|
||||||
|
$GeneralMIDIinstrumentLookup[9] = 'Glockenspiel';
|
||||||
|
$GeneralMIDIinstrumentLookup[10] = 'Music Box';
|
||||||
|
$GeneralMIDIinstrumentLookup[11] = 'Vibraphone';
|
||||||
|
$GeneralMIDIinstrumentLookup[12] = 'Marimba';
|
||||||
|
$GeneralMIDIinstrumentLookup[13] = 'Xylophone';
|
||||||
|
$GeneralMIDIinstrumentLookup[14] = 'Tubular Bells';
|
||||||
|
$GeneralMIDIinstrumentLookup[15] = 'Dulcimer';
|
||||||
|
$GeneralMIDIinstrumentLookup[16] = 'Drawbar Organ';
|
||||||
|
$GeneralMIDIinstrumentLookup[17] = 'Percussive Organ';
|
||||||
|
$GeneralMIDIinstrumentLookup[18] = 'Rock Organ';
|
||||||
|
$GeneralMIDIinstrumentLookup[19] = 'Church Organ';
|
||||||
|
$GeneralMIDIinstrumentLookup[20] = 'Reed Organ';
|
||||||
|
$GeneralMIDIinstrumentLookup[21] = 'Accordian';
|
||||||
|
$GeneralMIDIinstrumentLookup[22] = 'Harmonica';
|
||||||
|
$GeneralMIDIinstrumentLookup[23] = 'Tango Accordian';
|
||||||
|
$GeneralMIDIinstrumentLookup[24] = 'Acoustic Guitar (nylon)';
|
||||||
|
$GeneralMIDIinstrumentLookup[25] = 'Acoustic Guitar (steel)';
|
||||||
|
$GeneralMIDIinstrumentLookup[26] = 'Electric Guitar (jazz)';
|
||||||
|
$GeneralMIDIinstrumentLookup[27] = 'Electric Guitar (clean)';
|
||||||
|
$GeneralMIDIinstrumentLookup[28] = 'Electric Guitar (muted)';
|
||||||
|
$GeneralMIDIinstrumentLookup[29] = 'Overdriven Guitar';
|
||||||
|
$GeneralMIDIinstrumentLookup[30] = 'Distortion Guitar';
|
||||||
|
$GeneralMIDIinstrumentLookup[31] = 'Guitar Harmonics';
|
||||||
|
$GeneralMIDIinstrumentLookup[32] = 'Acoustic Bass';
|
||||||
|
$GeneralMIDIinstrumentLookup[33] = 'Electric Bass (finger)';
|
||||||
|
$GeneralMIDIinstrumentLookup[34] = 'Electric Bass (pick)';
|
||||||
|
$GeneralMIDIinstrumentLookup[35] = 'Fretless Bass';
|
||||||
|
$GeneralMIDIinstrumentLookup[36] = 'Slap Bass 1';
|
||||||
|
$GeneralMIDIinstrumentLookup[37] = 'Slap Bass 2';
|
||||||
|
$GeneralMIDIinstrumentLookup[38] = 'Synth Bass 1';
|
||||||
|
$GeneralMIDIinstrumentLookup[39] = 'Synth Bass 2';
|
||||||
|
$GeneralMIDIinstrumentLookup[40] = 'Violin';
|
||||||
|
$GeneralMIDIinstrumentLookup[41] = 'Viola';
|
||||||
|
$GeneralMIDIinstrumentLookup[42] = 'Cello';
|
||||||
|
$GeneralMIDIinstrumentLookup[43] = 'Contrabass';
|
||||||
|
$GeneralMIDIinstrumentLookup[44] = 'Tremolo Strings';
|
||||||
|
$GeneralMIDIinstrumentLookup[45] = 'Pizzicato Strings';
|
||||||
|
$GeneralMIDIinstrumentLookup[46] = 'Orchestral Strings';
|
||||||
|
$GeneralMIDIinstrumentLookup[47] = 'Timpani';
|
||||||
|
$GeneralMIDIinstrumentLookup[48] = 'String Ensemble 1';
|
||||||
|
$GeneralMIDIinstrumentLookup[49] = 'String Ensemble 2';
|
||||||
|
$GeneralMIDIinstrumentLookup[50] = 'SynthStrings 1';
|
||||||
|
$GeneralMIDIinstrumentLookup[51] = 'SynthStrings 2';
|
||||||
|
$GeneralMIDIinstrumentLookup[52] = 'Choir Aahs';
|
||||||
|
$GeneralMIDIinstrumentLookup[53] = 'Voice Oohs';
|
||||||
|
$GeneralMIDIinstrumentLookup[54] = 'Synth Voice';
|
||||||
|
$GeneralMIDIinstrumentLookup[55] = 'Orchestra Hit';
|
||||||
|
$GeneralMIDIinstrumentLookup[56] = 'Trumpet';
|
||||||
|
$GeneralMIDIinstrumentLookup[57] = 'Trombone';
|
||||||
|
$GeneralMIDIinstrumentLookup[58] = 'Tuba';
|
||||||
|
$GeneralMIDIinstrumentLookup[59] = 'Muted Trumpet';
|
||||||
|
$GeneralMIDIinstrumentLookup[60] = 'French Horn';
|
||||||
|
$GeneralMIDIinstrumentLookup[61] = 'Brass Section';
|
||||||
|
$GeneralMIDIinstrumentLookup[62] = 'SynthBrass 1';
|
||||||
|
$GeneralMIDIinstrumentLookup[63] = 'SynthBrass 2';
|
||||||
|
$GeneralMIDIinstrumentLookup[64] = 'Soprano Sax';
|
||||||
|
$GeneralMIDIinstrumentLookup[65] = 'Alto Sax';
|
||||||
|
$GeneralMIDIinstrumentLookup[66] = 'Tenor Sax';
|
||||||
|
$GeneralMIDIinstrumentLookup[67] = 'Baritone Sax';
|
||||||
|
$GeneralMIDIinstrumentLookup[68] = 'Oboe';
|
||||||
|
$GeneralMIDIinstrumentLookup[69] = 'English Horn';
|
||||||
|
$GeneralMIDIinstrumentLookup[70] = 'Bassoon';
|
||||||
|
$GeneralMIDIinstrumentLookup[71] = 'Clarinet';
|
||||||
|
$GeneralMIDIinstrumentLookup[72] = 'Piccolo';
|
||||||
|
$GeneralMIDIinstrumentLookup[73] = 'Flute';
|
||||||
|
$GeneralMIDIinstrumentLookup[74] = 'Recorder';
|
||||||
|
$GeneralMIDIinstrumentLookup[75] = 'Pan Flute';
|
||||||
|
$GeneralMIDIinstrumentLookup[76] = 'Blown Bottle';
|
||||||
|
$GeneralMIDIinstrumentLookup[77] = 'Shakuhachi';
|
||||||
|
$GeneralMIDIinstrumentLookup[78] = 'Whistle';
|
||||||
|
$GeneralMIDIinstrumentLookup[79] = 'Ocarina';
|
||||||
|
$GeneralMIDIinstrumentLookup[80] = 'Lead 1 (square)';
|
||||||
|
$GeneralMIDIinstrumentLookup[81] = 'Lead 2 (sawtooth)';
|
||||||
|
$GeneralMIDIinstrumentLookup[82] = 'Lead 3 (calliope)';
|
||||||
|
$GeneralMIDIinstrumentLookup[83] = 'Lead 4 (chiff)';
|
||||||
|
$GeneralMIDIinstrumentLookup[84] = 'Lead 5 (charang)';
|
||||||
|
$GeneralMIDIinstrumentLookup[85] = 'Lead 6 (voice)';
|
||||||
|
$GeneralMIDIinstrumentLookup[86] = 'Lead 7 (fifths)';
|
||||||
|
$GeneralMIDIinstrumentLookup[87] = 'Lead 8 (bass + lead)';
|
||||||
|
$GeneralMIDIinstrumentLookup[88] = 'Pad 1 (new age)';
|
||||||
|
$GeneralMIDIinstrumentLookup[89] = 'Pad 2 (warm)';
|
||||||
|
$GeneralMIDIinstrumentLookup[90] = 'Pad 3 (polysynth)';
|
||||||
|
$GeneralMIDIinstrumentLookup[91] = 'Pad 4 (choir)';
|
||||||
|
$GeneralMIDIinstrumentLookup[92] = 'Pad 5 (bowed)';
|
||||||
|
$GeneralMIDIinstrumentLookup[93] = 'Pad 6 (metallic)';
|
||||||
|
$GeneralMIDIinstrumentLookup[94] = 'Pad 7 (halo)';
|
||||||
|
$GeneralMIDIinstrumentLookup[95] = 'Pad 8 (sweep)';
|
||||||
|
$GeneralMIDIinstrumentLookup[96] = 'FX 1 (rain)';
|
||||||
|
$GeneralMIDIinstrumentLookup[97] = 'FX 2 (soundtrack)';
|
||||||
|
$GeneralMIDIinstrumentLookup[98] = 'FX 3 (crystal)';
|
||||||
|
$GeneralMIDIinstrumentLookup[99] = 'FX 4 (atmosphere)';
|
||||||
|
$GeneralMIDIinstrumentLookup[100] = 'FX 5 (brightness)';
|
||||||
|
$GeneralMIDIinstrumentLookup[101] = 'FX 6 (goblins)';
|
||||||
|
$GeneralMIDIinstrumentLookup[102] = 'FX 7 (echoes)';
|
||||||
|
$GeneralMIDIinstrumentLookup[103] = 'FX 8 (sci-fi)';
|
||||||
|
$GeneralMIDIinstrumentLookup[104] = 'Sitar';
|
||||||
|
$GeneralMIDIinstrumentLookup[105] = 'Banjo';
|
||||||
|
$GeneralMIDIinstrumentLookup[106] = 'Shamisen';
|
||||||
|
$GeneralMIDIinstrumentLookup[107] = 'Koto';
|
||||||
|
$GeneralMIDIinstrumentLookup[108] = 'Kalimba';
|
||||||
|
$GeneralMIDIinstrumentLookup[109] = 'Bagpipe';
|
||||||
|
$GeneralMIDIinstrumentLookup[110] = 'Fiddle';
|
||||||
|
$GeneralMIDIinstrumentLookup[111] = 'Shanai';
|
||||||
|
$GeneralMIDIinstrumentLookup[112] = 'Tinkle Bell';
|
||||||
|
$GeneralMIDIinstrumentLookup[113] = 'Agogo';
|
||||||
|
$GeneralMIDIinstrumentLookup[114] = 'Steel Drums';
|
||||||
|
$GeneralMIDIinstrumentLookup[115] = 'Woodblock';
|
||||||
|
$GeneralMIDIinstrumentLookup[116] = 'Taiko Drum';
|
||||||
|
$GeneralMIDIinstrumentLookup[117] = 'Melodic Tom';
|
||||||
|
$GeneralMIDIinstrumentLookup[118] = 'Synth Drum';
|
||||||
|
$GeneralMIDIinstrumentLookup[119] = 'Reverse Cymbal';
|
||||||
|
$GeneralMIDIinstrumentLookup[120] = 'Guitar Fret Noise';
|
||||||
|
$GeneralMIDIinstrumentLookup[121] = 'Breath Noise';
|
||||||
|
$GeneralMIDIinstrumentLookup[122] = 'Seashore';
|
||||||
|
$GeneralMIDIinstrumentLookup[123] = 'Bird Tweet';
|
||||||
|
$GeneralMIDIinstrumentLookup[124] = 'Telephone Ring';
|
||||||
|
$GeneralMIDIinstrumentLookup[125] = 'Helicopter';
|
||||||
|
$GeneralMIDIinstrumentLookup[126] = 'Applause';
|
||||||
|
$GeneralMIDIinstrumentLookup[127] = 'Gunshot';
|
||||||
|
}
|
||||||
|
|
||||||
|
return (isset($GeneralMIDIinstrumentLookup[$instrumentid]) ? $GeneralMIDIinstrumentLookup[$instrumentid] : '');
|
||||||
|
}
|
||||||
|
|
||||||
|
function GeneralMIDIpercussionLookup($instrumentid) {
|
||||||
|
static $GeneralMIDIpercussionLookup = array();
|
||||||
|
if (empty($GeneralMIDIpercussionLookup)) {
|
||||||
|
$GeneralMIDIpercussionLookup[35] = 'Acoustic Bass Drum';
|
||||||
|
$GeneralMIDIpercussionLookup[36] = 'Bass Drum 1';
|
||||||
|
$GeneralMIDIpercussionLookup[37] = 'Side Stick';
|
||||||
|
$GeneralMIDIpercussionLookup[38] = 'Acoustic Snare';
|
||||||
|
$GeneralMIDIpercussionLookup[39] = 'Hand Clap';
|
||||||
|
$GeneralMIDIpercussionLookup[40] = 'Electric Snare';
|
||||||
|
$GeneralMIDIpercussionLookup[41] = 'Low Floor Tom';
|
||||||
|
$GeneralMIDIpercussionLookup[42] = 'Closed Hi-Hat';
|
||||||
|
$GeneralMIDIpercussionLookup[43] = 'High Floor Tom';
|
||||||
|
$GeneralMIDIpercussionLookup[44] = 'Pedal Hi-Hat';
|
||||||
|
$GeneralMIDIpercussionLookup[45] = 'Low Tom';
|
||||||
|
$GeneralMIDIpercussionLookup[46] = 'Open Hi-Hat';
|
||||||
|
$GeneralMIDIpercussionLookup[47] = 'Low-Mid Tom';
|
||||||
|
$GeneralMIDIpercussionLookup[48] = 'Hi-Mid Tom';
|
||||||
|
$GeneralMIDIpercussionLookup[49] = 'Crash Cymbal 1';
|
||||||
|
$GeneralMIDIpercussionLookup[50] = 'High Tom';
|
||||||
|
$GeneralMIDIpercussionLookup[51] = 'Ride Cymbal 1';
|
||||||
|
$GeneralMIDIpercussionLookup[52] = 'Chinese Cymbal';
|
||||||
|
$GeneralMIDIpercussionLookup[53] = 'Ride Bell';
|
||||||
|
$GeneralMIDIpercussionLookup[54] = 'Tambourine';
|
||||||
|
$GeneralMIDIpercussionLookup[55] = 'Splash Cymbal';
|
||||||
|
$GeneralMIDIpercussionLookup[56] = 'Cowbell';
|
||||||
|
$GeneralMIDIpercussionLookup[57] = 'Crash Cymbal 2';
|
||||||
|
$GeneralMIDIpercussionLookup[59] = 'Ride Cymbal 2';
|
||||||
|
$GeneralMIDIpercussionLookup[60] = 'Hi Bongo';
|
||||||
|
$GeneralMIDIpercussionLookup[61] = 'Low Bongo';
|
||||||
|
$GeneralMIDIpercussionLookup[62] = 'Mute Hi Conga';
|
||||||
|
$GeneralMIDIpercussionLookup[63] = 'Open Hi Conga';
|
||||||
|
$GeneralMIDIpercussionLookup[64] = 'Low Conga';
|
||||||
|
$GeneralMIDIpercussionLookup[65] = 'High Timbale';
|
||||||
|
$GeneralMIDIpercussionLookup[66] = 'Low Timbale';
|
||||||
|
$GeneralMIDIpercussionLookup[67] = 'High Agogo';
|
||||||
|
$GeneralMIDIpercussionLookup[68] = 'Low Agogo';
|
||||||
|
$GeneralMIDIpercussionLookup[69] = 'Cabasa';
|
||||||
|
$GeneralMIDIpercussionLookup[70] = 'Maracas';
|
||||||
|
$GeneralMIDIpercussionLookup[71] = 'Short Whistle';
|
||||||
|
$GeneralMIDIpercussionLookup[72] = 'Long Whistle';
|
||||||
|
$GeneralMIDIpercussionLookup[73] = 'Short Guiro';
|
||||||
|
$GeneralMIDIpercussionLookup[74] = 'Long Guiro';
|
||||||
|
$GeneralMIDIpercussionLookup[75] = 'Claves';
|
||||||
|
$GeneralMIDIpercussionLookup[76] = 'Hi Wood Block';
|
||||||
|
$GeneralMIDIpercussionLookup[77] = 'Low Wood Block';
|
||||||
|
$GeneralMIDIpercussionLookup[78] = 'Mute Cuica';
|
||||||
|
$GeneralMIDIpercussionLookup[79] = 'Open Cuica';
|
||||||
|
$GeneralMIDIpercussionLookup[80] = 'Mute Triangle';
|
||||||
|
$GeneralMIDIpercussionLookup[81] = 'Open Triangle';
|
||||||
|
}
|
||||||
|
|
||||||
|
return (isset($GeneralMIDIpercussionLookup[$instrumentid]) ? $GeneralMIDIpercussionLookup[$instrumentid] : '');
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
112
livesupport/modules/getid3/var/getid3.monkey.php
Normal file
112
livesupport/modules/getid3/var/getid3.monkey.php
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
<?php
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
/// getID3() by James Heinrich <getid3@users.sourceforge.net> //
|
||||||
|
// available at http://getid3.sourceforge.net ///
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
// //
|
||||||
|
// getid3.monkey.php - part of getID3() //
|
||||||
|
// See getid3.readme.txt for more details //
|
||||||
|
// //
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
function getMonkeysAudioHeaderFilepointer(&$fd, &$ThisFileInfo) {
|
||||||
|
// based loosely on code from TMonkey by Jurgen Faul
|
||||||
|
// jfaul@gmx.de http://jfaul.de/atl
|
||||||
|
|
||||||
|
$ThisFileInfo['fileformat'] = 'mac';
|
||||||
|
$ThisFileInfo['audio']['dataformat'] = 'mac';
|
||||||
|
$ThisFileInfo['audio']['bitrate_mode'] = 'vbr';
|
||||||
|
|
||||||
|
fseek($fd, $ThisFileInfo['avdataoffset'], SEEK_SET);
|
||||||
|
$MACheaderData = fread($fd, 40);
|
||||||
|
|
||||||
|
$ThisFileInfo['monkeys_audio']['raw']['header_tag'] = substr($MACheaderData, 0, 4);
|
||||||
|
$ThisFileInfo['monkeys_audio']['raw']['nVersion'] = LittleEndian2Int(substr($MACheaderData, 4, 2));
|
||||||
|
$ThisFileInfo['monkeys_audio']['raw']['nCompressionLevel'] = LittleEndian2Int(substr($MACheaderData, 6, 2));
|
||||||
|
$ThisFileInfo['monkeys_audio']['raw']['nFormatFlags'] = LittleEndian2Int(substr($MACheaderData, 8, 2));
|
||||||
|
$ThisFileInfo['monkeys_audio']['raw']['nChannels'] = LittleEndian2Int(substr($MACheaderData, 10, 2));
|
||||||
|
$ThisFileInfo['monkeys_audio']['raw']['nSampleRate'] = LittleEndian2Int(substr($MACheaderData, 12, 4));
|
||||||
|
$ThisFileInfo['monkeys_audio']['raw']['nWAVHeaderBytes'] = LittleEndian2Int(substr($MACheaderData, 16, 4));
|
||||||
|
$ThisFileInfo['monkeys_audio']['raw']['nWAVTerminatingBytes'] = LittleEndian2Int(substr($MACheaderData, 20, 4));
|
||||||
|
$ThisFileInfo['monkeys_audio']['raw']['nTotalFrames'] = LittleEndian2Int(substr($MACheaderData, 24, 4));
|
||||||
|
$ThisFileInfo['monkeys_audio']['raw']['nFinalFrameSamples'] = LittleEndian2Int(substr($MACheaderData, 28, 4));
|
||||||
|
$ThisFileInfo['monkeys_audio']['raw']['nPeakLevel'] = LittleEndian2Int(substr($MACheaderData, 32, 4));
|
||||||
|
$ThisFileInfo['monkeys_audio']['raw']['nSeekElements'] = LittleEndian2Int(substr($MACheaderData, 38, 2));
|
||||||
|
|
||||||
|
$ThisFileInfo['monkeys_audio']['flags']['8-bit'] = (bool) ($ThisFileInfo['monkeys_audio']['raw']['nFormatFlags'] & 0x0001);
|
||||||
|
$ThisFileInfo['monkeys_audio']['flags']['crc-32'] = (bool) ($ThisFileInfo['monkeys_audio']['raw']['nFormatFlags'] & 0x0002);
|
||||||
|
$ThisFileInfo['monkeys_audio']['flags']['peak_level'] = (bool) ($ThisFileInfo['monkeys_audio']['raw']['nFormatFlags'] & 0x0004);
|
||||||
|
$ThisFileInfo['monkeys_audio']['flags']['24-bit'] = (bool) ($ThisFileInfo['monkeys_audio']['raw']['nFormatFlags'] & 0x0008);
|
||||||
|
$ThisFileInfo['monkeys_audio']['flags']['seek_elements'] = (bool) ($ThisFileInfo['monkeys_audio']['raw']['nFormatFlags'] & 0x0010);
|
||||||
|
$ThisFileInfo['monkeys_audio']['flags']['no_wav_header'] = (bool) ($ThisFileInfo['monkeys_audio']['raw']['nFormatFlags'] & 0x0020);
|
||||||
|
$ThisFileInfo['monkeys_audio']['version'] = $ThisFileInfo['monkeys_audio']['raw']['nVersion'] / 1000;
|
||||||
|
$ThisFileInfo['monkeys_audio']['compression'] = MonkeyCompressionLevelNameLookup($ThisFileInfo['monkeys_audio']['raw']['nCompressionLevel']);
|
||||||
|
$ThisFileInfo['monkeys_audio']['samples_per_frame'] = MonkeySamplesPerFrame($ThisFileInfo['monkeys_audio']['raw']['nVersion'], $ThisFileInfo['monkeys_audio']['raw']['nCompressionLevel']);
|
||||||
|
$ThisFileInfo['monkeys_audio']['bits_per_sample'] = ($ThisFileInfo['monkeys_audio']['flags']['24-bit'] ? 24 : ($ThisFileInfo['monkeys_audio']['flags']['8-bit'] ? 8 : 16));
|
||||||
|
if ($ThisFileInfo['monkeys_audio']['bits_per_sample'] == 0) {
|
||||||
|
$ThisFileInfo['error'] .= "\n".'Corrupt MAC file: bits_per_sample == zero';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$ThisFileInfo['monkeys_audio']['channels'] = $ThisFileInfo['monkeys_audio']['raw']['nChannels'];
|
||||||
|
$ThisFileInfo['audio']['channels'] = $ThisFileInfo['monkeys_audio']['channels'];
|
||||||
|
$ThisFileInfo['monkeys_audio']['sample_rate'] = $ThisFileInfo['monkeys_audio']['raw']['nSampleRate'];
|
||||||
|
if ($ThisFileInfo['monkeys_audio']['sample_rate'] == 0) {
|
||||||
|
$ThisFileInfo['error'] .= "\n".'Corrupt MAC file: frequency == zero';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$ThisFileInfo['audio']['sample_rate'] = $ThisFileInfo['monkeys_audio']['sample_rate'];
|
||||||
|
$ThisFileInfo['monkeys_audio']['peak_level'] = $ThisFileInfo['monkeys_audio']['raw']['nPeakLevel'];
|
||||||
|
$ThisFileInfo['monkeys_audio']['peak_ratio'] = $ThisFileInfo['monkeys_audio']['peak_level'] / pow(2, $ThisFileInfo['monkeys_audio']['bits_per_sample'] - 1);
|
||||||
|
$ThisFileInfo['monkeys_audio']['frames'] = $ThisFileInfo['monkeys_audio']['raw']['nTotalFrames'];
|
||||||
|
$ThisFileInfo['monkeys_audio']['samples'] = (($ThisFileInfo['monkeys_audio']['frames'] - 1) * $ThisFileInfo['monkeys_audio']['samples_per_frame']) + $ThisFileInfo['monkeys_audio']['raw']['nFinalFrameSamples'];
|
||||||
|
$ThisFileInfo['monkeys_audio']['playtime'] = $ThisFileInfo['monkeys_audio']['samples'] / $ThisFileInfo['monkeys_audio']['sample_rate'];
|
||||||
|
if ($ThisFileInfo['monkeys_audio']['playtime'] == 0) {
|
||||||
|
$ThisFileInfo['error'] .= "\n".'Corrupt MAC file: playtime == zero';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$ThisFileInfo['playtime_seconds'] = $ThisFileInfo['monkeys_audio']['playtime'];
|
||||||
|
$ThisFileInfo['monkeys_audio']['compressed_size'] = $ThisFileInfo['avdataend'] - $ThisFileInfo['avdataoffset'];
|
||||||
|
$ThisFileInfo['monkeys_audio']['uncompressed_size'] = $ThisFileInfo['monkeys_audio']['samples'] * $ThisFileInfo['monkeys_audio']['channels'] * ($ThisFileInfo['monkeys_audio']['bits_per_sample'] / 8);
|
||||||
|
if ($ThisFileInfo['monkeys_audio']['uncompressed_size'] == 0) {
|
||||||
|
$ThisFileInfo['error'] .= "\n".'Corrupt MAC file: uncompressed_size == zero';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$ThisFileInfo['monkeys_audio']['compression_ratio'] = $ThisFileInfo['monkeys_audio']['compressed_size'] / ($ThisFileInfo['monkeys_audio']['uncompressed_size'] + $ThisFileInfo['monkeys_audio']['raw']['nWAVHeaderBytes']);
|
||||||
|
$ThisFileInfo['monkeys_audio']['bitrate'] = (($ThisFileInfo['monkeys_audio']['samples'] * $ThisFileInfo['monkeys_audio']['channels'] * $ThisFileInfo['monkeys_audio']['bits_per_sample']) / $ThisFileInfo['monkeys_audio']['playtime']) * $ThisFileInfo['monkeys_audio']['compression_ratio'];
|
||||||
|
$ThisFileInfo['audio']['bitrate'] = $ThisFileInfo['monkeys_audio']['bitrate'];
|
||||||
|
|
||||||
|
// add size of MAC header to avdataoffset - MD5data
|
||||||
|
$ThisFileInfo['avdataoffset'] += 40;
|
||||||
|
|
||||||
|
$ThisFileInfo['audio']['bits_per_sample'] = $ThisFileInfo['monkeys_audio']['bits_per_sample'];
|
||||||
|
$ThisFileInfo['audio']['encoder'] = 'MAC v'.number_format($ThisFileInfo['monkeys_audio']['version'], 2);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function MonkeyCompressionLevelNameLookup($compressionlevel) {
|
||||||
|
static $MonkeyCompressionLevelNameLookup = array();
|
||||||
|
if (empty($MonkeyCompressionLevelNameLookup)) {
|
||||||
|
$MonkeyCompressionLevelNameLookup[0] = 'unknown';
|
||||||
|
$MonkeyCompressionLevelNameLookup[1000] = 'fast';
|
||||||
|
$MonkeyCompressionLevelNameLookup[2000] = 'normal';
|
||||||
|
$MonkeyCompressionLevelNameLookup[3000] = 'high';
|
||||||
|
$MonkeyCompressionLevelNameLookup[4000] = 'extra-high';
|
||||||
|
$MonkeyCompressionLevelNameLookup[5000] = 'insane'; // thanks Allan Hansen <ah@artemis.dk> (October 6, 2002)
|
||||||
|
}
|
||||||
|
return (isset($MonkeyCompressionLevelNameLookup[$compressionlevel]) ? $MonkeyCompressionLevelNameLookup[$compressionlevel] : 'invalid');
|
||||||
|
}
|
||||||
|
|
||||||
|
function MonkeySamplesPerFrame($versionid, $compressionlevel) {
|
||||||
|
if ($versionid >= 3950) {
|
||||||
|
return 73728 * 4;
|
||||||
|
} elseif ($versionid >= 3900) {
|
||||||
|
return 73728;
|
||||||
|
} elseif (($versionid >= 3800) && ($compressionlevel == 4000)) {
|
||||||
|
return 73728;
|
||||||
|
} else {
|
||||||
|
return 9216;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
1075
livesupport/modules/getid3/var/getid3.mp3.php
Normal file
1075
livesupport/modules/getid3/var/getid3.mp3.php
Normal file
File diff suppressed because it is too large
Load diff
180
livesupport/modules/getid3/var/getid3.mpc.php
Normal file
180
livesupport/modules/getid3/var/getid3.mpc.php
Normal file
|
@ -0,0 +1,180 @@
|
||||||
|
<?php
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
/// getID3() by James Heinrich <getid3@users.sourceforge.net> //
|
||||||
|
// available at http://getid3.sourceforge.net ///
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
// //
|
||||||
|
// getid3.mpc.php - part of getID3() //
|
||||||
|
// See getid3.readme.txt for more details //
|
||||||
|
// //
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
function getMPCHeaderFilepointer(&$fd, &$ThisFileInfo) {
|
||||||
|
// http://www.uni-jena.de/~pfk/mpp/sv8/header.html
|
||||||
|
|
||||||
|
$ThisFileInfo['fileformat'] = 'mpc';
|
||||||
|
$ThisFileInfo['audio']['dataformat'] = 'mpc';
|
||||||
|
$ThisFileInfo['audio']['bitrate_mode'] = 'vbr';
|
||||||
|
$ThisFileInfo['audio']['channels'] = 2; // the format appears to be hardcoded for stereo only
|
||||||
|
|
||||||
|
fseek($fd, $ThisFileInfo['avdataoffset'], SEEK_SET);
|
||||||
|
|
||||||
|
$ThisFileInfo['mpc']['header']['size'] = 30;
|
||||||
|
$MPCheaderData = fread($fd, $ThisFileInfo['mpc']['header']['size']);
|
||||||
|
$offset = 0;
|
||||||
|
|
||||||
|
$ThisFileInfo['mpc']['header']['raw']['preamble'] = substr($MPCheaderData, $offset, 3); // should be 'MP+'
|
||||||
|
$offset += 3;
|
||||||
|
$StreamVersionByte = LittleEndian2Int(substr($MPCheaderData, $offset, 1));
|
||||||
|
$offset += 1;
|
||||||
|
$ThisFileInfo['mpc']['header']['stream_major_version'] = ($StreamVersionByte & 0x0F);
|
||||||
|
$ThisFileInfo['mpc']['header']['stream_minor_version'] = ($StreamVersionByte & 0xF0) >> 4;
|
||||||
|
$ThisFileInfo['mpc']['header']['frame_count'] = LittleEndian2Int(substr($MPCheaderData, $offset, 4));
|
||||||
|
$offset += 4;
|
||||||
|
|
||||||
|
switch ($ThisFileInfo['mpc']['header']['stream_major_version']) {
|
||||||
|
case 7:
|
||||||
|
//$ThisFileInfo['fileformat'] = 'SV7';
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
$ThisFileInfo['error'] .= "\n".'Only MPEGplus/Musepack SV7 supported';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$FlagsByte1 = LittleEndian2Int(substr($MPCheaderData, $offset, 4));
|
||||||
|
$offset += 4;
|
||||||
|
$ThisFileInfo['mpc']['header']['intensity_stereo'] = (bool) (($FlagsByte1 & 0x80000000) >> 31);
|
||||||
|
$ThisFileInfo['mpc']['header']['mid_side_stereo'] = (bool) (($FlagsByte1 & 0x40000000) >> 30);
|
||||||
|
$ThisFileInfo['mpc']['header']['max_subband'] = ($FlagsByte1 & 0x3F000000) >> 24;
|
||||||
|
$ThisFileInfo['mpc']['header']['raw']['profile'] = ($FlagsByte1 & 0x00F00000) >> 20;
|
||||||
|
$ThisFileInfo['mpc']['header']['begin_loud'] = (bool) (($FlagsByte1 & 0x00080000) >> 19);
|
||||||
|
$ThisFileInfo['mpc']['header']['end_loud'] = (bool) (($FlagsByte1 & 0x00040000) >> 18);
|
||||||
|
$ThisFileInfo['mpc']['header']['raw']['sample_rate'] = ($FlagsByte1 & 0x00030000) >> 16;
|
||||||
|
$ThisFileInfo['mpc']['header']['max_level'] = ($FlagsByte1 & 0x0000FFFF);
|
||||||
|
|
||||||
|
$ThisFileInfo['mpc']['header']['raw']['title_peak'] = LittleEndian2Int(substr($MPCheaderData, $offset, 2));
|
||||||
|
$offset += 2;
|
||||||
|
$ThisFileInfo['mpc']['header']['raw']['title_gain'] = LittleEndian2Int(substr($MPCheaderData, $offset, 2), true);
|
||||||
|
$offset += 2;
|
||||||
|
|
||||||
|
$ThisFileInfo['mpc']['header']['raw']['album_peak'] = LittleEndian2Int(substr($MPCheaderData, $offset, 2));
|
||||||
|
$offset += 2;
|
||||||
|
$ThisFileInfo['mpc']['header']['raw']['album_gain'] = LittleEndian2Int(substr($MPCheaderData, $offset, 2), true);
|
||||||
|
$offset += 2;
|
||||||
|
|
||||||
|
$FlagsByte2 = LittleEndian2Int(substr($MPCheaderData, $offset, 4));
|
||||||
|
$offset += 4;
|
||||||
|
$ThisFileInfo['mpc']['header']['true_gapless'] = (bool) (($FlagsByte2 & 0x80000000) >> 31);
|
||||||
|
$ThisFileInfo['mpc']['header']['last_frame_length'] = ($FlagsByte2 & 0x7FF00000) >> 20;
|
||||||
|
|
||||||
|
|
||||||
|
$offset += 3; // unused?
|
||||||
|
$ThisFileInfo['mpc']['header']['raw']['encoder_version'] = LittleEndian2Int(substr($MPCheaderData, $offset, 1));
|
||||||
|
$offset += 1;
|
||||||
|
|
||||||
|
$ThisFileInfo['mpc']['header']['profile'] = MPCprofileNameLookup($ThisFileInfo['mpc']['header']['raw']['profile']);
|
||||||
|
$ThisFileInfo['mpc']['header']['sample_rate'] = MPCfrequencyLookup($ThisFileInfo['mpc']['header']['raw']['sample_rate']);
|
||||||
|
if ($ThisFileInfo['mpc']['header']['sample_rate'] == 0) {
|
||||||
|
$ThisFileInfo['error'] .= "\n".'Corrupt MPC file: frequency == zero';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$ThisFileInfo['audio']['sample_rate'] = $ThisFileInfo['mpc']['header']['sample_rate'];
|
||||||
|
$ThisFileInfo['mpc']['header']['samples'] = ((($ThisFileInfo['mpc']['header']['frame_count'] - 1) * 1152) + $ThisFileInfo['mpc']['header']['last_frame_length']) * $ThisFileInfo['audio']['channels'];
|
||||||
|
|
||||||
|
$ThisFileInfo['playtime_seconds'] = ($ThisFileInfo['mpc']['header']['samples'] / $ThisFileInfo['audio']['channels']) / $ThisFileInfo['audio']['sample_rate'];
|
||||||
|
if ($ThisFileInfo['playtime_seconds'] == 0) {
|
||||||
|
$ThisFileInfo['error'] .= "\n".'Corrupt MPC file: playtime_seconds == zero';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// add size of file header to avdataoffset - calc bitrate correctly + MD5 data
|
||||||
|
$ThisFileInfo['avdataoffset'] += $ThisFileInfo['mpc']['header']['size'];
|
||||||
|
|
||||||
|
$ThisFileInfo['audio']['bitrate'] = (($ThisFileInfo['avdataend'] - $ThisFileInfo['avdataoffset']) * 8) / $ThisFileInfo['playtime_seconds'];
|
||||||
|
|
||||||
|
$ThisFileInfo['mpc']['header']['title_peak'] = $ThisFileInfo['mpc']['header']['raw']['title_peak'];
|
||||||
|
$ThisFileInfo['mpc']['header']['title_peak_db'] = MPCpeakDBLookup($ThisFileInfo['mpc']['header']['title_peak']);
|
||||||
|
$ThisFileInfo['mpc']['header']['title_gain_db'] = $ThisFileInfo['mpc']['header']['raw']['title_gain'] / 100;
|
||||||
|
$ThisFileInfo['mpc']['header']['album_peak'] = $ThisFileInfo['mpc']['header']['raw']['album_peak'];
|
||||||
|
$ThisFileInfo['mpc']['header']['album_peak_db'] = MPCpeakDBLookup($ThisFileInfo['mpc']['header']['album_peak']);
|
||||||
|
$ThisFileInfo['mpc']['header']['album_gain_db'] = $ThisFileInfo['mpc']['header']['raw']['album_gain'] / 100;;
|
||||||
|
$ThisFileInfo['mpc']['header']['encoder_version'] = MPCencoderVersionLookup($ThisFileInfo['mpc']['header']['raw']['encoder_version']);
|
||||||
|
|
||||||
|
if ($ThisFileInfo['mpc']['header']['title_peak_db']) {
|
||||||
|
$ThisFileInfo['replay_gain']['radio']['peak'] = $ThisFileInfo['mpc']['header']['title_peak'];
|
||||||
|
$ThisFileInfo['replay_gain']['radio']['adjustment'] = $ThisFileInfo['mpc']['header']['title_gain_db'];
|
||||||
|
} else {
|
||||||
|
$ThisFileInfo['replay_gain']['radio']['peak'] = CastAsInt(round($ThisFileInfo['mpc']['header']['max_level'] * 1.18)); // why? I don't know - see mppdec.c
|
||||||
|
$ThisFileInfo['replay_gain']['radio']['adjustment'] = 0;
|
||||||
|
}
|
||||||
|
if ($ThisFileInfo['mpc']['header']['album_peak_db']) {
|
||||||
|
$ThisFileInfo['replay_gain']['audiophile']['peak'] = $ThisFileInfo['mpc']['header']['album_peak'];
|
||||||
|
$ThisFileInfo['replay_gain']['audiophile']['adjustment'] = $ThisFileInfo['mpc']['header']['album_gain_db'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$ThisFileInfo['audio']['encoder'] = $ThisFileInfo['mpc']['header']['encoder_version'].', SV'.$ThisFileInfo['mpc']['header']['stream_major_version'].'.'.$ThisFileInfo['mpc']['header']['stream_minor_version'];
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function MPCprofileNameLookup($profileid) {
|
||||||
|
static $MPCprofileNameLookup = array();
|
||||||
|
if (empty($MPCprofileNameLookup)) {
|
||||||
|
$MPCprofileNameLookup[0] = 'no profile';
|
||||||
|
$MPCprofileNameLookup[1] = 'Experimental';
|
||||||
|
$MPCprofileNameLookup[2] = 'unused';
|
||||||
|
$MPCprofileNameLookup[3] = 'unused';
|
||||||
|
$MPCprofileNameLookup[4] = 'unused';
|
||||||
|
$MPCprofileNameLookup[5] = 'below Telephone (q = 0.0)';
|
||||||
|
$MPCprofileNameLookup[6] = 'below Telephone (q = 1.0)';
|
||||||
|
$MPCprofileNameLookup[7] = 'Telephone (q = 2.0)';
|
||||||
|
$MPCprofileNameLookup[8] = 'Thumb (q = 3.0)';
|
||||||
|
$MPCprofileNameLookup[9] = 'Radio (q = 4.0)';
|
||||||
|
$MPCprofileNameLookup[10] = 'Standard (q = 5.0)';
|
||||||
|
$MPCprofileNameLookup[11] = 'Extreme (q = 6.0)';
|
||||||
|
$MPCprofileNameLookup[12] = 'Insane (q = 7.0)';
|
||||||
|
$MPCprofileNameLookup[13] = 'BrainDead (q = 8.0)';
|
||||||
|
$MPCprofileNameLookup[14] = 'above BrainDead (q = 9.0)';
|
||||||
|
$MPCprofileNameLookup[15] = 'above BrainDead (q = 10.0)';
|
||||||
|
}
|
||||||
|
return (isset($MPCprofileNameLookup[$profileid]) ? $MPCprofileNameLookup[$profileid] : 'invalid');
|
||||||
|
}
|
||||||
|
|
||||||
|
function MPCfrequencyLookup($frequencyid) {
|
||||||
|
static $MPCfrequencyLookup = array();
|
||||||
|
if (empty($MPCfrequencyLookup)) {
|
||||||
|
$MPCfrequencyLookup[0] = 44100;
|
||||||
|
$MPCfrequencyLookup[1] = 48000;
|
||||||
|
$MPCfrequencyLookup[2] = 37800;
|
||||||
|
$MPCfrequencyLookup[3] = 32000;
|
||||||
|
}
|
||||||
|
return (isset($MPCfrequencyLookup[$frequencyid]) ? $MPCfrequencyLookup[$frequencyid] : 'invalid');
|
||||||
|
}
|
||||||
|
|
||||||
|
function MPCpeakDBLookup($intvalue) {
|
||||||
|
if ($intvalue > 0) {
|
||||||
|
return ((log10($intvalue) / log10(2)) - 15) * 6;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function MPCencoderVersionLookup($encoderversion) {
|
||||||
|
//Encoder version * 100 (106 = 1.06)
|
||||||
|
//EncoderVersion % 10 == 0 Release (1.0)
|
||||||
|
//EncoderVersion % 2 == 0 Beta (1.06)
|
||||||
|
//EncoderVersion % 2 == 1 Alpha (1.05a...z)
|
||||||
|
|
||||||
|
if (($encoderversion % 10) == 0) {
|
||||||
|
// release version
|
||||||
|
return number_format($encoderversion / 100, 2);
|
||||||
|
} elseif (($encoderversion % 2) == 0) {
|
||||||
|
// beta version
|
||||||
|
return number_format($encoderversion / 100, 2).' beta';
|
||||||
|
} else {
|
||||||
|
// alpha version
|
||||||
|
return number_format($encoderversion / 100, 2).' alpha';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
113
livesupport/modules/getid3/var/getid3.mpeg.php
Normal file
113
livesupport/modules/getid3/var/getid3.mpeg.php
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
<?php
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
/// getID3() by James Heinrich <getid3@users.sourceforge.net> //
|
||||||
|
// available at http://getid3.sourceforge.net ///
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
// //
|
||||||
|
// getid3.mpeg.php - part of getID3() //
|
||||||
|
// See getid3.readme.txt for more details //
|
||||||
|
// //
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
function getMPEGHeaderFilepointer(&$fd, &$ThisFileInfo) {
|
||||||
|
$ThisFileInfo['fileformat'] = 'mpeg';
|
||||||
|
|
||||||
|
// Start code 32 bits
|
||||||
|
// horizontal frame size 12 bits
|
||||||
|
// vertical frame size 12 bits
|
||||||
|
// pixel aspect ratio 4 bits
|
||||||
|
// frame rate 4 bits
|
||||||
|
// bitrate 18 bits
|
||||||
|
// marker bit 1 bit
|
||||||
|
// VBV buffer size 10 bits
|
||||||
|
// constrained parameter flag 1 bit
|
||||||
|
// intra quant. matrix flag 1 bit
|
||||||
|
// intra quant. matrix values 512 bits (present if matrix flag == 1)
|
||||||
|
// non-intra quant. matrix flag 1 bit
|
||||||
|
// non-intra quant. matrix values 512 bits (present if matrix flag == 1)
|
||||||
|
|
||||||
|
fseek($fd, $ThisFileInfo['avdataoffset'], SEEK_SET);
|
||||||
|
$MPEGvideoHeader = fread($fd, FREAD_BUFFER_SIZE);
|
||||||
|
$offset = 0;
|
||||||
|
|
||||||
|
// MPEG video information is found as $00 $00 $01 $B3
|
||||||
|
$matching_pattern = chr(0x00).chr(0x00).chr(0x01).chr(0xB3);
|
||||||
|
while (substr($MPEGvideoHeader, $offset++, 4) !== $matching_pattern) {
|
||||||
|
if ($offset >= (strlen($MPEGvideoHeader) - 12)) {
|
||||||
|
$MPEGvideoHeader .= fread($fd, FREAD_BUFFER_SIZE);
|
||||||
|
$MPEGvideoHeader = substr($MPEGvideoHeader, $offset);
|
||||||
|
$offset = 0;
|
||||||
|
if (strlen($MPEGvideoHeader) < 12) {
|
||||||
|
$ThisFileInfo['error'] .= "\n".'Could not find start of video block before end of file';
|
||||||
|
unset($ThisFileInfo['fileformat']);
|
||||||
|
return false;
|
||||||
|
} elseif (ftell($fd) >= 100000) {
|
||||||
|
$ThisFileInfo['error'] .= "\n".'Could not find start of video block in the first 100,000 bytes (this might not be an MPEG-video file?)';
|
||||||
|
unset($ThisFileInfo['fileformat']);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$ThisFileInfo['video']['dataformat'] = 'mpeg';
|
||||||
|
|
||||||
|
$offset += (strlen($matching_pattern) - 1);
|
||||||
|
|
||||||
|
$FrameSizeAspectRatioFrameRateDWORD = BigEndian2Int(substr($MPEGvideoHeader, $offset, 4));
|
||||||
|
$offset += 4;
|
||||||
|
|
||||||
|
$assortedinformation = BigEndian2Int(substr($MPEGvideoHeader, $offset, 4));
|
||||||
|
$offset += 4;
|
||||||
|
|
||||||
|
$ThisFileInfo['mpeg']['video']['raw']['framesize_horizontal'] = ($FrameSizeAspectRatioFrameRateDWORD & 0xFFF00000) >> 20; // 12 bits for horizontal frame size
|
||||||
|
$ThisFileInfo['mpeg']['video']['raw']['framesize_vertical'] = ($FrameSizeAspectRatioFrameRateDWORD & 0x000FFF00) >> 8; // 12 bits for vertical frame size
|
||||||
|
$ThisFileInfo['mpeg']['video']['raw']['pixel_aspect_ratio'] = ($FrameSizeAspectRatioFrameRateDWORD & 0x000000F0) >> 4;
|
||||||
|
$ThisFileInfo['mpeg']['video']['raw']['frame_rate'] = ($FrameSizeAspectRatioFrameRateDWORD & 0x0000000F);
|
||||||
|
|
||||||
|
$ThisFileInfo['mpeg']['video']['framesize_horizontal'] = $ThisFileInfo['mpeg']['video']['raw']['framesize_horizontal'];
|
||||||
|
$ThisFileInfo['mpeg']['video']['framesize_vertical'] = $ThisFileInfo['mpeg']['video']['raw']['framesize_vertical'];
|
||||||
|
$ThisFileInfo['video']['resolution_x'] = $ThisFileInfo['mpeg']['video']['framesize_horizontal'];
|
||||||
|
$ThisFileInfo['video']['resolution_y'] = $ThisFileInfo['mpeg']['video']['framesize_vertical'];
|
||||||
|
|
||||||
|
$ThisFileInfo['mpeg']['video']['pixel_aspect_ratio'] = MPEGvideoAspectRatioLookup($ThisFileInfo['mpeg']['video']['raw']['pixel_aspect_ratio']);
|
||||||
|
$ThisFileInfo['mpeg']['video']['pixel_aspect_ratio_text'] = MPEGvideoAspectRatioTextLookup($ThisFileInfo['mpeg']['video']['raw']['pixel_aspect_ratio']);
|
||||||
|
$ThisFileInfo['mpeg']['video']['frame_rate'] = MPEGvideoFramerateLookup($ThisFileInfo['mpeg']['video']['raw']['frame_rate']);
|
||||||
|
$ThisFileInfo['video']['frame_rate'] = $ThisFileInfo['mpeg']['video']['frame_rate'];
|
||||||
|
|
||||||
|
$ThisFileInfo['mpeg']['video']['raw']['bitrate'] = ($assortedinformation & 0xFFFFC000) >> 14;
|
||||||
|
$ThisFileInfo['mpeg']['video']['raw']['marker_bit'] = ($assortedinformation & 0x00002000) >> 13;
|
||||||
|
$ThisFileInfo['mpeg']['video']['raw']['vbv_buffer_size'] = ($assortedinformation & 0x00001FF8) >> 3;
|
||||||
|
$ThisFileInfo['mpeg']['video']['raw']['constrained_param_flag'] = ($assortedinformation & 0x00000004) >> 2;
|
||||||
|
$ThisFileInfo['mpeg']['video']['raw']['intra_quant_flag'] = ($assortedinformation & 0x00000002) >> 1;
|
||||||
|
|
||||||
|
if ($ThisFileInfo['mpeg']['video']['raw']['bitrate'] == 0x3FFFF) { // 18 set bits
|
||||||
|
$ThisFileInfo['mpeg']['video']['bitrate_type'] = 'variable';
|
||||||
|
$ThisFileInfo['bitrate_mode'] = 'vbr';
|
||||||
|
} else {
|
||||||
|
$ThisFileInfo['mpeg']['video']['bitrate'] = $ThisFileInfo['mpeg']['video']['raw']['bitrate'] * 400;
|
||||||
|
$ThisFileInfo['mpeg']['video']['bitrate_mode'] = 'cbr';
|
||||||
|
$ThisFileInfo['video']['bitrate_mode'] = $ThisFileInfo['mpeg']['video']['bitrate_mode'];
|
||||||
|
$ThisFileInfo['video']['bitrate'] = $ThisFileInfo['mpeg']['video']['bitrate'];
|
||||||
|
}
|
||||||
|
$ThisFileInfo['video']['bitrate_mode'] = $ThisFileInfo['mpeg']['video']['bitrate_mode'];
|
||||||
|
$ThisFileInfo['video']['bitrate'] = $ThisFileInfo['mpeg']['video']['bitrate'];
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function MPEGvideoFramerateLookup($rawframerate) {
|
||||||
|
$MPEGvideoFramerateLookup = array(0, 23.976, 24, 25, 29.97, 30, 50, 59.94, 60);
|
||||||
|
return (isset($MPEGvideoFramerateLookup[$rawframerate]) ? (float) $MPEGvideoFramerateLookup[$rawframerate] : (float) 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function MPEGvideoAspectRatioLookup($rawaspectratio) {
|
||||||
|
$MPEGvideoAspectRatioLookup = array(0, 1, 0.6735, 0.7031, 0.7615, 0.8055, 0.8437, 0.8935, 0.9157, 0.9815, 1.0255, 1.0695, 1.0950, 1.1575, 1.2015, 0);
|
||||||
|
return (isset($MPEGvideoAspectRatioLookup[$rawaspectratio]) ? (float) $MPEGvideoAspectRatioLookup[$rawaspectratio] : (float) 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function MPEGvideoAspectRatioTextLookup($rawaspectratio) {
|
||||||
|
$MPEGvideoAspectRatioTextLookup = array('forbidden', 'square pixels', '0.6735', '16:9, 625 line, PAL', '0.7615', '0.8055', '16:9, 525 line, NTSC', '0.8935', '4:3, 625 line, PAL, CCIR601', '0.9815', '1.0255', '1.0695', '4:3, 525 line, NTSC, CCIR601', '1.1575', '1.2015', 'reserved');
|
||||||
|
return (isset($MPEGvideoAspectRatioTextLookup[$rawaspectratio]) ? $MPEGvideoAspectRatioTextLookup[$rawaspectratio] : '');
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
220
livesupport/modules/getid3/var/getid3.nsv.php
Normal file
220
livesupport/modules/getid3/var/getid3.nsv.php
Normal file
|
@ -0,0 +1,220 @@
|
||||||
|
<?php
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
/// getID3() by James Heinrich <getid3@users.sourceforge.net> //
|
||||||
|
// available at http://getid3.sourceforge.net ///
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
// //
|
||||||
|
// getid3.nsv.php - part of getID3() //
|
||||||
|
// See getid3.readme.txt for more details //
|
||||||
|
// //
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
function getNSVHeaderFilepointer(&$fd, &$ThisFileInfo) {
|
||||||
|
fseek($fd, $ThisFileInfo['avdataoffset'], SEEK_SET);
|
||||||
|
$NSVheader = fread($fd, 4);
|
||||||
|
|
||||||
|
switch ($NSVheader) {
|
||||||
|
case 'NSVs':
|
||||||
|
if (getNSVsHeaderFilepointer($fd, $ThisFileInfo, 0)) {
|
||||||
|
$ThisFileInfo['fileformat'] = 'nsv';
|
||||||
|
$ThisFileInfo['audio']['dataformat'] = 'nsv';
|
||||||
|
$ThisFileInfo['video']['dataformat'] = 'nsv';
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'NSVf':
|
||||||
|
if (getNSVfHeaderFilepointer($fd, $ThisFileInfo, 0)) {
|
||||||
|
$ThisFileInfo['fileformat'] = 'nsv';
|
||||||
|
$ThisFileInfo['audio']['dataformat'] = 'nsv';
|
||||||
|
$ThisFileInfo['video']['dataformat'] = 'nsv';
|
||||||
|
getNSVsHeaderFilepointer($fd, $ThisFileInfo, $ThisFileInfo['nsv']['NSVf']['header_length']);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
$ThisFileInfo['error'] .= "\n".'unknown NSV file header ('.$NSVheader.')';
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($ThisFileInfo['nsv']['NSVf'])) {
|
||||||
|
$ThisFileInfo['warning'] .= "\n".'NSVf header not present - cannot calculate playtime or bitrate';
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getNSVsHeaderFilepointer(&$fd, &$ThisFileInfo, $fileoffset) {
|
||||||
|
fseek($fd, $fileoffset, SEEK_SET);
|
||||||
|
$NSVsheader = fread($fd, 28);
|
||||||
|
$offset = 0;
|
||||||
|
|
||||||
|
$ThisFileInfo['nsv']['NSVs']['identifier'] = substr($NSVsheader, $offset, 4);
|
||||||
|
$offset += 4;
|
||||||
|
|
||||||
|
if ($ThisFileInfo['nsv']['NSVs']['identifier'] != 'NSVs') {
|
||||||
|
$ThisFileInfo['error'] .= "\n".'expected "NSVs" at offset ('.$fileoffset.'), found "'.$ThisFileInfo['nsv']['NSVs']['identifier'].'" instead';
|
||||||
|
unset($ThisFileInfo['nsv']['NSVs']);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$ThisFileInfo['nsv']['NSVs']['offset'] = $fileoffset;
|
||||||
|
|
||||||
|
$ThisFileInfo['nsv']['NSVs']['video_codec'] = substr($NSVsheader, $offset, 4);
|
||||||
|
$offset += 4;
|
||||||
|
$ThisFileInfo['nsv']['NSVs']['audio_codec'] = substr($NSVsheader, $offset, 4);
|
||||||
|
$offset += 4;
|
||||||
|
$ThisFileInfo['nsv']['NSVs']['resolution_x'] = LittleEndian2Int(substr($NSVsheader, $offset, 2));
|
||||||
|
$offset += 2;
|
||||||
|
$ThisFileInfo['nsv']['NSVs']['resolution_y'] = LittleEndian2Int(substr($NSVsheader, $offset, 2));
|
||||||
|
$offset += 2;
|
||||||
|
|
||||||
|
$ThisFileInfo['nsv']['NSVs']['framerate_index'] = LittleEndian2Int(substr($NSVsheader, $offset, 2));
|
||||||
|
$offset += 1;
|
||||||
|
$ThisFileInfo['nsv']['NSVs']['unknown1b'] = LittleEndian2Int(substr($NSVsheader, $offset, 1));
|
||||||
|
$offset += 1;
|
||||||
|
$ThisFileInfo['nsv']['NSVs']['unknown1c'] = LittleEndian2Int(substr($NSVsheader, $offset, 1));
|
||||||
|
$offset += 1;
|
||||||
|
$ThisFileInfo['nsv']['NSVs']['unknown1d'] = LittleEndian2Int(substr($NSVsheader, $offset, 1));
|
||||||
|
$offset += 1;
|
||||||
|
$ThisFileInfo['nsv']['NSVs']['unknown2a'] = LittleEndian2Int(substr($NSVsheader, $offset, 1));
|
||||||
|
$offset += 1;
|
||||||
|
$ThisFileInfo['nsv']['NSVs']['unknown2b'] = LittleEndian2Int(substr($NSVsheader, $offset, 1));
|
||||||
|
$offset += 1;
|
||||||
|
$ThisFileInfo['nsv']['NSVs']['unknown2c'] = LittleEndian2Int(substr($NSVsheader, $offset, 1));
|
||||||
|
$offset += 1;
|
||||||
|
$ThisFileInfo['nsv']['NSVs']['unknown2d'] = LittleEndian2Int(substr($NSVsheader, $offset, 1));
|
||||||
|
$offset += 1;
|
||||||
|
|
||||||
|
switch ($ThisFileInfo['nsv']['NSVs']['audio_codec']) {
|
||||||
|
case 'PCM ':
|
||||||
|
$ThisFileInfo['nsv']['NSVs']['bits_channel'] = LittleEndian2Int(substr($NSVsheader, $offset, 1));
|
||||||
|
$offset += 1;
|
||||||
|
$ThisFileInfo['nsv']['NSVs']['channels'] = LittleEndian2Int(substr($NSVsheader, $offset, 1));
|
||||||
|
$offset += 1;
|
||||||
|
$ThisFileInfo['nsv']['NSVs']['sample_rate'] = LittleEndian2Int(substr($NSVsheader, $offset, 2));
|
||||||
|
$offset += 2;
|
||||||
|
|
||||||
|
$ThisFileInfo['audio']['sample_rate'] = $ThisFileInfo['nsv']['NSVs']['sample_rate'];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'MP3 ':
|
||||||
|
case 'NONE':
|
||||||
|
default:
|
||||||
|
$ThisFileInfo['nsv']['NSVs']['unknown3a'] = LittleEndian2Int(substr($NSVsheader, $offset, 1));
|
||||||
|
$offset += 1;
|
||||||
|
$ThisFileInfo['nsv']['NSVs']['unknown3b'] = LittleEndian2Int(substr($NSVsheader, $offset, 1));
|
||||||
|
$offset += 1;
|
||||||
|
$ThisFileInfo['nsv']['NSVs']['unknown3c'] = LittleEndian2Int(substr($NSVsheader, $offset, 1));
|
||||||
|
$offset += 1;
|
||||||
|
$ThisFileInfo['nsv']['NSVs']['unknown3d'] = LittleEndian2Int(substr($NSVsheader, $offset, 1));
|
||||||
|
$offset += 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
$ThisFileInfo['video']['resolution_x'] = $ThisFileInfo['nsv']['NSVs']['resolution_x'];
|
||||||
|
$ThisFileInfo['video']['resolution_y'] = $ThisFileInfo['nsv']['NSVs']['resolution_y'];
|
||||||
|
$ThisFileInfo['nsv']['NSVs']['frame_rate'] = NSVframerateLookup($ThisFileInfo['nsv']['NSVs']['framerate_index']);
|
||||||
|
$ThisFileInfo['video']['frame_rate'] = $ThisFileInfo['nsv']['NSVs']['frame_rate'];
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getNSVfHeaderFilepointer(&$fd, &$ThisFileInfo, $fileoffset, $getTOCoffsets=false) {
|
||||||
|
fseek($fd, $fileoffset, SEEK_SET);
|
||||||
|
$NSVfheader = fread($fd, 28);
|
||||||
|
$offset = 0;
|
||||||
|
|
||||||
|
$ThisFileInfo['nsv']['NSVf']['identifier'] = substr($NSVfheader, $offset, 4);
|
||||||
|
$offset += 4;
|
||||||
|
|
||||||
|
if ($ThisFileInfo['nsv']['NSVf']['identifier'] != 'NSVf') {
|
||||||
|
$ThisFileInfo['error'] .= "\n".'expected "NSVf" at offset ('.$fileoffset.'), found "'.$ThisFileInfo['nsv']['NSVf']['identifier'].'" instead';
|
||||||
|
unset($ThisFileInfo['nsv']['NSVf']);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$ThisFileInfo['nsv']['NSVs']['offset'] = $fileoffset;
|
||||||
|
|
||||||
|
$ThisFileInfo['nsv']['NSVf']['header_length'] = LittleEndian2Int(substr($NSVfheader, $offset, 4));
|
||||||
|
$offset += 4;
|
||||||
|
$ThisFileInfo['nsv']['NSVf']['file_size'] = LittleEndian2Int(substr($NSVfheader, $offset, 4));
|
||||||
|
$offset += 4;
|
||||||
|
|
||||||
|
if ($ThisFileInfo['nsv']['NSVf']['file_size'] > $ThisFileInfo['avdataend']) {
|
||||||
|
$ThisFileInfo['warning'] .= "\n".'truncated file - NSVf header indicates '.$ThisFileInfo['nsv']['NSVf']['file_size'].' bytes, file actually '.$ThisFileInfo['avdataend'].' bytes';
|
||||||
|
}
|
||||||
|
|
||||||
|
$ThisFileInfo['nsv']['NSVf']['playtime_ms'] = LittleEndian2Int(substr($NSVfheader, $offset, 4));
|
||||||
|
$offset += 4;
|
||||||
|
$ThisFileInfo['nsv']['NSVf']['meta_size'] = LittleEndian2Int(substr($NSVfheader, $offset, 4));
|
||||||
|
$offset += 4;
|
||||||
|
$ThisFileInfo['nsv']['NSVf']['TOC_entries_1'] = LittleEndian2Int(substr($NSVfheader, $offset, 4));
|
||||||
|
$offset += 4;
|
||||||
|
$ThisFileInfo['nsv']['NSVf']['TOC_entries_2'] = LittleEndian2Int(substr($NSVfheader, $offset, 4));
|
||||||
|
$offset += 4;
|
||||||
|
|
||||||
|
if ($ThisFileInfo['nsv']['NSVf']['playtime_ms'] == 0) {
|
||||||
|
$ThisFileInfo['error'] .= "\n".'Corrupt NSV file: NSVf.playtime_ms == zero';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$NSVfheader .= fread($fd, $ThisFileInfo['nsv']['NSVf']['meta_size'] + (4 * $ThisFileInfo['nsv']['NSVf']['TOC_entries_1']) + (4 * $ThisFileInfo['nsv']['NSVf']['TOC_entries_2']));
|
||||||
|
$NSVfheaderlength = strlen($NSVfheader);
|
||||||
|
$ThisFileInfo['nsv']['NSVf']['metadata'] = substr($NSVfheader, $offset, $ThisFileInfo['nsv']['NSVf']['meta_size']);
|
||||||
|
$offset += $ThisFileInfo['nsv']['NSVf']['meta_size'];
|
||||||
|
|
||||||
|
if ($getTOCoffsets) {
|
||||||
|
$TOCcounter = 0;
|
||||||
|
while ($TOCcounter < $ThisFileInfo['nsv']['NSVf']['TOC_entries_1']) {
|
||||||
|
if ($TOCcounter < $ThisFileInfo['nsv']['NSVf']['TOC_entries_1']) {
|
||||||
|
$ThisFileInfo['nsv']['NSVf']['TOC_1'][$TOCcounter] = LittleEndian2Int(substr($NSVfheader, $offset, 4));
|
||||||
|
$offset += 4;
|
||||||
|
$TOCcounter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (trim($ThisFileInfo['nsv']['NSVf']['metadata']) != '') {
|
||||||
|
$CommentPairArray = explode('` ', $ThisFileInfo['nsv']['NSVf']['metadata']);
|
||||||
|
foreach ($CommentPairArray as $CommentPair) {
|
||||||
|
if (strstr($CommentPair, '=`')) {
|
||||||
|
list($key, $value) = explode('=`', $CommentPair, 2);
|
||||||
|
$ThisFileInfo['nsv']['comments'][strtolower($key)] = str_replace('`', '', $value);
|
||||||
|
} elseif (strstr($CommentPair, '='.chr(1))) {
|
||||||
|
list($key, $value) = explode('='.chr(1), $CommentPair, 2);
|
||||||
|
$ThisFileInfo['nsv']['comments'][strtolower($key)] = str_replace(chr(1), '', $value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// NSV tags have highest priority
|
||||||
|
if (!empty($ThisFileInfo['nsv']['comments'])) {
|
||||||
|
CopyFormatCommentsToRootComments($ThisFileInfo['nsv']['comments'], $ThisFileInfo, true, true, true);
|
||||||
|
}
|
||||||
|
// add tag to array of tags
|
||||||
|
$ThisFileInfo['tags'][] = 'nsv';
|
||||||
|
|
||||||
|
$ThisFileInfo['playtime_seconds'] = $ThisFileInfo['nsv']['NSVf']['playtime_ms'] / 1000;
|
||||||
|
$ThisFileInfo['bitrate'] = ($ThisFileInfo['nsv']['NSVf']['file_size'] * 8) / $ThisFileInfo['playtime_seconds'];
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function NSVframerateLookup($framerateindex) {
|
||||||
|
if ($framerateindex <= 127) {
|
||||||
|
return (float) $framerateindex;
|
||||||
|
}
|
||||||
|
|
||||||
|
static $NSVframerateLookup = array();
|
||||||
|
if (empty($NSVframerateLookup)) {
|
||||||
|
$NSVframerateLookup[129] = (float) 29.970;
|
||||||
|
$NSVframerateLookup[131] = (float) 23.976;
|
||||||
|
$NSVframerateLookup[133] = (float) 14.985;
|
||||||
|
$NSVframerateLookup[197] = (float) 59.940;
|
||||||
|
$NSVframerateLookup[199] = (float) 47.952;
|
||||||
|
}
|
||||||
|
return (isset($NSVframerateLookup[$framerateindex]) ? $NSVframerateLookup[$framerateindex] : false);
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
493
livesupport/modules/getid3/var/getid3.ogg.php
Normal file
493
livesupport/modules/getid3/var/getid3.ogg.php
Normal file
|
@ -0,0 +1,493 @@
|
||||||
|
<?php
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
/// getID3() by James Heinrich <getid3@users.sourceforge.net> //
|
||||||
|
// available at http://getid3.sourceforge.net ///
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
// //
|
||||||
|
// getid3.ogg.php - part of getID3() //
|
||||||
|
// See getid3.readme.txt for more details //
|
||||||
|
// //
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
function getOggHeaderFilepointer(&$fd, &$ThisFileInfo) {
|
||||||
|
|
||||||
|
$ThisFileInfo['fileformat'] = 'ogg';
|
||||||
|
|
||||||
|
// Warn about illegal tags - only vorbiscomments are allowed
|
||||||
|
if (isset($ThisFileInfo['id3v2'])) {
|
||||||
|
$ThisFileInfo['warning'] .= "\n".'Illegal ID3v2 tag present.';
|
||||||
|
}
|
||||||
|
if (isset($ThisFileInfo['id3v1'])) {
|
||||||
|
$ThisFileInfo['warning'] .= "\n".'Illegal ID3v1 tag present.';
|
||||||
|
}
|
||||||
|
if (isset($ThisFileInfo['ape'])) {
|
||||||
|
$ThisFileInfo['warning'] .= "\n".'Illegal APE tag present.';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Page 1 - Stream Header
|
||||||
|
|
||||||
|
fseek($fd, $ThisFileInfo['avdataoffset'], SEEK_SET);
|
||||||
|
|
||||||
|
$oggpageinfo = ParseOggPageHeader($fd);
|
||||||
|
$ThisFileInfo['ogg']['pageheader'][$oggpageinfo['page_seqno']] = $oggpageinfo;
|
||||||
|
|
||||||
|
if (ftell($fd) >= FREAD_BUFFER_SIZE) {
|
||||||
|
$ThisFileInfo['error'] .= "\n".'Could not find start of Ogg page in the first '.FREAD_BUFFER_SIZE.' bytes (this might not be an Ogg-Vorbis file?)';
|
||||||
|
unset($ThisFileInfo['fileformat']);
|
||||||
|
unset($ThisFileInfo['ogg']);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$filedata = fread($fd, $oggpageinfo['page_length']);
|
||||||
|
$filedataoffset = 0;
|
||||||
|
|
||||||
|
if (substr($filedata, 0, 4) == 'fLaC') {
|
||||||
|
|
||||||
|
$ThisFileInfo['audio']['dataformat'] = 'flac';
|
||||||
|
$ThisFileInfo['audio']['bitrate_mode'] = 'vbr';
|
||||||
|
|
||||||
|
} elseif (substr($filedata, 1, 6) == 'vorbis') {
|
||||||
|
|
||||||
|
$ThisFileInfo['audio']['dataformat'] = 'vorbis';
|
||||||
|
|
||||||
|
$ThisFileInfo['ogg']['pageheader'][$oggpageinfo['page_seqno']]['packet_type'] = LittleEndian2Int(substr($filedata, $filedataoffset, 1));
|
||||||
|
$filedataoffset += 1;
|
||||||
|
$ThisFileInfo['ogg']['pageheader'][$oggpageinfo['page_seqno']]['stream_type'] = substr($filedata, $filedataoffset, 6); // hard-coded to 'vorbis'
|
||||||
|
$filedataoffset += 6;
|
||||||
|
$ThisFileInfo['ogg']['bitstreamversion'] = LittleEndian2Int(substr($filedata, $filedataoffset, 4));
|
||||||
|
$filedataoffset += 4;
|
||||||
|
$ThisFileInfo['ogg']['numberofchannels'] = LittleEndian2Int(substr($filedata, $filedataoffset, 1));
|
||||||
|
$filedataoffset += 1;
|
||||||
|
$ThisFileInfo['audio']['channels'] = $ThisFileInfo['ogg']['numberofchannels'];
|
||||||
|
$ThisFileInfo['ogg']['samplerate'] = LittleEndian2Int(substr($filedata, $filedataoffset, 4));
|
||||||
|
$filedataoffset += 4;
|
||||||
|
if ($ThisFileInfo['ogg']['samplerate'] == 0) {
|
||||||
|
$ThisFileInfo['error'] .= "\n".'Corrupt Ogg file: sample rate == zero';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$ThisFileInfo['audio']['sample_rate'] = $ThisFileInfo['ogg']['samplerate'];
|
||||||
|
$ThisFileInfo['ogg']['samples'] = 0; // filled in later
|
||||||
|
$ThisFileInfo['ogg']['bitrate_average'] = 0; // filled in later
|
||||||
|
$ThisFileInfo['ogg']['bitrate_max'] = LittleEndian2Int(substr($filedata, $filedataoffset, 4));
|
||||||
|
$filedataoffset += 4;
|
||||||
|
$ThisFileInfo['ogg']['bitrate_nominal'] = LittleEndian2Int(substr($filedata, $filedataoffset, 4));
|
||||||
|
$filedataoffset += 4;
|
||||||
|
$ThisFileInfo['ogg']['bitrate_min'] = LittleEndian2Int(substr($filedata, $filedataoffset, 4));
|
||||||
|
$filedataoffset += 4;
|
||||||
|
$ThisFileInfo['ogg']['blocksize_small'] = pow(2, LittleEndian2Int(substr($filedata, $filedataoffset, 1)) & 0x0F);
|
||||||
|
$ThisFileInfo['ogg']['blocksize_large'] = pow(2, (LittleEndian2Int(substr($filedata, $filedataoffset, 1)) & 0xF0) >> 4);
|
||||||
|
$ThisFileInfo['ogg']['stop_bit'] = LittleEndian2Int(substr($filedata, $filedataoffset, 1)); // must be 1, marks end of packet
|
||||||
|
|
||||||
|
$ThisFileInfo['audio']['bitrate_mode'] = 'vbr'; // overridden if actually abr
|
||||||
|
if ($ThisFileInfo['ogg']['bitrate_max'] == 0xFFFFFFFF) {
|
||||||
|
unset($ThisFileInfo['ogg']['bitrate_max']);
|
||||||
|
$ThisFileInfo['audio']['bitrate_mode'] = 'abr';
|
||||||
|
}
|
||||||
|
if ($ThisFileInfo['ogg']['bitrate_nominal'] == 0xFFFFFFFF) {
|
||||||
|
unset($ThisFileInfo['ogg']['bitrate_nominal']);
|
||||||
|
}
|
||||||
|
if ($ThisFileInfo['ogg']['bitrate_min'] == 0xFFFFFFFF) {
|
||||||
|
unset($ThisFileInfo['ogg']['bitrate_min']);
|
||||||
|
$ThisFileInfo['audio']['bitrate_mode'] = 'abr';
|
||||||
|
}
|
||||||
|
|
||||||
|
} elseif (substr($filedata, 0, 8) == 'Speex ') {
|
||||||
|
|
||||||
|
// http://www.speex.org/manual/node10.html
|
||||||
|
|
||||||
|
$ThisFileInfo['audio']['dataformat'] = 'speex';
|
||||||
|
$ThisFileInfo['mime_type'] = 'audio/speex';
|
||||||
|
$ThisFileInfo['audio']['bitrate_mode'] = 'abr';
|
||||||
|
|
||||||
|
$ThisFileInfo['ogg']['pageheader'][$oggpageinfo['page_seqno']]['speex_string'] = substr($filedata, $filedataoffset, 8); // hard-coded to 'Speex '
|
||||||
|
$filedataoffset += 8;
|
||||||
|
$ThisFileInfo['ogg']['pageheader'][$oggpageinfo['page_seqno']]['speex_version'] = substr($filedata, $filedataoffset, 20);
|
||||||
|
$filedataoffset += 20;
|
||||||
|
$ThisFileInfo['ogg']['pageheader'][$oggpageinfo['page_seqno']]['speex_version_id'] = LittleEndian2Int(substr($filedata, $filedataoffset, 4));
|
||||||
|
$filedataoffset += 4;
|
||||||
|
$ThisFileInfo['ogg']['pageheader'][$oggpageinfo['page_seqno']]['header_size'] = LittleEndian2Int(substr($filedata, $filedataoffset, 4));
|
||||||
|
$filedataoffset += 4;
|
||||||
|
$ThisFileInfo['ogg']['pageheader'][$oggpageinfo['page_seqno']]['rate'] = LittleEndian2Int(substr($filedata, $filedataoffset, 4));
|
||||||
|
$filedataoffset += 4;
|
||||||
|
$ThisFileInfo['ogg']['pageheader'][$oggpageinfo['page_seqno']]['mode'] = LittleEndian2Int(substr($filedata, $filedataoffset, 4));
|
||||||
|
$filedataoffset += 4;
|
||||||
|
$ThisFileInfo['ogg']['pageheader'][$oggpageinfo['page_seqno']]['mode_bitstream_version'] = LittleEndian2Int(substr($filedata, $filedataoffset, 4));
|
||||||
|
$filedataoffset += 4;
|
||||||
|
$ThisFileInfo['ogg']['pageheader'][$oggpageinfo['page_seqno']]['nb_channels'] = LittleEndian2Int(substr($filedata, $filedataoffset, 4));
|
||||||
|
$filedataoffset += 4;
|
||||||
|
$ThisFileInfo['ogg']['pageheader'][$oggpageinfo['page_seqno']]['bitrate'] = LittleEndian2Int(substr($filedata, $filedataoffset, 4));
|
||||||
|
$filedataoffset += 4;
|
||||||
|
$ThisFileInfo['ogg']['pageheader'][$oggpageinfo['page_seqno']]['framesize'] = LittleEndian2Int(substr($filedata, $filedataoffset, 4));
|
||||||
|
$filedataoffset += 4;
|
||||||
|
$ThisFileInfo['ogg']['pageheader'][$oggpageinfo['page_seqno']]['vbr'] = LittleEndian2Int(substr($filedata, $filedataoffset, 4));
|
||||||
|
$filedataoffset += 4;
|
||||||
|
$ThisFileInfo['ogg']['pageheader'][$oggpageinfo['page_seqno']]['frames_per_packet'] = LittleEndian2Int(substr($filedata, $filedataoffset, 4));
|
||||||
|
$filedataoffset += 4;
|
||||||
|
$ThisFileInfo['ogg']['pageheader'][$oggpageinfo['page_seqno']]['extra_headers'] = LittleEndian2Int(substr($filedata, $filedataoffset, 4));
|
||||||
|
$filedataoffset += 4;
|
||||||
|
$ThisFileInfo['ogg']['pageheader'][$oggpageinfo['page_seqno']]['reserved1'] = LittleEndian2Int(substr($filedata, $filedataoffset, 4));
|
||||||
|
$filedataoffset += 4;
|
||||||
|
$ThisFileInfo['ogg']['pageheader'][$oggpageinfo['page_seqno']]['reserved2'] = LittleEndian2Int(substr($filedata, $filedataoffset, 4));
|
||||||
|
$filedataoffset += 4;
|
||||||
|
|
||||||
|
$ThisFileInfo['speex']['speex_version'] = trim($ThisFileInfo['ogg']['pageheader'][$oggpageinfo['page_seqno']]['speex_version']);
|
||||||
|
$ThisFileInfo['speex']['sample_rate'] = $ThisFileInfo['ogg']['pageheader'][$oggpageinfo['page_seqno']]['rate'];
|
||||||
|
$ThisFileInfo['speex']['channels'] = $ThisFileInfo['ogg']['pageheader'][$oggpageinfo['page_seqno']]['nb_channels'];
|
||||||
|
$ThisFileInfo['speex']['vbr'] = (bool) $ThisFileInfo['ogg']['pageheader'][$oggpageinfo['page_seqno']]['vbr'];
|
||||||
|
$ThisFileInfo['speex']['band_type'] = SpeexBandModeLookup($ThisFileInfo['ogg']['pageheader'][$oggpageinfo['page_seqno']]['mode']);
|
||||||
|
|
||||||
|
$ThisFileInfo['audio']['sample_rate'] = $ThisFileInfo['speex']['sample_rate'];
|
||||||
|
$ThisFileInfo['audio']['channels'] = $ThisFileInfo['speex']['channels'];
|
||||||
|
if ($ThisFileInfo['speex']['vbr']) {
|
||||||
|
$ThisFileInfo['audio']['bitrate_mode'] = 'vbr';
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
$ThisFileInfo['error'] .= "\n".'Expecting either "Speex " or "vorbis" identifier strings, found neither';
|
||||||
|
unset($ThisFileInfo['ogg']);
|
||||||
|
unset($ThisFileInfo['mime_type']);
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Page 2 - Comment Header
|
||||||
|
|
||||||
|
$oggpageinfo = ParseOggPageHeader($fd);
|
||||||
|
$ThisFileInfo['ogg']['pageheader'][$oggpageinfo['page_seqno']] = $oggpageinfo;
|
||||||
|
|
||||||
|
switch ($ThisFileInfo['audio']['dataformat']) {
|
||||||
|
|
||||||
|
case 'vorbis':
|
||||||
|
$filedata = fread($fd, $ThisFileInfo['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_length']);
|
||||||
|
$ThisFileInfo['ogg']['pageheader'][$oggpageinfo['page_seqno']]['packet_type'] = LittleEndian2Int(substr($filedata, 0, 1));
|
||||||
|
$ThisFileInfo['ogg']['pageheader'][$oggpageinfo['page_seqno']]['stream_type'] = substr($filedata, 1, 6); // hard-coded to 'vorbis'
|
||||||
|
|
||||||
|
ParseVorbisCommentsFilepointer($fd, $ThisFileInfo);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'flac':
|
||||||
|
require_once(GETID3_INCLUDEPATH.'getid3.flac.php');
|
||||||
|
if (!FLACparseMETAdata($fd, $ThisFileInfo)) {
|
||||||
|
$ThisFileInfo['error'] .= "\n".'Failed to parse FLAC headers';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'speex':
|
||||||
|
fseek($fd, $ThisFileInfo['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_length'], SEEK_CUR);
|
||||||
|
ParseVorbisCommentsFilepointer($fd, $ThisFileInfo);
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Last Page - Number of Samples
|
||||||
|
|
||||||
|
fseek($fd, max($ThisFileInfo['avdataend'] - FREAD_BUFFER_SIZE, 0), SEEK_SET);
|
||||||
|
$LastChunkOfOgg = strrev(fread($fd, FREAD_BUFFER_SIZE));
|
||||||
|
if ($LastOggSpostion = strpos($LastChunkOfOgg, 'SggO')) {
|
||||||
|
fseek($fd, 0 - ($LastOggSpostion + strlen('SggO')), SEEK_END);
|
||||||
|
$ThisFileInfo['avdataend'] = ftell($fd);
|
||||||
|
$ThisFileInfo['ogg']['pageheader']['eos'] = ParseOggPageHeader($fd);
|
||||||
|
$ThisFileInfo['ogg']['samples'] = $ThisFileInfo['ogg']['pageheader']['eos']['pcm_abs_position'];
|
||||||
|
if ($ThisFileInfo['ogg']['samples'] == 0) {
|
||||||
|
$ThisFileInfo['error'] .= "\n".'Corrupt Ogg file: eos.number of samples == zero';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$ThisFileInfo['ogg']['bitrate_average'] = (($ThisFileInfo['avdataend'] - $ThisFileInfo['avdataoffset']) * 8) / ($ThisFileInfo['ogg']['samples'] / $ThisFileInfo['audio']['sample_rate']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($ThisFileInfo['ogg']['bitrate_average']) && ($ThisFileInfo['ogg']['bitrate_average'] > 0)) {
|
||||||
|
$ThisFileInfo['audio']['bitrate'] = $ThisFileInfo['ogg']['bitrate_average'];
|
||||||
|
} elseif (isset($ThisFileInfo['ogg']['bitrate_nominal']) && ($ThisFileInfo['ogg']['bitrate_nominal'] > 0)) {
|
||||||
|
$ThisFileInfo['audio']['bitrate'] = $ThisFileInfo['ogg']['bitrate_nominal'];
|
||||||
|
} elseif (isset($ThisFileInfo['ogg']['bitrate_min']) && isset($ThisFileInfo['ogg']['bitrate_max'])) {
|
||||||
|
$ThisFileInfo['audio']['bitrate'] = ($ThisFileInfo['ogg']['bitrate_min'] + $ThisFileInfo['ogg']['bitrate_max']) / 2;
|
||||||
|
}
|
||||||
|
if (isset($ThisFileInfo['audio']['bitrate']) && !isset($ThisFileInfo['playtime_seconds'])) {
|
||||||
|
if ($ThisFileInfo['audio']['bitrate'] == 0) {
|
||||||
|
$ThisFileInfo['error'] .= "\n".'Corrupt Ogg file: bitrate_audio == zero';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$ThisFileInfo['playtime_seconds'] = (float) ((($ThisFileInfo['avdataend'] - $ThisFileInfo['avdataoffset']) * 8) / $ThisFileInfo['audio']['bitrate']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($ThisFileInfo['ogg']['vendor'])) {
|
||||||
|
$ThisFileInfo['audio']['encoder'] = preg_replace('/^Encoded with /', '', $ThisFileInfo['ogg']['vendor']);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function ParseOggPageHeader(&$fd) {
|
||||||
|
// http://xiph.org/ogg/vorbis/doc/framing.html
|
||||||
|
$oggheader['page_start_offset'] = ftell($fd); // where we started from in the file
|
||||||
|
|
||||||
|
$filedata = fread($fd, FREAD_BUFFER_SIZE);
|
||||||
|
$filedataoffset = 0;
|
||||||
|
while ((substr($filedata, $filedataoffset++, 4) != 'OggS')) {
|
||||||
|
if ((ftell($fd) - $oggheader['page_start_offset']) >= FREAD_BUFFER_SIZE) {
|
||||||
|
// should be found before here
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (strlen($filedata) < 1024) {
|
||||||
|
if (feof($fd) || (($filedata .= fread($fd, FREAD_BUFFER_SIZE)) === false)) {
|
||||||
|
// get some more data, unless eof, in which case fail
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$filedataoffset += strlen('OggS') - 1; // page, delimited by 'OggS'
|
||||||
|
|
||||||
|
$oggheader['stream_structver'] = LittleEndian2Int(substr($filedata, $filedataoffset, 1));
|
||||||
|
$filedataoffset += 1;
|
||||||
|
$oggheader['flags_raw'] = LittleEndian2Int(substr($filedata, $filedataoffset, 1));
|
||||||
|
$filedataoffset += 1;
|
||||||
|
$oggheader['flags']['fresh'] = (bool) ($oggheader['flags_raw'] & 0x01); // fresh packet
|
||||||
|
$oggheader['flags']['bos'] = (bool) ($oggheader['flags_raw'] & 0x02); // first page of logical bitstream (bos)
|
||||||
|
$oggheader['flags']['eos'] = (bool) ($oggheader['flags_raw'] & 0x04); // last page of logical bitstream (eos)
|
||||||
|
|
||||||
|
$oggheader['pcm_abs_position'] = LittleEndian2Int(substr($filedata, $filedataoffset, 8));
|
||||||
|
$filedataoffset += 8;
|
||||||
|
$oggheader['stream_serialno'] = LittleEndian2Int(substr($filedata, $filedataoffset, 4));
|
||||||
|
$filedataoffset += 4;
|
||||||
|
$oggheader['page_seqno'] = LittleEndian2Int(substr($filedata, $filedataoffset, 4));
|
||||||
|
$filedataoffset += 4;
|
||||||
|
$oggheader['page_checksum'] = LittleEndian2Int(substr($filedata, $filedataoffset, 4));
|
||||||
|
$filedataoffset += 4;
|
||||||
|
$oggheader['page_segments'] = LittleEndian2Int(substr($filedata, $filedataoffset, 1));
|
||||||
|
$filedataoffset += 1;
|
||||||
|
$oggheader['page_length'] = 0;
|
||||||
|
for ($i = 0; $i < $oggheader['page_segments']; $i++) {
|
||||||
|
$oggheader['segment_table'][$i] = LittleEndian2Int(substr($filedata, $filedataoffset, 1));
|
||||||
|
$filedataoffset += 1;
|
||||||
|
$oggheader['page_length'] += $oggheader['segment_table'][$i];
|
||||||
|
}
|
||||||
|
$oggheader['header_end_offset'] = $oggheader['page_start_offset'] + $filedataoffset;
|
||||||
|
$oggheader['page_end_offset'] = $oggheader['header_end_offset'] + $oggheader['page_length'];
|
||||||
|
fseek($fd, $oggheader['header_end_offset'], SEEK_SET);
|
||||||
|
|
||||||
|
return $oggheader;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function ParseVorbisCommentsFilepointer(&$fd, &$ThisFileInfo) {
|
||||||
|
|
||||||
|
$OriginalOffset = ftell($fd);
|
||||||
|
$CommentStartOffset = $OriginalOffset;
|
||||||
|
$commentdataoffset = 0;
|
||||||
|
$VorbisCommentPage = 1;
|
||||||
|
|
||||||
|
switch ($ThisFileInfo['audio']['dataformat']) {
|
||||||
|
case 'vorbis':
|
||||||
|
$CommentStartOffset = $ThisFileInfo['ogg']['pageheader'][$VorbisCommentPage]['page_start_offset']; // Second Ogg page, after header block
|
||||||
|
fseek($fd, $CommentStartOffset, SEEK_SET);
|
||||||
|
$commentdataoffset = 27 + $ThisFileInfo['ogg']['pageheader'][$VorbisCommentPage]['page_segments'];
|
||||||
|
$commentdata = fread($fd, OggPageSegmentLength($ThisFileInfo['ogg']['pageheader'][$VorbisCommentPage], 1) + $commentdataoffset);
|
||||||
|
|
||||||
|
$commentdataoffset += (strlen('vorbis') + 1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'flac':
|
||||||
|
fseek($fd, $ThisFileInfo['flac']['VORBIS_COMMENT']['raw']['offset'] + 4, SEEK_SET);
|
||||||
|
$commentdata = fread($fd, $ThisFileInfo['flac']['VORBIS_COMMENT']['raw']['block_length']);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'speex':
|
||||||
|
$CommentStartOffset = $ThisFileInfo['ogg']['pageheader'][$VorbisCommentPage]['page_start_offset']; // Second Ogg page, after header block
|
||||||
|
fseek($fd, $CommentStartOffset, SEEK_SET);
|
||||||
|
$commentdataoffset = 27 + $ThisFileInfo['ogg']['pageheader'][$VorbisCommentPage]['page_segments'];
|
||||||
|
$commentdata = fread($fd, OggPageSegmentLength($ThisFileInfo['ogg']['pageheader'][$VorbisCommentPage], 1) + $commentdataoffset);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
$VendorSize = LittleEndian2Int(substr($commentdata, $commentdataoffset, 4));
|
||||||
|
$commentdataoffset += 4;
|
||||||
|
|
||||||
|
$ThisFileInfo['ogg']['vendor'] = substr($commentdata, $commentdataoffset, $VendorSize);
|
||||||
|
$commentdataoffset += $VendorSize;
|
||||||
|
|
||||||
|
$CommentsCount = LittleEndian2Int(substr($commentdata, $commentdataoffset, 4));
|
||||||
|
$commentdataoffset += 4;
|
||||||
|
$ThisFileInfo['avdataoffset'] = $CommentStartOffset + $commentdataoffset;
|
||||||
|
|
||||||
|
$basicfields = array('TITLE', 'ARTIST', 'ALBUM', 'TRACKNUMBER', 'GENRE', 'DATE', 'DESCRIPTION', 'COMMENT');
|
||||||
|
for ($i = 0; $i < $CommentsCount; $i++) {
|
||||||
|
|
||||||
|
$ThisFileInfo['ogg']['comments_raw'][$i]['dataoffset'] = $CommentStartOffset + $commentdataoffset;
|
||||||
|
|
||||||
|
if (ftell($fd) < ($ThisFileInfo['ogg']['comments_raw'][$i]['dataoffset'] + 4)) {
|
||||||
|
$VorbisCommentPage++;
|
||||||
|
|
||||||
|
$oggpageinfo = ParseOggPageHeader($fd);
|
||||||
|
$ThisFileInfo['ogg']['pageheader'][$oggpageinfo['page_seqno']] = $oggpageinfo;
|
||||||
|
|
||||||
|
// First, save what we haven't read yet
|
||||||
|
$AsYetUnusedData = substr($commentdata, $commentdataoffset);
|
||||||
|
|
||||||
|
// Then take that data off the end
|
||||||
|
$commentdata = substr($commentdata, 0, $commentdataoffset);
|
||||||
|
|
||||||
|
// Add [headerlength] bytes of dummy data for the Ogg Page Header, just to keep absolute offsets correct
|
||||||
|
$commentdata .= str_repeat(chr(0), 27 + $ThisFileInfo['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_segments']);
|
||||||
|
$commentdataoffset += (27 + $ThisFileInfo['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_segments']);
|
||||||
|
|
||||||
|
// Finally, stick the unused data back on the end
|
||||||
|
$commentdata .= $AsYetUnusedData;
|
||||||
|
|
||||||
|
//$commentdata .= fread($fd, $ThisFileInfo['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_length']);
|
||||||
|
$commentdata .= fread($fd, OggPageSegmentLength($ThisFileInfo['ogg']['pageheader'][$VorbisCommentPage], 1));
|
||||||
|
|
||||||
|
}
|
||||||
|
$ThisFileInfo['ogg']['comments_raw'][$i]['size'] = LittleEndian2Int(substr($commentdata, $commentdataoffset, 4));
|
||||||
|
|
||||||
|
// replace avdataoffset with position just after the last vorbiscomment
|
||||||
|
$ThisFileInfo['avdataoffset'] = $ThisFileInfo['ogg']['comments_raw'][$i]['dataoffset'] + $ThisFileInfo['ogg']['comments_raw'][$i]['size'] + 4;
|
||||||
|
|
||||||
|
$commentdataoffset += 4;
|
||||||
|
while ((strlen($commentdata) - $commentdataoffset) < $ThisFileInfo['ogg']['comments_raw'][$i]['size']) {
|
||||||
|
if (($ThisFileInfo['ogg']['comments_raw'][$i]['size'] > $ThisFileInfo['avdataend']) || ($ThisFileInfo['ogg']['comments_raw'][$i]['size'] < 0)) {
|
||||||
|
$ThisFileInfo['error'] .= "\n".'Invalid Ogg comment size (comment #'.$i.', claims to be '.number_format($ThisFileInfo['ogg']['comments_raw'][$i]['size']).' bytes) - aborting reading comments';
|
||||||
|
break 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
$VorbisCommentPage++;
|
||||||
|
|
||||||
|
$oggpageinfo = ParseOggPageHeader($fd);
|
||||||
|
$ThisFileInfo['ogg']['pageheader'][$oggpageinfo['page_seqno']] = $oggpageinfo;
|
||||||
|
|
||||||
|
// First, save what we haven't read yet
|
||||||
|
$AsYetUnusedData = substr($commentdata, $commentdataoffset);
|
||||||
|
|
||||||
|
// Then take that data off the end
|
||||||
|
$commentdata = substr($commentdata, 0, $commentdataoffset);
|
||||||
|
|
||||||
|
// Add [headerlength] bytes of dummy data for the Ogg Page Header, just to keep absolute offsets correct
|
||||||
|
$commentdata .= str_repeat(chr(0), 27 + $ThisFileInfo['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_segments']);
|
||||||
|
$commentdataoffset += (27 + $ThisFileInfo['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_segments']);
|
||||||
|
|
||||||
|
// Finally, stick the unused data back on the end
|
||||||
|
$commentdata .= $AsYetUnusedData;
|
||||||
|
|
||||||
|
//$commentdata .= fread($fd, $ThisFileInfo['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_length']);
|
||||||
|
$commentdata .= fread($fd, OggPageSegmentLength($ThisFileInfo['ogg']['pageheader'][$VorbisCommentPage], 1));
|
||||||
|
|
||||||
|
//$filebaseoffset += $oggpageinfo['header_end_offset'] - $oggpageinfo['page_start_offset'];
|
||||||
|
}
|
||||||
|
$commentstring = substr($commentdata, $commentdataoffset, $ThisFileInfo['ogg']['comments_raw'][$i]['size']);
|
||||||
|
$commentdataoffset += $ThisFileInfo['ogg']['comments_raw'][$i]['size'];
|
||||||
|
|
||||||
|
if (!$commentstring) {
|
||||||
|
|
||||||
|
// no comment?
|
||||||
|
$ThisFileInfo['warning'] .= "\n".'Blank Ogg comment ['.$i.']';
|
||||||
|
|
||||||
|
} elseif (strstr($commentstring, '=')) {
|
||||||
|
|
||||||
|
$commentexploded = explode('=', $commentstring, 2);
|
||||||
|
$ThisFileInfo['ogg']['comments_raw'][$i]['key'] = strtoupper($commentexploded[0]);
|
||||||
|
$ThisFileInfo['ogg']['comments_raw'][$i]['value'] = ($commentexploded[1] ? utf8_decode($commentexploded[1]) : '');
|
||||||
|
$ThisFileInfo['ogg']['comments_raw'][$i]['data'] = base64_decode($ThisFileInfo['ogg']['comments_raw'][$i]['value']);
|
||||||
|
|
||||||
|
$ThisFileInfo['ogg']['comments'][strtolower($ThisFileInfo['ogg']['comments_raw'][$i]['key'])][] = $ThisFileInfo['ogg']['comments_raw'][$i]['value'];
|
||||||
|
|
||||||
|
require_once(GETID3_INCLUDEPATH.'getid3.getimagesize.php');
|
||||||
|
$imagechunkcheck = GetDataImageSize($ThisFileInfo['ogg']['comments_raw'][$i]['data']);
|
||||||
|
$ThisFileInfo['ogg']['comments_raw'][$i]['image_mime'] = image_type_to_mime_type($imagechunkcheck[2]);
|
||||||
|
if (!$ThisFileInfo['ogg']['comments_raw'][$i]['image_mime'] || ($ThisFileInfo['ogg']['comments_raw'][$i]['image_mime'] == 'application/octet-stream')) {
|
||||||
|
unset($ThisFileInfo['ogg']['comments_raw'][$i]['image_mime']);
|
||||||
|
unset($ThisFileInfo['ogg']['comments_raw'][$i]['data']);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
$ThisFileInfo['warning'] .= "\n".'[known problem with CDex >= v1.40, < v1.50b7] Invalid Ogg comment name/value pair ['.$i.']: '.$commentstring;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Check for presence of vorbiscomments
|
||||||
|
if (isset($ThisFileInfo['ogg']['comments'])) {
|
||||||
|
$ThisFileInfo['tags'][] = 'vorbiscomment';
|
||||||
|
|
||||||
|
// Yank other comments - vorbiscomments has highest preference
|
||||||
|
if (isset($ThisFileInfo['ogg']['comments'])) {
|
||||||
|
CopyFormatCommentsToRootComments($ThisFileInfo['ogg']['comments'], $ThisFileInfo, true, true, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Replay Gain Adjustment
|
||||||
|
// http://privatewww.essex.ac.uk/~djmrob/replaygain/
|
||||||
|
if (isset($ThisFileInfo['ogg']['comments']) && is_array($ThisFileInfo['ogg']['comments'])) {
|
||||||
|
foreach ($ThisFileInfo['ogg']['comments'] as $index => $keyvaluepair) {
|
||||||
|
if (isset($keyvaluepair['key'])) {
|
||||||
|
switch ($keyvaluepair['key']) {
|
||||||
|
case 'RG_AUDIOPHILE':
|
||||||
|
case 'REPLAYGAIN_ALBUM_GAIN':
|
||||||
|
$ThisFileInfo['replay_gain']['audiophile']['adjustment'] = (double) $keyvaluepair['value'];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'RG_RADIO':
|
||||||
|
case 'REPLAYGAIN_TRACK_GAIN':
|
||||||
|
$ThisFileInfo['replay_gain']['radio']['adjustment'] = (double) $keyvaluepair['value'];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'REPLAYGAIN_ALBUM_PEAK':
|
||||||
|
$ThisFileInfo['replay_gain']['audiophile']['peak'] = (double) $keyvaluepair['value'];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'RG_PEAK':
|
||||||
|
case 'REPLAYGAIN_TRACK_PEAK':
|
||||||
|
$ThisFileInfo['replay_gain']['radio']['peak'] = (double) $keyvaluepair['value'];
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
default:
|
||||||
|
// do nothing
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fseek($fd, $OriginalOffset, SEEK_SET);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function SpeexBandModeLookup($mode) {
|
||||||
|
static $SpeexBandModeLookup = array();
|
||||||
|
if (empty($SpeexBandModeLookup)) {
|
||||||
|
$SpeexBandModeLookup[0] = 'narrow';
|
||||||
|
$SpeexBandModeLookup[1] = 'wide';
|
||||||
|
$SpeexBandModeLookup[2] = 'ultra-wide';
|
||||||
|
}
|
||||||
|
return (isset($SpeexBandModeLookup[$mode]) ? $SpeexBandModeLookup[$mode] : null);
|
||||||
|
}
|
||||||
|
|
||||||
|
function OggPageSegmentLength($OggInfoArray, $SegmentNumber=1) {
|
||||||
|
for ($i = 0; $i < $SegmentNumber; $i++) {
|
||||||
|
$segmentlength = 0;
|
||||||
|
foreach ($OggInfoArray['segment_table'] as $key => $value) {
|
||||||
|
$segmentlength += $value;
|
||||||
|
if ($value < 255) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $segmentlength;
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
21
livesupport/modules/getid3/var/getid3.optimfrog.php
Normal file
21
livesupport/modules/getid3/var/getid3.optimfrog.php
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
<?php
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
/// getID3() by James Heinrich <getid3@users.sourceforge.net> //
|
||||||
|
// available at http://getid3.sourceforge.net ///
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
// //
|
||||||
|
// getid3.optimfrog.php - part of getID3() //
|
||||||
|
// See getid3.readme.txt for more details //
|
||||||
|
// //
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
function getOptimFrogFilepointer(&$fd, &$ThisFileInfo) {
|
||||||
|
|
||||||
|
$ThisFileInfo['fileformat'] = 'ofr';
|
||||||
|
|
||||||
|
$ThisFileInfo['error'] .= "\n".'OptimFrog parsing not enabled in this version of getID3()';
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
459
livesupport/modules/getid3/var/getid3.readme.txt
Normal file
459
livesupport/modules/getid3/var/getid3.readme.txt
Normal file
|
@ -0,0 +1,459 @@
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
/// getID3() by James Heinrich <getid3@users.sourceforge.net> //
|
||||||
|
// available at http://getid3.sourceforge.net ///
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
This code is released under the GNU GPL:
|
||||||
|
http://www.gnu.org/copyleft/gpl.html
|
||||||
|
|
||||||
|
+---------------------------------------------+
|
||||||
|
| If you do use this code somewhere, send me |
|
||||||
|
| an email and tell me how/where you used it. |
|
||||||
|
| |
|
||||||
|
| If you really like it, send me a postcard: |
|
||||||
|
| James Heinrich |
|
||||||
|
| 17 Scott Street |
|
||||||
|
| Kingston, Ontario |
|
||||||
|
| K7L 1L3 |
|
||||||
|
| Canada |
|
||||||
|
+---------------------------------------------+
|
||||||
|
|
||||||
|
|
||||||
|
What does getID3() do?
|
||||||
|
======================
|
||||||
|
|
||||||
|
Reads & parses (to varying degrees):
|
||||||
|
* APE tags: v1 and v2
|
||||||
|
* ASF: ASF, Windows Media Audio (WMA), Windows Media Video (WMV)
|
||||||
|
* BMP (Windows & OS/2, uncompressed / RLE4 / RLE8)
|
||||||
|
* CD-audio (*.cda)
|
||||||
|
* FLAC
|
||||||
|
* GIF
|
||||||
|
* ISO-9660 CD-ROM image (directory structure)
|
||||||
|
* JPEG
|
||||||
|
* LA (Lossless Audio)
|
||||||
|
* Lyrics 3: v1 and v2
|
||||||
|
* MIDI
|
||||||
|
* Monkey's Audio
|
||||||
|
* MPC / Musepack
|
||||||
|
* ID3v1 & ID3v1.1
|
||||||
|
* ID3v2.2, ID3v2.3, ID3v2.4
|
||||||
|
* MP3: MPEG-audio information (bitrate, sampling frequency, etc)
|
||||||
|
* Lyrics3 v1 & v2
|
||||||
|
* MPEG-1 video frame size, bitrate, aspect ratio, etc
|
||||||
|
* NSV (Nullsoft Streaming Video)
|
||||||
|
* Ogg Vorbis: stream information, comment tags
|
||||||
|
* PNG
|
||||||
|
* Quicktime
|
||||||
|
* RealAudio, RealVideo
|
||||||
|
* RIFF: AVI audio/video information (codecs, bitrates, frame sizes, etc)
|
||||||
|
* RIFF: WAV audio information (bitrate, sampling frequency, etc)
|
||||||
|
* Speex
|
||||||
|
* VQF
|
||||||
|
* ZIP (directory structure)
|
||||||
|
|
||||||
|
Writes:
|
||||||
|
* ID3v1 & ID3v1.1
|
||||||
|
* ID3v2.3 & ID3v2.4
|
||||||
|
* Ogg Vorbis comment tags
|
||||||
|
|
||||||
|
|
||||||
|
Requirements
|
||||||
|
============
|
||||||
|
|
||||||
|
* PHP 4.1.0 (or higher)
|
||||||
|
* GD <1.6 for GIF and JPEG functions
|
||||||
|
* GD >=1.6 for PNG and JPEG functions
|
||||||
|
|
||||||
|
|
||||||
|
Notes
|
||||||
|
=====
|
||||||
|
|
||||||
|
If the format parser encounters a problem, it will return something
|
||||||
|
in $fileinfo['error'], describing the encountered error. If nothing is
|
||||||
|
returned in that array element, you can assume the entire file parsed OK.
|
||||||
|
|
||||||
|
Conforms to ID3v2.2, ID3v2.3 and ID3v2.4 specs as published at www.id3.org
|
||||||
|
|
||||||
|
|
||||||
|
Known Bugs/Issues
|
||||||
|
=================
|
||||||
|
|
||||||
|
See the end of getid3.changelog.txt for notes on known issues with getID3(),
|
||||||
|
encoders, players, etc.
|
||||||
|
|
||||||
|
|
||||||
|
Disclaimer
|
||||||
|
==========
|
||||||
|
|
||||||
|
getID3() has been tested on many systems, on many types of files, under many
|
||||||
|
operating systems, and is generally believe to be stable and safe.
|
||||||
|
That being said, there is still the chance there is an undiscovered and/or
|
||||||
|
unfixed bug that may potentially corrupt your file, especially within the
|
||||||
|
writing functions. By using getID3() you agree that it's not my fault if
|
||||||
|
any of your files are corrupted. In fact, I'm not liable for anything :)
|
||||||
|
|
||||||
|
|
||||||
|
Usage
|
||||||
|
=====
|
||||||
|
|
||||||
|
For detailed examples of implementation, see getid3.check.php
|
||||||
|
|
||||||
|
$mp3info = GetAllMP3info(<filename>);
|
||||||
|
$mp3info = GetAllMP3info('/home/mp3s/song.mp3');
|
||||||
|
$mp3info = GetAllMP3info('c:\\mp3s\\song.mp3');
|
||||||
|
$mp3info = GetAllMP3info('http://www.example.com/song.mp3');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Sample recursive scanning code that scans every file starting in the
|
||||||
|
// current directory (or whatever $DirectoryToStartScanningFrom is set
|
||||||
|
// to).
|
||||||
|
|
||||||
|
/*
|
||||||
|
$DirectoryToStartScanningFrom = '.';
|
||||||
|
$DirectoriesToScan = array(realpath($DirectoryToStartScanningFrom));
|
||||||
|
$DirectoriesScanned = array();
|
||||||
|
while (count($DirectoriesToScan) > 0) {
|
||||||
|
foreach ($DirectoriesToScan as $DirectoryKey => $startingdir) {
|
||||||
|
if ($dir = @opendir($startingdir)) {
|
||||||
|
while (($file = readdir($dir)) !== false) {
|
||||||
|
if (($file != '.') && ($file != '..')) {
|
||||||
|
$RealPathName = realpath($startingdir.'/'.$file);
|
||||||
|
if (is_dir($RealPathName)) {
|
||||||
|
if (!in_array($RealPathName, $DirectoriesScanned) && !in_array($RealPathName, $DirectoriesToScan)) {
|
||||||
|
$DirectoriesToScan[] = $RealPathName;
|
||||||
|
}
|
||||||
|
} else if (is_file($RealPathName)) {
|
||||||
|
$FilesInDir[] = $RealPathName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
closedir($dir);
|
||||||
|
}
|
||||||
|
$DirectoriesScanned[] = $startingdir;
|
||||||
|
unset($DirectoriesToScan[$DirectoryKey]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$FilesInDir = array_unique($FilesInDir);
|
||||||
|
sort($FilesInDir);
|
||||||
|
|
||||||
|
require_once('getid3.php');
|
||||||
|
foreach ($FilesInDir as $filename) {
|
||||||
|
|
||||||
|
set_time_limit(30);
|
||||||
|
$fileinfo = GetAllFileInfo($filename);
|
||||||
|
|
||||||
|
// do something with $fileinfo here...
|
||||||
|
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
What does the returned data structure look like?
|
||||||
|
================================================
|
||||||
|
|
||||||
|
array() {
|
||||||
|
['exist']=>bool() // does this file actually exist?
|
||||||
|
['filename']=>string() // filename including extension, not including path
|
||||||
|
['filesize']=>int() // in bytes
|
||||||
|
['getID3version']=>string() // ex: '1.4.0'
|
||||||
|
['error']=>string() // if present, what error occured
|
||||||
|
['fileformat']=>string() // 'mp3', 'mp2', 'zip', 'ogg', 'id3', 'mpg', 'riff', 'wav', 'midi', 'asf', 'mac', 'ape', 'gif', 'jpg', 'png', 'bmp', 'mpc', 'real'
|
||||||
|
['dataformat']=>string() //
|
||||||
|
['bitrate_audio']=>float() // total bitrate for audio stream (if present) in bits per second
|
||||||
|
['bitrate_video']=>float() // total bitrate for video stream (if present) in bits per second
|
||||||
|
['bitrate']=>float() // total bitrate (audio + video) in bits per second
|
||||||
|
['bitrate_mode']=>string() // 'cbr' or 'vbr' or 'abr'
|
||||||
|
['resolution_x']=>int() // horizontal resolution of video stream, if present
|
||||||
|
['resolution_y']=>int() // vertical resolution of video stream, if present
|
||||||
|
['playtime_seconds']=>float() // playtime in floating-point seconds
|
||||||
|
['playtime_string']=>string() // playtime in minutes:seconds format
|
||||||
|
['audiobytes']=>int() // bytes of MPEG audio, with ID3v2 headers stripped
|
||||||
|
['audiodataoffset']=>int() // byte offset where start of data is (not counting prepended / appended tags)
|
||||||
|
['audiodataend']=>int() // byte offset where end of data is (not counting prepended / appended tags)
|
||||||
|
['mime_type']=>string() //
|
||||||
|
['id3v1']=>
|
||||||
|
array(8) {
|
||||||
|
['title']=>string()
|
||||||
|
['artist']=>string()
|
||||||
|
['album']=>string()
|
||||||
|
['year']=>string()
|
||||||
|
['comment']=>string()
|
||||||
|
['genreid']=>int()
|
||||||
|
['genre']=>string()
|
||||||
|
['track']=>int()
|
||||||
|
}
|
||||||
|
['id3v2']=>array(8) { // ID3v2.x data
|
||||||
|
['header']=>bool()
|
||||||
|
['majorversion']=>int()
|
||||||
|
['minorversion']=>int()
|
||||||
|
['flags']['unsynch']=>bool()
|
||||||
|
['flags']['exthead']=>bool()
|
||||||
|
['flags']['experim']=>bool()
|
||||||
|
['flags']['isfooter']=>bool()
|
||||||
|
['headerlength']=>int() // in bytes, including the 6/10-byte ID3v2 header
|
||||||
|
['title']=>string()
|
||||||
|
['artist']=>string()
|
||||||
|
['album']=>string()
|
||||||
|
['year']=>string()
|
||||||
|
['track']=>string()
|
||||||
|
['totaltracks']=>string()
|
||||||
|
['genre']=>string()
|
||||||
|
['genreid']=>int()
|
||||||
|
['genrelist']=>array()
|
||||||
|
['comment']=>string()
|
||||||
|
['padding']=>array() {
|
||||||
|
['start']=>int() // start of padding, byte offset from beginning of file
|
||||||
|
['length']=>int() // amount of padding, in bytes
|
||||||
|
['valid']=>bool() // TRUE if padding consists entirely of null bytes
|
||||||
|
['errorpos']=>int() // position of non-null byte, byte offset from beginning of file
|
||||||
|
}
|
||||||
|
[<3- or 4-char frame name>]=> // see http://www.id3.org/id3v2.4.0-structure.txt
|
||||||
|
array { // for details on which 4-character name represents which data
|
||||||
|
['flags']=>string() // NOTE: the actual structure varies depending on the FrameID
|
||||||
|
['datalength']=>int() // length of frame data (in bytes) not including 6/10-byte frame header
|
||||||
|
['dataoffset']=>int() // offset of beginning of frame from beginning of file, in *de-unsynchronized* bytes
|
||||||
|
['asciidata']=>string() // approximate translation from text-encodings other than ISO-8859-1 (ie UTF-16, UTF-16BE and UTF-8)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
['lyrics3']=>array() { // for MP3 files with Lyrics3 tag only
|
||||||
|
}
|
||||||
|
['ogg']=>array() { // for Ogg Vorbis files only
|
||||||
|
['comments']=>array() {
|
||||||
|
[n]=>array() {
|
||||||
|
['key']=>string // 'TITLE', 'ARTIST', etc [http://www.xiph.org/ogg/vorbis/doc/v-comment.html]
|
||||||
|
['value']=>string // 'Yellow Submarine', 'The Beatles', etc
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
['riff']=>array() { // for RIFF/WAV files only
|
||||||
|
['raw']=>array() { // data as read in, unprocessed
|
||||||
|
['riff']=>array() {
|
||||||
|
['size']=>int() // in bytes
|
||||||
|
}
|
||||||
|
['WAVE']=>array() {
|
||||||
|
['size']=>int() // in bytes
|
||||||
|
}
|
||||||
|
['fmt ']=>array() { // note the trailing space
|
||||||
|
['size']=>int() // in bytes
|
||||||
|
['wFormatTag']=>int() // waveform format code
|
||||||
|
['nChannels']=>int() // 1 (mono) or 2 (stereo)
|
||||||
|
['nSamplesPerSec']=>int() // samples per second (aka frequency)
|
||||||
|
['nAvgBytesPerSec']=>int() // byterate, bytes per second
|
||||||
|
['nBlockAlign']=> // The block alignment (in bytes) of the waveform data
|
||||||
|
}
|
||||||
|
['rgad']=>array() {
|
||||||
|
['size']=>int() // in bytes
|
||||||
|
['fPeakAmplitude']=>float() // 1 means the .wav file peaks at digital full scale (equivalent to -32768 for 16-bit wav)
|
||||||
|
['nRadioRgAdjust']=>int() // meaningless by itself, see below array
|
||||||
|
['nAudiophileRgAdjust']=>int() // meaningless by itself, see below array
|
||||||
|
['radio']=>array() { // settings for Radio Gain Adjustment
|
||||||
|
['name']=>int() // represents 'Radio' or 'not set'
|
||||||
|
['originator']=>int() // how/by whom the RGAD was set/calculated
|
||||||
|
['signbit']=>int() // 1->negative, 0->positive
|
||||||
|
['adjustment']=>int() // absolute value of adjustment, multiplied by 10
|
||||||
|
}
|
||||||
|
['audiophile']=>array() { //
|
||||||
|
['name']=>int() // represents 'Audiophile' or 'not set'
|
||||||
|
['originator']=>int() // how/by whom the RGAD was set/calculated
|
||||||
|
['signbit']=>int() // 1->negative, 0->positive
|
||||||
|
['adjustment']=>int() // absolute value of adjustment, multiplied by 10
|
||||||
|
}
|
||||||
|
}
|
||||||
|
['data']=>array() {
|
||||||
|
['size']=>int() // in bytes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
['rgad']=>array() {
|
||||||
|
['peakamplitude']=>float() // 1 means the .wav file peaks at digital full scale (equivalent to -32768 for 16-bit wav)
|
||||||
|
['radio']=>array() {
|
||||||
|
['name']=>string() // 'Radio Gain Adjustment'
|
||||||
|
['originator']=>string() // how/by whom the RGAD was set/calculated
|
||||||
|
['adjustment']=>float() // adjustment in dB
|
||||||
|
}
|
||||||
|
['audiophile']=>array() {
|
||||||
|
['name']=>string() // 'Audiophile Gain Adjustment'
|
||||||
|
['originator']=>string() // how/by whom the RGAD was set/calculated
|
||||||
|
['adjustment']=>float() // adjustment in dB
|
||||||
|
}
|
||||||
|
}
|
||||||
|
['audio']=>array() {
|
||||||
|
[n]=>array() {
|
||||||
|
['codec']=>string() // MS-PCM, IBM mu-law, IBM a-law, IBM ADPCM
|
||||||
|
['channels']=>int() // 1 (mono) or 2 (stereo)
|
||||||
|
['channelmode']=>string() // 'mono' or 'stereo'
|
||||||
|
['frequency']=>int() // sampling frequency in Hz
|
||||||
|
['bitrate']=>int() // in bits per second
|
||||||
|
['bitspersample']=>int()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
['mpeg']=>array() {
|
||||||
|
['audio']=>array() { // MPEG audio data
|
||||||
|
['version']=>string() // MPEG audio version - 1, 2, or 2.5
|
||||||
|
['layer']=>string() // MPEG audio layer - I, II or III
|
||||||
|
['protection']=>boolean()
|
||||||
|
['bitrate']=>int() // in kbps, ex: 128 (CBR files only)
|
||||||
|
['frequency']=>int() // in Hz, ex: 44100
|
||||||
|
['padding']=>boolean()
|
||||||
|
['private']=>boolean()
|
||||||
|
['channelmode']=>string() // mono, stereo, joint stereo or dual channel
|
||||||
|
['channels']=>int() // 1 or 2
|
||||||
|
['modeextension']=>string() // IS, MS, IS+MS for Layer III; 4-31, 8-31, 12-31, 16-31 for Layer I or Layer II
|
||||||
|
['copyright']=>boolean()
|
||||||
|
['original']=>boolean()
|
||||||
|
['emphasis']=>string() // none, 50/15 ms or CCIT J.17
|
||||||
|
['raw']=>array() {
|
||||||
|
// same as above, but unparsed integer values
|
||||||
|
}
|
||||||
|
['VBR_bitrate']=>double() // exact average bitrate in kbps (VBR files only)
|
||||||
|
['bitratemode']=>string() // 'VBR' or 'CBR'
|
||||||
|
['VBR_method']=>string() // 'Xing' or 'Fraunhofer' (VBR files only)
|
||||||
|
['VBR_frames']=>int() // NOT including the Xing / Fraunhofer (VBRI) header frame (VBR files only)
|
||||||
|
['VBR_bytes']=>int() // should be the same as ['audiobytes'] (VBR files only)
|
||||||
|
['VBR_quality']=>int() // 0-100 (VBR, Fraunhofer only)
|
||||||
|
['VBR_seek_offsets']=>int() // number of seek offsets
|
||||||
|
['VBR_seek_offsets_stride']=>int() // offset "stride" (number of frames between offsets)
|
||||||
|
['VBR_offsets_relative']=>array() // array of seek offsets (from previous offset)
|
||||||
|
['VBR_offsets_absolute']=>array() // array of seek offsets (from beginning of file)
|
||||||
|
|
||||||
|
['video']=>array() { // MPEG video data
|
||||||
|
['framesize_horizontal']=>int() // frame width in pixels (ex: 352)
|
||||||
|
['framesize_vertical']=>int() // frame height in pixels (ex: 240)
|
||||||
|
['pixel_aspect_ratio']=>float() // pixel aspect ratio (ex: 1.095)
|
||||||
|
['pixel_aspect_ratio_text']=>string() // pixel aspect ratio (ex: '4:3, 525 line, NTSC, CCIR601')
|
||||||
|
['frame_rate']=>int() // frames per second (ex: 25)
|
||||||
|
['bitrate_type']=>int() // 'constant' or 'variable'
|
||||||
|
['bitrate_bps']=>int() // bits per second (ex: 1150000)
|
||||||
|
['raw']=>array() {
|
||||||
|
// same as above, but unparsed integer values
|
||||||
|
}
|
||||||
|
}
|
||||||
|
['replay_gain']=>array() {
|
||||||
|
['radio']=>array() {
|
||||||
|
['peak']=>double() // peak level - 1.0 = 100%
|
||||||
|
['originator']=>string() // who set the replay gain
|
||||||
|
['adjustment']=>double() // adjustment in dB
|
||||||
|
}
|
||||||
|
['audiophile']=>array() {
|
||||||
|
['peak']=>double() // peak level - 1.0 = 100%
|
||||||
|
['originator']=>string() // who set the replay gain
|
||||||
|
['adjustment']=>double() // adjustment in dB
|
||||||
|
}
|
||||||
|
}
|
||||||
|
['asf']=>array() {
|
||||||
|
}
|
||||||
|
['mpc']=>array() {
|
||||||
|
}
|
||||||
|
['real']=>array() {
|
||||||
|
}
|
||||||
|
['jpg']=>array() {
|
||||||
|
}
|
||||||
|
['gif']=>array() {
|
||||||
|
}
|
||||||
|
['png']=>array() {
|
||||||
|
}
|
||||||
|
['bmp']=>array() {
|
||||||
|
['type_os']=>string() // 'OS/2' or 'Windows'
|
||||||
|
['type_version']=>int() // 1 or
|
||||||
|
['header']=>array() {
|
||||||
|
}
|
||||||
|
['palette']=>array() {
|
||||||
|
}
|
||||||
|
['data']=>array() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
['flac']=>array() {
|
||||||
|
}
|
||||||
|
['vqf']=>array() {
|
||||||
|
}
|
||||||
|
['aac']=>array() {
|
||||||
|
}
|
||||||
|
['quicktime']=>array() {
|
||||||
|
}
|
||||||
|
['zip']=>array() {
|
||||||
|
}
|
||||||
|
['iso']=>array() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License
|
||||||
|
as published by the Free Software Foundation; either version 2
|
||||||
|
of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to:
|
||||||
|
Free Software Foundation, Inc.
|
||||||
|
59 Temple Place - Suite 330
|
||||||
|
Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
Reference material:
|
||||||
|
[www.id3.org material now mirrored at http://id3lib.sourceforge.net/id3/]
|
||||||
|
* http://www.id3.org/id3v2.4.0-structure.txt
|
||||||
|
* http://www.id3.org/id3v2.4.0-frames.txt
|
||||||
|
* http://www.id3.org/id3v2.4.0-changes.txt
|
||||||
|
* http://www.id3.org/id3v2.3.0.txt
|
||||||
|
* http://www.id3.org/id3v2-00.txt
|
||||||
|
* http://www.id3.org/mp3frame.html
|
||||||
|
* http://minnie.tuhs.org/pipermail/mp3encoder/2001-January/001800.html <mathewhendry@hotmail.com>
|
||||||
|
* http://www.dv.co.yu/mpgscript/mpeghdr.htm
|
||||||
|
* http://www.mp3-tech.org/programmer/frame_header.html
|
||||||
|
* http://users.belgacom.net/gc247244/extra/tag.html
|
||||||
|
* http://www.id3.org/iso4217.html
|
||||||
|
* http://www.unicode.org/Public/MAPPINGS/ISO8859/8859-1.TXT
|
||||||
|
* http://www.xiph.org/ogg/vorbis/doc/framing.html
|
||||||
|
* http://www.xiph.org/ogg/vorbis/doc/v-comment.html
|
||||||
|
* http://leknor.com/code/php/class.ogg.php.txt
|
||||||
|
* http://www.id3.org/iso639-2.html
|
||||||
|
* http://www.psc.edu/general/software/packages/ieee/ieee.html
|
||||||
|
* http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/ieee-expl.html
|
||||||
|
* http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/binary.html
|
||||||
|
* http://www.jmcgowan.com/avi.html
|
||||||
|
* http://www.wotsit.org/
|
||||||
|
* http://www.herdsoft.com/ti/davincie/davp3xo2.htm
|
||||||
|
* http://www.mathdogs.com/vorbis-illuminated/bitstream-appendix.html
|
||||||
|
* "Standard MIDI File Format" by Dustin Caldwell (from www.wotsit.org)
|
||||||
|
* http://midistudio.com/Help/GMSpecs_Patches.htm
|
||||||
|
* http://www.xiph.org/archives/vorbis/200109/0459.html
|
||||||
|
* http://www.replaygain.org/
|
||||||
|
* http://www.lossless-audio.com/
|
||||||
|
* http://download.microsoft.com/download/winmediatech40/Doc/1.0/WIN98MeXP/EN-US/ASF_Specification_v.1.0.exe
|
||||||
|
* http://mediaxw.sourceforge.net/files/doc/Active%20Streaming%20Format%20(ASF)%201.0%20Specification.pdf
|
||||||
|
* http://www.uni-jena.de/~pfk/mpp/sv8/
|
||||||
|
* http://jfaul.de/atl/
|
||||||
|
* http://www.uni-jena.de/~pfk/mpp/
|
||||||
|
* http://www.libpng.org/pub/png/spec/png-1.2-pdg.html
|
||||||
|
* http://www.real.com/devzone/library/creating/rmsdk/doc/rmff.htm
|
||||||
|
* http://www.fastgraph.com/help/bmp_os2_header_format.html
|
||||||
|
* http://netghost.narod.ru/gff/graphics/summary/os2bmp.htm
|
||||||
|
* http://flac.sourceforge.net/format.html
|
||||||
|
* http://www.research.att.com/projects/mpegaudio/mpeg2.html
|
||||||
|
* http://www.audiocoding.com/wiki/index.php?page=AAC
|
||||||
|
* http://libmpeg.org/mpeg4/doc/w2203tfs.pdf
|
||||||
|
* http://www.geocities.com/xhelmboyx/quicktime/formats/qtm-layout.txt
|
||||||
|
* http://developer.apple.com/techpubs/quicktime/qtdevdocs/RM/frameset.htm
|
||||||
|
* http://www.nullsoft.com/nsv/
|
||||||
|
* http://www.wotsit.org/download.asp?f=iso9660
|
||||||
|
* http://sandbox.mc.edu/~bennet/cs110/tc/tctod.html
|
||||||
|
* http://www.cdroller.com/htm/readdata.html
|
||||||
|
* http://www.speex.org/manual/node10.html
|
||||||
|
* http://www.harmony-central.com/Computer/Programming/aiff-file-format.doc
|
||||||
|
* http://www.faqs.org/rfcs/rfc2361.html
|
216
livesupport/modules/getid3/var/getid3.real.php
Normal file
216
livesupport/modules/getid3/var/getid3.real.php
Normal file
|
@ -0,0 +1,216 @@
|
||||||
|
<?php
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
/// getID3() by James Heinrich <getid3@users.sourceforge.net> //
|
||||||
|
// available at http://getid3.sourceforge.net ///
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
// //
|
||||||
|
// getid3.real.php - part of getID3() //
|
||||||
|
// See getid3.readme.txt for more details //
|
||||||
|
// //
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
function getRealHeaderFilepointer(&$fd, &$ThisFileInfo) {
|
||||||
|
$ThisFileInfo['fileformat'] = 'real';
|
||||||
|
$ThisFileInfo['bitrate'] = 0;
|
||||||
|
$ThisFileInfo['playtime_seconds'] = 0;
|
||||||
|
|
||||||
|
fseek($fd, $ThisFileInfo['avdataoffset'], SEEK_SET);
|
||||||
|
$ChunkCounter = 0;
|
||||||
|
while (ftell($fd) < $ThisFileInfo['avdataend']) {
|
||||||
|
$ChunkData = fread($fd, 8);
|
||||||
|
$ChunkName = substr($ChunkData, 0, 4);
|
||||||
|
$ChunkSize = BigEndian2Int(substr($ChunkData, 4, 4));
|
||||||
|
|
||||||
|
$ThisFileInfo['real']['chunks'][$ChunkCounter]['name'] = $ChunkName;
|
||||||
|
$ThisFileInfo['real']['chunks'][$ChunkCounter]['offset'] = ftell($fd) - 8;
|
||||||
|
$ThisFileInfo['real']['chunks'][$ChunkCounter]['length'] = $ChunkSize;
|
||||||
|
$ChunkData .= fread($fd, $ChunkSize - 8);
|
||||||
|
$offset = 8;
|
||||||
|
|
||||||
|
switch ($ChunkName) {
|
||||||
|
|
||||||
|
case '.RMF': // RealMedia File Header
|
||||||
|
$ThisFileInfo['real']['chunks'][$ChunkCounter]['object_version'] = BigEndian2Int(substr($ChunkData, $offset, 2));
|
||||||
|
$offset += 2;
|
||||||
|
switch ($ThisFileInfo['real']['chunks'][$ChunkCounter]['object_version']) {
|
||||||
|
|
||||||
|
case 0:
|
||||||
|
$ThisFileInfo['real']['chunks'][$ChunkCounter]['file_version'] = BigEndian2Int(substr($ChunkData, $offset, 4));
|
||||||
|
$offset += 4;
|
||||||
|
$ThisFileInfo['real']['chunks'][$ChunkCounter]['headers_count'] = BigEndian2Int(substr($ChunkData, $offset, 4));
|
||||||
|
$offset += 4;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
//$ThisFileInfo['warning'] .= "\n".'Expected .RMF-object_version to be "0", actual value is "'.$ThisFileInfo['real']['chunks'][$ChunkCounter]['object_version'].'" (should not be a problem)';
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
case 'PROP': // Properties Header
|
||||||
|
$ThisFileInfo['real']['chunks'][$ChunkCounter]['object_version'] = BigEndian2Int(substr($ChunkData, $offset, 2));
|
||||||
|
$offset += 2;
|
||||||
|
if ($ThisFileInfo['real']['chunks'][$ChunkCounter]['object_version'] == 0) {
|
||||||
|
$ThisFileInfo['real']['chunks'][$ChunkCounter]['max_bit_rate'] = BigEndian2Int(substr($ChunkData, $offset, 4));
|
||||||
|
$offset += 4;
|
||||||
|
$ThisFileInfo['real']['chunks'][$ChunkCounter]['avg_bit_rate'] = BigEndian2Int(substr($ChunkData, $offset, 4));
|
||||||
|
$offset += 4;
|
||||||
|
$ThisFileInfo['real']['chunks'][$ChunkCounter]['max_packet_size'] = BigEndian2Int(substr($ChunkData, $offset, 4));
|
||||||
|
$offset += 4;
|
||||||
|
$ThisFileInfo['real']['chunks'][$ChunkCounter]['avg_packet_size'] = BigEndian2Int(substr($ChunkData, $offset, 4));
|
||||||
|
$offset += 4;
|
||||||
|
$ThisFileInfo['real']['chunks'][$ChunkCounter]['num_packets'] = BigEndian2Int(substr($ChunkData, $offset, 4));
|
||||||
|
$offset += 4;
|
||||||
|
$ThisFileInfo['real']['chunks'][$ChunkCounter]['duration'] = BigEndian2Int(substr($ChunkData, $offset, 4));
|
||||||
|
$offset += 4;
|
||||||
|
$ThisFileInfo['real']['chunks'][$ChunkCounter]['preroll'] = BigEndian2Int(substr($ChunkData, $offset, 4));
|
||||||
|
$offset += 4;
|
||||||
|
$ThisFileInfo['real']['chunks'][$ChunkCounter]['index_offset'] = BigEndian2Int(substr($ChunkData, $offset, 4));
|
||||||
|
$offset += 4;
|
||||||
|
$ThisFileInfo['real']['chunks'][$ChunkCounter]['data_offset'] = BigEndian2Int(substr($ChunkData, $offset, 4));
|
||||||
|
$offset += 4;
|
||||||
|
$ThisFileInfo['real']['chunks'][$ChunkCounter]['num_streams'] = BigEndian2Int(substr($ChunkData, $offset, 2));
|
||||||
|
$offset += 2;
|
||||||
|
$ThisFileInfo['real']['chunks'][$ChunkCounter]['flags_raw'] = BigEndian2Int(substr($ChunkData, $offset, 2));
|
||||||
|
$offset += 2;
|
||||||
|
|
||||||
|
$ThisFileInfo['playtime_seconds'] = $ThisFileInfo['real']['chunks'][$ChunkCounter]['duration'] / 1000;
|
||||||
|
if ($ThisFileInfo['real']['chunks'][$ChunkCounter]['duration'] > 0) {
|
||||||
|
$ThisFileInfo['bitrate'] += $ThisFileInfo['real']['chunks'][$ChunkCounter]['avg_bit_rate'];
|
||||||
|
}
|
||||||
|
$ThisFileInfo['real']['chunks'][$ChunkCounter]['flags']['save_enabled'] = (bool) ($ThisFileInfo['real']['chunks'][$ChunkCounter]['flags_raw'] & 0x0001);
|
||||||
|
$ThisFileInfo['real']['chunks'][$ChunkCounter]['flags']['perfect_play'] = (bool) ($ThisFileInfo['real']['chunks'][$ChunkCounter]['flags_raw'] & 0x0002);
|
||||||
|
$ThisFileInfo['real']['chunks'][$ChunkCounter]['flags']['live_broadcast'] = (bool) ($ThisFileInfo['real']['chunks'][$ChunkCounter]['flags_raw'] & 0x0004);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'MDPR': // Media Properties Header
|
||||||
|
$ThisFileInfo['real']['chunks'][$ChunkCounter]['object_version'] = BigEndian2Int(substr($ChunkData, $offset, 2));
|
||||||
|
$offset += 2;
|
||||||
|
if ($ThisFileInfo['real']['chunks'][$ChunkCounter]['object_version'] == 0) {
|
||||||
|
$ThisFileInfo['real']['chunks'][$ChunkCounter]['stream_number'] = BigEndian2Int(substr($ChunkData, $offset, 2));
|
||||||
|
$offset += 2;
|
||||||
|
$ThisFileInfo['real']['chunks'][$ChunkCounter]['max_bit_rate'] = BigEndian2Int(substr($ChunkData, $offset, 4));
|
||||||
|
$offset += 4;
|
||||||
|
$ThisFileInfo['real']['chunks'][$ChunkCounter]['avg_bit_rate'] = BigEndian2Int(substr($ChunkData, $offset, 4));
|
||||||
|
$offset += 4;
|
||||||
|
$ThisFileInfo['real']['chunks'][$ChunkCounter]['max_packet_size'] = BigEndian2Int(substr($ChunkData, $offset, 4));
|
||||||
|
$offset += 4;
|
||||||
|
$ThisFileInfo['real']['chunks'][$ChunkCounter]['avg_packet_size'] = BigEndian2Int(substr($ChunkData, $offset, 4));
|
||||||
|
$offset += 4;
|
||||||
|
$ThisFileInfo['real']['chunks'][$ChunkCounter]['start_time'] = BigEndian2Int(substr($ChunkData, $offset, 4));
|
||||||
|
$offset += 4;
|
||||||
|
$ThisFileInfo['real']['chunks'][$ChunkCounter]['preroll'] = BigEndian2Int(substr($ChunkData, $offset, 4));
|
||||||
|
$offset += 4;
|
||||||
|
$ThisFileInfo['real']['chunks'][$ChunkCounter]['duration'] = BigEndian2Int(substr($ChunkData, $offset, 4));
|
||||||
|
$offset += 4;
|
||||||
|
$ThisFileInfo['real']['chunks'][$ChunkCounter]['stream_name_size'] = BigEndian2Int(substr($ChunkData, $offset, 1));
|
||||||
|
$offset += 1;
|
||||||
|
$ThisFileInfo['real']['chunks'][$ChunkCounter]['stream_name'] = substr($ChunkData, $offset, $ThisFileInfo['real']['chunks'][$ChunkCounter]['stream_name_size']);
|
||||||
|
$offset += $ThisFileInfo['real']['chunks'][$ChunkCounter]['stream_name_size'];
|
||||||
|
$ThisFileInfo['real']['chunks'][$ChunkCounter]['mime_type_size'] = BigEndian2Int(substr($ChunkData, $offset, 1));
|
||||||
|
$offset += 1;
|
||||||
|
$ThisFileInfo['real']['chunks'][$ChunkCounter]['mime_type'] = substr($ChunkData, $offset, $ThisFileInfo['real']['chunks'][$ChunkCounter]['mime_type_size']);
|
||||||
|
$offset += $ThisFileInfo['real']['chunks'][$ChunkCounter]['mime_type_size'];
|
||||||
|
$ThisFileInfo['real']['chunks'][$ChunkCounter]['type_specific_len'] = BigEndian2Int(substr($ChunkData, $offset, 4));
|
||||||
|
$offset += 4;
|
||||||
|
$ThisFileInfo['real']['chunks'][$ChunkCounter]['type_specific_data'] = substr($ChunkData, $offset, $ThisFileInfo['real']['chunks'][$ChunkCounter]['type_specific_len']);
|
||||||
|
$offset += $ThisFileInfo['real']['chunks'][$ChunkCounter]['type_specific_len'];
|
||||||
|
|
||||||
|
if (empty($ThisFileInfo['playtime_seconds'])) {
|
||||||
|
$ThisFileInfo['playtime_seconds'] = max($ThisFileInfo['playtime_seconds'], ($ThisFileInfo['real']['chunks'][$ChunkCounter]['duration'] + $ThisFileInfo['real']['chunks'][$ChunkCounter]['start_time']) / 1000);
|
||||||
|
}
|
||||||
|
if ($ThisFileInfo['real']['chunks'][$ChunkCounter]['duration'] > 0) {
|
||||||
|
if (strstr($ThisFileInfo['real']['chunks'][$ChunkCounter]['mime_type'], 'audio')) {
|
||||||
|
$ThisFileInfo['audio']['bitrate'] = (isset($ThisFileInfo['audio']['bitrate']) ? $ThisFileInfo['audio']['bitrate'] : 0) + $ThisFileInfo['real']['chunks'][$ChunkCounter]['avg_bit_rate'];
|
||||||
|
$ThisFileInfo['audio']['dataformat'] = 'real';
|
||||||
|
} elseif (strstr($ThisFileInfo['real']['chunks'][$ChunkCounter]['mime_type'], 'video')) {
|
||||||
|
$ThisFileInfo['video']['bitrate'] = (isset($ThisFileInfo['video']['bitrate']) ? $ThisFileInfo['video']['bitrate'] : 0) + $ThisFileInfo['real']['chunks'][$ChunkCounter]['avg_bit_rate'];
|
||||||
|
$ThisFileInfo['video']['dataformat'] = 'real';
|
||||||
|
}
|
||||||
|
$ThisFileInfo['bitrate'] = (isset($ThisFileInfo['video']['bitrate']) ? $ThisFileInfo['video']['bitrate'] : 0) + (isset($ThisFileInfo['audio']['bitrate']) ? $ThisFileInfo['audio']['bitrate'] : 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'CONT': // Content Description Header
|
||||||
|
$ThisFileInfo['real']['chunks'][$ChunkCounter]['object_version'] = BigEndian2Int(substr($ChunkData, $offset, 2));
|
||||||
|
$offset += 2;
|
||||||
|
if ($ThisFileInfo['real']['chunks'][$ChunkCounter]['object_version'] == 0) {
|
||||||
|
$ThisFileInfo['real']['chunks'][$ChunkCounter]['raw']['title_len'] = BigEndian2Int(substr($ChunkData, $offset, 2));
|
||||||
|
$offset += 2;
|
||||||
|
$ThisFileInfo['real']['chunks'][$ChunkCounter]['title'] = (string) substr($ChunkData, $offset, $ThisFileInfo['real']['chunks'][$ChunkCounter]['raw']['title_len']);
|
||||||
|
$offset += $ThisFileInfo['real']['chunks'][$ChunkCounter]['raw']['title_len'];
|
||||||
|
|
||||||
|
$ThisFileInfo['real']['chunks'][$ChunkCounter]['raw']['artist_len'] = BigEndian2Int(substr($ChunkData, $offset, 2));
|
||||||
|
$offset += 2;
|
||||||
|
$ThisFileInfo['real']['chunks'][$ChunkCounter]['artist'] = (string) substr($ChunkData, $offset, $ThisFileInfo['real']['chunks'][$ChunkCounter]['raw']['artist_len']);
|
||||||
|
$offset += $ThisFileInfo['real']['chunks'][$ChunkCounter]['raw']['artist_len'];
|
||||||
|
|
||||||
|
$ThisFileInfo['real']['chunks'][$ChunkCounter]['raw']['copyright_len'] = BigEndian2Int(substr($ChunkData, $offset, 2));
|
||||||
|
$offset += 2;
|
||||||
|
$ThisFileInfo['real']['chunks'][$ChunkCounter]['copyright'] = (string) substr($ChunkData, $offset, $ThisFileInfo['real']['chunks'][$ChunkCounter]['raw']['copyright_len']);
|
||||||
|
$offset += $ThisFileInfo['real']['chunks'][$ChunkCounter]['raw']['copyright_len'];
|
||||||
|
|
||||||
|
$ThisFileInfo['real']['chunks'][$ChunkCounter]['raw']['comment_len'] = BigEndian2Int(substr($ChunkData, $offset, 2));
|
||||||
|
$offset += 2;
|
||||||
|
$ThisFileInfo['real']['chunks'][$ChunkCounter]['comment'] = (string) substr($ChunkData, $offset, $ThisFileInfo['real']['chunks'][$ChunkCounter]['raw']['comment_len']);
|
||||||
|
$offset += $ThisFileInfo['real']['chunks'][$ChunkCounter]['raw']['comment_len'];
|
||||||
|
|
||||||
|
|
||||||
|
$commentkeystocopy = array('title'=>'title', 'artist'=>'artist', 'comment'=>'comment');
|
||||||
|
foreach ($commentkeystocopy as $key => $val) {
|
||||||
|
if ($ThisFileInfo['real']['chunks'][$ChunkCounter]["$key"]) {
|
||||||
|
$ThisFileInfo['real']['comments']["$val"] = $ThisFileInfo['real']['chunks'][$ChunkCounter]["$key"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RealMedia tags have highest priority
|
||||||
|
if (!empty($ThisFileInfo['real']['comments'])) {
|
||||||
|
CopyFormatCommentsToRootComments($ThisFileInfo['real']['comments'], $ThisFileInfo, true, true, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// add tag to array of tags
|
||||||
|
$ThisFileInfo['tags'][] = 'real';
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
case 'DATA': // Data Chunk Header
|
||||||
|
// do nothing
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'INDX': // Index Section Header
|
||||||
|
$ThisFileInfo['real']['chunks'][$ChunkCounter]['object_version'] = BigEndian2Int(substr($ChunkData, $offset, 2));
|
||||||
|
$offset += 2;
|
||||||
|
if ($ThisFileInfo['real']['chunks'][$ChunkCounter]['object_version'] == 0) {
|
||||||
|
$ThisFileInfo['real']['chunks'][$ChunkCounter]['num_indices'] = BigEndian2Int(substr($ChunkData, $offset, 4));
|
||||||
|
$offset += 4;
|
||||||
|
$ThisFileInfo['real']['chunks'][$ChunkCounter]['stream_number'] = BigEndian2Int(substr($ChunkData, $offset, 2));
|
||||||
|
$offset += 2;
|
||||||
|
$ThisFileInfo['real']['chunks'][$ChunkCounter]['next_index_header'] = BigEndian2Int(substr($ChunkData, $offset, 4));
|
||||||
|
$offset += 4;
|
||||||
|
|
||||||
|
if ($ThisFileInfo['real']['chunks'][$ChunkCounter]['next_index_header'] == 0) {
|
||||||
|
// last index chunk found, ignore rest of file
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
// non-last index chunk, seek to next index chunk (skipping actual index data)
|
||||||
|
fseek($fd, $ThisFileInfo['real']['chunks'][$ChunkCounter]['next_index_header'], SEEK_SET);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
$ThisFileInfo['warning'] .= "\n".'Unhandled RealMedia chunk "'.$ChunkName.'" at offset '.$ThisFileInfo['real']['chunks'][$ChunkCounter]['offset'];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
$ChunkCounter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
875
livesupport/modules/getid3/var/getid3.riff.php
Normal file
875
livesupport/modules/getid3/var/getid3.riff.php
Normal file
|
@ -0,0 +1,875 @@
|
||||||
|
<?php
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
/// getID3() by James Heinrich <getid3@users.sourceforge.net> //
|
||||||
|
// available at http://getid3.sourceforge.net ///
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
// //
|
||||||
|
// getid3.riff.php - part of getID3() //
|
||||||
|
// See getid3.readme.txt for more details //
|
||||||
|
// //
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
function getRIFFHeaderFilepointer(&$fd, &$ThisFileInfo) {
|
||||||
|
fseek($fd, $ThisFileInfo['avdataoffset'], SEEK_SET);
|
||||||
|
$RIFFheader = fread($fd, 12);
|
||||||
|
switch (substr($RIFFheader, 0, 4)) {
|
||||||
|
case 'RIFF':
|
||||||
|
case 'SDSS': // SDSS is identical to RIFF, just renamed. Used by SmartSound QuickTracks (www.smartsound.com)
|
||||||
|
$ThisFileInfo['fileformat'] = 'riff';
|
||||||
|
$ThisFileInfo['RIFF'][substr($RIFFheader, 8, 4)] = ParseRIFF($fd, $ThisFileInfo['avdataoffset'] + 12, $ThisFileInfo['avdataoffset'] + LittleEndian2Int(substr($RIFFheader, 4, 4)), $ThisFileInfo);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
$ThisFileInfo['error'] .= "\n".'Cannot parse RIFF (this is maybe not a RIFF / WAV / AVI file?)';
|
||||||
|
unset($ThisFileInfo['fileformat']);
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
$streamindex = 0;
|
||||||
|
$arraykeys = array_keys($ThisFileInfo['RIFF']);
|
||||||
|
switch ($arraykeys[0]) {
|
||||||
|
case 'WAVE':
|
||||||
|
$ThisFileInfo['audio']['bitrate_mode'] = 'cbr';
|
||||||
|
$ThisFileInfo['audio']['dataformat'] = 'wav';
|
||||||
|
if (isset($ThisFileInfo['RIFF']['WAVE']['fmt '][0]['data'])) {
|
||||||
|
|
||||||
|
$ThisFileInfo['RIFF']['audio'][$streamindex] = RIFFparseWAVEFORMATex($ThisFileInfo['RIFF']['WAVE']['fmt '][0]['data']);
|
||||||
|
|
||||||
|
if ($ThisFileInfo['RIFF']['audio'][$streamindex] == 0) {
|
||||||
|
$ThisFileInfo['error'] .= 'Corrupt RIFF file: bitrate_audio == zero';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$ThisFileInfo['RIFF']['raw']['fmt '] = $ThisFileInfo['RIFF']['audio'][$streamindex]['raw'];
|
||||||
|
unset($ThisFileInfo['RIFF']['audio'][$streamindex]['raw']);
|
||||||
|
$ThisFileInfo['audio'] = array_merge_noclobber($ThisFileInfo['audio'], $ThisFileInfo['RIFF']['audio'][$streamindex]);
|
||||||
|
|
||||||
|
$ThisFileInfo['audio']['bitrate'] = $ThisFileInfo['RIFF']['audio'][$streamindex]['bitrate'];
|
||||||
|
|
||||||
|
$ThisFileInfo['playtime_seconds'] = (float) ((($ThisFileInfo['avdataend'] - $ThisFileInfo['avdataoffset']) * 8) / $ThisFileInfo['audio']['bitrate']);
|
||||||
|
|
||||||
|
if (isset($ThisFileInfo['RIFF']['WAVE']['data'][0]['offset']) && isset($ThisFileInfo['RIFF']['raw']['fmt ']['wFormatTag'])) {
|
||||||
|
switch ($ThisFileInfo['RIFF']['raw']['fmt ']['wFormatTag']) {
|
||||||
|
|
||||||
|
case 85: // LAME ACM
|
||||||
|
require_once(GETID3_INCLUDEPATH.'getid3.mp3.php');
|
||||||
|
getOnlyMPEGaudioInfo($fd, $ThisFileInfo, $ThisFileInfo['RIFF']['WAVE']['data'][0]['offset'], false);
|
||||||
|
$ThisFileInfo['audio']['dataformat'] = 'mp3';
|
||||||
|
if (isset($ThisFileInfo['mpeg']['audio'])) {
|
||||||
|
$ThisFileInfo['audio']['sample_rate'] = $ThisFileInfo['mpeg']['audio']['sample_rate'];
|
||||||
|
$ThisFileInfo['audio']['channels'] = $ThisFileInfo['mpeg']['audio']['channels'];
|
||||||
|
$ThisFileInfo['audio']['bitrate'] = $ThisFileInfo['mpeg']['audio']['bitrate'] * 1000;
|
||||||
|
$ThisFileInfo['bitrate'] = $ThisFileInfo['audio']['bitrate'];
|
||||||
|
$ThisFileInfo['audio']['bitrate_mode'] = strtolower($ThisFileInfo['mpeg']['audio']['bitratemode']);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
// do nothing
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isset($ThisFileInfo['RIFF']['WAVE']['rgad'][0]['data'])) {
|
||||||
|
require_once(GETID3_INCLUDEPATH.'getid3.rgad.php');
|
||||||
|
|
||||||
|
$rgadData = $ThisFileInfo['RIFF']['WAVE']['rgad'][0]['data'];
|
||||||
|
$ThisFileInfo['RIFF']['raw']['rgad']['fPeakAmplitude'] = LittleEndian2Float(substr($rgadData, 0, 4));
|
||||||
|
$ThisFileInfo['RIFF']['raw']['rgad']['nRadioRgAdjust'] = LittleEndian2Int(substr($rgadData, 4, 2));
|
||||||
|
$ThisFileInfo['RIFF']['raw']['rgad']['nAudiophileRgAdjust'] = LittleEndian2Int(substr($rgadData, 6, 2));
|
||||||
|
$nRadioRgAdjustBitstring = str_pad(Dec2Bin($ThisFileInfo['RIFF']['raw']['rgad']['nRadioRgAdjust']), 16, '0', STR_PAD_LEFT);
|
||||||
|
$nAudiophileRgAdjustBitstring = str_pad(Dec2Bin($ThisFileInfo['RIFF']['raw']['rgad']['nAudiophileRgAdjust']), 16, '0', STR_PAD_LEFT);
|
||||||
|
$ThisFileInfo['RIFF']['raw']['rgad']['radio']['name'] = Bin2Dec(substr($nRadioRgAdjustBitstring, 0, 3));
|
||||||
|
$ThisFileInfo['RIFF']['raw']['rgad']['radio']['originator'] = Bin2Dec(substr($nRadioRgAdjustBitstring, 3, 3));
|
||||||
|
$ThisFileInfo['RIFF']['raw']['rgad']['radio']['signbit'] = Bin2Dec(substr($nRadioRgAdjustBitstring, 6, 1));
|
||||||
|
$ThisFileInfo['RIFF']['raw']['rgad']['radio']['adjustment'] = Bin2Dec(substr($nRadioRgAdjustBitstring, 7, 9));
|
||||||
|
$ThisFileInfo['RIFF']['raw']['rgad']['audiophile']['name'] = Bin2Dec(substr($nAudiophileRgAdjustBitstring, 0, 3));
|
||||||
|
$ThisFileInfo['RIFF']['raw']['rgad']['audiophile']['originator'] = Bin2Dec(substr($nAudiophileRgAdjustBitstring, 3, 3));
|
||||||
|
$ThisFileInfo['RIFF']['raw']['rgad']['audiophile']['signbit'] = Bin2Dec(substr($nAudiophileRgAdjustBitstring, 6, 1));
|
||||||
|
$ThisFileInfo['RIFF']['raw']['rgad']['audiophile']['adjustment'] = Bin2Dec(substr($nAudiophileRgAdjustBitstring, 7, 9));
|
||||||
|
|
||||||
|
$ThisFileInfo['RIFF']['rgad']['peakamplitude'] = $ThisFileInfo['RIFF']['raw']['rgad']['fPeakAmplitude'];
|
||||||
|
if (($ThisFileInfo['RIFF']['raw']['rgad']['radio']['name'] != 0) && ($ThisFileInfo['RIFF']['raw']['rgad']['radio']['originator'] != 0)) {
|
||||||
|
$ThisFileInfo['RIFF']['rgad']['radio']['name'] = RGADnameLookup($ThisFileInfo['RIFF']['raw']['rgad']['radio']['name']);
|
||||||
|
$ThisFileInfo['RIFF']['rgad']['radio']['originator'] = RGADoriginatorLookup($ThisFileInfo['RIFF']['raw']['rgad']['radio']['originator']);
|
||||||
|
$ThisFileInfo['RIFF']['rgad']['radio']['adjustment'] = RGADadjustmentLookup($ThisFileInfo['RIFF']['raw']['rgad']['radio']['adjustment'], $ThisFileInfo['RIFF']['raw']['rgad']['radio']['signbit']);
|
||||||
|
}
|
||||||
|
if (($ThisFileInfo['RIFF']['raw']['rgad']['audiophile']['name'] != 0) && ($ThisFileInfo['RIFF']['raw']['rgad']['audiophile']['originator'] != 0)) {
|
||||||
|
$ThisFileInfo['RIFF']['rgad']['audiophile']['name'] = RGADnameLookup($ThisFileInfo['RIFF']['raw']['rgad']['audiophile']['name']);
|
||||||
|
$ThisFileInfo['RIFF']['rgad']['audiophile']['originator'] = RGADoriginatorLookup($ThisFileInfo['RIFF']['raw']['rgad']['audiophile']['originator']);
|
||||||
|
$ThisFileInfo['RIFF']['rgad']['audiophile']['adjustment'] = RGADadjustmentLookup($ThisFileInfo['RIFF']['raw']['rgad']['audiophile']['adjustment'], $ThisFileInfo['RIFF']['raw']['rgad']['audiophile']['signbit']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isset($ThisFileInfo['RIFF']['WAVE']['fact'][0]['data'])) {
|
||||||
|
$ThisFileInfo['RIFF']['raw']['fact']['NumberOfSamples'] = LittleEndian2Int(substr($ThisFileInfo['RIFF']['WAVE']['fact'][0]['data'], 0, 4));
|
||||||
|
|
||||||
|
if (isset($ThisFileInfo['RIFF']['raw']['fmt ']['nSamplesPerSec']) && ($ThisFileInfo['RIFF']['raw']['fmt ']['nSamplesPerSec'] > 0)) {
|
||||||
|
$ThisFileInfo['playtime_seconds'] = (float) $ThisFileInfo['RIFF']['raw']['fact']['NumberOfSamples'] / $ThisFileInfo['RIFF']['raw']['fmt ']['nSamplesPerSec'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($ThisFileInfo['RIFF']['raw']['fmt ']['nAvgBytesPerSec']) && $ThisFileInfo['RIFF']['raw']['fmt ']['nAvgBytesPerSec']) {
|
||||||
|
$ThisFileInfo['audio']['bitrate'] = CastAsInt($ThisFileInfo['RIFF']['raw']['fmt ']['nAvgBytesPerSec'] * 8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($ThisFileInfo['audio']['bitrate']) && isset($ThisFileInfo['RIFF']['audio'][$streamindex]['bitrate'])) {
|
||||||
|
$ThisFileInfo['audio']['bitrate'] = $ThisFileInfo['RIFF']['audio'][$streamindex]['bitrate'];
|
||||||
|
$ThisFileInfo['playtime_seconds'] = (float) ((($ThisFileInfo['avdataend'] - $ThisFileInfo['avdataoffset']) * 8) / $ThisFileInfo['audio']['bitrate']);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'AVI ':
|
||||||
|
$ThisFileInfo['video']['bitrate_mode'] = 'cbr';
|
||||||
|
$ThisFileInfo['video']['dataformat'] = 'avi';
|
||||||
|
$ThisFileInfo['mime_type'] = 'video/avi';
|
||||||
|
if (isset($ThisFileInfo['RIFF']['AVI ']['hdrl']['avih'][$streamindex]['data'])) {
|
||||||
|
$avihData = $ThisFileInfo['RIFF']['AVI ']['hdrl']['avih'][$streamindex]['data'];
|
||||||
|
$ThisFileInfo['RIFF']['raw']['avih']['dwMicroSecPerFrame'] = LittleEndian2Int(substr($avihData, 0, 4)); // frame display rate (or 0L)
|
||||||
|
if ($ThisFileInfo['RIFF']['raw']['avih']['dwMicroSecPerFrame'] == 0) {
|
||||||
|
$ThisFileInfo['error'] .= 'Corrupt RIFF file: avih.dwMicroSecPerFrame == zero';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$ThisFileInfo['RIFF']['raw']['avih']['dwMaxBytesPerSec'] = LittleEndian2Int(substr($avihData, 4, 4)); // max. transfer rate
|
||||||
|
$ThisFileInfo['RIFF']['raw']['avih']['dwPaddingGranularity'] = LittleEndian2Int(substr($avihData, 8, 4)); // pad to multiples of this size; normally 2K.
|
||||||
|
$ThisFileInfo['RIFF']['raw']['avih']['dwFlags'] = LittleEndian2Int(substr($avihData, 12, 4)); // the ever-present flags
|
||||||
|
$ThisFileInfo['RIFF']['raw']['avih']['dwTotalFrames'] = LittleEndian2Int(substr($avihData, 16, 4)); // # frames in file
|
||||||
|
$ThisFileInfo['RIFF']['raw']['avih']['dwInitialFrames'] = LittleEndian2Int(substr($avihData, 20, 4));
|
||||||
|
$ThisFileInfo['RIFF']['raw']['avih']['dwStreams'] = LittleEndian2Int(substr($avihData, 24, 4));
|
||||||
|
$ThisFileInfo['RIFF']['raw']['avih']['dwSuggestedBufferSize'] = LittleEndian2Int(substr($avihData, 28, 4));
|
||||||
|
$ThisFileInfo['RIFF']['raw']['avih']['dwWidth'] = LittleEndian2Int(substr($avihData, 32, 4));
|
||||||
|
$ThisFileInfo['RIFF']['raw']['avih']['dwHeight'] = LittleEndian2Int(substr($avihData, 36, 4));
|
||||||
|
$ThisFileInfo['RIFF']['raw']['avih']['dwScale'] = LittleEndian2Int(substr($avihData, 40, 4));
|
||||||
|
$ThisFileInfo['RIFF']['raw']['avih']['dwRate'] = LittleEndian2Int(substr($avihData, 44, 4));
|
||||||
|
$ThisFileInfo['RIFF']['raw']['avih']['dwStart'] = LittleEndian2Int(substr($avihData, 48, 4));
|
||||||
|
$ThisFileInfo['RIFF']['raw']['avih']['dwLength'] = LittleEndian2Int(substr($avihData, 52, 4));
|
||||||
|
|
||||||
|
$ThisFileInfo['RIFF']['raw']['avih']['flags']['hasindex'] = (bool) ($ThisFileInfo['RIFF']['raw']['avih']['dwFlags'] & 0x00000010);
|
||||||
|
$ThisFileInfo['RIFF']['raw']['avih']['flags']['mustuseindex'] = (bool) ($ThisFileInfo['RIFF']['raw']['avih']['dwFlags'] & 0x00000020);
|
||||||
|
$ThisFileInfo['RIFF']['raw']['avih']['flags']['interleaved'] = (bool) ($ThisFileInfo['RIFF']['raw']['avih']['dwFlags'] & 0x00000100);
|
||||||
|
$ThisFileInfo['RIFF']['raw']['avih']['flags']['trustcktype'] = (bool) ($ThisFileInfo['RIFF']['raw']['avih']['dwFlags'] & 0x00000800);
|
||||||
|
$ThisFileInfo['RIFF']['raw']['avih']['flags']['capturedfile'] = (bool) ($ThisFileInfo['RIFF']['raw']['avih']['dwFlags'] & 0x00010000);
|
||||||
|
$ThisFileInfo['RIFF']['raw']['avih']['flags']['copyrighted'] = (bool) ($ThisFileInfo['RIFF']['raw']['avih']['dwFlags'] & 0x00020010);
|
||||||
|
|
||||||
|
|
||||||
|
$ThisFileInfo['RIFF']['video'][$streamindex]['frame_width'] = $ThisFileInfo['RIFF']['raw']['avih']['dwWidth'];
|
||||||
|
$ThisFileInfo['RIFF']['video'][$streamindex]['frame_height'] = $ThisFileInfo['RIFF']['raw']['avih']['dwHeight'];
|
||||||
|
$ThisFileInfo['RIFF']['video'][$streamindex]['frame_rate'] = round(1000000 / $ThisFileInfo['RIFF']['raw']['avih']['dwMicroSecPerFrame'], 3);
|
||||||
|
if (!isset($ThisFileInfo['video']['resolution_x'])) {
|
||||||
|
$ThisFileInfo['video']['resolution_x'] = $ThisFileInfo['RIFF']['video'][$streamindex]['frame_width'];
|
||||||
|
}
|
||||||
|
if (!isset($ThisFileInfo['video']['resolution_y'])) {
|
||||||
|
$ThisFileInfo['video']['resolution_y'] = $ThisFileInfo['RIFF']['video'][$streamindex]['frame_height'];
|
||||||
|
}
|
||||||
|
$ThisFileInfo['video']['frame_rate'] = $ThisFileInfo['RIFF']['video'][$streamindex]['frame_rate'];
|
||||||
|
}
|
||||||
|
if (isset($ThisFileInfo['RIFF']['AVI ']['hdrl']['strl']['strh'][0]['data'])) {
|
||||||
|
if (is_array($ThisFileInfo['RIFF']['AVI ']['hdrl']['strl']['strh'])) {
|
||||||
|
for ($i = 0; $i < count($ThisFileInfo['RIFF']['AVI ']['hdrl']['strl']['strh']); $i++) {
|
||||||
|
if (isset($ThisFileInfo['RIFF']['AVI ']['hdrl']['strl']['strh'][$i]['data'])) {
|
||||||
|
$strhData = $ThisFileInfo['RIFF']['AVI ']['hdrl']['strl']['strh'][$i]['data'];
|
||||||
|
$strhfccType = substr($strhData, 0, 4);
|
||||||
|
|
||||||
|
if (isset($ThisFileInfo['RIFF']['AVI ']['hdrl']['strl']['strf'][$i]['data'])) {
|
||||||
|
$strfData = $ThisFileInfo['RIFF']['AVI ']['hdrl']['strl']['strf'][$i]['data'];
|
||||||
|
switch ($strhfccType) {
|
||||||
|
case 'auds':
|
||||||
|
$ThisFileInfo['audio']['bitrate_mode'] = 'cbr';
|
||||||
|
$ThisFileInfo['audio']['dataformat'] = 'wav';
|
||||||
|
if (isset($ThisFileInfo['RIFF']['audio']) && is_array($ThisFileInfo['RIFF']['audio'])) {
|
||||||
|
$streamindex = count($ThisFileInfo['RIFF']['audio']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$ThisFileInfo['RIFF']['audio'][$streamindex] = RIFFparseWAVEFORMATex($strfData);
|
||||||
|
$ThisFileInfo['RIFF']['raw']['strf']["$strhfccType"][$streamindex] = $ThisFileInfo['RIFF']['audio'][$streamindex]['raw'];
|
||||||
|
unset($ThisFileInfo['RIFF']['audio'][$streamindex]['raw']);
|
||||||
|
|
||||||
|
$ThisFileInfo['audio'] = array_merge_noclobber($ThisFileInfo['audio'], $ThisFileInfo['RIFF']['audio'][$streamindex]);
|
||||||
|
|
||||||
|
switch ($ThisFileInfo['RIFF']['raw']['strf']["$strhfccType"][$streamindex]['wFormatTag']) {
|
||||||
|
case 85:
|
||||||
|
$ThisFileInfo['audio']['dataformat'] = 'mp3';
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 8192:
|
||||||
|
$ThisFileInfo['audio']['dataformat'] = 'ac3';
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
$ThisFileInfo['audio']['dataformat'] = 'wav';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
case 'iavs':
|
||||||
|
case 'vids':
|
||||||
|
$ThisFileInfo['RIFF']['raw']['strh'][$i]['fccType'] = substr($strhData, 0, 4); // same as $strhfccType;
|
||||||
|
$ThisFileInfo['RIFF']['raw']['strh'][$i]['fccHandler'] = substr($strhData, 4, 4);
|
||||||
|
$ThisFileInfo['RIFF']['raw']['strh'][$i]['dwFlags'] = LittleEndian2Int(substr($strhData, 8, 4)); // Contains AVITF_* flags
|
||||||
|
$ThisFileInfo['RIFF']['raw']['strh'][$i]['wPriority'] = LittleEndian2Int(substr($strhData, 12, 2));
|
||||||
|
$ThisFileInfo['RIFF']['raw']['strh'][$i]['wLanguage'] = LittleEndian2Int(substr($strhData, 14, 2));
|
||||||
|
$ThisFileInfo['RIFF']['raw']['strh'][$i]['dwInitialFrames'] = LittleEndian2Int(substr($strhData, 16, 4));
|
||||||
|
$ThisFileInfo['RIFF']['raw']['strh'][$i]['dwScale'] = LittleEndian2Int(substr($strhData, 20, 4));
|
||||||
|
$ThisFileInfo['RIFF']['raw']['strh'][$i]['dwRate'] = LittleEndian2Int(substr($strhData, 24, 4));
|
||||||
|
$ThisFileInfo['RIFF']['raw']['strh'][$i]['dwStart'] = LittleEndian2Int(substr($strhData, 28, 4));
|
||||||
|
$ThisFileInfo['RIFF']['raw']['strh'][$i]['dwLength'] = LittleEndian2Int(substr($strhData, 32, 4));
|
||||||
|
$ThisFileInfo['RIFF']['raw']['strh'][$i]['dwSuggestedBufferSize'] = LittleEndian2Int(substr($strhData, 36, 4));
|
||||||
|
$ThisFileInfo['RIFF']['raw']['strh'][$i]['dwQuality'] = LittleEndian2Int(substr($strhData, 40, 4));
|
||||||
|
$ThisFileInfo['RIFF']['raw']['strh'][$i]['dwSampleSize'] = LittleEndian2Int(substr($strhData, 44, 4));
|
||||||
|
$ThisFileInfo['RIFF']['raw']['strh'][$i]['rcFrame'] = LittleEndian2Int(substr($strhData, 48, 4));
|
||||||
|
|
||||||
|
$ThisFileInfo['RIFF']['video'][$streamindex]['codec'] = RIFFfourccLookup($ThisFileInfo['RIFF']['raw']['strh'][$i]['fccHandler']);
|
||||||
|
if (!$ThisFileInfo['RIFF']['video'][$streamindex]['codec'] && isset($ThisFileInfo['RIFF']['raw']['strf']["$strhfccType"][$streamindex]['fourcc']) && RIFFfourccLookup($ThisFileInfo['RIFF']['raw']['strf']["$strhfccType"][$streamindex]['fourcc'])) {
|
||||||
|
$ThisFileInfo['RIFF']['video'][$streamindex]['codec'] = RIFFfourccLookup($ThisFileInfo['RIFF']['raw']['strf']["$strhfccType"][$streamindex]['fourcc']);
|
||||||
|
}
|
||||||
|
$ThisFileInfo['video']['codec'] = $ThisFileInfo['RIFF']['video'][$streamindex]['codec'];
|
||||||
|
|
||||||
|
switch ($strhfccType) {
|
||||||
|
case 'vids':
|
||||||
|
$ThisFileInfo['RIFF']['raw']['strf']["$strhfccType"][$streamindex]['biSize'] = LittleEndian2Int(substr($strfData, 0, 4)); // number of bytes required by the BITMAPINFOHEADER structure
|
||||||
|
$ThisFileInfo['RIFF']['raw']['strf']["$strhfccType"][$streamindex]['biWidth'] = LittleEndian2Int(substr($strfData, 4, 4)); // width of the bitmap in pixels
|
||||||
|
$ThisFileInfo['RIFF']['raw']['strf']["$strhfccType"][$streamindex]['biHeight'] = LittleEndian2Int(substr($strfData, 8, 4)); // height of the bitmap in pixels. If biHeight is positive, the bitmap is a 'bottom-up' DIB and its origin is the lower left corner. If biHeight is negative, the bitmap is a 'top-down' DIB and its origin is the upper left corner
|
||||||
|
$ThisFileInfo['RIFF']['raw']['strf']["$strhfccType"][$streamindex]['biPlanes'] = LittleEndian2Int(substr($strfData, 12, 2)); // number of color planes on the target device. In most cases this value must be set to 1
|
||||||
|
$ThisFileInfo['RIFF']['raw']['strf']["$strhfccType"][$streamindex]['biBitCount'] = LittleEndian2Int(substr($strfData, 14, 2)); // Specifies the number of bits per pixels
|
||||||
|
$ThisFileInfo['RIFF']['raw']['strf']["$strhfccType"][$streamindex]['fourcc'] = substr($strfData, 16, 4); //
|
||||||
|
$ThisFileInfo['RIFF']['raw']['strf']["$strhfccType"][$streamindex]['biSizeImage'] = LittleEndian2Int(substr($strfData, 20, 4)); // size of the bitmap data section of the image (the actual pixel data, excluding BITMAPINFOHEADER and RGBQUAD structures)
|
||||||
|
$ThisFileInfo['RIFF']['raw']['strf']["$strhfccType"][$streamindex]['biXPelsPerMeter'] = LittleEndian2Int(substr($strfData, 24, 4)); // horizontal resolution, in pixels per metre, of the target device
|
||||||
|
$ThisFileInfo['RIFF']['raw']['strf']["$strhfccType"][$streamindex]['biYPelsPerMeter'] = LittleEndian2Int(substr($strfData, 28, 4)); // vertical resolution, in pixels per metre, of the target device
|
||||||
|
$ThisFileInfo['RIFF']['raw']['strf']["$strhfccType"][$streamindex]['biClrUsed'] = LittleEndian2Int(substr($strfData, 32, 4)); // actual number of color indices in the color table used by the bitmap. If this value is zero, the bitmap uses the maximum number of colors corresponding to the value of the biBitCount member for the compression mode specified by biCompression
|
||||||
|
$ThisFileInfo['RIFF']['raw']['strf']["$strhfccType"][$streamindex]['biClrImportant'] = LittleEndian2Int(substr($strfData, 36, 4)); // number of color indices that are considered important for displaying the bitmap. If this value is zero, all colors are important
|
||||||
|
|
||||||
|
if ($ThisFileInfo['RIFF']['video'][$streamindex]['codec'] == 'DV') {
|
||||||
|
$ThisFileInfo['RIFF']['video'][$streamindex]['dv_type'] = 2;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'iavs':
|
||||||
|
$ThisFileInfo['RIFF']['video'][$streamindex]['dv_type'] = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
$ThisFileInfo['warning'] .= "\n".'Unhandled fccType for stream ('.$i.'): "'.$strhfccType.'"';
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isset($ThisFileInfo['RIFF']['raw']['strf']["$strhfccType"][$streamindex]['fourcc']) && RIFFfourccLookup($ThisFileInfo['RIFF']['raw']['strf']["$strhfccType"][$streamindex]['fourcc'])) {
|
||||||
|
$ThisFileInfo['RIFF']['video'][$streamindex]['codec'] = RIFFfourccLookup($ThisFileInfo['RIFF']['raw']['strf']["$strhfccType"][$streamindex]['fourcc']);
|
||||||
|
$ThisFileInfo['video']['codec'] = $ThisFileInfo['RIFF']['video'][$streamindex]['codec'];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'CDDA':
|
||||||
|
$ThisFileInfo['audio']['bitrate_mode'] = 'cbr';
|
||||||
|
$ThisFileInfo['audio']['dataformat'] = 'cda';
|
||||||
|
unset($ThisFileInfo['mime_type']);
|
||||||
|
|
||||||
|
if (isset($ThisFileInfo['RIFF']['CDDA']['fmt '][0]['data'])) {
|
||||||
|
$fmtData = $ThisFileInfo['RIFF']['CDDA']['fmt '][0]['data'];
|
||||||
|
$ThisFileInfo['RIFF']['CDDA']['fmt '][0]['unknown1'] = LittleEndian2Int(substr($fmtData, 0, 2));
|
||||||
|
$ThisFileInfo['RIFF']['CDDA']['fmt '][0]['track_num'] = LittleEndian2Int(substr($fmtData, 2, 2));
|
||||||
|
$ThisFileInfo['RIFF']['CDDA']['fmt '][0]['disc_id'] = LittleEndian2Int(substr($fmtData, 4, 4));
|
||||||
|
$ThisFileInfo['RIFF']['CDDA']['fmt '][0]['start_offset_frame'] = LittleEndian2Int(substr($fmtData, 8, 4));
|
||||||
|
$ThisFileInfo['RIFF']['CDDA']['fmt '][0]['playtime_frames'] = LittleEndian2Int(substr($fmtData, 12, 4));
|
||||||
|
$ThisFileInfo['RIFF']['CDDA']['fmt '][0]['unknown6'] = LittleEndian2Int(substr($fmtData, 16, 4));
|
||||||
|
$ThisFileInfo['RIFF']['CDDA']['fmt '][0]['unknown7'] = LittleEndian2Int(substr($fmtData, 20, 4));
|
||||||
|
|
||||||
|
$ThisFileInfo['RIFF']['CDDA']['fmt '][0]['start_offset_seconds'] = (float) $ThisFileInfo['RIFF']['CDDA']['fmt '][0]['start_offset_frame'] / 75;
|
||||||
|
$ThisFileInfo['RIFF']['CDDA']['fmt '][0]['playtime_seconds'] = (float) $ThisFileInfo['RIFF']['CDDA']['fmt '][0]['playtime_frames'] / 75;
|
||||||
|
$ThisFileInfo['comments']['track'] = $ThisFileInfo['RIFF']['CDDA']['fmt '][0]['track_num'];
|
||||||
|
$ThisFileInfo['playtime_seconds'] = $ThisFileInfo['RIFF']['CDDA']['fmt '][0]['playtime_seconds'];
|
||||||
|
|
||||||
|
// hardcoded data for CD-audio
|
||||||
|
$ThisFileInfo['audio']['sample_rate'] = 44100;
|
||||||
|
$ThisFileInfo['audio']['channels'] = 2;
|
||||||
|
$ThisFileInfo['audio']['bits_per_sample'] = 16;
|
||||||
|
$ThisFileInfo['audio']['bitrate'] = $ThisFileInfo['audio']['sample_rate'] * $ThisFileInfo['audio']['channels'] * $ThisFileInfo['audio']['bits_per_sample'];
|
||||||
|
$ThisFileInfo['audio']['bitrate_mode'] = 'cbr';
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
default:
|
||||||
|
unset($ThisFileInfo['fileformat']);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($ThisFileInfo['RIFF']['WAVE']['DISP']) && is_array($ThisFileInfo['RIFF']['WAVE']['DISP'])) {
|
||||||
|
$ThisFileInfo['tags'][] = 'riff';
|
||||||
|
$ThisFileInfo['RIFF']['comments']['title'][] = trim(substr($ThisFileInfo['RIFF']['WAVE']['DISP'][count($ThisFileInfo['RIFF']['WAVE']['DISP']) - 1]['data'], 4));
|
||||||
|
}
|
||||||
|
if (isset($ThisFileInfo['RIFF']['WAVE']['INFO']) && is_array($ThisFileInfo['RIFF']['WAVE']['INFO'])) {
|
||||||
|
$ThisFileInfo['tags'][] = 'riff';
|
||||||
|
$RIFFinfoKeyLookup = array('IART'=>'artist', 'IGNR'=>'genre', 'ICMT'=>'comment', 'ICOP'=>'copyright', 'IENG'=>'engineers', 'IKEY'=>'keywords', 'IMED'=>'orignalmedium', 'INAM'=>'name', 'ISRC'=>'sourcesupplier', 'ITCH'=>'digitizer', 'ISBJ'=>'subject', 'ISRF'=>'digitizationsource');
|
||||||
|
foreach ($RIFFinfoKeyLookup as $key => $value) {
|
||||||
|
foreach ($ThisFileInfo['RIFF']['WAVE']['INFO']["$key"] as $commentid => $commentdata) {
|
||||||
|
if (trim($commentdata['data']) != '') {
|
||||||
|
$ThisFileInfo['RIFF']['comments']["$value"][] = trim($commentdata['data']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!empty($ThisFileInfo['RIFF']['comments'])) {
|
||||||
|
CopyFormatCommentsToRootComments($ThisFileInfo['RIFF']['comments'], $ThisFileInfo, true, true, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($ThisFileInfo['playtime_seconds'])) {
|
||||||
|
$ThisFileInfo['playtime_seconds'] = 0;
|
||||||
|
}
|
||||||
|
if (isset($ThisFileInfo['RIFF']['raw']['avih']['dwTotalFrames']) && isset($ThisFileInfo['RIFF']['raw']['avih']['dwMicroSecPerFrame'])) {
|
||||||
|
$ThisFileInfo['playtime_seconds'] = $ThisFileInfo['RIFF']['raw']['avih']['dwTotalFrames'] * ($ThisFileInfo['RIFF']['raw']['avih']['dwMicroSecPerFrame'] / 1000000);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($ThisFileInfo['playtime_seconds'] > 0) {
|
||||||
|
|
||||||
|
if (isset($ThisFileInfo['RIFF']['audio']) && isset($ThisFileInfo['RIFF']['video'])) {
|
||||||
|
|
||||||
|
if (!isset($ThisFileInfo['bitrate'])) {
|
||||||
|
$ThisFileInfo['bitrate'] = ((($ThisFileInfo['avdataend'] - $ThisFileInfo['avdataoffset']) / $ThisFileInfo['playtime_seconds']) * 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
} elseif (isset($ThisFileInfo['RIFF']['audio']) && !isset($ThisFileInfo['RIFF']['video'])) {
|
||||||
|
|
||||||
|
if (!isset($ThisFileInfo['audio']['bitrate'])) {
|
||||||
|
$ThisFileInfo['audio']['bitrate'] = ((($ThisFileInfo['avdataend'] - $ThisFileInfo['avdataoffset']) / $ThisFileInfo['playtime_seconds']) * 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
} elseif (!isset($ThisFileInfo['RIFF']['audio']) && isset($ThisFileInfo['RIFF']['video'])) {
|
||||||
|
|
||||||
|
if (!isset($ThisFileInfo['video']['bitrate'])) {
|
||||||
|
$ThisFileInfo['video']['bitrate'] = ((($ThisFileInfo['avdataend'] - $ThisFileInfo['avdataoffset']) / $ThisFileInfo['playtime_seconds']) * 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (isset($ThisFileInfo['RIFF']['video']) && isset($ThisFileInfo['audio']['bitrate']) && ($ThisFileInfo['audio']['bitrate'] > 0) && ($ThisFileInfo['playtime_seconds'] > 0)) {
|
||||||
|
$ThisFileInfo['audio']['bitrate'] = 0;
|
||||||
|
$ThisFileInfo['video']['bitrate'] = ((($ThisFileInfo['avdataend'] - $ThisFileInfo['avdataoffset']) / $ThisFileInfo['playtime_seconds']) * 8);
|
||||||
|
foreach ($ThisFileInfo['RIFF']['audio'] as $channelnumber => $audioinfoarray) {
|
||||||
|
$ThisFileInfo['video']['bitrate'] -= $audioinfoarray['bitrate'];
|
||||||
|
$ThisFileInfo['audio']['bitrate'] += $audioinfoarray['bitrate'];
|
||||||
|
}
|
||||||
|
if ($ThisFileInfo['video']['bitrate'] <= 0) {
|
||||||
|
unset($ThisFileInfo['video']['bitrate']);
|
||||||
|
}
|
||||||
|
if ($ThisFileInfo['audio']['bitrate'] <= 0) {
|
||||||
|
unset($ThisFileInfo['audio']['bitrate']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($ThisFileInfo['RIFF']['raw']['fmt ']['nBitsPerSample'])) {
|
||||||
|
$ThisFileInfo['audio']['bits_per_sample'] = $ThisFileInfo['RIFF']['raw']['fmt ']['nBitsPerSample'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip RIFF header
|
||||||
|
$ThisFileInfo['avdataoffset'] += 44;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function ParseRIFF(&$fd, $startoffset, $maxoffset, &$ThisFileInfo) {
|
||||||
|
$RIFFchunk = false;
|
||||||
|
|
||||||
|
fseek($fd, $startoffset, SEEK_SET);
|
||||||
|
|
||||||
|
while (ftell($fd) < $maxoffset) {
|
||||||
|
$chunkname = fread($fd, 4);
|
||||||
|
$chunksize = LittleEndian2Int(fread($fd, 4));
|
||||||
|
if (($chunksize % 2) != 0) {
|
||||||
|
// all structures are packed on word boundaries
|
||||||
|
$chunksize++;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ($chunkname) {
|
||||||
|
|
||||||
|
case 'LIST':
|
||||||
|
$listname = fread($fd, 4);
|
||||||
|
switch ($listname) {
|
||||||
|
case 'movi':
|
||||||
|
case 'rec ':
|
||||||
|
// skip over
|
||||||
|
$RIFFchunk["$listname"]['offset'] = ftell($fd) - 4;
|
||||||
|
$RIFFchunk["$listname"]['size'] = $chunksize;
|
||||||
|
fseek($fd, $chunksize - 4, SEEK_CUR);
|
||||||
|
|
||||||
|
$ThisFileInfo['avdataoffset'] = max($ThisFileInfo['avdataoffset'], $RIFFchunk["$listname"]['offset']);
|
||||||
|
$ThisFileInfo['avdataend'] = max($ThisFileInfo['avdataend'], $RIFFchunk["$listname"]['offset'] + $RIFFchunk["$listname"]['size']);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (!isset($RIFFchunk["$listname"])) {
|
||||||
|
$RIFFchunk["$listname"] = array();
|
||||||
|
}
|
||||||
|
$RIFFchunk["$listname"] = array_merge_recursive($RIFFchunk["$listname"], ParseRIFF($fd, ftell($fd), ftell($fd) + $chunksize - 4, $ThisFileInfo));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
$thisindex = 0;
|
||||||
|
if (isset($RIFFchunk["$chunkname"]) && is_array($RIFFchunk["$chunkname"])) {
|
||||||
|
$thisindex = count($RIFFchunk["$chunkname"]);
|
||||||
|
}
|
||||||
|
$RIFFchunk["$chunkname"][$thisindex]['offset'] = ftell($fd) - 8;
|
||||||
|
$RIFFchunk["$chunkname"][$thisindex]['size'] = $chunksize;
|
||||||
|
if ($chunksize <= 2048) {
|
||||||
|
$RIFFchunk["$chunkname"][$thisindex]['data'] = fread($fd, $chunksize);
|
||||||
|
} else {
|
||||||
|
fseek($fd, $chunksize, SEEK_CUR);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return $RIFFchunk;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function RIFFparseWAVEFORMATex($WaveFormatExData) {
|
||||||
|
$WaveFormatEx['raw']['wFormatTag'] = LittleEndian2Int(substr($WaveFormatExData, 0, 2));
|
||||||
|
$WaveFormatEx['raw']['nChannels'] = LittleEndian2Int(substr($WaveFormatExData, 2, 2));
|
||||||
|
$WaveFormatEx['raw']['nSamplesPerSec'] = LittleEndian2Int(substr($WaveFormatExData, 4, 4));
|
||||||
|
$WaveFormatEx['raw']['nAvgBytesPerSec'] = LittleEndian2Int(substr($WaveFormatExData, 8, 4));
|
||||||
|
$WaveFormatEx['raw']['nBlockAlign'] = LittleEndian2Int(substr($WaveFormatExData, 12, 2));
|
||||||
|
$WaveFormatEx['raw']['nBitsPerSample'] = LittleEndian2Int(substr($WaveFormatExData, 14, 2));
|
||||||
|
|
||||||
|
$WaveFormatEx['codec'] = RIFFwFormatTagLookup($WaveFormatEx['raw']['wFormatTag']);
|
||||||
|
$WaveFormatEx['channels'] = $WaveFormatEx['raw']['nChannels'];
|
||||||
|
$WaveFormatEx['sample_rate'] = $WaveFormatEx['raw']['nSamplesPerSec'];
|
||||||
|
$WaveFormatEx['bitrate'] = $WaveFormatEx['raw']['nAvgBytesPerSec'] * 8;
|
||||||
|
$WaveFormatEx['bits_per_sample'] = $WaveFormatEx['raw']['nBitsPerSample'];
|
||||||
|
|
||||||
|
return $WaveFormatEx;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function RIFFwFormatTagLookup($wFormatTag) {
|
||||||
|
static $RIFFwFormatTagLookup = array();
|
||||||
|
if (empty($RIFFwFormatTagLookup)) {
|
||||||
|
$RIFFwFormatTagLookup[0x0000] = 'Microsoft Unknown Wave Format';
|
||||||
|
$RIFFwFormatTagLookup[0x0001] = 'Microsoft Pulse Code Modulation (PCM)';
|
||||||
|
$RIFFwFormatTagLookup[0x0002] = 'Microsoft ADPCM';
|
||||||
|
$RIFFwFormatTagLookup[0x0003] = 'IEEE Float';
|
||||||
|
$RIFFwFormatTagLookup[0x0004] = 'Compaq Computer VSELP';
|
||||||
|
$RIFFwFormatTagLookup[0x0005] = 'IBM CVSD';
|
||||||
|
$RIFFwFormatTagLookup[0x0006] = 'Microsoft A-Law';
|
||||||
|
$RIFFwFormatTagLookup[0x0007] = 'Microsoft mu-Law';
|
||||||
|
$RIFFwFormatTagLookup[0x0010] = 'OKI ADPCM';
|
||||||
|
$RIFFwFormatTagLookup[0x0011] = 'Intel DVI/IMA ADPCM';
|
||||||
|
$RIFFwFormatTagLookup[0x0012] = 'Videologic MediaSpace ADPCM';
|
||||||
|
$RIFFwFormatTagLookup[0x0013] = 'Sierra Semiconductor ADPCM';
|
||||||
|
$RIFFwFormatTagLookup[0x0014] = 'Antex Electronics G.723 ADPCM';
|
||||||
|
$RIFFwFormatTagLookup[0x0015] = 'DSP Solutions DigiSTD';
|
||||||
|
$RIFFwFormatTagLookup[0x0016] = 'DSP Solutions DigiFIX';
|
||||||
|
$RIFFwFormatTagLookup[0x0017] = 'Dialogic OKI ADPCM';
|
||||||
|
$RIFFwFormatTagLookup[0x0018] = 'MediaVision ADPCM';
|
||||||
|
$RIFFwFormatTagLookup[0x0019] = 'Hewlett-Packard CU';
|
||||||
|
$RIFFwFormatTagLookup[0x0020] = 'Yamaha ADPCM';
|
||||||
|
$RIFFwFormatTagLookup[0x0021] = 'Speech Compression Sonarc';
|
||||||
|
$RIFFwFormatTagLookup[0x0022] = 'DSP Group TrueSpeech';
|
||||||
|
$RIFFwFormatTagLookup[0x0023] = 'Echo Speech EchoSC1';
|
||||||
|
$RIFFwFormatTagLookup[0x0024] = 'Audiofile AF36';
|
||||||
|
$RIFFwFormatTagLookup[0x0025] = 'Audio Processing Technology APTX';
|
||||||
|
$RIFFwFormatTagLookup[0x0026] = 'AudioFile AF10';
|
||||||
|
$RIFFwFormatTagLookup[0x0027] = 'Prosody 1612';
|
||||||
|
$RIFFwFormatTagLookup[0x0028] = 'LRC';
|
||||||
|
$RIFFwFormatTagLookup[0x0030] = 'Dolby AC2';
|
||||||
|
$RIFFwFormatTagLookup[0x0031] = 'Microsoft GSM 6.10';
|
||||||
|
$RIFFwFormatTagLookup[0x0032] = 'MSNAudio';
|
||||||
|
$RIFFwFormatTagLookup[0x0033] = 'Antex Electronics ADPCME';
|
||||||
|
$RIFFwFormatTagLookup[0x0034] = 'Control Resources VQLPC';
|
||||||
|
$RIFFwFormatTagLookup[0x0035] = 'DSP Solutions DigiREAL';
|
||||||
|
$RIFFwFormatTagLookup[0x0036] = 'DSP Solutions DigiADPCM';
|
||||||
|
$RIFFwFormatTagLookup[0x0037] = 'Control Resources CR10';
|
||||||
|
$RIFFwFormatTagLookup[0x0038] = 'Natural MicroSystems VBXADPCM';
|
||||||
|
$RIFFwFormatTagLookup[0x0039] = 'Crystal Semiconductor IMA ADPCM';
|
||||||
|
$RIFFwFormatTagLookup[0x003A] = 'EchoSC3';
|
||||||
|
$RIFFwFormatTagLookup[0x003B] = 'Rockwell ADPCM';
|
||||||
|
$RIFFwFormatTagLookup[0x003C] = 'Rockwell Digit LK';
|
||||||
|
$RIFFwFormatTagLookup[0x003D] = 'Xebec';
|
||||||
|
$RIFFwFormatTagLookup[0x0040] = 'Antex Electronics G.721 ADPCM';
|
||||||
|
$RIFFwFormatTagLookup[0x0041] = 'G.728 CELP';
|
||||||
|
$RIFFwFormatTagLookup[0x0042] = 'MSG723';
|
||||||
|
$RIFFwFormatTagLookup[0x0050] = 'Microsoft MPEG';
|
||||||
|
$RIFFwFormatTagLookup[0x0052] = 'RT24';
|
||||||
|
$RIFFwFormatTagLookup[0x0053] = 'PAC';
|
||||||
|
$RIFFwFormatTagLookup[0x0055] = 'MPEG Layer 3';
|
||||||
|
$RIFFwFormatTagLookup[0x0059] = 'Lucent G.723';
|
||||||
|
$RIFFwFormatTagLookup[0x0060] = 'Cirrus';
|
||||||
|
$RIFFwFormatTagLookup[0x0061] = 'ESPCM';
|
||||||
|
$RIFFwFormatTagLookup[0x0062] = 'Voxware';
|
||||||
|
$RIFFwFormatTagLookup[0x0063] = 'Canopus Atrac';
|
||||||
|
$RIFFwFormatTagLookup[0x0064] = 'G.726 ADPCM';
|
||||||
|
$RIFFwFormatTagLookup[0x0065] = 'G.722 ADPCM';
|
||||||
|
$RIFFwFormatTagLookup[0x0066] = 'DSAT';
|
||||||
|
$RIFFwFormatTagLookup[0x0067] = 'DSAT Display';
|
||||||
|
$RIFFwFormatTagLookup[0x0069] = 'Voxware Byte Aligned';
|
||||||
|
$RIFFwFormatTagLookup[0x0070] = 'Voxware AC8';
|
||||||
|
$RIFFwFormatTagLookup[0x0071] = 'Voxware AC10';
|
||||||
|
$RIFFwFormatTagLookup[0x0072] = 'Voxware AC16';
|
||||||
|
$RIFFwFormatTagLookup[0x0073] = 'Voxware AC20';
|
||||||
|
$RIFFwFormatTagLookup[0x0074] = 'Voxware MetaVoice';
|
||||||
|
$RIFFwFormatTagLookup[0x0075] = 'Voxware MetaSound';
|
||||||
|
$RIFFwFormatTagLookup[0x0076] = 'Voxware RT29HW';
|
||||||
|
$RIFFwFormatTagLookup[0x0077] = 'Voxware VR12';
|
||||||
|
$RIFFwFormatTagLookup[0x0078] = 'Voxware VR18';
|
||||||
|
$RIFFwFormatTagLookup[0x0079] = 'Voxware TQ40';
|
||||||
|
$RIFFwFormatTagLookup[0x0080] = 'Softsound';
|
||||||
|
$RIFFwFormatTagLookup[0x0081] = 'Voxware TQ60';
|
||||||
|
$RIFFwFormatTagLookup[0x0082] = 'MSRT24';
|
||||||
|
$RIFFwFormatTagLookup[0x0083] = 'G.729A';
|
||||||
|
$RIFFwFormatTagLookup[0x0084] = 'MVI MV12';
|
||||||
|
$RIFFwFormatTagLookup[0x0085] = 'DF G.726';
|
||||||
|
$RIFFwFormatTagLookup[0x0086] = 'DF GSM610';
|
||||||
|
$RIFFwFormatTagLookup[0x0088] = 'ISIAudio';
|
||||||
|
$RIFFwFormatTagLookup[0x0089] = 'Onlive';
|
||||||
|
$RIFFwFormatTagLookup[0x0091] = 'SBC24';
|
||||||
|
$RIFFwFormatTagLookup[0x0092] = 'Dolby AC3 SPDIF';
|
||||||
|
$RIFFwFormatTagLookup[0x0097] = 'ZyXEL ADPCM';
|
||||||
|
$RIFFwFormatTagLookup[0x0098] = 'Philips LPCBB';
|
||||||
|
$RIFFwFormatTagLookup[0x0099] = 'Packed';
|
||||||
|
$RIFFwFormatTagLookup[0x0100] = 'Rhetorex ADPCM';
|
||||||
|
$RIFFwFormatTagLookup[0x0101] = 'IBM mu-law';
|
||||||
|
$RIFFwFormatTagLookup[0x0102] = 'IBM A-law';
|
||||||
|
$RIFFwFormatTagLookup[0x0103] = 'IBM AVC Adaptive Differential Pulse Code Modulation (ADPCM)';
|
||||||
|
$RIFFwFormatTagLookup[0x0111] = 'Vivo G.723';
|
||||||
|
$RIFFwFormatTagLookup[0x0112] = 'Vivo Siren';
|
||||||
|
$RIFFwFormatTagLookup[0x0123] = 'Digital G.723';
|
||||||
|
$RIFFwFormatTagLookup[0x0140] = 'Windows Media Video V8';
|
||||||
|
$RIFFwFormatTagLookup[0x0161] = 'Windows Media Audio V7 / V8 / V9';
|
||||||
|
$RIFFwFormatTagLookup[0x0162] = 'Windows Media Audio Professional V9';
|
||||||
|
$RIFFwFormatTagLookup[0x0163] = 'Windows Media Audio Lossless V9';
|
||||||
|
$RIFFwFormatTagLookup[0x0200] = 'Creative Labs ADPCM';
|
||||||
|
$RIFFwFormatTagLookup[0x0202] = 'Creative Labs Fastspeech8';
|
||||||
|
$RIFFwFormatTagLookup[0x0203] = 'Creative Labs Fastspeech10';
|
||||||
|
$RIFFwFormatTagLookup[0x0220] = 'Quarterdeck';
|
||||||
|
$RIFFwFormatTagLookup[0x0300] = 'FM Towns Snd';
|
||||||
|
$RIFFwFormatTagLookup[0x0300] = 'Fujitsu FM Towns Snd';
|
||||||
|
$RIFFwFormatTagLookup[0x0400] = 'BTV Digital';
|
||||||
|
$RIFFwFormatTagLookup[0x0680] = 'VME VMPCM';
|
||||||
|
$RIFFwFormatTagLookup[0x1000] = 'Olivetti GSM';
|
||||||
|
$RIFFwFormatTagLookup[0x1001] = 'Olivetti ADPCM';
|
||||||
|
$RIFFwFormatTagLookup[0x1002] = 'Olivetti CELP';
|
||||||
|
$RIFFwFormatTagLookup[0x1003] = 'Olivetti SBC';
|
||||||
|
$RIFFwFormatTagLookup[0x1004] = 'Olivetti OPR';
|
||||||
|
$RIFFwFormatTagLookup[0x1100] = 'Lernout & Hauspie LH Codec';
|
||||||
|
$RIFFwFormatTagLookup[0x1400] = 'Norris';
|
||||||
|
$RIFFwFormatTagLookup[0x1401] = 'AT&T ISIAudio';
|
||||||
|
$RIFFwFormatTagLookup[0x1500] = 'Soundspace Music Compression';
|
||||||
|
$RIFFwFormatTagLookup[0x2000] = 'AC3';
|
||||||
|
$RIFFwFormatTagLookup[0x7A21] = 'GSM-AMR (CBR, no SID)';
|
||||||
|
$RIFFwFormatTagLookup[0x7A22] = 'GSM-AMR (VBR, including SID)';
|
||||||
|
$RIFFwFormatTagLookup[0xFFFF] = 'development';
|
||||||
|
}
|
||||||
|
|
||||||
|
return (isset($RIFFwFormatTagLookup[$wFormatTag]) ? $RIFFwFormatTagLookup[$wFormatTag] : 'unknown: 0x'.dechex($wFormatTag));
|
||||||
|
}
|
||||||
|
|
||||||
|
function RIFFfourccLookup($fourcc) {
|
||||||
|
static $RIFFfourccLookup = array();
|
||||||
|
if (empty($RIFFfourccLookup)) {
|
||||||
|
$RIFFfourccLookup['3IV1'] = '3ivx v1';
|
||||||
|
$RIFFfourccLookup['3IV2'] = '3ivx v2';
|
||||||
|
$RIFFfourccLookup['AASC'] = 'Autodesk Animator';
|
||||||
|
$RIFFfourccLookup['ABYR'] = 'Kensington ?ABYR?';
|
||||||
|
$RIFFfourccLookup['AEMI'] = 'Array VideoONE MPEG1-I Capture';
|
||||||
|
$RIFFfourccLookup['AFLC'] = 'Autodesk Animator FLC';
|
||||||
|
$RIFFfourccLookup['AFLI'] = 'Autodesk Animator FLI';
|
||||||
|
$RIFFfourccLookup['AMPG'] = 'Array VideoONE MPEG';
|
||||||
|
$RIFFfourccLookup['ANIM'] = 'Intel RDX (ANIM)';
|
||||||
|
$RIFFfourccLookup['AP41'] = 'AngelPotion Definitive';
|
||||||
|
$RIFFfourccLookup['ASV1'] = 'Asus Video v1';
|
||||||
|
$RIFFfourccLookup['ASV2'] = 'Asus Video v2';
|
||||||
|
$RIFFfourccLookup['ASVX'] = 'Asus Video 2.0 (audio)';
|
||||||
|
$RIFFfourccLookup['AUR2'] = 'Aura 2 Codec - YUV 4:2:2';
|
||||||
|
$RIFFfourccLookup['AURA'] = 'Aura 1 Codec - YUV 4:1:1';
|
||||||
|
$RIFFfourccLookup['BINK'] = 'RAD Game Tools Bink Video';
|
||||||
|
$RIFFfourccLookup['BT20'] = 'Conexant Prosumer Video';
|
||||||
|
$RIFFfourccLookup['BTCV'] = 'Conexant Composite Video Codec';
|
||||||
|
$RIFFfourccLookup['BW10'] = 'Data Translation Broadway MPEG Capture';
|
||||||
|
$RIFFfourccLookup['CC12'] = 'Intel YUV12';
|
||||||
|
$RIFFfourccLookup['CDVC'] = 'Canopus DV';
|
||||||
|
$RIFFfourccLookup['CFCC'] = 'Digital Processing Systems DPS Perception';
|
||||||
|
$RIFFfourccLookup['CGDI'] = 'Microsoft Office 97 Camcorder Video';
|
||||||
|
$RIFFfourccLookup['CHAM'] = 'Winnov Caviara Champagne';
|
||||||
|
$RIFFfourccLookup['CJPG'] = 'Creative WebCam JPEG';
|
||||||
|
$RIFFfourccLookup['CLJR'] = 'Cirrus Logic YUV 4 pixels';
|
||||||
|
$RIFFfourccLookup['CMYK'] = 'Common Data Format in Printing';
|
||||||
|
$RIFFfourccLookup['CPLA'] = 'Weitek 4:2:0 YUV Planar';
|
||||||
|
$RIFFfourccLookup['CRAM'] = 'Microsoft Video 1 (CRAM)';
|
||||||
|
$RIFFfourccLookup['CVID'] = 'Radius Cinepak';
|
||||||
|
$RIFFfourccLookup['CWLT'] = '?CWLT?';
|
||||||
|
$RIFFfourccLookup['CWLT'] = 'Microsoft Color WLT DIB';
|
||||||
|
$RIFFfourccLookup['CYUV'] = 'Creative Labs YUV';
|
||||||
|
$RIFFfourccLookup['CYUY'] = 'ATI YUV';
|
||||||
|
$RIFFfourccLookup['D261'] = 'H.261';
|
||||||
|
$RIFFfourccLookup['D263'] = 'H.263';
|
||||||
|
$RIFFfourccLookup['DIV3'] = 'DivX v3 MPEG-4 Low-Motion';
|
||||||
|
$RIFFfourccLookup['DIV4'] = 'DivX v3 MPEG-4 Fast-Motion';
|
||||||
|
$RIFFfourccLookup['DIV5'] = '?DIV5?';
|
||||||
|
$RIFFfourccLookup['DIVX'] = 'DivX v4';
|
||||||
|
$RIFFfourccLookup['divx'] = 'DivX';
|
||||||
|
$RIFFfourccLookup['DMB1'] = 'Matrox Rainbow Runner hardware MJPEG';
|
||||||
|
$RIFFfourccLookup['DMB2'] = 'Paradigm MJPEG';
|
||||||
|
$RIFFfourccLookup['DSVD'] = '?DSVD?';
|
||||||
|
$RIFFfourccLookup['DUCK'] = 'Duck True Motion 1.0';
|
||||||
|
$RIFFfourccLookup['DVAN'] = '?DVAN?';
|
||||||
|
$RIFFfourccLookup['DVE2'] = 'InSoft DVE-2 Videoconferencing';
|
||||||
|
$RIFFfourccLookup['dvsd'] = 'DV';
|
||||||
|
$RIFFfourccLookup['DVSD'] = 'DV';
|
||||||
|
$RIFFfourccLookup['DVX1'] = 'DVX1000SP Video Decoder';
|
||||||
|
$RIFFfourccLookup['DVX2'] = 'DVX2000S Video Decoder';
|
||||||
|
$RIFFfourccLookup['DVX3'] = 'DVX3000S Video Decoder';
|
||||||
|
$RIFFfourccLookup['DX50'] = 'DivX v5';
|
||||||
|
$RIFFfourccLookup['DXT1'] = 'Microsoft DirectX Compressed Texture (DXT1)';
|
||||||
|
$RIFFfourccLookup['DXT2'] = 'Microsoft DirectX Compressed Texture (DXT2)';
|
||||||
|
$RIFFfourccLookup['DXT3'] = 'Microsoft DirectX Compressed Texture (DXT3)';
|
||||||
|
$RIFFfourccLookup['DXT4'] = 'Microsoft DirectX Compressed Texture (DXT4)';
|
||||||
|
$RIFFfourccLookup['DXT5'] = 'Microsoft DirectX Compressed Texture (DXT5)';
|
||||||
|
$RIFFfourccLookup['DXTC'] = 'Microsoft DirectX Compressed Texture (DXTC)';
|
||||||
|
$RIFFfourccLookup['EKQ0'] = 'Elsa ?EKQ0?';
|
||||||
|
$RIFFfourccLookup['ELK0'] = 'Elsa ?ELK0?';
|
||||||
|
$RIFFfourccLookup['ESCP'] = 'Eidos Escape';
|
||||||
|
$RIFFfourccLookup['ETV1'] = 'eTreppid Video ETV1';
|
||||||
|
$RIFFfourccLookup['ETV2'] = 'eTreppid Video ETV2';
|
||||||
|
$RIFFfourccLookup['ETVC'] = 'eTreppid Video ETVC';
|
||||||
|
$RIFFfourccLookup['FLJP'] = 'D-Vision Field Encoded Motion JPEG';
|
||||||
|
$RIFFfourccLookup['FRWA'] = 'SoftLab-Nsk Forward Motion JPEG w/ alpha channel';
|
||||||
|
$RIFFfourccLookup['FRWD'] = 'SoftLab-Nsk Forward Motion JPEG';
|
||||||
|
$RIFFfourccLookup['FVF1'] = 'Iterated Systems Fractal Video Frame';
|
||||||
|
$RIFFfourccLookup['GLZW'] = 'Motion LZW (gabest@freemail.hu)';
|
||||||
|
$RIFFfourccLookup['GPEG'] = 'Motion JPEG (gabest@freemail.hu)';
|
||||||
|
$RIFFfourccLookup['GWLT'] = 'Microsoft Greyscale WLT DIB';
|
||||||
|
$RIFFfourccLookup['H260'] = 'Intel ITU H.260 Videoconferencing';
|
||||||
|
$RIFFfourccLookup['H261'] = 'Intel ITU H.261 Videoconferencing';
|
||||||
|
$RIFFfourccLookup['H262'] = 'Intel ITU H.262 Videoconferencing';
|
||||||
|
$RIFFfourccLookup['H263'] = 'Intel ITU H.263 Videoconferencing';
|
||||||
|
$RIFFfourccLookup['H264'] = 'Intel ITU H.264 Videoconferencing';
|
||||||
|
$RIFFfourccLookup['H265'] = 'Intel ITU H.265 Videoconferencing';
|
||||||
|
$RIFFfourccLookup['H266'] = 'Intel ITU H.266 Videoconferencing';
|
||||||
|
$RIFFfourccLookup['H267'] = 'Intel ITU H.267 Videoconferencing';
|
||||||
|
$RIFFfourccLookup['H268'] = 'Intel ITU H.268 Videoconferencing';
|
||||||
|
$RIFFfourccLookup['H269'] = 'Intel ITU H.269 Videoconferencing';
|
||||||
|
$RIFFfourccLookup['HFYU'] = 'Huffman Lossless Codec';
|
||||||
|
$RIFFfourccLookup['HMCR'] = 'Rendition Motion Compensation Format (HMCR)';
|
||||||
|
$RIFFfourccLookup['HMRR'] = 'Rendition Motion Compensation Format (HMRR)';
|
||||||
|
$RIFFfourccLookup['i263'] = 'Intel ITU H.263 Videoconferencing (i263)';
|
||||||
|
$RIFFfourccLookup['I420'] = 'Intel Indeo 4';
|
||||||
|
$RIFFfourccLookup['IAN '] = 'Intel RDX';
|
||||||
|
$RIFFfourccLookup['ICLB'] = 'InSoft CellB Videoconferencing';
|
||||||
|
$RIFFfourccLookup['IGOR'] = 'Power DVD';
|
||||||
|
$RIFFfourccLookup['IJPG'] = 'Intergraph JPEG';
|
||||||
|
$RIFFfourccLookup['ILVC'] = 'Intel Layered Video';
|
||||||
|
$RIFFfourccLookup['ILVR'] = 'ITU-T H.263+';
|
||||||
|
$RIFFfourccLookup['IPDV'] = 'I-O Data Device Giga AVI DV Codec';
|
||||||
|
$RIFFfourccLookup['IR21'] = 'Intel Indeo 2.1';
|
||||||
|
$RIFFfourccLookup['IRAW'] = 'Intel YUV Uncompressed';
|
||||||
|
$RIFFfourccLookup['IV30'] = 'Ligos Indeo 3.0';
|
||||||
|
$RIFFfourccLookup['IV31'] = 'Ligos Indeo 3.1';
|
||||||
|
$RIFFfourccLookup['IV32'] = 'Ligos Indeo 3.2';
|
||||||
|
$RIFFfourccLookup['IV33'] = 'Ligos Indeo 3.3';
|
||||||
|
$RIFFfourccLookup['IV34'] = 'Ligos Indeo 3.4';
|
||||||
|
$RIFFfourccLookup['IV35'] = 'Ligos Indeo 3.5';
|
||||||
|
$RIFFfourccLookup['IV36'] = 'Ligos Indeo 3.6';
|
||||||
|
$RIFFfourccLookup['IV37'] = 'Ligos Indeo 3.7';
|
||||||
|
$RIFFfourccLookup['IV38'] = 'Ligos Indeo 3.8';
|
||||||
|
$RIFFfourccLookup['IV39'] = 'Ligos Indeo 3.9';
|
||||||
|
$RIFFfourccLookup['IV40'] = 'Ligos Indeo Interactive 4.0';
|
||||||
|
$RIFFfourccLookup['IV41'] = 'Ligos Indeo Interactive 4.1';
|
||||||
|
$RIFFfourccLookup['IV42'] = 'Ligos Indeo Interactive 4.2';
|
||||||
|
$RIFFfourccLookup['IV43'] = 'Ligos Indeo Interactive 4.3';
|
||||||
|
$RIFFfourccLookup['IV44'] = 'Ligos Indeo Interactive 4.4';
|
||||||
|
$RIFFfourccLookup['IV45'] = 'Ligos Indeo Interactive 4.5';
|
||||||
|
$RIFFfourccLookup['IV46'] = 'Ligos Indeo Interactive 4.6';
|
||||||
|
$RIFFfourccLookup['IV47'] = 'Ligos Indeo Interactive 4.7';
|
||||||
|
$RIFFfourccLookup['IV48'] = 'Ligos Indeo Interactive 4.8';
|
||||||
|
$RIFFfourccLookup['IV49'] = 'Ligos Indeo Interactive 4.9';
|
||||||
|
$RIFFfourccLookup['IV50'] = 'Ligos Indeo Interactive 5.0';
|
||||||
|
$RIFFfourccLookup['JBYR'] = 'Kensington ?JBYR?';
|
||||||
|
$RIFFfourccLookup['JPEG'] = 'Still Image JPEG DIB';
|
||||||
|
$RIFFfourccLookup['JPGL'] = 'Webcam JPEG Light?';
|
||||||
|
$RIFFfourccLookup['KMVC'] = 'Karl Morton\'s Video Codec';
|
||||||
|
$RIFFfourccLookup['LEAD'] = 'LEAD Video Codec';
|
||||||
|
$RIFFfourccLookup['Ljpg'] = 'LEAD MJPEG Codec';
|
||||||
|
$RIFFfourccLookup['M261'] = 'Microsoft H.261';
|
||||||
|
$RIFFfourccLookup['M263'] = 'Microsoft H.263';
|
||||||
|
$RIFFfourccLookup['M4S2'] = 'Microsoft MPEG-4 (M4S2)';
|
||||||
|
$RIFFfourccLookup['m4s2'] = 'Microsoft MPEG-4 (m4s2)';
|
||||||
|
$RIFFfourccLookup['MC12'] = 'ATI Motion Compensation Format (MC12)';
|
||||||
|
$RIFFfourccLookup['MCAM'] = 'ATI Motion Compensation Format (MCAM)';
|
||||||
|
$RIFFfourccLookup['MJ2C'] = 'Morgan Multimedia Motion JPEG2000';
|
||||||
|
$RIFFfourccLookup['mJPG'] = 'IBM Motion JPEG w/ Huffman Tables';
|
||||||
|
$RIFFfourccLookup['MJPG'] = 'Motion JPEG DIB';
|
||||||
|
$RIFFfourccLookup['MP42'] = 'Microsoft MPEG-4 (low-motion)';
|
||||||
|
$RIFFfourccLookup['MP43'] = 'Microsoft MPEG-4 (fast-motion)';
|
||||||
|
$RIFFfourccLookup['MP4S'] = 'Microsoft MPEG-4 (MP4S)';
|
||||||
|
$RIFFfourccLookup['mp4s'] = 'Microsoft MPEG-4 (mp4s)';
|
||||||
|
$RIFFfourccLookup['MPEG'] = 'MPEG 1 Video I-Frame';
|
||||||
|
$RIFFfourccLookup['MPG4'] = 'Microsoft MPEG-4 Video High Speed Compressor';
|
||||||
|
$RIFFfourccLookup['MPGI'] = 'Sigma Designs MPEG';
|
||||||
|
$RIFFfourccLookup['MRCA'] = 'FAST Multimedia Mrcodec';
|
||||||
|
$RIFFfourccLookup['MRCA'] = 'Martin Regen Codec';
|
||||||
|
$RIFFfourccLookup['MRLE'] = 'Microsoft RLE';
|
||||||
|
$RIFFfourccLookup['MRLE'] = 'Run Length Encoding';
|
||||||
|
$RIFFfourccLookup['MSVC'] = 'Microsoft Video 1';
|
||||||
|
$RIFFfourccLookup['MTX1'] = 'Matrox ?MTX1?';
|
||||||
|
$RIFFfourccLookup['MTX2'] = 'Matrox ?MTX2?';
|
||||||
|
$RIFFfourccLookup['MTX3'] = 'Matrox ?MTX3?';
|
||||||
|
$RIFFfourccLookup['MTX4'] = 'Matrox ?MTX4?';
|
||||||
|
$RIFFfourccLookup['MTX5'] = 'Matrox ?MTX5?';
|
||||||
|
$RIFFfourccLookup['MTX6'] = 'Matrox ?MTX6?';
|
||||||
|
$RIFFfourccLookup['MTX7'] = 'Matrox ?MTX7?';
|
||||||
|
$RIFFfourccLookup['MTX8'] = 'Matrox ?MTX8?';
|
||||||
|
$RIFFfourccLookup['MTX9'] = 'Matrox ?MTX9?';
|
||||||
|
$RIFFfourccLookup['MV12'] = '?MV12?';
|
||||||
|
$RIFFfourccLookup['MWV1'] = 'Aware Motion Wavelets';
|
||||||
|
$RIFFfourccLookup['nAVI'] = '?nAVI?';
|
||||||
|
$RIFFfourccLookup['NTN1'] = 'Nogatech Video Compression 1';
|
||||||
|
$RIFFfourccLookup['NVS0'] = 'nVidia GeForce Texture (NVS0)';
|
||||||
|
$RIFFfourccLookup['NVS1'] = 'nVidia GeForce Texture (NVS1)';
|
||||||
|
$RIFFfourccLookup['NVS2'] = 'nVidia GeForce Texture (NVS2)';
|
||||||
|
$RIFFfourccLookup['NVS3'] = 'nVidia GeForce Texture (NVS3)';
|
||||||
|
$RIFFfourccLookup['NVS4'] = 'nVidia GeForce Texture (NVS4)';
|
||||||
|
$RIFFfourccLookup['NVS5'] = 'nVidia GeForce Texture (NVS5)';
|
||||||
|
$RIFFfourccLookup['NVT0'] = 'nVidia GeForce Texture (NVT0)';
|
||||||
|
$RIFFfourccLookup['NVT1'] = 'nVidia GeForce Texture (NVT1)';
|
||||||
|
$RIFFfourccLookup['NVT2'] = 'nVidia GeForce Texture (NVT2)';
|
||||||
|
$RIFFfourccLookup['NVT3'] = 'nVidia GeForce Texture (NVT3)';
|
||||||
|
$RIFFfourccLookup['NVT4'] = 'nVidia GeForce Texture (NVT4)';
|
||||||
|
$RIFFfourccLookup['NVT5'] = 'nVidia GeForce Texture (NVT5)';
|
||||||
|
$RIFFfourccLookup['PDVC'] = 'I-O Data Device Digital Video Capture DV codec';
|
||||||
|
$RIFFfourccLookup['PGVV'] = 'Radius Video Vision';
|
||||||
|
$RIFFfourccLookup['PHMO'] = 'IBM Photomotion';
|
||||||
|
$RIFFfourccLookup['PIM1'] = 'Pegasus Imaging ?PIM1?';
|
||||||
|
$RIFFfourccLookup['PIM2'] = 'Pegasus Imaging ?PIM2?';
|
||||||
|
$RIFFfourccLookup['PIMJ'] = 'Pegasus Imaging Lossless JPEG';
|
||||||
|
$RIFFfourccLookup['PVEZ'] = 'Horizons Technology PowerEZ';
|
||||||
|
$RIFFfourccLookup['PVMM'] = 'PacketVideo Corporation MPEG-4';
|
||||||
|
$RIFFfourccLookup['PVW2'] = 'Pegasus Imaging Wavelet Compression';
|
||||||
|
$RIFFfourccLookup['QPEG'] = 'Q-Team QPEG 1.0';
|
||||||
|
$RIFFfourccLookup['qpeq'] = 'Q-Team QPEG 1.1';
|
||||||
|
$RIFFfourccLookup['RGBT'] = 'Computer Concepts 32-bit support';
|
||||||
|
$RIFFfourccLookup['RLE '] = 'Microsoft Run Length Encoder';
|
||||||
|
$RIFFfourccLookup['RLE4'] = 'Run Length Encoded 4';
|
||||||
|
$RIFFfourccLookup['RLE8'] = 'Run Length Encoded 8';
|
||||||
|
$RIFFfourccLookup['RT21'] = 'Intel Indeo 2.1';
|
||||||
|
$RIFFfourccLookup['RT21'] = 'Intel Real Time Video 2.1';
|
||||||
|
$RIFFfourccLookup['rv20'] = 'RealVideo G2';
|
||||||
|
$RIFFfourccLookup['rv30'] = 'RealVideo 8';
|
||||||
|
$RIFFfourccLookup['RVX '] = 'Intel RDX (RVX )';
|
||||||
|
$RIFFfourccLookup['s422'] = 'Tekram VideoCap C210 YUV 4:2:2';
|
||||||
|
$RIFFfourccLookup['SDCC'] = 'Sun Communication Digital Camera Codec';
|
||||||
|
$RIFFfourccLookup['SFMC'] = 'CrystalNet Surface Fitting Method';
|
||||||
|
$RIFFfourccLookup['SMSC'] = 'Radius SMSC';
|
||||||
|
$RIFFfourccLookup['SMSD'] = 'Radius SMSD';
|
||||||
|
$RIFFfourccLookup['smsv'] = 'WorldConnect Wavelet Video';
|
||||||
|
$RIFFfourccLookup['SPIG'] = 'Radius Spigot';
|
||||||
|
$RIFFfourccLookup['SPLC'] = 'Splash Studios ACM Audio Codec';
|
||||||
|
$RIFFfourccLookup['SQZ2'] = 'Microsoft VXTreme Video Codec V2';
|
||||||
|
$RIFFfourccLookup['STVA'] = 'ST CMOS Imager Data (Bayer)';
|
||||||
|
$RIFFfourccLookup['STVB'] = 'ST CMOS Imager Data (Nudged Bayer)';
|
||||||
|
$RIFFfourccLookup['STVC'] = 'ST CMOS Imager Data (Bunched)';
|
||||||
|
$RIFFfourccLookup['STVX'] = 'ST CMOS Imager Data (Extended CODEC Data Format)';
|
||||||
|
$RIFFfourccLookup['STVY'] = 'ST CMOS Imager Data (Extended CODEC Data Format with Correction Data)';
|
||||||
|
$RIFFfourccLookup['SV10'] = 'Sorenson Video R1';
|
||||||
|
$RIFFfourccLookup['SVQ1'] = 'Sorenson Video';
|
||||||
|
$RIFFfourccLookup['TLMS'] = 'TeraLogic Motion Intraframe Codec (TLMS)';
|
||||||
|
$RIFFfourccLookup['TLST'] = 'TeraLogic Motion Intraframe Codec (TLST)';
|
||||||
|
$RIFFfourccLookup['TM20'] = 'Duck TrueMotion 2.0';
|
||||||
|
$RIFFfourccLookup['TM2X'] = 'Duck TrueMotion 2X';
|
||||||
|
$RIFFfourccLookup['TMIC'] = 'TeraLogic Motion Intraframe Codec (TMIC)';
|
||||||
|
$RIFFfourccLookup['TMOT'] = 'Horizons Technology TrueMotion S';
|
||||||
|
$RIFFfourccLookup['tmot'] = 'Horizons TrueMotion Video Compression';
|
||||||
|
$RIFFfourccLookup['TR20'] = 'Duck TrueMotion RealTime 2.0';
|
||||||
|
$RIFFfourccLookup['TSCC'] = 'TechSmith Screen Capture Codec';
|
||||||
|
$RIFFfourccLookup['TV10'] = 'Tecomac Low-Bit Rate Codec';
|
||||||
|
$RIFFfourccLookup['TY0N'] = 'Trident ?TY0N?';
|
||||||
|
$RIFFfourccLookup['TY2C'] = 'Trident ?TY2C?';
|
||||||
|
$RIFFfourccLookup['TY2N'] = 'Trident ?TY2N?';
|
||||||
|
$RIFFfourccLookup['UCOD'] = 'eMajix.com ClearVideo';
|
||||||
|
$RIFFfourccLookup['ULTI'] = 'IBM Ultimotion';
|
||||||
|
$RIFFfourccLookup['UYVY'] = 'UYVY 4:2:2 byte ordering';
|
||||||
|
$RIFFfourccLookup['V261'] = 'Lucent VX2000S';
|
||||||
|
$RIFFfourccLookup['V422'] = '24 bit YUV 4:2:2 Format';
|
||||||
|
$RIFFfourccLookup['V655'] = '16 bit YUV 4:2:2 Format';
|
||||||
|
$RIFFfourccLookup['VCR1'] = 'ATI VCR 1.0';
|
||||||
|
$RIFFfourccLookup['VCR2'] = 'ATI VCR 2.0';
|
||||||
|
$RIFFfourccLookup['VCR3'] = 'ATI VCR 3.0';
|
||||||
|
$RIFFfourccLookup['VCR4'] = 'ATI VCR 4.0';
|
||||||
|
$RIFFfourccLookup['VCR5'] = 'ATI VCR 5.0';
|
||||||
|
$RIFFfourccLookup['VCR6'] = 'ATI VCR 6.0';
|
||||||
|
$RIFFfourccLookup['VCR7'] = 'ATI VCR 7.0';
|
||||||
|
$RIFFfourccLookup['VCR8'] = 'ATI VCR 8.0';
|
||||||
|
$RIFFfourccLookup['VCR9'] = 'ATI VCR 9.0';
|
||||||
|
$RIFFfourccLookup['VDCT'] = 'Video Maker Pro DIB';
|
||||||
|
$RIFFfourccLookup['VDOM'] = 'VDOnet VDOWave';
|
||||||
|
$RIFFfourccLookup['VDOW'] = 'VDOnet VDOLive (H.263)';
|
||||||
|
$RIFFfourccLookup['VDTZ'] = 'Darim Vison VideoTizer YUV';
|
||||||
|
$RIFFfourccLookup['VGPX'] = 'VGPixel Codec';
|
||||||
|
$RIFFfourccLookup['VIDS'] = 'Vitec Multimedia YUV 4:2:2 CCIR 601 for V422';
|
||||||
|
$RIFFfourccLookup['VIDS'] = 'YUV 4:2:2 CCIR 601 for V422';
|
||||||
|
$RIFFfourccLookup['VIFP'] = '?VIFP?';
|
||||||
|
$RIFFfourccLookup['VIVO'] = 'Vivo H.263 v2.00';
|
||||||
|
$RIFFfourccLookup['vivo'] = 'Vivo H.263';
|
||||||
|
$RIFFfourccLookup['VIXL'] = 'Miro Video XL';
|
||||||
|
$RIFFfourccLookup['VLV1'] = 'Videologic VLCAP.DRV';
|
||||||
|
$RIFFfourccLookup['VP30'] = 'On2 VP3.0';
|
||||||
|
$RIFFfourccLookup['VP31'] = 'On2 VP3.1';
|
||||||
|
$RIFFfourccLookup['VX1K'] = 'VX1000S Video Codec';
|
||||||
|
$RIFFfourccLookup['VX2K'] = 'VX2000S Video Codec';
|
||||||
|
$RIFFfourccLookup['VXSP'] = 'VX1000SP Video Codec';
|
||||||
|
$RIFFfourccLookup['WBVC'] = 'Winbond W9960';
|
||||||
|
$RIFFfourccLookup['WHAM'] = 'Microsoft Video 1 (WHAM)';
|
||||||
|
$RIFFfourccLookup['WINX'] = 'Winnov Software Compression';
|
||||||
|
$RIFFfourccLookup['WJPG'] = 'AverMedia Winbond JPEG';
|
||||||
|
$RIFFfourccLookup['WMV1'] = 'Windows Media Video V7';
|
||||||
|
$RIFFfourccLookup['WMV2'] = 'Windows Media Video V8';
|
||||||
|
$RIFFfourccLookup['WMV3'] = 'Windows Media Video V9';
|
||||||
|
$RIFFfourccLookup['WNV1'] = 'Winnov Hardware Compression';
|
||||||
|
$RIFFfourccLookup['x263'] = 'Xirlink H.263';
|
||||||
|
$RIFFfourccLookup['XLV0'] = 'NetXL Video Decoder';
|
||||||
|
$RIFFfourccLookup['XMPG'] = 'Xing MPEG (I-Frame only)';
|
||||||
|
$RIFFfourccLookup['XVID'] = 'XviD MPEG-4';
|
||||||
|
$RIFFfourccLookup['XXAN'] = '?XXAN?';
|
||||||
|
$RIFFfourccLookup['Y211'] = 'YUV 2:1:1 Packed';
|
||||||
|
$RIFFfourccLookup['Y411'] = 'YUV 4:1:1 Packed';
|
||||||
|
$RIFFfourccLookup['Y41B'] = 'YUV 4:1:1 Planar';
|
||||||
|
$RIFFfourccLookup['Y41P'] = 'PC1 4:1:1';
|
||||||
|
$RIFFfourccLookup['Y41T'] = 'PC1 4:1:1 with transparency';
|
||||||
|
$RIFFfourccLookup['Y42B'] = 'YUV 4:2:2 Planar';
|
||||||
|
$RIFFfourccLookup['Y42T'] = 'PCI 4:2:2 with transparency';
|
||||||
|
$RIFFfourccLookup['Y8 '] = 'Grayscale video';
|
||||||
|
$RIFFfourccLookup['YC12'] = 'Intel YUV 12 codec';
|
||||||
|
$RIFFfourccLookup['YC12'] = 'Intel YUV12 Codec';
|
||||||
|
$RIFFfourccLookup['YUV8'] = 'Winnov Caviar YUV8';
|
||||||
|
$RIFFfourccLookup['YUV9'] = 'Intel YUV9';
|
||||||
|
$RIFFfourccLookup['YUY2'] = 'Uncompressed YUV 4:2:2';
|
||||||
|
$RIFFfourccLookup['YUYV'] = 'Canopus YUV';
|
||||||
|
$RIFFfourccLookup['YV12'] = 'YVU12 Planar';
|
||||||
|
$RIFFfourccLookup['YVU9'] = 'Intel YVU9 Planar';
|
||||||
|
$RIFFfourccLookup['YVYU'] = 'YVYU 4:2:2 byte ordering';
|
||||||
|
$RIFFfourccLookup['ZLIB'] = '?ZLIB?';
|
||||||
|
$RIFFfourccLookup['ZPEG'] = 'Metheus Video Zipper';
|
||||||
|
}
|
||||||
|
|
||||||
|
return (isset($RIFFfourccLookup["$fourcc"]) ? $RIFFfourccLookup["$fourcc"] : '');
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
168
livesupport/modules/getid3/var/getid3.write.php
Normal file
168
livesupport/modules/getid3/var/getid3.write.php
Normal file
|
@ -0,0 +1,168 @@
|
||||||
|
<?php
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
/// getID3() by James Heinrich <getid3@users.sourceforge.net> //
|
||||||
|
// available at http://getid3.sourceforge.net ///
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
// //
|
||||||
|
// getid3.write.php - part of getID3() //
|
||||||
|
// sample script for demonstrating writing ID3v1 and ID3v2 //
|
||||||
|
// tags for MP3, or Ogg comment tags for Ogg Vorbis //
|
||||||
|
// See getid3.readme.txt for more details //
|
||||||
|
// //
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
require_once('getid3.php');
|
||||||
|
require_once(GETID3_INCLUDEPATH.'getid3.putid3.php');
|
||||||
|
require_once(GETID3_INCLUDEPATH.'getid3.ogginfo.php');
|
||||||
|
require_once(GETID3_INCLUDEPATH.'getid3.functions.php');
|
||||||
|
require_once(GETID3_INCLUDEPATH.'getid3.id3.php');
|
||||||
|
|
||||||
|
$EditorFilename = (isset($_REQUEST['EditorFilename']) ? SafeStripSlashes($_REQUEST['EditorFilename']) : '');
|
||||||
|
|
||||||
|
if (isset($_POST['WriteOggCommentTagNow'])) {
|
||||||
|
|
||||||
|
$data['title'] = $_POST['EditorTitle'];
|
||||||
|
$data['artist'] = $_POST['EditorArtist'];
|
||||||
|
$data['album'] = $_POST['EditorAlbum'];
|
||||||
|
$data['genre'] = LookupGenre($_POST['EditorGenre']);
|
||||||
|
$data['tracknumber'] = $_POST['EditorTrack'];
|
||||||
|
$data['comment'] = $_POST['EditorComment'];
|
||||||
|
echo 'Ogg tag'.(OggWrite($EditorFilename, $data) ? '' : ' NOT').' written successfully<HR>';
|
||||||
|
|
||||||
|
} elseif (isset($_POST['WriteID3v2TagNow'])) {
|
||||||
|
echo 'starting to write tag<BR>';
|
||||||
|
|
||||||
|
if ($_POST['EditorTitle']) {
|
||||||
|
$data['id3v2']['TIT2']['encodingid'] = 0;
|
||||||
|
$data['id3v2']['TIT2']['data'] = SafeStripSlashes($_POST['EditorTitle']);
|
||||||
|
}
|
||||||
|
if ($_POST['EditorArtist']) {
|
||||||
|
$data['id3v2']['TPE1']['encodingid'] = 0;
|
||||||
|
$data['id3v2']['TPE1']['data'] = SafeStripSlashes($_POST['EditorArtist']);
|
||||||
|
}
|
||||||
|
if ($_POST['EditorAlbum']) {
|
||||||
|
$data['id3v2']['TALB']['encodingid'] = 0;
|
||||||
|
$data['id3v2']['TALB']['data'] = SafeStripSlashes($_POST['EditorAlbum']);
|
||||||
|
}
|
||||||
|
if ($_POST['EditorYear']) {
|
||||||
|
$data['id3v2']['TYER']['encodingid'] = 0;
|
||||||
|
$data['id3v2']['TYER']['data'] = (int) SafeStripSlashes($_POST['EditorYear']);
|
||||||
|
}
|
||||||
|
if ($_POST['EditorTrack']) {
|
||||||
|
$data['id3v2']['TRCK']['encodingid'] = 0;
|
||||||
|
$data['id3v2']['TRCK']['data'] = (int) SafeStripSlashes($_POST['EditorTrack']);
|
||||||
|
}
|
||||||
|
if ($_POST['EditorGenre']) {
|
||||||
|
$data['id3v2']['TCON']['encodingid'] = 0;
|
||||||
|
$data['id3v2']['TCON']['data'] = '('.$_POST['EditorGenre'].')';
|
||||||
|
}
|
||||||
|
if ($_POST['EditorComment']) {
|
||||||
|
$data['id3v2']['COMM'][0]['encodingid'] = 0;
|
||||||
|
$data['id3v2']['COMM'][0]['language'] = 'eng';
|
||||||
|
$data['id3v2']['COMM'][0]['description'] = '';
|
||||||
|
$data['id3v2']['COMM'][0]['data'] = SafeStripSlashes($_POST['EditorComment']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($_FILES['userfile']['tmp_name']) && $_FILES['userfile']['tmp_name']) {
|
||||||
|
if (is_uploaded_file($_FILES['userfile']['tmp_name'])) {
|
||||||
|
if ($fd = @fopen($_FILES['userfile']['tmp_name'], 'rb')) {
|
||||||
|
$data['id3v2']['APIC'][0]['data'] = fread($fd, filesize($_FILES['userfile']['tmp_name']));
|
||||||
|
fclose ($fd);
|
||||||
|
|
||||||
|
$data['id3v2']['APIC'][0]['encodingid'] = (isset($EditorAPICencodingID) ? $EditorAPICencodingID : 0);
|
||||||
|
$data['id3v2']['APIC'][0]['picturetypeid'] = (isset($EditorAPICpictypeID) ? $EditorAPICpictypeID : 0);
|
||||||
|
$data['id3v2']['APIC'][0]['description'] = (isset($EditorAPICdescription) ? $EditorAPICdescription : '');
|
||||||
|
|
||||||
|
require_once(GETID3_INCLUDEPATH.'getid3.getimagesize.php');
|
||||||
|
$imageinfo = GetDataImageSize($data['id3v2']['APIC'][0]['data']);
|
||||||
|
$imagetypes = array(1=>'gif', 2=>'jpeg', 3=>'png');
|
||||||
|
if (isset($imageinfo[2]) && ($imageinfo[2] >= 1) && ($imageinfo[2] <= 3)) {
|
||||||
|
$data['id3v2']['APIC'][0]['mime'] = 'image/'.$imagetypes[$imageinfo[2]];
|
||||||
|
} else {
|
||||||
|
echo '<B>invalid image format</B><BR>';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
echo '<B>cannot open '.$_FILES['userfile']['tmp_name'].'</B><BR>';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
echo '<B>!is_uploaded_file('.$_FILES['userfile']['tmp_name'].')</B><BR>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$data['id3v2']['TXXX'][0]['encodingid'] = 0;
|
||||||
|
$data['id3v2']['TXXX'][0]['description'] = 'ID3v2-tagged by';
|
||||||
|
$data['id3v2']['TXXX'][0]['data'] = 'getID3() v'.GETID3VERSION.' (www.silisoftware.com)';
|
||||||
|
|
||||||
|
|
||||||
|
if ($_POST['WriteOrDelete'] == 'W') { // write tags
|
||||||
|
if (isset($_POST['VersionToEdit1']) && ($_POST['VersionToEdit1'] == '1')) {
|
||||||
|
if (!is_numeric($_POST['EditorGenre'])) {
|
||||||
|
$EditorGenre = 255; // ID3v1 only supports predefined numeric genres (255 = unknown)
|
||||||
|
}
|
||||||
|
echo 'ID3v1 changes'.(WriteID3v1($EditorFilename, $_POST['EditorTitle'], $_POST['EditorArtist'], $_POST['EditorAlbum'], $_POST['EditorYear'], $_POST['EditorComment'], $_POST['EditorGenre'], $_POST['EditorTrack'], true) ? '' : ' NOT').' written successfully<HR>';
|
||||||
|
}
|
||||||
|
if (isset($_POST['VersionToEdit2']) && ($_POST['VersionToEdit2'] == '2')) {
|
||||||
|
echo 'ID3v2 changes'.(WriteID3v2($EditorFilename, $data, 3, 0, true, 0, true) ? '' : ' NOT').' written successfully<HR>';
|
||||||
|
}
|
||||||
|
} else { // delete tags
|
||||||
|
if (isset($_POST['VersionToEdit1']) && ($_POST['VersionToEdit1'] == '1')) {
|
||||||
|
echo 'ID3v1 tag'.(RemoveID3v1($EditorFilename, true) ? '' : ' NOT').' successfully deleted<HR>';
|
||||||
|
}
|
||||||
|
if (isset($_POST['VersionToEdit2']) && ($_POST['VersionToEdit2'] == '2')) {
|
||||||
|
echo 'ID3v2 tag'.(RemoveID3v2($EditorFilename, true) ? '' : ' NOT').' successfully deleted<HR>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
echo '<A HREF="'.$_SERVER['PHP_SELF'].'">Start Over</A><BR>';
|
||||||
|
echo '<TABLE BORDER="0"><FORM ACTION="'.$_SERVER['PHP_SELF'].'" METHOD="POST" ENCTYPE="multipart/form-data">';
|
||||||
|
echo '<TR><TD ALIGN="CENTER" COLSPAN="2"><B>Sample ID3v1/ID3v2/OggComment editor</B></TD></TR>';
|
||||||
|
if ($EditorFilename) {
|
||||||
|
echo '<TR><TD ALIGN="RIGHT"><B>Filename: </B></TD><TD><INPUT TYPE="HIDDEN" NAME="EditorFilename" VALUE="'.FixTextFields($EditorFilename).'"><I>'.$EditorFilename.'</I></TD></TR>';
|
||||||
|
if (file_exists($EditorFilename)) {
|
||||||
|
$OldThisfileInfo = GetAllFileInfo($EditorFilename);
|
||||||
|
echo '<TR><TD ALIGN="RIGHT"><B>Title</B></TD><TD><INPUT TYPE="TEXT" SIZE="40" NAME="EditorTitle" VALUE="'.FixTextFields(isset($OldThisfileInfo['comments']['title'][0]) ? $OldThisfileInfo['comments']['title'][0] : '').'"></TD></TR>';
|
||||||
|
echo '<TR><TD ALIGN="RIGHT"><B>Artist</B></TD><TD><INPUT TYPE="TEXT" SIZE="40" NAME="EditorArtist" VALUE="'.FixTextFields(isset($OldThisfileInfo['comments']['artist'][0]) ? $OldThisfileInfo['comments']['artist'][0] : '').'"></TD></TR>';
|
||||||
|
echo '<TR><TD ALIGN="RIGHT"><B>Album</B></TD><TD><INPUT TYPE="TEXT" SIZE="40" NAME="EditorAlbum" VALUE="'.FixTextFields(isset($OldThisfileInfo['comments']['album'][0]) ? $OldThisfileInfo['comments']['album'][0] : '').'"></TD></TR>';
|
||||||
|
if ($OldThisfileInfo['fileformat'] == 'mp3') {
|
||||||
|
echo '<TR><TD ALIGN="RIGHT"><B>Year</B></TD><TD><INPUT TYPE="TEXT" SIZE="4" NAME="EditorYear" VALUE="'.FixTextFields(isset($OldThisfileInfo['comments']['year'][0]) ? $OldThisfileInfo['comments']['year'][0] : '').'"></TD></TR>';
|
||||||
|
}
|
||||||
|
echo '<TR><TD ALIGN="RIGHT"><B>Track</B></TD><TD><INPUT TYPE="TEXT" SIZE="2" NAME="EditorTrack" VALUE="'.FixTextFields(isset($OldThisfileInfo['comments']['track'][0]) ? $OldThisfileInfo['comments']['track'][0] : '').'"></TD></TR>';
|
||||||
|
echo '<TR><TD ALIGN="RIGHT"><B>Genre</B></TD><TD><SELECT NAME="EditorGenre">';
|
||||||
|
|
||||||
|
require_once(GETID3_INCLUDEPATH.'getid3.id3.php');
|
||||||
|
$ArrayOfGenres = ArrayOfGenres(); // get the array of genres
|
||||||
|
unset($ArrayOfGenres['CR']); // take off these special cases
|
||||||
|
unset($ArrayOfGenres['RX']);
|
||||||
|
unset($ArrayOfGenres[255]);
|
||||||
|
asort($ArrayOfGenres); // sort into alphabetical order
|
||||||
|
$ArrayOfGenres[255] = '-Unknown-'; // and put the special cases back on the end
|
||||||
|
$ArrayOfGenres['CR'] = '-Cover-';
|
||||||
|
$ArrayOfGenres['RX'] = '-Remix-';
|
||||||
|
$EditorGenre = (isset($OldThisfileInfo['comments']['genre'][0]) ? LookupGenre($OldThisfileInfo['comments']['genre'][0], true) : 255);
|
||||||
|
foreach ($ArrayOfGenres as $key => $value) {
|
||||||
|
echo '<OPTION VALUE="'.$key.'"'.(($EditorGenre == $key) ? ' SELECTED' : '').'>'.$value.'</OPTION>';
|
||||||
|
}
|
||||||
|
echo '</SELECT></TD></TR>';
|
||||||
|
|
||||||
|
echo '<TR><TD ALIGN="RIGHT"><B>Comment</B></TD><TD><TEXTAREA COLS="30" ROWS="3" NAME="EditorComment" WRAP="VIRTUAL">'.(isset($OldThisfileInfo['comment']) ? $OldThisfileInfo['comment'] : '').'</TEXTAREA></TD></TR>';
|
||||||
|
if ($OldThisfileInfo['fileformat'] == 'mp3') {
|
||||||
|
echo '<TR><TD ALIGN="RIGHT"><B>Picture</B></TD><TD><INPUT TYPE="FILE" NAME="userfile" ACCEPT="image/jpeg, image/gif, image/png"></TD></TR>';
|
||||||
|
echo '<INPUT TYPE="HIDDEN" NAME="WriteID3v2TagNow" VALUE="1">';
|
||||||
|
echo '<TR><TD ALIGN="CENTER" COLSPAN="2"><INPUT TYPE="RADIO" NAME="WriteOrDelete" VALUE="W" CHECKED> Write <INPUT TYPE="RADIO" NAME="WriteOrDelete" VALUE="D"> Delete</TD></TR>';
|
||||||
|
echo '<TR><TD ALIGN="CENTER" COLSPAN="2"><INPUT TYPE="CHECKBOX" NAME="VersionToEdit1" VALUE="1"> ID3v1 <INPUT TYPE="CHECKBOX" NAME="VersionToEdit2" VALUE="2" CHECKED> ID3v2</TD></TR>';
|
||||||
|
} elseif ($OldThisfileInfo['fileformat'] == 'ogg') {
|
||||||
|
echo '<INPUT TYPE="HIDDEN" NAME="WriteOggCommentTagNow" VALUE="1">';
|
||||||
|
}
|
||||||
|
echo '<TR><TD ALIGN="CENTER" COLSPAN="2"><INPUT TYPE="SUBMIT" VALUE="Save Changes"> <INPUT TYPE="RESET" VALUE="Reset"></TD></TR>';
|
||||||
|
} else {
|
||||||
|
echo '<TR><TD ALIGN="RIGHT"><B>Error</B></TD><TD>'.FixTextFields($EditorFilename).' does not exist</TD></TR>';
|
||||||
|
echo '<TR><TD ALIGN="CENTER" COLSPAN="2"><INPUT TYPE="SUBMIT" VALUE="Find File"></TD></TR>';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
echo '<TR><TD ALIGN="CENTER" COLSPAN="2"><INPUT TYPE="TEXT" NAME="EditorFilename"></TD></TR>';
|
||||||
|
echo '<TR><TD ALIGN="CENTER" COLSPAN="2"><INPUT TYPE="SUBMIT" VALUE="Find File"></TD></TR>';
|
||||||
|
}
|
||||||
|
echo '</FORM></TABLE>';
|
||||||
|
|
||||||
|
?>
|
389
livesupport/modules/getid3/var/getid3.zip.php
Normal file
389
livesupport/modules/getid3/var/getid3.zip.php
Normal file
|
@ -0,0 +1,389 @@
|
||||||
|
<?php
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
/// getID3() by James Heinrich <getid3@users.sourceforge.net> //
|
||||||
|
// available at http://getid3.sourceforge.net ///
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
// //
|
||||||
|
// getid3.zip.php - part of getID3() //
|
||||||
|
// See getid3.readme.txt for more details //
|
||||||
|
// //
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
function getZIPHeaderFilepointer(&$fd, &$ThisFileInfo) {
|
||||||
|
|
||||||
|
$ThisFileInfo['fileformat'] = 'zip';
|
||||||
|
$ThisFileInfo['zip']['files'] = array();
|
||||||
|
|
||||||
|
$ThisFileInfo['zip']['compressed_size'] = 0;
|
||||||
|
$ThisFileInfo['zip']['uncompressed_size'] = 0;
|
||||||
|
$ThisFileInfo['zip']['entries_count'] = 0;
|
||||||
|
|
||||||
|
$EOCDsearchData = '';
|
||||||
|
$EOCDsearchCounter = 0;
|
||||||
|
while ($EOCDsearchCounter++ < 512) {
|
||||||
|
|
||||||
|
fseek($fd, -128 * $EOCDsearchCounter, SEEK_END);
|
||||||
|
$EOCDsearchData = fread($fd, 128).$EOCDsearchData;
|
||||||
|
|
||||||
|
if (strstr($EOCDsearchData, 'PK'.chr(5).chr(6))) {
|
||||||
|
|
||||||
|
$EOCDposition = strpos($EOCDsearchData, 'PK'.chr(5).chr(6));
|
||||||
|
fseek($fd, (-128 * $EOCDsearchCounter) + $EOCDposition, SEEK_END);
|
||||||
|
$ThisFileInfo['zip']['end_central_directory'] = ZIPparseEndOfCentralDirectory($fd);
|
||||||
|
|
||||||
|
fseek($fd, $ThisFileInfo['zip']['end_central_directory']['directory_offset'], SEEK_SET);
|
||||||
|
$ThisFileInfo['zip']['entries_count'] = 0;
|
||||||
|
while ($centraldirectoryentry = ZIPparseCentralDirectory($fd)) {
|
||||||
|
$ThisFileInfo['zip']['central_directory'][] = $centraldirectoryentry;
|
||||||
|
$ThisFileInfo['zip']['entries_count']++;
|
||||||
|
$ThisFileInfo['zip']['compressed_size'] += $centraldirectoryentry['compressed_size'];
|
||||||
|
$ThisFileInfo['zip']['uncompressed_size'] += $centraldirectoryentry['uncompressed_size'];
|
||||||
|
|
||||||
|
if ($centraldirectoryentry['uncompressed_size'] > 0) {
|
||||||
|
$ThisFileInfo['zip']['files'] = array_merge_clobber($ThisFileInfo['zip']['files'], CreateDeepArray($centraldirectoryentry['filename'], '/', $centraldirectoryentry['uncompressed_size']));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($ThisFileInfo['zip']['entries_count'] == 0) {
|
||||||
|
$ThisFileInfo['error'] .= "\n".'No Central Directory entries found (truncated file?)';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($ThisFileInfo['zip']['end_central_directory']['comment'])) {
|
||||||
|
$ThisFileInfo['zip']['comments']['comment'] = $ThisFileInfo['zip']['end_central_directory']['comment'];
|
||||||
|
|
||||||
|
// ZIP tags have highest priority
|
||||||
|
if (!empty($ThisFileInfo['zip']['comments'])) {
|
||||||
|
CopyFormatCommentsToRootComments($ThisFileInfo['zip']['comments'], $ThisFileInfo, true, true, true);
|
||||||
|
}
|
||||||
|
// add tag to array of tags
|
||||||
|
$ThisFileInfo['tags'][] = 'zip';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($ThisFileInfo['zip']['central_directory'][0]['compression_method'])) {
|
||||||
|
$ThisFileInfo['zip']['compression_method'] = $ThisFileInfo['zip']['central_directory'][0]['compression_method'];
|
||||||
|
}
|
||||||
|
if (isset($ThisFileInfo['zip']['central_directory'][0]['flags']['compression_speed'])) {
|
||||||
|
$ThisFileInfo['zip']['compression_speed'] = $ThisFileInfo['zip']['central_directory'][0]['flags']['compression_speed'];
|
||||||
|
}
|
||||||
|
if (isset($ThisFileInfo['zip']['compression_method']) && ($ThisFileInfo['zip']['compression_method'] == 'store') && !isset($ThisFileInfo['zip']['compression_speed'])) {
|
||||||
|
$ThisFileInfo['zip']['compression_speed'] = 'store';
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getZIPentriesFilepointer($fd, $ThisFileInfo)) {
|
||||||
|
|
||||||
|
// central directory couldn't be found and/or parsed
|
||||||
|
// scan through actual file data entries, recover as much as possible from probable trucated file
|
||||||
|
if ($ThisFileInfo['zip']['compressed_size'] > ($ThisFileInfo['filesize'] - 46 - 22)) {
|
||||||
|
$ThisFileInfo['error'] .= "\n".'Warning: Truncated file! - Total compressed file sizes ('.$ThisFileInfo['zip']['compressed_size'].' bytes) is greater than filesize minus Central Directory and End Of Central Directory structures ('.($ThisFileInfo['filesize'] - 46 - 22).' bytes)';
|
||||||
|
}
|
||||||
|
$ThisFileInfo['error'] .= "\n".'Cannot find End Of Central Directory - returned list of files in [zip][entries] array may not be complete';
|
||||||
|
return true;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
unset($ThisFileInfo['zip']);
|
||||||
|
$ThisFileInfo['fileformat'] = '';
|
||||||
|
$ThisFileInfo['error'] .= "\n".'Cannot find End Of Central Directory (truncated file?)';
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function getZIPHeaderFilepointerTopDown(&$fd, &$ThisFileInfo) {
|
||||||
|
$ThisFileInfo['fileformat'] = 'zip';
|
||||||
|
|
||||||
|
$ThisFileInfo['zip']['compressed_size'] = 0;
|
||||||
|
$ThisFileInfo['zip']['uncompressed_size'] = 0;
|
||||||
|
$ThisFileInfo['zip']['entries_count'] = 0;
|
||||||
|
|
||||||
|
rewind($fd);
|
||||||
|
while ($fileentry = ZIPparseLocalFileHeader($fd)) {
|
||||||
|
$ThisFileInfo['zip']['entries'][] = $fileentry;
|
||||||
|
$ThisFileInfo['zip']['entries_count']++;
|
||||||
|
}
|
||||||
|
if ($ThisFileInfo['zip']['entries_count'] == 0) {
|
||||||
|
$ThisFileInfo['error'] .= "\n".'No Local File Header entries found';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$ThisFileInfo['zip']['entries_count'] = 0;
|
||||||
|
while ($centraldirectoryentry = ZIPparseCentralDirectory($fd)) {
|
||||||
|
$ThisFileInfo['zip']['central_directory'][] = $centraldirectoryentry;
|
||||||
|
$ThisFileInfo['zip']['entries_count']++;
|
||||||
|
$ThisFileInfo['zip']['compressed_size'] += $centraldirectoryentry['compressed_size'];
|
||||||
|
$ThisFileInfo['zip']['uncompressed_size'] += $centraldirectoryentry['uncompressed_size'];
|
||||||
|
}
|
||||||
|
if ($ThisFileInfo['zip']['entries_count'] == 0) {
|
||||||
|
$ThisFileInfo['error'] .= "\n".'No Central Directory entries found (truncated file?)';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($EOCD = ZIPparseEndOfCentralDirectory($fd)) {
|
||||||
|
$ThisFileInfo['zip']['end_central_directory'] = $EOCD;
|
||||||
|
} else {
|
||||||
|
$ThisFileInfo['error'] .= "\n".'No End Of Central Directory entry found (truncated file?)';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($ThisFileInfo['zip']['end_central_directory']['comment'])) {
|
||||||
|
$ThisFileInfo['zip']['comments']['comment'] = $ThisFileInfo['zip']['end_central_directory']['comment'];
|
||||||
|
|
||||||
|
// ZIP tags have highest priority
|
||||||
|
if (!empty($ThisFileInfo['zip']['comments'])) {
|
||||||
|
CopyFormatCommentsToRootComments($ThisFileInfo['zip']['comments'], $ThisFileInfo, true, true, true);
|
||||||
|
}
|
||||||
|
// add tag to array of tags
|
||||||
|
$ThisFileInfo['tags'][] = 'zip';
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function getZIPentriesFilepointer(&$fd, &$ThisFileInfo) {
|
||||||
|
$ThisFileInfo['zip']['compressed_size'] = 0;
|
||||||
|
$ThisFileInfo['zip']['uncompressed_size'] = 0;
|
||||||
|
$ThisFileInfo['zip']['entries_count'] = 0;
|
||||||
|
|
||||||
|
rewind($fd);
|
||||||
|
while ($fileentry = ZIPparseLocalFileHeader($fd)) {
|
||||||
|
$ThisFileInfo['zip']['entries'][] = $fileentry;
|
||||||
|
$ThisFileInfo['zip']['entries_count']++;
|
||||||
|
$ThisFileInfo['zip']['compressed_size'] += $fileentry['compressed_size'];
|
||||||
|
$ThisFileInfo['zip']['uncompressed_size'] += $fileentry['uncompressed_size'];
|
||||||
|
}
|
||||||
|
if ($ThisFileInfo['zip']['entries_count'] == 0) {
|
||||||
|
$ThisFileInfo['error'] .= "\n".'No Local File Header entries found';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function ZIPparseLocalFileHeader(&$fd) {
|
||||||
|
$LocalFileHeader['offset'] = ftell($fd);
|
||||||
|
|
||||||
|
$ZIPlocalFileHeader = fread($fd, 30);
|
||||||
|
|
||||||
|
$LocalFileHeader['raw']['signature'] = LittleEndian2Int(substr($ZIPlocalFileHeader, 0, 4));
|
||||||
|
if ($LocalFileHeader['raw']['signature'] != 0x04034B50) {
|
||||||
|
// invalid Local File Header Signature
|
||||||
|
fseek($fd, $LocalFileHeader['offset'], SEEK_SET); // seek back to where filepointer originally was so it can be handled properly
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$LocalFileHeader['raw']['extract_version'] = LittleEndian2Int(substr($ZIPlocalFileHeader, 4, 2));
|
||||||
|
$LocalFileHeader['raw']['general_flags'] = LittleEndian2Int(substr($ZIPlocalFileHeader, 6, 2));
|
||||||
|
$LocalFileHeader['raw']['compression_method'] = LittleEndian2Int(substr($ZIPlocalFileHeader, 8, 2));
|
||||||
|
$LocalFileHeader['raw']['last_mod_file_time'] = LittleEndian2Int(substr($ZIPlocalFileHeader, 10, 2));
|
||||||
|
$LocalFileHeader['raw']['last_mod_file_date'] = LittleEndian2Int(substr($ZIPlocalFileHeader, 12, 2));
|
||||||
|
$LocalFileHeader['raw']['crc_32'] = LittleEndian2Int(substr($ZIPlocalFileHeader, 14, 4));
|
||||||
|
$LocalFileHeader['raw']['compressed_size'] = LittleEndian2Int(substr($ZIPlocalFileHeader, 18, 4));
|
||||||
|
$LocalFileHeader['raw']['uncompressed_size'] = LittleEndian2Int(substr($ZIPlocalFileHeader, 22, 4));
|
||||||
|
$LocalFileHeader['raw']['filename_length'] = LittleEndian2Int(substr($ZIPlocalFileHeader, 26, 2));
|
||||||
|
$LocalFileHeader['raw']['extra_field_length'] = LittleEndian2Int(substr($ZIPlocalFileHeader, 28, 2));
|
||||||
|
|
||||||
|
$LocalFileHeader['extract_version'] = sprintf('%1.1f', $LocalFileHeader['raw']['extract_version'] / 10);
|
||||||
|
$LocalFileHeader['host_os'] = ZIPversionOSLookup(($LocalFileHeader['raw']['extract_version'] & 0xFF00) >> 8);
|
||||||
|
$LocalFileHeader['compression_method'] = ZIPcompressionMethodLookup($LocalFileHeader['raw']['compression_method']);
|
||||||
|
$LocalFileHeader['compressed_size'] = $LocalFileHeader['raw']['compressed_size'];
|
||||||
|
$LocalFileHeader['uncompressed_size'] = $LocalFileHeader['raw']['uncompressed_size'];
|
||||||
|
$LocalFileHeader['flags'] = ZIPparseGeneralPurposeFlags($LocalFileHeader['raw']['general_flags'], $LocalFileHeader['raw']['compression_method']);
|
||||||
|
$LocalFileHeader['last_modified_timestamp'] = DOStime2UNIXtime($LocalFileHeader['raw']['last_mod_file_date'], $LocalFileHeader['raw']['last_mod_file_time']);
|
||||||
|
|
||||||
|
$FilenameExtrafieldLength = $LocalFileHeader['raw']['filename_length'] + $LocalFileHeader['raw']['extra_field_length'];
|
||||||
|
if ($FilenameExtrafieldLength > 0) {
|
||||||
|
$ZIPlocalFileHeader .= fread($fd, $FilenameExtrafieldLength);
|
||||||
|
|
||||||
|
if ($LocalFileHeader['raw']['filename_length'] > 0) {
|
||||||
|
$LocalFileHeader['filename'] = substr($ZIPlocalFileHeader, 30, $LocalFileHeader['raw']['filename_length']);
|
||||||
|
}
|
||||||
|
if ($LocalFileHeader['raw']['extra_field_length'] > 0) {
|
||||||
|
$LocalFileHeader['raw']['extra_field_data'] = substr($ZIPlocalFileHeader, 30 + $LocalFileHeader['raw']['filename_length'], $LocalFileHeader['raw']['extra_field_length']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//$LocalFileHeader['compressed_data'] = fread($fd, $LocalFileHeader['raw']['compressed_size']);
|
||||||
|
fseek($fd, $LocalFileHeader['raw']['compressed_size'], SEEK_CUR);
|
||||||
|
|
||||||
|
if ($LocalFileHeader['flags']['data_descriptor_used']) {
|
||||||
|
$DataDescriptor = fread($fd, 12);
|
||||||
|
$LocalFileHeader['data_descriptor']['crc_32'] = LittleEndian2Int(substr($DataDescriptor, 0, 4));
|
||||||
|
$LocalFileHeader['data_descriptor']['compressed_size'] = LittleEndian2Int(substr($DataDescriptor, 4, 4));
|
||||||
|
$LocalFileHeader['data_descriptor']['uncompressed_size'] = LittleEndian2Int(substr($DataDescriptor, 8, 4));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $LocalFileHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function ZIPparseCentralDirectory(&$fd) {
|
||||||
|
$CentralDirectory['offset'] = ftell($fd);
|
||||||
|
|
||||||
|
$ZIPcentralDirectory = fread($fd, 46);
|
||||||
|
|
||||||
|
$CentralDirectory['raw']['signature'] = LittleEndian2Int(substr($ZIPcentralDirectory, 0, 4));
|
||||||
|
if ($CentralDirectory['raw']['signature'] != 0x02014B50) {
|
||||||
|
// invalid Central Directory Signature
|
||||||
|
fseek($fd, $CentralDirectory['offset'], SEEK_SET); // seek back to where filepointer originally was so it can be handled properly
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$CentralDirectory['raw']['create_version'] = LittleEndian2Int(substr($ZIPcentralDirectory, 4, 2));
|
||||||
|
$CentralDirectory['raw']['extract_version'] = LittleEndian2Int(substr($ZIPcentralDirectory, 6, 2));
|
||||||
|
$CentralDirectory['raw']['general_flags'] = LittleEndian2Int(substr($ZIPcentralDirectory, 8, 2));
|
||||||
|
$CentralDirectory['raw']['compression_method'] = LittleEndian2Int(substr($ZIPcentralDirectory, 10, 2));
|
||||||
|
$CentralDirectory['raw']['last_mod_file_time'] = LittleEndian2Int(substr($ZIPcentralDirectory, 12, 2));
|
||||||
|
$CentralDirectory['raw']['last_mod_file_date'] = LittleEndian2Int(substr($ZIPcentralDirectory, 14, 2));
|
||||||
|
$CentralDirectory['raw']['crc_32'] = LittleEndian2Int(substr($ZIPcentralDirectory, 16, 4));
|
||||||
|
$CentralDirectory['raw']['compressed_size'] = LittleEndian2Int(substr($ZIPcentralDirectory, 20, 4));
|
||||||
|
$CentralDirectory['raw']['uncompressed_size'] = LittleEndian2Int(substr($ZIPcentralDirectory, 24, 4));
|
||||||
|
$CentralDirectory['raw']['filename_length'] = LittleEndian2Int(substr($ZIPcentralDirectory, 28, 2));
|
||||||
|
$CentralDirectory['raw']['extra_field_length'] = LittleEndian2Int(substr($ZIPcentralDirectory, 30, 2));
|
||||||
|
$CentralDirectory['raw']['file_comment_length'] = LittleEndian2Int(substr($ZIPcentralDirectory, 32, 2));
|
||||||
|
$CentralDirectory['raw']['disk_number_start'] = LittleEndian2Int(substr($ZIPcentralDirectory, 34, 2));
|
||||||
|
$CentralDirectory['raw']['internal_file_attrib'] = LittleEndian2Int(substr($ZIPcentralDirectory, 36, 2));
|
||||||
|
$CentralDirectory['raw']['external_file_attrib'] = LittleEndian2Int(substr($ZIPcentralDirectory, 38, 4));
|
||||||
|
$CentralDirectory['raw']['local_header_offset'] = LittleEndian2Int(substr($ZIPcentralDirectory, 42, 4));
|
||||||
|
|
||||||
|
$CentralDirectory['entry_offset'] = $CentralDirectory['raw']['local_header_offset'];
|
||||||
|
$CentralDirectory['create_version'] = sprintf('%1.1f', $CentralDirectory['raw']['create_version'] / 10);
|
||||||
|
$CentralDirectory['extract_version'] = sprintf('%1.1f', $CentralDirectory['raw']['extract_version'] / 10);
|
||||||
|
$CentralDirectory['host_os'] = ZIPversionOSLookup(($CentralDirectory['raw']['extract_version'] & 0xFF00) >> 8);
|
||||||
|
$CentralDirectory['compression_method'] = ZIPcompressionMethodLookup($CentralDirectory['raw']['compression_method']);
|
||||||
|
$CentralDirectory['compressed_size'] = $CentralDirectory['raw']['compressed_size'];
|
||||||
|
$CentralDirectory['uncompressed_size'] = $CentralDirectory['raw']['uncompressed_size'];
|
||||||
|
$CentralDirectory['flags'] = ZIPparseGeneralPurposeFlags($CentralDirectory['raw']['general_flags'], $CentralDirectory['raw']['compression_method']);
|
||||||
|
$CentralDirectory['last_modified_timestamp'] = DOStime2UNIXtime($CentralDirectory['raw']['last_mod_file_date'], $CentralDirectory['raw']['last_mod_file_time']);
|
||||||
|
|
||||||
|
$FilenameExtrafieldCommentLength = $CentralDirectory['raw']['filename_length'] + $CentralDirectory['raw']['extra_field_length'] + $CentralDirectory['raw']['file_comment_length'];
|
||||||
|
if ($FilenameExtrafieldCommentLength > 0) {
|
||||||
|
$FilenameExtrafieldComment = fread($fd, $FilenameExtrafieldCommentLength);
|
||||||
|
|
||||||
|
if ($CentralDirectory['raw']['filename_length'] > 0) {
|
||||||
|
$CentralDirectory['filename'] = substr($FilenameExtrafieldComment, 0, $CentralDirectory['raw']['filename_length']);
|
||||||
|
}
|
||||||
|
if ($CentralDirectory['raw']['extra_field_length'] > 0) {
|
||||||
|
$CentralDirectory['raw']['extra_field_data'] = substr($FilenameExtrafieldComment, $CentralDirectory['raw']['filename_length'], $CentralDirectory['raw']['extra_field_length']);
|
||||||
|
}
|
||||||
|
if ($CentralDirectory['raw']['file_comment_length'] > 0) {
|
||||||
|
$CentralDirectory['file_comment'] = substr($FilenameExtrafieldComment, $CentralDirectory['raw']['filename_length'] + $CentralDirectory['raw']['extra_field_length'], $CentralDirectory['raw']['file_comment_length']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $CentralDirectory;
|
||||||
|
}
|
||||||
|
|
||||||
|
function ZIPparseEndOfCentralDirectory(&$fd) {
|
||||||
|
$EndOfCentralDirectory['offset'] = ftell($fd);
|
||||||
|
|
||||||
|
$ZIPendOfCentralDirectory = fread($fd, 22);
|
||||||
|
|
||||||
|
$EndOfCentralDirectory['signature'] = LittleEndian2Int(substr($ZIPendOfCentralDirectory, 0, 4));
|
||||||
|
if ($EndOfCentralDirectory['signature'] != 0x06054B50) {
|
||||||
|
// invalid End Of Central Directory Signature
|
||||||
|
fseek($fd, $EndOfCentralDirectory['offset'], SEEK_SET); // seek back to where filepointer originally was so it can be handled properly
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$EndOfCentralDirectory['disk_number_current'] = LittleEndian2Int(substr($ZIPendOfCentralDirectory, 4, 2));
|
||||||
|
$EndOfCentralDirectory['disk_number_start_directory'] = LittleEndian2Int(substr($ZIPendOfCentralDirectory, 6, 2));
|
||||||
|
$EndOfCentralDirectory['directory_entries_this_disk'] = LittleEndian2Int(substr($ZIPendOfCentralDirectory, 8, 2));
|
||||||
|
$EndOfCentralDirectory['directory_entries_total'] = LittleEndian2Int(substr($ZIPendOfCentralDirectory, 10, 2));
|
||||||
|
$EndOfCentralDirectory['directory_size'] = LittleEndian2Int(substr($ZIPendOfCentralDirectory, 12, 4));
|
||||||
|
$EndOfCentralDirectory['directory_offset'] = LittleEndian2Int(substr($ZIPendOfCentralDirectory, 16, 4));
|
||||||
|
$EndOfCentralDirectory['comment_length'] = LittleEndian2Int(substr($ZIPendOfCentralDirectory, 20, 2));
|
||||||
|
|
||||||
|
if ($EndOfCentralDirectory['comment_length'] > 0) {
|
||||||
|
$EndOfCentralDirectory['comment'] = fread($fd, $EndOfCentralDirectory['comment_length']);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $EndOfCentralDirectory;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function ZIPparseGeneralPurposeFlags($flagbytes, $compressionmethod) {
|
||||||
|
$ParsedFlags['encrypted'] = (bool) ($flagbytes & 0x0001);
|
||||||
|
|
||||||
|
switch ($compressionmethod) {
|
||||||
|
case 6:
|
||||||
|
$ParsedFlags['dictionary_size'] = (($flagbytes & 0x0002) ? 8192 : 4096);
|
||||||
|
$ParsedFlags['shannon_fano_trees'] = (($flagbytes & 0x0004) ? 3 : 2);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 8:
|
||||||
|
case 9:
|
||||||
|
switch (($flagbytes & 0x0006) >> 1) {
|
||||||
|
case 0:
|
||||||
|
$ParsedFlags['compression_speed'] = 'normal';
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
$ParsedFlags['compression_speed'] = 'maximum';
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
$ParsedFlags['compression_speed'] = 'fast';
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
$ParsedFlags['compression_speed'] = 'superfast';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
$ParsedFlags['data_descriptor_used'] = (bool) ($flagbytes & 0x0008);
|
||||||
|
|
||||||
|
return $ParsedFlags;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function ZIPversionOSLookup($index) {
|
||||||
|
static $ZIPversionOSLookup = array();
|
||||||
|
if (empty($ZIPversionOSLookup)) {
|
||||||
|
$ZIPversionOSLookup[0] = 'MS-DOS and OS/2 (FAT / VFAT / FAT32 file systems)';
|
||||||
|
$ZIPversionOSLookup[1] = 'Amiga';
|
||||||
|
$ZIPversionOSLookup[2] = 'OpenVMS';
|
||||||
|
$ZIPversionOSLookup[3] = 'Unix';
|
||||||
|
$ZIPversionOSLookup[4] = 'VM/CMS';
|
||||||
|
$ZIPversionOSLookup[5] = 'Atari ST';
|
||||||
|
$ZIPversionOSLookup[6] = 'OS/2 H.P.F.S.';
|
||||||
|
$ZIPversionOSLookup[7] = 'Macintosh';
|
||||||
|
$ZIPversionOSLookup[8] = 'Z-System';
|
||||||
|
$ZIPversionOSLookup[9] = 'CP/M';
|
||||||
|
$ZIPversionOSLookup[10] = 'Windows NTFS';
|
||||||
|
$ZIPversionOSLookup[11] = 'MVS';
|
||||||
|
$ZIPversionOSLookup[12] = 'VSE';
|
||||||
|
$ZIPversionOSLookup[13] = 'Acorn Risc';
|
||||||
|
$ZIPversionOSLookup[14] = 'VFAT';
|
||||||
|
$ZIPversionOSLookup[15] = 'Alternate MVS';
|
||||||
|
$ZIPversionOSLookup[16] = 'BeOS';
|
||||||
|
$ZIPversionOSLookup[17] = 'Tandem';
|
||||||
|
}
|
||||||
|
|
||||||
|
return (isset($ZIPversionOSLookup[$index]) ? $ZIPversionOSLookup[$index] : '[unknown]');
|
||||||
|
}
|
||||||
|
|
||||||
|
function ZIPcompressionMethodLookup($index) {
|
||||||
|
static $ZIPcompressionMethodLookup = array();
|
||||||
|
if (empty($ZIPcompressionMethodLookup)) {
|
||||||
|
$ZIPcompressionMethodLookup[0] = 'store';
|
||||||
|
$ZIPcompressionMethodLookup[1] = 'shrink';
|
||||||
|
$ZIPcompressionMethodLookup[2] = 'reduce-1';
|
||||||
|
$ZIPcompressionMethodLookup[3] = 'reduce-2';
|
||||||
|
$ZIPcompressionMethodLookup[4] = 'reduce-3';
|
||||||
|
$ZIPcompressionMethodLookup[5] = 'reduce-4';
|
||||||
|
$ZIPcompressionMethodLookup[6] = 'implode';
|
||||||
|
$ZIPcompressionMethodLookup[7] = 'tokenize';
|
||||||
|
$ZIPcompressionMethodLookup[8] = 'deflate';
|
||||||
|
$ZIPcompressionMethodLookup[9] = 'deflate64';
|
||||||
|
$ZIPcompressionMethodLookup[10] = 'PKWARE Date Compression Library Imploding';
|
||||||
|
}
|
||||||
|
|
||||||
|
return (isset($ZIPcompressionMethodLookup[$index]) ? $ZIPcompressionMethodLookup[$index] : '[unknown]');
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
Loading…
Add table
Add a link
Reference in a new issue