001function readframe($file) {
002if (! ($f = fopen($file, 'rb')) ) die("Unable to open " . $file);
003$res['filesize'] = filesize($file);
004do {
005while (fread($f,1) != Chr(255)) { // Find the first frame
006if (feof($f)) die( "No mpeg frame found") ;
007}
008fseek($f, ftell($f) - 1); // back up one byte
009
010$frameoffset = ftell($f);
011
012$r = fread($f, 4);
013
014$bits = sprintf("%'08b%'08b%'08b%'08b", ord($r{0}), ord($r{1}), ord($r{2}), ord($r{3}));
015}
016while (!$bits[8] and !$bits[9] and !$bits[10]); // 1st 8 bits true from the while
017
018// Detect VBR header
019if ($bits[11] == 0) {
020if (($bits[24] == 1) && ($bits[25] == 1)) {
021$vbroffset = 9; // MPEG 2.5 Mono
022} else {
023$vbroffset = 17; // MPEG 2.5 Stereo
024}
025} else if ($bits[12] == 0) {
026if (($bits[24] == 1) && ($bits[25] == 1)) {
027$vbroffset = 9; // MPEG 2 Mono
028} else {
029$vbroffset = 17; // MPEG 2 Stereo
030}
031} else {
032if (($bits[24] == 1) && ($bits[25] == 1)) {
033$vbroffset = 17; // MPEG 1 Mono
034} else {
035$vbroffset = 32; // MPEG 1 Stereo
036}
037}
038
039fseek($f, ftell($f) + $vbroffset);
040$r = fread($f, 4);
041
042switch ($r) {
043case 'Xing':
044$res['encoding_type'] = 'VBR';
045case 'VBRI':
046default:
047if ($vbroffset != 32) {
048// VBRI Header is fixed after 32 bytes, so maybe we are looking at the wrong place.
049fseek($f, ftell($f) + 32 - $vbroffset);
050$r = fread($f, 4);
051
052if ($r != 'VBRI') {
053$res['encoding_type'] = 'CBR';
054break;
055}
056} else {
057$res['encoding_type'] = 'CBR';
058break;
059}
060
061$res['encoding_type'] = 'VBR';
062}
063
064fclose($f);
065
066if ($bits[11] == 0) {
067$res['mpeg_ver'] = "2.5";
068$bitrates = array(
069'1' => array(0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, 0),
070'2' => array(0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0),
071'3' => array(0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0),
072);
073} else if ($bits[12] == 0) {
074$res['mpeg_ver'] = "2";
075$bitrates = array(
076'1' => array(0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, 0),
077'2' => array(0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0),
078'3' => array(0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0),
079);
080} else {
081$res['mpeg_ver'] = "1";
082$bitrates = array(
083'1' => array(0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 0),
084'2' => array(0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 0),
085'3' => array(0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 0),
086);
087}
088
089$layer = array(
090array(0,3),
091array(2,1),
092);
093$res['layer'] = $layer[$bits[13]][$bits[14]];
094
095if ($bits[15] == 0) {
096// It's backwards, if the bit is not set then it is protected.
097$res['crc'] = true;
098}
099
100$bitrate = 0;
101if ($bits[16] == 1) $bitrate += 8;
102if ($bits[17] == 1) $bitrate += 4;
103if ($bits[18] == 1) $bitrate += 2;
104if ($bits[19] == 1) $bitrate += 1;
105$res['bitrate'] = $bitrates[$res['layer']][$bitrate];
106
107$frequency = array(
108'1' => array(
109'0' => array(44100, 48000),
110'1' => array(32000, 0),
111),
112'2' => array(
113'0' => array(22050, 24000),
114'1' => array(16000, 0),
115),
116'2.5' => array(
117'0' => array(11025, 12000),
118'1' => array(8000, 0),
119),
120);
121$res['frequency'] = $frequency[$res['mpeg_ver']][$bits[20]][$bits[21]];
122
123$mode = array(
124array('Stereo', 'Joint Stereo'),
125array('Dual Channel', 'Mono'),
126);
127$res['mode'] = $mode[$bits[24]][$bits[25]];
128
129$samplesperframe = array(
130'1' => array(
131'1' => 384,
132'2' => 1152,
133'3' => 1152
134),
135'2' => array(
136'1' => 384,
137'2' => 1152,
138'3' => 576
139),
140'2.5' => array(
141'1' => 384,
142'2' => 1152,
143'3' => 576
144),
145);
146$res['samples_per_frame'] = $samplesperframe[$res['mpeg_ver']][$res['layer']];
147
148if ($res['encoding_type'] != 'VBR') {
149if ($res['bitrate'] == 0) {
150$s = -1;
151} else {
152$s = ((8*filesize($file))/1000) / $res['bitrate'];
153}
154$res['length'] = sprintf('%02d:%02d',floor($s/60),floor($s-(floor($s/60)*60)));
155$res['lengthh'] = sprintf('%02d:%02d:%02d',floor($s/3600),floor($s/60),floor($s-(floor($s/60)*60)));
156$res['lengths'] = (int)$s;
157
158$res['samples'] = ceil($res['lengths'] * $res['frequency']);
159if(0 != $res['samples_per_frame']) {
160$res['frames'] = ceil($res['samples'] / $res['samples_per_frame']);
161} else {
162$res['frames'] = 0;
163}
164$res['musicsize'] = ceil($res['lengths'] * $res['bitrate'] * 1000 / 8);
165} else {
166$res['samples'] = $res['samples_per_frame'] * $res['frames'];
167$s = $res['samples'] / $res['frequency'];
168
169$res['length'] = sprintf('%02d:%02d',floor($s/60),floor($s-(floor($s/60)*60)));
170$res['lengthh'] = sprintf('%02d:%02d:%02d',floor($s/3600),floor($s/60),floor($s-(floor($s/60)*60)));
171$res['lengths'] = (int)$s;
172
173$res['bitrate'] = (int)(($res['musicsize'] / $s) * 8 / 1000);
174}
175
176return $res;
177}