Now I've tried to make a simple version of how too get the tags out of ID3v2.3.0 tags, but I think I failed.....
It's was not easy to do.... On purpose I haven't gotten into the part about flags, and extended headers (allthough its not too hard to implement now), because it would cloud the bigger picture... So without further delay, here is the code... (please mail me if it simply dosn't make any sense, I've rewritten the code a few times, so a couple of mistakes can be present, but the code works though
)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Drawing;
namespace Id3
{
class test
{
private long startPosition = 0;
private byte[] byteArray = new byte[6];
private string path;
public Bitmap bmp;
// Method to do the bute parsing so we can calculate the size of the header
private static int GetLengthOfTag(byte[] calcByteArray)
{ // now this is kind of long haired so just take it as it is
/* Basically, every 8th bit is filled with a 0 (zero) which means that the bits look like this:
0xxxxxxx 0xxxxxxx 0xxxxxxx 0xxxxxxx
which again means that a bit pattern (2 bytes) looking like this:
00100011 10110011 (35 and 179)
will look like this:
01000111 00110011 (71 and 51)
So a need for bit crunching......
* if calByteArray[3] = 25 and calcByteArray[2] = 30, then its going look like this:
* bytes[3] = 25 + (30 << 7), which is 25 + 3840 and in bits:
* bytes[3] = 11001 + (11110 << 7)
* bytes[3] = 11001 + 111100000000 and the final number is:
* bytes[3] = 111100011001 (3865)..... Now taking a closer look at this number...
* bytes[3] = 11110 (30) 0011001 (25), its pure magic, don't forget, every 8th bit is zero'ed and therefore ignored....
*/
int lenght = 0;
int[] bytes = new int[4];
bytes[3] = calcByteArray[3] + ((calcByteArray[2] * 1) << 7);
bytes[2] = ((calcByteArray[2] >> 1) * 63) + ((calcByteArray[1] * 3) << 6);
bytes[1] = ((calcByteArray[1] >> 2) * 31) + ((calcByteArray[0] * 7) << 5);
bytes[0] = ((calcByteArray[0] >> 3) * 15);
lenght = (10 + bytes[3] + (bytes[2] << 8) + (bytes[1] << 16) + (bytes[0] << 24));
return lenght;
}
public void RecurseDirectories(string myPath)
{
path = myPath;
string[] dirs = Directory.GetDirectories(myPath);
if (dirs.Length > 0)
{
foreach (string subDir in dirs)
{
RecurseDirectories(subDir);
}
}
//This point will be reached after the current directory has been checked for other directories...
string[] fileNames = Directory.GetFiles(myPath);
foreach (string fileName in fileNames)
{
using (System.IO.FileStream fs = System.IO.File.OpenRead(fileName))
{
fs.Read(byteArray, 0, 6); // read the first 6 bytes of "main" header
// Read in the first three bytes to check for ID3, if its there we have a tag, otherwise we don't
string startOfID3 = ((char)byteArray[0]).ToString() + ((char)byteArray[1]).ToString() + ((char)byteArray[2]).ToString();
if (startOfID3.Equals("ID3"))
{
int versionMajor = byteArray[3]; //The version of the IDTAG is placed at the fourth byte
int versionMinor = byteArray[4]; //Not used right now, but will be used later
Console.WriteLine("MajorVersion = {0}", versionMajor);
Console.WriteLine("MinorVersion = {0}", versionMinor);
if (versionMajor == 2)
{ // at present time, only ID3v2.3 is supported
Console.WriteLine("ID3v2.2 not supported yet");
}
int frameIdSize; //ID3v2.2 uses 3 charecters xx xx xx while ID3v2.3 uses 4 charecters xx xx xx xx
int flagSize;
frameIdSize = (versionMajor > 2) ? 4 : 3;
Console.WriteLine("frameIdSize = {0}", frameIdSize);
flagSize = (versionMajor > 2) ? 2 : 0;
Console.WriteLine("flagSize = {0}", flagSize);
// parse the header
fs.Read(byteArray, 0, 4); // read the last 4 bytes of "main" header which containes the size
// of the header (header total = 10 bytes)
int lenghtOfHeader = GetLengthOfTag(byteArray); // Going on to calculate the length of the header
byteArray = new byte[lenghtOfHeader];
fs.Read(byteArray, 0, lenghtOfHeader); /* read the main header into our byteArray*/
startPosition = fs.Position;
int currentPosition = 0;
byte[] tag = new byte[frameIdSize];
byte[] lenghtArray = new byte[frameIdSize];
byte[] stringFrameContent;
string frameID;
int lengthOfTag = 0;
// Now looping through the tags
do
{
if ((currentPosition + 10) > lenghtOfHeader)
{
Console.WriteLine("Ups!");
break;
}
frameID = "";
// Copy contents of byteArray to tag
Array.Copy(byteArray, currentPosition, tag, 0, frameIdSize);
currentPosition += frameIdSize; // keep track of position
// Copy contents of byteArray to lenghtArray
Array.Copy(byteArray, currentPosition, lenghtArray, 0, frameIdSize);
currentPosition += frameIdSize; // keep track of position
if (flagSize > 0)
{
currentPosition += 2;
}
lengthOfTag = 0;
for (int i = frameIdSize - 1; i >= 0; i--)
{
int ml = 1;
for (int j = i; j < frameIdSize - 1; j++)
{
ml *= 256;
}
lengthOfTag += lenghtArray[i] * ml;
}
stringFrameContent = new byte[lengthOfTag];
// Copy contents of byteArray to stringContent
Array.Copy(byteArray, currentPosition, stringFrameContent, 0, lengthOfTag);
currentPosition += lengthOfTag;
frameID = System.Text.Encoding.ASCII.GetString(tag);
string contentOfFrame = "";
if (frameID.Equals("TPE1"))
{
contentOfFrame = System.Text.Encoding.ASCII.GetString(stringFrameContent);
Console.WriteLine("Artist: {0}", contentOfFrame);
}
if (frameID.Equals("TIT2"))
{
contentOfFrame = System.Text.Encoding.ASCII.GetString(stringFrameContent);
Console.WriteLine("Song Title: {0}", contentOfFrame);
}
if (frameID.Equals("TALB"))
{
contentOfFrame = System.Text.Encoding.ASCII.GetString(stringFrameContent);
Console.WriteLine("Album: {0}", contentOfFrame);
}
if (frameID.Equals("TRCK"))
{
contentOfFrame = System.Text.Encoding.ASCII.GetString(stringFrameContent);
Console.WriteLine("Tracknumber: {0}", contentOfFrame);
}
if (frameID.Equals("TYER"))
{
contentOfFrame = System.Text.Encoding.ASCII.GetString(stringFrameContent);
Console.WriteLine("Year: {0}", contentOfFrame);
}
if (frameID.Equals("TCON"))
{
contentOfFrame = System.Text.Encoding.ASCII.GetString(stringFrameContent);
Console.WriteLine("Genre: {0}", contentOfFrame);
}
if (frameID.Equals("APIC"))
{
Console.WriteLine("PICTURE");
}
}
while (lengthOfTag > 0);
}
else
{
Console.WriteLine("No tags present");
}
}//end using
Console.ReadLine();
}//end foreach
}//end method RecurseDirectories
}
}
I've tried to comment the code as good as possible, but hey, I'm only human... Send me a mail if something is wrong, or not understanderble....
This code may be revisited a few times to make modifications.......
Be the first to rate this post
- Currently 0/5 Stars.
- 1
- 2
- 3
- 4
- 5