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

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

            //MP+ Header string
            byte[] b = new byte[4];
            raf.Read(b, 0, b.Length);
            string mpc = new string(System.Text.Encoding.ASCII.GetChars(b));
            if (mpc != "MAC ") {
                throw new CannotReadException("'MAC ' Header not found");
            }

            b = new byte[4];
            raf.Read(b, 0, b.Length);
            int version = Utils.GetNumber(b, 0,3);
            if(version < 3970)
                throw new CannotReadException("Monkey Audio version <= 3.97 is not supported");

            b = new byte[44];
            raf.Read(b, 0, b.Length);
            MonkeyDescriptor md = new MonkeyDescriptor(b);

            b = new byte[24];
            raf.Read(b, 0, b.Length);
            MonkeyHeader mh = new MonkeyHeader(b);

            raf.Seek(md.RiffWavOffset, SeekOrigin.Begin);
            b = new byte[12];
            raf.Read(b, 0, b.Length);
            WavRIFFHeader wrh = new WavRIFFHeader(b);
            if(!wrh.Valid)
                throw new CannotReadException("No valid RIFF Header found");

            b = new byte[24];
            raf.Read(b, 0, b.Length);
            WavFormatHeader wfh = new WavFormatHeader(b);
            if(!wfh.Valid)
                throw new CannotReadException("No valid WAV Header found");

            info.Length = mh.Length;
            info.ChannelNumber = wfh.ChannelNumber ;
            info.SamplingRate = wfh.SamplingRate ;
            info.Bitrate = ComputeBitrate(info.Length, raf.Length) ;
            info.EncodingType = "Monkey Audio v" + (((double)version)/1000)+", compression level "+mh.CompressionLevel;
            info.ExtraEncodingInfos = "";

            return info;
        }
Beispiel #2
0
        /*
        * TODO: Better Implementation of bitrate determination.
        * Somehow first audio stream makes the day. Then Streamnumber must
        * be stored, to read the right info out of an optional stream bitrate properties
        * chunk. Or if that comes first, store all the data and assign it on occurence of the
        * fist audio stream.
        * Where is the info about VBR
        */
        public EncodingInfo Read(Stream stream) 
        {
            EncodingInfo result = new EncodingInfo();
            GUID header_guid = GUID.ReadGUID(stream);
            
            if(!GUID.GUID_HEADER.Equals(header_guid)) {
                return result;
            }
            
            BinaryReader reader = new BinaryReader(stream);
                
            // Skip length of header
            stream.Seek(8, SeekOrigin.Current);

            // Read the number of chunks.
            uint chunk_count = reader.ReadUInt32();
           
            // Skip unknown bytes
            stream.Seek (2, SeekOrigin.Current);
            
            // Two flags, When both are set, all Information needed has ben read
            bool is_file_header_parsed = false;
            bool is_stream_chunk_parsed = false;

           // Now read the chunks
           for(int i = 0; i < chunk_count && !(is_file_header_parsed && is_stream_chunk_parsed); i++) {
               long chunk_start = stream.Position;
               GUID current_guid = GUID.ReadGUID(stream);
               ulong chunk_len = reader.ReadUInt64();
               
               if(GUID.GUID_FILE.Equals(current_guid)) {
                   stream.Seek(48, SeekOrigin.Current);
                   result.Duration = new TimeSpan((long)reader.ReadUInt64());
                   is_file_header_parsed = true;
               } else if(GUID.GUID_STREAM.Equals(current_guid)) {
                   GUID streamTypeGUID = GUID.ReadGUID(stream);
                   if(GUID.GUID_AUDIOSTREAM.Equals(streamTypeGUID)) {
                       // Jump over ignored values.
                       stream.Seek(38, SeekOrigin.Current);
                       result.EncodingType = GetFormatDescription(reader.ReadUInt16());
                       result.ChannelNumber = reader.ReadUInt16();
                       result.SamplingRate = (int)reader.ReadUInt32();
                       result.Bitrate = (int)(reader.ReadUInt32() * 8 / 1000);
                       is_stream_chunk_parsed = true;
                   }
               }
               
               stream.Seek((long)((ulong)chunk_start + chunk_len - (ulong)stream.Position), SeekOrigin.Current);
           }
           
           return result;
        }
Beispiel #3
0
		public EncodingInfo Read( Stream raf ) {
			EncodingInfo info = new EncodingInfo();
			
			//Begin info fetch-------------------------------------------
			if ( raf.Length==0 ) {
				//Empty File
				throw new CannotReadException("File is empty");
			}
			raf.Seek( 0 , SeekOrigin.Begin);
		
			
			//MP+ Header string
			byte[] b = new byte[3];
			raf.Read(b, 0, b.Length);
			string mpc = new string(System.Text.Encoding.ASCII.GetChars(b));
			if (mpc != "MP+" && mpc == "ID3") {
				//TODO Do we have to do this ??
				//we have an ID3v2 tag at the beginning
				//We quickly jump to MPC data
				raf.Seek(6, SeekOrigin.Begin);
				int tagSize = ReadSyncsafeInteger(raf);
				raf.Seek(tagSize+10, SeekOrigin.Begin);
				
				//retry to read MPC stream
				b = new byte[3];
				raf.Read(b, 0, b.Length);
				mpc = new string(System.Text.Encoding.ASCII.GetChars(b));
				if (mpc != "MP+") {
					//We could definitely not go there
					throw new CannotReadException("MP+ Header not found");
				}
			} else if (mpc != "MP+"){
				throw new CannotReadException("MP+ Header not found");
			}
			
			b = new byte[25];
			raf.Read(b, 0, b.Length);
			MpcHeader mpcH = new MpcHeader(b);
			//We only support v7 Stream format, so if it isn't v7, then returned values
			//will be bogus, and the file will be ignored
			
			double pcm = mpcH.SamplesNumber;
			info.Duration = new TimeSpan((long)(pcm * 1152 / mpcH.SamplingRate) * TimeSpan.TicksPerSecond);
			info.ChannelNumber = mpcH.ChannelNumber;
			info.SamplingRate = mpcH.SamplingRate;
			info.EncodingType = mpcH.EncodingType;
			info.ExtraEncodingInfos = mpcH.EncoderInfo;
			info.Bitrate = ComputeBitrate( info.Duration.Seconds, raf.Length );

			return info;
		}
        public EncodingInfo Read(Stream raf)
        {
            //Read the infos--------------------------------------------------------
            if (raf.Length == 0) {
                //Empty File
                throw new CannotReadException("Error: File empty");
            }
            raf.Seek(0, SeekOrigin.Begin);

            //FLAC Header string
            byte[] b = new byte[4];
            raf.Read(b, 0, b.Length);
            string flac = new string(System.Text.Encoding.ASCII.GetChars(b));
            if (flac != "fLaC") {
                throw new CannotReadException("fLaC Header not found");
            }

            MetadataBlockDataStreamInfo mbdsi = null;
            bool isLastBlock = false;
            while (!isLastBlock) {
                b = new byte[4];
                raf.Read(b, 0, b.Length);
                MetadataBlockHeader mbh = new MetadataBlockHeader(b);

                if (mbh.BlockType == (int) MetadataBlockHeader.BlockTypes.StreamInfo) {
                    b = new byte[mbh.DataLength];
                    raf.Read(b, 0, b.Length);

                    mbdsi = new MetadataBlockDataStreamInfo(b);
                    if (!mbdsi.Valid) {
                        throw new CannotReadException("FLAC StreamInfo not valid");
                    }
                    break;
                }
                raf.Seek(raf.Position + mbh.DataLength, SeekOrigin.Begin);

                isLastBlock = mbh.IsLastBlock;
                mbh = null; //Free memory
            }

            EncodingInfo info = new EncodingInfo();
            info.Length = mbdsi.Length;
            info.ChannelNumber = mbdsi.ChannelNumber;
            info.SamplingRate = mbdsi.SamplingRate;
            info.EncodingType = mbdsi.EncodingType;
            info.ExtraEncodingInfos = "";
            info.Bitrate = ComputeBitrate(mbdsi.Length, raf.Length);

            return info;
        }
 public EncodingInfo Read(Stream raf)
 {
     EncodingInfo info = new EncodingInfo();
     return info;
 }
Beispiel #6
0
		public EncodingInfo Read( Stream raf )  {
			EncodingInfo info = new EncodingInfo();
			long oldPos = 0;
			
			//Reads the file encoding infos -----------------------------------
			raf.Seek( 0 , SeekOrigin.Begin);
			double PCMSamplesNumber = -1;
			raf.Seek( raf.Length-2, SeekOrigin.Begin);
			while(raf.Position >= 4) {
				if(raf.ReadByte()==0x53) {
					raf.Seek( raf.Position - 4, SeekOrigin.Begin);
					byte[] ogg = new byte[3];
					raf.Read(ogg, 0, 3);
					if(ogg[0]==0x4F && ogg[1]==0x67 && ogg[2]==0x67) {
						raf.Seek( raf.Position - 3, SeekOrigin.Begin);
						
						oldPos = raf.Position;
						raf.Seek(raf.Position + 26, SeekOrigin.Begin);
						int _pageSegments = raf.ReadByte()&0xFF; //Unsigned
						raf.Seek( oldPos , SeekOrigin.Begin);
						
						byte[] _b = new byte[27 + _pageSegments];
						raf.Read( _b, 0, _b.Length );

						OggPageHeader _pageHeader = new OggPageHeader( _b );
						raf.Seek(0, SeekOrigin.Begin);
						PCMSamplesNumber = _pageHeader.AbsoluteGranulePosition;
						break;
					}
				}	
				raf.Seek( raf.Position - 2, SeekOrigin.Begin);
			}
			
			if(PCMSamplesNumber == -1){
				throw new CannotReadException("Error: Could not find the Ogg Setup block");
			}
			

			//Supposing 1st page = codec infos
			//			2nd page = comment+decode info
			//...Extracting 1st page
			byte[] b = new byte[4];
			
			oldPos = raf.Position;
			raf.Seek(26, SeekOrigin.Begin);
			int pageSegments = raf.ReadByte()&0xFF; //Unsigned
			raf.Seek( oldPos , SeekOrigin.Begin);

			b = new byte[27 + pageSegments];
			raf.Read( b , 0,  b .Length);

			OggPageHeader pageHeader = new OggPageHeader( b );

			byte[] vorbisData = new byte[pageHeader.PageLength];

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

			VorbisCodecHeader vorbisCodecHeader = new VorbisCodecHeader( vorbisData );

			//Populates encodingInfo----------------------------------------------------
			info.Duration = new TimeSpan((long)(PCMSamplesNumber / vorbisCodecHeader.SamplingRate) * TimeSpan.TicksPerSecond);
			info.ChannelNumber = vorbisCodecHeader.ChannelNumber;
			info.SamplingRate = vorbisCodecHeader.SamplingRate;
			info.EncodingType = vorbisCodecHeader.EncodingType;
			info.ExtraEncodingInfos = "";
			if(vorbisCodecHeader.NominalBitrate != 0
		        && vorbisCodecHeader.MaxBitrate == vorbisCodecHeader.NominalBitrate
		        && vorbisCodecHeader.MinBitrate == vorbisCodecHeader.NominalBitrate) {
			    //CBR
			    info.Bitrate = vorbisCodecHeader.NominalBitrate;
			    info.Vbr = false;
			}
			else if(vorbisCodecHeader.NominalBitrate != 0
			        && vorbisCodecHeader.MaxBitrate == 0
			        && vorbisCodecHeader.MinBitrate == 0) {
			    //Average vbr
			    info.Bitrate = vorbisCodecHeader.NominalBitrate;
			    info.Vbr = true;
			}
			else {
				info.Bitrate = ComputeBitrate( (int)info.Duration.TotalSeconds, raf.Length );
				info.Vbr = true;
			}

			return info;
		}
        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;
        }