public void Write(Tag tag, Stream raf, Stream rafTemp) { //Read firstPage---------------------------------------------------- raf.Seek(26, SeekOrigin.Begin); byte[] b = new byte[4]; int pageSegments = raf.ReadByte()&0xFF; //Unsigned raf.Seek(0, SeekOrigin.Begin); b = new byte[27 + pageSegments]; raf.Read(b, 0, b.Length); OggPageHeader firstPage = new OggPageHeader(b); //------------------------------------------------------------------ raf.Seek(0, SeekOrigin.Begin); //write 1st page (unchanged)---------------------------------------- byte[] pageBytes = new byte[firstPage.PageLength + 27 + pageSegments]; raf.Read(pageBytes, 0, pageBytes.Length); rafTemp.Write(pageBytes, 0, pageBytes.Length); //rafTemp.Seek(firstPage.PageLength + raf.Position, SeekOrigin.Current); //------------------------------------------------------------------ //Read 2nd page----------------------------------------------------- long pos = raf.Position; raf.Seek(raf.Position + 26, SeekOrigin.Begin); pageSegments = raf.ReadByte()&0xFF; //Unsigned raf.Seek(pos, SeekOrigin.Begin); b = new byte[27 + pageSegments]; raf.Read(b, 0, b.Length); OggPageHeader secondPage = new OggPageHeader(b); long secondPageEndPos = raf.Position; //------------------------------------------------------------------ //Compute old comment length---------------------------------------- int oldCommentLength = 7; // [.vorbis] raf.Seek(raf.Position + 7, SeekOrigin.Begin); b = new byte[4]; raf.Read(b, 0, b.Length); int vendorstringLength = Utils.GetNumber(b, 0,3); oldCommentLength += 4 + vendorstringLength; raf.Seek(raf.Position + vendorstringLength, SeekOrigin.Begin); b = new byte[4]; raf.Read(b, 0, b.Length); int userComments = Utils.GetNumber(b, 0,3); oldCommentLength += 4; for (int i = 0; i < userComments; i++) { b = new byte[4]; raf.Read(b, 0, b.Length); int commentLength = Utils.GetNumber(b, 0,3); oldCommentLength += 4 + commentLength; raf.Seek(raf.Position + commentLength, SeekOrigin.Begin); } int isValid = raf.ReadByte(); oldCommentLength += 1; if (isValid != 1) throw new CannotWriteException("Unable to retreive old tag informations"); //------------------------------------------------------------------ //Get the new comment and create the container bytebuffer for 2nd page--- ByteBuffer newComment = tc.Convert(tag); int newCommentLength = newComment.Capacity; int newSecondPageLength = secondPage.PageLength - oldCommentLength + newCommentLength; byte[] segmentTable = CreateSegmentTable(oldCommentLength,newCommentLength,secondPage); int newSecondPageHeaderLength = 27 + segmentTable.Length; ByteBuffer secondPageBuffer = new ByteBuffer(newSecondPageLength + newSecondPageHeaderLength); //------------------------------------------------------------------ //Build the new second page header---------------------------------- //OggS capture secondPageBuffer.Put(Utils.GetBytes("OggS")); //Stream struct revision secondPageBuffer.Put((byte) 0); //header_type_flag secondPageBuffer.Put((byte) 0); //absolute granule position secondPageBuffer.Put( new byte[] { (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0 }); //stream serial number secondPageBuffer.Put(Utils.GetNumber(secondPage.SerialNumber)); //page sequence no secondPageBuffer.Put(Utils.GetNumber(secondPage.PageSequence)); //CRC (to be computed later) secondPageBuffer.Put(new byte[] {(byte) 0, (byte) 0, (byte) 0, (byte) 0 }); int crcOffset = 22; if (segmentTable.Length > 255) { throw new CannotWriteException ("In this special case we need to " + "create a new page, since we still hadn't the time for that " + "we won't write because it wouldn't create an ogg file."); } //page_segments nb. secondPageBuffer.Put((byte)segmentTable.Length); //page segment table for (int i = 0; i < segmentTable.Length; i++) secondPageBuffer.Put(segmentTable[i]); //------------------------------------------------------------------ //Add to the new second page the new comment------------------------ secondPageBuffer.Put(newComment); //------------------------------------------------------------------ //Add the remaining old second page (encoding infos, etc)----------- raf.Seek(secondPageEndPos+oldCommentLength, SeekOrigin.Begin); secondPageBuffer.Put(raf); //------------------------------------------------------------------ //Compute CRC over the new second page------------------------------ byte[] crc = OggCRCFactory.ComputeCRC(secondPageBuffer.Data); for (int i = 0; i < crc.Length; i++) { secondPageBuffer.Put(crcOffset + i, crc[i]); } //------------------------------------------------------------------ //Transfer the second page bytebuffer content----------------------- secondPageBuffer.Rewind(); rafTemp.Write(secondPageBuffer.Data, 0, secondPageBuffer.Data.Length); //------------------------------------------------------------------ //Write the rest of the original file------------------------------- byte[] buf = new byte[65536]; int read = raf.Read(buf, 0, buf.Length); while (read != 0) { rafTemp.Write(buf, 0, read); read = raf.Read(buf, 0, buf.Length); } //rafTemp.getChannel().transferFrom(raf.getChannel(), rafTemp.Position, raf.Length() - raf.Position); //------------------------------------------------------------------ }
public Tag Read( Stream raf ) { long oldPos = 0; //---------------------------------------------------------- //Check wheter we have an ogg stream--------------- raf.Seek( 0 , SeekOrigin.Begin); byte[] b = new byte[4]; raf.Read(b, 0, b.Length); string ogg = new string(System.Text.Encoding.ASCII.GetChars(b)); if( ogg != "OggS" ) throw new CannotReadException("OggS Header could not be found, not an ogg stream"); //-------------------------------------------------- //Parse the tag ------------------------------------ raf.Seek( 0 , SeekOrigin.Begin); //Supposing 1st page = codec infos // 2nd page = comment+decode info //...Extracting 2nd page //1st page to get the length 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 ); raf.Seek( raf.Position + pageHeader.PageLength , SeekOrigin.Begin); //2nd page extraction oldPos = raf.Position; raf.Seek(raf.Position + 26, SeekOrigin.Begin); pageSegments = raf.ReadByte()&0xFF; //unsigned raf.Seek(oldPos, SeekOrigin.Begin); b = new byte[27 + pageSegments]; raf.Read( b , 0, b .Length); pageHeader = new OggPageHeader( b ); b = new byte[7]; raf.Read( b , 0, b .Length); string vorbis = new string(System.Text.Encoding.ASCII.GetChars(b, 1, 6)); if(b[0] != 3 || vorbis != "vorbis") throw new CannotReadException("Cannot find comment block (no vorbis header)"); //Begin tag reading OggTag tag = oggTagReader.Read(raf); byte isValid = (byte) raf.ReadByte(); if ( isValid == 0 ) throw new CannotReadException("Error: The OGG Stream isn't valid, could not extract the tag"); return tag; }
/** * This method creates a new segment table for the second page (header). * @param oldCommentLength The lentgh of the old comment section, used to verify * the old secment table * @param newCommentLength Of this value the start of the segment table * will be created. * @param secondPage The second page from the source file. * @return new segment table. */ private byte[] CreateSegmentTable(int oldCommentLength, int newCommentLength, OggPageHeader secondPage) { int totalLenght = secondPage.PageLength; byte[] restShouldBe = CreateSegments(totalLenght-oldCommentLength,false); byte[] newStart = CreateSegments(newCommentLength,true); byte[] result = new byte[newStart.Length+restShouldBe.Length]; newStart.CopyTo(result, 0); restShouldBe.CopyTo(result, newStart.Length); return result; }
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 void Write(Tag tag, Stream raf, Stream rafTemp) { //Read firstPage---------------------------------------------------- raf.Seek(26, SeekOrigin.Begin); byte[] b = new byte[4]; int pageSegments = raf.ReadByte() & 0xFF; //Unsigned raf.Seek(0, SeekOrigin.Begin); b = new byte[27 + pageSegments]; raf.Read(b, 0, b.Length); OggPageHeader firstPage = new OggPageHeader(b); //------------------------------------------------------------------ raf.Seek(0, SeekOrigin.Begin); //write 1st page (unchanged)---------------------------------------- byte[] pageBytes = new byte[firstPage.PageLength + 27 + pageSegments]; raf.Read(pageBytes, 0, pageBytes.Length); rafTemp.Write(pageBytes, 0, pageBytes.Length); //rafTemp.Seek(firstPage.PageLength + raf.Position, SeekOrigin.Current); //------------------------------------------------------------------ //Read 2nd page----------------------------------------------------- long pos = raf.Position; raf.Seek(raf.Position + 26, SeekOrigin.Begin); pageSegments = raf.ReadByte() & 0xFF; //Unsigned raf.Seek(pos, SeekOrigin.Begin); b = new byte[27 + pageSegments]; raf.Read(b, 0, b.Length); OggPageHeader secondPage = new OggPageHeader(b); long secondPageEndPos = raf.Position; //------------------------------------------------------------------ //Compute old comment length---------------------------------------- int oldCommentLength = 7; // [.vorbis] raf.Seek(raf.Position + 7, SeekOrigin.Begin); b = new byte[4]; raf.Read(b, 0, b.Length); int vendorstringLength = Utils.GetNumber(b, 0, 3); oldCommentLength += 4 + vendorstringLength; raf.Seek(raf.Position + vendorstringLength, SeekOrigin.Begin); b = new byte[4]; raf.Read(b, 0, b.Length); int userComments = Utils.GetNumber(b, 0, 3); oldCommentLength += 4; for (int i = 0; i < userComments; i++) { b = new byte[4]; raf.Read(b, 0, b.Length); int commentLength = Utils.GetNumber(b, 0, 3); oldCommentLength += 4 + commentLength; raf.Seek(raf.Position + commentLength, SeekOrigin.Begin); } int isValid = raf.ReadByte(); oldCommentLength += 1; if (isValid != 1) { throw new CannotWriteException("Unable to retreive old tag informations"); } //------------------------------------------------------------------ //Get the new comment and create the container bytebuffer for 2nd page--- ByteBuffer newComment = tc.Convert(tag); int newCommentLength = newComment.Capacity; int newSecondPageLength = secondPage.PageLength - oldCommentLength + newCommentLength; byte[] segmentTable = CreateSegmentTable(oldCommentLength, newCommentLength, secondPage); int newSecondPageHeaderLength = 27 + segmentTable.Length; ByteBuffer secondPageBuffer = new ByteBuffer(newSecondPageLength + newSecondPageHeaderLength); //------------------------------------------------------------------ //Build the new second page header---------------------------------- //OggS capture secondPageBuffer.Put(Utils.GetBytes("OggS")); //Stream struct revision secondPageBuffer.Put((byte)0); //header_type_flag secondPageBuffer.Put((byte)0); //absolute granule position secondPageBuffer.Put( new byte[] { (byte)0, (byte)0, (byte)0, (byte)0, (byte)0, (byte)0, (byte)0, (byte)0 }); //stream serial number secondPageBuffer.Put(Utils.GetNumber(secondPage.SerialNumber)); //page sequence no secondPageBuffer.Put(Utils.GetNumber(secondPage.PageSequence)); //CRC (to be computed later) secondPageBuffer.Put(new byte[] { (byte)0, (byte)0, (byte)0, (byte)0 }); int crcOffset = 22; if (segmentTable.Length > 255) { throw new CannotWriteException("In this special case we need to " + "create a new page, since we still hadn't the time for that " + "we won't write because it wouldn't create an ogg file."); } //page_segments nb. secondPageBuffer.Put((byte)segmentTable.Length); //page segment table for (int i = 0; i < segmentTable.Length; i++) { secondPageBuffer.Put(segmentTable[i]); } //------------------------------------------------------------------ //Add to the new second page the new comment------------------------ secondPageBuffer.Put(newComment); //------------------------------------------------------------------ //Add the remaining old second page (encoding infos, etc)----------- raf.Seek(secondPageEndPos + oldCommentLength, SeekOrigin.Begin); secondPageBuffer.Put(raf); //------------------------------------------------------------------ //Compute CRC over the new second page------------------------------ byte[] crc = OggCRCFactory.ComputeCRC(secondPageBuffer.Data); for (int i = 0; i < crc.Length; i++) { secondPageBuffer.Put(crcOffset + i, crc[i]); } //------------------------------------------------------------------ //Transfer the second page bytebuffer content----------------------- secondPageBuffer.Rewind(); rafTemp.Write(secondPageBuffer.Data, 0, secondPageBuffer.Data.Length); //------------------------------------------------------------------ //Write the rest of the original file------------------------------- byte[] buf = new byte[65536]; int read = raf.Read(buf, 0, buf.Length); while (read != 0) { rafTemp.Write(buf, 0, read); read = raf.Read(buf, 0, buf.Length); } //rafTemp.getChannel().transferFrom(raf.getChannel(), rafTemp.Position, raf.Length() - raf.Position); //------------------------------------------------------------------ }
/** * This method creates a new segment table for the second page (header). * @param oldCommentLength The lentgh of the old comment section, used to verify * the old secment table * @param newCommentLength Of this value the start of the segment table * will be created. * @param secondPage The second page from the source file. * @return new segment table. */ private byte[] CreateSegmentTable(int oldCommentLength, int newCommentLength, OggPageHeader secondPage) { int totalLenght = secondPage.PageLength; byte[] restShouldBe = CreateSegments(totalLenght - oldCommentLength, false); byte[] newStart = CreateSegments(newCommentLength, true); byte[] result = new byte[newStart.Length + restShouldBe.Length]; newStart.CopyTo(result, 0); restShouldBe.CopyTo(result, newStart.Length); return(result); }
public Tag Read(Stream raf) { long oldPos = 0; //---------------------------------------------------------- //Check wheter we have an ogg stream--------------- raf.Seek(0, SeekOrigin.Begin); byte[] b = new byte[4]; raf.Read(b, 0, b.Length); string ogg = new string(System.Text.Encoding.ASCII.GetChars(b)); if (ogg != "OggS") { throw new CannotReadException("OggS Header could not be found, not an ogg stream"); } //-------------------------------------------------- //Parse the tag ------------------------------------ raf.Seek(0, SeekOrigin.Begin); //Supposing 1st page = codec infos // 2nd page = comment+decode info //...Extracting 2nd page //1st page to get the length 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); raf.Seek(raf.Position + pageHeader.PageLength, SeekOrigin.Begin); //2nd page extraction oldPos = raf.Position; raf.Seek(raf.Position + 26, SeekOrigin.Begin); pageSegments = raf.ReadByte() & 0xFF; //unsigned raf.Seek(oldPos, SeekOrigin.Begin); b = new byte[27 + pageSegments]; raf.Read(b, 0, b.Length); pageHeader = new OggPageHeader(b); b = new byte[7]; raf.Read(b, 0, b.Length); string vorbis = new string(System.Text.Encoding.ASCII.GetChars(b, 1, 6)); if (b[0] != 3 || vorbis != "vorbis") { throw new CannotReadException("Cannot find comment block (no vorbis header)"); } //Begin tag reading OggTag tag = oggTagReader.Read(raf); byte isValid = (byte)raf.ReadByte(); if (isValid == 0) { throw new CannotReadException("Error: The OGG Stream isn't valid, could not extract the tag"); } return(tag); }
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); }