private void ReadContentDescription(Stream stream, Tag tag) { BinaryReader reader = new BinaryReader(stream); ushort [] sizes = new ushort[5]; for(int i = 0; i < sizes.Length; i++) { sizes[i] = reader.ReadUInt16(); } string [] strings = new string[sizes.Length]; for(int i = 0; i < strings.Length; i++) { strings[i] = ReadUtf16String(reader, sizes[i]).Trim(); } if(sizes[0] > 0 && strings[0] != String.Empty) { tag.SetTitle(strings[0]); } if(sizes[1] > 0 && strings[1] != String.Empty) { tag.SetArtist(strings[1]); } if(sizes[3] > 0 && strings[3] != String.Empty) { tag.SetComment(strings[3]); } }
public Tag Read(Stream stream) { /* Assuming we are at the start of the ASF header GUID */ GUID header_guid = GUID.ReadGUID(stream); if(!GUID.GUID_HEADER.Equals(header_guid)) { return null; } Tag tag = new Tag(); 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_content_parsed = false; bool is_extended_parsed = false; // Now read the chunks for(int i = 0; i < chunk_count && !(is_content_parsed && is_extended_parsed); i++) { long chunk_start = stream.Position; GUID current_guid = GUID.ReadGUID(stream); ulong chunk_len = reader.ReadUInt64(); if(GUID.GUID_CONTENTDESCRIPTION.Equals(current_guid)) { ReadContentDescription(stream, tag); is_content_parsed = true; } else if(GUID.GUID_EXTENDED_CONTENT_DESCRIPTION.Equals(current_guid)) { ReadExtendedDescription(stream, tag); is_extended_parsed = true; } stream.Seek ((long)((ulong)chunk_start + chunk_len - (ulong)stream.Position), SeekOrigin.Current); } return tag; }
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 void Write( Tag tag, Stream raf, Stream rafTemp ) { //Clean up old datas ArrayList metadataBlockPadding = new ArrayList(1); ArrayList metadataBlocks = new ArrayList(); byte[] b = new byte[4]; raf.Read(b, 0, b.Length); if(new string(System.Text.Encoding.ASCII.GetChars(b)) != "fLaC") throw new CannotWriteException("This is not a FLAC file"); bool isLastBlock = false; while(!isLastBlock) { b = new byte[4]; raf.Read(b, 0, 4); MetadataBlockHeader mbh = new MetadataBlockHeader(b); if (mbh.BlockType == MetadataBlockHeader.BlockTypes.Padding) { raf.Seek(mbh.DataLength, SeekOrigin.Current); metadataBlockPadding.Add(mbh.DataLength+4); } else { b = new byte[mbh.DataLength]; raf.Read(b, 0, b.Length); metadataBlocks.Add(new MetadataBlockData(mbh, b)); } isLastBlock = mbh.IsLastBlock; } int availableRoom = ComputeAvailableRoom(metadataBlockPadding, metadataBlocks); int newTagSize = tc.GetTagLength(tag); int neededRoom = newTagSize + ComputeNeededRoom(metadataBlockPadding, metadataBlocks); raf.Seek(0, SeekOrigin.Begin); if(availableRoom>=neededRoom) { //OVERWRITE EXISTING TAG raf.Seek(42, SeekOrigin.Begin); foreach (MetadataBlockData data in metadataBlocks) { raf.Write(data.Header.Data, 0, data.Header.Data.Length); raf.Write(data.Bytes, 0, data.Bytes.Length); } byte[] newTagBytes = tc.Create(tag, availableRoom-neededRoom).Data; raf.Write(newTagBytes, 0, newTagBytes.Length); } else { //create new tag with padding (we remove the header and keep the audio data) b = new byte[42]; raf.Read(b, 0, b.Length); raf.Seek(availableRoom+42, SeekOrigin.Begin); rafTemp.Write(b, 0, b.Length); foreach (MetadataBlockData data in metadataBlocks) { raf.Write(data.Header.Data, 0, data.Header.Data.Length); raf.Write(data.Bytes, 0, data.Bytes.Length); } byte[] newTagBytes = tc.Create(tag, FlacTagCreator.DEFAULT_PADDING).Data; rafTemp.Write(newTagBytes, 0, newTagBytes.Length); b = new byte[65536]; int read = raf.Read(b, 0, b.Length); while (read != 0) { rafTemp.Write(b, 0, read); read = raf.Read(b, 0, b.Length); } //tempFC.transferFrom( fc, tempFC.position(), fc.size() ); } }
private void ReadExtendedDescription(Stream stream, Tag tag) { BinaryReader reader = new BinaryReader(stream); ushort field_count = reader.ReadUInt16(); for(int i = 0; i < field_count; i++) { ushort field_length = reader.ReadUInt16(); string property_name = ReadUtf16String(reader, field_length); ushort property_type = reader.ReadUInt16(); string property_value = String.Empty; switch(property_type) { case 0: property_value = ReadUtf16String(reader, reader.ReadUInt16()); break; case 1: stream.Seek(reader.ReadUInt16(), SeekOrigin.Current); break; case 2: reader.ReadUInt16(); property_value = (reader.ReadUInt32() == 1).ToString(); break; case 3: property_value = reader.ReadUInt32().ToString(); break; case 4: property_value = reader.ReadUInt64().ToString(); break; case 5: property_value = reader.ReadUInt16().ToString(); break; } switch(property_name) { case "WM/AlbumTitle": tag.SetAlbum(property_value); break; case "WM/AlbumArtist": tag.SetArtist(property_value); break; case "WM/TrackNumber": tag.SetTrack(property_value); break; case "WM/Year": tag.SetYear(property_value); break; case "WM/Genre": tag.SetGenre(property_value); break; } } }
public AudioFileContainer(EncodingInfo info, Tag tag) { this.info = info; this.tag = tag; }
public AudioFile(string s, EncodingInfo info) { this.s = s; this.info = info; this.tag = new GenericTag(); }
public AudioFile(string s, EncodingInfo info, Tag tag) { this.s = s; this.info = info; this.tag = tag; }