public MP3(string FileName) { Console.WriteLine(FileName); FileStream fs = new FileStream(FileName, FileMode.Open, FileAccess.Read); Valid = false; // Set the filename not including the path information strFileName = @fs.Name; char[] chrSeparators = new char[] { '\\', '/' }; string[] strSeparator = strFileName.Split(chrSeparators); int intUpper = strSeparator.GetUpperBound(0); strFileName = strSeparator[intUpper]; // Replace ' with '' for the SQL INSERT statement strFileName = strFileName.Replace("'", "''"); // Set the file size lngFileSize = fs.Length; byte[] bytHeader = new byte[4]; byte[] bytVBitRate = new byte[12]; int intPos = 0; // Keep reading 4 bytes from the header until we know for sure that in // fact it's an MP3 int nextFrame = 0; //Jeff - Location in stream to next Frame (current position + framesize) //Read if id3v1 exists id3v1 = new ID3v1Tag(fs); //Read if id3v2 exists id3v2 = new ID3v2Tag(fs); //Read if lyrics3 exists lyrics3 = new Lyrics3Tag(fs, id3v1.Exists); //Read if APEv2 exists apev2 = new APEv2Tag(fs, id3v1, lyrics3, true); //Pass up the ID3v2 tag (if it exists) if (id3v2.Exists) { if (!id3v2.FooterExists) { intPos = (int)id3v2.TagSize + 10; //+10 for header } else { intPos = (int)id3v2.TagSize + 20; //+20 for header and footer } } fs.Position = intPos; fs.Read(bytHeader, 0, 4); MPEGAudioFrame temp = new MPEGAudioFrame(bytHeader, 0); if (temp.Valid == false) { if (Encoding.ASCII.GetString(bytHeader, 0, 3) == "ID3") { //Another ID3v2 Tag? Console.WriteLine("Another ID3v2 tag was found after the initial one"); Console.WriteLine(); } else if (Encoding.ASCII.GetString(bytHeader, 0, 3) == "APE") { //APETAGEX has appeared before audio data Console.WriteLine("APEv2 Tag Found after ID3v2 tag"); Console.WriteLine(); } else { //Unknown - Somthing is here that is not supposed to be Console.WriteLine("Garbage found after ID3v2 tag"); Console.WriteLine(); } } //ID3v2 Tag was not valid, so the reported size may not be the actual size. Search backwards to try and find the first mpeg audio frame. if (!id3v2.Valid) { //Search Backwards (Max Search 16384) int intPosPrev = intPos; int maxPos = intPos - 16384; if (maxPos < 0) { maxPos = 0; } do { fs.Position = intPos; fs.Read(bytHeader, 0, 4); firstFrame = new MPEGAudioFrame(bytHeader, intPos); if (firstFrame.Valid) { nextFrame = intPos + firstFrame.FrameSize; fs.Position = nextFrame; bytHeader = new byte[4]; //Reset bytHeader array fs.Read(bytHeader, 0, 4); MPEGAudioFrame SecondHeader = new MPEGAudioFrame(bytHeader, nextFrame); if (SecondHeader.Valid) { Valid = true; break; } else { //The next frame did not appear valid - reset stream position fs.Position = intPos; } } intPos--; } while (!Valid && (fs.Position >= maxPos) && intPos >= 0); if (!Valid) { intPos = intPosPrev; } } //Search Forwards do { fs.Position = intPos; fs.Read(bytHeader, 0, 4); firstFrame = new MPEGAudioFrame(bytHeader, intPos); if (firstFrame.Valid) { nextFrame = intPos + firstFrame.FrameSize; fs.Position = nextFrame; bytHeader = new byte[4]; //Reset bytHeader array fs.Read(bytHeader, 0, 4); MPEGAudioFrame SecondHeader = new MPEGAudioFrame(bytHeader, nextFrame); if (SecondHeader.Valid) { Valid = true; break; } else { //The next frame did not appear valid - reset stream position fs.Position = intPos; } } intPos++; }while (!Valid && (fs.Position != fs.Length)); // If the current file stream position is equal to the length, // that means that we've read the entire file and it's not a valid MP3 file if (Valid && (fs.Position != fs.Length)) { intPos += 4; //Bypass the 4 byte header //The following is retrieved from XING SDK //http://www.mp3-tech.org/programmer/decoding.html if (firstFrame.getVersion() == 1.0) //MPEG Version 1 { if (firstFrame.ChannelModeIndex == 3) //Single Channel (Mono) { intPos += 17; } else { intPos += 32; } } else //MPEG Version 2.0 or 2.5 { if (firstFrame.ChannelModeIndex == 3) //Single Channel (Mono) { intPos += 9; } else { intPos += 17; } } // Check to see if the MP3 has a variable bitrate fs.Position = intPos; //fs.Read(bytVBitRate,0,12); //bVBR = LoadVBRHeader(bytVBitRate); vbrFrameInfo = new VBRHeader(fs, (long)intPos); // Find the last Audio Frame of the MP3 findLastFrame(fs); // Once the file's read in, then assign the properties of the file to the public variables intBitRate = getBitrate(); intFrequency = firstFrame.getFrequency(); strMode = firstFrame.getChannelMode(); intLength = getLengthInSeconds(); strLengthFormatted = getFormattedLength(); fs.Close(); } }
private void findLastFrame(FileStream fs) { long lngOffset = lngFileSize; if (apev2.Exists && apev2.Appended) { lngOffset -= apev2.TagSize; } if (lyrics3.Exists) { lngOffset -= lyrics3.TagSize; } if (id3v1.Exists) { lngOffset -= id3v1.TagSize; } long originalPos = lngOffset; fs.Position = lngOffset; bool forward = true; bool valid = false; long nextFrame = 0; byte[] tempHeader = new byte[4]; lngOffset = originalPos; MPEGAudioFrame FirstHeader; if (!valid) { while (!valid && (fs.Position >= 0) && (lngOffset - originalPos < 16384)) { fs.Position = lngOffset; fs.Read(tempHeader, 0, 4); FirstHeader = new MPEGAudioFrame(tempHeader, lngOffset); if (FirstHeader.Valid) { nextFrame = lngOffset + FirstHeader.FrameSize; fs.Position = nextFrame; tempHeader = new Byte[4]; //Reset tempHeader fs.Read(tempHeader, 0, 4); MPEGAudioFrame SecondHeader = new MPEGAudioFrame(tempHeader, nextFrame); if (SecondHeader.Valid) { //posFirstAudioFrame = intPos; valid = true; break; } else { lastFrame = FirstHeader; valid = true; break; } } lngOffset--; } } /*while (!valid && (fs.Position <= fs.Length)) * { * fs.Position = iPos; * fs.Read(tempHeader, 0, 4); * * Header = new MPEGAudioFrame(tempHeader); * if (Header.Valid) * { * nextFrame = iPos + Header.Size; * fs.Position = nextFrame; * fs.Read(tempHeader, 0, 4); * MPEGAudioFrame SecondHeader = new MPEGAudioFrame(tempHeader); * if (SecondHeader.Valid) * { * //posFirstAudioFrame = intPos; * valid = true; * break; * } * else * { * //The next frame did not appear valid - reset stream position * fs.Position = iPos; * } * } * * iPos++; * }*/ }