示例#1
0
        protected override int write(TagData tag, BinaryWriter w, string zone)
        {
            int result = 0;

            if (zone.Equals(CHUNK_BEXT) && BextTag.IsDataEligible(this))
            {
                result += BextTag.ToStream(w, isLittleEndian, this);
            }
            else if (zone.Equals(CHUNK_INFO) && InfoTag.IsDataEligible(this))
            {
                result += InfoTag.ToStream(w, isLittleEndian, this);
            }
            else if (zone.Equals(CHUNK_IXML) && IXmlTag.IsDataEligible(this))
            {
                result += IXmlTag.ToStream(w, isLittleEndian, this);
            }

            return(result);
        }
示例#2
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);
        }