コード例 #1
0
ファイル: AA.cs プロジェクト: jda808/atldotnet
        protected override bool read(BinaryReader source, ReadTagParams readTagParams)
        {
            bool result = true;

            ResetData();
            readHeader(source);
            if (toc.ContainsKey(TOC_CONTENT_TAGS))
            {
                readTags(source, toc[TOC_CONTENT_TAGS].Item1, toc[TOC_CONTENT_TAGS].Item2, readTagParams);
            }
            if (toc.ContainsKey(TOC_COVER_ART))
            {
                if (readTagParams.ReadPictures)
                {
                    readCover(source, toc[TOC_COVER_ART].Item1, PictureInfo.PIC_TYPE.Generic);
                }
                else
                {
                    addPictureToken(PictureInfo.PIC_TYPE.Generic);
                }
            }
            readChapters(source, toc[TOC_AUDIO].Item1, toc[TOC_AUDIO].Item2);

            return(result);
        }
コード例 #2
0
ファイル: InfoTag.cs プロジェクト: Enver-Yilmaz/atldotnet
        public static void FromStream(Stream source, MetaDataIO meta, ReadTagParams readTagParams, uint chunkSize)
        {
            long   position = source.Position;
            long   initialPos = position;
            string key, value;
            int    size;

            byte[] data = new byte[chunkSize];

            while (source.Position < initialPos + chunkSize - 4) // 4 being the "INFO" purpose that belongs to the chunk
            {
                // Key
                source.Read(data, 0, 4);
                key = Utils.Latin1Encoding.GetString(data, 0, 4);
                // Size
                source.Read(data, 0, 4);
                size = StreamUtils.DecodeInt32(data);
                if (size > 0)
                {
                    source.Read(data, 0, size);
                    // Manage parasite zeroes at the end of data
                    if (source.ReadByte() != 0)
                    {
                        source.Seek(-1, SeekOrigin.Current);
                    }
                    value = Utils.Latin1Encoding.GetString(data, 0, size);
                    meta.SetMetaField("info." + key, Utils.StripEndingZeroChars(value), readTagParams.ReadAllMetaFrames);
                }
            }
        }
コード例 #3
0
        public static void FromStream(Stream source, MetaDataIO meta, ReadTagParams readTagParams, UInt32 chunkSize)
        {
            var    position = source.Position;
            var    initialPos = position;
            String key, value;
            Int32  size;
            var    data = new Byte[256];

            while (source.Position < initialPos + chunkSize - 4) // 4 being the "INFO" purpose that belongs to the chunk
            {
                // Key
                source.Read(data, 0, 4);
                key = Utils.Latin1Encoding.GetString(data, 0, 4);
                // Size
                source.Read(data, 0, 4);
                size = StreamUtils.DecodeInt32(data);
                // Value
                value = StreamUtils.ReadNullTerminatedString(source, Utils.Latin1Encoding);

                if (value.Length > 0)
                {
                    meta.SetMetaField("info." + key, value, readTagParams.ReadAllMetaFrames);
                }

                position = source.Position;
            }
        }
コード例 #4
0
ファイル: VorbisTag.cs プロジェクト: skolmer/atldotnet
        public void ReadPicture(Stream s, ReadTagParams readTagParams)
        {
            int  picturePosition;
            long initPosition = s.Position;
            VorbisMetaDataBlockPicture block = ReadMetadataBlockPicture(s);

            if (block.picType.Equals(PictureInfo.PIC_TYPE.Unsupported))
            {
                addPictureToken(getImplementedTagType(), (byte)block.nativePicCode);
                picturePosition = takePicturePosition(getImplementedTagType(), (byte)block.nativePicCode);
            }
            else
            {
                addPictureToken(block.picType);
                picturePosition = takePicturePosition(block.picType);
            }

            if (readTagParams.ReadPictures)
            {
                s.Seek(initPosition + block.picDataOffset, SeekOrigin.Begin);
                PictureInfo picInfo = PictureInfo.fromBinaryData(s, block.picDataLength, block.picType, getImplementedTagType(), block.nativePicCode, picturePosition);
                picInfo.Description = block.description;
                tagData.Pictures.Add(picInfo);

                if (!tagExists)
                {
                    tagExists = true;
                }
            }
        }
コード例 #5
0
ファイル: FLAC.cs プロジェクト: iaingoodhew/atldotnet
        // NB : This only works if writeVorbisTag is called _before_ writePictures, since tagData fusion is done by vorbisTag.Write
        public bool Write(BinaryReader r, BinaryWriter w, TagData tag)
        {
            // Read all the fields in the existing tag (including unsupported fields)
            ReadTagParams readTagParams = new ReadTagParams(true, true);

            readTagParams.PrepareForWriting = true;
            bool tagExists = Read(r, readTagParams);

            // Save a snapshot of the initial embedded pictures for processing purposes
            existingPictureIndex = 0;
            targetPictureIndex   = 0;
            initialPictures      = vorbisTag.EmbeddedPictures;

            // Prepare picture data with freshly read vorbisTag
            TagData dataToWrite = new TagData();

            dataToWrite.Pictures = vorbisTag.EmbeddedPictures;
            dataToWrite.IntegrateValues(tag, true, false); // Merge existing information + new tag information except additional fields which will be merged by VorbisComment

            adjustPictureZones(dataToWrite.Pictures);

            FileSurgeon surgeon = new FileSurgeon(null, null, MetaDataIOFactory.TAG_NATIVE, TO_BUILTIN);

            surgeon.RewriteZones(w, new WriteDelegate(write), zones, dataToWrite, tagExists);

            // Set the 'isLast' bit on the actual last block
            w.BaseStream.Seek(latestBlockOffset, SeekOrigin.Begin);
            w.Write((byte)(latestBlockType | FLAG_LAST_METADATA_BLOCK));

            return(true);
        }
コード例 #6
0
        public bool Read(BinaryReader source, ReadTagParams readTagParams)
        {
            bool result = false;

            BufferedBinaryReader reader = new BufferedBinaryReader(source.BaseStream);

            if (readTagParams.ReadTag && null == vorbisTag)
            {
                vorbisTag = new VorbisTag(true, true, true);
            }
            info.Reset();

            if (getInfo(reader, info, readTagParams))
            {
                if (contents.Equals(CONTENTS_VORBIS))
                {
                    channelsArrangement = getArrangementFromCode(info.VorbisParameters.ChannelMode);
                    sampleRate          = info.VorbisParameters.SampleRate;
                    bitRateNominal      = (ushort)(info.VorbisParameters.BitRateNominal / 1000); // Integer division
                }
                else if (contents.Equals(CONTENTS_OPUS))
                {
                    channelsArrangement = getArrangementFromCode(info.OpusParameters.OutputChannelCount);
                    sampleRate          = (int)info.OpusParameters.InputSampleRate;
                    // No nominal bitrate for OPUS
                }

                samples = info.Samples;

                result = true;
            }
            return(result);
        }
コード例 #7
0
        public static void FromStream(Stream source, MetaDataIO meta, ReadTagParams readTagParams, uint chunkSize)
        {
            long   position = source.Position;
            long   initialPos = position;
            string key, value;
            int    size;

            byte[] data   = new byte[chunkSize];
            long   maxPos = initialPos + chunkSize - 4; // 4 being the "INFO" purpose that belongs to the chunk

            while (source.Position < maxPos)
            {
                // Key
                source.Read(data, 0, 4);
                key = Utils.Latin1Encoding.GetString(data, 0, 4);
                // Size
                source.Read(data, 0, 4);
                size = StreamUtils.DecodeInt32(data);
                // Do _NOT_ use StreamUtils.ReadNullTerminatedString because non-textual fields may be found here (e.g. NITR)
                if (size > 0)
                {
                    source.Read(data, 0, size);
                    // Manage parasite zeroes at the end of data
                    if (source.Position < maxPos && source.ReadByte() != 0)
                    {
                        source.Seek(-1, SeekOrigin.Current);
                    }
                    value = Utils.Latin1Encoding.GetString(data, 0, size);
                    meta.SetMetaField("info." + key, Utils.StripEndingZeroChars(value), readTagParams.ReadAllMetaFrames);
                }
            }
        }
コード例 #8
0
        public static void FromStream(Stream source, MetaDataIO meta, ReadTagParams readTagParams, uint chunkSize)
        {
            IList <string> position    = new List <string>();
            bool           inList      = false;
            int            listDepth   = 0;
            int            listCounter = 1;

            position.Add("ixml");

            using (MemoryStream mem = new MemoryStream((int)chunkSize))
            {
                StreamUtils.CopyStream(source, mem, (int)chunkSize); // Isolate XML structure in a clean memory chunk
                mem.Seek(0, SeekOrigin.Begin);

                using (XmlReader reader = XmlReader.Create(mem))
                {
                    while (reader.Read())
                    {
                        switch (reader.NodeType)
                        {
                        case XmlNodeType.Element:     // Element start
                            string key = reader.Name;
                            if (inList && reader.Depth == listDepth + 1 && !key.EndsWith("COUNT", StringComparison.OrdinalIgnoreCase))
                            {
                                key = key + "[" + listCounter + "]";
                                listCounter++;
                            }
                            if (!key.Equals("BWFXML", StringComparison.OrdinalIgnoreCase))
                            {
                                position.Add(key);
                            }
                            if (!inList && reader.Name.EndsWith("LIST", StringComparison.OrdinalIgnoreCase))
                            {
                                inList      = true;
                                listDepth   = reader.Depth;
                                listCounter = 1;
                            }
                            break;

                        case XmlNodeType.Text:
                            if (reader.Value != null && reader.Value.Length > 0)
                            {
                                meta.SetMetaField(getPosition(position), reader.Value, readTagParams.ReadAllMetaFrames);
                            }
                            break;

                        case XmlNodeType.EndElement:     // Element end
                            position.RemoveAt(position.Count - 1);
                            if (inList && reader.Name.EndsWith("LIST", StringComparison.OrdinalIgnoreCase))
                            {
                                inList = false;
                            }
                            break;
                        }
                    }
                }
            }
        }
コード例 #9
0
ファイル: MetaDataIO.cs プロジェクト: iaingoodhew/atldotnet
        public bool Read(BinaryReader source, ReadTagParams readTagParams)
        {
            if (readTagParams.PrepareForWriting)
            {
                structureHelper.Clear();
            }

            return(read(source, readTagParams));
        }
コード例 #10
0
        protected override bool read(BinaryReader source, ReadTagParams readTagParams)
        {
            resetData();

            bool result = readWAV(source.BaseStream, readTagParams);

            // Process data if loaded and header valid
            if (result)
            {
                bitrate  = getBitrate();
                duration = getDuration();
            }
            return(result);
        }
コード例 #11
0
        private Boolean readTag(BinaryReader source, HeaderInfo Header, ReadTagParams readTagParams)
        {
            var    chunk = new ChunkHeader();
            String data;
            var    result   = false;
            var    first    = true;
            Int64  tagStart = -1;

            source.BaseStream.Seek(40, SeekOrigin.Begin);
            do
            {
                // Read chunk header (length : 8 bytes)
                chunk.ID   = Utils.Latin1Encoding.GetString(source.ReadBytes(4));
                chunk.Size = StreamUtils.ReverseUInt32(source.ReadUInt32());

                // Read chunk data and set tag item if chunk header valid
                if (headerEndReached(chunk))
                {
                    break;
                }

                if (first)
                {
                    tagStart = source.BaseStream.Position - 8;
                    first    = false;
                }
                tagExists = true; // If something else than mandatory info is stored, we can consider metadata is present
                data      = Encoding.UTF8.GetString(source.ReadBytes((Int32)chunk.Size)).Trim();

                SetMetaField(chunk.ID, data, readTagParams.ReadAllMetaFrames);

                result = true;
            }           while (source.BaseStream.Position < source.BaseStream.Length);

            if (readTagParams.PrepareForWriting)
            {
                // Zone goes from the first field after COMM to the last field before DSIZ
                if (-1 == tagStart)
                {
                    structureHelper.AddZone(source.BaseStream.Position - 8, 0);
                }
                else
                {
                    structureHelper.AddZone(tagStart, (Int32)(source.BaseStream.Position - tagStart - 8));
                }
                structureHelper.AddSize(12, (UInt32)Header.Size);
            }

            return(result);
        }
コード例 #12
0
ファイル: SPC.cs プロジェクト: Olivier-couvez/LecteurAudioWPF
        protected override bool read(BinaryReader source, ReadTagParams readTagParams)
        {
            bool      result = true;
            SPCHeader header = new SPCHeader();
            SPCExTags footer = new SPCExTags();

            header.Reset();
            footer.Reset();
            resetData();

            source.BaseStream.Seek(sizeInfo.ID3v2Size, SeekOrigin.Begin);

            if (!readHeader(source, ref header))
            {
                throw new InvalidDataException("Not a SPC file");
            }

            // Reads the header tag
            if (SPCHeader.TAG_IN_HEADER == header.TagInHeader)
            {
                tagExists = true;
                source.BaseStream.Seek(REGISTERS_LENGTH, SeekOrigin.Current);
                readHeaderTags(source, ref header, readTagParams);
            }

            AudioDataOffset = source.BaseStream.Position;

            // Reads extended tag
            if (source.BaseStream.Length > SPC_RAW_LENGTH)
            {
                source.BaseStream.Seek(SPC_RAW_LENGTH, SeekOrigin.Begin);
                readExtendedData(source, ref footer, readTagParams);
            }
            else
            {
                if (readTagParams.PrepareForWriting)
                {
                    structureHelper.AddZone(SPC_RAW_LENGTH, 0, ZONE_EXTENDED);
                }
            }

            AudioDataSize = sizeInfo.FileSize - header.Size - footer.Size;
            bitrate       = AudioDataSize * 8 / duration;

            return(result);
        }
コード例 #13
0
        // === PRIVATE METHODS ===

        private bool readHeader(BufferedBinaryReader source, ReadTagParams readTagParams)
        {
            string str;

            if (GYM_SIGNATURE.Equals(Utils.Latin1Encoding.GetString(source.ReadBytes(GYM_SIGNATURE.Length))))
            {
                if (readTagParams.PrepareForWriting)
                {
                    structureHelper.AddZone(source.Position, 416, CORE_SIGNATURE);
                }

                tagExists = true;

                str = Utils.StripEndingZeroChars(Encoding.UTF8.GetString(source.ReadBytes(32))).Trim();
                tagData.IntegrateValue(TagData.TAG_FIELD_TITLE, str);
                str = Utils.StripEndingZeroChars(Encoding.UTF8.GetString(source.ReadBytes(32))).Trim();
                tagData.IntegrateValue(TagData.TAG_FIELD_ALBUM, str);
                str = Utils.StripEndingZeroChars(Encoding.UTF8.GetString(source.ReadBytes(32))).Trim();
                tagData.IntegrateValue(TagData.TAG_FIELD_COPYRIGHT, str);
                str = Utils.StripEndingZeroChars(Encoding.UTF8.GetString(source.ReadBytes(32))).Trim();
                tagData.AdditionalFields.Add(new MetaFieldInfo(getImplementedTagType(), "EMULATOR", str));
                str = Utils.StripEndingZeroChars(Encoding.UTF8.GetString(source.ReadBytes(32))).Trim();
                tagData.AdditionalFields.Add(new MetaFieldInfo(getImplementedTagType(), "DUMPER", str));
                str = Utils.StripEndingZeroChars(Encoding.UTF8.GetString(source.ReadBytes(256))).Trim();
                tagData.IntegrateValue(TagData.TAG_FIELD_COMMENT, str);

                loopStart = source.ReadUInt32();
                uint packedSize = source.ReadUInt32();
                AudioDataOffset = source.Position;
                AudioDataSize   = sizeInfo.FileSize - AudioDataOffset;

                if (packedSize > 0)
                {
                    LogDelegator.GetLogDelegate()(Log.LV_WARNING, "GZIP-compressed files are not supported"); // will be as soon as I find a sample to test with
                    return(false);
                }

                return(true);
            }
            else
            {
                LogDelegator.GetLogDelegate()(Log.LV_ERROR, "Not a GYM file");
                return(false);
            }
        }
コード例 #14
0
ファイル: AA.cs プロジェクト: jda808/atldotnet
        private void readTags(BinaryReader source, long offset, long size, ReadTagParams readTagParams)
        {
            source.BaseStream.Seek(offset, SeekOrigin.Begin);
            int nbTags = StreamUtils.DecodeBEInt32(source.ReadBytes(4));

            for (int i = 0; i < nbTags; i++)
            {
                source.BaseStream.Seek(1, SeekOrigin.Current); // No idea what this byte is
                int    keyLength   = StreamUtils.DecodeBEInt32(source.ReadBytes(4));
                int    valueLength = StreamUtils.DecodeBEInt32(source.ReadBytes(4));
                string key         = Encoding.UTF8.GetString(source.ReadBytes(keyLength));
                string value       = Encoding.UTF8.GetString(source.ReadBytes(valueLength)).Trim();
                SetMetaField(key, value, readTagParams.ReadAllMetaFrames);
                if ("codec".Equals(key))
                {
                    codec = value;
                }
            }
        }
コード例 #15
0
        public void ReadPicture(Stream s, ReadTagParams readTagParams)
        {
            int  picturePosition;
            long initPosition = s.Position;
            VorbisMetaDataBlockPicture block = ReadMetadataBlockPicture(s);

            if (block.picType.Equals(PictureInfo.PIC_TYPE.Unsupported))
            {
                addPictureToken(getImplementedTagType(), (byte)block.nativePicCode);
                picturePosition = takePicturePosition(getImplementedTagType(), (byte)block.nativePicCode);
            }
            else
            {
                addPictureToken(block.picType);
                picturePosition = takePicturePosition(block.picType);
            }

            if (readTagParams.ReadPictures || readTagParams.PictureStreamHandler != null)
            {
                PictureInfo picInfo = new PictureInfo(ImageUtils.GetImageFormatFromMimeType(block.mimeType), block.picType, getImplementedTagType(), block.nativePicCode, picturePosition);
                picInfo.Description = block.description;
                picInfo.PictureData = new byte[block.picDataLength];
                s.Seek(initPosition + block.picDataOffset, SeekOrigin.Begin);
                s.Read(picInfo.PictureData, 0, block.picDataLength);

                tagData.Pictures.Add(picInfo);

                if (!tagExists)
                {
                    tagExists = true;
                }


                if (readTagParams.PictureStreamHandler != null)
                {
                    MemoryStream mem = new MemoryStream(picInfo.PictureData);
                    readTagParams.PictureStreamHandler(ref mem, picInfo.PicType, picInfo.NativeFormat, picInfo.TagType, picInfo.NativePicCode, picInfo.Position);
                    mem.Close();
                }
            }
        }
コード例 #16
0
        protected override Boolean read(BinaryReader source, ReadTagParams readTagParams)
        {
            var reader = new BufferedBinaryReader(source.BaseStream);

            // Reset and load tag data from file to variable
            ResetData();
            tagVersion = TAG_VERSION_1_0;

            var result = ReadTag(reader);

            // Process data if loaded successfuly
            if (result)
            {
                tagExists = true;
            }
            else
            {
                ResetData();
            }

            return(result);
        }
コード例 #17
0
ファイル: PSF.cs プロジェクト: Olivier-couvez/LecteurAudioWPF
        protected override bool read(BinaryReader source, ReadTagParams readTagParams)
        {
            bool      result = true;
            PSFHeader header = new PSFHeader();
            PSFTag    tag    = new PSFTag();

            header.Reset();
            tag.Reset();
            resetData();

            isValid = readHeader(source, ref header);
            if (!isValid)
            {
                throw new InvalidDataException("Not a PSF file");
            }

            AudioDataOffset = 0;

            if (source.BaseStream.Length > HEADER_LENGTH + header.CompressedProgramLength + header.ReservedAreaLength)
            {
                source.BaseStream.Seek((long)(4 + header.CompressedProgramLength + header.ReservedAreaLength), SeekOrigin.Current);

                if (!readTag(source, ref tag, readTagParams))
                {
                    throw new InvalidDataException("Not a PSF tag");
                }

                tagExists = true;
            }

            AudioDataSize = sizeInfo.FileSize - tag.size;

            version = header.VersionByte;
            bitrate = AudioDataSize * 8 / duration;

            return(result);
        }
コード例 #18
0
        // Specific implementation for OGG container (multiple pages with limited size)

        // TODO DOC
        // Simplified implementation of MetaDataIO tweaked for OGG-Vorbis specifics, i.e.
        //  - tag spans over multiple pages, each having its own header
        //  - last page may include whole or part of 3rd Vorbis header (setup header)

        public bool Write(BinaryReader r, BinaryWriter w, TagData tag)
        {
            bool result         = true;
            int  writtenPages   = 0;
            long nextPageOffset = 0;

            // Read all the fields in the existing tag (including unsupported fields)
            ReadTagParams readTagParams = new ReadTagParams(true, true);

            readTagParams.PrepareForWriting = true;
            Read(r, readTagParams);

            // Get "unpaged" virtual stream to be written, containing the vorbis tag (=comment header)
            using (MemoryStream stream = new MemoryStream((int)(info.SetupHeaderEnd - info.CommentHeaderStart)))
            {
                stream.Write(Utils.Latin1Encoding.GetBytes(VORBIS_TAG_ID), 0, VORBIS_TAG_ID.Length);
                vorbisTag.Write(stream, tag);

                long newTagSize      = stream.Position;
                int  setupHeaderSize = (int)(info.SetupHeaderEnd - info.SetupHeaderStart);

                // Append the setup header in the "unpaged" virtual stream
                r.BaseStream.Seek(info.SetupHeaderStart, SeekOrigin.Begin);
                if (1 == info.SetupHeaderSpanPages)
                {
                    StreamUtils.CopyStream(r.BaseStream, stream, setupHeaderSize);
                }
                else
                {
                    // TODO - handle case where initial setup header spans across two pages
                    LogDelegator.GetLogDelegate()(Log.LV_ERROR, "ATL does not yet handle the case where Vorbis setup header spans across two OGG pages");
                    return(false);
                }


                // Construct the entire segments table
                int  commentsHeader_nbSegments = (int)Math.Ceiling(1.0 * newTagSize / 255);
                byte commentsHeader_remainingBytesInLastSegment = (byte)(newTagSize % 255);

                int  setupHeader_nbSegments = (int)Math.Ceiling(1.0 * setupHeaderSize / 255);
                byte setupHeader_remainingBytesInLastSegment = (byte)(setupHeaderSize % 255);

                byte[] entireSegmentsTable = new byte[commentsHeader_nbSegments + setupHeader_nbSegments];
                for (int i = 0; i < commentsHeader_nbSegments - 1; i++)
                {
                    entireSegmentsTable[i] = 255;
                }
                entireSegmentsTable[commentsHeader_nbSegments - 1] = commentsHeader_remainingBytesInLastSegment;
                for (int i = commentsHeader_nbSegments; i < commentsHeader_nbSegments + setupHeader_nbSegments - 1; i++)
                {
                    entireSegmentsTable[i] = 255;
                }
                entireSegmentsTable[commentsHeader_nbSegments + setupHeader_nbSegments - 1] = setupHeader_remainingBytesInLastSegment;

                int nbPageHeaders        = (int)Math.Ceiling((commentsHeader_nbSegments + setupHeader_nbSegments) / 255.0);
                int totalPageHeadersSize = (nbPageHeaders * 27) + setupHeader_nbSegments + commentsHeader_nbSegments;


                // Resize the whole virtual stream once and for all to avoid multiple reallocations while repaging
                stream.SetLength(stream.Position + totalPageHeadersSize);


                /// Repage comments header & setup header within the virtual stream
                stream.Seek(0, SeekOrigin.Begin);

                OggHeader header = new OggHeader()
                {
                    ID               = OGG_PAGE_ID,
                    StreamVersion    = info.CommentHeader.StreamVersion,
                    TypeFlag         = 0,
                    AbsolutePosition = ulong.MaxValue,
                    Serial           = info.CommentHeader.Serial,
                    PageNumber       = 1,
                    Checksum         = 0
                };

                int  segmentsLeftToPage = commentsHeader_nbSegments + setupHeader_nbSegments;
                int  bytesLeftToPage    = (int)newTagSize + setupHeaderSize;
                int  pagedSegments      = 0;
                int  pagedBytes         = 0;
                long position;

                BinaryWriter virtualW = new BinaryWriter(stream);
                IList <KeyValuePair <long, int> > pageHeaderOffsets = new List <KeyValuePair <long, int> >();

                // Repaging
                while (segmentsLeftToPage > 0)
                {
                    header.Segments     = (byte)Math.Min(255, segmentsLeftToPage);
                    header.LacingValues = new byte[header.Segments];
                    if (segmentsLeftToPage == header.Segments)
                    {
                        header.AbsolutePosition = 0;                                        // Last header page has its absolutePosition = 0
                    }
                    Array.Copy(entireSegmentsTable, pagedSegments, header.LacingValues, 0, header.Segments);

                    position = stream.Position;
                    // Push current data to write header
                    StreamUtils.CopySameStream(stream, stream.Position, stream.Position + header.GetHeaderSize(), bytesLeftToPage);
                    stream.Seek(position, SeekOrigin.Begin);

                    pageHeaderOffsets.Add(new KeyValuePair <long, int>(position, header.GetPageLength() + header.GetHeaderSize()));

                    header.WriteToStream(virtualW);
                    stream.Seek(header.GetPageLength(), SeekOrigin.Current);

                    pagedSegments      += header.Segments;
                    segmentsLeftToPage -= header.Segments;
                    pagedBytes         += header.GetPageLength();
                    bytesLeftToPage    -= header.GetPageLength();

                    header.PageNumber++;
                    if (0 == header.TypeFlag)
                    {
                        header.TypeFlag = 1;
                    }
                }
                writtenPages = header.PageNumber - 1;


                // Generate CRC32 of created pages
                uint   crc;
                byte[] data;
                foreach (KeyValuePair <long, int> kv in pageHeaderOffsets)
                {
                    crc = 0;
                    stream.Seek(kv.Key, SeekOrigin.Begin);
                    data = new byte[kv.Value];
                    stream.Read(data, 0, kv.Value);
                    crc = OggCRC32.CalculateCRC(crc, data, (uint)kv.Value);
                    stream.Seek(kv.Key + 22, SeekOrigin.Begin); // Position of CRC within OGG header
                    virtualW.Write(crc);
                }


                /// Insert the virtual paged stream into the actual file
                long oldHeadersSize = info.SetupHeaderEnd - info.CommentHeaderStart;
                long newHeadersSize = stream.Length;

                if (newHeadersSize > oldHeadersSize) // Need to build a larger file
                {
                    StreamUtils.LengthenStream(w.BaseStream, info.CommentHeaderEnd, (uint)(newHeadersSize - oldHeadersSize));
                }
                else if (newHeadersSize < oldHeadersSize) // Need to reduce file size
                {
                    StreamUtils.ShortenStream(w.BaseStream, info.CommentHeaderEnd, (uint)(oldHeadersSize - newHeadersSize));
                }

                // Rewrite Comment and Setup headers
                w.BaseStream.Seek(info.CommentHeaderStart, SeekOrigin.Begin);
                stream.Seek(0, SeekOrigin.Begin);

                StreamUtils.CopyStream(stream, w.BaseStream);

                nextPageOffset = info.CommentHeaderStart + stream.Length;
            }

            // If the number of written pages is different than the number of previous existing pages,
            // all the next pages of the file need to be renumbered, and their CRC accordingly recalculated
            if (writtenPages != info.CommentHeaderSpanPages + info.SetupHeaderSpanPages - 1)
            {
                OggHeader header = new OggHeader();
                byte[]    data;
                uint      crc;

                do
                {
                    w.BaseStream.Seek(nextPageOffset, SeekOrigin.Begin);
                    header.ReadFromStream(r);

                    if (header.IsValid())
                    {
                        // Rewrite page number
                        writtenPages++;
                        w.BaseStream.Seek(nextPageOffset + 18, SeekOrigin.Begin);
                        w.Write(writtenPages);

                        // Rewrite CRC
                        w.BaseStream.Seek(nextPageOffset, SeekOrigin.Begin);
                        data = new byte[header.GetHeaderSize() + header.GetPageLength()];
                        r.Read(data, 0, data.Length);

                        // Checksum has to include its own location, as if it were 0
                        data[22] = 0;
                        data[23] = 0;
                        data[24] = 0;
                        data[25] = 0;

                        crc = OggCRC32.CalculateCRC(0, data, (uint)data.Length);
                        r.BaseStream.Seek(nextPageOffset + 22, SeekOrigin.Begin); // Position of CRC within OGG header
                        w.Write(crc);

                        // To the next header
                        nextPageOffset += data.Length;
                    }
                    else
                    {
                        LogDelegator.GetLogDelegate()(Log.LV_ERROR, "Invalid OGG header found; aborting writing operation"); // Throw exception ?
                        return(false);
                    }
                } while (0 == (header.TypeFlag & 0x04));  // 0x04 marks the last page of the logical bitstream
            }

            return(result);
        }
コード例 #19
0
ファイル: SPC.cs プロジェクト: Olivier-couvez/LecteurAudioWPF
        // === PUBLIC METHODS ===

        public bool Read(BinaryReader source, SizeInfo sizeInfo, ReadTagParams readTagParams)
        {
            this.sizeInfo = sizeInfo;

            return(read(source, readTagParams));
        }
コード例 #20
0
ファイル: SPC.cs プロジェクト: Olivier-couvez/LecteurAudioWPF
        private void readExtendedData(BinaryReader source, ref SPCExTags footer, ReadTagParams readTagParams)
        {
            long initialPosition = source.BaseStream.Position;

            footer.FormatTag = Utils.Latin1Encoding.GetString(source.ReadBytes(4));
            if (XTENDED_TAG == footer.FormatTag)
            {
                tagExists   = true;
                footer.Size = source.ReadUInt32();

                byte   ID, type;
                ushort size;
                string strData = "";
                int    intData = 0;
                long   ticks   = 0;

                long dataPosition = source.BaseStream.Position;
                while (source.BaseStream.Position < dataPosition + footer.Size - 4)
                {
                    ID   = source.ReadByte();
                    type = source.ReadByte();
                    size = source.ReadUInt16();

                    switch (type)
                    {
                    case XID6_TVAL:
                        // Value is stored into the Size field
                        if (ID == XID6_TRACK)     // Specific case : upper byte is the number 0-99, lower byte is an optional ASCII character
                        {
                            intData = size >> 8;
                            strData = intData.ToString();
                            byte optionalChar = (byte)(size & 0x00FF);
                            if (optionalChar > 0x20)     // Character is displayable
                            {
                                strData += (char)optionalChar;
                            }
                        }
                        else
                        {
                            intData = size;
                            strData = intData.ToString();
                        }
                        break;

                    case XID6_TSTR:
                        intData = 0;
                        strData = Utils.Latin1Encoding.GetString(source.ReadBytes(size)).Replace("\0", "").Trim();

                        while (source.BaseStream.Position < source.BaseStream.Length && 0 == source.ReadByte())
                        {
                            ;                                                                                         // Skip parasite ending zeroes
                        }
                        if (source.BaseStream.Position < source.BaseStream.Length)
                        {
                            source.BaseStream.Seek(-1, SeekOrigin.Current);
                        }
                        break;

                    case XID6_TINT:
                        intData = source.ReadInt32();
                        strData = intData.ToString();
                        break;
                    }

                    if (XID6_LOOP == ID)
                    {
                        ticks += Math.Min(XID6_MAXTICKS, intData);
                    }
                    else if (XID6_LOOPX == ID)
                    {
                        ticks = ticks * Math.Min(XID6_MAXLOOP, (int)size);
                    }
                    else if (XID6_INTRO == ID)
                    {
                        ticks += Math.Min(XID6_MAXTICKS, intData);
                    }
                    else if (XID6_END == ID)
                    {
                        ticks += Math.Min(XID6_MAXTICKS, intData);
                    }
                    else if (XID6_FADE == ID)
                    {
                        ticks += Math.Min(XID6_MAXTICKS, intData);
                    }

                    SetMetaField(ID.ToString(), strData, readTagParams.ReadAllMetaFrames, ZONE_EXTENDED);
                }

                if (ticks > 0)
                {
                    duration = Math.Round((double)ticks / XID6_TICKSSEC);
                }

                if (readTagParams.PrepareForWriting)
                {
                    structureHelper.AddZone(initialPosition, (int)(source.BaseStream.Position - initialPosition), ZONE_EXTENDED);
                }
            }
        }
コード例 #21
0
ファイル: SPC.cs プロジェクト: Olivier-couvez/LecteurAudioWPF
        private void readHeaderTags(BinaryReader source, ref SPCHeader header, ReadTagParams readTagParams)
        {
            long initialPosition = source.BaseStream.Position;

            SetMetaField(HEADER_TITLE.ToString(), Utils.Latin1Encoding.GetString(source.ReadBytes(32)).Replace("\0", "").Trim(), readTagParams.ReadAllMetaFrames, ZONE_HEADER);
            SetMetaField(HEADER_ALBUM.ToString(), Utils.Latin1Encoding.GetString(source.ReadBytes(32)).Replace("\0", "").Trim(), readTagParams.ReadAllMetaFrames, ZONE_HEADER);
            SetMetaField(HEADER_DUMPERNAME.ToString(), Utils.Latin1Encoding.GetString(source.ReadBytes(16)).Replace("\0", "").Trim(), readTagParams.ReadAllMetaFrames, ZONE_HEADER);
            SetMetaField(HEADER_COMMENT.ToString(), Utils.Latin1Encoding.GetString(source.ReadBytes(32)).Replace("\0", "").Trim(), readTagParams.ReadAllMetaFrames, ZONE_HEADER);

            byte[] date, song, fade;

            // NB : Dump date is used to determine if the tag is binary or text-based.
            // It won't be recorded as a property of TSPC
            date = source.ReadBytes(11);
            song = source.ReadBytes(3);
            fade = source.ReadBytes(5);

            bool bin;
            int  dateRes = isText(date);
            int  songRes = isText(song);
            int  fadeRes = isText(fade);

            //if ( 0 == (dateRes | songRes | fadeRes) ) // No time nor date -> use default
            //{
            bin = true;
            //}
            //else
            if ((songRes != -1) && (fadeRes != -1)) // No time, or time is text
            {
                if (dateRes > 0)                    //If date is text, then tag is text
                {
                    bin = false;
                }
                else if (0 == dateRes)              //No date
                {
                    bin = PREFER_BIN;               //Times could still be binary (ex. 56 bin = '8' txt)
                }
                else if (-1 == dateRes)             //Date contains invalid characters
                {
                    bin = true;
                    for (int i = 4; i < 8; i++)
                    {
                        bin = bin && (0 == date[i]);
                    }
                }
            }
            else
            {
                bin = true;
            }

            int fadeVal;
            int songVal;

            if (bin)
            {
                fadeVal =
                    fade[0] * 0x000001 +
                    fade[1] * 0x0000FF +
                    fade[2] * 0x00FF00 +
                    fade[3] * 0xFF0000;
                if (fadeVal > 59999)
                {
                    fadeVal = 59999;
                }

                songVal = song[0] * 0x01 + song[1] * 0x10;
                if (songVal > 959)
                {
                    songVal = 959;
                }

                source.BaseStream.Seek(-1, SeekOrigin.Current); // We're one byte ahead
                SetMetaField(HEADER_FADE.ToString(), Utils.Latin1Encoding.GetString(fade), readTagParams.ReadAllMetaFrames, ZONE_HEADER);
            }
            else
            {
                fadeVal = TrackUtils.ExtractTrackNumber(Utils.Latin1Encoding.GetString(fade));
                songVal = TrackUtils.ExtractTrackNumber(Utils.Latin1Encoding.GetString(song));

                SetMetaField(HEADER_FADE.ToString(), Utils.Latin1Encoding.GetString(fade), readTagParams.ReadAllMetaFrames, ZONE_HEADER);
            }

            SetMetaField(HEADER_DUMPDATE.ToString(), Utils.Latin1Encoding.GetString(date), readTagParams.ReadAllMetaFrames, ZONE_HEADER);
            SetMetaField(HEADER_SONGLENGTH.ToString(), Utils.Latin1Encoding.GetString(song), readTagParams.ReadAllMetaFrames, ZONE_HEADER);

            // if fadeval > 0 alone, the fade is applied on the default 3:00 duration without extending it
            if (songVal > 0)
            {
                duration = Math.Round((double)fadeVal) + songVal;
            }

            SetMetaField(HEADER_ARTIST.ToString(), Utils.Latin1Encoding.GetString(source.ReadBytes(32)).Replace("\0", "").Trim(), readTagParams.ReadAllMetaFrames, ZONE_HEADER);
            header.Size += source.BaseStream.Position - initialPosition;

            if (readTagParams.PrepareForWriting)
            {
                structureHelper.AddZone(initialPosition, (int)(source.BaseStream.Position - initialPosition), ZONE_HEADER);
            }
        }
コード例 #22
0
ファイル: FLAC.cs プロジェクト: iaingoodhew/atldotnet
        /* Unused for now
         *
         *      //   Get compression ratio
         *      private double getCompressionRatio()
         *      {
         *          if (isValid())
         *          {
         *              return (double)sizeInfo.FileSize / (samples * channels * bitsPerSample / 8.0) * 100;
         *          }
         *          else
         *          {
         *              return 0;
         *          }
         *      }
         */

        public bool Read(BinaryReader source, AudioDataManager.SizeInfo sizeInfo, ReadTagParams readTagParams)
        {
            this.sizeInfo = sizeInfo;

            return(Read(source, readTagParams));
        }
コード例 #23
0
ファイル: FLAC.cs プロジェクト: iaingoodhew/atldotnet
        // TODO : support for CUESHEET block
        public bool Read(BinaryReader source, ReadTagParams readTagParams)
        {
            bool result = false;

            if (readTagParams.ReadTag && null == vorbisTag)
            {
                vorbisTag = new VorbisTag(false, false, false, false);
            }

            initialPaddingOffset = -1;
            initialPaddingSize   = 0;

            byte[] aMetaDataBlockHeader;
            long   position;
            uint   blockLength;
            byte   blockType;
            int    blockIndex;
            bool   isLast;
            bool   paddingFound   = false;
            long   blockEndOffset = -1;

            readHeader(source);

            // Process data if loaded and header valid
            if (header.IsValid())
            {
                int channels = (header.Info[12] >> 1) & 0x7;
                switch (channels)
                {
                case 0b0000: channelsArrangement = MONO; break;

                case 0b0001: channelsArrangement = STEREO; break;

                case 0b0010: channelsArrangement = ISO_3_0_0; break;

                case 0b0011: channelsArrangement = QUAD; break;

                case 0b0100: channelsArrangement = ISO_3_2_0; break;

                case 0b0101: channelsArrangement = ISO_3_2_1; break;

                case 0b0110: channelsArrangement = LRCLFECrLssRss; break;

                case 0b0111: channelsArrangement = LRCLFELrRrLssRss; break;

                case 0b1000: channelsArrangement = JOINT_STEREO_LEFT_SIDE; break;

                case 0b1001: channelsArrangement = JOINT_STEREO_RIGHT_SIDE; break;

                case 0b1010: channelsArrangement = JOINT_STEREO_MID_SIDE; break;

                default: channelsArrangement = UNKNOWN; break;
                }

                sampleRate    = header.Info[10] << 12 | header.Info[11] << 4 | header.Info[12] >> 4;
                bitsPerSample = (byte)(((header.Info[12] & 1) << 4) | (header.Info[13] >> 4) + 1);
                samples       = header.Info[14] << 24 | header.Info[15] << 16 | header.Info[16] << 8 | header.Info[17];

                if (0 == (header.MetaDataBlockHeader[1] & FLAG_LAST_METADATA_BLOCK)) // metadata block exists
                {
                    blockIndex = 0;
                    vorbisTag.Clear();
                    if (readTagParams.PrepareForWriting)
                    {
                        if (null == zones)
                        {
                            zones = new List <Zone>();
                        }
                        else
                        {
                            zones.Clear();
                        }
                        blockEndOffset = source.BaseStream.Position;
                    }

                    do // Read all metadata blocks
                    {
                        aMetaDataBlockHeader = source.ReadBytes(4);
                        isLast = (aMetaDataBlockHeader[0] & FLAG_LAST_METADATA_BLOCK) > 0; // last flag ( first bit == 1 )

                        blockIndex++;
                        blockLength = StreamUtils.DecodeBEUInt24(aMetaDataBlockHeader, 1);

                        blockType = (byte)(aMetaDataBlockHeader[0] & 0x7F); // decode metablock type
                        position  = source.BaseStream.Position;

                        if (blockType == META_VORBIS_COMMENT) // Vorbis metadata
                        {
                            if (readTagParams.PrepareForWriting)
                            {
                                zones.Add(new Zone(blockType + "", position - 4, (int)blockLength + 4, new byte[0], blockType));
                            }
                            vorbisTag.Read(source, readTagParams);
                        }
                        else if ((blockType == META_PADDING) && (!paddingFound))  // Padding block (skip any other padding block)
                        {
                            if (readTagParams.PrepareForWriting)
                            {
                                zones.Add(new Zone(PADDING_ZONE_NAME, position - 4, (int)blockLength + 4, new byte[0], blockType));
                            }
                            initialPaddingSize   = blockLength;
                            initialPaddingOffset = position;
                            paddingFound         = true;
                            source.BaseStream.Seek(blockLength, SeekOrigin.Current);
                        }
                        else if (blockType == META_PICTURE) // Picture (NB: as per FLAC specs, pictures must be embedded at the FLAC level, not in the VorbisComment !)
                        {
                            if (readTagParams.PrepareForWriting)
                            {
                                zones.Add(new Zone(blockType + "", position - 4, (int)blockLength + 4, new byte[0], blockType));
                            }
                            vorbisTag.ReadPicture(source.BaseStream, readTagParams);
                        }
                        else // Unhandled block; needs to be zoned anyway to be able to manage the 'isLast' flag at write-time
                        {
                            if (readTagParams.PrepareForWriting)
                            {
                                zones.Add(new Zone(blockType + "", position - 4, (int)blockLength + 4, new byte[0], blockType));
                            }
                        }


                        if (blockType < 7)
                        {
                            source.BaseStream.Seek(position + blockLength, SeekOrigin.Begin);
                            blockEndOffset = position + blockLength;
                        }
                        else
                        {
                            // Abnormal header : incorrect size and/or misplaced last-metadata-block flag
                            break;
                        }
                    }while (!isLast);

                    if (readTagParams.PrepareForWriting)
                    {
                        bool vorbisTagFound = false;
                        bool pictureFound   = false;

                        foreach (Zone zone in zones)
                        {
                            if (zone.Flag == META_PICTURE)
                            {
                                pictureFound = true;
                            }
                            else if (zone.Flag == META_VORBIS_COMMENT)
                            {
                                vorbisTagFound = true;
                            }
                        }

                        if (!vorbisTagFound)
                        {
                            zones.Add(new Zone(META_VORBIS_COMMENT + "", blockEndOffset, 0, new byte[0], META_VORBIS_COMMENT));
                        }
                        if (!pictureFound)
                        {
                            zones.Add(new Zone(META_PICTURE + "", blockEndOffset, 0, new byte[0], META_PICTURE));
                        }
                        // Padding must be the last block for it to correctly absorb size variations of the other blocks
                        if (!paddingFound && Settings.AddNewPadding)
                        {
                            zones.Add(new Zone(PADDING_ZONE_NAME, blockEndOffset, 0, new byte[0], META_PADDING));
                        }
                    }
                }
            }

            if (isValid())
            {
                audioOffset = source.BaseStream.Position;  // we need that to calculate the bitrate
                result      = true;
            }

            return(result);
        }
コード例 #24
0
        // ---------- SUPPORT METHODS

        private bool readWAV(Stream source, ReadTagParams readTagParams)
        {
            bool result = true;
            uint riffChunkSize;
            long riffChunkSizePos;

            byte[] data = new byte[4];

            source.Seek(0, SeekOrigin.Begin);

            // Read header
            source.Read(data, 0, 4);
            string str = Utils.Latin1Encoding.GetString(data);

            if (str.Equals(HEADER_RIFF))
            {
                _isLittleEndian = true;
            }
            else if (str.Equals(HEADER_RIFX))
            {
                _isLittleEndian = false;
            }
            else
            {
                return(false);
            }

            // Force creation of FileStructureHelper with detected endianness
            structureHelper      = new FileStructureHelper(isLittleEndian);
            id3v2StructureHelper = new FileStructureHelper(isLittleEndian);

            riffChunkSizePos = source.Position;
            source.Read(data, 0, 4);
            if (isLittleEndian)
            {
                riffChunkSize = StreamUtils.DecodeUInt32(data);
            }
            else
            {
                riffChunkSize = StreamUtils.DecodeBEUInt32(data);
            }

            // Format code
            source.Read(data, 0, 4);
            str = Utils.Latin1Encoding.GetString(data);
            if (!str.Equals(FORMAT_WAVE))
            {
                return(false);
            }


            string subChunkId;
            uint   chunkSize;
            long   chunkDataPos;
            bool   foundSample = false;
            bool   foundBext   = false;
            bool   foundInfo   = false;
            bool   foundIXml   = false;

            // Sub-chunks loop
            while (source.Position < riffChunkSize + 8)
            {
                // Chunk ID
                source.Read(data, 0, 4);
                if (0 == data[0]) // Sometimes data segment ends with a parasite null byte
                {
                    source.Seek(-3, SeekOrigin.Current);
                    source.Read(data, 0, 4);
                }

                subChunkId = Utils.Latin1Encoding.GetString(data);

                // Chunk size
                source.Read(data, 0, 4);
                if (isLittleEndian)
                {
                    chunkSize = StreamUtils.DecodeUInt32(data);
                }
                else
                {
                    chunkSize = StreamUtils.DecodeBEUInt32(data);
                }

                chunkDataPos = source.Position;

                if (subChunkId.Equals(CHUNK_FORMAT))
                {
                    source.Read(data, 0, 2);
                    if (isLittleEndian)
                    {
                        formatId = StreamUtils.DecodeUInt16(data);
                    }
                    else
                    {
                        formatId = StreamUtils.DecodeBEUInt16(data);
                    }

                    source.Read(data, 0, 2);
                    if (isLittleEndian)
                    {
                        channelsArrangement = ChannelsArrangements.GuessFromChannelNumber(StreamUtils.DecodeUInt16(data));
                    }
                    else
                    {
                        channelsArrangement = ChannelsArrangements.GuessFromChannelNumber(StreamUtils.DecodeBEUInt16(data));
                    }

                    source.Read(data, 0, 4);
                    if (isLittleEndian)
                    {
                        sampleRate = StreamUtils.DecodeUInt32(data);
                    }
                    else
                    {
                        sampleRate = StreamUtils.DecodeBEUInt32(data);
                    }

                    source.Read(data, 0, 4);
                    if (isLittleEndian)
                    {
                        bytesPerSecond = StreamUtils.DecodeUInt32(data);
                    }
                    else
                    {
                        bytesPerSecond = StreamUtils.DecodeBEUInt32(data);
                    }

                    source.Seek(2, SeekOrigin.Current); // BlockAlign

                    source.Read(data, 0, 2);
                    if (isLittleEndian)
                    {
                        bitsPerSample = StreamUtils.DecodeUInt16(data);
                    }
                    else
                    {
                        bitsPerSample = StreamUtils.DecodeBEUInt16(data);
                    }
                }
                else if (subChunkId.Equals(CHUNK_DATA))
                {
                    headerSize = riffChunkSize - chunkSize;
                }
                else if (subChunkId.Equals(CHUNK_FACT))
                {
                    source.Read(data, 0, 4);
                    if (isLittleEndian)
                    {
                        sampleNumber = StreamUtils.DecodeInt32(data);
                    }
                    else
                    {
                        sampleNumber = StreamUtils.DecodeBEInt32(data);
                    }
                }
                else if (subChunkId.Equals(CHUNK_SAMPLE))
                {
                    structureHelper.AddZone(source.Position - 8, (int)(chunkSize + 8), subChunkId);
                    structureHelper.AddSize(riffChunkSizePos, riffChunkSize, subChunkId);

                    foundSample = true;
                    tagExists   = true;

                    SampleTag.FromStream(source, this, readTagParams);
                }
                else if (subChunkId.Equals(CHUNK_BEXT))
                {
                    structureHelper.AddZone(source.Position - 8, (int)(chunkSize + 8), subChunkId);
                    structureHelper.AddSize(riffChunkSizePos, riffChunkSize, subChunkId);

                    foundBext = true;
                    tagExists = true;

                    BextTag.FromStream(source, this, readTagParams);
                }
                else if (subChunkId.Equals(CHUNK_INFO))
                {
                    // Purpose of the list should be INFO
                    source.Read(data, 0, 4);
                    string purpose = Utils.Latin1Encoding.GetString(data, 0, 4);
                    if (purpose.Equals(InfoTag.PURPOSE_INFO))
                    {
                        structureHelper.AddZone(source.Position - 12, (int)(chunkSize + 8), subChunkId);
                        structureHelper.AddSize(riffChunkSizePos, riffChunkSize, subChunkId);

                        foundInfo = true;
                        tagExists = true;

                        InfoTag.FromStream(source, this, readTagParams, chunkSize);
                    }
                }
                else if (subChunkId.Equals(CHUNK_IXML))
                {
                    structureHelper.AddZone(source.Position - 8, (int)(chunkSize + 8), subChunkId);
                    structureHelper.AddSize(riffChunkSizePos, riffChunkSize, subChunkId);

                    foundIXml = true;
                    tagExists = true;

                    IXmlTag.FromStream(source, this, readTagParams, chunkSize);
                }
                else if (subChunkId.Equals(CHUNK_ID3))
                {
                    id3v2Offset = source.Position;

                    // Zone is already added by Id3v2.Read
                    id3v2StructureHelper.AddZone(id3v2Offset - 8, (int)(chunkSize + 8), subChunkId);
                    id3v2StructureHelper.AddSize(riffChunkSizePos, riffChunkSize, subChunkId);
                }

                source.Seek(chunkDataPos + chunkSize, SeekOrigin.Begin);
            }

            // Add zone placeholders for future tag writing
            if (readTagParams.PrepareForWriting)
            {
                if (!foundSample)
                {
                    structureHelper.AddZone(source.Position, 0, CHUNK_SAMPLE);
                    structureHelper.AddSize(riffChunkSizePos, riffChunkSize, CHUNK_SAMPLE);
                }
                if (!foundBext)
                {
                    structureHelper.AddZone(source.Position, 0, CHUNK_BEXT);
                    structureHelper.AddSize(riffChunkSizePos, riffChunkSize, CHUNK_BEXT);
                }
                if (!foundInfo)
                {
                    structureHelper.AddZone(source.Position, 0, CHUNK_INFO);
                    structureHelper.AddSize(riffChunkSizePos, riffChunkSize, CHUNK_INFO);
                }
                if (!foundIXml)
                {
                    structureHelper.AddZone(source.Position, 0, CHUNK_IXML);
                    structureHelper.AddSize(riffChunkSizePos, riffChunkSize, CHUNK_IXML);
                }
            }

            // ID3 zone should be set as the very last one for Windows to be able to read the LIST INFO zone properly
            if (-1 == id3v2Offset)
            {
                id3v2Offset = 0; // Switch status to "tried to read, but nothing found"

                if (readTagParams.PrepareForWriting)
                {
                    id3v2StructureHelper.AddZone(source.Position, 0, CHUNK_ID3);
                    id3v2StructureHelper.AddSize(riffChunkSizePos, riffChunkSize, CHUNK_ID3);
                }
            }

            return(result);
        }
コード例 #25
0
ファイル: VGM.cs プロジェクト: skolmer/atldotnet
        // === PRIVATE METHODS ===

        private bool readHeader(BinaryReader source, ReadTagParams readTagParams)
        {
            int nbSamples, loopNbSamples;
            int nbLoops       = LOOP_COUNT_DEFAULT;
            int recordingRate = RECORDING_RATE_DEFAULT;

            byte[] headerSignature = source.ReadBytes(VGM_SIGNATURE.Length);
            if (VGM_SIGNATURE.Equals(Utils.Latin1Encoding.GetString(headerSignature)))
            {
                source.BaseStream.Seek(4, SeekOrigin.Current); // EOF offset
                version = source.ReadInt32();
                source.BaseStream.Seek(8, SeekOrigin.Current); // Clocks
                gd3TagOffset = source.ReadInt32() + (int)source.BaseStream.Position - 4;

                if (/*gd3TagOffset > 0 && */ readTagParams.PrepareForWriting)
                {
                    if (gd3TagOffset > VGM_HEADER_SIZE)
                    {
                        structureHelper.AddZone(gd3TagOffset, (int)sizeInfo.FileSize - gd3TagOffset);
                        structureHelper.AddIndex(source.BaseStream.Position - 4, gd3TagOffset, true);
                    }
                    else
                    {
                        structureHelper.AddZone(sizeInfo.FileSize, 0);
                        structureHelper.AddIndex(source.BaseStream.Position - 4, (int)sizeInfo.FileSize, true);
                    }
                }

                nbSamples = source.ReadInt32();

                source.BaseStream.Seek(4, SeekOrigin.Current); // Loop offset

                loopNbSamples = source.ReadInt32();
                if (version >= 0x00000101)
                {
                    recordingRate = source.ReadInt32();
                }
                if (version >= 0x00000160)
                {
                    source.BaseStream.Seek(0x7E, SeekOrigin.Begin);
                    nbLoops -= source.ReadSByte();                  // Loop base
                }
                if (version >= 0x00000151)
                {
                    source.BaseStream.Seek(0x7F, SeekOrigin.Begin);
                    nbLoops = nbLoops * source.ReadByte();          // Loop modifier
                }

                duration = (nbSamples * 1000.0 / sampleRate) + (nbLoops * (loopNbSamples * 1000.0 / sampleRate));
                if (Settings.GYM_VGM_playbackRate > 0)
                {
                    duration = duration * (Settings.GYM_VGM_playbackRate / (double)recordingRate);
                }
                if (nbLoops > 0)
                {
                    duration += FADEOUT_DURATION_DEFAULT;
                }

                bitrate = (sizeInfo.FileSize - VGM_HEADER_SIZE) * 8 / duration; // TODO - use unpacked size if applicable, and not raw file size

                return(true);
            }
            else
            {
                LogDelegator.GetLogDelegate()(Log.LV_ERROR, "Not a VGM file");
                return(false);
            }
        }
コード例 #26
0
ファイル: MetaDataIO.cs プロジェクト: iaingoodhew/atldotnet
        // ------ ABSTRACT METHODS -----------------------------------------------------

        abstract protected bool read(BinaryReader source, ReadTagParams readTagParams);
コード例 #27
0
        public void readTagField(BinaryReader source, string zoneCode, string fieldName, ushort fieldDataType, int fieldDataSize, ReadTagParams readTagParams, bool isExtendedHeader = false, ushort languageIndex = 0, ushort streamNumber = 0)
        {
            string fieldValue = "";
            bool   setMeta    = true;

            addFrameClass(fieldName, fieldDataType);

            if (0 == fieldDataType) // Unicode string
            {
                fieldValue = Utils.StripEndingZeroChars(Encoding.Unicode.GetString(source.ReadBytes(fieldDataSize)));
            }
            else if (1 == fieldDataType) // Byte array
            {
                if (fieldName.ToUpper().Equals("WM/PICTURE"))
                {
                    byte picCode = source.ReadByte();
                    // TODO factorize : abstract PictureTypeDecoder + unsupported / supported decision in MetaDataIO ?
                    PictureInfo.PIC_TYPE picType = ID3v2.DecodeID3v2PictureType(picCode);

                    int picturePosition;
                    if (picType.Equals(PictureInfo.PIC_TYPE.Unsupported))
                    {
                        addPictureToken(MetaDataIOFactory.TAG_NATIVE, picCode);
                        picturePosition = takePicturePosition(MetaDataIOFactory.TAG_NATIVE, picCode);
                    }
                    else
                    {
                        addPictureToken(picType);
                        picturePosition = takePicturePosition(picType);
                    }

                    if (readTagParams.ReadPictures)
                    {
                        int    picSize     = source.ReadInt32();
                        string mimeType    = StreamUtils.ReadNullTerminatedString(source, Encoding.Unicode);
                        string description = StreamUtils.ReadNullTerminatedString(source, Encoding.Unicode);

                        PictureInfo picInfo = PictureInfo.fromBinaryData(source.BaseStream, picSize, picType, getImplementedTagType(), picCode, picturePosition);
                        picInfo.Description = description;

                        tagData.Pictures.Add(picInfo);
                    }
                    setMeta = false;
                }
                else
                {
                    source.BaseStream.Seek(fieldDataSize, SeekOrigin.Current);
                }
            }
            else if (2 == fieldDataType) // 16-bit Boolean (metadata); 32-bit Boolean (extended header)
            {
                if (isExtendedHeader)
                {
                    fieldValue = source.ReadUInt32().ToString();
                }
                else
                {
                    fieldValue = source.ReadUInt16().ToString();
                }
            }
            else if (3 == fieldDataType) // 32-bit unsigned integer
            {
                uint intValue = source.ReadUInt32();
                if (fieldName.Equals("WM/GENRE", StringComparison.OrdinalIgnoreCase))
                {
                    intValue++;
                }
                fieldValue = intValue.ToString();
            }
            else if (4 == fieldDataType) // 64-bit unsigned integer
            {
                fieldValue = source.ReadUInt64().ToString();
            }
            else if (5 == fieldDataType) // 16-bit unsigned integer
            {
                fieldValue = source.ReadUInt16().ToString();
            }
            else if (6 == fieldDataType) // 128-bit GUID; unused for now
            {
                source.BaseStream.Seek(fieldDataSize, SeekOrigin.Current);
            }

            if (setMeta)
            {
                SetMetaField(fieldName.Trim(), fieldValue, readTagParams.ReadAllMetaFrames, zoneCode, 0, streamNumber, decodeLanguage(source.BaseStream, languageIndex));
            }
        }
コード例 #28
0
        private bool getInfo(BufferedBinaryReader source, FileInfo info, ReadTagParams readTagParams)
        {
            // Get info from file
            bool result        = false;
            bool isValidHeader = false;

            // Check for ID3v2 (NB : this case should not even exist since OGG has its own native tagging system, and is not deemed compatible with ID3v2 according to the ID3 FAQ)
            source.Seek(sizeInfo.ID3v2Size, SeekOrigin.Begin);

            // Read global file header
            info.IdentificationHeader.ReadFromStream(source);

            if (info.IdentificationHeader.IsValid())
            {
                source.Seek(sizeInfo.ID3v2Size + info.IdentificationHeader.Segments + 27, SeekOrigin.Begin); // 27 being the size from 'ID' to 'Segments'

                // Read Vorbis or Opus stream info
                long position = source.Position;

                String headerStart = Utils.Latin1Encoding.GetString(source.ReadBytes(3));
                source.Seek(position, SeekOrigin.Begin);
                if (VORBIS_HEADER_ID.StartsWith(headerStart))
                {
                    contents = CONTENTS_VORBIS;
                    info.VorbisParameters.ID = Utils.Latin1Encoding.GetString(source.ReadBytes(7));
                    isValidHeader            = VORBIS_HEADER_ID.Equals(info.VorbisParameters.ID);

                    info.VorbisParameters.BitstreamVersion = source.ReadBytes(4);
                    info.VorbisParameters.ChannelMode      = source.ReadByte();
                    info.VorbisParameters.SampleRate       = source.ReadInt32();
                    info.VorbisParameters.BitRateMaximal   = source.ReadInt32();
                    info.VorbisParameters.BitRateNominal   = source.ReadInt32();
                    info.VorbisParameters.BitRateMinimal   = source.ReadInt32();
                    info.VorbisParameters.BlockSize        = source.ReadByte();
                    info.VorbisParameters.StopFlag         = source.ReadByte();
                }
                else if (OPUS_HEADER_ID.StartsWith(headerStart))
                {
                    contents = CONTENTS_OPUS;
                    info.OpusParameters.ID = Utils.Latin1Encoding.GetString(source.ReadBytes(8));
                    isValidHeader          = OPUS_HEADER_ID.Equals(info.OpusParameters.ID);

                    info.OpusParameters.Version            = source.ReadByte();
                    info.OpusParameters.OutputChannelCount = source.ReadByte();
                    info.OpusParameters.PreSkip            = source.ReadUInt16();
                    //info.OpusParameters.InputSampleRate = source.ReadUInt32();
                    info.OpusParameters.InputSampleRate = 48000; // Actual sample rate is hardware-dependent. Let's assume for now that the hardware ATL runs on supports 48KHz
                    source.Seek(4, SeekOrigin.Current);
                    info.OpusParameters.OutputGain = source.ReadInt16();

                    info.OpusParameters.ChannelMappingFamily = source.ReadByte();

                    if (info.OpusParameters.ChannelMappingFamily > 0)
                    {
                        info.OpusParameters.StreamCount        = source.ReadByte();
                        info.OpusParameters.CoupledStreamCount = source.ReadByte();

                        info.OpusParameters.ChannelMapping = new byte[info.OpusParameters.OutputChannelCount];
                        for (int i = 0; i < info.OpusParameters.OutputChannelCount; i++)
                        {
                            info.OpusParameters.ChannelMapping[i] = source.ReadByte();
                        }
                    }
                }

                if (isValidHeader)
                {
                    info.CommentHeaderStart = source.Position;
                    IList <long> pagePos = new List <long>();

                    // Reads all related Vorbis pages that describe Comment and Setup headers
                    // and concatenate their content into a single, continuous data stream
                    bool loop  = true;
                    bool first = true;
                    using (MemoryStream s = new MemoryStream())
                    {
                        // Reconstruct the whole Comment header from OGG pages to a MemoryStream
                        while (loop)
                        {
                            info.SetupHeaderEnd              = source.Position; // When the loop stops, cursor is starting to read a brand new page located after Comment _and_ Setup headers
                            info.CommentHeader.ID            = Utils.Latin1Encoding.GetString(source.ReadBytes(4));
                            info.CommentHeader.StreamVersion = source.ReadByte();
                            info.CommentHeader.TypeFlag      = source.ReadByte();
                            // 0 marks a new page
                            if (0 == info.CommentHeader.TypeFlag)
                            {
                                loop = first;
                            }
                            if (loop)
                            {
                                info.CommentHeader.AbsolutePosition = source.ReadUInt64();
                                info.CommentHeader.Serial           = source.ReadInt32();
                                info.CommentHeader.PageNumber       = source.ReadInt32();
                                info.CommentHeader.Checksum         = source.ReadUInt32();
                                info.CommentHeader.Segments         = source.ReadByte();
                                info.CommentHeader.LacingValues     = source.ReadBytes(info.CommentHeader.Segments);
                                s.Write(source.ReadBytes(info.CommentHeader.GetPageLength()), 0, info.CommentHeader.GetPageLength());
                                pagePos.Add(info.SetupHeaderEnd);
                            }
                            first = false;
                        }

                        if (readTagParams.PrepareForWriting) // Metrics to prepare writing
                        {
                            if (pagePos.Count > 1)
                            {
                                source.Position = pagePos[pagePos.Count - 2];
                            }
                            else
                            {
                                source.Position = pagePos[0];
                            }

                            // Determine the boundaries of 3rd header (Setup header) by searching from last-but-one page
                            if (StreamUtils.FindSequence(source, Utils.Latin1Encoding.GetBytes(VORBIS_SETUP_ID)))
                            {
                                info.SetupHeaderStart = source.Position - VORBIS_SETUP_ID.Length;
                                info.CommentHeaderEnd = info.SetupHeaderStart;

                                if (pagePos.Count > 1)
                                {
                                    int firstSetupPage = -1;
                                    for (int i = 1; i < pagePos.Count; i++)
                                    {
                                        if (info.CommentHeaderEnd < pagePos[i])
                                        {
                                            info.CommentHeaderSpanPages = i - 1;
                                            firstSetupPage = i - 1;
                                        }
                                        if (info.SetupHeaderEnd < pagePos[i])
                                        {
                                            info.SetupHeaderSpanPages = i - firstSetupPage;
                                        }
                                    }
                                    /// Not found yet => comment header takes up all pages, and setup header is on the end of the last page
                                    if (-1 == firstSetupPage)
                                    {
                                        info.CommentHeaderSpanPages = pagePos.Count;
                                        info.SetupHeaderSpanPages   = 1;
                                    }
                                }
                                else
                                {
                                    info.CommentHeaderSpanPages = 1;
                                    info.SetupHeaderSpanPages   = 1;
                                }
                            }
                        }

                        // Get total number of samples
                        info.Samples = getSamples(source);

                        // Read metadata from the reconstructed Comment header inside the memoryStream
                        if (readTagParams.ReadTag)
                        {
                            BinaryReader msr = new BinaryReader(s);
                            s.Seek(0, SeekOrigin.Begin);

                            string tagId;
                            bool   isValidTagHeader = false;
                            if (contents.Equals(CONTENTS_VORBIS))
                            {
                                tagId            = Utils.Latin1Encoding.GetString(msr.ReadBytes(7));
                                isValidTagHeader = (VORBIS_TAG_ID.Equals(tagId));
                            }
                            else if (contents.Equals(CONTENTS_OPUS))
                            {
                                tagId            = Utils.Latin1Encoding.GetString(msr.ReadBytes(8));
                                isValidTagHeader = (OPUS_TAG_ID.Equals(tagId));
                            }

                            if (isValidTagHeader)
                            {
                                vorbisTag.Clear();
                                vorbisTag.Read(msr, readTagParams);
                            }
                        }
                    } // using MemoryStream

                    result = true;
                }
            }

            return(result);
        }
コード例 #29
0
        private bool readData(BinaryReader source, ReadTagParams readTagParams)
        {
            Stream fs = source.BaseStream;

            byte[] ID;
            uint   objectCount;
            ulong  headerSize, objectSize;
            long   initialPos, position;
            long   countPosition, sizePosition1, sizePosition2;
            bool   result = false;

            if (languages != null)
            {
                languages.Clear();
            }

            fs.Seek(sizeInfo.ID3v2Size, SeekOrigin.Begin);

            initialPos = fs.Position;

            // Check for existing header
            ID = source.ReadBytes(16);

            // Header (mandatory; one only)
            if (StreamUtils.ArrEqualsArr(WMA_HEADER_ID, ID))
            {
                sizePosition1 = fs.Position;
                headerSize    = source.ReadUInt64();
                countPosition = fs.Position;
                objectCount   = source.ReadUInt32();
                fs.Seek(2, SeekOrigin.Current); // Reserved data
                fileData.ObjectCount      = objectCount;
                fileData.ObjectListOffset = fs.Position;

                // Read all objects in header and get needed data
                for (int i = 0; i < objectCount; i++)
                {
                    position      = fs.Position;
                    ID            = source.ReadBytes(16);
                    sizePosition2 = fs.Position;
                    objectSize    = source.ReadUInt64();

                    // File properties (mandatory; one only)
                    if (StreamUtils.ArrEqualsArr(WMA_FILE_PROPERTIES_ID, ID))
                    {
                        source.BaseStream.Seek(40, SeekOrigin.Current);
                        duration = source.ReadUInt64() / 10000.0;       // Play duration (100-nanoseconds)
                        source.BaseStream.Seek(8, SeekOrigin.Current);  // Send duration; unused for now
                        duration -= source.ReadUInt64();                // Preroll duration (ms)
                    }
                    // Stream properties (mandatory; one per stream)
                    else if (StreamUtils.ArrEqualsArr(WMA_STREAM_PROPERTIES_ID, ID))
                    {
                        source.BaseStream.Seek(54, SeekOrigin.Current);
                        fileData.FormatTag  = source.ReadUInt16();
                        fileData.Channels   = source.ReadUInt16();
                        fileData.SampleRate = source.ReadInt32();
                    }
                    // Content description (optional; one only)
                    // -> standard, pre-defined metadata
                    else if (StreamUtils.ArrEqualsArr(WMA_CONTENT_DESCRIPTION_ID, ID) && readTagParams.ReadTag)
                    {
                        tagExists = true;
                        structureHelper.AddZone(position, (int)objectSize, ZONE_CONTENT_DESCRIPTION);
                        // Store frame information for future editing, since current frame is optional
                        if (readTagParams.PrepareForWriting)
                        {
                            structureHelper.AddSize(sizePosition1, headerSize, ZONE_CONTENT_DESCRIPTION);
                            structureHelper.AddCounter(countPosition, objectCount, ZONE_CONTENT_DESCRIPTION);
                        }
                        readContentDescription(source, readTagParams);
                    }
                    // Extended content description (optional; one only)
                    // -> extended, dynamic metadata
                    else if (StreamUtils.ArrEqualsArr(WMA_EXTENDED_CONTENT_DESCRIPTION_ID, ID) && readTagParams.ReadTag)
                    {
                        tagExists = true;
                        structureHelper.AddZone(position, (int)objectSize, ZONE_EXTENDED_CONTENT_DESCRIPTION);
                        // Store frame information for future editing, since current frame is optional
                        if (readTagParams.PrepareForWriting)
                        {
                            structureHelper.AddSize(sizePosition1, headerSize, ZONE_EXTENDED_CONTENT_DESCRIPTION);
                            structureHelper.AddCounter(countPosition, objectCount, ZONE_EXTENDED_CONTENT_DESCRIPTION);
                        }
                        readExtendedContentDescription(source, readTagParams);
                    }
                    // Header extension (mandatory; one only)
                    // -> extended, dynamic additional metadata such as additional embedded pictures (any picture after the 1st one stored in extended content)
                    else if (StreamUtils.ArrEqualsArr(WMA_HEADER_EXTENSION_ID, ID) && readTagParams.ReadTag)
                    {
                        readHeaderExtended(source, sizePosition1, headerSize, sizePosition2, objectSize, readTagParams);
                    }

                    fs.Seek(position + (long)objectSize, SeekOrigin.Begin);
                }

                // Add absent zone definitions for further editing
                if (readTagParams.PrepareForWriting)
                {
                    if (!structureHelper.ZoneNames.Contains(ZONE_CONTENT_DESCRIPTION))
                    {
                        structureHelper.AddZone(fs.Position, 0, ZONE_CONTENT_DESCRIPTION);
                        structureHelper.AddSize(sizePosition1, headerSize, ZONE_CONTENT_DESCRIPTION);
                        structureHelper.AddCounter(countPosition, objectCount, ZONE_CONTENT_DESCRIPTION);
                    }
                    if (!structureHelper.ZoneNames.Contains(ZONE_EXTENDED_CONTENT_DESCRIPTION))
                    {
                        structureHelper.AddZone(fs.Position, 0, ZONE_EXTENDED_CONTENT_DESCRIPTION);
                        structureHelper.AddSize(sizePosition1, headerSize, ZONE_EXTENDED_CONTENT_DESCRIPTION);
                        structureHelper.AddCounter(countPosition, objectCount, ZONE_EXTENDED_CONTENT_DESCRIPTION);
                    }
                }

                result = true;
            }

            fileData.HeaderSize = fs.Position - initialPos;

            return(result);
        }
コード例 #30
0
ファイル: MetaDataIO.cs プロジェクト: iaingoodhew/atldotnet
        public bool Write(BinaryReader r, BinaryWriter w, TagData tag)
        {
            bool result = true;

            // Constraint-check on non-supported values
            if (FieldCodeFixedLength > 0)
            {
                if (tag.Pictures != null)
                {
                    foreach (PictureInfo picInfo in tag.Pictures)
                    {
                        if (PictureInfo.PIC_TYPE.Unsupported.Equals(picInfo.PicType) && (picInfo.TagType.Equals(getImplementedTagType())))
                        {
                            if ((-1 == picInfo.NativePicCode) && (Utils.ProtectValue(picInfo.NativePicCodeStr).Length != FieldCodeFixedLength))
                            {
                                throw new NotSupportedException("Field code fixed length is " + FieldCodeFixedLength + "; detected field '" + Utils.ProtectValue(picInfo.NativePicCodeStr) + "' is " + Utils.ProtectValue(picInfo.NativePicCodeStr).Length + " characters long and cannot be written");
                            }
                        }
                    }
                }
                foreach (MetaFieldInfo fieldInfo in tag.AdditionalFields)
                {
                    if (fieldInfo.TagType.Equals(getImplementedTagType()) || MetaDataIOFactory.TAG_ANY == fieldInfo.TagType)
                    {
                        string fieldCode = Utils.ProtectValue(fieldInfo.NativeFieldCode);
                        if (fieldCode.Length != FieldCodeFixedLength && !fieldCode.Contains("----")) // "----" = exception for MP4 extended fields (e.g. ----:com.apple.iTunes:CONDUCTOR)
                        {
                            throw new NotSupportedException("Field code fixed length is " + FieldCodeFixedLength + "; detected field '" + fieldCode + "' is " + fieldCode.Length + " characters long and cannot be written");
                        }
                    }
                }
            }

            structureHelper.Clear();
            tagData.Pictures.Clear();

            // Read all the fields in the existing tag (including unsupported fields)
            ReadTagParams readTagParams = new ReadTagParams(true, true);

            readTagParams.PrepareForWriting = true;

            if (embedder != null && embedder.HasEmbeddedID3v2 > 0)
            {
                readTagParams.offset = embedder.HasEmbeddedID3v2;
            }

            this.read(r, readTagParams);

            if (embedder != null && getImplementedTagType() == MetaDataIOFactory.TAG_ID3V2)
            {
                structureHelper.Clear();
                structureHelper.AddZone(embedder.Id3v2Zone);
            }

            // Give engine something to work with if the tag is really empty
            if (!tagExists && 0 == Zones.Count)
            {
                structureHelper.AddZone(0, 0);
            }

            TagData dataToWrite;

            dataToWrite = tagData;
            dataToWrite.IntegrateValues(tag); // Merge existing information + new tag information
            dataToWrite.Cleanup();

            FileSurgeon surgeon = new FileSurgeon(structureHelper, embedder, getImplementedTagType(), getDefaultTagOffset());

            result = surgeon.RewriteZones(w, new FileSurgeon.WriteDelegate(writeAdapter), Zones, dataToWrite, tagExists);

            // Update tag information without calling Read

            /* TODO - this implementation is too risky :
             *   - if one of the writing operations fails, data is updated as if everything went right
             *   - any picture slot with a markForDeletion flag is recorded as-is in the tag
             */
            tagData = dataToWrite;

            return(result);
        }