public EncodingInfo Read( Stream raf )
        {
            EncodingInfo encodingInfo = new EncodingInfo();

            //Begin info fetch-------------------------------------------
            if ( raf.Length == 0 ) {
                throw new CannotReadException("File is empty");
            }

            int id3TagSize = 0;
            raf.Seek( 0 , SeekOrigin.Begin);
            // skip id3v2 tag, because there may be long pictures inside with
            // slows reading and they can be not unsyncronized
            byte[] bbb = new byte[3];
                raf.Read(bbb, 0, 3);
                raf.Seek(0, SeekOrigin.Begin);
                string ID3 = new string(System.Text.Encoding.ASCII.GetChars(bbb));
                if (ID3 == "ID3") {
                    raf.Seek(6, SeekOrigin.Begin);
                    id3TagSize = ReadSyncsafeInteger(raf);
                    raf.Seek(id3TagSize+10, SeekOrigin.Begin);
                }

            MPEGFrame firstFrame = null;

            byte[] b = new byte[4];
            raf.Read(b, 0, b.Length);

            // search for sync mark, but also for a right bitrate, samplerate and layer(that way you can
            // read corrupted but playable files)
            while ( !( (b[0]&0xFF)==0xFF  &&  (b[1]&0xE0)==0xE0 && (b[1]&0x06)!=0  && (b[2]&0xF0)!=0xF0  && (b[2]&0x0C)!=0x0C ) && raf.Position < raf.Length-4) {
                raf.Seek( -3, SeekOrigin.Current);
                raf.Read(b, 0, b.Length);
            }

            firstFrame = new MPEGFrame( b );
            if ( firstFrame == null || !firstFrame.Valid || firstFrame.SamplingRate == 0 ) {
                //MP3File corrupted, no valid MPEG frames
                throw new CannotReadException("Error: could not synchronize to first mp3 frame");
            }

            int firstFrameLength = firstFrame.FrameLength;
            //----------------------------------------------------------------------------
            int skippedLength = 0;

            if ( firstFrame.MpegVersion == MPEGFrame.MPEG_VERSION_1 && firstFrame.ChannelMode == MPEGFrame.CHANNEL_MODE_MONO ) {
                raf.Seek( 17, SeekOrigin.Current );
                skippedLength += 17;
            }
            else if ( firstFrame.MpegVersion == MPEGFrame.MPEG_VERSION_1 ) {
                raf.Seek( 32 , SeekOrigin.Current );
                skippedLength += 32;
            }
            else if ( firstFrame.MpegVersion == MPEGFrame.MPEG_VERSION_2 && firstFrame.ChannelMode == MPEGFrame.CHANNEL_MODE_MONO ) {
                raf.Seek(9, SeekOrigin.Current );
                skippedLength += 9;
            }
            else if ( firstFrame.MpegVersion == MPEGFrame.MPEG_VERSION_2 ) {
                raf.Seek( 17, SeekOrigin.Current );
                skippedLength += 17;
            }
            int optionalFrameLength = 0;

            byte[] xingPart1 = new byte[16];

            raf.Read( xingPart1, 0, xingPart1.Length );
            raf.Seek( 100 , SeekOrigin.Current );

            byte[] xingPart2 = new byte[4];

            raf.Read( xingPart2, 0, xingPart2.Length );

            XingMPEGFrame currentXingFrame = new XingMPEGFrame( xingPart1, xingPart2 );
            //System.err.println(currentXingFrame);

            if ( !currentXingFrame.Valid )
                raf.Seek( - 120 - skippedLength - 4 , SeekOrigin.Current );  //120 Xing bytes, unused skipped bytes and 4 mpeg info bytes
            //Skipping Xing frame reading

            else {
                optionalFrameLength += 120;

                byte[] lameHeader = new byte[36];

                raf.Read( lameHeader, 0,  lameHeader.Length);

                LameMPEGFrame currentLameFrame = new LameMPEGFrame( lameHeader );

                if ( !currentLameFrame.Valid )
                    raf.Seek( - 36 , SeekOrigin.Current );
                //Skipping Lame frame reading

                else
                    optionalFrameLength += 36;
                //Lame Frame read

            }
            //----------------------------------------------------------------------------
            //----------------------------------------------------------------------------
            //Length computation
            if ( currentXingFrame.Valid )
                raf.Seek( firstFrameLength - ( skippedLength + optionalFrameLength + 4 ) , SeekOrigin.Current );

            double timePerFrame = ((double) firstFrame.SampleNumber) / firstFrame.SamplingRate;
            double lengthInSeconds;
            if ( currentXingFrame.Valid ) {
                //Preffered Method: extracts time length with the Xing Header (vbr:Xing or cbr:Info)********************

                lengthInSeconds = ( timePerFrame * currentXingFrame.FrameCount );

                encodingInfo.Vbr = currentXingFrame.IsVbr;
                int fs = currentXingFrame.FileSize;
                encodingInfo.Bitrate = (int)( ( (fs==0 ? raf.Length-id3TagSize : fs) * 8 ) / ( timePerFrame * currentXingFrame.FrameCount * 1000 ) );
            }
            else {
                //Default Method: extracts time length using the file length and assuming CBR********************
                int frameLength = firstFrame.FrameLength;
                if (frameLength==0)
                    throw new CannotReadException("Error while reading header(maybe file is corrupted, or missing first mpeg frame before xing header)");

                lengthInSeconds =  timePerFrame * ((raf.Length-id3TagSize) / frameLength);

                encodingInfo.Vbr = false;
                encodingInfo.Bitrate =  firstFrame.Bitrate ;
            }

            //Populates encodingInfo----------------------------------------------------
            encodingInfo.Length = (int) lengthInSeconds;
            encodingInfo.ChannelNumber = firstFrame.ChannelNumber;
            encodingInfo.SamplingRate = firstFrame.SamplingRate;
            encodingInfo.EncodingType = firstFrame.MpegVersionToString( firstFrame.MpegVersion ) + " || " + firstFrame.LayerToString( firstFrame.LayerVersion );
            encodingInfo.ExtraEncodingInfos = "";

            return encodingInfo;
        }
Exemple #2
0
        public EncodingInfo Read(Stream raf)
        {
            EncodingInfo encodingInfo = new EncodingInfo();

            //Begin info fetch-------------------------------------------
            if (raf.Length == 0)
            {
                throw new CannotReadException("File is empty");
            }

            int id3TagSize = 0;

            raf.Seek(0, SeekOrigin.Begin);
            // skip id3v2 tag, because there may be long pictures inside with
            // slows reading and they can be not unsyncronized
            byte[] bbb = new byte[3];
            raf.Read(bbb, 0, 3);
            raf.Seek(0, SeekOrigin.Begin);
            string ID3 = new string(System.Text.Encoding.ASCII.GetChars(bbb));

            if (ID3 == "ID3")
            {
                raf.Seek(6, SeekOrigin.Begin);
                id3TagSize = ReadSyncsafeInteger(raf);
                raf.Seek(id3TagSize + 10, SeekOrigin.Begin);
            }

            MPEGFrame firstFrame = null;

            byte[] b = new byte[4];
            raf.Read(b, 0, b.Length);

            // search for sync mark, but also for a right bitrate, samplerate and layer(that way you can
            // read corrupted but playable files)
            while (!((b[0] & 0xFF) == 0xFF && (b[1] & 0xE0) == 0xE0 && (b[1] & 0x06) != 0 && (b[2] & 0xF0) != 0xF0 && (b[2] & 0x0C) != 0x0C) && raf.Position < raf.Length - 4)
            {
                raf.Seek(-3, SeekOrigin.Current);
                raf.Read(b, 0, b.Length);
            }

            firstFrame = new MPEGFrame(b);
            if (firstFrame == null || !firstFrame.Valid || firstFrame.SamplingRate == 0)
            {
                //MP3File corrupted, no valid MPEG frames
                throw new CannotReadException("Error: could not synchronize to first mp3 frame");
            }

            int firstFrameLength = firstFrame.FrameLength;
            //----------------------------------------------------------------------------
            int skippedLength = 0;

            if (firstFrame.MpegVersion == MPEGFrame.MPEG_VERSION_1 && firstFrame.ChannelMode == MPEGFrame.CHANNEL_MODE_MONO)
            {
                raf.Seek(17, SeekOrigin.Current);
                skippedLength += 17;
            }
            else if (firstFrame.MpegVersion == MPEGFrame.MPEG_VERSION_1)
            {
                raf.Seek(32, SeekOrigin.Current);
                skippedLength += 32;
            }
            else if (firstFrame.MpegVersion == MPEGFrame.MPEG_VERSION_2 && firstFrame.ChannelMode == MPEGFrame.CHANNEL_MODE_MONO)
            {
                raf.Seek(9, SeekOrigin.Current);
                skippedLength += 9;
            }
            else if (firstFrame.MpegVersion == MPEGFrame.MPEG_VERSION_2)
            {
                raf.Seek(17, SeekOrigin.Current);
                skippedLength += 17;
            }
            int optionalFrameLength = 0;

            byte[] xingPart1 = new byte[16];

            raf.Read(xingPart1, 0, xingPart1.Length);
            raf.Seek(100, SeekOrigin.Current);

            byte[] xingPart2 = new byte[4];

            raf.Read(xingPart2, 0, xingPart2.Length);

            XingMPEGFrame currentXingFrame = new XingMPEGFrame(xingPart1, xingPart2);

            //System.err.println(currentXingFrame);

            if (!currentXingFrame.Valid)
            {
                raf.Seek(-120 - skippedLength - 4, SeekOrigin.Current);                      //120 Xing bytes, unused skipped bytes and 4 mpeg info bytes
            }
            //Skipping Xing frame reading

            else
            {
                optionalFrameLength += 120;

                byte[] lameHeader = new byte[36];

                raf.Read(lameHeader, 0, lameHeader.Length);

                LameMPEGFrame currentLameFrame = new LameMPEGFrame(lameHeader);

                if (!currentLameFrame.Valid)
                {
                    raf.Seek(-36, SeekOrigin.Current);
                }
                //Skipping Lame frame reading

                else
                {
                    optionalFrameLength += 36;
                }
                //Lame Frame read
            }
            //----------------------------------------------------------------------------
            //----------------------------------------------------------------------------
            //Length computation
            if (currentXingFrame.Valid)
            {
                raf.Seek(firstFrameLength - (skippedLength + optionalFrameLength + 4), SeekOrigin.Current);
            }

            double timePerFrame = ((double)firstFrame.SampleNumber) / firstFrame.SamplingRate;
            double lengthInSeconds;

            if (currentXingFrame.Valid)
            {
                //Preffered Method: extracts time length with the Xing Header (vbr:Xing or cbr:Info)********************

                lengthInSeconds = (timePerFrame * currentXingFrame.FrameCount);

                encodingInfo.Vbr = currentXingFrame.IsVbr;
                int fs = currentXingFrame.FileSize;
                encodingInfo.Bitrate = (int)(((fs == 0 ? raf.Length - id3TagSize : fs) * 8) / (timePerFrame * currentXingFrame.FrameCount * 1000));
            }
            else
            {
                //Default Method: extracts time length using the file length and assuming CBR********************
                int frameLength = firstFrame.FrameLength;
                if (frameLength == 0)
                {
                    throw new CannotReadException("Error while reading header(maybe file is corrupted, or missing first mpeg frame before xing header)");
                }

                lengthInSeconds = timePerFrame * ((raf.Length - id3TagSize) / frameLength);

                encodingInfo.Vbr     = false;
                encodingInfo.Bitrate = firstFrame.Bitrate;
            }

            //Populates encodingInfo----------------------------------------------------
            encodingInfo.Duration           = new TimeSpan((long)lengthInSeconds * TimeSpan.TicksPerSecond);
            encodingInfo.ChannelNumber      = firstFrame.ChannelNumber;
            encodingInfo.SamplingRate       = firstFrame.SamplingRate;
            encodingInfo.EncodingType       = firstFrame.MpegVersionToString(firstFrame.MpegVersion) + " || " + firstFrame.LayerToString(firstFrame.LayerVersion);
            encodingInfo.ExtraEncodingInfos = "";

            return(encodingInfo);
        }