Recognise file type without extention

GMMorris

Well-known member
Joined
Feb 28, 2004
Messages
61
Hi,

Is there a way for me to recognise an MP3, WMA or Ogg file without it having an extention? By somekind of header perhaps?
 
GMMorris said:
Hi,

Is there a way for me to recognise an MP3, WMA or Ogg file without it having an extention? By somekind of header perhaps?

Yes, You can parse the files for headers and structures unique to the file format and use those to extract information. This is quite simple with MP3 and more difficult with ogg due to the way that the ogg spec and api is written exclusively for c usage.

I have a 10K class thatll get mp3 headers from an mp3 file if you want it.
 
Wraith : I wannnnnnnnnnnnnnnnt this class. :D Post it on the forum (no .exe or .dll ... only the .cs or .vb). I should make good use of it.
 
Provided as-is. All my own work from freely available information gathered from around the internet with the able assistance of google. Use however you like as long as you dont claim to have written it yourself.

For a simple example create a new form, add a property grid to it. Create a new MP3Properties instance bycalling the constructor with the path to an mp3 file. Set the property grids selected object to the MP3properties instance. All done.

Posted next for post length restrictions.
 
Code:
using System;

namespace MP3Format
{
	using System.IO;

	class MP3Properties
	{
		private MP3.Version l_version;
		private MP3.Layer l_layer;
		private bool l_protected;
		private int l_bitrate;
		private int l_samplefreq;
		private bool l_padding;
		private bool l_private;
		private MP3.ChannelMode l_channelmode;
		private int l_modeextension;
		private bool l_copyright;
		private bool l_original;
		private MP3.Emphasis l_emphasis;
		private bool l_valid;
		private string l_path;
		
		public MP3Properties(uint header, string path)
		{
			l_path=path;
			parseheader(header);
		}

		public MP3Properties(string path)
		{
			uint header=0;
			FileStream stream = null;

			stream = MP3.GetMP3Stream(path);
			if (stream!=null)
			{
				header = MP3.GetMP3Header(stream);
				stream.Close();
				stream=null;
			}
			if (header!=0)
			{
				l_path=path;
				parseheader(header);
			}
			
		}


		private void parseheader(uint header)
		{
			uint l_hdr = header;
			l_valid=false;			
			if (!((l_hdr&MP3.Sync)==MP3.Sync))
			{
				l_hdr=SwapBytes(l_hdr);
			}
			l_emphasis = (MP3.Emphasis)(l_hdr&0x3);
			l_hdr>>=2;
			l_original=(l_hdr&0x1)>0;
			l_hdr>>=1;
			l_copyright=(l_hdr&0x1)>0;
			l_hdr>>=1;
			l_modeextension=(int)l_hdr&0x3;
			l_hdr>>=2;
			l_channelmode = (MP3.ChannelMode)(l_hdr&0x3);
			l_hdr>>=2;
			l_private=(l_hdr&0x1)>0;
			l_hdr>>=1;
			l_padding=(l_hdr&0x1)>0;
			l_hdr>>=1;
			l_samplefreq=(int)l_hdr&0x3;
			l_hdr>>=2;
			l_bitrate=(int)l_hdr&0xF;
			l_hdr>>=4;
			l_protected=(l_hdr&0x1)>0;
			l_hdr>>=1;
			l_layer = (MP3.Layer)(l_hdr&0x3);
			l_hdr>>=2;
			l_version = (MP3.Version)(l_hdr&0x3);
			l_hdr>>=2;

			l_valid= ( 
				(l_layer!=MP3.Layer.reserved) &&  // reerved field
				(l_version!=MP3.Version.reserved) && // reserved field
				(l_emphasis!=MP3.Emphasis.reserved) && // reserved field
				(MP3.Bitrate(l_version,l_layer,l_bitrate)!=-1) &&  // bad bitrate
				(MP3.SampleFrequency(l_version,l_samplefreq)!=-1)  // reserved sample rate
				);
		}

		private uint SwapBytes(uint toswap)
		{
			uint retval = toswap;
			retval = (uint) ( ((toswap&0x000000ff)<<24) + ((toswap&0x0000ff00)<<8) +  ((toswap&0x00ff0000)>>8) + ((toswap&0xff000000)>>24));
			return retval;
		}


		public MP3.Version Version
		{
			get
			{
				if (l_valid)
					return l_version;
				else
					return MP3.Version.reserved;
			}
		}

		public MP3.Layer Layer
		{
			get
			{
				if (l_valid)
					return l_layer;
				else
					return MP3.Layer.reserved;
			}
		}
		public bool Protected
		{
			get
			{
				if (l_valid)
					return l_protected;
				else
					return false;
			}
		}
		public int Bitrate
		{
			get
			{
				if (l_valid)
					return MP3.Bitrate(l_version,l_layer,l_bitrate);
				else
					return 0;
			}
		}

		public int SampleFrequency
		{
			get
			{
				if (l_valid)
					return MP3.SampleFrequency(l_version,l_samplefreq);
				else
					return 0;
			}
		}
		public bool Padding
		{
			get
			{
				if (l_valid)
					return l_padding;
				else
					return false;
			}
		}
		public bool Private
		{
			get
			{
				if (l_valid)
					return l_private;
				else
					return false;
			}
		}
		public string ChannelMode
		{
			get
			{
				if (l_valid)
					return MP3.ChannelModeStrings[(int)l_channelmode];
				else
					return "";
			}
		}

		public string ModeExtension
		{
			get
			{
				if (l_valid)
					return MP3.ModeExtension(l_layer,l_channelmode,l_modeextension);
				else
					return "";
			}
		}
		public bool Copyright
		{
			get
			{
				if (l_valid)
					return l_copyright;
				else
					return false;
			}
		}
		public bool Original
		{
			get
			{
				if (l_valid)
					return l_original;
				else
					return false;
			}
		}
		public MP3.Emphasis Emphasis
		{
			get
			{
				if (l_valid)
					return l_emphasis;
				else
					return MP3.Emphasis.reserved;
			}
		}

		public bool Valid
		{
			get
			{
				return l_valid;
			}
		}

		public string Filename
		{
			get
			{
				return l_path;
			}
		}

		
	}


	class MP3
	{
		static MP3()
		{
		}


		public const uint Sync = 0xFFe0;
		public const byte SyncHigh = 0xFF;
		public const byte SyncLow = 0xE0;

		public enum Version : int
		{
			V25= 0x0,
			reserved = 0x1,
			V2 = 0x2,
			V1 = 0x3		
		}

		public enum Layer : int
		{
			reserved = 0x0,
			Layer_III = 0x1,
			Layer_II = 0x2,
			Layer_I = 0x3,
		}

		public enum ChannelMode : int
		{
			Stereo = 0x0,
			Joint = 0x1,
			Dual = 0x2,
			Single = 0x3
		}

		public enum Emphasis
		{
			none = 0x0,
			ms50_15 = 0x1,
			reserved = 0x2,
			CCIT = 0x3
		}


		public static string[] ChannelModeStrings =
		{
			"Stereo",
			"Joint stereo (Stereo)",
			"Dual channel (Stereo)",
			"Single channel (Mono)"
		};

		public static string[] EmphasisStrings = 
		{
			"none",
			"50/15 ms",
			"reserved",
			"CCIT J.17"
		};

		private static int[] SampleFrequency_Version1 = { 44100, 48000, 32000, -1 };
		private static int[] SampleFrequency_Version2 = { 22050, 24000, 16000, -1 };
		private static int[] SampleFrequency_Version25 = { 11025, 12000, 8000, -1 };

		private static int[] Bitrate_Version1Level1 = { 0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 488, -1 };
		private static int[] Bitrate_Version1Level2 = { 0, 32, 48, 56,  64,  80,  96, 112, 128, 160, 192, 224, 256, 320, 384, -1 };
		private static int[] Bitrate_Version1Level3 = { 0, 32, 40 ,48,  56,  64,  80,  96, 112, 128, 160, 192, 224, 256, 320, -1 };
		private static int[] Bitrate_Version2Level1 = { 0, 32, 48, 56,  64,  80,  96, 112, 128, 144, 160, 176, 192, 224, 256, -1 };
		private static int[] Bitrate_Version2Level2 = { 0,  8, 16, 24,  32,  40,  48,  56,  64,  80,  96, 112, 128, 144, 160, -1 };

		public static int Bitrate(Version version, Layer layer, int value)
		{
			int retval = -1;

			switch (version)
			{
				case Version.V1:
				switch (layer)
				{
					case Layer.Layer_I:
						retval = Bitrate_Version1Level1[value];
						break;
					case Layer.Layer_II:
						retval = Bitrate_Version1Level2[value];
						break;
					case Layer.Layer_III:
						retval = Bitrate_Version1Level3[value];
						break;
				}
					break;
				case Version.V2:
				switch (layer)
				{
					case Layer.Layer_I:
						retval = Bitrate_Version2Level1[value];
						break;
					case Layer.Layer_II:
					case Layer.Layer_III:
						retval = Bitrate_Version2Level2[value];
						break;
				}
					break;
			}
			return retval;
		}

		public static string ModeExtension(Layer layer, ChannelMode mode, int value)
		{
			string retval = "";
			if (mode == ChannelMode.Joint)
			{
				switch (layer)
				{
					case Layer.Layer_I:
					case Layer.Layer_II:
						switch (value)
						{
							case 0:
								retval = "bands 4 to 31";
								break;
							case 1:
								retval = "bands 8 to 31 ";
								break;
							case 2:
								retval = "bands 12 to 31 ";
								break;
							case 3:
								retval = "bands 16 to 31";
								break;
						}
						break;
					case Layer.Layer_III:
						retval+="MS Stereo: ";
						if (  (value & 0x2) > 0x0 )
						{
							retval +="on";
						}
						else
						{
							retval +="off";
						}
						retval +=", Intensity stereo: ";
						if (  (value & 0x1) > 0x0 )
						{
							retval +="on";
						}
						else
						{
							retval +="off";
						}
						break;
				}
			}
			return retval;
		}
		public static int SampleFrequency(Version version, int value)
		{
			int retval = 0;
			switch(version)
			{
				case Version.V1:
					retval = SampleFrequency_Version1[value];
					break;
				case Version.V2:
					retval = SampleFrequency_Version2[value];
					break;
				case Version.V25:
					retval = SampleFrequency_Version25[value];
					break;
			}
			return retval;
		}

		public static MP3Properties GetFileProperties(string path)
		{
			MP3Properties retval=null;
			FileStream stream=null;
			uint header=0;

			stream = MP3.GetMP3Stream(path);
			if (stream!=null) 
			{
				header = MP3.GetMP3Header(stream);
				stream.Close();
				stream=null;
			}
			if (header!=0) retval = new MP3Properties(header,path);

			return retval;
		}

		public static FileStream GetMP3Stream(string path)
		{
			FileStream fs=null;
			if (File.Exists(path))
			{
				
				try
				{
					fs=new FileStream(path,FileMode.Open,FileAccess.Read,FileShare.Read);
				}
				catch (FileNotFoundException)
				{
					// file doesnt exist
				}
				catch (DirectoryNotFoundException)
				{
					// the path is invalid
				}
				catch (IOException)
				{
					// cant open the file
				}
			}
			return fs;
				
		}

		public static uint GetMP3Header(FileStream fs)
		{
			uint retval=0;
			uint first=0;
			uint second=0;
			bool prevsync=false;
			bool found=false;
			byte cur=0;

			BinaryReader bin = new BinaryReader(fs);

			while (bin.BaseStream.Position<bin.BaseStream.Length)
			{
				cur = bin.ReadByte();
				if (prevsync)
				{
					if ( (cur&MP3.SyncLow)==MP3.SyncLow)
					{
						bin.BaseStream.Seek(-2,SeekOrigin.Current );
						if (first==0)
						{
							first = bin.ReadUInt32();
						}
						else
						{
							second = bin.ReadUInt32();
							if (first!=second)
							{
								first=second;
								second=0;
							}
							else
							{
								found=true;
								break;
							}

						}
						prevsync=false;
					}
				}
				else
				{
					prevsync = (cur==MP3.SyncHigh);
				}
			}
			bin.Close();
			bin=null;

			if (found) retval = second;
			return retval;
		}
	}
}
 
Thanks, Wraith, after I posted the question I found a another solution which is specific to my application, but solved my problem well, without having to check what the extension was. Thanks anyway though, its a nice class to hang on to :D
 
Back
Top