I've been trying to develop an ID3 parser and here's what i got so far.
I've update the ID3Parser. It is much faster now.
Actionscript:
-
package libs.ashier.id3 {
-
-
package libs.ashier.id3 {
-
-
import flash.events.EventDispatcher;
-
import flash.filesystem.File;
-
import flash.filesystem.FileMode;
-
import flash.filesystem.FileStream;
-
import flash.utils.ByteArray;
-
import flash.utils.Dictionary;
-
import flash.utils.clearInterval;
-
import flash.utils.setInterval;
-
-
public class ID3Parser extends EventDispatcher{
-
-
public function ID3Parser():void {}
-
-
/**
-
* Bit 7 in the 'ID3v2 flags' indicates whether or not
-
* unsynchronisation is applied on all frames.
-
*/
-
private var unsynchronisation:uint;
-
-
/**
-
* The second bit (bit 6) indicates whether or not the header is
-
* followed by an extended header.
-
* A set bit indicates the presence of an extended header.
-
*/
-
private var extendedHeader:uint;
-
-
/**
-
* The third bit (bit 5) is used as an 'experimental indicator'. This
-
* flag SHALL always be set when the tag is in an experimental stage.
-
*/
-
private var experimental:uint;
-
-
/**
-
* FileStream / Bytes
-
*/
-
private var fs:FileStream;
-
-
/**
-
* Id3 Version
-
*/
-
private var version:Number;
-
-
/**
-
* Available Genres
-
*/
-
private var genres:Array = [
-
"Blues", "Classic Rock", "Country", "Dance", "Disco", "Funk",
-
"Grunge", "Hip-Hop", "Jazz", "Metal", "New Age", "Oldies", "Other",
-
"Pop", "R&B", "Rap", "Reggae", "Rock", "Techno", "Industrial",
-
"Alternative", "Ska", "Death Metal", "Pranks", "Soundtrack",
-
"Euro-Techno", "Ambient", "Trip-Hop", "Vocal", "Jazz+Funk", "Fusion",
-
"Trance", "Classical", "Instrumental", "Acid", "House", "Game",
-
"Sound Clip", "Gospel", "Noise", "Alt. Rock", "Bass", "Soul",
-
"Punk", "Space", "Meditative", "Instrum. Pop", "Instrum. Rock",
-
"Ethnic", "Gothic", "Darkwave", "Techno-Indust.", "Electronic",
-
"Pop-Folk", "Eurodance", "Dream", "Southern Rock", "Comedy",
-
"Cult", "Gangsta", "Top 40", "Christian Rap", "Pop/Funk", "Jungle",
-
"Native American", "Cabaret", "New Wave", "Psychadelic", "Rave",
-
"Showtunes", "Trailer", "Lo-Fi", "Tribal", "Acid Punk", "Acid Jazz",
-
"Polka", "Retro", "Musical", "Rock & Roll", "Hard Rock", "Folk",
-
"Folk/Rock", "National Folk", "Swing", "Fusion", "Bebob", "Latin",
-
"Revival", "Celtic", "Bluegrass", "Avantgarde", "Gothic Rock",
-
"Progress. Rock", "Psychadel. Rock", "Symphonic Rock", "Slow Rock",
-
"Big Band", "Chorus", "Easy Listening", "Acoustic", "Humour",
-
"Speech", "Chanson", "Opera", "Chamber Music", "Sonata", "Symphony",
-
"Booty Bass", "Primus", "Porn Groove", "Satire", "Slow Jam",
-
"Club", "Tango", "Samba", "Folklore", "Ballad", "Power Ballad",
-
"Rhythmic Soul", "Freestyle", "Duet", "Punk Rock", "Drum Solo",
-
"A Capella", "Euro-House", "Dance Hall", "Goa", "Drum & Bass",
-
"Club-House", "Hardcore", "Terror", "Indie", "BritPop", "Negerpunk",
-
"Polsk Punk", "Beat", "Christian Gangsta Rap", "Heavy Metal",
-
"Black Metal", "Crossover", "Contemporary Christian", "Christian Rock",
-
"Merengue", "Salsa", "Thrash Metal", "Anime", "Jpop", "Synthpop"
-
];
-
-
-
/**
-
* Get ID3 Profile
-
*
-
*/
-
private function getID3Profile():void {
-
fs = new FileStream();
-
try {
-
fs.open(_file, FileMode.READ);
-
}catch (e:Error) {}
-
if(_file) {
-
clearInterval(interval);
-
interval = setInterval(checkID3, 10, fs);
-
}
-
}
-
-
/**
-
* ID3 Flag
-
*/
-
private var flags:uint;
-
private var interval:uint;
-
private var interval2:uint;
-
-
/**
-
* Check if ID3 is Valid.
-
* @param fs
-
*
-
*/
-
public function checkID3(fs:FileStream):void {
-
clearInterval(interval);
-
fs.position = 0;
-
var type:String = fs.readUTFBytes(3);
-
if(type.toLocaleUpperCase() == "ID3") {
-
version = fs.readByte() + fs.readByte()/100;
-
if(version>= 3) {
-
frameIdSize = 4;
-
}
-
-
flags = fs.readByte();
-
unsynchronisation = flags>> 7;
-
extendedHeader = flags>> 6 && 01;
-
experimental = flags>> 5 && 001;
-
clearInterval(interval2);
-
interval2 = setInterval(readFrames, 10);
-
}else {
-
dispatchEvent(new ID3ParserEvent(ID3ParserEvent.ERROR, {message:"Not a valid ID3."}));
-
}
-
}
-
-
/**
-
* Declared ID3v2 frames
-
*/
-
private var frames:Object;
-
-
/**
-
* First FrameId Size. Default is 3.
-
*/
-
private var frameIdSize:uint = 3;
-
-
/**
-
* Parse all types of frames in an ID3.
-
*
-
*/
-
-
private var length:int = 0;
-
private var lastFSPosition:int = 0;
-
-
private function readFrames():void {
-
clearInterval(interval2);
-
if(!frames) {
-
frames = new Object();
-
}
-
length = convertSynchsafe(fs.readUnsignedInt()) + 10;
-
parseFrames();
-
lastFSPosition = fs.position;
-
fs.close();
-
dispatchEvent(new ID3ParserEvent(ID3ParserEvent.ID3, ID3Info));
-
}
-
-
private var regEx:RegExp = new RegExp("" +
-
"/AENC|APIC|PIC|" +
-
"COMM|COMR|" +
-
"ENCR|EQUA|ETCO|" +
-
"GEOB|GRID|" +
-
"IPLS|" +
-
"LINK|" +
-
"MCDI|MLLT|" +
-
"OWNE|" +
-
"PRIV|PCNT|POPM|POSS|" +
-
"RBUF|RVAD|RVRB|" +
-
"SYLT|SYTC|" +
-
"T*" +
-
"UFID|USER|USLT|" +
-
"W*/", "ig");
-
-
private function parseFrames():void {
-
var id:String = "";
-
var size:uint = 0;
-
if(fs.position <length) {
-
try {
-
id = fs.readUTFBytes(frameIdSize);
-
size = fs.readUnsignedInt();
-
if (version>= 3) {
-
fs.readByte();
-
fs.readByte();
-
}
-
if(id.match(regEx)) {
-
var obj:Object = new Object();
-
obj.encoding = fs.readByte();
-
obj.text = fs.readUTFBytes(size - 1);
-
frames[id] = obj;
-
}
-
parseFrames();
-
}catch(e:Error) {}
-
}
-
}
-
-
/**
-
* Get value from a ID3 frame.
-
* @param frameType
-
* @return
-
*
-
*/
-
public function getFrameType(frameType:String):Object {
-
return frames[frameType];
-
}
-
private var ID3Frames:Object = {GENRE:”TCON”,ALBUM:”TALB”,ARTIST:”TPE1″,COMMENT:”COMM”,TITLE:”TIT2″,TRACK_NUMBER:”TRCK”,LYRICIST:”TOLY”,YEAR:”TYER”};
-
/**
-
* Returns ID3Info.
-
* @return
-
*
-
*/
-
public function get ID3Info():Object {
-
if(frames) {
-
var genreType:String = "";
-
if(frames[ID3Frames.GENRE]) {
-
try {
-
genreType = frames[ID3Frames.GENRE].text;
-
if(genreType.indexOf("(") != -1) {
-
genreType = genreType.substr(1, genreType.indexOf(")") - 1);
-
genreType = genres[Number(genreType)];
-
}
-
}catch(e:Error) {
-
genreType = "";
-
}
-
}
-
return {
-
album:frames[ID3Frames.ALBUM] ? frames[ID3Frames.ALBUM].text : "",
-
artist:frames[ID3Frames.ARTIST] ? frames[ID3Frames.ARTIST].text : "",
-
comment:frames[ID3Frames.COMMENT] ? frames[ID3Frames.COMMENT].text : "",
-
genre:genreType,
-
title:frames[ID3Frames.TITLE] ? frames[ID3Frames.TITLE].text : "",
-
track:frames[ID3Frames.TRACK_NUMBER] ? frames[ID3Frames.TRACK_NUMBER].text : "",
-
lyrics:frames[ID3Frames.LYRICIST] ? frames[ID3Frames.LYRICIST].text : "",
-
year:frames[ID3Frames.YEAR] ? frames[ID3Frames.YEAR].text : ""
-
};
-
}
-
return new Object();
-
}
-
-
private function convertSynchsafe(value:uint):uint {
-
return (value & 127) + 128 * ((value>> 8) & 127) + 16384 * ((value>>16) & 127) + 2097152 * ((value>> 24) & 127);
-
}
-
-
private var _file:File;
-
public function set file(f:File):void {
-
_file = f;
-
getID3Profile();
-
}
-
-
public function get file():File {
-
return _file;
-
}
-
}
-
}
ID3 Parser Event
Actionscript:
-
package libs.ashier.id3 {
-
-
import flash.events.Event;
-
-
public class ID3ParserEvent extends Event {
-
-
public static const ERROR:String = "error";
-
public static const ID3:String = "id3";
-
-
public function ID3ParserEvent(type:String, value:Object = null) {
-
super(type);
-
this.data = value;
-
}
-
-
public var data:Object;
-
override public function clone():Event {
-
return new ID3ParserEvent(type, data);
-
}
-
-
}
-
}
Usage:
Actionscript:
-
private var file:File = new File();
-
private function initialize():void {
-
file.browseForDirectory("Browse...");
-
file.addEventListener(Event.SELECT, onDirectory);
-
}
-
-
private function onDirectory(event:Event):void {
-
var files:Array = File(event.target).getDirectoryListing();
-
for( var i:Number = 0; i <files.length; i++ ){
-
var file:File = File(files[i]);
-
var prof:ID3Parser = new ID3Parser();
-
prof.addEventListener(ID3ParserEvent.ID3, onID3);
-
prof.file = file;
-
}
-
}
-
private function onID3(event:ID3ParserEvent):void {
-
//event.data
-
}
This is written for an AIR application.


May 5th, 2008 at 9:09 pm
on the ID3Parser I get:
Access of undefined property ID3Frames.
you also have your package twice in ID3Parser.
May 5th, 2008 at 10:23 pm
No worries, got it working.
For anyone else just add this to ID3Parser:
private var ID3Frames:Object = {GENRE:”TCON”,ALBUM:”TALB”,ARTIST:”TPE1″,COMMENT:”COMM”,TITLE:”TIT2″,TRACK_NUMBER:”TRCK”,LYRICIST:”TOLY”,YEAR:”TYER”};
you might also want to change the constructor name in ID3Parser
May 6th, 2008 at 9:21 am
ooops… nice find. Thanks
May 29th, 2008 at 10:15 pm
Great Help, Thanks.
October 19th, 2008 at 1:10 am
Why would you use this over the sound method?
var s:Sound = new Sound();
s.addEventListener(Event.ID3, onID3InfoReceived);
var url:URLRequest = new URLRequest(file.url);
s.load(url);
private function onID3InfoReceived(event:Event):void {
var id3:ID3Info = event.target.id3;
}