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; }
/* * 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; }
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; }
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; }