Detect-It-Easy/db/Binary/mp3.2.sg
2014-06-01 23:42:39 +02:00

215 lines
6.4 KiB
Text

// DIE's signature file
// Author: Jason Hood <jadoxa@yahoo.com.au>
/*
Ref: http://mpgedit.org/mpgedit/mpeg_format/mpeghdr.htm
http://www.codeproject.com/Articles/8295/MPEG-Audio-Frame-Header
*/
init("audio","MP3 Audio File");
includeScript("duration");
var MP3={
aVersion:["2.5","2","1"],
aLayer: ["III","II","I"],
aRatev1: [32,40,48, 56, 64, 80, 96,112,128,160,192,224,256,320, // Layer III
32,48,56, 64, 80, 96,112,128,160,192,224,256,320,384, // Layer II
32,64,96,128,160,192,224,256,288,320,352,384,416,448], // Layer I
aRatev2: [ 8,16,24,32,40,48, 56, 64, 80, 96,112,128,144,160, // Layers III & II
32,48,56,64,80,96,112,128,144,160,176,192,224,256], // Layer I
aFreq: [11025,12000, 8000, // v2.5
22050,24000,16000, // v2
44100,48000,32000], // v1
aCh: ["Stereo","Joint stereo","Dual mono","Mono"],
header: function(nOffset)
{
// AAAAAAAA AAABBCCD EEEEFFGH IIJJKLMM
var nHeader=Binary.readBEDword(nOffset);
if((nHeader&0xFFE00000)!=~~0xFFE00000) // AAAAAAAAAAA
{
return null;
}
var nVer=(nHeader>>>19)&3; // BB
if(nVer==1) // reserved
{
return null;
}
if(nVer>1)
{
--nVer;
}
var nLayer=(nHeader>>>17)&3; // CC
if(nLayer==0) // reserved
{
return null;
}
--nLayer;
var nBitrateIndex=(nHeader>>>12)&15; // EEEE
if(nBitrateIndex==0||nBitrateIndex==15) // free/bad
{
return null;
}
--nBitrateIndex;
var nSamplingIndex=(nHeader>>>10)&3; // FF
if(nSamplingIndex==3) // reserved
{
return null;
}
var nPadding=(nHeader>>>9)&1; // G
var nChannelMode=(nHeader>>>6)&3; // II
var nBitrate=nVer==2?this.aRatev1[nLayer*14+nBitrateIndex]
:this.aRatev2[(nLayer==2)*14+nBitrateIndex];
var nFreq=this.aFreq[nVer*3+nSamplingIndex];
var nTime;
if(nLayer==2) // Layer I
{
nTime=384/nFreq;
}
else if(nLayer==1||nVer==2) // Layer II or v1,Layer III
{
nTime=1152/nFreq;
}
else // v2/2.5,Layer III
{
nTime=576/nFreq;
}
var bVBR=1;
var nVBR=Binary.findString(nOffset,40,"Xing");
if(nVBR==-1)
{
nVBR=Binary.findString(nOffset,40,"Info");
bVBR=0;
}
if(nVBR!=-1&&(Binary.readByte(nVBR+7)&1))
{
nTime*=Binary.readBEDword(nVBR+8);
nOffset=bVBR?-1:-2;
}
else if(Binary.compare("'VBRI'",nOffset+32))
{
nTime*=Binary.readBEDword(nVBR+46);
nOffset=-1;
}
else
{
if(nLayer==2) // Layer I
{
nOffset+=Math.floor(12000*nBitrate/nFreq+nPadding)*4;
}
else
{
// 125 = 1000/8 = kilobits to bytes
nOffset+=Math.floor(125*nBitrate*nTime+nPadding);
}
}
return [this.aVersion[nVer],
this.aLayer[nLayer],
nBitrate,
nFreq,
this.aCh[nChannelMode],
nTime,
nOffset];
}
}
function detect(bShowType,bShowVersion,bShowOptions)
{
if(Binary.getSize()>=128)
{
if(Binary.compare("'TAG'",Binary.getSize()-128))
{
sOptions="ID3v1";
}
var nOffset=0,bID3v2=0;
if(Binary.compare("'ID3'"))
{
nOffset=(Binary.readByte(6)<<21)
|(Binary.readByte(7)<<14)
|(Binary.readByte(8)<<7)
|(Binary.readByte(9));
nOffset+=10;
if(sOptions=="")
{
sOptions="ID3v2";
}
else
{
sOptions+="&2";
}
bID3v2=1;
}
else if(Binary.compare("'WAVEfmt '........55",8))
{
nOffset=Binary.findString(50,50,"data")+8;
}
var aResult1,aResult=null;
aResult1=MP3.header(nOffset);
if(aResult1==null)
{
if(bID3v2)
{
// There may be some junk between the ID3 tag & the data (Win7
// sample music files - C:\Users\Public\Music\Sample Music).
// Since the ID3 tag is a fair indicator of an MP3, do a search
// for v1,Layer III header.
nOffset=Binary.findSignature(nOffset,768,"FFFB");
aResult1=MP3.header(nOffset);
}
if(aResult1==null)
{
return "";
}
}
if(aResult1[6]>0)
{
aResult=MP3.header(aResult1[6]);
if(aResult==null)
{
return "";
}
}
bDetected=1;
// Assume version, layer & channels don't change.
sVersion="v"+aResult1[0]+",Layer "+aResult1[1];
if(bShowOptions)
{
var nFrames=1;
var nRateSum=aResult1[2];
var nFreqSum=aResult1[3];
var nSeconds=aResult1[5];
var bVBR=0,bVF=0;
while(aResult!=null)
{
nFrames++;
nRateSum+=aResult[2];
nFreqSum+=aResult[3];
nSeconds+=aResult[5];
if(aResult[2]!=aResult1[2])
{
bVBR=1;
}
if(aResult[3]!=aResult1[3])
{
bVF=1;
}
aResult=MP3.header(aResult[6]);
}
sOptions=sOptions.append(Math.round(nRateSum/nFrames)+"kbps");
if(bVBR)
{
sOptions+="(avg)";
}
sOptions=sOptions.append(Math.round(nFreqSum/nFrames)+"Hz");
if(bVF)
{
sOptions+="(avg)";
}
sOptions=sOptions.append(aResult1[4],duration(nSeconds));
}
}
return result(bShowType,bShowVersion,bShowOptions);
}